1 | // SPDX-License-Identifier: GPL-2.0-or-later |
2 | /* |
3 | * gl520sm.c - Part of lm_sensors, Linux kernel modules for hardware |
4 | * monitoring |
5 | * Copyright (c) 1998, 1999 Frodo Looijaard <frodol@dds.nl>, |
6 | * Kyösti Mälkki <kmalkki@cc.hut.fi> |
7 | * Copyright (c) 2005 Maarten Deprez <maartendeprez@users.sourceforge.net> |
8 | */ |
9 | |
10 | #include <linux/module.h> |
11 | #include <linux/init.h> |
12 | #include <linux/slab.h> |
13 | #include <linux/jiffies.h> |
14 | #include <linux/i2c.h> |
15 | #include <linux/hwmon.h> |
16 | #include <linux/hwmon-sysfs.h> |
17 | #include <linux/hwmon-vid.h> |
18 | #include <linux/err.h> |
19 | #include <linux/mutex.h> |
20 | #include <linux/sysfs.h> |
21 | |
22 | /* Type of the extra sensor */ |
23 | static unsigned short ; |
24 | module_param(extra_sensor_type, ushort, 0); |
25 | MODULE_PARM_DESC(extra_sensor_type, "Type of extra sensor (0=autodetect, 1=temperature, 2=voltage)" ); |
26 | |
27 | /* Addresses to scan */ |
28 | static const unsigned short normal_i2c[] = { 0x2c, 0x2d, I2C_CLIENT_END }; |
29 | |
30 | /* |
31 | * Many GL520 constants specified below |
32 | * One of the inputs can be configured as either temp or voltage. |
33 | * That's why _TEMP2 and _IN4 access the same register |
34 | */ |
35 | |
36 | /* The GL520 registers */ |
37 | #define GL520_REG_CHIP_ID 0x00 |
38 | #define GL520_REG_REVISION 0x01 |
39 | #define GL520_REG_CONF 0x03 |
40 | #define GL520_REG_MASK 0x11 |
41 | |
42 | #define GL520_REG_VID_INPUT 0x02 |
43 | |
44 | static const u8 GL520_REG_IN_INPUT[] = { 0x15, 0x14, 0x13, 0x0d, 0x0e }; |
45 | static const u8 GL520_REG_IN_LIMIT[] = { 0x0c, 0x09, 0x0a, 0x0b }; |
46 | static const u8 GL520_REG_IN_MIN[] = { 0x0c, 0x09, 0x0a, 0x0b, 0x18 }; |
47 | static const u8 GL520_REG_IN_MAX[] = { 0x0c, 0x09, 0x0a, 0x0b, 0x17 }; |
48 | |
49 | static const u8 GL520_REG_TEMP_INPUT[] = { 0x04, 0x0e }; |
50 | static const u8 GL520_REG_TEMP_MAX[] = { 0x05, 0x17 }; |
51 | static const u8 GL520_REG_TEMP_MAX_HYST[] = { 0x06, 0x18 }; |
52 | |
53 | #define GL520_REG_FAN_INPUT 0x07 |
54 | #define GL520_REG_FAN_MIN 0x08 |
55 | #define GL520_REG_FAN_DIV 0x0f |
56 | #define GL520_REG_FAN_OFF GL520_REG_FAN_DIV |
57 | |
58 | #define GL520_REG_ALARMS 0x12 |
59 | #define GL520_REG_BEEP_MASK 0x10 |
60 | #define GL520_REG_BEEP_ENABLE GL520_REG_CONF |
61 | |
62 | /* Client data */ |
63 | struct gl520_data { |
64 | struct i2c_client *client; |
65 | const struct attribute_group *groups[3]; |
66 | struct mutex update_lock; |
67 | bool valid; /* false until the following fields are valid */ |
68 | unsigned long last_updated; /* in jiffies */ |
69 | |
70 | u8 vid; |
71 | u8 vrm; |
72 | u8 in_input[5]; /* [0] = VVD */ |
73 | u8 in_min[5]; /* [0] = VDD */ |
74 | u8 in_max[5]; /* [0] = VDD */ |
75 | u8 fan_input[2]; |
76 | u8 fan_min[2]; |
77 | u8 fan_div[2]; |
78 | u8 fan_off; |
79 | u8 temp_input[2]; |
80 | u8 temp_max[2]; |
81 | u8 temp_max_hyst[2]; |
82 | u8 alarms; |
83 | u8 beep_enable; |
84 | u8 beep_mask; |
85 | u8 alarm_mask; |
86 | u8 two_temps; |
87 | }; |
88 | |
89 | /* |
90 | * Registers 0x07 to 0x0c are word-sized, others are byte-sized |
91 | * GL520 uses a high-byte first convention |
92 | */ |
93 | static int gl520_read_value(struct i2c_client *client, u8 reg) |
94 | { |
95 | if ((reg >= 0x07) && (reg <= 0x0c)) |
96 | return i2c_smbus_read_word_swapped(client, command: reg); |
97 | else |
98 | return i2c_smbus_read_byte_data(client, command: reg); |
99 | } |
100 | |
101 | static int gl520_write_value(struct i2c_client *client, u8 reg, u16 value) |
102 | { |
103 | if ((reg >= 0x07) && (reg <= 0x0c)) |
104 | return i2c_smbus_write_word_swapped(client, command: reg, value); |
105 | else |
106 | return i2c_smbus_write_byte_data(client, command: reg, value); |
107 | } |
108 | |
109 | static struct gl520_data *gl520_update_device(struct device *dev) |
110 | { |
111 | struct gl520_data *data = dev_get_drvdata(dev); |
112 | struct i2c_client *client = data->client; |
113 | int val, i; |
114 | |
115 | mutex_lock(&data->update_lock); |
116 | |
117 | if (time_after(jiffies, data->last_updated + 2 * HZ) || !data->valid) { |
118 | |
119 | dev_dbg(&client->dev, "Starting gl520sm update\n" ); |
120 | |
121 | data->alarms = gl520_read_value(client, GL520_REG_ALARMS); |
122 | data->beep_mask = gl520_read_value(client, GL520_REG_BEEP_MASK); |
123 | data->vid = gl520_read_value(client, |
124 | GL520_REG_VID_INPUT) & 0x1f; |
125 | |
126 | for (i = 0; i < 4; i++) { |
127 | data->in_input[i] = gl520_read_value(client, |
128 | reg: GL520_REG_IN_INPUT[i]); |
129 | val = gl520_read_value(client, reg: GL520_REG_IN_LIMIT[i]); |
130 | data->in_min[i] = val & 0xff; |
131 | data->in_max[i] = (val >> 8) & 0xff; |
132 | } |
133 | |
134 | val = gl520_read_value(client, GL520_REG_FAN_INPUT); |
135 | data->fan_input[0] = (val >> 8) & 0xff; |
136 | data->fan_input[1] = val & 0xff; |
137 | |
138 | val = gl520_read_value(client, GL520_REG_FAN_MIN); |
139 | data->fan_min[0] = (val >> 8) & 0xff; |
140 | data->fan_min[1] = val & 0xff; |
141 | |
142 | data->temp_input[0] = gl520_read_value(client, |
143 | reg: GL520_REG_TEMP_INPUT[0]); |
144 | data->temp_max[0] = gl520_read_value(client, |
145 | reg: GL520_REG_TEMP_MAX[0]); |
146 | data->temp_max_hyst[0] = gl520_read_value(client, |
147 | reg: GL520_REG_TEMP_MAX_HYST[0]); |
148 | |
149 | val = gl520_read_value(client, GL520_REG_FAN_DIV); |
150 | data->fan_div[0] = (val >> 6) & 0x03; |
151 | data->fan_div[1] = (val >> 4) & 0x03; |
152 | data->fan_off = (val >> 2) & 0x01; |
153 | |
154 | data->alarms &= data->alarm_mask; |
155 | |
156 | val = gl520_read_value(client, GL520_REG_CONF); |
157 | data->beep_enable = !((val >> 2) & 1); |
158 | |
159 | /* Temp1 and Vin4 are the same input */ |
160 | if (data->two_temps) { |
161 | data->temp_input[1] = gl520_read_value(client, |
162 | reg: GL520_REG_TEMP_INPUT[1]); |
163 | data->temp_max[1] = gl520_read_value(client, |
164 | reg: GL520_REG_TEMP_MAX[1]); |
165 | data->temp_max_hyst[1] = gl520_read_value(client, |
166 | reg: GL520_REG_TEMP_MAX_HYST[1]); |
167 | } else { |
168 | data->in_input[4] = gl520_read_value(client, |
169 | reg: GL520_REG_IN_INPUT[4]); |
170 | data->in_min[4] = gl520_read_value(client, |
171 | reg: GL520_REG_IN_MIN[4]); |
172 | data->in_max[4] = gl520_read_value(client, |
173 | reg: GL520_REG_IN_MAX[4]); |
174 | } |
175 | |
176 | data->last_updated = jiffies; |
177 | data->valid = true; |
178 | } |
179 | |
180 | mutex_unlock(lock: &data->update_lock); |
181 | |
182 | return data; |
183 | } |
184 | |
185 | /* |
186 | * Sysfs stuff |
187 | */ |
188 | |
189 | static ssize_t cpu0_vid_show(struct device *dev, |
190 | struct device_attribute *attr, char *buf) |
191 | { |
192 | struct gl520_data *data = gl520_update_device(dev); |
193 | return sprintf(buf, fmt: "%u\n" , vid_from_reg(val: data->vid, vrm: data->vrm)); |
194 | } |
195 | static DEVICE_ATTR_RO(cpu0_vid); |
196 | |
197 | #define VDD_FROM_REG(val) DIV_ROUND_CLOSEST((val) * 95, 4) |
198 | #define VDD_CLAMP(val) clamp_val(val, 0, 255 * 95 / 4) |
199 | #define VDD_TO_REG(val) DIV_ROUND_CLOSEST(VDD_CLAMP(val) * 4, 95) |
200 | |
201 | #define IN_FROM_REG(val) ((val) * 19) |
202 | #define IN_CLAMP(val) clamp_val(val, 0, 255 * 19) |
203 | #define IN_TO_REG(val) DIV_ROUND_CLOSEST(IN_CLAMP(val), 19) |
204 | |
205 | static ssize_t in_input_show(struct device *dev, |
206 | struct device_attribute *attr, char *buf) |
207 | { |
208 | int n = to_sensor_dev_attr(attr)->index; |
209 | struct gl520_data *data = gl520_update_device(dev); |
210 | u8 r = data->in_input[n]; |
211 | |
212 | if (n == 0) |
213 | return sprintf(buf, fmt: "%d\n" , VDD_FROM_REG(r)); |
214 | else |
215 | return sprintf(buf, fmt: "%d\n" , IN_FROM_REG(r)); |
216 | } |
217 | |
218 | static ssize_t in_min_show(struct device *dev, struct device_attribute *attr, |
219 | char *buf) |
220 | { |
221 | int n = to_sensor_dev_attr(attr)->index; |
222 | struct gl520_data *data = gl520_update_device(dev); |
223 | u8 r = data->in_min[n]; |
224 | |
225 | if (n == 0) |
226 | return sprintf(buf, fmt: "%d\n" , VDD_FROM_REG(r)); |
227 | else |
228 | return sprintf(buf, fmt: "%d\n" , IN_FROM_REG(r)); |
229 | } |
230 | |
231 | static ssize_t in_max_show(struct device *dev, struct device_attribute *attr, |
232 | char *buf) |
233 | { |
234 | int n = to_sensor_dev_attr(attr)->index; |
235 | struct gl520_data *data = gl520_update_device(dev); |
236 | u8 r = data->in_max[n]; |
237 | |
238 | if (n == 0) |
239 | return sprintf(buf, fmt: "%d\n" , VDD_FROM_REG(r)); |
240 | else |
241 | return sprintf(buf, fmt: "%d\n" , IN_FROM_REG(r)); |
242 | } |
243 | |
244 | static ssize_t in_min_store(struct device *dev, struct device_attribute *attr, |
245 | const char *buf, size_t count) |
246 | { |
247 | struct gl520_data *data = dev_get_drvdata(dev); |
248 | struct i2c_client *client = data->client; |
249 | int n = to_sensor_dev_attr(attr)->index; |
250 | u8 r; |
251 | long v; |
252 | int err; |
253 | |
254 | err = kstrtol(s: buf, base: 10, res: &v); |
255 | if (err) |
256 | return err; |
257 | |
258 | mutex_lock(&data->update_lock); |
259 | |
260 | if (n == 0) |
261 | r = VDD_TO_REG(v); |
262 | else |
263 | r = IN_TO_REG(v); |
264 | |
265 | data->in_min[n] = r; |
266 | |
267 | if (n < 4) |
268 | gl520_write_value(client, reg: GL520_REG_IN_MIN[n], |
269 | value: (gl520_read_value(client, reg: GL520_REG_IN_MIN[n]) |
270 | & ~0xff) | r); |
271 | else |
272 | gl520_write_value(client, reg: GL520_REG_IN_MIN[n], value: r); |
273 | |
274 | mutex_unlock(lock: &data->update_lock); |
275 | return count; |
276 | } |
277 | |
278 | static ssize_t in_max_store(struct device *dev, struct device_attribute *attr, |
279 | const char *buf, size_t count) |
280 | { |
281 | struct gl520_data *data = dev_get_drvdata(dev); |
282 | struct i2c_client *client = data->client; |
283 | int n = to_sensor_dev_attr(attr)->index; |
284 | u8 r; |
285 | long v; |
286 | int err; |
287 | |
288 | err = kstrtol(s: buf, base: 10, res: &v); |
289 | if (err) |
290 | return err; |
291 | |
292 | if (n == 0) |
293 | r = VDD_TO_REG(v); |
294 | else |
295 | r = IN_TO_REG(v); |
296 | |
297 | mutex_lock(&data->update_lock); |
298 | |
299 | data->in_max[n] = r; |
300 | |
301 | if (n < 4) |
302 | gl520_write_value(client, reg: GL520_REG_IN_MAX[n], |
303 | value: (gl520_read_value(client, reg: GL520_REG_IN_MAX[n]) |
304 | & ~0xff00) | (r << 8)); |
305 | else |
306 | gl520_write_value(client, reg: GL520_REG_IN_MAX[n], value: r); |
307 | |
308 | mutex_unlock(lock: &data->update_lock); |
309 | return count; |
310 | } |
311 | |
312 | static SENSOR_DEVICE_ATTR_RO(in0_input, in_input, 0); |
313 | static SENSOR_DEVICE_ATTR_RO(in1_input, in_input, 1); |
314 | static SENSOR_DEVICE_ATTR_RO(in2_input, in_input, 2); |
315 | static SENSOR_DEVICE_ATTR_RO(in3_input, in_input, 3); |
316 | static SENSOR_DEVICE_ATTR_RO(in4_input, in_input, 4); |
317 | static SENSOR_DEVICE_ATTR_RW(in0_min, in_min, 0); |
318 | static SENSOR_DEVICE_ATTR_RW(in1_min, in_min, 1); |
319 | static SENSOR_DEVICE_ATTR_RW(in2_min, in_min, 2); |
320 | static SENSOR_DEVICE_ATTR_RW(in3_min, in_min, 3); |
321 | static SENSOR_DEVICE_ATTR_RW(in4_min, in_min, 4); |
322 | static SENSOR_DEVICE_ATTR_RW(in0_max, in_max, 0); |
323 | static SENSOR_DEVICE_ATTR_RW(in1_max, in_max, 1); |
324 | static SENSOR_DEVICE_ATTR_RW(in2_max, in_max, 2); |
325 | static SENSOR_DEVICE_ATTR_RW(in3_max, in_max, 3); |
326 | static SENSOR_DEVICE_ATTR_RW(in4_max, in_max, 4); |
327 | |
328 | #define DIV_FROM_REG(val) (1 << (val)) |
329 | #define FAN_FROM_REG(val, div) ((val) == 0 ? 0 : (480000 / ((val) << (div)))) |
330 | |
331 | #define FAN_BASE(div) (480000 >> (div)) |
332 | #define FAN_CLAMP(val, div) clamp_val(val, FAN_BASE(div) / 255, \ |
333 | FAN_BASE(div)) |
334 | #define FAN_TO_REG(val, div) ((val) == 0 ? 0 : \ |
335 | DIV_ROUND_CLOSEST(480000, \ |
336 | FAN_CLAMP(val, div) << (div))) |
337 | |
338 | static ssize_t fan_input_show(struct device *dev, |
339 | struct device_attribute *attr, char *buf) |
340 | { |
341 | int n = to_sensor_dev_attr(attr)->index; |
342 | struct gl520_data *data = gl520_update_device(dev); |
343 | |
344 | return sprintf(buf, fmt: "%d\n" , FAN_FROM_REG(data->fan_input[n], |
345 | data->fan_div[n])); |
346 | } |
347 | |
348 | static ssize_t fan_min_show(struct device *dev, struct device_attribute *attr, |
349 | char *buf) |
350 | { |
351 | int n = to_sensor_dev_attr(attr)->index; |
352 | struct gl520_data *data = gl520_update_device(dev); |
353 | |
354 | return sprintf(buf, fmt: "%d\n" , FAN_FROM_REG(data->fan_min[n], |
355 | data->fan_div[n])); |
356 | } |
357 | |
358 | static ssize_t fan_div_show(struct device *dev, struct device_attribute *attr, |
359 | char *buf) |
360 | { |
361 | int n = to_sensor_dev_attr(attr)->index; |
362 | struct gl520_data *data = gl520_update_device(dev); |
363 | |
364 | return sprintf(buf, fmt: "%d\n" , DIV_FROM_REG(data->fan_div[n])); |
365 | } |
366 | |
367 | static ssize_t fan1_off_show(struct device *dev, |
368 | struct device_attribute *attr, char *buf) |
369 | { |
370 | struct gl520_data *data = gl520_update_device(dev); |
371 | return sprintf(buf, fmt: "%d\n" , data->fan_off); |
372 | } |
373 | |
374 | static ssize_t fan_min_store(struct device *dev, |
375 | struct device_attribute *attr, const char *buf, |
376 | size_t count) |
377 | { |
378 | struct gl520_data *data = dev_get_drvdata(dev); |
379 | struct i2c_client *client = data->client; |
380 | int n = to_sensor_dev_attr(attr)->index; |
381 | u8 r; |
382 | unsigned long v; |
383 | int err; |
384 | |
385 | err = kstrtoul(s: buf, base: 10, res: &v); |
386 | if (err) |
387 | return err; |
388 | |
389 | mutex_lock(&data->update_lock); |
390 | r = FAN_TO_REG(v, data->fan_div[n]); |
391 | data->fan_min[n] = r; |
392 | |
393 | if (n == 0) |
394 | gl520_write_value(client, GL520_REG_FAN_MIN, |
395 | value: (gl520_read_value(client, GL520_REG_FAN_MIN) |
396 | & ~0xff00) | (r << 8)); |
397 | else |
398 | gl520_write_value(client, GL520_REG_FAN_MIN, |
399 | value: (gl520_read_value(client, GL520_REG_FAN_MIN) |
400 | & ~0xff) | r); |
401 | |
402 | data->beep_mask = gl520_read_value(client, GL520_REG_BEEP_MASK); |
403 | if (data->fan_min[n] == 0) |
404 | data->alarm_mask &= (n == 0) ? ~0x20 : ~0x40; |
405 | else |
406 | data->alarm_mask |= (n == 0) ? 0x20 : 0x40; |
407 | data->beep_mask &= data->alarm_mask; |
408 | gl520_write_value(client, GL520_REG_BEEP_MASK, value: data->beep_mask); |
409 | |
410 | mutex_unlock(lock: &data->update_lock); |
411 | return count; |
412 | } |
413 | |
414 | static ssize_t fan_div_store(struct device *dev, |
415 | struct device_attribute *attr, const char *buf, |
416 | size_t count) |
417 | { |
418 | struct gl520_data *data = dev_get_drvdata(dev); |
419 | struct i2c_client *client = data->client; |
420 | int n = to_sensor_dev_attr(attr)->index; |
421 | u8 r; |
422 | unsigned long v; |
423 | int err; |
424 | |
425 | err = kstrtoul(s: buf, base: 10, res: &v); |
426 | if (err) |
427 | return err; |
428 | |
429 | switch (v) { |
430 | case 1: |
431 | r = 0; |
432 | break; |
433 | case 2: |
434 | r = 1; |
435 | break; |
436 | case 4: |
437 | r = 2; |
438 | break; |
439 | case 8: |
440 | r = 3; |
441 | break; |
442 | default: |
443 | dev_err(&client->dev, |
444 | "fan_div value %ld not supported. Choose one of 1, 2, 4 or 8!\n" , v); |
445 | return -EINVAL; |
446 | } |
447 | |
448 | mutex_lock(&data->update_lock); |
449 | data->fan_div[n] = r; |
450 | |
451 | if (n == 0) |
452 | gl520_write_value(client, GL520_REG_FAN_DIV, |
453 | value: (gl520_read_value(client, GL520_REG_FAN_DIV) |
454 | & ~0xc0) | (r << 6)); |
455 | else |
456 | gl520_write_value(client, GL520_REG_FAN_DIV, |
457 | value: (gl520_read_value(client, GL520_REG_FAN_DIV) |
458 | & ~0x30) | (r << 4)); |
459 | |
460 | mutex_unlock(lock: &data->update_lock); |
461 | return count; |
462 | } |
463 | |
464 | static ssize_t fan1_off_store(struct device *dev, |
465 | struct device_attribute *attr, const char *buf, |
466 | size_t count) |
467 | { |
468 | struct gl520_data *data = dev_get_drvdata(dev); |
469 | struct i2c_client *client = data->client; |
470 | u8 r; |
471 | unsigned long v; |
472 | int err; |
473 | |
474 | err = kstrtoul(s: buf, base: 10, res: &v); |
475 | if (err) |
476 | return err; |
477 | |
478 | r = (v ? 1 : 0); |
479 | |
480 | mutex_lock(&data->update_lock); |
481 | data->fan_off = r; |
482 | gl520_write_value(client, GL520_REG_FAN_OFF, |
483 | value: (gl520_read_value(client, GL520_REG_FAN_OFF) |
484 | & ~0x0c) | (r << 2)); |
485 | mutex_unlock(lock: &data->update_lock); |
486 | return count; |
487 | } |
488 | |
489 | static SENSOR_DEVICE_ATTR_RO(fan1_input, fan_input, 0); |
490 | static SENSOR_DEVICE_ATTR_RO(fan2_input, fan_input, 1); |
491 | static SENSOR_DEVICE_ATTR_RW(fan1_min, fan_min, 0); |
492 | static SENSOR_DEVICE_ATTR_RW(fan2_min, fan_min, 1); |
493 | static SENSOR_DEVICE_ATTR_RW(fan1_div, fan_div, 0); |
494 | static SENSOR_DEVICE_ATTR_RW(fan2_div, fan_div, 1); |
495 | static DEVICE_ATTR_RW(fan1_off); |
496 | |
497 | #define TEMP_FROM_REG(val) (((val) - 130) * 1000) |
498 | #define TEMP_CLAMP(val) clamp_val(val, -130000, 125000) |
499 | #define TEMP_TO_REG(val) (DIV_ROUND_CLOSEST(TEMP_CLAMP(val), 1000) + 130) |
500 | |
501 | static ssize_t temp_input_show(struct device *dev, |
502 | struct device_attribute *attr, char *buf) |
503 | { |
504 | int n = to_sensor_dev_attr(attr)->index; |
505 | struct gl520_data *data = gl520_update_device(dev); |
506 | |
507 | return sprintf(buf, fmt: "%d\n" , TEMP_FROM_REG(data->temp_input[n])); |
508 | } |
509 | |
510 | static ssize_t temp_max_show(struct device *dev, |
511 | struct device_attribute *attr, char *buf) |
512 | { |
513 | int n = to_sensor_dev_attr(attr)->index; |
514 | struct gl520_data *data = gl520_update_device(dev); |
515 | |
516 | return sprintf(buf, fmt: "%d\n" , TEMP_FROM_REG(data->temp_max[n])); |
517 | } |
518 | |
519 | static ssize_t temp_max_hyst_show(struct device *dev, |
520 | struct device_attribute *attr, char *buf) |
521 | { |
522 | int n = to_sensor_dev_attr(attr)->index; |
523 | struct gl520_data *data = gl520_update_device(dev); |
524 | |
525 | return sprintf(buf, fmt: "%d\n" , TEMP_FROM_REG(data->temp_max_hyst[n])); |
526 | } |
527 | |
528 | static ssize_t temp_max_store(struct device *dev, |
529 | struct device_attribute *attr, const char *buf, |
530 | size_t count) |
531 | { |
532 | struct gl520_data *data = dev_get_drvdata(dev); |
533 | struct i2c_client *client = data->client; |
534 | int n = to_sensor_dev_attr(attr)->index; |
535 | long v; |
536 | int err; |
537 | |
538 | err = kstrtol(s: buf, base: 10, res: &v); |
539 | if (err) |
540 | return err; |
541 | |
542 | mutex_lock(&data->update_lock); |
543 | data->temp_max[n] = TEMP_TO_REG(v); |
544 | gl520_write_value(client, reg: GL520_REG_TEMP_MAX[n], value: data->temp_max[n]); |
545 | mutex_unlock(lock: &data->update_lock); |
546 | return count; |
547 | } |
548 | |
549 | static ssize_t temp_max_hyst_store(struct device *dev, |
550 | struct device_attribute *attr, |
551 | const char *buf, size_t count) |
552 | { |
553 | struct gl520_data *data = dev_get_drvdata(dev); |
554 | struct i2c_client *client = data->client; |
555 | int n = to_sensor_dev_attr(attr)->index; |
556 | long v; |
557 | int err; |
558 | |
559 | err = kstrtol(s: buf, base: 10, res: &v); |
560 | if (err) |
561 | return err; |
562 | |
563 | mutex_lock(&data->update_lock); |
564 | data->temp_max_hyst[n] = TEMP_TO_REG(v); |
565 | gl520_write_value(client, reg: GL520_REG_TEMP_MAX_HYST[n], |
566 | value: data->temp_max_hyst[n]); |
567 | mutex_unlock(lock: &data->update_lock); |
568 | return count; |
569 | } |
570 | |
571 | static SENSOR_DEVICE_ATTR_RO(temp1_input, temp_input, 0); |
572 | static SENSOR_DEVICE_ATTR_RO(temp2_input, temp_input, 1); |
573 | static SENSOR_DEVICE_ATTR_RW(temp1_max, temp_max, 0); |
574 | static SENSOR_DEVICE_ATTR_RW(temp2_max, temp_max, 1); |
575 | static SENSOR_DEVICE_ATTR_RW(temp1_max_hyst, temp_max_hyst, 0); |
576 | static SENSOR_DEVICE_ATTR_RW(temp2_max_hyst, temp_max_hyst, 1); |
577 | |
578 | static ssize_t alarms_show(struct device *dev, struct device_attribute *attr, |
579 | char *buf) |
580 | { |
581 | struct gl520_data *data = gl520_update_device(dev); |
582 | return sprintf(buf, fmt: "%d\n" , data->alarms); |
583 | } |
584 | |
585 | static ssize_t beep_enable_show(struct device *dev, |
586 | struct device_attribute *attr, char *buf) |
587 | { |
588 | struct gl520_data *data = gl520_update_device(dev); |
589 | return sprintf(buf, fmt: "%d\n" , data->beep_enable); |
590 | } |
591 | |
592 | static ssize_t beep_mask_show(struct device *dev, |
593 | struct device_attribute *attr, char *buf) |
594 | { |
595 | struct gl520_data *data = gl520_update_device(dev); |
596 | return sprintf(buf, fmt: "%d\n" , data->beep_mask); |
597 | } |
598 | |
599 | static ssize_t beep_enable_store(struct device *dev, |
600 | struct device_attribute *attr, |
601 | const char *buf, size_t count) |
602 | { |
603 | struct gl520_data *data = dev_get_drvdata(dev); |
604 | struct i2c_client *client = data->client; |
605 | u8 r; |
606 | unsigned long v; |
607 | int err; |
608 | |
609 | err = kstrtoul(s: buf, base: 10, res: &v); |
610 | if (err) |
611 | return err; |
612 | |
613 | r = (v ? 0 : 1); |
614 | |
615 | mutex_lock(&data->update_lock); |
616 | data->beep_enable = !r; |
617 | gl520_write_value(client, GL520_REG_BEEP_ENABLE, |
618 | value: (gl520_read_value(client, GL520_REG_BEEP_ENABLE) |
619 | & ~0x04) | (r << 2)); |
620 | mutex_unlock(lock: &data->update_lock); |
621 | return count; |
622 | } |
623 | |
624 | static ssize_t beep_mask_store(struct device *dev, |
625 | struct device_attribute *attr, const char *buf, |
626 | size_t count) |
627 | { |
628 | struct gl520_data *data = dev_get_drvdata(dev); |
629 | struct i2c_client *client = data->client; |
630 | unsigned long r; |
631 | int err; |
632 | |
633 | err = kstrtoul(s: buf, base: 10, res: &r); |
634 | if (err) |
635 | return err; |
636 | |
637 | mutex_lock(&data->update_lock); |
638 | r &= data->alarm_mask; |
639 | data->beep_mask = r; |
640 | gl520_write_value(client, GL520_REG_BEEP_MASK, value: r); |
641 | mutex_unlock(lock: &data->update_lock); |
642 | return count; |
643 | } |
644 | |
645 | static DEVICE_ATTR_RO(alarms); |
646 | static DEVICE_ATTR_RW(beep_enable); |
647 | static DEVICE_ATTR_RW(beep_mask); |
648 | |
649 | static ssize_t alarm_show(struct device *dev, struct device_attribute *attr, |
650 | char *buf) |
651 | { |
652 | int bit_nr = to_sensor_dev_attr(attr)->index; |
653 | struct gl520_data *data = gl520_update_device(dev); |
654 | |
655 | return sprintf(buf, fmt: "%d\n" , (data->alarms >> bit_nr) & 1); |
656 | } |
657 | |
658 | static SENSOR_DEVICE_ATTR_RO(in0_alarm, alarm, 0); |
659 | static SENSOR_DEVICE_ATTR_RO(in1_alarm, alarm, 1); |
660 | static SENSOR_DEVICE_ATTR_RO(in2_alarm, alarm, 2); |
661 | static SENSOR_DEVICE_ATTR_RO(in3_alarm, alarm, 3); |
662 | static SENSOR_DEVICE_ATTR_RO(temp1_alarm, alarm, 4); |
663 | static SENSOR_DEVICE_ATTR_RO(fan1_alarm, alarm, 5); |
664 | static SENSOR_DEVICE_ATTR_RO(fan2_alarm, alarm, 6); |
665 | static SENSOR_DEVICE_ATTR_RO(temp2_alarm, alarm, 7); |
666 | static SENSOR_DEVICE_ATTR_RO(in4_alarm, alarm, 7); |
667 | |
668 | static ssize_t beep_show(struct device *dev, struct device_attribute *attr, |
669 | char *buf) |
670 | { |
671 | int bitnr = to_sensor_dev_attr(attr)->index; |
672 | struct gl520_data *data = gl520_update_device(dev); |
673 | |
674 | return sprintf(buf, fmt: "%d\n" , (data->beep_mask >> bitnr) & 1); |
675 | } |
676 | |
677 | static ssize_t beep_store(struct device *dev, struct device_attribute *attr, |
678 | const char *buf, size_t count) |
679 | { |
680 | struct gl520_data *data = dev_get_drvdata(dev); |
681 | struct i2c_client *client = data->client; |
682 | int bitnr = to_sensor_dev_attr(attr)->index; |
683 | unsigned long bit; |
684 | |
685 | int err; |
686 | |
687 | err = kstrtoul(s: buf, base: 10, res: &bit); |
688 | if (err) |
689 | return err; |
690 | if (bit & ~1) |
691 | return -EINVAL; |
692 | |
693 | mutex_lock(&data->update_lock); |
694 | data->beep_mask = gl520_read_value(client, GL520_REG_BEEP_MASK); |
695 | if (bit) |
696 | data->beep_mask |= (1 << bitnr); |
697 | else |
698 | data->beep_mask &= ~(1 << bitnr); |
699 | gl520_write_value(client, GL520_REG_BEEP_MASK, value: data->beep_mask); |
700 | mutex_unlock(lock: &data->update_lock); |
701 | return count; |
702 | } |
703 | |
704 | static SENSOR_DEVICE_ATTR_RW(in0_beep, beep, 0); |
705 | static SENSOR_DEVICE_ATTR_RW(in1_beep, beep, 1); |
706 | static SENSOR_DEVICE_ATTR_RW(in2_beep, beep, 2); |
707 | static SENSOR_DEVICE_ATTR_RW(in3_beep, beep, 3); |
708 | static SENSOR_DEVICE_ATTR_RW(temp1_beep, beep, 4); |
709 | static SENSOR_DEVICE_ATTR_RW(fan1_beep, beep, 5); |
710 | static SENSOR_DEVICE_ATTR_RW(fan2_beep, beep, 6); |
711 | static SENSOR_DEVICE_ATTR_RW(temp2_beep, beep, 7); |
712 | static SENSOR_DEVICE_ATTR_RW(in4_beep, beep, 7); |
713 | |
714 | static struct attribute *gl520_attributes[] = { |
715 | &dev_attr_cpu0_vid.attr, |
716 | |
717 | &sensor_dev_attr_in0_input.dev_attr.attr, |
718 | &sensor_dev_attr_in0_min.dev_attr.attr, |
719 | &sensor_dev_attr_in0_max.dev_attr.attr, |
720 | &sensor_dev_attr_in0_alarm.dev_attr.attr, |
721 | &sensor_dev_attr_in0_beep.dev_attr.attr, |
722 | &sensor_dev_attr_in1_input.dev_attr.attr, |
723 | &sensor_dev_attr_in1_min.dev_attr.attr, |
724 | &sensor_dev_attr_in1_max.dev_attr.attr, |
725 | &sensor_dev_attr_in1_alarm.dev_attr.attr, |
726 | &sensor_dev_attr_in1_beep.dev_attr.attr, |
727 | &sensor_dev_attr_in2_input.dev_attr.attr, |
728 | &sensor_dev_attr_in2_min.dev_attr.attr, |
729 | &sensor_dev_attr_in2_max.dev_attr.attr, |
730 | &sensor_dev_attr_in2_alarm.dev_attr.attr, |
731 | &sensor_dev_attr_in2_beep.dev_attr.attr, |
732 | &sensor_dev_attr_in3_input.dev_attr.attr, |
733 | &sensor_dev_attr_in3_min.dev_attr.attr, |
734 | &sensor_dev_attr_in3_max.dev_attr.attr, |
735 | &sensor_dev_attr_in3_alarm.dev_attr.attr, |
736 | &sensor_dev_attr_in3_beep.dev_attr.attr, |
737 | |
738 | &sensor_dev_attr_fan1_input.dev_attr.attr, |
739 | &sensor_dev_attr_fan1_min.dev_attr.attr, |
740 | &sensor_dev_attr_fan1_div.dev_attr.attr, |
741 | &sensor_dev_attr_fan1_alarm.dev_attr.attr, |
742 | &sensor_dev_attr_fan1_beep.dev_attr.attr, |
743 | &dev_attr_fan1_off.attr, |
744 | &sensor_dev_attr_fan2_input.dev_attr.attr, |
745 | &sensor_dev_attr_fan2_min.dev_attr.attr, |
746 | &sensor_dev_attr_fan2_div.dev_attr.attr, |
747 | &sensor_dev_attr_fan2_alarm.dev_attr.attr, |
748 | &sensor_dev_attr_fan2_beep.dev_attr.attr, |
749 | |
750 | &sensor_dev_attr_temp1_input.dev_attr.attr, |
751 | &sensor_dev_attr_temp1_max.dev_attr.attr, |
752 | &sensor_dev_attr_temp1_max_hyst.dev_attr.attr, |
753 | &sensor_dev_attr_temp1_alarm.dev_attr.attr, |
754 | &sensor_dev_attr_temp1_beep.dev_attr.attr, |
755 | |
756 | &dev_attr_alarms.attr, |
757 | &dev_attr_beep_enable.attr, |
758 | &dev_attr_beep_mask.attr, |
759 | NULL |
760 | }; |
761 | |
762 | static const struct attribute_group gl520_group = { |
763 | .attrs = gl520_attributes, |
764 | }; |
765 | |
766 | static struct attribute *gl520_attributes_in4[] = { |
767 | &sensor_dev_attr_in4_input.dev_attr.attr, |
768 | &sensor_dev_attr_in4_min.dev_attr.attr, |
769 | &sensor_dev_attr_in4_max.dev_attr.attr, |
770 | &sensor_dev_attr_in4_alarm.dev_attr.attr, |
771 | &sensor_dev_attr_in4_beep.dev_attr.attr, |
772 | NULL |
773 | }; |
774 | |
775 | static struct attribute *gl520_attributes_temp2[] = { |
776 | &sensor_dev_attr_temp2_input.dev_attr.attr, |
777 | &sensor_dev_attr_temp2_max.dev_attr.attr, |
778 | &sensor_dev_attr_temp2_max_hyst.dev_attr.attr, |
779 | &sensor_dev_attr_temp2_alarm.dev_attr.attr, |
780 | &sensor_dev_attr_temp2_beep.dev_attr.attr, |
781 | NULL |
782 | }; |
783 | |
784 | static const struct attribute_group gl520_group_in4 = { |
785 | .attrs = gl520_attributes_in4, |
786 | }; |
787 | |
788 | static const struct attribute_group gl520_group_temp2 = { |
789 | .attrs = gl520_attributes_temp2, |
790 | }; |
791 | |
792 | |
793 | /* |
794 | * Real code |
795 | */ |
796 | |
797 | /* Return 0 if detection is successful, -ENODEV otherwise */ |
798 | static int gl520_detect(struct i2c_client *client, struct i2c_board_info *info) |
799 | { |
800 | struct i2c_adapter *adapter = client->adapter; |
801 | |
802 | if (!i2c_check_functionality(adap: adapter, I2C_FUNC_SMBUS_BYTE_DATA | |
803 | I2C_FUNC_SMBUS_WORD_DATA)) |
804 | return -ENODEV; |
805 | |
806 | /* Determine the chip type. */ |
807 | if ((gl520_read_value(client, GL520_REG_CHIP_ID) != 0x20) || |
808 | ((gl520_read_value(client, GL520_REG_REVISION) & 0x7f) != 0x00) || |
809 | ((gl520_read_value(client, GL520_REG_CONF) & 0x80) != 0x00)) { |
810 | dev_dbg(&client->dev, "Unknown chip type, skipping\n" ); |
811 | return -ENODEV; |
812 | } |
813 | |
814 | strscpy(p: info->type, q: "gl520sm" , I2C_NAME_SIZE); |
815 | |
816 | return 0; |
817 | } |
818 | |
819 | /* Called when we have found a new GL520SM. */ |
820 | static void gl520_init_client(struct i2c_client *client) |
821 | { |
822 | struct gl520_data *data = i2c_get_clientdata(client); |
823 | u8 oldconf, conf; |
824 | |
825 | conf = oldconf = gl520_read_value(client, GL520_REG_CONF); |
826 | |
827 | data->alarm_mask = 0xff; |
828 | data->vrm = vid_which_vrm(); |
829 | |
830 | if (extra_sensor_type == 1) |
831 | conf &= ~0x10; |
832 | else if (extra_sensor_type == 2) |
833 | conf |= 0x10; |
834 | data->two_temps = !(conf & 0x10); |
835 | |
836 | /* If IRQ# is disabled, we can safely force comparator mode */ |
837 | if (!(conf & 0x20)) |
838 | conf &= 0xf7; |
839 | |
840 | /* Enable monitoring if needed */ |
841 | conf |= 0x40; |
842 | |
843 | if (conf != oldconf) |
844 | gl520_write_value(client, GL520_REG_CONF, value: conf); |
845 | |
846 | gl520_update_device(dev: &(client->dev)); |
847 | |
848 | if (data->fan_min[0] == 0) |
849 | data->alarm_mask &= ~0x20; |
850 | if (data->fan_min[1] == 0) |
851 | data->alarm_mask &= ~0x40; |
852 | |
853 | data->beep_mask &= data->alarm_mask; |
854 | gl520_write_value(client, GL520_REG_BEEP_MASK, value: data->beep_mask); |
855 | } |
856 | |
857 | static int gl520_probe(struct i2c_client *client) |
858 | { |
859 | struct device *dev = &client->dev; |
860 | struct device *hwmon_dev; |
861 | struct gl520_data *data; |
862 | |
863 | data = devm_kzalloc(dev, size: sizeof(struct gl520_data), GFP_KERNEL); |
864 | if (!data) |
865 | return -ENOMEM; |
866 | |
867 | i2c_set_clientdata(client, data); |
868 | mutex_init(&data->update_lock); |
869 | data->client = client; |
870 | |
871 | /* Initialize the GL520SM chip */ |
872 | gl520_init_client(client); |
873 | |
874 | /* sysfs hooks */ |
875 | data->groups[0] = &gl520_group; |
876 | |
877 | if (data->two_temps) |
878 | data->groups[1] = &gl520_group_temp2; |
879 | else |
880 | data->groups[1] = &gl520_group_in4; |
881 | |
882 | hwmon_dev = devm_hwmon_device_register_with_groups(dev, name: client->name, |
883 | drvdata: data, groups: data->groups); |
884 | return PTR_ERR_OR_ZERO(ptr: hwmon_dev); |
885 | } |
886 | |
887 | static const struct i2c_device_id gl520_id[] = { |
888 | { "gl520sm" , 0 }, |
889 | { } |
890 | }; |
891 | MODULE_DEVICE_TABLE(i2c, gl520_id); |
892 | |
893 | static struct i2c_driver gl520_driver = { |
894 | .class = I2C_CLASS_HWMON, |
895 | .driver = { |
896 | .name = "gl520sm" , |
897 | }, |
898 | .probe = gl520_probe, |
899 | .id_table = gl520_id, |
900 | .detect = gl520_detect, |
901 | .address_list = normal_i2c, |
902 | }; |
903 | |
904 | module_i2c_driver(gl520_driver); |
905 | |
906 | MODULE_AUTHOR("Frodo Looijaard <frodol@dds.nl>, " |
907 | "Kyösti Mälkki <kmalkki@cc.hut.fi>, " |
908 | "Maarten Deprez <maartendeprez@users.sourceforge.net>" ); |
909 | MODULE_DESCRIPTION("GL520SM driver" ); |
910 | MODULE_LICENSE("GPL" ); |
911 | |