diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2013-07-03 22:56:35 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2013-07-03 22:56:35 -0400 |
commit | ddcf6600b133697adbafd96e080818bdc0dfd028 (patch) | |
tree | f382f8eaca3cc2d298542ae9599ce49884127d0e /drivers/hwmon | |
parent | c16bfeb264decb964742067f02fdd51494e25e64 (diff) | |
parent | a50d9a4d9ad3c71341788099d733e4151b8a511b (diff) |
Merge tag 'hwmon-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/groeck/linux-staging
Pull hwmon updates from Guenter Roeck:
- new driver to support GMT G762/G763 pwm fan controllers
- add support for DS1631, DS1721, and DS1731 to ds1621 driver
- remove detect function from ds1621 driver as unreliable
- bug fixes in nct6775, iio_hwmon, and adm1021 drivers
- remove redundant platform_set_drvdata in various drivers
- add device tree support to ina2xx driver
* tag 'hwmon-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/groeck/linux-staging:
hwmon: (ds1621) Fix temperature rounding operations
hwmon: (nct6775) Drop unsupported fan alarm attributes for NCT6775
hwmon: (nct6775) Fix temperature alarm attributes
Add support for GMT G762/G763 PWM fan controllers
hwmon: (ina2xx) Add device tree support to pass the shunt resistor
hwmon: (ds1621) Update documentation
hwmon: (ds1621) Add DS1731 chip support to ds1621 driver
hwmon: (iio_hwmon) add alias table
hwmon: (adm1021) Do not create min sysfs attributes for LM84
hwmon: (ds1621) Remove detect function
hwmon: (ds1621) Add ds1631 chip support to ds1621 driver and documentation
hwmon: (ds1621) Add ds1721 update interval sysfs attribute
hwmon: (ds1621) Add ds1721 chip support
hwmon: (w83627ehf) Remove redundant platform_set_drvdata()
hwmon: (ntc_thermistor) Remove redundant platform_set_drvdata()
hwmon: (i5k_amb) Remove redundant platform_set_drvdata()
hwmon: (coretemp) Remove redundant platform_set_drvdata()
hwmon: (abituguru3) Remove redundant platform_set_drvdata()
Diffstat (limited to 'drivers/hwmon')
-rw-r--r-- | drivers/hwmon/Kconfig | 21 | ||||
-rw-r--r-- | drivers/hwmon/Makefile | 1 | ||||
-rw-r--r-- | drivers/hwmon/abituguru3.c | 1 | ||||
-rw-r--r-- | drivers/hwmon/adm1021.c | 32 | ||||
-rw-r--r-- | drivers/hwmon/coretemp.c | 2 | ||||
-rw-r--r-- | drivers/hwmon/ds1621.c | 226 | ||||
-rw-r--r-- | drivers/hwmon/g762.c | 1149 | ||||
-rw-r--r-- | drivers/hwmon/i5k_amb.c | 2 | ||||
-rw-r--r-- | drivers/hwmon/iio_hwmon.c | 1 | ||||
-rw-r--r-- | drivers/hwmon/ina2xx.c | 5 | ||||
-rw-r--r-- | drivers/hwmon/nct6775.c | 92 | ||||
-rw-r--r-- | drivers/hwmon/ntc_thermistor.c | 1 | ||||
-rw-r--r-- | drivers/hwmon/w83627ehf.c | 2 |
13 files changed, 1435 insertions, 100 deletions
diff --git a/drivers/hwmon/Kconfig b/drivers/hwmon/Kconfig index 0428e8a74b19..e989f7fd645b 100644 --- a/drivers/hwmon/Kconfig +++ b/drivers/hwmon/Kconfig | |||
@@ -348,11 +348,16 @@ config SENSORS_DS620 | |||
348 | will be called ds620. | 348 | will be called ds620. |
349 | 349 | ||
350 | config SENSORS_DS1621 | 350 | config SENSORS_DS1621 |
351 | tristate "Dallas Semiconductor DS1621 and DS1625" | 351 | tristate "Dallas Semiconductor DS1621 and compatibles" |
352 | depends on I2C | 352 | depends on I2C |
353 | help | 353 | help |
354 | If you say yes here you get support for Dallas Semiconductor | 354 | If you say yes here you get support for Dallas Semiconductor/Maxim |
355 | DS1621 and DS1625 sensor chips. | 355 | Integrated DS1621 sensor chips and compatible models including: |
356 | |||
357 | - Dallas Semiconductor DS1625 | ||
358 | - Maxim Integrated DS1631 | ||
359 | - Maxim Integrated DS1721 | ||
360 | - Maxim Integrated DS1731 | ||
356 | 361 | ||
357 | This driver can also be built as a module. If so, the module | 362 | This driver can also be built as a module. If so, the module |
358 | will be called ds1621. | 363 | will be called ds1621. |
@@ -456,6 +461,16 @@ config SENSORS_G760A | |||
456 | This driver can also be built as a module. If so, the module | 461 | This driver can also be built as a module. If so, the module |
457 | will be called g760a. | 462 | will be called g760a. |
458 | 463 | ||
464 | config SENSORS_G762 | ||
465 | tristate "GMT G762 and G763" | ||
466 | depends on I2C | ||
467 | help | ||
468 | If you say yes here you get support for Global Mixed-mode | ||
469 | Technology Inc G762 and G763 fan speed PWM controller chips. | ||
470 | |||
471 | This driver can also be built as a module. If so, the module | ||
472 | will be called g762. | ||
473 | |||
459 | config SENSORS_GL518SM | 474 | config SENSORS_GL518SM |
460 | tristate "Genesys Logic GL518SM" | 475 | tristate "Genesys Logic GL518SM" |
461 | depends on I2C | 476 | depends on I2C |
diff --git a/drivers/hwmon/Makefile b/drivers/hwmon/Makefile index d17d3e64f9f4..4f0fb5235f42 100644 --- a/drivers/hwmon/Makefile +++ b/drivers/hwmon/Makefile | |||
@@ -60,6 +60,7 @@ obj-$(CONFIG_SENSORS_F75375S) += f75375s.o | |||
60 | obj-$(CONFIG_SENSORS_FAM15H_POWER) += fam15h_power.o | 60 | obj-$(CONFIG_SENSORS_FAM15H_POWER) += fam15h_power.o |
61 | obj-$(CONFIG_SENSORS_FSCHMD) += fschmd.o | 61 | obj-$(CONFIG_SENSORS_FSCHMD) += fschmd.o |
62 | obj-$(CONFIG_SENSORS_G760A) += g760a.o | 62 | obj-$(CONFIG_SENSORS_G760A) += g760a.o |
63 | obj-$(CONFIG_SENSORS_G762) += g762.o | ||
63 | obj-$(CONFIG_SENSORS_GL518SM) += gl518sm.o | 64 | obj-$(CONFIG_SENSORS_GL518SM) += gl518sm.o |
64 | obj-$(CONFIG_SENSORS_GL520SM) += gl520sm.o | 65 | obj-$(CONFIG_SENSORS_GL520SM) += gl520sm.o |
65 | obj-$(CONFIG_SENSORS_GPIO_FAN) += gpio-fan.o | 66 | obj-$(CONFIG_SENSORS_GPIO_FAN) += gpio-fan.o |
diff --git a/drivers/hwmon/abituguru3.c b/drivers/hwmon/abituguru3.c index 1d2da31c27c6..0cac8c0b001a 100644 --- a/drivers/hwmon/abituguru3.c +++ b/drivers/hwmon/abituguru3.c | |||
@@ -1079,7 +1079,6 @@ static int abituguru3_remove(struct platform_device *pdev) | |||
1079 | int i; | 1079 | int i; |
1080 | struct abituguru3_data *data = platform_get_drvdata(pdev); | 1080 | struct abituguru3_data *data = platform_get_drvdata(pdev); |
1081 | 1081 | ||
1082 | platform_set_drvdata(pdev, NULL); | ||
1083 | hwmon_device_unregister(data->hwmon_dev); | 1082 | hwmon_device_unregister(data->hwmon_dev); |
1084 | for (i = 0; data->sysfs_attr[i].dev_attr.attr.name; i++) | 1083 | for (i = 0; data->sysfs_attr[i].dev_attr.attr.name; i++) |
1085 | device_remove_file(&pdev->dev, &data->sysfs_attr[i].dev_attr); | 1084 | device_remove_file(&pdev->dev, &data->sysfs_attr[i].dev_attr); |
diff --git a/drivers/hwmon/adm1021.c b/drivers/hwmon/adm1021.c index f920619cd6da..29dd9f746dfa 100644 --- a/drivers/hwmon/adm1021.c +++ b/drivers/hwmon/adm1021.c | |||
@@ -284,15 +284,11 @@ static DEVICE_ATTR(low_power, S_IWUSR | S_IRUGO, show_low_power, set_low_power); | |||
284 | 284 | ||
285 | static struct attribute *adm1021_attributes[] = { | 285 | static struct attribute *adm1021_attributes[] = { |
286 | &sensor_dev_attr_temp1_max.dev_attr.attr, | 286 | &sensor_dev_attr_temp1_max.dev_attr.attr, |
287 | &sensor_dev_attr_temp1_min.dev_attr.attr, | ||
288 | &sensor_dev_attr_temp1_input.dev_attr.attr, | 287 | &sensor_dev_attr_temp1_input.dev_attr.attr, |
289 | &sensor_dev_attr_temp2_max.dev_attr.attr, | 288 | &sensor_dev_attr_temp2_max.dev_attr.attr, |
290 | &sensor_dev_attr_temp2_min.dev_attr.attr, | ||
291 | &sensor_dev_attr_temp2_input.dev_attr.attr, | 289 | &sensor_dev_attr_temp2_input.dev_attr.attr, |
292 | &sensor_dev_attr_temp1_max_alarm.dev_attr.attr, | 290 | &sensor_dev_attr_temp1_max_alarm.dev_attr.attr, |
293 | &sensor_dev_attr_temp1_min_alarm.dev_attr.attr, | ||
294 | &sensor_dev_attr_temp2_max_alarm.dev_attr.attr, | 291 | &sensor_dev_attr_temp2_max_alarm.dev_attr.attr, |
295 | &sensor_dev_attr_temp2_min_alarm.dev_attr.attr, | ||
296 | &sensor_dev_attr_temp2_fault.dev_attr.attr, | 292 | &sensor_dev_attr_temp2_fault.dev_attr.attr, |
297 | &dev_attr_alarms.attr, | 293 | &dev_attr_alarms.attr, |
298 | &dev_attr_low_power.attr, | 294 | &dev_attr_low_power.attr, |
@@ -303,6 +299,18 @@ static const struct attribute_group adm1021_group = { | |||
303 | .attrs = adm1021_attributes, | 299 | .attrs = adm1021_attributes, |
304 | }; | 300 | }; |
305 | 301 | ||
302 | static struct attribute *adm1021_min_attributes[] = { | ||
303 | &sensor_dev_attr_temp1_min.dev_attr.attr, | ||
304 | &sensor_dev_attr_temp2_min.dev_attr.attr, | ||
305 | &sensor_dev_attr_temp1_min_alarm.dev_attr.attr, | ||
306 | &sensor_dev_attr_temp2_min_alarm.dev_attr.attr, | ||
307 | NULL | ||
308 | }; | ||
309 | |||
310 | static const struct attribute_group adm1021_min_group = { | ||
311 | .attrs = adm1021_min_attributes, | ||
312 | }; | ||
313 | |||
306 | /* Return 0 if detection is successful, -ENODEV otherwise */ | 314 | /* Return 0 if detection is successful, -ENODEV otherwise */ |
307 | static int adm1021_detect(struct i2c_client *client, | 315 | static int adm1021_detect(struct i2c_client *client, |
308 | struct i2c_board_info *info) | 316 | struct i2c_board_info *info) |
@@ -425,6 +433,12 @@ static int adm1021_probe(struct i2c_client *client, | |||
425 | if (err) | 433 | if (err) |
426 | return err; | 434 | return err; |
427 | 435 | ||
436 | if (data->type != lm84) { | ||
437 | err = sysfs_create_group(&client->dev.kobj, &adm1021_min_group); | ||
438 | if (err) | ||
439 | goto error; | ||
440 | } | ||
441 | |||
428 | data->hwmon_dev = hwmon_device_register(&client->dev); | 442 | data->hwmon_dev = hwmon_device_register(&client->dev); |
429 | if (IS_ERR(data->hwmon_dev)) { | 443 | if (IS_ERR(data->hwmon_dev)) { |
430 | err = PTR_ERR(data->hwmon_dev); | 444 | err = PTR_ERR(data->hwmon_dev); |
@@ -434,6 +448,7 @@ static int adm1021_probe(struct i2c_client *client, | |||
434 | return 0; | 448 | return 0; |
435 | 449 | ||
436 | error: | 450 | error: |
451 | sysfs_remove_group(&client->dev.kobj, &adm1021_min_group); | ||
437 | sysfs_remove_group(&client->dev.kobj, &adm1021_group); | 452 | sysfs_remove_group(&client->dev.kobj, &adm1021_group); |
438 | return err; | 453 | return err; |
439 | } | 454 | } |
@@ -452,6 +467,7 @@ static int adm1021_remove(struct i2c_client *client) | |||
452 | struct adm1021_data *data = i2c_get_clientdata(client); | 467 | struct adm1021_data *data = i2c_get_clientdata(client); |
453 | 468 | ||
454 | hwmon_device_unregister(data->hwmon_dev); | 469 | hwmon_device_unregister(data->hwmon_dev); |
470 | sysfs_remove_group(&client->dev.kobj, &adm1021_min_group); | ||
455 | sysfs_remove_group(&client->dev.kobj, &adm1021_group); | 471 | sysfs_remove_group(&client->dev.kobj, &adm1021_group); |
456 | 472 | ||
457 | return 0; | 473 | return 0; |
@@ -477,9 +493,11 @@ static struct adm1021_data *adm1021_update_device(struct device *dev) | |||
477 | data->temp_max[i] = 1000 * | 493 | data->temp_max[i] = 1000 * |
478 | (s8) i2c_smbus_read_byte_data( | 494 | (s8) i2c_smbus_read_byte_data( |
479 | client, ADM1021_REG_TOS_R(i)); | 495 | client, ADM1021_REG_TOS_R(i)); |
480 | data->temp_min[i] = 1000 * | 496 | if (data->type != lm84) { |
481 | (s8) i2c_smbus_read_byte_data( | 497 | data->temp_min[i] = 1000 * |
482 | client, ADM1021_REG_THYST_R(i)); | 498 | (s8) i2c_smbus_read_byte_data(client, |
499 | ADM1021_REG_THYST_R(i)); | ||
500 | } | ||
483 | } | 501 | } |
484 | data->alarms = i2c_smbus_read_byte_data(client, | 502 | data->alarms = i2c_smbus_read_byte_data(client, |
485 | ADM1021_REG_STATUS) & 0x7c; | 503 | ADM1021_REG_STATUS) & 0x7c; |
diff --git a/drivers/hwmon/coretemp.c b/drivers/hwmon/coretemp.c index 658ce3a8717f..ade35cf3f488 100644 --- a/drivers/hwmon/coretemp.c +++ b/drivers/hwmon/coretemp.c | |||
@@ -578,7 +578,6 @@ static int coretemp_probe(struct platform_device *pdev) | |||
578 | 578 | ||
579 | exit_name: | 579 | exit_name: |
580 | device_remove_file(&pdev->dev, &pdata->name_attr); | 580 | device_remove_file(&pdev->dev, &pdata->name_attr); |
581 | platform_set_drvdata(pdev, NULL); | ||
582 | exit_free: | 581 | exit_free: |
583 | kfree(pdata); | 582 | kfree(pdata); |
584 | return err; | 583 | return err; |
@@ -595,7 +594,6 @@ static int coretemp_remove(struct platform_device *pdev) | |||
595 | 594 | ||
596 | device_remove_file(&pdev->dev, &pdata->name_attr); | 595 | device_remove_file(&pdev->dev, &pdata->name_attr); |
597 | hwmon_device_unregister(pdata->hwmon_dev); | 596 | hwmon_device_unregister(pdata->hwmon_dev); |
598 | platform_set_drvdata(pdev, NULL); | ||
599 | kfree(pdata); | 597 | kfree(pdata); |
600 | return 0; | 598 | return 0; |
601 | } | 599 | } |
diff --git a/drivers/hwmon/ds1621.c b/drivers/hwmon/ds1621.c index 1c568736baff..a26ba7a17c2b 100644 --- a/drivers/hwmon/ds1621.c +++ b/drivers/hwmon/ds1621.c | |||
@@ -6,6 +6,19 @@ | |||
6 | * Ported to Linux 2.6 by Aurelien Jarno <aurelien@aurel32.net> with | 6 | * Ported to Linux 2.6 by Aurelien Jarno <aurelien@aurel32.net> with |
7 | * the help of Jean Delvare <khali@linux-fr.org> | 7 | * the help of Jean Delvare <khali@linux-fr.org> |
8 | * | 8 | * |
9 | * The DS1621 device is a digital temperature/thermometer with 9-bit | ||
10 | * resolution, a thermal alarm output (Tout), and user-defined minimum | ||
11 | * and maximum temperature thresholds (TH and TL). | ||
12 | * | ||
13 | * The DS1625, DS1631, DS1721, and DS1731 are pin compatible with the DS1621 | ||
14 | * and similar in operation, with slight variations as noted in the device | ||
15 | * datasheets (please refer to www.maximintegrated.com for specific | ||
16 | * device information). | ||
17 | * | ||
18 | * Since the DS1621 was the first chipset supported by this driver, | ||
19 | * most comments will refer to this chipset, but are actually general | ||
20 | * and concern all supported chipsets, unless mentioned otherwise. | ||
21 | * | ||
9 | * This program is free software; you can redistribute it and/or modify | 22 | * This program is free software; you can redistribute it and/or modify |
10 | * it under the terms of the GNU General Public License as published by | 23 | * it under the terms of the GNU General Public License as published by |
11 | * the Free Software Foundation; either version 2 of the License, or | 24 | * the Free Software Foundation; either version 2 of the License, or |
@@ -31,27 +44,62 @@ | |||
31 | #include <linux/err.h> | 44 | #include <linux/err.h> |
32 | #include <linux/mutex.h> | 45 | #include <linux/mutex.h> |
33 | #include <linux/sysfs.h> | 46 | #include <linux/sysfs.h> |
34 | #include "lm75.h" | 47 | #include <linux/kernel.h> |
35 | 48 | ||
36 | /* Addresses to scan */ | 49 | /* Supported devices */ |
37 | static const unsigned short normal_i2c[] = { 0x48, 0x49, 0x4a, 0x4b, 0x4c, | 50 | enum chips { ds1621, ds1625, ds1631, ds1721, ds1731 }; |
38 | 0x4d, 0x4e, 0x4f, I2C_CLIENT_END }; | ||
39 | 51 | ||
40 | /* Insmod parameters */ | 52 | /* Insmod parameters */ |
41 | static int polarity = -1; | 53 | static int polarity = -1; |
42 | module_param(polarity, int, 0); | 54 | module_param(polarity, int, 0); |
43 | MODULE_PARM_DESC(polarity, "Output's polarity: 0 = active high, 1 = active low"); | 55 | MODULE_PARM_DESC(polarity, "Output's polarity: 0 = active high, 1 = active low"); |
44 | 56 | ||
45 | /* Many DS1621 constants specified below */ | 57 | /* |
46 | /* Config register used for detection */ | 58 | * The Configuration/Status register |
47 | /* 7 6 5 4 3 2 1 0 */ | 59 | * |
48 | /* |Done|THF |TLF |NVB | X | X |POL |1SHOT| */ | 60 | * - DS1621: |
61 | * 7 6 5 4 3 2 1 0 | ||
62 | * |Done|THF |TLF |NVB | X | X |POL |1SHOT| | ||
63 | * | ||
64 | * - DS1625: | ||
65 | * 7 6 5 4 3 2 1 0 | ||
66 | * |Done|THF |TLF |NVB | 1 | 0 |POL |1SHOT| | ||
67 | * | ||
68 | * - DS1631, DS1731: | ||
69 | * 7 6 5 4 3 2 1 0 | ||
70 | * |Done|THF |TLF |NVB | R1 | R0 |POL |1SHOT| | ||
71 | * | ||
72 | * - DS1721: | ||
73 | * 7 6 5 4 3 2 1 0 | ||
74 | * |Done| X | X | U | R1 | R0 |POL |1SHOT| | ||
75 | * | ||
76 | * Where: | ||
77 | * - 'X' is Reserved | ||
78 | * - 'U' is Undefined | ||
79 | */ | ||
49 | #define DS1621_REG_CONFIG_NVB 0x10 | 80 | #define DS1621_REG_CONFIG_NVB 0x10 |
81 | #define DS1621_REG_CONFIG_RESOL 0x0C | ||
50 | #define DS1621_REG_CONFIG_POLARITY 0x02 | 82 | #define DS1621_REG_CONFIG_POLARITY 0x02 |
51 | #define DS1621_REG_CONFIG_1SHOT 0x01 | 83 | #define DS1621_REG_CONFIG_1SHOT 0x01 |
52 | #define DS1621_REG_CONFIG_DONE 0x80 | 84 | #define DS1621_REG_CONFIG_DONE 0x80 |
53 | 85 | ||
54 | /* The DS1621 registers */ | 86 | #define DS1621_REG_CONFIG_RESOL_SHIFT 2 |
87 | |||
88 | /* ds1721 conversion rates: {C/LSB, time(ms), resolution bit setting} */ | ||
89 | static const unsigned short ds1721_convrates[] = { | ||
90 | 94, /* 9-bits (0.5, 93.75, RES[0..1] = 0 */ | ||
91 | 188, /* 10-bits (0.25, 187.5, RES[0..1] = 1 */ | ||
92 | 375, /* 11-bits (0.125, 375, RES[0..1] = 2 */ | ||
93 | 750, /* 12-bits (0.0625, 750, RES[0..1] = 3 */ | ||
94 | }; | ||
95 | |||
96 | #define DS1621_CONVERSION_MAX 750 | ||
97 | #define DS1625_CONVERSION_MAX 500 | ||
98 | |||
99 | #define DS1621_TEMP_MAX 125000 | ||
100 | #define DS1621_TEMP_MIN (-55000) | ||
101 | |||
102 | /* The DS1621 temperature registers */ | ||
55 | static const u8 DS1621_REG_TEMP[3] = { | 103 | static const u8 DS1621_REG_TEMP[3] = { |
56 | 0xAA, /* input, word, RO */ | 104 | 0xAA, /* input, word, RO */ |
57 | 0xA2, /* min, word, RW */ | 105 | 0xA2, /* min, word, RW */ |
@@ -59,6 +107,7 @@ static const u8 DS1621_REG_TEMP[3] = { | |||
59 | }; | 107 | }; |
60 | #define DS1621_REG_CONF 0xAC /* byte, RW */ | 108 | #define DS1621_REG_CONF 0xAC /* byte, RW */ |
61 | #define DS1621_COM_START 0xEE /* no data */ | 109 | #define DS1621_COM_START 0xEE /* no data */ |
110 | #define DS1721_COM_START 0x51 /* no data */ | ||
62 | #define DS1621_COM_STOP 0x22 /* no data */ | 111 | #define DS1621_COM_STOP 0x22 /* no data */ |
63 | 112 | ||
64 | /* The DS1621 configuration register */ | 113 | /* The DS1621 configuration register */ |
@@ -75,14 +124,37 @@ struct ds1621_data { | |||
75 | struct mutex update_lock; | 124 | struct mutex update_lock; |
76 | char valid; /* !=0 if following fields are valid */ | 125 | char valid; /* !=0 if following fields are valid */ |
77 | unsigned long last_updated; /* In jiffies */ | 126 | unsigned long last_updated; /* In jiffies */ |
127 | enum chips kind; /* device type */ | ||
78 | 128 | ||
79 | u16 temp[3]; /* Register values, word */ | 129 | u16 temp[3]; /* Register values, word */ |
80 | u8 conf; /* Register encoding, combined */ | 130 | u8 conf; /* Register encoding, combined */ |
131 | u8 zbits; /* Resolution encoded as number of | ||
132 | * zero bits */ | ||
133 | u16 update_interval; /* Conversion rate in milliseconds */ | ||
81 | }; | 134 | }; |
82 | 135 | ||
136 | static inline int DS1621_TEMP_FROM_REG(u16 reg) | ||
137 | { | ||
138 | return DIV_ROUND_CLOSEST(((s16)reg / 16) * 625, 10); | ||
139 | } | ||
140 | |||
141 | /* | ||
142 | * TEMP: 0.001C/bit (-55C to +125C) | ||
143 | * REG: | ||
144 | * - 1621, 1625: 0.5C/bit, 7 zero-bits | ||
145 | * - 1631, 1721, 1731: 0.0625C/bit, 4 zero-bits | ||
146 | */ | ||
147 | static inline u16 DS1621_TEMP_TO_REG(long temp, u8 zbits) | ||
148 | { | ||
149 | temp = clamp_val(temp, DS1621_TEMP_MIN, DS1621_TEMP_MAX); | ||
150 | temp = DIV_ROUND_CLOSEST(temp * (1 << (8 - zbits)), 1000) << zbits; | ||
151 | return temp; | ||
152 | } | ||
153 | |||
83 | static void ds1621_init_client(struct i2c_client *client) | 154 | static void ds1621_init_client(struct i2c_client *client) |
84 | { | 155 | { |
85 | u8 conf, new_conf; | 156 | u8 conf, new_conf, sreg, resol; |
157 | struct ds1621_data *data = i2c_get_clientdata(client); | ||
86 | 158 | ||
87 | new_conf = conf = i2c_smbus_read_byte_data(client, DS1621_REG_CONF); | 159 | new_conf = conf = i2c_smbus_read_byte_data(client, DS1621_REG_CONF); |
88 | /* switch to continuous conversion mode */ | 160 | /* switch to continuous conversion mode */ |
@@ -97,8 +169,30 @@ static void ds1621_init_client(struct i2c_client *client) | |||
97 | if (conf != new_conf) | 169 | if (conf != new_conf) |
98 | i2c_smbus_write_byte_data(client, DS1621_REG_CONF, new_conf); | 170 | i2c_smbus_write_byte_data(client, DS1621_REG_CONF, new_conf); |
99 | 171 | ||
172 | switch (data->kind) { | ||
173 | case ds1625: | ||
174 | data->update_interval = DS1625_CONVERSION_MAX; | ||
175 | data->zbits = 7; | ||
176 | sreg = DS1621_COM_START; | ||
177 | break; | ||
178 | case ds1631: | ||
179 | case ds1721: | ||
180 | case ds1731: | ||
181 | resol = (new_conf & DS1621_REG_CONFIG_RESOL) >> | ||
182 | DS1621_REG_CONFIG_RESOL_SHIFT; | ||
183 | data->update_interval = ds1721_convrates[resol]; | ||
184 | data->zbits = 7 - resol; | ||
185 | sreg = DS1721_COM_START; | ||
186 | break; | ||
187 | default: | ||
188 | data->update_interval = DS1621_CONVERSION_MAX; | ||
189 | data->zbits = 7; | ||
190 | sreg = DS1621_COM_START; | ||
191 | break; | ||
192 | } | ||
193 | |||
100 | /* start conversion */ | 194 | /* start conversion */ |
101 | i2c_smbus_write_byte(client, DS1621_COM_START); | 195 | i2c_smbus_write_byte(client, sreg); |
102 | } | 196 | } |
103 | 197 | ||
104 | static struct ds1621_data *ds1621_update_client(struct device *dev) | 198 | static struct ds1621_data *ds1621_update_client(struct device *dev) |
@@ -109,8 +203,8 @@ static struct ds1621_data *ds1621_update_client(struct device *dev) | |||
109 | 203 | ||
110 | mutex_lock(&data->update_lock); | 204 | mutex_lock(&data->update_lock); |
111 | 205 | ||
112 | if (time_after(jiffies, data->last_updated + HZ + HZ / 2) | 206 | if (time_after(jiffies, data->last_updated + data->update_interval) || |
113 | || !data->valid) { | 207 | !data->valid) { |
114 | int i; | 208 | int i; |
115 | 209 | ||
116 | dev_dbg(&client->dev, "Starting ds1621 update\n"); | 210 | dev_dbg(&client->dev, "Starting ds1621 update\n"); |
@@ -146,7 +240,7 @@ static ssize_t show_temp(struct device *dev, struct device_attribute *da, | |||
146 | struct sensor_device_attribute *attr = to_sensor_dev_attr(da); | 240 | struct sensor_device_attribute *attr = to_sensor_dev_attr(da); |
147 | struct ds1621_data *data = ds1621_update_client(dev); | 241 | struct ds1621_data *data = ds1621_update_client(dev); |
148 | return sprintf(buf, "%d\n", | 242 | return sprintf(buf, "%d\n", |
149 | LM75_TEMP_FROM_REG(data->temp[attr->index])); | 243 | DS1621_TEMP_FROM_REG(data->temp[attr->index])); |
150 | } | 244 | } |
151 | 245 | ||
152 | static ssize_t set_temp(struct device *dev, struct device_attribute *da, | 246 | static ssize_t set_temp(struct device *dev, struct device_attribute *da, |
@@ -163,7 +257,7 @@ static ssize_t set_temp(struct device *dev, struct device_attribute *da, | |||
163 | return err; | 257 | return err; |
164 | 258 | ||
165 | mutex_lock(&data->update_lock); | 259 | mutex_lock(&data->update_lock); |
166 | data->temp[attr->index] = LM75_TEMP_TO_REG(val); | 260 | data->temp[attr->index] = DS1621_TEMP_TO_REG(val, data->zbits); |
167 | i2c_smbus_write_word_swapped(client, DS1621_REG_TEMP[attr->index], | 261 | i2c_smbus_write_word_swapped(client, DS1621_REG_TEMP[attr->index], |
168 | data->temp[attr->index]); | 262 | data->temp[attr->index]); |
169 | mutex_unlock(&data->update_lock); | 263 | mutex_unlock(&data->update_lock); |
@@ -185,7 +279,47 @@ static ssize_t show_alarm(struct device *dev, struct device_attribute *da, | |||
185 | return sprintf(buf, "%d\n", !!(data->conf & attr->index)); | 279 | return sprintf(buf, "%d\n", !!(data->conf & attr->index)); |
186 | } | 280 | } |
187 | 281 | ||
282 | static ssize_t show_convrate(struct device *dev, struct device_attribute *da, | ||
283 | char *buf) | ||
284 | { | ||
285 | struct i2c_client *client = to_i2c_client(dev); | ||
286 | struct ds1621_data *data = i2c_get_clientdata(client); | ||
287 | return scnprintf(buf, PAGE_SIZE, "%hu\n", data->update_interval); | ||
288 | } | ||
289 | |||
290 | static ssize_t set_convrate(struct device *dev, struct device_attribute *da, | ||
291 | const char *buf, size_t count) | ||
292 | { | ||
293 | struct i2c_client *client = to_i2c_client(dev); | ||
294 | struct ds1621_data *data = i2c_get_clientdata(client); | ||
295 | unsigned long convrate; | ||
296 | s32 err; | ||
297 | int resol = 0; | ||
298 | |||
299 | err = kstrtoul(buf, 10, &convrate); | ||
300 | if (err) | ||
301 | return err; | ||
302 | |||
303 | /* Convert rate into resolution bits */ | ||
304 | while (resol < (ARRAY_SIZE(ds1721_convrates) - 1) && | ||
305 | convrate > ds1721_convrates[resol]) | ||
306 | resol++; | ||
307 | |||
308 | mutex_lock(&data->update_lock); | ||
309 | data->conf = i2c_smbus_read_byte_data(client, DS1621_REG_CONF); | ||
310 | data->conf &= ~DS1621_REG_CONFIG_RESOL; | ||
311 | data->conf |= (resol << DS1621_REG_CONFIG_RESOL_SHIFT); | ||
312 | i2c_smbus_write_byte_data(client, DS1621_REG_CONF, data->conf); | ||
313 | data->update_interval = ds1721_convrates[resol]; | ||
314 | mutex_unlock(&data->update_lock); | ||
315 | |||
316 | return count; | ||
317 | } | ||
318 | |||
188 | static DEVICE_ATTR(alarms, S_IRUGO, show_alarms, NULL); | 319 | static DEVICE_ATTR(alarms, S_IRUGO, show_alarms, NULL); |
320 | static DEVICE_ATTR(update_interval, S_IWUSR | S_IRUGO, show_convrate, | ||
321 | set_convrate); | ||
322 | |||
189 | static SENSOR_DEVICE_ATTR(temp1_input, S_IRUGO, show_temp, NULL, 0); | 323 | static SENSOR_DEVICE_ATTR(temp1_input, S_IRUGO, show_temp, NULL, 0); |
190 | static SENSOR_DEVICE_ATTR(temp1_min, S_IWUSR | S_IRUGO, show_temp, set_temp, 1); | 324 | static SENSOR_DEVICE_ATTR(temp1_min, S_IWUSR | S_IRUGO, show_temp, set_temp, 1); |
191 | static SENSOR_DEVICE_ATTR(temp1_max, S_IWUSR | S_IRUGO, show_temp, set_temp, 2); | 325 | static SENSOR_DEVICE_ATTR(temp1_max, S_IWUSR | S_IRUGO, show_temp, set_temp, 2); |
@@ -201,48 +335,29 @@ static struct attribute *ds1621_attributes[] = { | |||
201 | &sensor_dev_attr_temp1_min_alarm.dev_attr.attr, | 335 | &sensor_dev_attr_temp1_min_alarm.dev_attr.attr, |
202 | &sensor_dev_attr_temp1_max_alarm.dev_attr.attr, | 336 | &sensor_dev_attr_temp1_max_alarm.dev_attr.attr, |
203 | &dev_attr_alarms.attr, | 337 | &dev_attr_alarms.attr, |
338 | &dev_attr_update_interval.attr, | ||
204 | NULL | 339 | NULL |
205 | }; | 340 | }; |
206 | 341 | ||
207 | static const struct attribute_group ds1621_group = { | 342 | static umode_t ds1621_attribute_visible(struct kobject *kobj, |
208 | .attrs = ds1621_attributes, | 343 | struct attribute *attr, int index) |
209 | }; | ||
210 | |||
211 | |||
212 | /* Return 0 if detection is successful, -ENODEV otherwise */ | ||
213 | static int ds1621_detect(struct i2c_client *client, | ||
214 | struct i2c_board_info *info) | ||
215 | { | 344 | { |
216 | struct i2c_adapter *adapter = client->adapter; | 345 | struct device *dev = container_of(kobj, struct device, kobj); |
217 | int conf, temp; | 346 | struct i2c_client *client = to_i2c_client(dev); |
218 | int i; | 347 | struct ds1621_data *data = i2c_get_clientdata(client); |
219 | |||
220 | if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA | ||
221 | | I2C_FUNC_SMBUS_WORD_DATA | ||
222 | | I2C_FUNC_SMBUS_WRITE_BYTE)) | ||
223 | return -ENODEV; | ||
224 | |||
225 | /* | ||
226 | * Now, we do the remaining detection. It is lousy. | ||
227 | * | ||
228 | * The NVB bit should be low if no EEPROM write has been requested | ||
229 | * during the latest 10ms, which is highly improbable in our case. | ||
230 | */ | ||
231 | conf = i2c_smbus_read_byte_data(client, DS1621_REG_CONF); | ||
232 | if (conf < 0 || conf & DS1621_REG_CONFIG_NVB) | ||
233 | return -ENODEV; | ||
234 | /* The 7 lowest bits of a temperature should always be 0. */ | ||
235 | for (i = 0; i < ARRAY_SIZE(DS1621_REG_TEMP); i++) { | ||
236 | temp = i2c_smbus_read_word_data(client, DS1621_REG_TEMP[i]); | ||
237 | if (temp < 0 || (temp & 0x7f00)) | ||
238 | return -ENODEV; | ||
239 | } | ||
240 | |||
241 | strlcpy(info->type, "ds1621", I2C_NAME_SIZE); | ||
242 | 348 | ||
243 | return 0; | 349 | if (attr == &dev_attr_update_interval.attr) |
350 | if (data->kind == ds1621 || data->kind == ds1625) | ||
351 | /* shhh, we're hiding update_interval */ | ||
352 | return 0; | ||
353 | return attr->mode; | ||
244 | } | 354 | } |
245 | 355 | ||
356 | static const struct attribute_group ds1621_group = { | ||
357 | .attrs = ds1621_attributes, | ||
358 | .is_visible = ds1621_attribute_visible | ||
359 | }; | ||
360 | |||
246 | static int ds1621_probe(struct i2c_client *client, | 361 | static int ds1621_probe(struct i2c_client *client, |
247 | const struct i2c_device_id *id) | 362 | const struct i2c_device_id *id) |
248 | { | 363 | { |
@@ -257,6 +372,8 @@ static int ds1621_probe(struct i2c_client *client, | |||
257 | i2c_set_clientdata(client, data); | 372 | i2c_set_clientdata(client, data); |
258 | mutex_init(&data->update_lock); | 373 | mutex_init(&data->update_lock); |
259 | 374 | ||
375 | data->kind = id->driver_data; | ||
376 | |||
260 | /* Initialize the DS1621 chip */ | 377 | /* Initialize the DS1621 chip */ |
261 | ds1621_init_client(client); | 378 | ds1621_init_client(client); |
262 | 379 | ||
@@ -289,8 +406,11 @@ static int ds1621_remove(struct i2c_client *client) | |||
289 | } | 406 | } |
290 | 407 | ||
291 | static const struct i2c_device_id ds1621_id[] = { | 408 | static const struct i2c_device_id ds1621_id[] = { |
292 | { "ds1621", 0 }, | 409 | { "ds1621", ds1621 }, |
293 | { "ds1625", 0 }, | 410 | { "ds1625", ds1625 }, |
411 | { "ds1631", ds1631 }, | ||
412 | { "ds1721", ds1721 }, | ||
413 | { "ds1731", ds1731 }, | ||
294 | { } | 414 | { } |
295 | }; | 415 | }; |
296 | MODULE_DEVICE_TABLE(i2c, ds1621_id); | 416 | MODULE_DEVICE_TABLE(i2c, ds1621_id); |
@@ -304,8 +424,6 @@ static struct i2c_driver ds1621_driver = { | |||
304 | .probe = ds1621_probe, | 424 | .probe = ds1621_probe, |
305 | .remove = ds1621_remove, | 425 | .remove = ds1621_remove, |
306 | .id_table = ds1621_id, | 426 | .id_table = ds1621_id, |
307 | .detect = ds1621_detect, | ||
308 | .address_list = normal_i2c, | ||
309 | }; | 427 | }; |
310 | 428 | ||
311 | module_i2c_driver(ds1621_driver); | 429 | module_i2c_driver(ds1621_driver); |
diff --git a/drivers/hwmon/g762.c b/drivers/hwmon/g762.c new file mode 100644 index 000000000000..73adf01b0ef2 --- /dev/null +++ b/drivers/hwmon/g762.c | |||
@@ -0,0 +1,1149 @@ | |||
1 | /* | ||
2 | * g762 - Driver for the Global Mixed-mode Technology Inc. fan speed | ||
3 | * PWM controller chips from G762 family, i.e. G762 and G763 | ||
4 | * | ||
5 | * Copyright (C) 2013, Arnaud EBALARD <arno@natisbad.org> | ||
6 | * | ||
7 | * This work is based on a basic version for 2.6.31 kernel developed | ||
8 | * by Olivier Mouchet for LaCie. Updates and correction have been | ||
9 | * performed to run on recent kernels. Additional features, like the | ||
10 | * ability to configure various characteristics via .dts file or | ||
11 | * board init file have been added. Detailed datasheet on which this | ||
12 | * development is based is available here: | ||
13 | * | ||
14 | * http://natisbad.org/NAS/refs/GMT_EDS-762_763-080710-0.2.pdf | ||
15 | * | ||
16 | * Headers from previous developments have been kept below: | ||
17 | * | ||
18 | * Copyright (c) 2009 LaCie | ||
19 | * | ||
20 | * Author: Olivier Mouchet <olivier.mouchet@gmail.com> | ||
21 | * | ||
22 | * based on g760a code written by Herbert Valerio Riedel <hvr@gnu.org> | ||
23 | * Copyright (C) 2007 Herbert Valerio Riedel <hvr@gnu.org> | ||
24 | * | ||
25 | * g762: minimal datasheet available at: | ||
26 | * http://www.gmt.com.tw/product/datasheet/EDS-762_3.pdf | ||
27 | * | ||
28 | * This program is free software; you can redistribute it and/or modify | ||
29 | * it under the terms of the GNU General Public License as published by | ||
30 | * the Free Software Foundation; either version 2 of the License, or | ||
31 | * (at your option) any later version. | ||
32 | * | ||
33 | * This program is distributed in the hope that it will be useful, | ||
34 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
35 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
36 | * GNU General Public License for more details. | ||
37 | * | ||
38 | * You should have received a copy of the GNU General Public License | ||
39 | * along with this program; if not, write to the Free Software | ||
40 | * Foundation. | ||
41 | */ | ||
42 | |||
43 | #include <linux/device.h> | ||
44 | #include <linux/module.h> | ||
45 | #include <linux/init.h> | ||
46 | #include <linux/jiffies.h> | ||
47 | #include <linux/i2c.h> | ||
48 | #include <linux/hwmon.h> | ||
49 | #include <linux/hwmon-sysfs.h> | ||
50 | #include <linux/err.h> | ||
51 | #include <linux/mutex.h> | ||
52 | #include <linux/kernel.h> | ||
53 | #include <linux/clk.h> | ||
54 | #include <linux/of.h> | ||
55 | #include <linux/of_device.h> | ||
56 | #include <linux/platform_data/g762.h> | ||
57 | |||
58 | #define DRVNAME "g762" | ||
59 | |||
60 | static const struct i2c_device_id g762_id[] = { | ||
61 | { "g762", 0 }, | ||
62 | { "g763", 0 }, | ||
63 | { } | ||
64 | }; | ||
65 | MODULE_DEVICE_TABLE(i2c, g762_id); | ||
66 | |||
67 | enum g762_regs { | ||
68 | G762_REG_SET_CNT = 0x00, | ||
69 | G762_REG_ACT_CNT = 0x01, | ||
70 | G762_REG_FAN_STA = 0x02, | ||
71 | G762_REG_SET_OUT = 0x03, | ||
72 | G762_REG_FAN_CMD1 = 0x04, | ||
73 | G762_REG_FAN_CMD2 = 0x05, | ||
74 | }; | ||
75 | |||
76 | /* Config register bits */ | ||
77 | #define G762_REG_FAN_CMD1_DET_FAN_FAIL 0x80 /* enable fan_fail signal */ | ||
78 | #define G762_REG_FAN_CMD1_DET_FAN_OOC 0x40 /* enable fan_out_of_control */ | ||
79 | #define G762_REG_FAN_CMD1_OUT_MODE 0x20 /* out mode: PWM or DC */ | ||
80 | #define G762_REG_FAN_CMD1_FAN_MODE 0x10 /* fan mode: closed/open-loop */ | ||
81 | #define G762_REG_FAN_CMD1_CLK_DIV_ID1 0x08 /* clock divisor value */ | ||
82 | #define G762_REG_FAN_CMD1_CLK_DIV_ID0 0x04 | ||
83 | #define G762_REG_FAN_CMD1_PWM_POLARITY 0x02 /* PWM polarity */ | ||
84 | #define G762_REG_FAN_CMD1_PULSE_PER_REV 0x01 /* pulse per fan revolution */ | ||
85 | |||
86 | #define G762_REG_FAN_CMD2_GEAR_MODE_1 0x08 /* fan gear mode */ | ||
87 | #define G762_REG_FAN_CMD2_GEAR_MODE_0 0x04 | ||
88 | #define G762_REG_FAN_CMD2_FAN_STARTV_1 0x02 /* fan startup voltage */ | ||
89 | #define G762_REG_FAN_CMD2_FAN_STARTV_0 0x01 | ||
90 | |||
91 | #define G762_REG_FAN_STA_FAIL 0x02 /* fan fail */ | ||
92 | #define G762_REG_FAN_STA_OOC 0x01 /* fan out of control */ | ||
93 | |||
94 | /* Config register values */ | ||
95 | #define G762_OUT_MODE_PWM 1 | ||
96 | #define G762_OUT_MODE_DC 0 | ||
97 | |||
98 | #define G762_FAN_MODE_CLOSED_LOOP 2 | ||
99 | #define G762_FAN_MODE_OPEN_LOOP 1 | ||
100 | |||
101 | #define G762_PWM_POLARITY_NEGATIVE 1 | ||
102 | #define G762_PWM_POLARITY_POSITIVE 0 | ||
103 | |||
104 | /* Register data is read (and cached) at most once per second. */ | ||
105 | #define G762_UPDATE_INTERVAL HZ | ||
106 | |||
107 | /* | ||
108 | * Extract pulse count per fan revolution value (2 or 4) from given | ||
109 | * FAN_CMD1 register value. | ||
110 | */ | ||
111 | #define G762_PULSE_FROM_REG(reg) \ | ||
112 | ((((reg) & G762_REG_FAN_CMD1_PULSE_PER_REV) + 1) << 1) | ||
113 | |||
114 | /* | ||
115 | * Extract fan clock divisor (1, 2, 4 or 8) from given FAN_CMD1 | ||
116 | * register value. | ||
117 | */ | ||
118 | #define G762_CLKDIV_FROM_REG(reg) \ | ||
119 | (1 << (((reg) & (G762_REG_FAN_CMD1_CLK_DIV_ID0 | \ | ||
120 | G762_REG_FAN_CMD1_CLK_DIV_ID1)) >> 2)) | ||
121 | |||
122 | /* | ||
123 | * Extract fan gear mode multiplier value (0, 2 or 4) from given | ||
124 | * FAN_CMD2 register value. | ||
125 | */ | ||
126 | #define G762_GEARMULT_FROM_REG(reg) \ | ||
127 | (1 << (((reg) & (G762_REG_FAN_CMD2_GEAR_MODE_0 | \ | ||
128 | G762_REG_FAN_CMD2_GEAR_MODE_1)) >> 2)) | ||
129 | |||
130 | struct g762_data { | ||
131 | struct i2c_client *client; | ||
132 | struct device *hwmon_dev; | ||
133 | struct clk *clk; | ||
134 | |||
135 | /* update mutex */ | ||
136 | struct mutex update_lock; | ||
137 | |||
138 | /* board specific parameters. */ | ||
139 | u32 clk_freq; | ||
140 | |||
141 | /* g762 register cache */ | ||
142 | bool valid; | ||
143 | unsigned long last_updated; /* in jiffies */ | ||
144 | |||
145 | u8 set_cnt; /* controls fan rotation speed in closed-loop mode */ | ||
146 | u8 act_cnt; /* provides access to current fan RPM value */ | ||
147 | u8 fan_sta; /* bit 0: set when actual fan speed is more than | ||
148 | * 25% outside requested fan speed | ||
149 | * bit 1: set when no transition occurs on fan | ||
150 | * pin for 0.7s | ||
151 | */ | ||
152 | u8 set_out; /* controls fan rotation speed in open-loop mode */ | ||
153 | u8 fan_cmd1; /* 0: FG_PLS_ID0 FG pulses count per revolution | ||
154 | * 0: 2 counts per revolution | ||
155 | * 1: 4 counts per revolution | ||
156 | * 1: PWM_POLARITY 1: negative_duty | ||
157 | * 0: positive_duty | ||
158 | * 2,3: [FG_CLOCK_ID0, FG_CLK_ID1] | ||
159 | * 00: Divide fan clock by 1 | ||
160 | * 01: Divide fan clock by 2 | ||
161 | * 10: Divide fan clock by 4 | ||
162 | * 11: Divide fan clock by 8 | ||
163 | * 4: FAN_MODE 1:closed-loop, 0:open-loop | ||
164 | * 5: OUT_MODE 1:PWM, 0:DC | ||
165 | * 6: DET_FAN_OOC enable "fan ooc" status | ||
166 | * 7: DET_FAN_FAIL enable "fan fail" status | ||
167 | */ | ||
168 | u8 fan_cmd2; /* 0,1: FAN_STARTV 0,1,2,3 -> 0,32,64,96 dac_code | ||
169 | * 2,3: FG_GEAR_MODE | ||
170 | * 00: multiplier = 1 | ||
171 | * 01: multiplier = 2 | ||
172 | * 10: multiplier = 4 | ||
173 | * 4: Mask ALERT# (g763 only) | ||
174 | */ | ||
175 | }; | ||
176 | |||
177 | /* | ||
178 | * Convert count value from fan controller register (FAN_SET_CNT) into fan | ||
179 | * speed RPM value. Note that the datasheet documents a basic formula; | ||
180 | * influence of additional parameters (fan clock divisor, fan gear mode) | ||
181 | * have been infered from examples in the datasheet and tests. | ||
182 | */ | ||
183 | static inline unsigned int rpm_from_cnt(u8 cnt, u32 clk_freq, u16 p, | ||
184 | u8 clk_div, u8 gear_mult) | ||
185 | { | ||
186 | if (cnt == 0xff) /* setting cnt to 255 stops the fan */ | ||
187 | return 0; | ||
188 | |||
189 | return (clk_freq * 30 * gear_mult) / ((cnt ? cnt : 1) * p * clk_div); | ||
190 | } | ||
191 | |||
192 | /* | ||
193 | * Convert fan RPM value from sysfs into count value for fan controller | ||
194 | * register (FAN_SET_CNT). | ||
195 | */ | ||
196 | static inline unsigned char cnt_from_rpm(u32 rpm, u32 clk_freq, u16 p, | ||
197 | u8 clk_div, u8 gear_mult) | ||
198 | { | ||
199 | if (!rpm) /* to stop the fan, set cnt to 255 */ | ||
200 | return 0xff; | ||
201 | |||
202 | return clamp_val(((clk_freq * 30 * gear_mult) / (rpm * p * clk_div)), | ||
203 | 0, 255); | ||
204 | } | ||
205 | |||
206 | /* helper to grab and cache data, at most one time per second */ | ||
207 | static struct g762_data *g762_update_client(struct device *dev) | ||
208 | { | ||
209 | struct i2c_client *client = to_i2c_client(dev); | ||
210 | struct g762_data *data = i2c_get_clientdata(client); | ||
211 | int ret = 0; | ||
212 | |||
213 | mutex_lock(&data->update_lock); | ||
214 | if (time_before(jiffies, data->last_updated + G762_UPDATE_INTERVAL) && | ||
215 | likely(data->valid)) | ||
216 | goto out; | ||
217 | |||
218 | ret = i2c_smbus_read_byte_data(client, G762_REG_SET_CNT); | ||
219 | if (ret < 0) | ||
220 | goto out; | ||
221 | data->set_cnt = ret; | ||
222 | |||
223 | ret = i2c_smbus_read_byte_data(client, G762_REG_ACT_CNT); | ||
224 | if (ret < 0) | ||
225 | goto out; | ||
226 | data->act_cnt = ret; | ||
227 | |||
228 | ret = i2c_smbus_read_byte_data(client, G762_REG_FAN_STA); | ||
229 | if (ret < 0) | ||
230 | goto out; | ||
231 | data->fan_sta = ret; | ||
232 | |||
233 | ret = i2c_smbus_read_byte_data(client, G762_REG_SET_OUT); | ||
234 | if (ret < 0) | ||
235 | goto out; | ||
236 | data->set_out = ret; | ||
237 | |||
238 | ret = i2c_smbus_read_byte_data(client, G762_REG_FAN_CMD1); | ||
239 | if (ret < 0) | ||
240 | goto out; | ||
241 | data->fan_cmd1 = ret; | ||
242 | |||
243 | ret = i2c_smbus_read_byte_data(client, G762_REG_FAN_CMD2); | ||
244 | if (ret < 0) | ||
245 | goto out; | ||
246 | data->fan_cmd2 = ret; | ||
247 | |||
248 | data->last_updated = jiffies; | ||
249 | data->valid = true; | ||
250 | out: | ||
251 | mutex_unlock(&data->update_lock); | ||
252 | |||
253 | if (ret < 0) /* upon error, encode it in return value */ | ||
254 | data = ERR_PTR(ret); | ||
255 | |||
256 | return data; | ||
257 | } | ||
258 | |||
259 | /* helpers for writing hardware parameters */ | ||
260 | |||
261 | /* | ||
262 | * Set input clock frequency received on CLK pin of the chip. Accepted values | ||
263 | * are between 0 and 0xffffff. If zero is given, then default frequency | ||
264 | * (32,768Hz) is used. Note that clock frequency is a characteristic of the | ||
265 | * system but an internal parameter, i.e. value is not passed to the device. | ||
266 | */ | ||
267 | static int do_set_clk_freq(struct device *dev, unsigned long val) | ||
268 | { | ||
269 | struct i2c_client *client = to_i2c_client(dev); | ||
270 | struct g762_data *data = i2c_get_clientdata(client); | ||
271 | |||
272 | if (val > 0xffffff) | ||
273 | return -EINVAL; | ||
274 | if (!val) | ||
275 | val = 32768; | ||
276 | |||
277 | data->clk_freq = val; | ||
278 | |||
279 | return 0; | ||
280 | } | ||
281 | |||
282 | /* Set pwm mode. Accepts either 0 (PWM mode) or 1 (DC mode) */ | ||
283 | static int do_set_pwm_mode(struct device *dev, unsigned long val) | ||
284 | { | ||
285 | struct i2c_client *client = to_i2c_client(dev); | ||
286 | struct g762_data *data = g762_update_client(dev); | ||
287 | int ret; | ||
288 | |||
289 | if (IS_ERR(data)) | ||
290 | return PTR_ERR(data); | ||
291 | |||
292 | mutex_lock(&data->update_lock); | ||
293 | switch (val) { | ||
294 | case G762_OUT_MODE_PWM: | ||
295 | data->fan_cmd1 |= G762_REG_FAN_CMD1_OUT_MODE; | ||
296 | break; | ||
297 | case G762_OUT_MODE_DC: | ||
298 | data->fan_cmd1 &= ~G762_REG_FAN_CMD1_OUT_MODE; | ||
299 | break; | ||
300 | default: | ||
301 | ret = -EINVAL; | ||
302 | goto out; | ||
303 | } | ||
304 | ret = i2c_smbus_write_byte_data(client, G762_REG_FAN_CMD1, | ||
305 | data->fan_cmd1); | ||
306 | data->valid = false; | ||
307 | out: | ||
308 | mutex_unlock(&data->update_lock); | ||
309 | |||
310 | return ret; | ||
311 | } | ||
312 | |||
313 | /* Set fan clock divisor. Accepts either 1, 2, 4 or 8. */ | ||
314 | static int do_set_fan_div(struct device *dev, unsigned long val) | ||
315 | { | ||
316 | struct i2c_client *client = to_i2c_client(dev); | ||
317 | struct g762_data *data = g762_update_client(dev); | ||
318 | int ret; | ||
319 | |||
320 | if (IS_ERR(data)) | ||
321 | return PTR_ERR(data); | ||
322 | |||
323 | mutex_lock(&data->update_lock); | ||
324 | switch (val) { | ||
325 | case 1: | ||
326 | data->fan_cmd1 &= ~G762_REG_FAN_CMD1_CLK_DIV_ID0; | ||
327 | data->fan_cmd1 &= ~G762_REG_FAN_CMD1_CLK_DIV_ID1; | ||
328 | break; | ||
329 | case 2: | ||
330 | data->fan_cmd1 |= G762_REG_FAN_CMD1_CLK_DIV_ID0; | ||
331 | data->fan_cmd1 &= ~G762_REG_FAN_CMD1_CLK_DIV_ID1; | ||
332 | break; | ||
333 | case 4: | ||
334 | data->fan_cmd1 &= ~G762_REG_FAN_CMD1_CLK_DIV_ID0; | ||
335 | data->fan_cmd1 |= G762_REG_FAN_CMD1_CLK_DIV_ID1; | ||
336 | break; | ||
337 | case 8: | ||
338 | data->fan_cmd1 |= G762_REG_FAN_CMD1_CLK_DIV_ID0; | ||
339 | data->fan_cmd1 |= G762_REG_FAN_CMD1_CLK_DIV_ID1; | ||
340 | break; | ||
341 | default: | ||
342 | ret = -EINVAL; | ||
343 | goto out; | ||
344 | } | ||
345 | ret = i2c_smbus_write_byte_data(client, G762_REG_FAN_CMD1, | ||
346 | data->fan_cmd1); | ||
347 | data->valid = false; | ||
348 | out: | ||
349 | mutex_unlock(&data->update_lock); | ||
350 | |||
351 | return ret; | ||
352 | } | ||
353 | |||
354 | /* Set fan gear mode. Accepts either 0, 1 or 2. */ | ||
355 | static int do_set_fan_gear_mode(struct device *dev, unsigned long val) | ||
356 | { | ||
357 | struct i2c_client *client = to_i2c_client(dev); | ||
358 | struct g762_data *data = g762_update_client(dev); | ||
359 | int ret; | ||
360 | |||
361 | if (IS_ERR(data)) | ||
362 | return PTR_ERR(data); | ||
363 | |||
364 | mutex_lock(&data->update_lock); | ||
365 | switch (val) { | ||
366 | case 0: | ||
367 | data->fan_cmd2 &= ~G762_REG_FAN_CMD2_GEAR_MODE_0; | ||
368 | data->fan_cmd2 &= ~G762_REG_FAN_CMD2_GEAR_MODE_1; | ||
369 | break; | ||
370 | case 1: | ||
371 | data->fan_cmd2 |= G762_REG_FAN_CMD2_GEAR_MODE_0; | ||
372 | data->fan_cmd2 &= ~G762_REG_FAN_CMD2_GEAR_MODE_1; | ||
373 | break; | ||
374 | case 2: | ||
375 | data->fan_cmd2 &= ~G762_REG_FAN_CMD2_GEAR_MODE_0; | ||
376 | data->fan_cmd2 |= G762_REG_FAN_CMD2_GEAR_MODE_1; | ||
377 | break; | ||
378 | default: | ||
379 | ret = -EINVAL; | ||
380 | goto out; | ||
381 | } | ||
382 | ret = i2c_smbus_write_byte_data(client, G762_REG_FAN_CMD2, | ||
383 | data->fan_cmd2); | ||
384 | data->valid = false; | ||
385 | out: | ||
386 | mutex_unlock(&data->update_lock); | ||
387 | |||
388 | return ret; | ||
389 | } | ||
390 | |||
391 | /* Set number of fan pulses per revolution. Accepts either 2 or 4. */ | ||
392 | static int do_set_fan_pulses(struct device *dev, unsigned long val) | ||
393 | { | ||
394 | struct i2c_client *client = to_i2c_client(dev); | ||
395 | struct g762_data *data = g762_update_client(dev); | ||
396 | int ret; | ||
397 | |||
398 | if (IS_ERR(data)) | ||
399 | return PTR_ERR(data); | ||
400 | |||
401 | mutex_lock(&data->update_lock); | ||
402 | switch (val) { | ||
403 | case 2: | ||
404 | data->fan_cmd1 &= ~G762_REG_FAN_CMD1_PULSE_PER_REV; | ||
405 | break; | ||
406 | case 4: | ||
407 | data->fan_cmd1 |= G762_REG_FAN_CMD1_PULSE_PER_REV; | ||
408 | break; | ||
409 | default: | ||
410 | ret = -EINVAL; | ||
411 | goto out; | ||
412 | } | ||
413 | ret = i2c_smbus_write_byte_data(client, G762_REG_FAN_CMD1, | ||
414 | data->fan_cmd1); | ||
415 | data->valid = false; | ||
416 | out: | ||
417 | mutex_unlock(&data->update_lock); | ||
418 | |||
419 | return ret; | ||
420 | } | ||
421 | |||
422 | /* Set fan mode. Accepts either 1 (open-loop) or 2 (closed-loop). */ | ||
423 | static int do_set_pwm_enable(struct device *dev, unsigned long val) | ||
424 | { | ||
425 | struct i2c_client *client = to_i2c_client(dev); | ||
426 | struct g762_data *data = g762_update_client(dev); | ||
427 | int ret; | ||
428 | |||
429 | if (IS_ERR(data)) | ||
430 | return PTR_ERR(data); | ||
431 | |||
432 | mutex_lock(&data->update_lock); | ||
433 | switch (val) { | ||
434 | case G762_FAN_MODE_CLOSED_LOOP: | ||
435 | data->fan_cmd1 |= G762_REG_FAN_CMD1_FAN_MODE; | ||
436 | break; | ||
437 | case G762_FAN_MODE_OPEN_LOOP: | ||
438 | data->fan_cmd1 &= ~G762_REG_FAN_CMD1_FAN_MODE; | ||
439 | /* | ||
440 | * BUG FIX: if SET_CNT register value is 255 then, for some | ||
441 | * unknown reason, fan will not rotate as expected, no matter | ||
442 | * the value of SET_OUT (to be specific, this seems to happen | ||
443 | * only in PWM mode). To workaround this bug, we give SET_CNT | ||
444 | * value of 254 if it is 255 when switching to open-loop. | ||
445 | */ | ||
446 | if (data->set_cnt == 0xff) | ||
447 | i2c_smbus_write_byte_data(client, G762_REG_SET_CNT, | ||
448 | 254); | ||
449 | break; | ||
450 | default: | ||
451 | ret = -EINVAL; | ||
452 | goto out; | ||
453 | } | ||
454 | |||
455 | ret = i2c_smbus_write_byte_data(client, G762_REG_FAN_CMD1, | ||
456 | data->fan_cmd1); | ||
457 | data->valid = false; | ||
458 | out: | ||
459 | mutex_unlock(&data->update_lock); | ||
460 | |||
461 | return ret; | ||
462 | } | ||
463 | |||
464 | /* Set PWM polarity. Accepts either 0 (positive duty) or 1 (negative duty) */ | ||
465 | static int do_set_pwm_polarity(struct device *dev, unsigned long val) | ||
466 | { | ||
467 | struct i2c_client *client = to_i2c_client(dev); | ||
468 | struct g762_data *data = g762_update_client(dev); | ||
469 | int ret; | ||
470 | |||
471 | if (IS_ERR(data)) | ||
472 | return PTR_ERR(data); | ||
473 | |||
474 | mutex_lock(&data->update_lock); | ||
475 | switch (val) { | ||
476 | case G762_PWM_POLARITY_POSITIVE: | ||
477 | data->fan_cmd1 &= ~G762_REG_FAN_CMD1_PWM_POLARITY; | ||
478 | break; | ||
479 | case G762_PWM_POLARITY_NEGATIVE: | ||
480 | data->fan_cmd1 |= G762_REG_FAN_CMD1_PWM_POLARITY; | ||
481 | break; | ||
482 | default: | ||
483 | ret = -EINVAL; | ||
484 | goto out; | ||
485 | } | ||
486 | ret = i2c_smbus_write_byte_data(client, G762_REG_FAN_CMD1, | ||
487 | data->fan_cmd1); | ||
488 | data->valid = false; | ||
489 | out: | ||
490 | mutex_unlock(&data->update_lock); | ||
491 | |||
492 | return ret; | ||
493 | } | ||
494 | |||
495 | /* | ||
496 | * Set pwm value. Accepts values between 0 (stops the fan) and | ||
497 | * 255 (full speed). This only makes sense in open-loop mode. | ||
498 | */ | ||
499 | static int do_set_pwm(struct device *dev, unsigned long val) | ||
500 | { | ||
501 | struct i2c_client *client = to_i2c_client(dev); | ||
502 | struct g762_data *data = i2c_get_clientdata(client); | ||
503 | int ret; | ||
504 | |||
505 | if (val > 255) | ||
506 | return -EINVAL; | ||
507 | |||
508 | mutex_lock(&data->update_lock); | ||
509 | ret = i2c_smbus_write_byte_data(client, G762_REG_SET_OUT, val); | ||
510 | data->valid = false; | ||
511 | mutex_unlock(&data->update_lock); | ||
512 | |||
513 | return ret; | ||
514 | } | ||
515 | |||
516 | /* | ||
517 | * Set fan RPM value. Can be called both in closed and open-loop mode | ||
518 | * but effect will only be seen after closed-loop mode is configured. | ||
519 | */ | ||
520 | static int do_set_fan_target(struct device *dev, unsigned long val) | ||
521 | { | ||
522 | struct i2c_client *client = to_i2c_client(dev); | ||
523 | struct g762_data *data = g762_update_client(dev); | ||
524 | int ret; | ||
525 | |||
526 | if (IS_ERR(data)) | ||
527 | return PTR_ERR(data); | ||
528 | |||
529 | mutex_lock(&data->update_lock); | ||
530 | data->set_cnt = cnt_from_rpm(val, data->clk_freq, | ||
531 | G762_PULSE_FROM_REG(data->fan_cmd1), | ||
532 | G762_CLKDIV_FROM_REG(data->fan_cmd1), | ||
533 | G762_GEARMULT_FROM_REG(data->fan_cmd2)); | ||
534 | ret = i2c_smbus_write_byte_data(client, G762_REG_SET_CNT, | ||
535 | data->set_cnt); | ||
536 | data->valid = false; | ||
537 | mutex_unlock(&data->update_lock); | ||
538 | |||
539 | return ret; | ||
540 | } | ||
541 | |||
542 | /* Set fan startup voltage. Accepted values are either 0, 1, 2 or 3. */ | ||
543 | static int do_set_fan_startv(struct device *dev, unsigned long val) | ||
544 | { | ||
545 | struct i2c_client *client = to_i2c_client(dev); | ||
546 | struct g762_data *data = g762_update_client(dev); | ||
547 | int ret; | ||
548 | |||
549 | if (IS_ERR(data)) | ||
550 | return PTR_ERR(data); | ||
551 | |||
552 | mutex_lock(&data->update_lock); | ||
553 | switch (val) { | ||
554 | case 0: | ||
555 | data->fan_cmd2 &= ~G762_REG_FAN_CMD2_FAN_STARTV_0; | ||
556 | data->fan_cmd2 &= ~G762_REG_FAN_CMD2_FAN_STARTV_1; | ||
557 | break; | ||
558 | case 1: | ||
559 | data->fan_cmd2 |= G762_REG_FAN_CMD2_FAN_STARTV_0; | ||
560 | data->fan_cmd2 &= ~G762_REG_FAN_CMD2_FAN_STARTV_1; | ||
561 | break; | ||
562 | case 2: | ||
563 | data->fan_cmd2 &= ~G762_REG_FAN_CMD2_FAN_STARTV_0; | ||
564 | data->fan_cmd2 |= G762_REG_FAN_CMD2_FAN_STARTV_1; | ||
565 | break; | ||
566 | case 3: | ||
567 | data->fan_cmd2 |= G762_REG_FAN_CMD2_FAN_STARTV_0; | ||
568 | data->fan_cmd2 |= G762_REG_FAN_CMD2_FAN_STARTV_1; | ||
569 | break; | ||
570 | default: | ||
571 | ret = -EINVAL; | ||
572 | goto out; | ||
573 | } | ||
574 | ret = i2c_smbus_write_byte_data(client, G762_REG_FAN_CMD2, | ||
575 | data->fan_cmd2); | ||
576 | data->valid = false; | ||
577 | out: | ||
578 | mutex_unlock(&data->update_lock); | ||
579 | |||
580 | return ret; | ||
581 | } | ||
582 | |||
583 | /* | ||
584 | * Helper to import hardware characteristics from .dts file and push | ||
585 | * those to the chip. | ||
586 | */ | ||
587 | |||
588 | #ifdef CONFIG_OF | ||
589 | static struct of_device_id g762_dt_match[] = { | ||
590 | { .compatible = "gmt,g762" }, | ||
591 | { .compatible = "gmt,g763" }, | ||
592 | { }, | ||
593 | }; | ||
594 | |||
595 | /* | ||
596 | * Grab clock (a required property), enable it, get (fixed) clock frequency | ||
597 | * and store it. Note: upon success, clock has been prepared and enabled; it | ||
598 | * must later be unprepared and disabled (e.g. during module unloading) by a | ||
599 | * call to g762_of_clock_disable(). Note that a reference to clock is kept | ||
600 | * in our private data structure to be used in this function. | ||
601 | */ | ||
602 | static int g762_of_clock_enable(struct i2c_client *client) | ||
603 | { | ||
604 | struct g762_data *data; | ||
605 | unsigned long clk_freq; | ||
606 | struct clk *clk; | ||
607 | int ret; | ||
608 | |||
609 | if (!client->dev.of_node) | ||
610 | return 0; | ||
611 | |||
612 | clk = of_clk_get(client->dev.of_node, 0); | ||
613 | if (IS_ERR(clk)) { | ||
614 | dev_err(&client->dev, "failed to get clock\n"); | ||
615 | return PTR_ERR(clk); | ||
616 | } | ||
617 | |||
618 | ret = clk_prepare_enable(clk); | ||
619 | if (ret) { | ||
620 | dev_err(&client->dev, "failed to enable clock\n"); | ||
621 | goto clk_put; | ||
622 | } | ||
623 | |||
624 | clk_freq = clk_get_rate(clk); | ||
625 | ret = do_set_clk_freq(&client->dev, clk_freq); | ||
626 | if (ret) { | ||
627 | dev_err(&client->dev, "invalid clock freq %lu\n", clk_freq); | ||
628 | goto clk_unprep; | ||
629 | } | ||
630 | |||
631 | data = i2c_get_clientdata(client); | ||
632 | data->clk = clk; | ||
633 | |||
634 | return 0; | ||
635 | |||
636 | clk_unprep: | ||
637 | clk_disable_unprepare(clk); | ||
638 | |||
639 | clk_put: | ||
640 | clk_put(clk); | ||
641 | |||
642 | return ret; | ||
643 | } | ||
644 | |||
645 | static void g762_of_clock_disable(struct i2c_client *client) | ||
646 | { | ||
647 | struct g762_data *data = i2c_get_clientdata(client); | ||
648 | |||
649 | if (!data->clk) | ||
650 | return; | ||
651 | |||
652 | clk_disable_unprepare(data->clk); | ||
653 | clk_put(data->clk); | ||
654 | } | ||
655 | |||
656 | static int g762_of_prop_import_one(struct i2c_client *client, | ||
657 | const char *pname, | ||
658 | int (*psetter)(struct device *dev, | ||
659 | unsigned long val)) | ||
660 | { | ||
661 | const __be32 *prop; | ||
662 | int len, ret; | ||
663 | u32 pval; | ||
664 | |||
665 | prop = of_get_property(client->dev.of_node, pname, &len); | ||
666 | if (!prop || len != sizeof(u32)) | ||
667 | return 0; | ||
668 | |||
669 | pval = be32_to_cpu(prop[0]); | ||
670 | dev_dbg(&client->dev, "found %s (%d)\n", pname, pval); | ||
671 | ret = (*psetter)(&client->dev, pval); | ||
672 | if (ret) | ||
673 | dev_err(&client->dev, "unable to set %s (%d)\n", pname, pval); | ||
674 | |||
675 | return ret; | ||
676 | } | ||
677 | |||
678 | static int g762_of_prop_import(struct i2c_client *client) | ||
679 | { | ||
680 | int ret; | ||
681 | |||
682 | if (!client->dev.of_node) | ||
683 | return 0; | ||
684 | |||
685 | ret = g762_of_prop_import_one(client, "fan_gear_mode", | ||
686 | do_set_fan_gear_mode); | ||
687 | if (ret) | ||
688 | return ret; | ||
689 | |||
690 | ret = g762_of_prop_import_one(client, "pwm_polarity", | ||
691 | do_set_pwm_polarity); | ||
692 | if (ret) | ||
693 | return ret; | ||
694 | |||
695 | return g762_of_prop_import_one(client, "fan_startv", | ||
696 | do_set_fan_startv); | ||
697 | } | ||
698 | |||
699 | #else | ||
700 | static int g762_of_prop_import(struct i2c_client *client) | ||
701 | { | ||
702 | return 0; | ||
703 | } | ||
704 | |||
705 | static int g762_of_clock_enable(struct i2c_client *client) | ||
706 | { | ||
707 | return 0; | ||
708 | } | ||
709 | |||
710 | static void g762_of_clock_disable(struct i2c_client *client) { } | ||
711 | #endif | ||
712 | |||
713 | /* | ||
714 | * Helper to import hardware characteristics from .dts file and push | ||
715 | * those to the chip. | ||
716 | */ | ||
717 | |||
718 | static int g762_pdata_prop_import(struct i2c_client *client) | ||
719 | { | ||
720 | struct g762_platform_data *pdata = client->dev.platform_data; | ||
721 | int ret; | ||
722 | |||
723 | if (!pdata) | ||
724 | return 0; | ||
725 | |||
726 | ret = do_set_fan_gear_mode(&client->dev, pdata->fan_gear_mode); | ||
727 | if (ret) | ||
728 | return ret; | ||
729 | |||
730 | ret = do_set_pwm_polarity(&client->dev, pdata->pwm_polarity); | ||
731 | if (ret) | ||
732 | return ret; | ||
733 | |||
734 | ret = do_set_fan_startv(&client->dev, pdata->fan_startv); | ||
735 | if (ret) | ||
736 | return ret; | ||
737 | |||
738 | return do_set_clk_freq(&client->dev, pdata->clk_freq); | ||
739 | } | ||
740 | |||
741 | /* | ||
742 | * sysfs attributes | ||
743 | */ | ||
744 | |||
745 | /* | ||
746 | * Read function for fan1_input sysfs file. Return current fan RPM value, or | ||
747 | * 0 if fan is out of control. | ||
748 | */ | ||
749 | static ssize_t get_fan_rpm(struct device *dev, struct device_attribute *da, | ||
750 | char *buf) | ||
751 | { | ||
752 | struct g762_data *data = g762_update_client(dev); | ||
753 | unsigned int rpm = 0; | ||
754 | |||
755 | if (IS_ERR(data)) | ||
756 | return PTR_ERR(data); | ||
757 | |||
758 | mutex_lock(&data->update_lock); | ||
759 | /* reverse logic: fan out of control reporting is enabled low */ | ||
760 | if (data->fan_sta & G762_REG_FAN_STA_OOC) { | ||
761 | rpm = rpm_from_cnt(data->act_cnt, data->clk_freq, | ||
762 | G762_PULSE_FROM_REG(data->fan_cmd1), | ||
763 | G762_CLKDIV_FROM_REG(data->fan_cmd1), | ||
764 | G762_GEARMULT_FROM_REG(data->fan_cmd2)); | ||
765 | } | ||
766 | mutex_unlock(&data->update_lock); | ||
767 | |||
768 | return sprintf(buf, "%u\n", rpm); | ||
769 | } | ||
770 | |||
771 | /* | ||
772 | * Read and write functions for pwm1_mode sysfs file. Get and set fan speed | ||
773 | * control mode i.e. PWM (1) or DC (0). | ||
774 | */ | ||
775 | static ssize_t get_pwm_mode(struct device *dev, struct device_attribute *da, | ||
776 | char *buf) | ||
777 | { | ||
778 | struct g762_data *data = g762_update_client(dev); | ||
779 | |||
780 | if (IS_ERR(data)) | ||
781 | return PTR_ERR(data); | ||
782 | |||
783 | return sprintf(buf, "%d\n", | ||
784 | !!(data->fan_cmd1 & G762_REG_FAN_CMD1_OUT_MODE)); | ||
785 | } | ||
786 | |||
787 | static ssize_t set_pwm_mode(struct device *dev, struct device_attribute *da, | ||
788 | const char *buf, size_t count) | ||
789 | { | ||
790 | unsigned long val; | ||
791 | int ret; | ||
792 | |||
793 | if (kstrtoul(buf, 10, &val)) | ||
794 | return -EINVAL; | ||
795 | |||
796 | ret = do_set_pwm_mode(dev, val); | ||
797 | if (ret < 0) | ||
798 | return ret; | ||
799 | |||
800 | return count; | ||
801 | } | ||
802 | |||
803 | /* | ||
804 | * Read and write functions for fan1_div sysfs file. Get and set fan | ||
805 | * controller prescaler value | ||
806 | */ | ||
807 | static ssize_t get_fan_div(struct device *dev, | ||
808 | struct device_attribute *da, char *buf) | ||
809 | { | ||
810 | struct g762_data *data = g762_update_client(dev); | ||
811 | |||
812 | if (IS_ERR(data)) | ||
813 | return PTR_ERR(data); | ||
814 | |||
815 | return sprintf(buf, "%d\n", G762_CLKDIV_FROM_REG(data->fan_cmd1)); | ||
816 | } | ||
817 | |||
818 | static ssize_t set_fan_div(struct device *dev, | ||
819 | struct device_attribute *da, | ||
820 | const char *buf, size_t count) | ||
821 | { | ||
822 | unsigned long val; | ||
823 | int ret; | ||
824 | |||
825 | if (kstrtoul(buf, 10, &val)) | ||
826 | return -EINVAL; | ||
827 | |||
828 | ret = do_set_fan_div(dev, val); | ||
829 | if (ret < 0) | ||
830 | return ret; | ||
831 | |||
832 | return count; | ||
833 | } | ||
834 | |||
835 | /* | ||
836 | * Read and write functions for fan1_pulses sysfs file. Get and set number | ||
837 | * of tachometer pulses per fan revolution. | ||
838 | */ | ||
839 | static ssize_t get_fan_pulses(struct device *dev, | ||
840 | struct device_attribute *da, char *buf) | ||
841 | { | ||
842 | struct g762_data *data = g762_update_client(dev); | ||
843 | |||
844 | if (IS_ERR(data)) | ||
845 | return PTR_ERR(data); | ||
846 | |||
847 | return sprintf(buf, "%d\n", G762_PULSE_FROM_REG(data->fan_cmd1)); | ||
848 | } | ||
849 | |||
850 | static ssize_t set_fan_pulses(struct device *dev, | ||
851 | struct device_attribute *da, | ||
852 | const char *buf, size_t count) | ||
853 | { | ||
854 | unsigned long val; | ||
855 | int ret; | ||
856 | |||
857 | if (kstrtoul(buf, 10, &val)) | ||
858 | return -EINVAL; | ||
859 | |||
860 | ret = do_set_fan_pulses(dev, val); | ||
861 | if (ret < 0) | ||
862 | return ret; | ||
863 | |||
864 | return count; | ||
865 | } | ||
866 | |||
867 | /* | ||
868 | * Read and write functions for pwm1_enable. Get and set fan speed control mode | ||
869 | * (i.e. closed or open-loop). | ||
870 | * | ||
871 | * Following documentation about hwmon's sysfs interface, a pwm1_enable node | ||
872 | * should accept followings: | ||
873 | * | ||
874 | * 0 : no fan speed control (i.e. fan at full speed) | ||
875 | * 1 : manual fan speed control enabled (use pwm[1-*]) (open-loop) | ||
876 | * 2+: automatic fan speed control enabled (use fan[1-*]_target) (closed-loop) | ||
877 | * | ||
878 | * but we do not accept 0 as this mode is not natively supported by the chip | ||
879 | * and it is not emulated by g762 driver. -EINVAL is returned in this case. | ||
880 | */ | ||
881 | static ssize_t get_pwm_enable(struct device *dev, | ||
882 | struct device_attribute *da, char *buf) | ||
883 | { | ||
884 | struct g762_data *data = g762_update_client(dev); | ||
885 | |||
886 | if (IS_ERR(data)) | ||
887 | return PTR_ERR(data); | ||
888 | |||
889 | return sprintf(buf, "%d\n", | ||
890 | (!!(data->fan_cmd1 & G762_REG_FAN_CMD1_FAN_MODE)) + 1); | ||
891 | } | ||
892 | |||
893 | static ssize_t set_pwm_enable(struct device *dev, | ||
894 | struct device_attribute *da, | ||
895 | const char *buf, size_t count) | ||
896 | { | ||
897 | unsigned long val; | ||
898 | int ret; | ||
899 | |||
900 | if (kstrtoul(buf, 10, &val)) | ||
901 | return -EINVAL; | ||
902 | |||
903 | ret = do_set_pwm_enable(dev, val); | ||
904 | if (ret < 0) | ||
905 | return ret; | ||
906 | |||
907 | return count; | ||
908 | } | ||
909 | |||
910 | /* | ||
911 | * Read and write functions for pwm1 sysfs file. Get and set pwm value | ||
912 | * (which affects fan speed) in open-loop mode. 0 stops the fan and 255 | ||
913 | * makes it run at full speed. | ||
914 | */ | ||
915 | static ssize_t get_pwm(struct device *dev, struct device_attribute *da, | ||
916 | char *buf) | ||
917 | { | ||
918 | struct g762_data *data = g762_update_client(dev); | ||
919 | |||
920 | if (IS_ERR(data)) | ||
921 | return PTR_ERR(data); | ||
922 | |||
923 | return sprintf(buf, "%d\n", data->set_out); | ||
924 | } | ||
925 | |||
926 | static ssize_t set_pwm(struct device *dev, struct device_attribute *da, | ||
927 | const char *buf, size_t count) | ||
928 | { | ||
929 | unsigned long val; | ||
930 | int ret; | ||
931 | |||
932 | if (kstrtoul(buf, 10, &val)) | ||
933 | return -EINVAL; | ||
934 | |||
935 | ret = do_set_pwm(dev, val); | ||
936 | if (ret < 0) | ||
937 | return ret; | ||
938 | |||
939 | return count; | ||
940 | } | ||
941 | |||
942 | /* | ||
943 | * Read and write function for fan1_target sysfs file. Get/set the fan speed in | ||
944 | * closed-loop mode. Speed is given as a RPM value; then the chip will regulate | ||
945 | * the fan speed using pulses from fan tachometer. | ||
946 | * | ||
947 | * Refer to rpm_from_cnt() implementation above to get info about count number | ||
948 | * calculation. | ||
949 | * | ||
950 | * Also note that due to rounding errors it is possible that you don't read | ||
951 | * back exactly the value you have set. | ||
952 | */ | ||
953 | static ssize_t get_fan_target(struct device *dev, struct device_attribute *da, | ||
954 | char *buf) | ||
955 | { | ||
956 | struct g762_data *data = g762_update_client(dev); | ||
957 | unsigned int rpm; | ||
958 | |||
959 | if (IS_ERR(data)) | ||
960 | return PTR_ERR(data); | ||
961 | |||
962 | mutex_lock(&data->update_lock); | ||
963 | rpm = rpm_from_cnt(data->set_cnt, data->clk_freq, | ||
964 | G762_PULSE_FROM_REG(data->fan_cmd1), | ||
965 | G762_CLKDIV_FROM_REG(data->fan_cmd1), | ||
966 | G762_GEARMULT_FROM_REG(data->fan_cmd2)); | ||
967 | mutex_unlock(&data->update_lock); | ||
968 | |||
969 | return sprintf(buf, "%u\n", rpm); | ||
970 | } | ||
971 | |||
972 | static ssize_t set_fan_target(struct device *dev, struct device_attribute *da, | ||
973 | const char *buf, size_t count) | ||
974 | { | ||
975 | unsigned long val; | ||
976 | int ret; | ||
977 | |||
978 | if (kstrtoul(buf, 10, &val)) | ||
979 | return -EINVAL; | ||
980 | |||
981 | ret = do_set_fan_target(dev, val); | ||
982 | if (ret < 0) | ||
983 | return ret; | ||
984 | |||
985 | return count; | ||
986 | } | ||
987 | |||
988 | /* read function for fan1_fault sysfs file. */ | ||
989 | static ssize_t get_fan_failure(struct device *dev, struct device_attribute *da, | ||
990 | char *buf) | ||
991 | { | ||
992 | struct g762_data *data = g762_update_client(dev); | ||
993 | |||
994 | if (IS_ERR(data)) | ||
995 | return PTR_ERR(data); | ||
996 | |||
997 | return sprintf(buf, "%u\n", !!(data->fan_sta & G762_REG_FAN_STA_FAIL)); | ||
998 | } | ||
999 | |||
1000 | /* | ||
1001 | * read function for fan1_alarm sysfs file. Note that OOC condition is | ||
1002 | * enabled low | ||
1003 | */ | ||
1004 | static ssize_t get_fan_ooc(struct device *dev, struct device_attribute *da, | ||
1005 | char *buf) | ||
1006 | { | ||
1007 | struct g762_data *data = g762_update_client(dev); | ||
1008 | |||
1009 | if (IS_ERR(data)) | ||
1010 | return PTR_ERR(data); | ||
1011 | |||
1012 | return sprintf(buf, "%u\n", !(data->fan_sta & G762_REG_FAN_STA_OOC)); | ||
1013 | } | ||
1014 | |||
1015 | static DEVICE_ATTR(pwm1, S_IWUSR | S_IRUGO, get_pwm, set_pwm); | ||
1016 | static DEVICE_ATTR(pwm1_mode, S_IWUSR | S_IRUGO, get_pwm_mode, set_pwm_mode); | ||
1017 | static DEVICE_ATTR(pwm1_enable, S_IWUSR | S_IRUGO, | ||
1018 | get_pwm_enable, set_pwm_enable); | ||
1019 | static DEVICE_ATTR(fan1_input, S_IRUGO, get_fan_rpm, NULL); | ||
1020 | static DEVICE_ATTR(fan1_alarm, S_IRUGO, get_fan_ooc, NULL); | ||
1021 | static DEVICE_ATTR(fan1_fault, S_IRUGO, get_fan_failure, NULL); | ||
1022 | static DEVICE_ATTR(fan1_target, S_IWUSR | S_IRUGO, | ||
1023 | get_fan_target, set_fan_target); | ||
1024 | static DEVICE_ATTR(fan1_div, S_IWUSR | S_IRUGO, get_fan_div, set_fan_div); | ||
1025 | static DEVICE_ATTR(fan1_pulses, S_IWUSR | S_IRUGO, | ||
1026 | get_fan_pulses, set_fan_pulses); | ||
1027 | |||
1028 | /* Driver data */ | ||
1029 | static struct attribute *g762_attributes[] = { | ||
1030 | &dev_attr_fan1_input.attr, | ||
1031 | &dev_attr_fan1_alarm.attr, | ||
1032 | &dev_attr_fan1_fault.attr, | ||
1033 | &dev_attr_fan1_target.attr, | ||
1034 | &dev_attr_fan1_div.attr, | ||
1035 | &dev_attr_fan1_pulses.attr, | ||
1036 | &dev_attr_pwm1.attr, | ||
1037 | &dev_attr_pwm1_mode.attr, | ||
1038 | &dev_attr_pwm1_enable.attr, | ||
1039 | NULL | ||
1040 | }; | ||
1041 | |||
1042 | static const struct attribute_group g762_group = { | ||
1043 | .attrs = g762_attributes, | ||
1044 | }; | ||
1045 | |||
1046 | /* | ||
1047 | * Enable both fan failure detection and fan out of control protection. The | ||
1048 | * function does not protect change/access to data structure; it must thus | ||
1049 | * only be called during initialization. | ||
1050 | */ | ||
1051 | static inline int g762_fan_init(struct device *dev) | ||
1052 | { | ||
1053 | struct i2c_client *client = to_i2c_client(dev); | ||
1054 | struct g762_data *data = g762_update_client(dev); | ||
1055 | |||
1056 | if (IS_ERR(data)) | ||
1057 | return PTR_ERR(data); | ||
1058 | |||
1059 | data->fan_cmd1 |= G762_REG_FAN_CMD1_DET_FAN_FAIL; | ||
1060 | data->fan_cmd1 |= G762_REG_FAN_CMD1_DET_FAN_OOC; | ||
1061 | data->valid = false; | ||
1062 | |||
1063 | return i2c_smbus_write_byte_data(client, G762_REG_FAN_CMD1, | ||
1064 | data->fan_cmd1); | ||
1065 | } | ||
1066 | |||
1067 | static int g762_probe(struct i2c_client *client, const struct i2c_device_id *id) | ||
1068 | { | ||
1069 | struct g762_data *data; | ||
1070 | int ret; | ||
1071 | |||
1072 | if (!i2c_check_functionality(client->adapter, | ||
1073 | I2C_FUNC_SMBUS_BYTE_DATA)) | ||
1074 | return -ENODEV; | ||
1075 | |||
1076 | data = devm_kzalloc(&client->dev, sizeof(struct g762_data), GFP_KERNEL); | ||
1077 | if (!data) | ||
1078 | return -ENOMEM; | ||
1079 | |||
1080 | i2c_set_clientdata(client, data); | ||
1081 | data->client = client; | ||
1082 | mutex_init(&data->update_lock); | ||
1083 | |||
1084 | /* Enable fan failure detection and fan out of control protection */ | ||
1085 | ret = g762_fan_init(&client->dev); | ||
1086 | if (ret) | ||
1087 | return ret; | ||
1088 | |||
1089 | /* Get configuration via DT ... */ | ||
1090 | ret = g762_of_clock_enable(client); | ||
1091 | if (ret) | ||
1092 | return ret; | ||
1093 | ret = g762_of_prop_import(client); | ||
1094 | if (ret) | ||
1095 | goto clock_dis; | ||
1096 | /* ... or platform_data */ | ||
1097 | ret = g762_pdata_prop_import(client); | ||
1098 | if (ret) | ||
1099 | goto clock_dis; | ||
1100 | |||
1101 | /* Register sysfs hooks */ | ||
1102 | ret = sysfs_create_group(&client->dev.kobj, &g762_group); | ||
1103 | if (ret) | ||
1104 | goto clock_dis; | ||
1105 | |||
1106 | data->hwmon_dev = hwmon_device_register(&client->dev); | ||
1107 | if (IS_ERR(data->hwmon_dev)) { | ||
1108 | ret = PTR_ERR(data->hwmon_dev); | ||
1109 | goto sysfs_rem; | ||
1110 | } | ||
1111 | |||
1112 | return 0; | ||
1113 | |||
1114 | sysfs_rem: | ||
1115 | sysfs_remove_group(&client->dev.kobj, &g762_group); | ||
1116 | |||
1117 | clock_dis: | ||
1118 | g762_of_clock_disable(client); | ||
1119 | |||
1120 | return ret; | ||
1121 | } | ||
1122 | |||
1123 | static int g762_remove(struct i2c_client *client) | ||
1124 | { | ||
1125 | struct g762_data *data = i2c_get_clientdata(client); | ||
1126 | |||
1127 | hwmon_device_unregister(data->hwmon_dev); | ||
1128 | sysfs_remove_group(&client->dev.kobj, &g762_group); | ||
1129 | g762_of_clock_disable(client); | ||
1130 | |||
1131 | return 0; | ||
1132 | } | ||
1133 | |||
1134 | static struct i2c_driver g762_driver = { | ||
1135 | .driver = { | ||
1136 | .name = DRVNAME, | ||
1137 | .owner = THIS_MODULE, | ||
1138 | .of_match_table = of_match_ptr(g762_dt_match), | ||
1139 | }, | ||
1140 | .probe = g762_probe, | ||
1141 | .remove = g762_remove, | ||
1142 | .id_table = g762_id, | ||
1143 | }; | ||
1144 | |||
1145 | module_i2c_driver(g762_driver); | ||
1146 | |||
1147 | MODULE_AUTHOR("Arnaud EBALARD <arno@natisbad.org>"); | ||
1148 | MODULE_DESCRIPTION("GMT G762/G763 driver"); | ||
1149 | MODULE_LICENSE("GPL"); | ||
diff --git a/drivers/hwmon/i5k_amb.c b/drivers/hwmon/i5k_amb.c index b87c2ccee06b..de058c278aa9 100644 --- a/drivers/hwmon/i5k_amb.c +++ b/drivers/hwmon/i5k_amb.c | |||
@@ -556,7 +556,6 @@ static int i5k_amb_probe(struct platform_device *pdev) | |||
556 | 556 | ||
557 | err_init_failed: | 557 | err_init_failed: |
558 | iounmap(data->amb_mmio); | 558 | iounmap(data->amb_mmio); |
559 | platform_set_drvdata(pdev, NULL); | ||
560 | err_map_failed: | 559 | err_map_failed: |
561 | release_mem_region(data->amb_base, data->amb_len); | 560 | release_mem_region(data->amb_base, data->amb_len); |
562 | err: | 561 | err: |
@@ -576,7 +575,6 @@ static int i5k_amb_remove(struct platform_device *pdev) | |||
576 | kfree(data->attrs); | 575 | kfree(data->attrs); |
577 | iounmap(data->amb_mmio); | 576 | iounmap(data->amb_mmio); |
578 | release_mem_region(data->amb_base, data->amb_len); | 577 | release_mem_region(data->amb_base, data->amb_len); |
579 | platform_set_drvdata(pdev, NULL); | ||
580 | kfree(data); | 578 | kfree(data); |
581 | return 0; | 579 | return 0; |
582 | } | 580 | } |
diff --git a/drivers/hwmon/iio_hwmon.c b/drivers/hwmon/iio_hwmon.c index 52b77afebde1..708081b68c6f 100644 --- a/drivers/hwmon/iio_hwmon.c +++ b/drivers/hwmon/iio_hwmon.c | |||
@@ -180,6 +180,7 @@ static struct of_device_id iio_hwmon_of_match[] = { | |||
180 | { .compatible = "iio-hwmon", }, | 180 | { .compatible = "iio-hwmon", }, |
181 | { } | 181 | { } |
182 | }; | 182 | }; |
183 | MODULE_DEVICE_TABLE(of, iio_hwmon_of_match); | ||
183 | 184 | ||
184 | static struct platform_driver __refdata iio_hwmon_driver = { | 185 | static struct platform_driver __refdata iio_hwmon_driver = { |
185 | .driver = { | 186 | .driver = { |
diff --git a/drivers/hwmon/ina2xx.c b/drivers/hwmon/ina2xx.c index 4958b2f89dce..d917a2d8c30f 100644 --- a/drivers/hwmon/ina2xx.c +++ b/drivers/hwmon/ina2xx.c | |||
@@ -34,6 +34,7 @@ | |||
34 | #include <linux/hwmon.h> | 34 | #include <linux/hwmon.h> |
35 | #include <linux/hwmon-sysfs.h> | 35 | #include <linux/hwmon-sysfs.h> |
36 | #include <linux/jiffies.h> | 36 | #include <linux/jiffies.h> |
37 | #include <linux/of.h> | ||
37 | 38 | ||
38 | #include <linux/platform_data/ina2xx.h> | 39 | #include <linux/platform_data/ina2xx.h> |
39 | 40 | ||
@@ -221,6 +222,7 @@ static int ina2xx_probe(struct i2c_client *client, | |||
221 | struct ina2xx_data *data; | 222 | struct ina2xx_data *data; |
222 | struct ina2xx_platform_data *pdata; | 223 | struct ina2xx_platform_data *pdata; |
223 | int ret; | 224 | int ret; |
225 | u32 val; | ||
224 | long shunt = 10000; /* default shunt value 10mOhms */ | 226 | long shunt = 10000; /* default shunt value 10mOhms */ |
225 | 227 | ||
226 | if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_WORD_DATA)) | 228 | if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_WORD_DATA)) |
@@ -234,6 +236,9 @@ static int ina2xx_probe(struct i2c_client *client, | |||
234 | pdata = | 236 | pdata = |
235 | (struct ina2xx_platform_data *)client->dev.platform_data; | 237 | (struct ina2xx_platform_data *)client->dev.platform_data; |
236 | shunt = pdata->shunt_uohms; | 238 | shunt = pdata->shunt_uohms; |
239 | } else if (!of_property_read_u32(client->dev.of_node, | ||
240 | "shunt-resistor", &val)) { | ||
241 | shunt = val; | ||
237 | } | 242 | } |
238 | 243 | ||
239 | if (shunt <= 0) | 244 | if (shunt <= 0) |
diff --git a/drivers/hwmon/nct6775.c b/drivers/hwmon/nct6775.c index 04638aee9039..99cec1825420 100644 --- a/drivers/hwmon/nct6775.c +++ b/drivers/hwmon/nct6775.c | |||
@@ -199,7 +199,7 @@ static const s8 NCT6775_ALARM_BITS[] = { | |||
199 | 0, 1, 2, 3, 8, 21, 20, 16, /* in0.. in7 */ | 199 | 0, 1, 2, 3, 8, 21, 20, 16, /* in0.. in7 */ |
200 | 17, -1, -1, -1, -1, -1, -1, /* in8..in14 */ | 200 | 17, -1, -1, -1, -1, -1, -1, /* in8..in14 */ |
201 | -1, /* unused */ | 201 | -1, /* unused */ |
202 | 6, 7, 11, 10, 23, /* fan1..fan5 */ | 202 | 6, 7, 11, -1, -1, /* fan1..fan5 */ |
203 | -1, -1, -1, /* unused */ | 203 | -1, -1, -1, /* unused */ |
204 | 4, 5, 13, -1, -1, -1, /* temp1..temp6 */ | 204 | 4, 5, 13, -1, -1, -1, /* temp1..temp6 */ |
205 | 12, -1 }; /* intrusion0, intrusion1 */ | 205 | 12, -1 }; /* intrusion0, intrusion1 */ |
@@ -625,6 +625,7 @@ struct nct6775_data { | |||
625 | u8 has_fan_min; /* some fans don't have min register */ | 625 | u8 has_fan_min; /* some fans don't have min register */ |
626 | bool has_fan_div; | 626 | bool has_fan_div; |
627 | 627 | ||
628 | u8 num_temp_alarms; /* 2 or 3 */ | ||
628 | u8 temp_fixed_num; /* 3 or 6 */ | 629 | u8 temp_fixed_num; /* 3 or 6 */ |
629 | u8 temp_type[NUM_TEMP_FIXED]; | 630 | u8 temp_type[NUM_TEMP_FIXED]; |
630 | s8 temp_offset[NUM_TEMP_FIXED]; | 631 | s8 temp_offset[NUM_TEMP_FIXED]; |
@@ -1193,6 +1194,42 @@ show_alarm(struct device *dev, struct device_attribute *attr, char *buf) | |||
1193 | (unsigned int)((data->alarms >> nr) & 0x01)); | 1194 | (unsigned int)((data->alarms >> nr) & 0x01)); |
1194 | } | 1195 | } |
1195 | 1196 | ||
1197 | static int find_temp_source(struct nct6775_data *data, int index, int count) | ||
1198 | { | ||
1199 | int source = data->temp_src[index]; | ||
1200 | int nr; | ||
1201 | |||
1202 | for (nr = 0; nr < count; nr++) { | ||
1203 | int src; | ||
1204 | |||
1205 | src = nct6775_read_value(data, | ||
1206 | data->REG_TEMP_SOURCE[nr]) & 0x1f; | ||
1207 | if (src == source) | ||
1208 | return nr; | ||
1209 | } | ||
1210 | return -1; | ||
1211 | } | ||
1212 | |||
1213 | static ssize_t | ||
1214 | show_temp_alarm(struct device *dev, struct device_attribute *attr, char *buf) | ||
1215 | { | ||
1216 | struct sensor_device_attribute *sattr = to_sensor_dev_attr(attr); | ||
1217 | struct nct6775_data *data = nct6775_update_device(dev); | ||
1218 | unsigned int alarm = 0; | ||
1219 | int nr; | ||
1220 | |||
1221 | /* | ||
1222 | * For temperatures, there is no fixed mapping from registers to alarm | ||
1223 | * bits. Alarm bits are determined by the temperature source mapping. | ||
1224 | */ | ||
1225 | nr = find_temp_source(data, sattr->index, data->num_temp_alarms); | ||
1226 | if (nr >= 0) { | ||
1227 | int bit = data->ALARM_BITS[nr + TEMP_ALARM_BASE]; | ||
1228 | alarm = (data->alarms >> bit) & 0x01; | ||
1229 | } | ||
1230 | return sprintf(buf, "%u\n", alarm); | ||
1231 | } | ||
1232 | |||
1196 | static SENSOR_DEVICE_ATTR_2(in0_input, S_IRUGO, show_in_reg, NULL, 0, 0); | 1233 | static SENSOR_DEVICE_ATTR_2(in0_input, S_IRUGO, show_in_reg, NULL, 0, 0); |
1197 | static SENSOR_DEVICE_ATTR_2(in1_input, S_IRUGO, show_in_reg, NULL, 1, 0); | 1234 | static SENSOR_DEVICE_ATTR_2(in1_input, S_IRUGO, show_in_reg, NULL, 1, 0); |
1198 | static SENSOR_DEVICE_ATTR_2(in2_input, S_IRUGO, show_in_reg, NULL, 2, 0); | 1235 | static SENSOR_DEVICE_ATTR_2(in2_input, S_IRUGO, show_in_reg, NULL, 2, 0); |
@@ -1874,22 +1911,18 @@ static struct sensor_device_attribute sda_temp_type[] = { | |||
1874 | }; | 1911 | }; |
1875 | 1912 | ||
1876 | static struct sensor_device_attribute sda_temp_alarm[] = { | 1913 | static struct sensor_device_attribute sda_temp_alarm[] = { |
1877 | SENSOR_ATTR(temp1_alarm, S_IRUGO, show_alarm, NULL, | 1914 | SENSOR_ATTR(temp1_alarm, S_IRUGO, show_temp_alarm, NULL, 0), |
1878 | TEMP_ALARM_BASE), | 1915 | SENSOR_ATTR(temp2_alarm, S_IRUGO, show_temp_alarm, NULL, 1), |
1879 | SENSOR_ATTR(temp2_alarm, S_IRUGO, show_alarm, NULL, | 1916 | SENSOR_ATTR(temp3_alarm, S_IRUGO, show_temp_alarm, NULL, 2), |
1880 | TEMP_ALARM_BASE + 1), | 1917 | SENSOR_ATTR(temp4_alarm, S_IRUGO, show_temp_alarm, NULL, 3), |
1881 | SENSOR_ATTR(temp3_alarm, S_IRUGO, show_alarm, NULL, | 1918 | SENSOR_ATTR(temp5_alarm, S_IRUGO, show_temp_alarm, NULL, 4), |
1882 | TEMP_ALARM_BASE + 2), | 1919 | SENSOR_ATTR(temp6_alarm, S_IRUGO, show_temp_alarm, NULL, 5), |
1883 | SENSOR_ATTR(temp4_alarm, S_IRUGO, show_alarm, NULL, | 1920 | SENSOR_ATTR(temp7_alarm, S_IRUGO, show_temp_alarm, NULL, 6), |
1884 | TEMP_ALARM_BASE + 3), | 1921 | SENSOR_ATTR(temp8_alarm, S_IRUGO, show_temp_alarm, NULL, 7), |
1885 | SENSOR_ATTR(temp5_alarm, S_IRUGO, show_alarm, NULL, | 1922 | SENSOR_ATTR(temp9_alarm, S_IRUGO, show_temp_alarm, NULL, 8), |
1886 | TEMP_ALARM_BASE + 4), | 1923 | SENSOR_ATTR(temp10_alarm, S_IRUGO, show_temp_alarm, NULL, 9), |
1887 | SENSOR_ATTR(temp6_alarm, S_IRUGO, show_alarm, NULL, | ||
1888 | TEMP_ALARM_BASE + 5), | ||
1889 | }; | 1924 | }; |
1890 | 1925 | ||
1891 | #define NUM_TEMP_ALARM ARRAY_SIZE(sda_temp_alarm) | ||
1892 | |||
1893 | static ssize_t | 1926 | static ssize_t |
1894 | show_pwm_mode(struct device *dev, struct device_attribute *attr, char *buf) | 1927 | show_pwm_mode(struct device *dev, struct device_attribute *attr, char *buf) |
1895 | { | 1928 | { |
@@ -3215,13 +3248,11 @@ static void nct6775_device_remove_files(struct device *dev) | |||
3215 | device_remove_file(dev, &sda_temp_max[i].dev_attr); | 3248 | device_remove_file(dev, &sda_temp_max[i].dev_attr); |
3216 | device_remove_file(dev, &sda_temp_max_hyst[i].dev_attr); | 3249 | device_remove_file(dev, &sda_temp_max_hyst[i].dev_attr); |
3217 | device_remove_file(dev, &sda_temp_crit[i].dev_attr); | 3250 | device_remove_file(dev, &sda_temp_crit[i].dev_attr); |
3251 | device_remove_file(dev, &sda_temp_alarm[i].dev_attr); | ||
3218 | if (!(data->have_temp_fixed & (1 << i))) | 3252 | if (!(data->have_temp_fixed & (1 << i))) |
3219 | continue; | 3253 | continue; |
3220 | device_remove_file(dev, &sda_temp_type[i].dev_attr); | 3254 | device_remove_file(dev, &sda_temp_type[i].dev_attr); |
3221 | device_remove_file(dev, &sda_temp_offset[i].dev_attr); | 3255 | device_remove_file(dev, &sda_temp_offset[i].dev_attr); |
3222 | if (i >= NUM_TEMP_ALARM) | ||
3223 | continue; | ||
3224 | device_remove_file(dev, &sda_temp_alarm[i].dev_attr); | ||
3225 | } | 3256 | } |
3226 | 3257 | ||
3227 | device_remove_file(dev, &sda_caseopen[0].dev_attr); | 3258 | device_remove_file(dev, &sda_caseopen[0].dev_attr); |
@@ -3419,6 +3450,7 @@ static int nct6775_probe(struct platform_device *pdev) | |||
3419 | data->auto_pwm_num = 6; | 3450 | data->auto_pwm_num = 6; |
3420 | data->has_fan_div = true; | 3451 | data->has_fan_div = true; |
3421 | data->temp_fixed_num = 3; | 3452 | data->temp_fixed_num = 3; |
3453 | data->num_temp_alarms = 3; | ||
3422 | 3454 | ||
3423 | data->ALARM_BITS = NCT6775_ALARM_BITS; | 3455 | data->ALARM_BITS = NCT6775_ALARM_BITS; |
3424 | 3456 | ||
@@ -3483,6 +3515,7 @@ static int nct6775_probe(struct platform_device *pdev) | |||
3483 | data->auto_pwm_num = 4; | 3515 | data->auto_pwm_num = 4; |
3484 | data->has_fan_div = false; | 3516 | data->has_fan_div = false; |
3485 | data->temp_fixed_num = 3; | 3517 | data->temp_fixed_num = 3; |
3518 | data->num_temp_alarms = 3; | ||
3486 | 3519 | ||
3487 | data->ALARM_BITS = NCT6776_ALARM_BITS; | 3520 | data->ALARM_BITS = NCT6776_ALARM_BITS; |
3488 | 3521 | ||
@@ -3547,6 +3580,7 @@ static int nct6775_probe(struct platform_device *pdev) | |||
3547 | data->auto_pwm_num = 4; | 3580 | data->auto_pwm_num = 4; |
3548 | data->has_fan_div = false; | 3581 | data->has_fan_div = false; |
3549 | data->temp_fixed_num = 6; | 3582 | data->temp_fixed_num = 6; |
3583 | data->num_temp_alarms = 2; | ||
3550 | 3584 | ||
3551 | data->ALARM_BITS = NCT6779_ALARM_BITS; | 3585 | data->ALARM_BITS = NCT6779_ALARM_BITS; |
3552 | 3586 | ||
@@ -3843,10 +3877,12 @@ static int nct6775_probe(struct platform_device *pdev) | |||
3843 | &sda_fan_input[i].dev_attr); | 3877 | &sda_fan_input[i].dev_attr); |
3844 | if (err) | 3878 | if (err) |
3845 | goto exit_remove; | 3879 | goto exit_remove; |
3846 | err = device_create_file(dev, | 3880 | if (data->ALARM_BITS[FAN_ALARM_BASE + i] >= 0) { |
3847 | &sda_fan_alarm[i].dev_attr); | 3881 | err = device_create_file(dev, |
3848 | if (err) | 3882 | &sda_fan_alarm[i].dev_attr); |
3849 | goto exit_remove; | 3883 | if (err) |
3884 | goto exit_remove; | ||
3885 | } | ||
3850 | if (data->kind != nct6776 && | 3886 | if (data->kind != nct6776 && |
3851 | data->kind != nct6779) { | 3887 | data->kind != nct6779) { |
3852 | err = device_create_file(dev, | 3888 | err = device_create_file(dev, |
@@ -3897,6 +3933,12 @@ static int nct6775_probe(struct platform_device *pdev) | |||
3897 | if (err) | 3933 | if (err) |
3898 | goto exit_remove; | 3934 | goto exit_remove; |
3899 | } | 3935 | } |
3936 | if (find_temp_source(data, i, data->num_temp_alarms) >= 0) { | ||
3937 | err = device_create_file(dev, | ||
3938 | &sda_temp_alarm[i].dev_attr); | ||
3939 | if (err) | ||
3940 | goto exit_remove; | ||
3941 | } | ||
3900 | if (!(data->have_temp_fixed & (1 << i))) | 3942 | if (!(data->have_temp_fixed & (1 << i))) |
3901 | continue; | 3943 | continue; |
3902 | err = device_create_file(dev, &sda_temp_type[i].dev_attr); | 3944 | err = device_create_file(dev, &sda_temp_type[i].dev_attr); |
@@ -3905,12 +3947,6 @@ static int nct6775_probe(struct platform_device *pdev) | |||
3905 | err = device_create_file(dev, &sda_temp_offset[i].dev_attr); | 3947 | err = device_create_file(dev, &sda_temp_offset[i].dev_attr); |
3906 | if (err) | 3948 | if (err) |
3907 | goto exit_remove; | 3949 | goto exit_remove; |
3908 | if (i >= NUM_TEMP_ALARM || | ||
3909 | data->ALARM_BITS[TEMP_ALARM_BASE + i] < 0) | ||
3910 | continue; | ||
3911 | err = device_create_file(dev, &sda_temp_alarm[i].dev_attr); | ||
3912 | if (err) | ||
3913 | goto exit_remove; | ||
3914 | } | 3950 | } |
3915 | 3951 | ||
3916 | for (i = 0; i < ARRAY_SIZE(sda_caseopen); i++) { | 3952 | for (i = 0; i < ARRAY_SIZE(sda_caseopen); i++) { |
diff --git a/drivers/hwmon/ntc_thermistor.c b/drivers/hwmon/ntc_thermistor.c index d6d640a733d5..830a842d796a 100644 --- a/drivers/hwmon/ntc_thermistor.c +++ b/drivers/hwmon/ntc_thermistor.c | |||
@@ -514,7 +514,6 @@ static int ntc_thermistor_remove(struct platform_device *pdev) | |||
514 | hwmon_device_unregister(data->hwmon_dev); | 514 | hwmon_device_unregister(data->hwmon_dev); |
515 | sysfs_remove_group(&data->dev->kobj, &ntc_attr_group); | 515 | sysfs_remove_group(&data->dev->kobj, &ntc_attr_group); |
516 | ntc_iio_channel_release(pdata); | 516 | ntc_iio_channel_release(pdata); |
517 | platform_set_drvdata(pdev, NULL); | ||
518 | 517 | ||
519 | return 0; | 518 | return 0; |
520 | } | 519 | } |
diff --git a/drivers/hwmon/w83627ehf.c b/drivers/hwmon/w83627ehf.c index 016027229e81..004801e6fbb9 100644 --- a/drivers/hwmon/w83627ehf.c +++ b/drivers/hwmon/w83627ehf.c | |||
@@ -2598,7 +2598,6 @@ static int w83627ehf_probe(struct platform_device *pdev) | |||
2598 | exit_remove: | 2598 | exit_remove: |
2599 | w83627ehf_device_remove_files(dev); | 2599 | w83627ehf_device_remove_files(dev); |
2600 | exit_release: | 2600 | exit_release: |
2601 | platform_set_drvdata(pdev, NULL); | ||
2602 | release_region(res->start, IOREGION_LENGTH); | 2601 | release_region(res->start, IOREGION_LENGTH); |
2603 | exit: | 2602 | exit: |
2604 | return err; | 2603 | return err; |
@@ -2611,7 +2610,6 @@ static int w83627ehf_remove(struct platform_device *pdev) | |||
2611 | hwmon_device_unregister(data->hwmon_dev); | 2610 | hwmon_device_unregister(data->hwmon_dev); |
2612 | w83627ehf_device_remove_files(&pdev->dev); | 2611 | w83627ehf_device_remove_files(&pdev->dev); |
2613 | release_region(data->addr, IOREGION_LENGTH); | 2612 | release_region(data->addr, IOREGION_LENGTH); |
2614 | platform_set_drvdata(pdev, NULL); | ||
2615 | 2613 | ||
2616 | return 0; | 2614 | return 0; |
2617 | } | 2615 | } |