diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2012-03-21 13:37:25 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2012-03-21 13:37:25 -0400 |
commit | 31f6765266417c0d99f0e922fe82848a7c9c2ae9 (patch) | |
tree | 2d5914dac0a918baad37decd3845b8c206051420 /drivers/hwmon/smsc47m1.c | |
parent | d15d76448bb58c7832e954b6a8f1e301720b7866 (diff) | |
parent | 312869ec935ab3bb67b7ba641a7d11230555aff5 (diff) |
Merge tag 'hwmon-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/groeck/linux-staging
Pull hwmon changes for v3.4 from Guenter Roeck:
"Mostly cleanup. No new drivers this time around, but support for
several chips added to existing drivers: TPS40400, TPS40422, MTD040,
MAX34446, ZL9101M, ZL9117M, and LM96080. Also, added watchdog support
for SCH56xx, and additional attributes for a couple of drivers."
* tag 'hwmon-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/groeck/linux-staging: (137 commits)
hwmon: (sch56xx) Add support for the integrated watchdog (v2)
hwmon: (w83627ehf) Add support for temperature offset registers
hwmon: (jc42) Remove unnecessary device IDs
hwmon: (zl6100) Add support for ZL9101M and ZL9117M
hwmon: (adm1275) Add support for ADM1075
hwmon: (max34440) Add support for MAX34446
hwmon: (pmbus) Add more virtual registers
hwmon: (pmbus) Add support for Lineage Power MDT040
hwmon: (pmbus) Add support for TI TPS40400 and TPS40422
hwmon: (max34440) Add support for 'lowest' output voltage attribute
hwmon: (jc42) Convert to use devm_kzalloc
hwmon: (max16065) Convert to use devm_kzalloc
hwmon: (smm665) Convert to use devm_kzalloc
hwmon: (ltc4261) Convert to use devm_kzalloc
hwmon: (pmbus) Simplify remove functions
hwmon: (pmbus) Convert pmbus drivers to use devm_kzalloc
hwmon: (lineage-pem) Convert to use devm_kzalloc
hwmon: (hwmon-vid) Fix checkpatch issues
hwmon: (hwmon-vid) Add new entries to VRM model table
hwmon: (lm80) Add detection of NatSemi/TI LM96080
...
Diffstat (limited to 'drivers/hwmon/smsc47m1.c')
-rw-r--r-- | drivers/hwmon/smsc47m1.c | 291 |
1 files changed, 184 insertions, 107 deletions
diff --git a/drivers/hwmon/smsc47m1.c b/drivers/hwmon/smsc47m1.c index f44a89aac381..c590c1469793 100644 --- a/drivers/hwmon/smsc47m1.c +++ b/drivers/hwmon/smsc47m1.c | |||
@@ -1,30 +1,30 @@ | |||
1 | /* | 1 | /* |
2 | smsc47m1.c - Part of lm_sensors, Linux kernel modules | 2 | * smsc47m1.c - Part of lm_sensors, Linux kernel modules |
3 | for hardware monitoring | 3 | * for hardware monitoring |
4 | 4 | * | |
5 | Supports the SMSC LPC47B27x, LPC47M10x, LPC47M112, LPC47M13x, | 5 | * Supports the SMSC LPC47B27x, LPC47M10x, LPC47M112, LPC47M13x, |
6 | LPC47M14x, LPC47M15x, LPC47M192, LPC47M292 and LPC47M997 | 6 | * LPC47M14x, LPC47M15x, LPC47M192, LPC47M292 and LPC47M997 |
7 | Super-I/O chips. | 7 | * Super-I/O chips. |
8 | 8 | * | |
9 | Copyright (C) 2002 Mark D. Studebaker <mdsxyz123@yahoo.com> | 9 | * Copyright (C) 2002 Mark D. Studebaker <mdsxyz123@yahoo.com> |
10 | Copyright (C) 2004-2007 Jean Delvare <khali@linux-fr.org> | 10 | * Copyright (C) 2004-2007 Jean Delvare <khali@linux-fr.org> |
11 | Ported to Linux 2.6 by Gabriele Gorla <gorlik@yahoo.com> | 11 | * Ported to Linux 2.6 by Gabriele Gorla <gorlik@yahoo.com> |
12 | and Jean Delvare | 12 | * and Jean Delvare |
13 | 13 | * | |
14 | This program is free software; you can redistribute it and/or modify | 14 | * This program is free software; you can redistribute it and/or modify |
15 | it under the terms of the GNU General Public License as published by | 15 | * it under the terms of the GNU General Public License as published by |
16 | the Free Software Foundation; either version 2 of the License, or | 16 | * the Free Software Foundation; either version 2 of the License, or |
17 | (at your option) any later version. | 17 | * (at your option) any later version. |
18 | 18 | * | |
19 | This program is distributed in the hope that it will be useful, | 19 | * This program is distributed in the hope that it will be useful, |
20 | but WITHOUT ANY WARRANTY; without even the implied warranty of | 20 | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
21 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | 21 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
22 | GNU General Public License for more details. | 22 | * GNU General Public License for more details. |
23 | 23 | * | |
24 | You should have received a copy of the GNU General Public License | 24 | * You should have received a copy of the GNU General Public License |
25 | along with this program; if not, write to the Free Software | 25 | * along with this program; if not, write to the Free Software |
26 | Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | 26 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. |
27 | */ | 27 | */ |
28 | 28 | ||
29 | #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt | 29 | #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt |
30 | 30 | ||
@@ -53,8 +53,8 @@ enum chips { smsc47m1, smsc47m2 }; | |||
53 | 53 | ||
54 | /* Super-I/0 registers and commands */ | 54 | /* Super-I/0 registers and commands */ |
55 | 55 | ||
56 | #define REG 0x2e /* The register to read/write */ | 56 | #define REG 0x2e /* The register to read/write */ |
57 | #define VAL 0x2f /* The value to read/write */ | 57 | #define VAL 0x2f /* The value to read/write */ |
58 | 58 | ||
59 | static inline void | 59 | static inline void |
60 | superio_outb(int reg, int val) | 60 | superio_outb(int reg, int val) |
@@ -111,10 +111,11 @@ static const u8 SMSC47M1_REG_PWM[3] = { 0x56, 0x57, 0x69 }; | |||
111 | #define SMSC47M2_REG_PPIN3 0x2c | 111 | #define SMSC47M2_REG_PPIN3 0x2c |
112 | #define SMSC47M2_REG_FANDIV3 0x6a | 112 | #define SMSC47M2_REG_FANDIV3 0x6a |
113 | 113 | ||
114 | #define MIN_FROM_REG(reg,div) ((reg)>=192 ? 0 : \ | 114 | #define MIN_FROM_REG(reg, div) ((reg) >= 192 ? 0 : \ |
115 | 983040/((192-(reg))*(div))) | 115 | 983040 / ((192 - (reg)) * (div))) |
116 | #define FAN_FROM_REG(reg,div,preload) ((reg)<=(preload) || (reg)==255 ? 0 : \ | 116 | #define FAN_FROM_REG(reg, div, preload) ((reg) <= (preload) || (reg) == 255 ? \ |
117 | 983040/(((reg)-(preload))*(div))) | 117 | 0 : \ |
118 | 983040 / (((reg) - (preload)) * (div))) | ||
118 | #define DIV_FROM_REG(reg) (1 << (reg)) | 119 | #define DIV_FROM_REG(reg) (1 << (reg)) |
119 | #define PWM_FROM_REG(reg) (((reg) & 0x7E) << 1) | 120 | #define PWM_FROM_REG(reg) (((reg) & 0x7E) << 1) |
120 | #define PWM_EN_FROM_REG(reg) ((~(reg)) & 0x01) | 121 | #define PWM_EN_FROM_REG(reg) ((~(reg)) & 0x01) |
@@ -171,10 +172,12 @@ static ssize_t get_fan(struct device *dev, struct device_attribute | |||
171 | struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); | 172 | struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); |
172 | struct smsc47m1_data *data = smsc47m1_update_device(dev, 0); | 173 | struct smsc47m1_data *data = smsc47m1_update_device(dev, 0); |
173 | int nr = attr->index; | 174 | int nr = attr->index; |
174 | /* This chip (stupidly) stops monitoring fan speed if PWM is | 175 | /* |
175 | enabled and duty cycle is 0%. This is fine if the monitoring | 176 | * This chip (stupidly) stops monitoring fan speed if PWM is |
176 | and control concern the same fan, but troublesome if they are | 177 | * enabled and duty cycle is 0%. This is fine if the monitoring |
177 | not (which could as well happen). */ | 178 | * and control concern the same fan, but troublesome if they are |
179 | * not (which could as well happen). | ||
180 | */ | ||
178 | int rpm = (data->pwm[nr] & 0x7F) == 0x00 ? 0 : | 181 | int rpm = (data->pwm[nr] & 0x7F) == 0x00 ? 0 : |
179 | FAN_FROM_REG(data->fan[nr], | 182 | FAN_FROM_REG(data->fan[nr], |
180 | DIV_FROM_REG(data->fan_div[nr]), | 183 | DIV_FROM_REG(data->fan_div[nr]), |
@@ -238,7 +241,13 @@ static ssize_t set_fan_min(struct device *dev, struct device_attribute | |||
238 | struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); | 241 | struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); |
239 | struct smsc47m1_data *data = dev_get_drvdata(dev); | 242 | struct smsc47m1_data *data = dev_get_drvdata(dev); |
240 | int nr = attr->index; | 243 | int nr = attr->index; |
241 | long rpmdiv, val = simple_strtol(buf, NULL, 10); | 244 | long rpmdiv; |
245 | long val; | ||
246 | int err; | ||
247 | |||
248 | err = kstrtol(buf, 10, &val); | ||
249 | if (err) | ||
250 | return err; | ||
242 | 251 | ||
243 | mutex_lock(&data->update_lock); | 252 | mutex_lock(&data->update_lock); |
244 | rpmdiv = val * DIV_FROM_REG(data->fan_div[nr]); | 253 | rpmdiv = val * DIV_FROM_REG(data->fan_div[nr]); |
@@ -256,28 +265,44 @@ static ssize_t set_fan_min(struct device *dev, struct device_attribute | |||
256 | return count; | 265 | return count; |
257 | } | 266 | } |
258 | 267 | ||
259 | /* Note: we save and restore the fan minimum here, because its value is | 268 | /* |
260 | determined in part by the fan clock divider. This follows the principle | 269 | * Note: we save and restore the fan minimum here, because its value is |
261 | of least surprise; the user doesn't expect the fan minimum to change just | 270 | * determined in part by the fan clock divider. This follows the principle |
262 | because the divider changed. */ | 271 | * of least surprise; the user doesn't expect the fan minimum to change just |
272 | * because the divider changed. | ||
273 | */ | ||
263 | static ssize_t set_fan_div(struct device *dev, struct device_attribute | 274 | static ssize_t set_fan_div(struct device *dev, struct device_attribute |
264 | *devattr, const char *buf, size_t count) | 275 | *devattr, const char *buf, size_t count) |
265 | { | 276 | { |
266 | struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); | 277 | struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); |
267 | struct smsc47m1_data *data = dev_get_drvdata(dev); | 278 | struct smsc47m1_data *data = dev_get_drvdata(dev); |
268 | int nr = attr->index; | 279 | int nr = attr->index; |
269 | long new_div = simple_strtol(buf, NULL, 10), tmp; | 280 | long new_div; |
281 | int err; | ||
282 | long tmp; | ||
270 | u8 old_div = DIV_FROM_REG(data->fan_div[nr]); | 283 | u8 old_div = DIV_FROM_REG(data->fan_div[nr]); |
271 | 284 | ||
285 | err = kstrtol(buf, 10, &new_div); | ||
286 | if (err) | ||
287 | return err; | ||
288 | |||
272 | if (new_div == old_div) /* No change */ | 289 | if (new_div == old_div) /* No change */ |
273 | return count; | 290 | return count; |
274 | 291 | ||
275 | mutex_lock(&data->update_lock); | 292 | mutex_lock(&data->update_lock); |
276 | switch (new_div) { | 293 | switch (new_div) { |
277 | case 1: data->fan_div[nr] = 0; break; | 294 | case 1: |
278 | case 2: data->fan_div[nr] = 1; break; | 295 | data->fan_div[nr] = 0; |
279 | case 4: data->fan_div[nr] = 2; break; | 296 | break; |
280 | case 8: data->fan_div[nr] = 3; break; | 297 | case 2: |
298 | data->fan_div[nr] = 1; | ||
299 | break; | ||
300 | case 4: | ||
301 | data->fan_div[nr] = 2; | ||
302 | break; | ||
303 | case 8: | ||
304 | data->fan_div[nr] = 3; | ||
305 | break; | ||
281 | default: | 306 | default: |
282 | mutex_unlock(&data->update_lock); | 307 | mutex_unlock(&data->update_lock); |
283 | return -EINVAL; | 308 | return -EINVAL; |
@@ -315,7 +340,12 @@ static ssize_t set_pwm(struct device *dev, struct device_attribute | |||
315 | struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); | 340 | struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); |
316 | struct smsc47m1_data *data = dev_get_drvdata(dev); | 341 | struct smsc47m1_data *data = dev_get_drvdata(dev); |
317 | int nr = attr->index; | 342 | int nr = attr->index; |
318 | long val = simple_strtol(buf, NULL, 10); | 343 | long val; |
344 | int err; | ||
345 | |||
346 | err = kstrtol(buf, 10, &val); | ||
347 | if (err) | ||
348 | return err; | ||
319 | 349 | ||
320 | if (val < 0 || val > 255) | 350 | if (val < 0 || val > 255) |
321 | return -EINVAL; | 351 | return -EINVAL; |
@@ -336,9 +366,14 @@ static ssize_t set_pwm_en(struct device *dev, struct device_attribute | |||
336 | struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); | 366 | struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); |
337 | struct smsc47m1_data *data = dev_get_drvdata(dev); | 367 | struct smsc47m1_data *data = dev_get_drvdata(dev); |
338 | int nr = attr->index; | 368 | int nr = attr->index; |
339 | long val = simple_strtol(buf, NULL, 10); | 369 | unsigned long val; |
340 | 370 | int err; | |
341 | if (val != 0 && val != 1) | 371 | |
372 | err = kstrtoul(buf, 10, &val); | ||
373 | if (err) | ||
374 | return err; | ||
375 | |||
376 | if (val > 1) | ||
342 | return -EINVAL; | 377 | return -EINVAL; |
343 | 378 | ||
344 | mutex_lock(&data->update_lock); | 379 | mutex_lock(&data->update_lock); |
@@ -380,30 +415,73 @@ static ssize_t show_name(struct device *dev, struct device_attribute | |||
380 | } | 415 | } |
381 | static DEVICE_ATTR(name, S_IRUGO, show_name, NULL); | 416 | static DEVICE_ATTR(name, S_IRUGO, show_name, NULL); |
382 | 417 | ||
383 | /* Almost all sysfs files may or may not be created depending on the chip | 418 | static struct attribute *smsc47m1_attributes_fan1[] = { |
384 | setup so we create them individually. It is still convenient to define a | ||
385 | group to remove them all at once. */ | ||
386 | static struct attribute *smsc47m1_attributes[] = { | ||
387 | &sensor_dev_attr_fan1_input.dev_attr.attr, | 419 | &sensor_dev_attr_fan1_input.dev_attr.attr, |
388 | &sensor_dev_attr_fan1_min.dev_attr.attr, | 420 | &sensor_dev_attr_fan1_min.dev_attr.attr, |
389 | &sensor_dev_attr_fan1_div.dev_attr.attr, | 421 | &sensor_dev_attr_fan1_div.dev_attr.attr, |
390 | &sensor_dev_attr_fan1_alarm.dev_attr.attr, | 422 | &sensor_dev_attr_fan1_alarm.dev_attr.attr, |
423 | NULL | ||
424 | }; | ||
425 | |||
426 | static const struct attribute_group smsc47m1_group_fan1 = { | ||
427 | .attrs = smsc47m1_attributes_fan1, | ||
428 | }; | ||
429 | |||
430 | static struct attribute *smsc47m1_attributes_fan2[] = { | ||
391 | &sensor_dev_attr_fan2_input.dev_attr.attr, | 431 | &sensor_dev_attr_fan2_input.dev_attr.attr, |
392 | &sensor_dev_attr_fan2_min.dev_attr.attr, | 432 | &sensor_dev_attr_fan2_min.dev_attr.attr, |
393 | &sensor_dev_attr_fan2_div.dev_attr.attr, | 433 | &sensor_dev_attr_fan2_div.dev_attr.attr, |
394 | &sensor_dev_attr_fan2_alarm.dev_attr.attr, | 434 | &sensor_dev_attr_fan2_alarm.dev_attr.attr, |
435 | NULL | ||
436 | }; | ||
437 | |||
438 | static const struct attribute_group smsc47m1_group_fan2 = { | ||
439 | .attrs = smsc47m1_attributes_fan2, | ||
440 | }; | ||
441 | |||
442 | static struct attribute *smsc47m1_attributes_fan3[] = { | ||
395 | &sensor_dev_attr_fan3_input.dev_attr.attr, | 443 | &sensor_dev_attr_fan3_input.dev_attr.attr, |
396 | &sensor_dev_attr_fan3_min.dev_attr.attr, | 444 | &sensor_dev_attr_fan3_min.dev_attr.attr, |
397 | &sensor_dev_attr_fan3_div.dev_attr.attr, | 445 | &sensor_dev_attr_fan3_div.dev_attr.attr, |
398 | &sensor_dev_attr_fan3_alarm.dev_attr.attr, | 446 | &sensor_dev_attr_fan3_alarm.dev_attr.attr, |
447 | NULL | ||
448 | }; | ||
449 | |||
450 | static const struct attribute_group smsc47m1_group_fan3 = { | ||
451 | .attrs = smsc47m1_attributes_fan3, | ||
452 | }; | ||
399 | 453 | ||
454 | static struct attribute *smsc47m1_attributes_pwm1[] = { | ||
400 | &sensor_dev_attr_pwm1.dev_attr.attr, | 455 | &sensor_dev_attr_pwm1.dev_attr.attr, |
401 | &sensor_dev_attr_pwm1_enable.dev_attr.attr, | 456 | &sensor_dev_attr_pwm1_enable.dev_attr.attr, |
457 | NULL | ||
458 | }; | ||
459 | |||
460 | static const struct attribute_group smsc47m1_group_pwm1 = { | ||
461 | .attrs = smsc47m1_attributes_pwm1, | ||
462 | }; | ||
463 | |||
464 | static struct attribute *smsc47m1_attributes_pwm2[] = { | ||
402 | &sensor_dev_attr_pwm2.dev_attr.attr, | 465 | &sensor_dev_attr_pwm2.dev_attr.attr, |
403 | &sensor_dev_attr_pwm2_enable.dev_attr.attr, | 466 | &sensor_dev_attr_pwm2_enable.dev_attr.attr, |
467 | NULL | ||
468 | }; | ||
469 | |||
470 | static const struct attribute_group smsc47m1_group_pwm2 = { | ||
471 | .attrs = smsc47m1_attributes_pwm2, | ||
472 | }; | ||
473 | |||
474 | static struct attribute *smsc47m1_attributes_pwm3[] = { | ||
404 | &sensor_dev_attr_pwm3.dev_attr.attr, | 475 | &sensor_dev_attr_pwm3.dev_attr.attr, |
405 | &sensor_dev_attr_pwm3_enable.dev_attr.attr, | 476 | &sensor_dev_attr_pwm3_enable.dev_attr.attr, |
477 | NULL | ||
478 | }; | ||
479 | |||
480 | static const struct attribute_group smsc47m1_group_pwm3 = { | ||
481 | .attrs = smsc47m1_attributes_pwm3, | ||
482 | }; | ||
406 | 483 | ||
484 | static struct attribute *smsc47m1_attributes[] = { | ||
407 | &dev_attr_alarms.attr, | 485 | &dev_attr_alarms.attr, |
408 | &dev_attr_name.attr, | 486 | &dev_attr_name.attr, |
409 | NULL | 487 | NULL |
@@ -476,8 +554,10 @@ static int __init smsc47m1_find(unsigned short *addr, | |||
476 | return -ENODEV; | 554 | return -ENODEV; |
477 | } | 555 | } |
478 | 556 | ||
479 | /* Enable only if address is set (needed at least on the | 557 | /* |
480 | * Compaq Presario S4000NX) */ | 558 | * Enable only if address is set (needed at least on the |
559 | * Compaq Presario S4000NX) | ||
560 | */ | ||
481 | sio_data->activate = superio_inb(SUPERIO_REG_ACT); | 561 | sio_data->activate = superio_inb(SUPERIO_REG_ACT); |
482 | if ((sio_data->activate & 0x01) == 0) { | 562 | if ((sio_data->activate & 0x01) == 0) { |
483 | pr_info("Enabling device\n"); | 563 | pr_info("Enabling device\n"); |
@@ -583,6 +663,17 @@ static int smsc47m1_handle_resources(unsigned short address, enum chips type, | |||
583 | return 0; | 663 | return 0; |
584 | } | 664 | } |
585 | 665 | ||
666 | static void smsc47m1_remove_files(struct device *dev) | ||
667 | { | ||
668 | sysfs_remove_group(&dev->kobj, &smsc47m1_group); | ||
669 | sysfs_remove_group(&dev->kobj, &smsc47m1_group_fan1); | ||
670 | sysfs_remove_group(&dev->kobj, &smsc47m1_group_fan2); | ||
671 | sysfs_remove_group(&dev->kobj, &smsc47m1_group_fan3); | ||
672 | sysfs_remove_group(&dev->kobj, &smsc47m1_group_pwm1); | ||
673 | sysfs_remove_group(&dev->kobj, &smsc47m1_group_pwm2); | ||
674 | sysfs_remove_group(&dev->kobj, &smsc47m1_group_pwm3); | ||
675 | } | ||
676 | |||
586 | static int __init smsc47m1_probe(struct platform_device *pdev) | 677 | static int __init smsc47m1_probe(struct platform_device *pdev) |
587 | { | 678 | { |
588 | struct device *dev = &pdev->dev; | 679 | struct device *dev = &pdev->dev; |
@@ -592,7 +683,7 @@ static int __init smsc47m1_probe(struct platform_device *pdev) | |||
592 | int err; | 683 | int err; |
593 | int fan1, fan2, fan3, pwm1, pwm2, pwm3; | 684 | int fan1, fan2, fan3, pwm1, pwm2, pwm3; |
594 | 685 | ||
595 | static const char *names[] = { | 686 | static const char * const names[] = { |
596 | "smsc47m1", | 687 | "smsc47m1", |
597 | "smsc47m2", | 688 | "smsc47m2", |
598 | }; | 689 | }; |
@@ -603,7 +694,8 @@ static int __init smsc47m1_probe(struct platform_device *pdev) | |||
603 | if (err < 0) | 694 | if (err < 0) |
604 | return err; | 695 | return err; |
605 | 696 | ||
606 | if (!(data = kzalloc(sizeof(struct smsc47m1_data), GFP_KERNEL))) { | 697 | data = kzalloc(sizeof(struct smsc47m1_data), GFP_KERNEL); |
698 | if (!data) { | ||
607 | err = -ENOMEM; | 699 | err = -ENOMEM; |
608 | goto error_release; | 700 | goto error_release; |
609 | } | 701 | } |
@@ -614,8 +706,10 @@ static int __init smsc47m1_probe(struct platform_device *pdev) | |||
614 | mutex_init(&data->update_lock); | 706 | mutex_init(&data->update_lock); |
615 | platform_set_drvdata(pdev, data); | 707 | platform_set_drvdata(pdev, data); |
616 | 708 | ||
617 | /* If no function is properly configured, there's no point in | 709 | /* |
618 | actually registering the chip. */ | 710 | * If no function is properly configured, there's no point in |
711 | * actually registering the chip. | ||
712 | */ | ||
619 | pwm1 = (smsc47m1_read_value(data, SMSC47M1_REG_PPIN(0)) & 0x05) | 713 | pwm1 = (smsc47m1_read_value(data, SMSC47M1_REG_PPIN(0)) & 0x05) |
620 | == 0x04; | 714 | == 0x04; |
621 | pwm2 = (smsc47m1_read_value(data, SMSC47M1_REG_PPIN(1)) & 0x05) | 715 | pwm2 = (smsc47m1_read_value(data, SMSC47M1_REG_PPIN(1)) & 0x05) |
@@ -643,84 +737,67 @@ static int __init smsc47m1_probe(struct platform_device *pdev) | |||
643 | goto error_free; | 737 | goto error_free; |
644 | } | 738 | } |
645 | 739 | ||
646 | /* Some values (fan min, clock dividers, pwm registers) may be | 740 | /* |
647 | needed before any update is triggered, so we better read them | 741 | * Some values (fan min, clock dividers, pwm registers) may be |
648 | at least once here. We don't usually do it that way, but in | 742 | * needed before any update is triggered, so we better read them |
649 | this particular case, manually reading 5 registers out of 8 | 743 | * at least once here. We don't usually do it that way, but in |
650 | doesn't make much sense and we're better using the existing | 744 | * this particular case, manually reading 5 registers out of 8 |
651 | function. */ | 745 | * doesn't make much sense and we're better using the existing |
746 | * function. | ||
747 | */ | ||
652 | smsc47m1_update_device(dev, 1); | 748 | smsc47m1_update_device(dev, 1); |
653 | 749 | ||
654 | /* Register sysfs hooks */ | 750 | /* Register sysfs hooks */ |
655 | if (fan1) { | 751 | if (fan1) { |
656 | if ((err = device_create_file(dev, | 752 | err = sysfs_create_group(&dev->kobj, |
657 | &sensor_dev_attr_fan1_input.dev_attr)) | 753 | &smsc47m1_group_fan1); |
658 | || (err = device_create_file(dev, | 754 | if (err) |
659 | &sensor_dev_attr_fan1_min.dev_attr)) | ||
660 | || (err = device_create_file(dev, | ||
661 | &sensor_dev_attr_fan1_div.dev_attr)) | ||
662 | || (err = device_create_file(dev, | ||
663 | &sensor_dev_attr_fan1_alarm.dev_attr))) | ||
664 | goto error_remove_files; | 755 | goto error_remove_files; |
665 | } else | 756 | } else |
666 | dev_dbg(dev, "Fan 1 not enabled by hardware, skipping\n"); | 757 | dev_dbg(dev, "Fan 1 not enabled by hardware, skipping\n"); |
667 | 758 | ||
668 | if (fan2) { | 759 | if (fan2) { |
669 | if ((err = device_create_file(dev, | 760 | err = sysfs_create_group(&dev->kobj, |
670 | &sensor_dev_attr_fan2_input.dev_attr)) | 761 | &smsc47m1_group_fan2); |
671 | || (err = device_create_file(dev, | 762 | if (err) |
672 | &sensor_dev_attr_fan2_min.dev_attr)) | ||
673 | || (err = device_create_file(dev, | ||
674 | &sensor_dev_attr_fan2_div.dev_attr)) | ||
675 | || (err = device_create_file(dev, | ||
676 | &sensor_dev_attr_fan2_alarm.dev_attr))) | ||
677 | goto error_remove_files; | 763 | goto error_remove_files; |
678 | } else | 764 | } else |
679 | dev_dbg(dev, "Fan 2 not enabled by hardware, skipping\n"); | 765 | dev_dbg(dev, "Fan 2 not enabled by hardware, skipping\n"); |
680 | 766 | ||
681 | if (fan3) { | 767 | if (fan3) { |
682 | if ((err = device_create_file(dev, | 768 | err = sysfs_create_group(&dev->kobj, |
683 | &sensor_dev_attr_fan3_input.dev_attr)) | 769 | &smsc47m1_group_fan3); |
684 | || (err = device_create_file(dev, | 770 | if (err) |
685 | &sensor_dev_attr_fan3_min.dev_attr)) | ||
686 | || (err = device_create_file(dev, | ||
687 | &sensor_dev_attr_fan3_div.dev_attr)) | ||
688 | || (err = device_create_file(dev, | ||
689 | &sensor_dev_attr_fan3_alarm.dev_attr))) | ||
690 | goto error_remove_files; | 771 | goto error_remove_files; |
691 | } else if (data->type == smsc47m2) | 772 | } else if (data->type == smsc47m2) |
692 | dev_dbg(dev, "Fan 3 not enabled by hardware, skipping\n"); | 773 | dev_dbg(dev, "Fan 3 not enabled by hardware, skipping\n"); |
693 | 774 | ||
694 | if (pwm1) { | 775 | if (pwm1) { |
695 | if ((err = device_create_file(dev, | 776 | err = sysfs_create_group(&dev->kobj, |
696 | &sensor_dev_attr_pwm1.dev_attr)) | 777 | &smsc47m1_group_pwm1); |
697 | || (err = device_create_file(dev, | 778 | if (err) |
698 | &sensor_dev_attr_pwm1_enable.dev_attr))) | ||
699 | goto error_remove_files; | 779 | goto error_remove_files; |
700 | } else | 780 | } else |
701 | dev_dbg(dev, "PWM 1 not enabled by hardware, skipping\n"); | 781 | dev_dbg(dev, "PWM 1 not enabled by hardware, skipping\n"); |
702 | 782 | ||
703 | if (pwm2) { | 783 | if (pwm2) { |
704 | if ((err = device_create_file(dev, | 784 | err = sysfs_create_group(&dev->kobj, |
705 | &sensor_dev_attr_pwm2.dev_attr)) | 785 | &smsc47m1_group_pwm2); |
706 | || (err = device_create_file(dev, | 786 | if (err) |
707 | &sensor_dev_attr_pwm2_enable.dev_attr))) | ||
708 | goto error_remove_files; | 787 | goto error_remove_files; |
709 | } else | 788 | } else |
710 | dev_dbg(dev, "PWM 2 not enabled by hardware, skipping\n"); | 789 | dev_dbg(dev, "PWM 2 not enabled by hardware, skipping\n"); |
711 | 790 | ||
712 | if (pwm3) { | 791 | if (pwm3) { |
713 | if ((err = device_create_file(dev, | 792 | err = sysfs_create_group(&dev->kobj, |
714 | &sensor_dev_attr_pwm3.dev_attr)) | 793 | &smsc47m1_group_pwm3); |
715 | || (err = device_create_file(dev, | 794 | if (err) |
716 | &sensor_dev_attr_pwm3_enable.dev_attr))) | ||
717 | goto error_remove_files; | 795 | goto error_remove_files; |
718 | } else if (data->type == smsc47m2) | 796 | } else if (data->type == smsc47m2) |
719 | dev_dbg(dev, "PWM 3 not enabled by hardware, skipping\n"); | 797 | dev_dbg(dev, "PWM 3 not enabled by hardware, skipping\n"); |
720 | 798 | ||
721 | if ((err = device_create_file(dev, &dev_attr_alarms))) | 799 | err = sysfs_create_group(&dev->kobj, &smsc47m1_group); |
722 | goto error_remove_files; | 800 | if (err) |
723 | if ((err = device_create_file(dev, &dev_attr_name))) | ||
724 | goto error_remove_files; | 801 | goto error_remove_files; |
725 | 802 | ||
726 | data->hwmon_dev = hwmon_device_register(dev); | 803 | data->hwmon_dev = hwmon_device_register(dev); |
@@ -732,7 +809,7 @@ static int __init smsc47m1_probe(struct platform_device *pdev) | |||
732 | return 0; | 809 | return 0; |
733 | 810 | ||
734 | error_remove_files: | 811 | error_remove_files: |
735 | sysfs_remove_group(&dev->kobj, &smsc47m1_group); | 812 | smsc47m1_remove_files(dev); |
736 | error_free: | 813 | error_free: |
737 | platform_set_drvdata(pdev, NULL); | 814 | platform_set_drvdata(pdev, NULL); |
738 | kfree(data); | 815 | kfree(data); |
@@ -747,7 +824,7 @@ static int __exit smsc47m1_remove(struct platform_device *pdev) | |||
747 | struct resource *res; | 824 | struct resource *res; |
748 | 825 | ||
749 | hwmon_device_unregister(data->hwmon_dev); | 826 | hwmon_device_unregister(data->hwmon_dev); |
750 | sysfs_remove_group(&pdev->dev.kobj, &smsc47m1_group); | 827 | smsc47m1_remove_files(&pdev->dev); |
751 | 828 | ||
752 | res = platform_get_resource(pdev, IORESOURCE_IO, 0); | 829 | res = platform_get_resource(pdev, IORESOURCE_IO, 0); |
753 | smsc47m1_handle_resources(res->start, data->type, RELEASE, &pdev->dev); | 830 | smsc47m1_handle_resources(res->start, data->type, RELEASE, &pdev->dev); |