diff options
author | Jonathan Herman <hermanjl@cs.unc.edu> | 2013-01-17 16:15:55 -0500 |
---|---|---|
committer | Jonathan Herman <hermanjl@cs.unc.edu> | 2013-01-17 16:15:55 -0500 |
commit | 8dea78da5cee153b8af9c07a2745f6c55057fe12 (patch) | |
tree | a8f4d49d63b1ecc92f2fddceba0655b2472c5bd9 /drivers/hwmon/pc87360.c | |
parent | 406089d01562f1e2bf9f089fd7637009ebaad589 (diff) |
Patched in Tegra support.
Diffstat (limited to 'drivers/hwmon/pc87360.c')
-rw-r--r-- | drivers/hwmon/pc87360.c | 635 |
1 files changed, 264 insertions, 371 deletions
diff --git a/drivers/hwmon/pc87360.c b/drivers/hwmon/pc87360.c index e35856bb79b..3d99b8854d7 100644 --- a/drivers/hwmon/pc87360.c +++ b/drivers/hwmon/pc87360.c | |||
@@ -56,11 +56,11 @@ static u8 confreg[4]; | |||
56 | static int init = 1; | 56 | static int init = 1; |
57 | module_param(init, int, 0); | 57 | module_param(init, int, 0); |
58 | MODULE_PARM_DESC(init, | 58 | MODULE_PARM_DESC(init, |
59 | "Chip initialization level:\n" | 59 | "Chip initialization level:\n" |
60 | " 0: None\n" | 60 | " 0: None\n" |
61 | "*1: Forcibly enable internal voltage and temperature channels, except in9\n" | 61 | "*1: Forcibly enable internal voltage and temperature channels, except in9\n" |
62 | " 2: Forcibly enable all voltage and temperature channels, except in9\n" | 62 | " 2: Forcibly enable all voltage and temperature channels, except in9\n" |
63 | " 3: Forcibly enable all voltage and temperature channels, including in9"); | 63 | " 3: Forcibly enable all voltage and temperature channels, including in9"); |
64 | 64 | ||
65 | static unsigned short force_id; | 65 | static unsigned short force_id; |
66 | module_param(force_id, ushort, 0); | 66 | module_param(force_id, ushort, 0); |
@@ -88,19 +88,19 @@ static const u8 logdev[LDNI_MAX] = { FSCM, VLM, TMS }; | |||
88 | static inline void superio_outb(int sioaddr, int reg, int val) | 88 | static inline void superio_outb(int sioaddr, int reg, int val) |
89 | { | 89 | { |
90 | outb(reg, sioaddr); | 90 | outb(reg, sioaddr); |
91 | outb(val, sioaddr + 1); | 91 | outb(val, sioaddr+1); |
92 | } | 92 | } |
93 | 93 | ||
94 | static inline int superio_inb(int sioaddr, int reg) | 94 | static inline int superio_inb(int sioaddr, int reg) |
95 | { | 95 | { |
96 | outb(reg, sioaddr); | 96 | outb(reg, sioaddr); |
97 | return inb(sioaddr + 1); | 97 | return inb(sioaddr+1); |
98 | } | 98 | } |
99 | 99 | ||
100 | static inline void superio_exit(int sioaddr) | 100 | static inline void superio_exit(int sioaddr) |
101 | { | 101 | { |
102 | outb(0x02, sioaddr); | 102 | outb(0x02, sioaddr); |
103 | outb(0x02, sioaddr + 1); | 103 | outb(0x02, sioaddr+1); |
104 | } | 104 | } |
105 | 105 | ||
106 | /* | 106 | /* |
@@ -122,18 +122,18 @@ static inline void superio_exit(int sioaddr) | |||
122 | #define PC87360_REG_FAN(nr) (0x07 + 3 * (nr)) | 122 | #define PC87360_REG_FAN(nr) (0x07 + 3 * (nr)) |
123 | #define PC87360_REG_FAN_STATUS(nr) (0x08 + 3 * (nr)) | 123 | #define PC87360_REG_FAN_STATUS(nr) (0x08 + 3 * (nr)) |
124 | 124 | ||
125 | #define FAN_FROM_REG(val, div) ((val) == 0 ? 0 : \ | 125 | #define FAN_FROM_REG(val,div) ((val) == 0 ? 0: \ |
126 | 480000 / ((val) * (div))) | 126 | 480000 / ((val)*(div))) |
127 | #define FAN_TO_REG(val, div) ((val) <= 100 ? 0 : \ | 127 | #define FAN_TO_REG(val,div) ((val) <= 100 ? 0 : \ |
128 | 480000 / ((val) * (div))) | 128 | 480000 / ((val)*(div))) |
129 | #define FAN_DIV_FROM_REG(val) (1 << (((val) >> 5) & 0x03)) | 129 | #define FAN_DIV_FROM_REG(val) (1 << ((val >> 5) & 0x03)) |
130 | #define FAN_STATUS_FROM_REG(val) ((val) & 0x07) | 130 | #define FAN_STATUS_FROM_REG(val) ((val) & 0x07) |
131 | 131 | ||
132 | #define FAN_CONFIG_MONITOR(val, nr) (((val) >> (2 + (nr) * 3)) & 1) | 132 | #define FAN_CONFIG_MONITOR(val,nr) (((val) >> (2 + nr * 3)) & 1) |
133 | #define FAN_CONFIG_CONTROL(val, nr) (((val) >> (3 + (nr) * 3)) & 1) | 133 | #define FAN_CONFIG_CONTROL(val,nr) (((val) >> (3 + nr * 3)) & 1) |
134 | #define FAN_CONFIG_INVERT(val, nr) (((val) >> (4 + (nr) * 3)) & 1) | 134 | #define FAN_CONFIG_INVERT(val,nr) (((val) >> (4 + nr * 3)) & 1) |
135 | 135 | ||
136 | #define PWM_FROM_REG(val, inv) ((inv) ? 255 - (val) : (val)) | 136 | #define PWM_FROM_REG(val,inv) ((inv) ? 255 - (val) : (val)) |
137 | static inline u8 PWM_TO_REG(int val, int inv) | 137 | static inline u8 PWM_TO_REG(int val, int inv) |
138 | { | 138 | { |
139 | if (inv) | 139 | if (inv) |
@@ -159,10 +159,10 @@ static inline u8 PWM_TO_REG(int val, int inv) | |||
159 | #define PC87365_REG_IN_ALARMS2 0x01 | 159 | #define PC87365_REG_IN_ALARMS2 0x01 |
160 | #define PC87365_REG_VID 0x06 | 160 | #define PC87365_REG_VID 0x06 |
161 | 161 | ||
162 | #define IN_FROM_REG(val, ref) (((val) * (ref) + 128) / 256) | 162 | #define IN_FROM_REG(val,ref) (((val) * (ref) + 128) / 256) |
163 | #define IN_TO_REG(val, ref) ((val) < 0 ? 0 : \ | 163 | #define IN_TO_REG(val,ref) ((val) < 0 ? 0 : \ |
164 | (val) * 256 >= (ref) * 255 ? 255 : \ | 164 | (val)*256 >= (ref)*255 ? 255: \ |
165 | ((val) * 256 + (ref) / 2) / (ref)) | 165 | ((val) * 256 + (ref)/2) / (ref)) |
166 | 166 | ||
167 | /* | 167 | /* |
168 | * Temperature registers and conversions | 168 | * Temperature registers and conversions |
@@ -228,7 +228,7 @@ struct pc87360_data { | |||
228 | */ | 228 | */ |
229 | 229 | ||
230 | static int pc87360_probe(struct platform_device *pdev); | 230 | static int pc87360_probe(struct platform_device *pdev); |
231 | static int pc87360_remove(struct platform_device *pdev); | 231 | static int __devexit pc87360_remove(struct platform_device *pdev); |
232 | 232 | ||
233 | static int pc87360_read_value(struct pc87360_data *data, u8 ldi, u8 bank, | 233 | static int pc87360_read_value(struct pc87360_data *data, u8 ldi, u8 bank, |
234 | u8 reg); | 234 | u8 reg); |
@@ -248,61 +248,50 @@ static struct platform_driver pc87360_driver = { | |||
248 | .name = "pc87360", | 248 | .name = "pc87360", |
249 | }, | 249 | }, |
250 | .probe = pc87360_probe, | 250 | .probe = pc87360_probe, |
251 | .remove = pc87360_remove, | 251 | .remove = __devexit_p(pc87360_remove), |
252 | }; | 252 | }; |
253 | 253 | ||
254 | /* | 254 | /* |
255 | * Sysfs stuff | 255 | * Sysfs stuff |
256 | */ | 256 | */ |
257 | 257 | ||
258 | static ssize_t show_fan_input(struct device *dev, | 258 | static ssize_t show_fan_input(struct device *dev, struct device_attribute *devattr, char *buf) |
259 | struct device_attribute *devattr, char *buf) | ||
260 | { | 259 | { |
261 | struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); | 260 | struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); |
262 | struct pc87360_data *data = pc87360_update_device(dev); | 261 | struct pc87360_data *data = pc87360_update_device(dev); |
263 | return sprintf(buf, "%u\n", FAN_FROM_REG(data->fan[attr->index], | 262 | return sprintf(buf, "%u\n", FAN_FROM_REG(data->fan[attr->index], |
264 | FAN_DIV_FROM_REG(data->fan_status[attr->index]))); | 263 | FAN_DIV_FROM_REG(data->fan_status[attr->index]))); |
265 | } | 264 | } |
266 | static ssize_t show_fan_min(struct device *dev, | 265 | static ssize_t show_fan_min(struct device *dev, struct device_attribute *devattr, char *buf) |
267 | struct device_attribute *devattr, char *buf) | ||
268 | { | 266 | { |
269 | struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); | 267 | struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); |
270 | struct pc87360_data *data = pc87360_update_device(dev); | 268 | struct pc87360_data *data = pc87360_update_device(dev); |
271 | return sprintf(buf, "%u\n", FAN_FROM_REG(data->fan_min[attr->index], | 269 | return sprintf(buf, "%u\n", FAN_FROM_REG(data->fan_min[attr->index], |
272 | FAN_DIV_FROM_REG(data->fan_status[attr->index]))); | 270 | FAN_DIV_FROM_REG(data->fan_status[attr->index]))); |
273 | } | 271 | } |
274 | static ssize_t show_fan_div(struct device *dev, | 272 | static ssize_t show_fan_div(struct device *dev, struct device_attribute *devattr, char *buf) |
275 | struct device_attribute *devattr, char *buf) | ||
276 | { | 273 | { |
277 | struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); | 274 | struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); |
278 | struct pc87360_data *data = pc87360_update_device(dev); | 275 | struct pc87360_data *data = pc87360_update_device(dev); |
279 | return sprintf(buf, "%u\n", | 276 | return sprintf(buf, "%u\n", |
280 | FAN_DIV_FROM_REG(data->fan_status[attr->index])); | 277 | FAN_DIV_FROM_REG(data->fan_status[attr->index])); |
281 | } | 278 | } |
282 | static ssize_t show_fan_status(struct device *dev, | 279 | static ssize_t show_fan_status(struct device *dev, struct device_attribute *devattr, char *buf) |
283 | struct device_attribute *devattr, char *buf) | ||
284 | { | 280 | { |
285 | struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); | 281 | struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); |
286 | struct pc87360_data *data = pc87360_update_device(dev); | 282 | struct pc87360_data *data = pc87360_update_device(dev); |
287 | return sprintf(buf, "%u\n", | 283 | return sprintf(buf, "%u\n", |
288 | FAN_STATUS_FROM_REG(data->fan_status[attr->index])); | 284 | FAN_STATUS_FROM_REG(data->fan_status[attr->index])); |
289 | } | 285 | } |
290 | static ssize_t set_fan_min(struct device *dev, | 286 | static ssize_t set_fan_min(struct device *dev, struct device_attribute *devattr, const char *buf, |
291 | struct device_attribute *devattr, const char *buf, | ||
292 | size_t count) | 287 | size_t count) |
293 | { | 288 | { |
294 | struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); | 289 | struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); |
295 | struct pc87360_data *data = dev_get_drvdata(dev); | 290 | struct pc87360_data *data = dev_get_drvdata(dev); |
296 | long fan_min; | 291 | long fan_min = simple_strtol(buf, NULL, 10); |
297 | int err; | ||
298 | |||
299 | err = kstrtol(buf, 10, &fan_min); | ||
300 | if (err) | ||
301 | return err; | ||
302 | 292 | ||
303 | mutex_lock(&data->update_lock); | 293 | mutex_lock(&data->update_lock); |
304 | fan_min = FAN_TO_REG(fan_min, | 294 | fan_min = FAN_TO_REG(fan_min, FAN_DIV_FROM_REG(data->fan_status[attr->index])); |
305 | FAN_DIV_FROM_REG(data->fan_status[attr->index])); | ||
306 | 295 | ||
307 | /* If it wouldn't fit, change clock divisor */ | 296 | /* If it wouldn't fit, change clock divisor */ |
308 | while (fan_min > 255 | 297 | while (fan_min > 255 |
@@ -312,13 +301,11 @@ static ssize_t set_fan_min(struct device *dev, | |||
312 | data->fan_status[attr->index] += 0x20; | 301 | data->fan_status[attr->index] += 0x20; |
313 | } | 302 | } |
314 | data->fan_min[attr->index] = fan_min > 255 ? 255 : fan_min; | 303 | data->fan_min[attr->index] = fan_min > 255 ? 255 : fan_min; |
315 | pc87360_write_value(data, LD_FAN, NO_BANK, | 304 | pc87360_write_value(data, LD_FAN, NO_BANK, PC87360_REG_FAN_MIN(attr->index), |
316 | PC87360_REG_FAN_MIN(attr->index), | ||
317 | data->fan_min[attr->index]); | 305 | data->fan_min[attr->index]); |
318 | 306 | ||
319 | /* Write new divider, preserve alarm bits */ | 307 | /* Write new divider, preserve alarm bits */ |
320 | pc87360_write_value(data, LD_FAN, NO_BANK, | 308 | pc87360_write_value(data, LD_FAN, NO_BANK, PC87360_REG_FAN_STATUS(attr->index), |
321 | PC87360_REG_FAN_STATUS(attr->index), | ||
322 | data->fan_status[attr->index] & 0xF9); | 309 | data->fan_status[attr->index] & 0xF9); |
323 | mutex_unlock(&data->update_lock); | 310 | mutex_unlock(&data->update_lock); |
324 | 311 | ||
@@ -346,16 +333,13 @@ static struct sensor_device_attribute fan_min[] = { | |||
346 | SENSOR_ATTR(fan3_min, S_IWUSR | S_IRUGO, show_fan_min, set_fan_min, 2), | 333 | SENSOR_ATTR(fan3_min, S_IWUSR | S_IRUGO, show_fan_min, set_fan_min, 2), |
347 | }; | 334 | }; |
348 | 335 | ||
349 | #define FAN_UNIT_ATTRS(X) \ | 336 | #define FAN_UNIT_ATTRS(X) \ |
350 | { &fan_input[X].dev_attr.attr, \ | 337 | &fan_input[X].dev_attr.attr, \ |
351 | &fan_status[X].dev_attr.attr, \ | 338 | &fan_status[X].dev_attr.attr, \ |
352 | &fan_div[X].dev_attr.attr, \ | 339 | &fan_div[X].dev_attr.attr, \ |
353 | &fan_min[X].dev_attr.attr, \ | 340 | &fan_min[X].dev_attr.attr |
354 | NULL \ | ||
355 | } | ||
356 | 341 | ||
357 | static ssize_t show_pwm(struct device *dev, struct device_attribute *devattr, | 342 | static ssize_t show_pwm(struct device *dev, struct device_attribute *devattr, char *buf) |
358 | char *buf) | ||
359 | { | 343 | { |
360 | struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); | 344 | struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); |
361 | struct pc87360_data *data = pc87360_update_device(dev); | 345 | struct pc87360_data *data = pc87360_update_device(dev); |
@@ -364,17 +348,12 @@ static ssize_t show_pwm(struct device *dev, struct device_attribute *devattr, | |||
364 | FAN_CONFIG_INVERT(data->fan_conf, | 348 | FAN_CONFIG_INVERT(data->fan_conf, |
365 | attr->index))); | 349 | attr->index))); |
366 | } | 350 | } |
367 | static ssize_t set_pwm(struct device *dev, struct device_attribute *devattr, | 351 | static ssize_t set_pwm(struct device *dev, struct device_attribute *devattr, const char *buf, |
368 | const char *buf, size_t count) | 352 | size_t count) |
369 | { | 353 | { |
370 | struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); | 354 | struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); |
371 | struct pc87360_data *data = dev_get_drvdata(dev); | 355 | struct pc87360_data *data = dev_get_drvdata(dev); |
372 | long val; | 356 | long val = simple_strtol(buf, NULL, 10); |
373 | int err; | ||
374 | |||
375 | err = kstrtol(buf, 10, &val); | ||
376 | if (err) | ||
377 | return err; | ||
378 | 357 | ||
379 | mutex_lock(&data->update_lock); | 358 | mutex_lock(&data->update_lock); |
380 | data->pwm[attr->index] = PWM_TO_REG(val, | 359 | data->pwm[attr->index] = PWM_TO_REG(val, |
@@ -391,60 +370,52 @@ static struct sensor_device_attribute pwm[] = { | |||
391 | SENSOR_ATTR(pwm3, S_IWUSR | S_IRUGO, show_pwm, set_pwm, 2), | 370 | SENSOR_ATTR(pwm3, S_IWUSR | S_IRUGO, show_pwm, set_pwm, 2), |
392 | }; | 371 | }; |
393 | 372 | ||
394 | static struct attribute *pc8736x_fan_attr[][5] = { | 373 | static struct attribute * pc8736x_fan_attr_array[] = { |
395 | FAN_UNIT_ATTRS(0), | 374 | FAN_UNIT_ATTRS(0), |
396 | FAN_UNIT_ATTRS(1), | 375 | FAN_UNIT_ATTRS(1), |
397 | FAN_UNIT_ATTRS(2) | 376 | FAN_UNIT_ATTRS(2), |
377 | &pwm[0].dev_attr.attr, | ||
378 | &pwm[1].dev_attr.attr, | ||
379 | &pwm[2].dev_attr.attr, | ||
380 | NULL | ||
398 | }; | 381 | }; |
399 | 382 | static const struct attribute_group pc8736x_fan_group = { | |
400 | static const struct attribute_group pc8736x_fan_attr_group[] = { | 383 | .attrs = pc8736x_fan_attr_array, |
401 | { .attrs = pc8736x_fan_attr[0], }, | ||
402 | { .attrs = pc8736x_fan_attr[1], }, | ||
403 | { .attrs = pc8736x_fan_attr[2], }, | ||
404 | }; | 384 | }; |
405 | 385 | ||
406 | static ssize_t show_in_input(struct device *dev, | 386 | static ssize_t show_in_input(struct device *dev, struct device_attribute *devattr, char *buf) |
407 | struct device_attribute *devattr, char *buf) | ||
408 | { | 387 | { |
409 | struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); | 388 | struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); |
410 | struct pc87360_data *data = pc87360_update_device(dev); | 389 | struct pc87360_data *data = pc87360_update_device(dev); |
411 | return sprintf(buf, "%u\n", IN_FROM_REG(data->in[attr->index], | 390 | return sprintf(buf, "%u\n", IN_FROM_REG(data->in[attr->index], |
412 | data->in_vref)); | 391 | data->in_vref)); |
413 | } | 392 | } |
414 | static ssize_t show_in_min(struct device *dev, | 393 | static ssize_t show_in_min(struct device *dev, struct device_attribute *devattr, char *buf) |
415 | struct device_attribute *devattr, char *buf) | ||
416 | { | 394 | { |
417 | struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); | 395 | struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); |
418 | struct pc87360_data *data = pc87360_update_device(dev); | 396 | struct pc87360_data *data = pc87360_update_device(dev); |
419 | return sprintf(buf, "%u\n", IN_FROM_REG(data->in_min[attr->index], | 397 | return sprintf(buf, "%u\n", IN_FROM_REG(data->in_min[attr->index], |
420 | data->in_vref)); | 398 | data->in_vref)); |
421 | } | 399 | } |
422 | static ssize_t show_in_max(struct device *dev, | 400 | static ssize_t show_in_max(struct device *dev, struct device_attribute *devattr, char *buf) |
423 | struct device_attribute *devattr, char *buf) | ||
424 | { | 401 | { |
425 | struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); | 402 | struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); |
426 | struct pc87360_data *data = pc87360_update_device(dev); | 403 | struct pc87360_data *data = pc87360_update_device(dev); |
427 | return sprintf(buf, "%u\n", IN_FROM_REG(data->in_max[attr->index], | 404 | return sprintf(buf, "%u\n", IN_FROM_REG(data->in_max[attr->index], |
428 | data->in_vref)); | 405 | data->in_vref)); |
429 | } | 406 | } |
430 | static ssize_t show_in_status(struct device *dev, | 407 | static ssize_t show_in_status(struct device *dev, struct device_attribute *devattr, char *buf) |
431 | struct device_attribute *devattr, char *buf) | ||
432 | { | 408 | { |
433 | struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); | 409 | struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); |
434 | struct pc87360_data *data = pc87360_update_device(dev); | 410 | struct pc87360_data *data = pc87360_update_device(dev); |
435 | return sprintf(buf, "%u\n", data->in_status[attr->index]); | 411 | return sprintf(buf, "%u\n", data->in_status[attr->index]); |
436 | } | 412 | } |
437 | static ssize_t set_in_min(struct device *dev, struct device_attribute *devattr, | 413 | static ssize_t set_in_min(struct device *dev, struct device_attribute *devattr, const char *buf, |
438 | const char *buf, size_t count) | 414 | size_t count) |
439 | { | 415 | { |
440 | struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); | 416 | struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); |
441 | struct pc87360_data *data = dev_get_drvdata(dev); | 417 | struct pc87360_data *data = dev_get_drvdata(dev); |
442 | long val; | 418 | long val = simple_strtol(buf, NULL, 10); |
443 | int err; | ||
444 | |||
445 | err = kstrtol(buf, 10, &val); | ||
446 | if (err) | ||
447 | return err; | ||
448 | 419 | ||
449 | mutex_lock(&data->update_lock); | 420 | mutex_lock(&data->update_lock); |
450 | data->in_min[attr->index] = IN_TO_REG(val, data->in_vref); | 421 | data->in_min[attr->index] = IN_TO_REG(val, data->in_vref); |
@@ -453,17 +424,12 @@ static ssize_t set_in_min(struct device *dev, struct device_attribute *devattr, | |||
453 | mutex_unlock(&data->update_lock); | 424 | mutex_unlock(&data->update_lock); |
454 | return count; | 425 | return count; |
455 | } | 426 | } |
456 | static ssize_t set_in_max(struct device *dev, struct device_attribute *devattr, | 427 | static ssize_t set_in_max(struct device *dev, struct device_attribute *devattr, const char *buf, |
457 | const char *buf, size_t count) | 428 | size_t count) |
458 | { | 429 | { |
459 | struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); | 430 | struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); |
460 | struct pc87360_data *data = dev_get_drvdata(dev); | 431 | struct pc87360_data *data = dev_get_drvdata(dev); |
461 | long val; | 432 | long val = simple_strtol(buf, NULL, 10); |
462 | int err; | ||
463 | |||
464 | err = kstrtol(buf, 10, &val); | ||
465 | if (err) | ||
466 | return err; | ||
467 | 433 | ||
468 | mutex_lock(&data->update_lock); | 434 | mutex_lock(&data->update_lock); |
469 | data->in_max[attr->index] = IN_TO_REG(val, | 435 | data->in_max[attr->index] = IN_TO_REG(val, |
@@ -532,11 +498,9 @@ static struct sensor_device_attribute in_max[] = { | |||
532 | #define CHAN_ALM_MAX 0x04 /* max limit exceeded */ | 498 | #define CHAN_ALM_MAX 0x04 /* max limit exceeded */ |
533 | #define TEMP_ALM_CRIT 0x08 /* temp crit exceeded (temp only) */ | 499 | #define TEMP_ALM_CRIT 0x08 /* temp crit exceeded (temp only) */ |
534 | 500 | ||
535 | /* | 501 | /* show_in_min/max_alarm() reads data from the per-channel status |
536 | * show_in_min/max_alarm() reads data from the per-channel status | 502 | register (sec 11.5.12), not the vin event status registers (sec |
537 | * register (sec 11.5.12), not the vin event status registers (sec | 503 | 11.5.2) that (legacy) show_in_alarm() resds (via data->in_alarms) */ |
538 | * 11.5.2) that (legacy) show_in_alarm() resds (via data->in_alarms) | ||
539 | */ | ||
540 | 504 | ||
541 | static ssize_t show_in_min_alarm(struct device *dev, | 505 | static ssize_t show_in_min_alarm(struct device *dev, |
542 | struct device_attribute *devattr, char *buf) | 506 | struct device_attribute *devattr, char *buf) |
@@ -590,38 +554,27 @@ static struct sensor_device_attribute in_max_alarm[] = { | |||
590 | &in_min_alarm[X].dev_attr.attr, \ | 554 | &in_min_alarm[X].dev_attr.attr, \ |
591 | &in_max_alarm[X].dev_attr.attr | 555 | &in_max_alarm[X].dev_attr.attr |
592 | 556 | ||
593 | static ssize_t show_vid(struct device *dev, struct device_attribute *attr, | 557 | static ssize_t show_vid(struct device *dev, struct device_attribute *attr, char *buf) |
594 | char *buf) | ||
595 | { | 558 | { |
596 | struct pc87360_data *data = pc87360_update_device(dev); | 559 | struct pc87360_data *data = pc87360_update_device(dev); |
597 | return sprintf(buf, "%u\n", vid_from_reg(data->vid, data->vrm)); | 560 | return sprintf(buf, "%u\n", vid_from_reg(data->vid, data->vrm)); |
598 | } | 561 | } |
599 | static DEVICE_ATTR(cpu0_vid, S_IRUGO, show_vid, NULL); | 562 | static DEVICE_ATTR(cpu0_vid, S_IRUGO, show_vid, NULL); |
600 | 563 | ||
601 | static ssize_t show_vrm(struct device *dev, struct device_attribute *attr, | 564 | static ssize_t show_vrm(struct device *dev, struct device_attribute *attr, char *buf) |
602 | char *buf) | ||
603 | { | 565 | { |
604 | struct pc87360_data *data = dev_get_drvdata(dev); | 566 | struct pc87360_data *data = dev_get_drvdata(dev); |
605 | return sprintf(buf, "%u\n", data->vrm); | 567 | return sprintf(buf, "%u\n", data->vrm); |
606 | } | 568 | } |
607 | static ssize_t set_vrm(struct device *dev, struct device_attribute *attr, | 569 | static ssize_t set_vrm(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) |
608 | const char *buf, size_t count) | ||
609 | { | 570 | { |
610 | struct pc87360_data *data = dev_get_drvdata(dev); | 571 | struct pc87360_data *data = dev_get_drvdata(dev); |
611 | unsigned long val; | 572 | data->vrm = simple_strtoul(buf, NULL, 10); |
612 | int err; | ||
613 | |||
614 | err = kstrtoul(buf, 10, &val); | ||
615 | if (err) | ||
616 | return err; | ||
617 | |||
618 | data->vrm = val; | ||
619 | return count; | 573 | return count; |
620 | } | 574 | } |
621 | static DEVICE_ATTR(vrm, S_IRUGO | S_IWUSR, show_vrm, set_vrm); | 575 | static DEVICE_ATTR(vrm, S_IRUGO | S_IWUSR, show_vrm, set_vrm); |
622 | 576 | ||
623 | static ssize_t show_in_alarms(struct device *dev, | 577 | static ssize_t show_in_alarms(struct device *dev, struct device_attribute *attr, char *buf) |
624 | struct device_attribute *attr, char *buf) | ||
625 | { | 578 | { |
626 | struct pc87360_data *data = pc87360_update_device(dev); | 579 | struct pc87360_data *data = pc87360_update_device(dev); |
627 | return sprintf(buf, "%u\n", data->in_alarms); | 580 | return sprintf(buf, "%u\n", data->in_alarms); |
@@ -649,58 +602,46 @@ static const struct attribute_group pc8736x_vin_group = { | |||
649 | .attrs = pc8736x_vin_attr_array, | 602 | .attrs = pc8736x_vin_attr_array, |
650 | }; | 603 | }; |
651 | 604 | ||
652 | static ssize_t show_therm_input(struct device *dev, | 605 | static ssize_t show_therm_input(struct device *dev, struct device_attribute *devattr, char *buf) |
653 | struct device_attribute *devattr, char *buf) | ||
654 | { | 606 | { |
655 | struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); | 607 | struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); |
656 | struct pc87360_data *data = pc87360_update_device(dev); | 608 | struct pc87360_data *data = pc87360_update_device(dev); |
657 | return sprintf(buf, "%u\n", IN_FROM_REG(data->in[attr->index], | 609 | return sprintf(buf, "%u\n", IN_FROM_REG(data->in[attr->index], |
658 | data->in_vref)); | 610 | data->in_vref)); |
659 | } | 611 | } |
660 | static ssize_t show_therm_min(struct device *dev, | 612 | static ssize_t show_therm_min(struct device *dev, struct device_attribute *devattr, char *buf) |
661 | struct device_attribute *devattr, char *buf) | ||
662 | { | 613 | { |
663 | struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); | 614 | struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); |
664 | struct pc87360_data *data = pc87360_update_device(dev); | 615 | struct pc87360_data *data = pc87360_update_device(dev); |
665 | return sprintf(buf, "%u\n", IN_FROM_REG(data->in_min[attr->index], | 616 | return sprintf(buf, "%u\n", IN_FROM_REG(data->in_min[attr->index], |
666 | data->in_vref)); | 617 | data->in_vref)); |
667 | } | 618 | } |
668 | static ssize_t show_therm_max(struct device *dev, | 619 | static ssize_t show_therm_max(struct device *dev, struct device_attribute *devattr, char *buf) |
669 | struct device_attribute *devattr, char *buf) | ||
670 | { | 620 | { |
671 | struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); | 621 | struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); |
672 | struct pc87360_data *data = pc87360_update_device(dev); | 622 | struct pc87360_data *data = pc87360_update_device(dev); |
673 | return sprintf(buf, "%u\n", IN_FROM_REG(data->in_max[attr->index], | 623 | return sprintf(buf, "%u\n", IN_FROM_REG(data->in_max[attr->index], |
674 | data->in_vref)); | 624 | data->in_vref)); |
675 | } | 625 | } |
676 | static ssize_t show_therm_crit(struct device *dev, | 626 | static ssize_t show_therm_crit(struct device *dev, struct device_attribute *devattr, char *buf) |
677 | struct device_attribute *devattr, char *buf) | ||
678 | { | 627 | { |
679 | struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); | 628 | struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); |
680 | struct pc87360_data *data = pc87360_update_device(dev); | 629 | struct pc87360_data *data = pc87360_update_device(dev); |
681 | return sprintf(buf, "%u\n", IN_FROM_REG(data->in_crit[attr->index-11], | 630 | return sprintf(buf, "%u\n", IN_FROM_REG(data->in_crit[attr->index-11], |
682 | data->in_vref)); | 631 | data->in_vref)); |
683 | } | 632 | } |
684 | static ssize_t show_therm_status(struct device *dev, | 633 | static ssize_t show_therm_status(struct device *dev, struct device_attribute *devattr, char *buf) |
685 | struct device_attribute *devattr, char *buf) | ||
686 | { | 634 | { |
687 | struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); | 635 | struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); |
688 | struct pc87360_data *data = pc87360_update_device(dev); | 636 | struct pc87360_data *data = pc87360_update_device(dev); |
689 | return sprintf(buf, "%u\n", data->in_status[attr->index]); | 637 | return sprintf(buf, "%u\n", data->in_status[attr->index]); |
690 | } | 638 | } |
691 | 639 | static ssize_t set_therm_min(struct device *dev, struct device_attribute *devattr, const char *buf, | |
692 | static ssize_t set_therm_min(struct device *dev, | 640 | size_t count) |
693 | struct device_attribute *devattr, | ||
694 | const char *buf, size_t count) | ||
695 | { | 641 | { |
696 | struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); | 642 | struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); |
697 | struct pc87360_data *data = dev_get_drvdata(dev); | 643 | struct pc87360_data *data = dev_get_drvdata(dev); |
698 | long val; | 644 | long val = simple_strtol(buf, NULL, 10); |
699 | int err; | ||
700 | |||
701 | err = kstrtol(buf, 10, &val); | ||
702 | if (err) | ||
703 | return err; | ||
704 | 645 | ||
705 | mutex_lock(&data->update_lock); | 646 | mutex_lock(&data->update_lock); |
706 | data->in_min[attr->index] = IN_TO_REG(val, data->in_vref); | 647 | data->in_min[attr->index] = IN_TO_REG(val, data->in_vref); |
@@ -709,19 +650,12 @@ static ssize_t set_therm_min(struct device *dev, | |||
709 | mutex_unlock(&data->update_lock); | 650 | mutex_unlock(&data->update_lock); |
710 | return count; | 651 | return count; |
711 | } | 652 | } |
712 | 653 | static ssize_t set_therm_max(struct device *dev, struct device_attribute *devattr, const char *buf, | |
713 | static ssize_t set_therm_max(struct device *dev, | 654 | size_t count) |
714 | struct device_attribute *devattr, | ||
715 | const char *buf, size_t count) | ||
716 | { | 655 | { |
717 | struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); | 656 | struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); |
718 | struct pc87360_data *data = dev_get_drvdata(dev); | 657 | struct pc87360_data *data = dev_get_drvdata(dev); |
719 | long val; | 658 | long val = simple_strtol(buf, NULL, 10); |
720 | int err; | ||
721 | |||
722 | err = kstrtol(buf, 10, &val); | ||
723 | if (err) | ||
724 | return err; | ||
725 | 659 | ||
726 | mutex_lock(&data->update_lock); | 660 | mutex_lock(&data->update_lock); |
727 | data->in_max[attr->index] = IN_TO_REG(val, data->in_vref); | 661 | data->in_max[attr->index] = IN_TO_REG(val, data->in_vref); |
@@ -730,18 +664,12 @@ static ssize_t set_therm_max(struct device *dev, | |||
730 | mutex_unlock(&data->update_lock); | 664 | mutex_unlock(&data->update_lock); |
731 | return count; | 665 | return count; |
732 | } | 666 | } |
733 | static ssize_t set_therm_crit(struct device *dev, | 667 | static ssize_t set_therm_crit(struct device *dev, struct device_attribute *devattr, const char *buf, |
734 | struct device_attribute *devattr, | 668 | size_t count) |
735 | const char *buf, size_t count) | ||
736 | { | 669 | { |
737 | struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); | 670 | struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); |
738 | struct pc87360_data *data = dev_get_drvdata(dev); | 671 | struct pc87360_data *data = dev_get_drvdata(dev); |
739 | long val; | 672 | long val = simple_strtol(buf, NULL, 10); |
740 | int err; | ||
741 | |||
742 | err = kstrtol(buf, 10, &val); | ||
743 | if (err) | ||
744 | return err; | ||
745 | 673 | ||
746 | mutex_lock(&data->update_lock); | 674 | mutex_lock(&data->update_lock); |
747 | data->in_crit[attr->index-11] = IN_TO_REG(val, data->in_vref); | 675 | data->in_crit[attr->index-11] = IN_TO_REG(val, data->in_vref); |
@@ -751,49 +679,46 @@ static ssize_t set_therm_crit(struct device *dev, | |||
751 | return count; | 679 | return count; |
752 | } | 680 | } |
753 | 681 | ||
754 | /* | 682 | /* the +11 term below reflects the fact that VLM units 11,12,13 are |
755 | * the +11 term below reflects the fact that VLM units 11,12,13 are | 683 | used in the chip to measure voltage across the thermistors |
756 | * used in the chip to measure voltage across the thermistors | 684 | */ |
757 | */ | ||
758 | static struct sensor_device_attribute therm_input[] = { | 685 | static struct sensor_device_attribute therm_input[] = { |
759 | SENSOR_ATTR(temp4_input, S_IRUGO, show_therm_input, NULL, 0 + 11), | 686 | SENSOR_ATTR(temp4_input, S_IRUGO, show_therm_input, NULL, 0+11), |
760 | SENSOR_ATTR(temp5_input, S_IRUGO, show_therm_input, NULL, 1 + 11), | 687 | SENSOR_ATTR(temp5_input, S_IRUGO, show_therm_input, NULL, 1+11), |
761 | SENSOR_ATTR(temp6_input, S_IRUGO, show_therm_input, NULL, 2 + 11), | 688 | SENSOR_ATTR(temp6_input, S_IRUGO, show_therm_input, NULL, 2+11), |
762 | }; | 689 | }; |
763 | static struct sensor_device_attribute therm_status[] = { | 690 | static struct sensor_device_attribute therm_status[] = { |
764 | SENSOR_ATTR(temp4_status, S_IRUGO, show_therm_status, NULL, 0 + 11), | 691 | SENSOR_ATTR(temp4_status, S_IRUGO, show_therm_status, NULL, 0+11), |
765 | SENSOR_ATTR(temp5_status, S_IRUGO, show_therm_status, NULL, 1 + 11), | 692 | SENSOR_ATTR(temp5_status, S_IRUGO, show_therm_status, NULL, 1+11), |
766 | SENSOR_ATTR(temp6_status, S_IRUGO, show_therm_status, NULL, 2 + 11), | 693 | SENSOR_ATTR(temp6_status, S_IRUGO, show_therm_status, NULL, 2+11), |
767 | }; | 694 | }; |
768 | static struct sensor_device_attribute therm_min[] = { | 695 | static struct sensor_device_attribute therm_min[] = { |
769 | SENSOR_ATTR(temp4_min, S_IRUGO | S_IWUSR, | 696 | SENSOR_ATTR(temp4_min, S_IRUGO | S_IWUSR, |
770 | show_therm_min, set_therm_min, 0 + 11), | 697 | show_therm_min, set_therm_min, 0+11), |
771 | SENSOR_ATTR(temp5_min, S_IRUGO | S_IWUSR, | 698 | SENSOR_ATTR(temp5_min, S_IRUGO | S_IWUSR, |
772 | show_therm_min, set_therm_min, 1 + 11), | 699 | show_therm_min, set_therm_min, 1+11), |
773 | SENSOR_ATTR(temp6_min, S_IRUGO | S_IWUSR, | 700 | SENSOR_ATTR(temp6_min, S_IRUGO | S_IWUSR, |
774 | show_therm_min, set_therm_min, 2 + 11), | 701 | show_therm_min, set_therm_min, 2+11), |
775 | }; | 702 | }; |
776 | static struct sensor_device_attribute therm_max[] = { | 703 | static struct sensor_device_attribute therm_max[] = { |
777 | SENSOR_ATTR(temp4_max, S_IRUGO | S_IWUSR, | 704 | SENSOR_ATTR(temp4_max, S_IRUGO | S_IWUSR, |
778 | show_therm_max, set_therm_max, 0 + 11), | 705 | show_therm_max, set_therm_max, 0+11), |
779 | SENSOR_ATTR(temp5_max, S_IRUGO | S_IWUSR, | 706 | SENSOR_ATTR(temp5_max, S_IRUGO | S_IWUSR, |
780 | show_therm_max, set_therm_max, 1 + 11), | 707 | show_therm_max, set_therm_max, 1+11), |
781 | SENSOR_ATTR(temp6_max, S_IRUGO | S_IWUSR, | 708 | SENSOR_ATTR(temp6_max, S_IRUGO | S_IWUSR, |
782 | show_therm_max, set_therm_max, 2 + 11), | 709 | show_therm_max, set_therm_max, 2+11), |
783 | }; | 710 | }; |
784 | static struct sensor_device_attribute therm_crit[] = { | 711 | static struct sensor_device_attribute therm_crit[] = { |
785 | SENSOR_ATTR(temp4_crit, S_IRUGO | S_IWUSR, | 712 | SENSOR_ATTR(temp4_crit, S_IRUGO | S_IWUSR, |
786 | show_therm_crit, set_therm_crit, 0 + 11), | 713 | show_therm_crit, set_therm_crit, 0+11), |
787 | SENSOR_ATTR(temp5_crit, S_IRUGO | S_IWUSR, | 714 | SENSOR_ATTR(temp5_crit, S_IRUGO | S_IWUSR, |
788 | show_therm_crit, set_therm_crit, 1 + 11), | 715 | show_therm_crit, set_therm_crit, 1+11), |
789 | SENSOR_ATTR(temp6_crit, S_IRUGO | S_IWUSR, | 716 | SENSOR_ATTR(temp6_crit, S_IRUGO | S_IWUSR, |
790 | show_therm_crit, set_therm_crit, 2 + 11), | 717 | show_therm_crit, set_therm_crit, 2+11), |
791 | }; | 718 | }; |
792 | 719 | ||
793 | /* | 720 | /* show_therm_min/max_alarm() reads data from the per-channel voltage |
794 | * show_therm_min/max_alarm() reads data from the per-channel voltage | 721 | status register (sec 11.5.12) */ |
795 | * status register (sec 11.5.12) | ||
796 | */ | ||
797 | 722 | ||
798 | static ssize_t show_therm_min_alarm(struct device *dev, | 723 | static ssize_t show_therm_min_alarm(struct device *dev, |
799 | struct device_attribute *devattr, char *buf) | 724 | struct device_attribute *devattr, char *buf) |
@@ -822,27 +747,27 @@ static ssize_t show_therm_crit_alarm(struct device *dev, | |||
822 | 747 | ||
823 | static struct sensor_device_attribute therm_min_alarm[] = { | 748 | static struct sensor_device_attribute therm_min_alarm[] = { |
824 | SENSOR_ATTR(temp4_min_alarm, S_IRUGO, | 749 | SENSOR_ATTR(temp4_min_alarm, S_IRUGO, |
825 | show_therm_min_alarm, NULL, 0 + 11), | 750 | show_therm_min_alarm, NULL, 0+11), |
826 | SENSOR_ATTR(temp5_min_alarm, S_IRUGO, | 751 | SENSOR_ATTR(temp5_min_alarm, S_IRUGO, |
827 | show_therm_min_alarm, NULL, 1 + 11), | 752 | show_therm_min_alarm, NULL, 1+11), |
828 | SENSOR_ATTR(temp6_min_alarm, S_IRUGO, | 753 | SENSOR_ATTR(temp6_min_alarm, S_IRUGO, |
829 | show_therm_min_alarm, NULL, 2 + 11), | 754 | show_therm_min_alarm, NULL, 2+11), |
830 | }; | 755 | }; |
831 | static struct sensor_device_attribute therm_max_alarm[] = { | 756 | static struct sensor_device_attribute therm_max_alarm[] = { |
832 | SENSOR_ATTR(temp4_max_alarm, S_IRUGO, | 757 | SENSOR_ATTR(temp4_max_alarm, S_IRUGO, |
833 | show_therm_max_alarm, NULL, 0 + 11), | 758 | show_therm_max_alarm, NULL, 0+11), |
834 | SENSOR_ATTR(temp5_max_alarm, S_IRUGO, | 759 | SENSOR_ATTR(temp5_max_alarm, S_IRUGO, |
835 | show_therm_max_alarm, NULL, 1 + 11), | 760 | show_therm_max_alarm, NULL, 1+11), |
836 | SENSOR_ATTR(temp6_max_alarm, S_IRUGO, | 761 | SENSOR_ATTR(temp6_max_alarm, S_IRUGO, |
837 | show_therm_max_alarm, NULL, 2 + 11), | 762 | show_therm_max_alarm, NULL, 2+11), |
838 | }; | 763 | }; |
839 | static struct sensor_device_attribute therm_crit_alarm[] = { | 764 | static struct sensor_device_attribute therm_crit_alarm[] = { |
840 | SENSOR_ATTR(temp4_crit_alarm, S_IRUGO, | 765 | SENSOR_ATTR(temp4_crit_alarm, S_IRUGO, |
841 | show_therm_crit_alarm, NULL, 0 + 11), | 766 | show_therm_crit_alarm, NULL, 0+11), |
842 | SENSOR_ATTR(temp5_crit_alarm, S_IRUGO, | 767 | SENSOR_ATTR(temp5_crit_alarm, S_IRUGO, |
843 | show_therm_crit_alarm, NULL, 1 + 11), | 768 | show_therm_crit_alarm, NULL, 1+11), |
844 | SENSOR_ATTR(temp6_crit_alarm, S_IRUGO, | 769 | SENSOR_ATTR(temp6_crit_alarm, S_IRUGO, |
845 | show_therm_crit_alarm, NULL, 2 + 11), | 770 | show_therm_crit_alarm, NULL, 2+11), |
846 | }; | 771 | }; |
847 | 772 | ||
848 | #define THERM_UNIT_ATTRS(X) \ | 773 | #define THERM_UNIT_ATTRS(X) \ |
@@ -855,7 +780,7 @@ static struct sensor_device_attribute therm_crit_alarm[] = { | |||
855 | &therm_max_alarm[X].dev_attr.attr, \ | 780 | &therm_max_alarm[X].dev_attr.attr, \ |
856 | &therm_crit_alarm[X].dev_attr.attr | 781 | &therm_crit_alarm[X].dev_attr.attr |
857 | 782 | ||
858 | static struct attribute *pc8736x_therm_attr_array[] = { | 783 | static struct attribute * pc8736x_therm_attr_array[] = { |
859 | THERM_UNIT_ATTRS(0), | 784 | THERM_UNIT_ATTRS(0), |
860 | THERM_UNIT_ATTRS(1), | 785 | THERM_UNIT_ATTRS(1), |
861 | THERM_UNIT_ATTRS(2), | 786 | THERM_UNIT_ATTRS(2), |
@@ -865,59 +790,42 @@ static const struct attribute_group pc8736x_therm_group = { | |||
865 | .attrs = pc8736x_therm_attr_array, | 790 | .attrs = pc8736x_therm_attr_array, |
866 | }; | 791 | }; |
867 | 792 | ||
868 | static ssize_t show_temp_input(struct device *dev, | 793 | static ssize_t show_temp_input(struct device *dev, struct device_attribute *devattr, char *buf) |
869 | struct device_attribute *devattr, char *buf) | ||
870 | { | 794 | { |
871 | struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); | 795 | struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); |
872 | struct pc87360_data *data = pc87360_update_device(dev); | 796 | struct pc87360_data *data = pc87360_update_device(dev); |
873 | return sprintf(buf, "%d\n", TEMP_FROM_REG(data->temp[attr->index])); | 797 | return sprintf(buf, "%d\n", TEMP_FROM_REG(data->temp[attr->index])); |
874 | } | 798 | } |
875 | 799 | static ssize_t show_temp_min(struct device *dev, struct device_attribute *devattr, char *buf) | |
876 | static ssize_t show_temp_min(struct device *dev, | ||
877 | struct device_attribute *devattr, char *buf) | ||
878 | { | 800 | { |
879 | struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); | 801 | struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); |
880 | struct pc87360_data *data = pc87360_update_device(dev); | 802 | struct pc87360_data *data = pc87360_update_device(dev); |
881 | return sprintf(buf, "%d\n", TEMP_FROM_REG(data->temp_min[attr->index])); | 803 | return sprintf(buf, "%d\n", TEMP_FROM_REG(data->temp_min[attr->index])); |
882 | } | 804 | } |
883 | 805 | static ssize_t show_temp_max(struct device *dev, struct device_attribute *devattr, char *buf) | |
884 | static ssize_t show_temp_max(struct device *dev, | ||
885 | struct device_attribute *devattr, char *buf) | ||
886 | { | 806 | { |
887 | struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); | 807 | struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); |
888 | struct pc87360_data *data = pc87360_update_device(dev); | 808 | struct pc87360_data *data = pc87360_update_device(dev); |
889 | return sprintf(buf, "%d\n", TEMP_FROM_REG(data->temp_max[attr->index])); | 809 | return sprintf(buf, "%d\n", TEMP_FROM_REG(data->temp_max[attr->index])); |
890 | } | 810 | } |
891 | 811 | static ssize_t show_temp_crit(struct device *dev, struct device_attribute *devattr, char *buf) | |
892 | static ssize_t show_temp_crit(struct device *dev, | ||
893 | struct device_attribute *devattr, char *buf) | ||
894 | { | 812 | { |
895 | struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); | 813 | struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); |
896 | struct pc87360_data *data = pc87360_update_device(dev); | 814 | struct pc87360_data *data = pc87360_update_device(dev); |
897 | return sprintf(buf, "%d\n", | 815 | return sprintf(buf, "%d\n", TEMP_FROM_REG(data->temp_crit[attr->index])); |
898 | TEMP_FROM_REG(data->temp_crit[attr->index])); | ||
899 | } | 816 | } |
900 | 817 | static ssize_t show_temp_status(struct device *dev, struct device_attribute *devattr, char *buf) | |
901 | static ssize_t show_temp_status(struct device *dev, | ||
902 | struct device_attribute *devattr, char *buf) | ||
903 | { | 818 | { |
904 | struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); | 819 | struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); |
905 | struct pc87360_data *data = pc87360_update_device(dev); | 820 | struct pc87360_data *data = pc87360_update_device(dev); |
906 | return sprintf(buf, "%d\n", data->temp_status[attr->index]); | 821 | return sprintf(buf, "%d\n", data->temp_status[attr->index]); |
907 | } | 822 | } |
908 | 823 | static ssize_t set_temp_min(struct device *dev, struct device_attribute *devattr, const char *buf, | |
909 | static ssize_t set_temp_min(struct device *dev, | 824 | size_t count) |
910 | struct device_attribute *devattr, | ||
911 | const char *buf, size_t count) | ||
912 | { | 825 | { |
913 | struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); | 826 | struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); |
914 | struct pc87360_data *data = dev_get_drvdata(dev); | 827 | struct pc87360_data *data = dev_get_drvdata(dev); |
915 | long val; | 828 | long val = simple_strtol(buf, NULL, 10); |
916 | int err; | ||
917 | |||
918 | err = kstrtol(buf, 10, &val); | ||
919 | if (err) | ||
920 | return err; | ||
921 | 829 | ||
922 | mutex_lock(&data->update_lock); | 830 | mutex_lock(&data->update_lock); |
923 | data->temp_min[attr->index] = TEMP_TO_REG(val); | 831 | data->temp_min[attr->index] = TEMP_TO_REG(val); |
@@ -926,19 +834,12 @@ static ssize_t set_temp_min(struct device *dev, | |||
926 | mutex_unlock(&data->update_lock); | 834 | mutex_unlock(&data->update_lock); |
927 | return count; | 835 | return count; |
928 | } | 836 | } |
929 | 837 | static ssize_t set_temp_max(struct device *dev, struct device_attribute *devattr, const char *buf, | |
930 | static ssize_t set_temp_max(struct device *dev, | 838 | size_t count) |
931 | struct device_attribute *devattr, | ||
932 | const char *buf, size_t count) | ||
933 | { | 839 | { |
934 | struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); | 840 | struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); |
935 | struct pc87360_data *data = dev_get_drvdata(dev); | 841 | struct pc87360_data *data = dev_get_drvdata(dev); |
936 | long val; | 842 | long val = simple_strtol(buf, NULL, 10); |
937 | int err; | ||
938 | |||
939 | err = kstrtol(buf, 10, &val); | ||
940 | if (err) | ||
941 | return err; | ||
942 | 843 | ||
943 | mutex_lock(&data->update_lock); | 844 | mutex_lock(&data->update_lock); |
944 | data->temp_max[attr->index] = TEMP_TO_REG(val); | 845 | data->temp_max[attr->index] = TEMP_TO_REG(val); |
@@ -947,19 +848,12 @@ static ssize_t set_temp_max(struct device *dev, | |||
947 | mutex_unlock(&data->update_lock); | 848 | mutex_unlock(&data->update_lock); |
948 | return count; | 849 | return count; |
949 | } | 850 | } |
950 | 851 | static ssize_t set_temp_crit(struct device *dev, struct device_attribute *devattr, const char *buf, | |
951 | static ssize_t set_temp_crit(struct device *dev, | 852 | size_t count) |
952 | struct device_attribute *devattr, const char *buf, | ||
953 | size_t count) | ||
954 | { | 853 | { |
955 | struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); | 854 | struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); |
956 | struct pc87360_data *data = dev_get_drvdata(dev); | 855 | struct pc87360_data *data = dev_get_drvdata(dev); |
957 | long val; | 856 | long val = simple_strtol(buf, NULL, 10); |
958 | int err; | ||
959 | |||
960 | err = kstrtol(buf, 10, &val); | ||
961 | if (err) | ||
962 | return err; | ||
963 | 857 | ||
964 | mutex_lock(&data->update_lock); | 858 | mutex_lock(&data->update_lock); |
965 | data->temp_crit[attr->index] = TEMP_TO_REG(val); | 859 | data->temp_crit[attr->index] = TEMP_TO_REG(val); |
@@ -1004,20 +898,16 @@ static struct sensor_device_attribute temp_crit[] = { | |||
1004 | show_temp_crit, set_temp_crit, 2), | 898 | show_temp_crit, set_temp_crit, 2), |
1005 | }; | 899 | }; |
1006 | 900 | ||
1007 | static ssize_t show_temp_alarms(struct device *dev, | 901 | static ssize_t show_temp_alarms(struct device *dev, struct device_attribute *attr, char *buf) |
1008 | struct device_attribute *attr, char *buf) | ||
1009 | { | 902 | { |
1010 | struct pc87360_data *data = pc87360_update_device(dev); | 903 | struct pc87360_data *data = pc87360_update_device(dev); |
1011 | return sprintf(buf, "%u\n", data->temp_alarms); | 904 | return sprintf(buf, "%u\n", data->temp_alarms); |
1012 | } | 905 | } |
1013 | |||
1014 | static DEVICE_ATTR(alarms_temp, S_IRUGO, show_temp_alarms, NULL); | 906 | static DEVICE_ATTR(alarms_temp, S_IRUGO, show_temp_alarms, NULL); |
1015 | 907 | ||
1016 | /* | 908 | /* show_temp_min/max_alarm() reads data from the per-channel status |
1017 | * show_temp_min/max_alarm() reads data from the per-channel status | 909 | register (sec 12.3.7), not the temp event status registers (sec |
1018 | * register (sec 12.3.7), not the temp event status registers (sec | 910 | 12.3.2) that show_temp_alarm() reads (via data->temp_alarms) */ |
1019 | * 12.3.2) that show_temp_alarm() reads (via data->temp_alarms) | ||
1020 | */ | ||
1021 | 911 | ||
1022 | static ssize_t show_temp_min_alarm(struct device *dev, | 912 | static ssize_t show_temp_min_alarm(struct device *dev, |
1023 | struct device_attribute *devattr, char *buf) | 913 | struct device_attribute *devattr, char *buf) |
@@ -1027,7 +917,6 @@ static ssize_t show_temp_min_alarm(struct device *dev, | |||
1027 | 917 | ||
1028 | return sprintf(buf, "%u\n", !!(data->temp_status[nr] & CHAN_ALM_MIN)); | 918 | return sprintf(buf, "%u\n", !!(data->temp_status[nr] & CHAN_ALM_MIN)); |
1029 | } | 919 | } |
1030 | |||
1031 | static ssize_t show_temp_max_alarm(struct device *dev, | 920 | static ssize_t show_temp_max_alarm(struct device *dev, |
1032 | struct device_attribute *devattr, char *buf) | 921 | struct device_attribute *devattr, char *buf) |
1033 | { | 922 | { |
@@ -1036,7 +925,6 @@ static ssize_t show_temp_max_alarm(struct device *dev, | |||
1036 | 925 | ||
1037 | return sprintf(buf, "%u\n", !!(data->temp_status[nr] & CHAN_ALM_MAX)); | 926 | return sprintf(buf, "%u\n", !!(data->temp_status[nr] & CHAN_ALM_MAX)); |
1038 | } | 927 | } |
1039 | |||
1040 | static ssize_t show_temp_crit_alarm(struct device *dev, | 928 | static ssize_t show_temp_crit_alarm(struct device *dev, |
1041 | struct device_attribute *devattr, char *buf) | 929 | struct device_attribute *devattr, char *buf) |
1042 | { | 930 | { |
@@ -1051,13 +939,11 @@ static struct sensor_device_attribute temp_min_alarm[] = { | |||
1051 | SENSOR_ATTR(temp2_min_alarm, S_IRUGO, show_temp_min_alarm, NULL, 1), | 939 | SENSOR_ATTR(temp2_min_alarm, S_IRUGO, show_temp_min_alarm, NULL, 1), |
1052 | SENSOR_ATTR(temp3_min_alarm, S_IRUGO, show_temp_min_alarm, NULL, 2), | 940 | SENSOR_ATTR(temp3_min_alarm, S_IRUGO, show_temp_min_alarm, NULL, 2), |
1053 | }; | 941 | }; |
1054 | |||
1055 | static struct sensor_device_attribute temp_max_alarm[] = { | 942 | static struct sensor_device_attribute temp_max_alarm[] = { |
1056 | SENSOR_ATTR(temp1_max_alarm, S_IRUGO, show_temp_max_alarm, NULL, 0), | 943 | SENSOR_ATTR(temp1_max_alarm, S_IRUGO, show_temp_max_alarm, NULL, 0), |
1057 | SENSOR_ATTR(temp2_max_alarm, S_IRUGO, show_temp_max_alarm, NULL, 1), | 944 | SENSOR_ATTR(temp2_max_alarm, S_IRUGO, show_temp_max_alarm, NULL, 1), |
1058 | SENSOR_ATTR(temp3_max_alarm, S_IRUGO, show_temp_max_alarm, NULL, 2), | 945 | SENSOR_ATTR(temp3_max_alarm, S_IRUGO, show_temp_max_alarm, NULL, 2), |
1059 | }; | 946 | }; |
1060 | |||
1061 | static struct sensor_device_attribute temp_crit_alarm[] = { | 947 | static struct sensor_device_attribute temp_crit_alarm[] = { |
1062 | SENSOR_ATTR(temp1_crit_alarm, S_IRUGO, show_temp_crit_alarm, NULL, 0), | 948 | SENSOR_ATTR(temp1_crit_alarm, S_IRUGO, show_temp_crit_alarm, NULL, 0), |
1063 | SENSOR_ATTR(temp2_crit_alarm, S_IRUGO, show_temp_crit_alarm, NULL, 1), | 949 | SENSOR_ATTR(temp2_crit_alarm, S_IRUGO, show_temp_crit_alarm, NULL, 1), |
@@ -1079,29 +965,27 @@ static struct sensor_device_attribute temp_fault[] = { | |||
1079 | SENSOR_ATTR(temp3_fault, S_IRUGO, show_temp_fault, NULL, 2), | 965 | SENSOR_ATTR(temp3_fault, S_IRUGO, show_temp_fault, NULL, 2), |
1080 | }; | 966 | }; |
1081 | 967 | ||
1082 | #define TEMP_UNIT_ATTRS(X) \ | 968 | #define TEMP_UNIT_ATTRS(X) \ |
1083 | { &temp_input[X].dev_attr.attr, \ | 969 | &temp_input[X].dev_attr.attr, \ |
1084 | &temp_status[X].dev_attr.attr, \ | 970 | &temp_status[X].dev_attr.attr, \ |
1085 | &temp_min[X].dev_attr.attr, \ | 971 | &temp_min[X].dev_attr.attr, \ |
1086 | &temp_max[X].dev_attr.attr, \ | 972 | &temp_max[X].dev_attr.attr, \ |
1087 | &temp_crit[X].dev_attr.attr, \ | 973 | &temp_crit[X].dev_attr.attr, \ |
1088 | &temp_min_alarm[X].dev_attr.attr, \ | 974 | &temp_min_alarm[X].dev_attr.attr, \ |
1089 | &temp_max_alarm[X].dev_attr.attr, \ | 975 | &temp_max_alarm[X].dev_attr.attr, \ |
1090 | &temp_crit_alarm[X].dev_attr.attr, \ | 976 | &temp_crit_alarm[X].dev_attr.attr, \ |
1091 | &temp_fault[X].dev_attr.attr, \ | 977 | &temp_fault[X].dev_attr.attr |
1092 | NULL \ | 978 | |
1093 | } | 979 | static struct attribute * pc8736x_temp_attr_array[] = { |
1094 | |||
1095 | static struct attribute *pc8736x_temp_attr[][10] = { | ||
1096 | TEMP_UNIT_ATTRS(0), | 980 | TEMP_UNIT_ATTRS(0), |
1097 | TEMP_UNIT_ATTRS(1), | 981 | TEMP_UNIT_ATTRS(1), |
1098 | TEMP_UNIT_ATTRS(2) | 982 | TEMP_UNIT_ATTRS(2), |
983 | /* include the few miscellaneous atts here */ | ||
984 | &dev_attr_alarms_temp.attr, | ||
985 | NULL | ||
1099 | }; | 986 | }; |
1100 | 987 | static const struct attribute_group pc8736x_temp_group = { | |
1101 | static const struct attribute_group pc8736x_temp_attr_group[] = { | 988 | .attrs = pc8736x_temp_attr_array, |
1102 | { .attrs = pc8736x_temp_attr[0] }, | ||
1103 | { .attrs = pc8736x_temp_attr[1] }, | ||
1104 | { .attrs = pc8736x_temp_attr[2] } | ||
1105 | }; | 989 | }; |
1106 | 990 | ||
1107 | static ssize_t show_name(struct device *dev, | 991 | static ssize_t show_name(struct device *dev, |
@@ -1110,15 +994,13 @@ static ssize_t show_name(struct device *dev, | |||
1110 | struct pc87360_data *data = dev_get_drvdata(dev); | 994 | struct pc87360_data *data = dev_get_drvdata(dev); |
1111 | return sprintf(buf, "%s\n", data->name); | 995 | return sprintf(buf, "%s\n", data->name); |
1112 | } | 996 | } |
1113 | |||
1114 | static DEVICE_ATTR(name, S_IRUGO, show_name, NULL); | 997 | static DEVICE_ATTR(name, S_IRUGO, show_name, NULL); |
1115 | 998 | ||
1116 | /* | 999 | /* |
1117 | * Device detection, registration and update | 1000 | * Device detection, registration and update |
1118 | */ | 1001 | */ |
1119 | 1002 | ||
1120 | static int __init pc87360_find(int sioaddr, u8 *devid, | 1003 | static int __init pc87360_find(int sioaddr, u8 *devid, unsigned short *addresses) |
1121 | unsigned short *addresses) | ||
1122 | { | 1004 | { |
1123 | u16 val; | 1005 | u16 val; |
1124 | int i; | 1006 | int i; |
@@ -1165,7 +1047,7 @@ static int __init pc87360_find(int sioaddr, u8 *devid, | |||
1165 | 1047 | ||
1166 | addresses[i] = val; | 1048 | addresses[i] = val; |
1167 | 1049 | ||
1168 | if (i == 0) { /* Fans */ | 1050 | if (i==0) { /* Fans */ |
1169 | confreg[0] = superio_inb(sioaddr, 0xF0); | 1051 | confreg[0] = superio_inb(sioaddr, 0xF0); |
1170 | confreg[1] = superio_inb(sioaddr, 0xF1); | 1052 | confreg[1] = superio_inb(sioaddr, 0xF1); |
1171 | 1053 | ||
@@ -1178,14 +1060,12 @@ static int __init pc87360_find(int sioaddr, u8 *devid, | |||
1178 | pr_debug("Fan %d: mon=%d ctrl=%d inv=%d\n", 3, | 1060 | pr_debug("Fan %d: mon=%d ctrl=%d inv=%d\n", 3, |
1179 | confreg[1] & 1, (confreg[1] >> 1) & 1, | 1061 | confreg[1] & 1, (confreg[1] >> 1) & 1, |
1180 | (confreg[1] >> 2) & 1); | 1062 | (confreg[1] >> 2) & 1); |
1181 | } else if (i == 1) { /* Voltages */ | 1063 | } else if (i==1) { /* Voltages */ |
1182 | /* Are we using thermistors? */ | 1064 | /* Are we using thermistors? */ |
1183 | if (*devid == 0xE9) { /* PC87366 */ | 1065 | if (*devid == 0xE9) { /* PC87366 */ |
1184 | /* | 1066 | /* These registers are not logical-device |
1185 | * These registers are not logical-device | 1067 | specific, just that we won't need them if |
1186 | * specific, just that we won't need them if | 1068 | we don't use the VLM device */ |
1187 | * we don't use the VLM device | ||
1188 | */ | ||
1189 | confreg[2] = superio_inb(sioaddr, 0x2B); | 1069 | confreg[2] = superio_inb(sioaddr, 0x2B); |
1190 | confreg[3] = superio_inb(sioaddr, 0x25); | 1070 | confreg[3] = superio_inb(sioaddr, 0x25); |
1191 | 1071 | ||
@@ -1205,23 +1085,7 @@ static int __init pc87360_find(int sioaddr, u8 *devid, | |||
1205 | return 0; | 1085 | return 0; |
1206 | } | 1086 | } |
1207 | 1087 | ||
1208 | static void pc87360_remove_files(struct device *dev) | 1088 | static int __devinit pc87360_probe(struct platform_device *pdev) |
1209 | { | ||
1210 | int i; | ||
1211 | |||
1212 | device_remove_file(dev, &dev_attr_name); | ||
1213 | device_remove_file(dev, &dev_attr_alarms_temp); | ||
1214 | for (i = 0; i < ARRAY_SIZE(pc8736x_temp_attr_group); i++) | ||
1215 | sysfs_remove_group(&dev->kobj, &pc8736x_temp_attr_group[i]); | ||
1216 | for (i = 0; i < ARRAY_SIZE(pc8736x_fan_attr_group); i++) { | ||
1217 | sysfs_remove_group(&pdev->dev.kobj, &pc8736x_fan_attr_group[i]); | ||
1218 | device_remove_file(dev, &pwm[i].dev_attr); | ||
1219 | } | ||
1220 | sysfs_remove_group(&dev->kobj, &pc8736x_therm_group); | ||
1221 | sysfs_remove_group(&dev->kobj, &pc8736x_vin_group); | ||
1222 | } | ||
1223 | |||
1224 | static int pc87360_probe(struct platform_device *pdev) | ||
1225 | { | 1089 | { |
1226 | int i; | 1090 | int i; |
1227 | struct pc87360_data *data; | 1091 | struct pc87360_data *data; |
@@ -1230,8 +1094,7 @@ static int pc87360_probe(struct platform_device *pdev) | |||
1230 | int use_thermistors = 0; | 1094 | int use_thermistors = 0; |
1231 | struct device *dev = &pdev->dev; | 1095 | struct device *dev = &pdev->dev; |
1232 | 1096 | ||
1233 | data = devm_kzalloc(dev, sizeof(struct pc87360_data), GFP_KERNEL); | 1097 | if (!(data = kzalloc(sizeof(struct pc87360_data), GFP_KERNEL))) |
1234 | if (!data) | ||
1235 | return -ENOMEM; | 1098 | return -ENOMEM; |
1236 | 1099 | ||
1237 | data->fannr = 2; | 1100 | data->fannr = 2; |
@@ -1267,14 +1130,16 @@ static int pc87360_probe(struct platform_device *pdev) | |||
1267 | platform_set_drvdata(pdev, data); | 1130 | platform_set_drvdata(pdev, data); |
1268 | 1131 | ||
1269 | for (i = 0; i < LDNI_MAX; i++) { | 1132 | for (i = 0; i < LDNI_MAX; i++) { |
1270 | data->address[i] = extra_isa[i]; | 1133 | if (((data->address[i] = extra_isa[i])) |
1271 | if (data->address[i] | 1134 | && !request_region(extra_isa[i], PC87360_EXTENT, |
1272 | && !devm_request_region(dev, extra_isa[i], PC87360_EXTENT, | 1135 | pc87360_driver.driver.name)) { |
1273 | pc87360_driver.driver.name)) { | ||
1274 | dev_err(dev, "Region 0x%x-0x%x already " | 1136 | dev_err(dev, "Region 0x%x-0x%x already " |
1275 | "in use!\n", extra_isa[i], | 1137 | "in use!\n", extra_isa[i], |
1276 | extra_isa[i]+PC87360_EXTENT-1); | 1138 | extra_isa[i]+PC87360_EXTENT-1); |
1277 | return -EBUSY; | 1139 | for (i--; i >= 0; i--) |
1140 | release_region(extra_isa[i], PC87360_EXTENT); | ||
1141 | err = -EBUSY; | ||
1142 | goto ERROR1; | ||
1278 | } | 1143 | } |
1279 | } | 1144 | } |
1280 | 1145 | ||
@@ -1282,11 +1147,9 @@ static int pc87360_probe(struct platform_device *pdev) | |||
1282 | if (data->fannr) | 1147 | if (data->fannr) |
1283 | data->fan_conf = confreg[0] | (confreg[1] << 8); | 1148 | data->fan_conf = confreg[0] | (confreg[1] << 8); |
1284 | 1149 | ||
1285 | /* | 1150 | /* Use the correct reference voltage |
1286 | * Use the correct reference voltage | 1151 | Unless both the VLM and the TMS logical devices agree to |
1287 | * Unless both the VLM and the TMS logical devices agree to | 1152 | use an external Vref, the internal one is used. */ |
1288 | * use an external Vref, the internal one is used. | ||
1289 | */ | ||
1290 | if (data->innr) { | 1153 | if (data->innr) { |
1291 | i = pc87360_read_value(data, LD_IN, NO_BANK, | 1154 | i = pc87360_read_value(data, LD_IN, NO_BANK, |
1292 | PC87365_REG_IN_CONFIG); | 1155 | PC87365_REG_IN_CONFIG); |
@@ -1319,76 +1182,113 @@ static int pc87360_probe(struct platform_device *pdev) | |||
1319 | 1182 | ||
1320 | /* Register all-or-nothing sysfs groups */ | 1183 | /* Register all-or-nothing sysfs groups */ |
1321 | 1184 | ||
1322 | if (data->innr) { | 1185 | if (data->innr && |
1323 | err = sysfs_create_group(&dev->kobj, &pc8736x_vin_group); | 1186 | (err = sysfs_create_group(&dev->kobj, |
1324 | if (err) | 1187 | &pc8736x_vin_group))) |
1325 | goto error; | 1188 | goto ERROR3; |
1326 | } | ||
1327 | 1189 | ||
1328 | if (data->innr == 14) { | 1190 | if (data->innr == 14 && |
1329 | err = sysfs_create_group(&dev->kobj, &pc8736x_therm_group); | 1191 | (err = sysfs_create_group(&dev->kobj, |
1330 | if (err) | 1192 | &pc8736x_therm_group))) |
1331 | goto error; | 1193 | goto ERROR3; |
1332 | } | ||
1333 | 1194 | ||
1334 | /* create device attr-files for varying sysfs groups */ | 1195 | /* create device attr-files for varying sysfs groups */ |
1335 | 1196 | ||
1336 | if (data->tempnr) { | 1197 | if (data->tempnr) { |
1337 | for (i = 0; i < data->tempnr; i++) { | 1198 | for (i = 0; i < data->tempnr; i++) { |
1338 | err = sysfs_create_group(&dev->kobj, | 1199 | if ((err = device_create_file(dev, |
1339 | &pc8736x_temp_attr_group[i]); | 1200 | &temp_input[i].dev_attr)) |
1340 | if (err) | 1201 | || (err = device_create_file(dev, |
1341 | goto error; | 1202 | &temp_min[i].dev_attr)) |
1203 | || (err = device_create_file(dev, | ||
1204 | &temp_max[i].dev_attr)) | ||
1205 | || (err = device_create_file(dev, | ||
1206 | &temp_crit[i].dev_attr)) | ||
1207 | || (err = device_create_file(dev, | ||
1208 | &temp_status[i].dev_attr)) | ||
1209 | || (err = device_create_file(dev, | ||
1210 | &temp_min_alarm[i].dev_attr)) | ||
1211 | || (err = device_create_file(dev, | ||
1212 | &temp_max_alarm[i].dev_attr)) | ||
1213 | || (err = device_create_file(dev, | ||
1214 | &temp_crit_alarm[i].dev_attr)) | ||
1215 | || (err = device_create_file(dev, | ||
1216 | &temp_fault[i].dev_attr))) | ||
1217 | goto ERROR3; | ||
1342 | } | 1218 | } |
1343 | err = device_create_file(dev, &dev_attr_alarms_temp); | 1219 | if ((err = device_create_file(dev, &dev_attr_alarms_temp))) |
1344 | if (err) | 1220 | goto ERROR3; |
1345 | goto error; | ||
1346 | } | 1221 | } |
1347 | 1222 | ||
1348 | for (i = 0; i < data->fannr; i++) { | 1223 | for (i = 0; i < data->fannr; i++) { |
1349 | if (FAN_CONFIG_MONITOR(data->fan_conf, i)) { | 1224 | if (FAN_CONFIG_MONITOR(data->fan_conf, i) |
1350 | err = sysfs_create_group(&dev->kobj, | 1225 | && ((err = device_create_file(dev, |
1351 | &pc8736x_fan_attr_group[i]); | 1226 | &fan_input[i].dev_attr)) |
1352 | if (err) | 1227 | || (err = device_create_file(dev, |
1353 | goto error; | 1228 | &fan_min[i].dev_attr)) |
1354 | } | 1229 | || (err = device_create_file(dev, |
1355 | if (FAN_CONFIG_CONTROL(data->fan_conf, i)) { | 1230 | &fan_div[i].dev_attr)) |
1356 | err = device_create_file(dev, &pwm[i].dev_attr); | 1231 | || (err = device_create_file(dev, |
1357 | if (err) | 1232 | &fan_status[i].dev_attr)))) |
1358 | goto error; | 1233 | goto ERROR3; |
1359 | } | 1234 | |
1235 | if (FAN_CONFIG_CONTROL(data->fan_conf, i) | ||
1236 | && (err = device_create_file(dev, &pwm[i].dev_attr))) | ||
1237 | goto ERROR3; | ||
1360 | } | 1238 | } |
1361 | 1239 | ||
1362 | err = device_create_file(dev, &dev_attr_name); | 1240 | if ((err = device_create_file(dev, &dev_attr_name))) |
1363 | if (err) | 1241 | goto ERROR3; |
1364 | goto error; | ||
1365 | 1242 | ||
1366 | data->hwmon_dev = hwmon_device_register(dev); | 1243 | data->hwmon_dev = hwmon_device_register(dev); |
1367 | if (IS_ERR(data->hwmon_dev)) { | 1244 | if (IS_ERR(data->hwmon_dev)) { |
1368 | err = PTR_ERR(data->hwmon_dev); | 1245 | err = PTR_ERR(data->hwmon_dev); |
1369 | goto error; | 1246 | goto ERROR3; |
1370 | } | 1247 | } |
1371 | return 0; | 1248 | return 0; |
1372 | 1249 | ||
1373 | error: | 1250 | ERROR3: |
1374 | pc87360_remove_files(dev); | 1251 | device_remove_file(dev, &dev_attr_name); |
1252 | /* can still remove groups whose members were added individually */ | ||
1253 | sysfs_remove_group(&dev->kobj, &pc8736x_temp_group); | ||
1254 | sysfs_remove_group(&dev->kobj, &pc8736x_fan_group); | ||
1255 | sysfs_remove_group(&dev->kobj, &pc8736x_therm_group); | ||
1256 | sysfs_remove_group(&dev->kobj, &pc8736x_vin_group); | ||
1257 | for (i = 0; i < 3; i++) { | ||
1258 | if (data->address[i]) { | ||
1259 | release_region(data->address[i], PC87360_EXTENT); | ||
1260 | } | ||
1261 | } | ||
1262 | ERROR1: | ||
1263 | kfree(data); | ||
1375 | return err; | 1264 | return err; |
1376 | } | 1265 | } |
1377 | 1266 | ||
1378 | static int pc87360_remove(struct platform_device *pdev) | 1267 | static int __devexit pc87360_remove(struct platform_device *pdev) |
1379 | { | 1268 | { |
1380 | struct pc87360_data *data = platform_get_drvdata(pdev); | 1269 | struct pc87360_data *data = platform_get_drvdata(pdev); |
1270 | int i; | ||
1381 | 1271 | ||
1382 | hwmon_device_unregister(data->hwmon_dev); | 1272 | hwmon_device_unregister(data->hwmon_dev); |
1383 | pc87360_remove_files(&pdev->dev); | 1273 | |
1274 | device_remove_file(&pdev->dev, &dev_attr_name); | ||
1275 | sysfs_remove_group(&pdev->dev.kobj, &pc8736x_temp_group); | ||
1276 | sysfs_remove_group(&pdev->dev.kobj, &pc8736x_fan_group); | ||
1277 | sysfs_remove_group(&pdev->dev.kobj, &pc8736x_therm_group); | ||
1278 | sysfs_remove_group(&pdev->dev.kobj, &pc8736x_vin_group); | ||
1279 | |||
1280 | for (i = 0; i < 3; i++) { | ||
1281 | if (data->address[i]) { | ||
1282 | release_region(data->address[i], PC87360_EXTENT); | ||
1283 | } | ||
1284 | } | ||
1285 | kfree(data); | ||
1384 | 1286 | ||
1385 | return 0; | 1287 | return 0; |
1386 | } | 1288 | } |
1387 | 1289 | ||
1388 | /* | 1290 | /* ldi is the logical device index |
1389 | * ldi is the logical device index | 1291 | bank is for voltages and temperatures only */ |
1390 | * bank is for voltages and temperatures only | ||
1391 | */ | ||
1392 | static int pc87360_read_value(struct pc87360_data *data, u8 ldi, u8 bank, | 1292 | static int pc87360_read_value(struct pc87360_data *data, u8 ldi, u8 bank, |
1393 | u8 reg) | 1293 | u8 reg) |
1394 | { | 1294 | { |
@@ -1459,10 +1359,8 @@ static void pc87360_init_device(struct platform_device *pdev, | |||
1459 | } | 1359 | } |
1460 | } | 1360 | } |
1461 | 1361 | ||
1462 | /* | 1362 | /* We can't blindly trust the Super-I/O space configuration bit, |
1463 | * We can't blindly trust the Super-I/O space configuration bit, | 1363 | most BIOS won't set it properly */ |
1464 | * most BIOS won't set it properly | ||
1465 | */ | ||
1466 | dev_dbg(&pdev->dev, "bios thermistors:%d\n", use_thermistors); | 1364 | dev_dbg(&pdev->dev, "bios thermistors:%d\n", use_thermistors); |
1467 | for (i = 11; i < data->innr; i++) { | 1365 | for (i = 11; i < data->innr; i++) { |
1468 | reg = pc87360_read_value(data, LD_IN, i, | 1366 | reg = pc87360_read_value(data, LD_IN, i, |
@@ -1477,12 +1375,12 @@ static void pc87360_init_device(struct platform_device *pdev, | |||
1477 | for (; i < data->tempnr; i++) { | 1375 | for (; i < data->tempnr; i++) { |
1478 | reg = pc87360_read_value(data, LD_TEMP, i, | 1376 | reg = pc87360_read_value(data, LD_TEMP, i, |
1479 | PC87365_REG_TEMP_STATUS); | 1377 | PC87365_REG_TEMP_STATUS); |
1480 | dev_dbg(&pdev->dev, "bios temp%d_status:0x%02x\n", i + 1, reg); | 1378 | dev_dbg(&pdev->dev, "bios temp%d_status:0x%02x\n", i+1, reg); |
1481 | if (init >= init_temp[i]) { | 1379 | if (init >= init_temp[i]) { |
1482 | /* Forcibly enable temperature channel */ | 1380 | /* Forcibly enable temperature channel */ |
1483 | if (!(reg & CHAN_ENA)) { | 1381 | if (!(reg & CHAN_ENA)) { |
1484 | dev_dbg(&pdev->dev, | 1382 | dev_dbg(&pdev->dev, "Forcibly " |
1485 | "Forcibly enabling temp%d\n", i + 1); | 1383 | "enabling temp%d\n", i+1); |
1486 | pc87360_write_value(data, LD_TEMP, i, | 1384 | pc87360_write_value(data, LD_TEMP, i, |
1487 | PC87365_REG_TEMP_STATUS, | 1385 | PC87365_REG_TEMP_STATUS, |
1488 | 0xCF); | 1386 | 0xCF); |
@@ -1493,16 +1391,14 @@ static void pc87360_init_device(struct platform_device *pdev, | |||
1493 | if (use_thermistors) { | 1391 | if (use_thermistors) { |
1494 | for (i = 11; i < data->innr; i++) { | 1392 | for (i = 11; i < data->innr; i++) { |
1495 | if (init >= init_in[i]) { | 1393 | if (init >= init_in[i]) { |
1496 | /* | 1394 | /* The pin may already be used by thermal |
1497 | * The pin may already be used by thermal | 1395 | diodes */ |
1498 | * diodes | ||
1499 | */ | ||
1500 | reg = pc87360_read_value(data, LD_TEMP, | 1396 | reg = pc87360_read_value(data, LD_TEMP, |
1501 | (i - 11) / 2, PC87365_REG_TEMP_STATUS); | 1397 | (i-11)/2, PC87365_REG_TEMP_STATUS); |
1502 | if (reg & CHAN_ENA) { | 1398 | if (reg & CHAN_ENA) { |
1503 | dev_dbg(&pdev->dev, | 1399 | dev_dbg(&pdev->dev, "Skipping " |
1504 | "Skipping temp%d, pin already in use by temp%d\n", | 1400 | "temp%d, pin already in use " |
1505 | i - 7, (i - 11) / 2); | 1401 | "by temp%d\n", i-7, (i-11)/2); |
1506 | continue; | 1402 | continue; |
1507 | } | 1403 | } |
1508 | 1404 | ||
@@ -1510,9 +1406,8 @@ static void pc87360_init_device(struct platform_device *pdev, | |||
1510 | reg = pc87360_read_value(data, LD_IN, i, | 1406 | reg = pc87360_read_value(data, LD_IN, i, |
1511 | PC87365_REG_IN_STATUS); | 1407 | PC87365_REG_IN_STATUS); |
1512 | if (!(reg & CHAN_ENA)) { | 1408 | if (!(reg & CHAN_ENA)) { |
1513 | dev_dbg(&pdev->dev, | 1409 | dev_dbg(&pdev->dev, "Forcibly " |
1514 | "Forcibly enabling temp%d\n", | 1410 | "enabling temp%d\n", i-7); |
1515 | i - 7); | ||
1516 | pc87360_write_value(data, LD_IN, i, | 1411 | pc87360_write_value(data, LD_IN, i, |
1517 | PC87365_REG_TEMP_STATUS, | 1412 | PC87365_REG_TEMP_STATUS, |
1518 | (reg & 0x60) | 0x8F); | 1413 | (reg & 0x60) | 0x8F); |
@@ -1526,8 +1421,8 @@ static void pc87360_init_device(struct platform_device *pdev, | |||
1526 | PC87365_REG_IN_CONFIG); | 1421 | PC87365_REG_IN_CONFIG); |
1527 | dev_dbg(&pdev->dev, "bios vin-cfg:0x%02x\n", reg); | 1422 | dev_dbg(&pdev->dev, "bios vin-cfg:0x%02x\n", reg); |
1528 | if (reg & CHAN_ENA) { | 1423 | if (reg & CHAN_ENA) { |
1529 | dev_dbg(&pdev->dev, | 1424 | dev_dbg(&pdev->dev, "Forcibly " |
1530 | "Forcibly enabling monitoring (VLM)\n"); | 1425 | "enabling monitoring (VLM)\n"); |
1531 | pc87360_write_value(data, LD_IN, NO_BANK, | 1426 | pc87360_write_value(data, LD_IN, NO_BANK, |
1532 | PC87365_REG_IN_CONFIG, | 1427 | PC87365_REG_IN_CONFIG, |
1533 | reg & 0xFE); | 1428 | reg & 0xFE); |
@@ -1539,8 +1434,8 @@ static void pc87360_init_device(struct platform_device *pdev, | |||
1539 | PC87365_REG_TEMP_CONFIG); | 1434 | PC87365_REG_TEMP_CONFIG); |
1540 | dev_dbg(&pdev->dev, "bios temp-cfg:0x%02x\n", reg); | 1435 | dev_dbg(&pdev->dev, "bios temp-cfg:0x%02x\n", reg); |
1541 | if (reg & CHAN_ENA) { | 1436 | if (reg & CHAN_ENA) { |
1542 | dev_dbg(&pdev->dev, | 1437 | dev_dbg(&pdev->dev, "Forcibly enabling " |
1543 | "Forcibly enabling monitoring (TMS)\n"); | 1438 | "monitoring (TMS)\n"); |
1544 | pc87360_write_value(data, LD_TEMP, NO_BANK, | 1439 | pc87360_write_value(data, LD_TEMP, NO_BANK, |
1545 | PC87365_REG_TEMP_CONFIG, | 1440 | PC87365_REG_TEMP_CONFIG, |
1546 | reg & 0xFE); | 1441 | reg & 0xFE); |
@@ -1549,12 +1444,10 @@ static void pc87360_init_device(struct platform_device *pdev, | |||
1549 | if (init >= 2) { | 1444 | if (init >= 2) { |
1550 | /* Chip config as documented by National Semi. */ | 1445 | /* Chip config as documented by National Semi. */ |
1551 | pc87360_write_value(data, LD_TEMP, 0xF, 0xA, 0x08); | 1446 | pc87360_write_value(data, LD_TEMP, 0xF, 0xA, 0x08); |
1552 | /* | 1447 | /* We voluntarily omit the bank here, in case the |
1553 | * We voluntarily omit the bank here, in case the | 1448 | sequence itself matters. It shouldn't be a problem, |
1554 | * sequence itself matters. It shouldn't be a problem, | 1449 | since nobody else is supposed to access the |
1555 | * since nobody else is supposed to access the | 1450 | device at that point. */ |
1556 | * device at that point. | ||
1557 | */ | ||
1558 | pc87360_write_value(data, LD_TEMP, NO_BANK, 0xB, 0x04); | 1451 | pc87360_write_value(data, LD_TEMP, NO_BANK, 0xB, 0x04); |
1559 | pc87360_write_value(data, LD_TEMP, NO_BANK, 0xC, 0x35); | 1452 | pc87360_write_value(data, LD_TEMP, NO_BANK, 0xC, 0x35); |
1560 | pc87360_write_value(data, LD_TEMP, NO_BANK, 0xD, 0x05); | 1453 | pc87360_write_value(data, LD_TEMP, NO_BANK, 0xD, 0x05); |
@@ -1577,7 +1470,7 @@ static void pc87360_autodiv(struct device *dev, int nr) | |||
1577 | data->fan[nr] >>= 1; | 1470 | data->fan[nr] >>= 1; |
1578 | dev_dbg(dev, "Increasing " | 1471 | dev_dbg(dev, "Increasing " |
1579 | "clock divider to %d for fan %d\n", | 1472 | "clock divider to %d for fan %d\n", |
1580 | FAN_DIV_FROM_REG(data->fan_status[nr]), nr + 1); | 1473 | FAN_DIV_FROM_REG(data->fan_status[nr]), nr+1); |
1581 | } | 1474 | } |
1582 | } else { | 1475 | } else { |
1583 | /* Decrease clock divider if possible */ | 1476 | /* Decrease clock divider if possible */ |
@@ -1590,7 +1483,7 @@ static void pc87360_autodiv(struct device *dev, int nr) | |||
1590 | dev_dbg(dev, "Decreasing " | 1483 | dev_dbg(dev, "Decreasing " |
1591 | "clock divider to %d for fan %d\n", | 1484 | "clock divider to %d for fan %d\n", |
1592 | FAN_DIV_FROM_REG(data->fan_status[nr]), | 1485 | FAN_DIV_FROM_REG(data->fan_status[nr]), |
1593 | nr + 1); | 1486 | nr+1); |
1594 | } | 1487 | } |
1595 | } | 1488 | } |
1596 | 1489 | ||