diff options
author | Linus Torvalds <torvalds@woody.linux-foundation.org> | 2007-02-19 16:36:16 -0500 |
---|---|---|
committer | Linus Torvalds <torvalds@woody.linux-foundation.org> | 2007-02-19 16:36:16 -0500 |
commit | 42eaf0d8f2e7b8201afc00b0ebe1bd89ea51d42d (patch) | |
tree | a2c92841628fb7cf63a0df9ec6e7e4c8b8acdd19 | |
parent | 4935361766cc73949fe032cd157d314f288922ba (diff) | |
parent | 2219cd81a6cd186200606693b360c6429c003bb3 (diff) |
Merge branch 'hwmon-for-linus' of git://jdelvare.pck.nerim.net/jdelvare-2.6
* 'hwmon-for-linus' of git://jdelvare.pck.nerim.net/jdelvare-2.6:
hwmon/vt1211: Add probing of alternate config index port
hwmon/f71805f: Fix a race condition
hwmon/abituguru: Fix unchecked return status
hwmon: New driver for the Analog Devices ADM1029
hwmon/w83627ehf: Add support for the W83627DHG chip
hwmon: Use subsys_initcall
hwmon/lm70: Make lm70_remove a __devexit function
hwmon: Cleanup a bogus legacy comment
hwmon: Simplify the locking model of two drivers
hwmon: Drop unused mutexes in two drivers
hwmon/it87: Add PWM base frequency control
-rw-r--r-- | Documentation/hwmon/it87 | 10 | ||||
-rw-r--r-- | Documentation/hwmon/sysfs-interface | 15 | ||||
-rw-r--r-- | Documentation/hwmon/w83627ehf | 54 | ||||
-rw-r--r-- | MAINTAINERS | 6 | ||||
-rw-r--r-- | drivers/hwmon/Kconfig | 11 | ||||
-rw-r--r-- | drivers/hwmon/Makefile | 1 | ||||
-rw-r--r-- | drivers/hwmon/abituguru.c | 30 | ||||
-rw-r--r-- | drivers/hwmon/adm1026.c | 1 | ||||
-rw-r--r-- | drivers/hwmon/adm1029.c | 508 | ||||
-rw-r--r-- | drivers/hwmon/f71805f.c | 30 | ||||
-rw-r--r-- | drivers/hwmon/hwmon.c | 2 | ||||
-rw-r--r-- | drivers/hwmon/it87.c | 84 | ||||
-rw-r--r-- | drivers/hwmon/lm70.c | 2 | ||||
-rw-r--r-- | drivers/hwmon/lm78.c | 6 | ||||
-rw-r--r-- | drivers/hwmon/lm85.c | 8 | ||||
-rw-r--r-- | drivers/hwmon/sis5595.c | 6 | ||||
-rw-r--r-- | drivers/hwmon/via686a.c | 5 | ||||
-rw-r--r-- | drivers/hwmon/vt1211.c | 58 | ||||
-rw-r--r-- | drivers/hwmon/w83627ehf.c | 54 | ||||
-rw-r--r-- | drivers/hwmon/w83627hf.c | 5 | ||||
-rw-r--r-- | drivers/hwmon/w83781d.c | 10 |
21 files changed, 769 insertions, 137 deletions
diff --git a/Documentation/hwmon/it87 b/Documentation/hwmon/it87 index 74a80992d237..c0528d6f9ace 100644 --- a/Documentation/hwmon/it87 +++ b/Documentation/hwmon/it87 | |||
@@ -135,6 +135,16 @@ Give 0 for unused sensor. Any other value is invalid. To configure this at | |||
135 | startup, consult lm_sensors's /etc/sensors.conf. (2 = thermistor; | 135 | startup, consult lm_sensors's /etc/sensors.conf. (2 = thermistor; |
136 | 3 = thermal diode) | 136 | 3 = thermal diode) |
137 | 137 | ||
138 | |||
139 | Fan speed control | ||
140 | ----------------- | ||
141 | |||
138 | The fan speed control features are limited to manual PWM mode. Automatic | 142 | The fan speed control features are limited to manual PWM mode. Automatic |
139 | "Smart Guardian" mode control handling is not implemented. However | 143 | "Smart Guardian" mode control handling is not implemented. However |
140 | if you want to go for "manual mode" just write 1 to pwmN_enable. | 144 | if you want to go for "manual mode" just write 1 to pwmN_enable. |
145 | |||
146 | If you are only able to control the fan speed with very small PWM values, | ||
147 | try lowering the PWM base frequency (pwm1_freq). Depending on the fan, | ||
148 | it may give you a somewhat greater control range. The same frequency is | ||
149 | used to drive all fan outputs, which is why pwm2_freq and pwm3_freq are | ||
150 | read-only. | ||
diff --git a/Documentation/hwmon/sysfs-interface b/Documentation/hwmon/sysfs-interface index efef3b962cd3..d73d2e8c7534 100644 --- a/Documentation/hwmon/sysfs-interface +++ b/Documentation/hwmon/sysfs-interface | |||
@@ -166,16 +166,21 @@ pwm[1-*] Pulse width modulation fan control. | |||
166 | 166 | ||
167 | pwm[1-*]_enable | 167 | pwm[1-*]_enable |
168 | Switch PWM on and off. | 168 | Switch PWM on and off. |
169 | Not always present even if fan*_pwm is. | 169 | Not always present even if pwmN is. |
170 | 0: turn off | 170 | 0: turn off |
171 | 1: turn on in manual mode | 171 | 1: turn on in manual mode |
172 | 2+: turn on in automatic mode | 172 | 2+: turn on in automatic mode |
173 | Check individual chip documentation files for automatic mode details. | 173 | Check individual chip documentation files for automatic mode |
174 | details. | ||
174 | RW | 175 | RW |
175 | 176 | ||
176 | pwm[1-*]_mode | 177 | pwm[1-*]_mode 0: DC mode (direct current) |
177 | 0: DC mode | 178 | 1: PWM mode (pulse-width modulation) |
178 | 1: PWM mode | 179 | RW |
180 | |||
181 | pwm[1-*]_freq Base PWM frequency in Hz. | ||
182 | Only possibly available when pwmN_mode is PWM, but not always | ||
183 | present even then. | ||
179 | RW | 184 | RW |
180 | 185 | ||
181 | pwm[1-*]_auto_channels_temp | 186 | pwm[1-*]_auto_channels_temp |
diff --git a/Documentation/hwmon/w83627ehf b/Documentation/hwmon/w83627ehf index 8a15a7408753..030fac6cec7a 100644 --- a/Documentation/hwmon/w83627ehf +++ b/Documentation/hwmon/w83627ehf | |||
@@ -2,26 +2,29 @@ Kernel driver w83627ehf | |||
2 | ======================= | 2 | ======================= |
3 | 3 | ||
4 | Supported chips: | 4 | Supported chips: |
5 | * Winbond W83627EHF/EHG (ISA access ONLY) | 5 | * Winbond W83627EHF/EHG/DHG (ISA access ONLY) |
6 | Prefix: 'w83627ehf' | 6 | Prefix: 'w83627ehf' |
7 | Addresses scanned: ISA address retrieved from Super I/O registers | 7 | Addresses scanned: ISA address retrieved from Super I/O registers |
8 | Datasheet: http://www.winbond-usa.com/products/winbond_products/pdfs/PCIC/W83627EHF_%20W83627EHGb.pdf | 8 | Datasheet: |
9 | http://www.winbond-usa.com/products/winbond_products/pdfs/PCIC/W83627EHF_%20W83627EHGb.pdf | ||
10 | DHG datasheet confidential. | ||
9 | 11 | ||
10 | Authors: | 12 | Authors: |
11 | Jean Delvare <khali@linux-fr.org> | 13 | Jean Delvare <khali@linux-fr.org> |
12 | Yuan Mu (Winbond) | 14 | Yuan Mu (Winbond) |
13 | Rudolf Marek <r.marek@assembler.cz> | 15 | Rudolf Marek <r.marek@assembler.cz> |
16 | David Hubbard <david.c.hubbard@gmail.com> | ||
14 | 17 | ||
15 | Description | 18 | Description |
16 | ----------- | 19 | ----------- |
17 | 20 | ||
18 | This driver implements support for the Winbond W83627EHF and W83627EHG | 21 | This driver implements support for the Winbond W83627EHF, W83627EHG, and |
19 | super I/O chips. We will refer to them collectively as Winbond chips. | 22 | W83627DHG super I/O chips. We will refer to them collectively as Winbond chips. |
20 | 23 | ||
21 | The chips implement three temperature sensors, five fan rotation | 24 | The chips implement three temperature sensors, five fan rotation |
22 | speed sensors, ten analog voltage sensors, alarms with beep warnings (control | 25 | speed sensors, ten analog voltage sensors (only nine for the 627DHG), alarms |
23 | unimplemented), and some automatic fan regulation strategies (plus manual | 26 | with beep warnings (control unimplemented), and some automatic fan regulation |
24 | fan control mode). | 27 | strategies (plus manual fan control mode). |
25 | 28 | ||
26 | Temperatures are measured in degrees Celsius and measurement resolution is 1 | 29 | Temperatures are measured in degrees Celsius and measurement resolution is 1 |
27 | degC for temp1 and 0.5 degC for temp2 and temp3. An alarm is triggered when | 30 | degC for temp1 and 0.5 degC for temp2 and temp3. An alarm is triggered when |
@@ -55,6 +58,9 @@ prog -> pwm4 (the programmable setting is not supported by the driver) | |||
55 | /sys files | 58 | /sys files |
56 | ---------- | 59 | ---------- |
57 | 60 | ||
61 | name - this is a standard hwmon device entry. For the W83627EHF and W83627EHG, | ||
62 | it is set to "w83627ehf" and for the W83627DHG it is set to "w83627dhg" | ||
63 | |||
58 | pwm[1-4] - this file stores PWM duty cycle or DC value (fan speed) in range: | 64 | pwm[1-4] - this file stores PWM duty cycle or DC value (fan speed) in range: |
59 | 0 (stop) to 255 (full) | 65 | 0 (stop) to 255 (full) |
60 | 66 | ||
@@ -83,3 +89,37 @@ pwm[1-4]_stop_time - how many milliseconds [ms] must elapse to switch | |||
83 | 89 | ||
84 | Note: last two functions are influenced by other control bits, not yet exported | 90 | Note: last two functions are influenced by other control bits, not yet exported |
85 | by the driver, so a change might not have any effect. | 91 | by the driver, so a change might not have any effect. |
92 | |||
93 | Implementation Details | ||
94 | ---------------------- | ||
95 | |||
96 | Future driver development should bear in mind that the following registers have | ||
97 | different functions on the 627EHF and the 627DHG. Some registers also have | ||
98 | different power-on default values, but BIOS should already be loading | ||
99 | appropriate defaults. Note that bank selection must be performed as is currently | ||
100 | done in the driver for all register addresses. | ||
101 | |||
102 | 0x49: only on DHG, selects temperature source for AUX fan, CPU fan0 | ||
103 | 0x4a: not completely documented for the EHF and the DHG documentation assigns | ||
104 | different behavior to bits 7 and 6, including extending the temperature | ||
105 | input selection to SmartFan I, not just SmartFan III. Testing on the EHF | ||
106 | will reveal whether they are compatible or not. | ||
107 | |||
108 | 0x58: Chip ID: 0xa1=EHF 0xc1=DHG | ||
109 | 0x5e: only on DHG, has bits to enable "current mode" temperature detection and | ||
110 | critical temperature protection | ||
111 | 0x45b: only on EHF, bit 3, vin4 alarm (EHF supports 10 inputs, only 9 on DHG) | ||
112 | 0x552: only on EHF, vin4 | ||
113 | 0x558: only on EHF, vin4 high limit | ||
114 | 0x559: only on EHF, vin4 low limit | ||
115 | 0x6b: only on DHG, SYS fan critical temperature | ||
116 | 0x6c: only on DHG, CPU fan0 critical temperature | ||
117 | 0x6d: only on DHG, AUX fan critical temperature | ||
118 | 0x6e: only on DHG, CPU fan1 critical temperature | ||
119 | |||
120 | 0x50-0x55 and 0x650-0x657 are marked "Test Register" for the EHF, but "Reserved | ||
121 | Register" for the DHG | ||
122 | |||
123 | The DHG also supports PECI, where the DHG queries Intel CPU temperatures, and | ||
124 | the ICH8 southbridge gets that data via PECI from the DHG, so that the | ||
125 | southbridge drives the fans. And the DHG supports SST, a one-wire serial bus. | ||
diff --git a/MAINTAINERS b/MAINTAINERS index 270c6b006b91..6261597a1bce 100644 --- a/MAINTAINERS +++ b/MAINTAINERS | |||
@@ -275,6 +275,12 @@ M: khali@linux-fr.org | |||
275 | L: lm-sensors@lm-sensors.org | 275 | L: lm-sensors@lm-sensors.org |
276 | S: Maintained | 276 | S: Maintained |
277 | 277 | ||
278 | ADM1029 HARDWARE MONITOR DRIVER | ||
279 | P: Corentin Labbe | ||
280 | M: corentin.labbe@geomatys.fr | ||
281 | L: lm-sensors@lm-sensors.org | ||
282 | S: Maintained | ||
283 | |||
278 | ADT746X FAN DRIVER | 284 | ADT746X FAN DRIVER |
279 | P: Colin Leroy | 285 | P: Colin Leroy |
280 | M: colin@colino.net | 286 | M: colin@colino.net |
diff --git a/drivers/hwmon/Kconfig b/drivers/hwmon/Kconfig index 891ef6d0b1bf..c3d4856fb618 100644 --- a/drivers/hwmon/Kconfig +++ b/drivers/hwmon/Kconfig | |||
@@ -73,6 +73,17 @@ config SENSORS_ADM1026 | |||
73 | This driver can also be built as a module. If so, the module | 73 | This driver can also be built as a module. If so, the module |
74 | will be called adm1026. | 74 | will be called adm1026. |
75 | 75 | ||
76 | config SENSORS_ADM1029 | ||
77 | tristate "Analog Devices ADM1029" | ||
78 | depends on HWMON && I2C && EXPERIMENTAL | ||
79 | help | ||
80 | If you say yes here you get support for Analog Devices ADM1029 | ||
81 | sensor chip. | ||
82 | Very rare chip, please let us know you use it. | ||
83 | |||
84 | This driver can also be built as a module. If so, the module | ||
85 | will be called adm1029. | ||
86 | |||
76 | config SENSORS_ADM1031 | 87 | config SENSORS_ADM1031 |
77 | tristate "Analog Devices ADM1031 and compatibles" | 88 | tristate "Analog Devices ADM1031 and compatibles" |
78 | depends on HWMON && I2C && EXPERIMENTAL | 89 | depends on HWMON && I2C && EXPERIMENTAL |
diff --git a/drivers/hwmon/Makefile b/drivers/hwmon/Makefile index 31661124271e..4165c27a2f25 100644 --- a/drivers/hwmon/Makefile +++ b/drivers/hwmon/Makefile | |||
@@ -17,6 +17,7 @@ obj-$(CONFIG_SENSORS_ABITUGURU) += abituguru.o | |||
17 | obj-$(CONFIG_SENSORS_ADM1021) += adm1021.o | 17 | obj-$(CONFIG_SENSORS_ADM1021) += adm1021.o |
18 | obj-$(CONFIG_SENSORS_ADM1025) += adm1025.o | 18 | obj-$(CONFIG_SENSORS_ADM1025) += adm1025.o |
19 | obj-$(CONFIG_SENSORS_ADM1026) += adm1026.o | 19 | obj-$(CONFIG_SENSORS_ADM1026) += adm1026.o |
20 | obj-$(CONFIG_SENSORS_ADM1029) += adm1029.o | ||
20 | obj-$(CONFIG_SENSORS_ADM1031) += adm1031.o | 21 | obj-$(CONFIG_SENSORS_ADM1031) += adm1031.o |
21 | obj-$(CONFIG_SENSORS_ADM9240) += adm9240.o | 22 | obj-$(CONFIG_SENSORS_ADM9240) += adm9240.o |
22 | obj-$(CONFIG_SENSORS_AMS) += ams/ | 23 | obj-$(CONFIG_SENSORS_AMS) += ams/ |
diff --git a/drivers/hwmon/abituguru.c b/drivers/hwmon/abituguru.c index b1dc63e4ac7b..bede4d990ea6 100644 --- a/drivers/hwmon/abituguru.c +++ b/drivers/hwmon/abituguru.c | |||
@@ -1267,30 +1267,42 @@ static int __devinit abituguru_probe(struct platform_device *pdev) | |||
1267 | printk(KERN_INFO ABIT_UGURU_NAME ": found Abit uGuru\n"); | 1267 | printk(KERN_INFO ABIT_UGURU_NAME ": found Abit uGuru\n"); |
1268 | 1268 | ||
1269 | /* Register sysfs hooks */ | 1269 | /* Register sysfs hooks */ |
1270 | data->class_dev = hwmon_device_register(&pdev->dev); | ||
1271 | if (IS_ERR(data->class_dev)) { | ||
1272 | res = PTR_ERR(data->class_dev); | ||
1273 | goto abituguru_probe_error; | ||
1274 | } | ||
1275 | for (i = 0; i < sysfs_attr_i; i++) | 1270 | for (i = 0; i < sysfs_attr_i; i++) |
1276 | device_create_file(&pdev->dev, &data->sysfs_attr[i].dev_attr); | 1271 | if (device_create_file(&pdev->dev, |
1272 | &data->sysfs_attr[i].dev_attr)) | ||
1273 | goto abituguru_probe_error; | ||
1277 | for (i = 0; i < ARRAY_SIZE(abituguru_sysfs_attr); i++) | 1274 | for (i = 0; i < ARRAY_SIZE(abituguru_sysfs_attr); i++) |
1278 | device_create_file(&pdev->dev, | 1275 | if (device_create_file(&pdev->dev, |
1279 | &abituguru_sysfs_attr[i].dev_attr); | 1276 | &abituguru_sysfs_attr[i].dev_attr)) |
1277 | goto abituguru_probe_error; | ||
1280 | 1278 | ||
1281 | return 0; | 1279 | data->class_dev = hwmon_device_register(&pdev->dev); |
1280 | if (!IS_ERR(data->class_dev)) | ||
1281 | return 0; /* success */ | ||
1282 | 1282 | ||
1283 | res = PTR_ERR(data->class_dev); | ||
1283 | abituguru_probe_error: | 1284 | abituguru_probe_error: |
1285 | for (i = 0; data->sysfs_attr[i].dev_attr.attr.name; i++) | ||
1286 | device_remove_file(&pdev->dev, &data->sysfs_attr[i].dev_attr); | ||
1287 | for (i = 0; i < ARRAY_SIZE(abituguru_sysfs_attr); i++) | ||
1288 | device_remove_file(&pdev->dev, | ||
1289 | &abituguru_sysfs_attr[i].dev_attr); | ||
1284 | kfree(data); | 1290 | kfree(data); |
1285 | return res; | 1291 | return res; |
1286 | } | 1292 | } |
1287 | 1293 | ||
1288 | static int __devexit abituguru_remove(struct platform_device *pdev) | 1294 | static int __devexit abituguru_remove(struct platform_device *pdev) |
1289 | { | 1295 | { |
1296 | int i; | ||
1290 | struct abituguru_data *data = platform_get_drvdata(pdev); | 1297 | struct abituguru_data *data = platform_get_drvdata(pdev); |
1291 | 1298 | ||
1292 | platform_set_drvdata(pdev, NULL); | 1299 | platform_set_drvdata(pdev, NULL); |
1293 | hwmon_device_unregister(data->class_dev); | 1300 | hwmon_device_unregister(data->class_dev); |
1301 | for (i = 0; data->sysfs_attr[i].dev_attr.attr.name; i++) | ||
1302 | device_remove_file(&pdev->dev, &data->sysfs_attr[i].dev_attr); | ||
1303 | for (i = 0; i < ARRAY_SIZE(abituguru_sysfs_attr); i++) | ||
1304 | device_remove_file(&pdev->dev, | ||
1305 | &abituguru_sysfs_attr[i].dev_attr); | ||
1294 | kfree(data); | 1306 | kfree(data); |
1295 | 1307 | ||
1296 | return 0; | 1308 | return 0; |
diff --git a/drivers/hwmon/adm1026.c b/drivers/hwmon/adm1026.c index b4618b2705f7..ba80cd3258c6 100644 --- a/drivers/hwmon/adm1026.c +++ b/drivers/hwmon/adm1026.c | |||
@@ -261,7 +261,6 @@ struct pwm_data { | |||
261 | struct adm1026_data { | 261 | struct adm1026_data { |
262 | struct i2c_client client; | 262 | struct i2c_client client; |
263 | struct class_device *class_dev; | 263 | struct class_device *class_dev; |
264 | struct mutex lock; | ||
265 | enum chips type; | 264 | enum chips type; |
266 | 265 | ||
267 | struct mutex update_lock; | 266 | struct mutex update_lock; |
diff --git a/drivers/hwmon/adm1029.c b/drivers/hwmon/adm1029.c new file mode 100644 index 000000000000..73ce31b31511 --- /dev/null +++ b/drivers/hwmon/adm1029.c | |||
@@ -0,0 +1,508 @@ | |||
1 | /* | ||
2 | * adm1029.c - Part of lm_sensors, Linux kernel modules for hardware monitoring | ||
3 | * | ||
4 | * Copyright (C) 2006 Corentin LABBE <corentin.labbe@geomatys.fr> | ||
5 | * | ||
6 | * Based on LM83 Driver by Jean Delvare <khali@linux-fr.org> | ||
7 | * | ||
8 | * Give only processor, motherboard temperatures and fan tachs | ||
9 | * Very rare chip please let me know if you use it | ||
10 | * | ||
11 | * http://www.analog.com/UploadedFiles/Data_Sheets/ADM1029.pdf | ||
12 | * | ||
13 | * | ||
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 | ||
16 | * the Free Software Foundation version 2 of the License | ||
17 | * | ||
18 | * This program is distributed in the hope that it will be useful, | ||
19 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
20 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
21 | * GNU General Public License for more details. | ||
22 | * | ||
23 | * You should have received a copy of the GNU General Public License | ||
24 | * along with this program; if not, write to the Free Software | ||
25 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
26 | */ | ||
27 | |||
28 | #include <linux/module.h> | ||
29 | #include <linux/init.h> | ||
30 | #include <linux/slab.h> | ||
31 | #include <linux/jiffies.h> | ||
32 | #include <linux/i2c.h> | ||
33 | #include <linux/hwmon-sysfs.h> | ||
34 | #include <linux/hwmon.h> | ||
35 | #include <linux/err.h> | ||
36 | #include <linux/mutex.h> | ||
37 | |||
38 | /* | ||
39 | * Addresses to scan | ||
40 | */ | ||
41 | |||
42 | static unsigned short normal_i2c[] = { | ||
43 | 0x28, 0x29, 0x2a, | ||
44 | 0x2b, 0x2c, 0x2d, | ||
45 | 0x2e, 0x2f, I2C_CLIENT_END | ||
46 | }; | ||
47 | |||
48 | /* | ||
49 | * Insmod parameters | ||
50 | */ | ||
51 | |||
52 | I2C_CLIENT_INSMOD_1(adm1029); | ||
53 | |||
54 | /* | ||
55 | * The ADM1029 registers | ||
56 | * Manufacturer ID is 0x41 for Analog Devices | ||
57 | */ | ||
58 | |||
59 | #define ADM1029_REG_MAN_ID 0x0D | ||
60 | #define ADM1029_REG_CHIP_ID 0x0E | ||
61 | #define ADM1029_REG_CONFIG 0x01 | ||
62 | #define ADM1029_REG_NB_FAN_SUPPORT 0x02 | ||
63 | |||
64 | #define ADM1029_REG_TEMP_DEVICES_INSTALLED 0x06 | ||
65 | |||
66 | #define ADM1029_REG_LOCAL_TEMP 0xA0 | ||
67 | #define ADM1029_REG_REMOTE1_TEMP 0xA1 | ||
68 | #define ADM1029_REG_REMOTE2_TEMP 0xA2 | ||
69 | |||
70 | #define ADM1029_REG_LOCAL_TEMP_HIGH 0x90 | ||
71 | #define ADM1029_REG_REMOTE1_TEMP_HIGH 0x91 | ||
72 | #define ADM1029_REG_REMOTE2_TEMP_HIGH 0x92 | ||
73 | |||
74 | #define ADM1029_REG_LOCAL_TEMP_LOW 0x98 | ||
75 | #define ADM1029_REG_REMOTE1_TEMP_LOW 0x99 | ||
76 | #define ADM1029_REG_REMOTE2_TEMP_LOW 0x9A | ||
77 | |||
78 | #define ADM1029_REG_FAN1 0x70 | ||
79 | #define ADM1029_REG_FAN2 0x71 | ||
80 | |||
81 | #define ADM1029_REG_FAN1_MIN 0x78 | ||
82 | #define ADM1029_REG_FAN2_MIN 0x79 | ||
83 | |||
84 | #define ADM1029_REG_FAN1_CONFIG 0x68 | ||
85 | #define ADM1029_REG_FAN2_CONFIG 0x69 | ||
86 | |||
87 | #define TEMP_FROM_REG(val) ((val) * 1000) | ||
88 | |||
89 | #define DIV_FROM_REG(val) ( 1 << (((val) >> 6) - 1)) | ||
90 | |||
91 | /* Registers to be checked by adm1029_update_device() */ | ||
92 | static const u8 ADM1029_REG_TEMP[] = { | ||
93 | ADM1029_REG_LOCAL_TEMP, | ||
94 | ADM1029_REG_REMOTE1_TEMP, | ||
95 | ADM1029_REG_REMOTE2_TEMP, | ||
96 | ADM1029_REG_LOCAL_TEMP_HIGH, | ||
97 | ADM1029_REG_REMOTE1_TEMP_HIGH, | ||
98 | ADM1029_REG_REMOTE2_TEMP_HIGH, | ||
99 | ADM1029_REG_LOCAL_TEMP_LOW, | ||
100 | ADM1029_REG_REMOTE1_TEMP_LOW, | ||
101 | ADM1029_REG_REMOTE2_TEMP_LOW, | ||
102 | }; | ||
103 | |||
104 | static const u8 ADM1029_REG_FAN[] = { | ||
105 | ADM1029_REG_FAN1, | ||
106 | ADM1029_REG_FAN2, | ||
107 | ADM1029_REG_FAN1_MIN, | ||
108 | ADM1029_REG_FAN2_MIN, | ||
109 | }; | ||
110 | |||
111 | static const u8 ADM1029_REG_FAN_DIV[] = { | ||
112 | ADM1029_REG_FAN1_CONFIG, | ||
113 | ADM1029_REG_FAN2_CONFIG, | ||
114 | }; | ||
115 | |||
116 | /* | ||
117 | * Functions declaration | ||
118 | */ | ||
119 | |||
120 | static int adm1029_attach_adapter(struct i2c_adapter *adapter); | ||
121 | static int adm1029_detect(struct i2c_adapter *adapter, int address, int kind); | ||
122 | static int adm1029_detach_client(struct i2c_client *client); | ||
123 | static struct adm1029_data *adm1029_update_device(struct device *dev); | ||
124 | static int adm1029_init_client(struct i2c_client *client); | ||
125 | |||
126 | /* | ||
127 | * Driver data (common to all clients) | ||
128 | */ | ||
129 | |||
130 | static struct i2c_driver adm1029_driver = { | ||
131 | .driver = { | ||
132 | .name = "adm1029", | ||
133 | }, | ||
134 | .attach_adapter = adm1029_attach_adapter, | ||
135 | .detach_client = adm1029_detach_client, | ||
136 | }; | ||
137 | |||
138 | /* | ||
139 | * Client data (each client gets its own) | ||
140 | */ | ||
141 | |||
142 | struct adm1029_data { | ||
143 | struct i2c_client client; | ||
144 | struct class_device *class_dev; | ||
145 | struct mutex update_lock; | ||
146 | char valid; /* zero until following fields are valid */ | ||
147 | unsigned long last_updated; /* in jiffies */ | ||
148 | |||
149 | /* registers values, signed for temperature, unsigned for other stuff */ | ||
150 | s8 temp[ARRAY_SIZE(ADM1029_REG_TEMP)]; | ||
151 | u8 fan[ARRAY_SIZE(ADM1029_REG_FAN)]; | ||
152 | u8 fan_div[ARRAY_SIZE(ADM1029_REG_FAN_DIV)]; | ||
153 | }; | ||
154 | |||
155 | /* | ||
156 | * Sysfs stuff | ||
157 | */ | ||
158 | |||
159 | static ssize_t | ||
160 | show_temp(struct device *dev, struct device_attribute *devattr, char *buf) | ||
161 | { | ||
162 | struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); | ||
163 | struct adm1029_data *data = adm1029_update_device(dev); | ||
164 | return sprintf(buf, "%d\n", TEMP_FROM_REG(data->temp[attr->index])); | ||
165 | } | ||
166 | |||
167 | static ssize_t | ||
168 | show_fan(struct device *dev, struct device_attribute *devattr, char *buf) | ||
169 | { | ||
170 | struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); | ||
171 | struct adm1029_data *data = adm1029_update_device(dev); | ||
172 | u16 val; | ||
173 | if (data->fan[attr->index] == 0 || data->fan_div[attr->index] == 0 | ||
174 | || data->fan[attr->index] == 255) { | ||
175 | return sprintf(buf, "0\n"); | ||
176 | } | ||
177 | |||
178 | val = 1880 * 120 / DIV_FROM_REG(data->fan_div[attr->index]) | ||
179 | / data->fan[attr->index]; | ||
180 | return sprintf(buf, "%d\n", val); | ||
181 | } | ||
182 | |||
183 | static ssize_t | ||
184 | show_fan_div(struct device *dev, struct device_attribute *devattr, char *buf) | ||
185 | { | ||
186 | struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); | ||
187 | struct adm1029_data *data = adm1029_update_device(dev); | ||
188 | if (data->fan_div[attr->index] == 0) | ||
189 | return sprintf(buf, "0\n"); | ||
190 | return sprintf(buf, "%d\n", DIV_FROM_REG(data->fan_div[attr->index])); | ||
191 | } | ||
192 | |||
193 | static ssize_t set_fan_div(struct device *dev, | ||
194 | struct device_attribute *devattr, const char *buf, size_t count) | ||
195 | { | ||
196 | struct i2c_client *client = to_i2c_client(dev); | ||
197 | struct adm1029_data *data = i2c_get_clientdata(client); | ||
198 | struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); | ||
199 | long val = simple_strtol(buf, NULL, 10); | ||
200 | u8 reg; | ||
201 | |||
202 | mutex_lock(&data->update_lock); | ||
203 | |||
204 | /*Read actual config */ | ||
205 | reg = i2c_smbus_read_byte_data(client, | ||
206 | ADM1029_REG_FAN_DIV[attr->index]); | ||
207 | |||
208 | switch (val) { | ||
209 | case 1: | ||
210 | val = 1; | ||
211 | break; | ||
212 | case 2: | ||
213 | val = 2; | ||
214 | break; | ||
215 | case 4: | ||
216 | val = 3; | ||
217 | break; | ||
218 | default: | ||
219 | mutex_unlock(&data->update_lock); | ||
220 | dev_err(&client->dev, "fan_div value %ld not " | ||
221 | "supported. Choose one of 1, 2 or 4!\n", val); | ||
222 | return -EINVAL; | ||
223 | } | ||
224 | /* Update the value */ | ||
225 | reg = (reg & 0x3F) | (val << 6); | ||
226 | |||
227 | /* Write value */ | ||
228 | i2c_smbus_write_byte_data(client, | ||
229 | ADM1029_REG_FAN_DIV[attr->index], reg); | ||
230 | mutex_unlock(&data->update_lock); | ||
231 | |||
232 | return count; | ||
233 | } | ||
234 | |||
235 | /* | ||
236 | Access rights on sysfs, S_IRUGO stand for Is Readable by User, Group and Others | ||
237 | S_IWUSR stand for Is Writable by User | ||
238 | */ | ||
239 | static SENSOR_DEVICE_ATTR(temp1_input, S_IRUGO, show_temp, NULL, 0); | ||
240 | static SENSOR_DEVICE_ATTR(temp2_input, S_IRUGO, show_temp, NULL, 1); | ||
241 | static SENSOR_DEVICE_ATTR(temp3_input, S_IRUGO, show_temp, NULL, 2); | ||
242 | |||
243 | static SENSOR_DEVICE_ATTR(temp1_max, S_IRUGO, show_temp, NULL, 3); | ||
244 | static SENSOR_DEVICE_ATTR(temp2_max, S_IRUGO, show_temp, NULL, 4); | ||
245 | static SENSOR_DEVICE_ATTR(temp3_max, S_IRUGO, show_temp, NULL, 5); | ||
246 | |||
247 | static SENSOR_DEVICE_ATTR(temp1_min, S_IRUGO, show_temp, NULL, 6); | ||
248 | static SENSOR_DEVICE_ATTR(temp2_min, S_IRUGO, show_temp, NULL, 7); | ||
249 | static SENSOR_DEVICE_ATTR(temp3_min, S_IRUGO, show_temp, NULL, 8); | ||
250 | |||
251 | static SENSOR_DEVICE_ATTR(fan1_input, S_IRUGO, show_fan, NULL, 0); | ||
252 | static SENSOR_DEVICE_ATTR(fan2_input, S_IRUGO, show_fan, NULL, 1); | ||
253 | |||
254 | static SENSOR_DEVICE_ATTR(fan1_min, S_IRUGO, show_fan, NULL, 2); | ||
255 | static SENSOR_DEVICE_ATTR(fan2_min, S_IRUGO, show_fan, NULL, 3); | ||
256 | |||
257 | static SENSOR_DEVICE_ATTR(fan1_div, S_IRUGO | S_IWUSR, | ||
258 | show_fan_div, set_fan_div, 0); | ||
259 | static SENSOR_DEVICE_ATTR(fan2_div, S_IRUGO | S_IWUSR, | ||
260 | show_fan_div, set_fan_div, 1); | ||
261 | |||
262 | static struct attribute *adm1029_attributes[] = { | ||
263 | &sensor_dev_attr_temp1_input.dev_attr.attr, | ||
264 | &sensor_dev_attr_temp1_min.dev_attr.attr, | ||
265 | &sensor_dev_attr_temp1_max.dev_attr.attr, | ||
266 | &sensor_dev_attr_temp2_input.dev_attr.attr, | ||
267 | &sensor_dev_attr_temp2_min.dev_attr.attr, | ||
268 | &sensor_dev_attr_temp2_max.dev_attr.attr, | ||
269 | &sensor_dev_attr_temp3_input.dev_attr.attr, | ||
270 | &sensor_dev_attr_temp3_min.dev_attr.attr, | ||
271 | &sensor_dev_attr_temp3_max.dev_attr.attr, | ||
272 | &sensor_dev_attr_fan1_input.dev_attr.attr, | ||
273 | &sensor_dev_attr_fan2_input.dev_attr.attr, | ||
274 | &sensor_dev_attr_fan1_min.dev_attr.attr, | ||
275 | &sensor_dev_attr_fan2_min.dev_attr.attr, | ||
276 | &sensor_dev_attr_fan1_div.dev_attr.attr, | ||
277 | &sensor_dev_attr_fan2_div.dev_attr.attr, | ||
278 | NULL | ||
279 | }; | ||
280 | |||
281 | static const struct attribute_group adm1029_group = { | ||
282 | .attrs = adm1029_attributes, | ||
283 | }; | ||
284 | |||
285 | /* | ||
286 | * Real code | ||
287 | */ | ||
288 | |||
289 | static int adm1029_attach_adapter(struct i2c_adapter *adapter) | ||
290 | { | ||
291 | if (!(adapter->class & I2C_CLASS_HWMON)) | ||
292 | return 0; | ||
293 | return i2c_probe(adapter, &addr_data, adm1029_detect); | ||
294 | } | ||
295 | |||
296 | /* | ||
297 | * The following function does more than just detection. If detection | ||
298 | * succeeds, it also registers the new chip. | ||
299 | */ | ||
300 | |||
301 | static int adm1029_detect(struct i2c_adapter *adapter, int address, int kind) | ||
302 | { | ||
303 | struct i2c_client *client; | ||
304 | struct adm1029_data *data; | ||
305 | int err = 0; | ||
306 | const char *name = ""; | ||
307 | if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA)) | ||
308 | goto exit; | ||
309 | |||
310 | if (!(data = kzalloc(sizeof(struct adm1029_data), GFP_KERNEL))) { | ||
311 | err = -ENOMEM; | ||
312 | goto exit; | ||
313 | } | ||
314 | |||
315 | client = &data->client; | ||
316 | i2c_set_clientdata(client, data); | ||
317 | client->addr = address; | ||
318 | client->adapter = adapter; | ||
319 | client->driver = &adm1029_driver; | ||
320 | |||
321 | /* Now we do the detection and identification. A negative kind | ||
322 | * means that the driver was loaded with no force parameter | ||
323 | * (default), so we must both detect and identify the chip | ||
324 | * (actually there is only one possible kind of chip for now, adm1029). | ||
325 | * A zero kind means that the driver was loaded with the force | ||
326 | * parameter, the detection step shall be skipped. A positive kind | ||
327 | * means that the driver was loaded with the force parameter and a | ||
328 | * given kind of chip is requested, so both the detection and the | ||
329 | * identification steps are skipped. */ | ||
330 | |||
331 | /* Default to an adm1029 if forced */ | ||
332 | if (kind == 0) | ||
333 | kind = adm1029; | ||
334 | |||
335 | /* ADM1029 doesn't have CHIP ID, check just MAN ID | ||
336 | * For better detection we check also ADM1029_TEMP_DEVICES_INSTALLED, | ||
337 | * ADM1029_REG_NB_FAN_SUPPORT and compare it with possible values | ||
338 | * documented | ||
339 | */ | ||
340 | |||
341 | if (kind <= 0) { /* identification */ | ||
342 | u8 man_id, chip_id, temp_devices_installed, nb_fan_support; | ||
343 | |||
344 | man_id = i2c_smbus_read_byte_data(client, ADM1029_REG_MAN_ID); | ||
345 | chip_id = i2c_smbus_read_byte_data(client, ADM1029_REG_CHIP_ID); | ||
346 | temp_devices_installed = i2c_smbus_read_byte_data(client, | ||
347 | ADM1029_REG_TEMP_DEVICES_INSTALLED); | ||
348 | nb_fan_support = i2c_smbus_read_byte_data(client, | ||
349 | ADM1029_REG_NB_FAN_SUPPORT); | ||
350 | /* 0x41 is Analog Devices */ | ||
351 | if (man_id == 0x41 && (temp_devices_installed & 0xf9) == 0x01 | ||
352 | && nb_fan_support == 0x03) { | ||
353 | if ((chip_id & 0xF0) == 0x00) { | ||
354 | kind = adm1029; | ||
355 | } else { | ||
356 | /* There are no "official" CHIP ID, so actually | ||
357 | * we use Major/Minor revision for that */ | ||
358 | printk(KERN_INFO | ||
359 | "adm1029: Unknown major revision %x, " | ||
360 | "please let us know\n", chip_id); | ||
361 | } | ||
362 | } | ||
363 | |||
364 | if (kind <= 0) { /* identification failed */ | ||
365 | pr_debug("adm1029: Unsupported chip (man_id=0x%02X, " | ||
366 | "chip_id=0x%02X)\n", man_id, chip_id); | ||
367 | goto exit_free; | ||
368 | } | ||
369 | } | ||
370 | |||
371 | if (kind == adm1029) { | ||
372 | name = "adm1029"; | ||
373 | } | ||
374 | |||
375 | /* We can fill in the remaining client fields */ | ||
376 | strlcpy(client->name, name, I2C_NAME_SIZE); | ||
377 | mutex_init(&data->update_lock); | ||
378 | |||
379 | /* Tell the I2C layer a new client has arrived */ | ||
380 | if ((err = i2c_attach_client(client))) | ||
381 | goto exit_free; | ||
382 | |||
383 | /* | ||
384 | * Initialize the ADM1029 chip | ||
385 | * Check config register | ||
386 | */ | ||
387 | if (adm1029_init_client(client) == 0) | ||
388 | goto exit_detach; | ||
389 | |||
390 | /* Register sysfs hooks */ | ||
391 | if ((err = sysfs_create_group(&client->dev.kobj, &adm1029_group))) | ||
392 | goto exit_detach; | ||
393 | |||
394 | data->class_dev = hwmon_device_register(&client->dev); | ||
395 | if (IS_ERR(data->class_dev)) { | ||
396 | err = PTR_ERR(data->class_dev); | ||
397 | goto exit_remove_files; | ||
398 | } | ||
399 | |||
400 | return 0; | ||
401 | |||
402 | exit_remove_files: | ||
403 | sysfs_remove_group(&client->dev.kobj, &adm1029_group); | ||
404 | exit_detach: | ||
405 | i2c_detach_client(client); | ||
406 | exit_free: | ||
407 | kfree(data); | ||
408 | exit: | ||
409 | return err; | ||
410 | } | ||
411 | |||
412 | static int adm1029_init_client(struct i2c_client *client) | ||
413 | { | ||
414 | u8 config; | ||
415 | config = i2c_smbus_read_byte_data(client, ADM1029_REG_CONFIG); | ||
416 | if ((config & 0x10) == 0) { | ||
417 | i2c_smbus_write_byte_data(client, ADM1029_REG_CONFIG, | ||
418 | config | 0x10); | ||
419 | } | ||
420 | /* recheck config */ | ||
421 | config = i2c_smbus_read_byte_data(client, ADM1029_REG_CONFIG); | ||
422 | if ((config & 0x10) == 0) { | ||
423 | dev_err(&client->dev, "Initialization failed!\n"); | ||
424 | return 0; | ||
425 | } | ||
426 | return 1; | ||
427 | } | ||
428 | |||
429 | static int adm1029_detach_client(struct i2c_client *client) | ||
430 | { | ||
431 | struct adm1029_data *data = i2c_get_clientdata(client); | ||
432 | int err; | ||
433 | |||
434 | hwmon_device_unregister(data->class_dev); | ||
435 | sysfs_remove_group(&client->dev.kobj, &adm1029_group); | ||
436 | |||
437 | if ((err = i2c_detach_client(client))) | ||
438 | return err; | ||
439 | |||
440 | kfree(data); | ||
441 | return 0; | ||
442 | } | ||
443 | |||
444 | /* | ||
445 | function that update the status of the chips (temperature for exemple) | ||
446 | */ | ||
447 | static struct adm1029_data *adm1029_update_device(struct device *dev) | ||
448 | { | ||
449 | struct i2c_client *client = to_i2c_client(dev); | ||
450 | struct adm1029_data *data = i2c_get_clientdata(client); | ||
451 | |||
452 | mutex_lock(&data->update_lock); | ||
453 | /* | ||
454 | * Use the "cache" Luke, don't recheck values | ||
455 | * if there are already checked not a long time later | ||
456 | */ | ||
457 | if (time_after(jiffies, data->last_updated + HZ * 2) | ||
458 | || !data->valid) { | ||
459 | int nr; | ||
460 | |||
461 | dev_dbg(&client->dev, "Updating adm1029 data\n"); | ||
462 | |||
463 | for (nr = 0; nr < ARRAY_SIZE(ADM1029_REG_TEMP); nr++) { | ||
464 | data->temp[nr] = | ||
465 | i2c_smbus_read_byte_data(client, | ||
466 | ADM1029_REG_TEMP[nr]); | ||
467 | } | ||
468 | for (nr = 0; nr < ARRAY_SIZE(ADM1029_REG_FAN); nr++) { | ||
469 | data->fan[nr] = | ||
470 | i2c_smbus_read_byte_data(client, | ||
471 | ADM1029_REG_FAN[nr]); | ||
472 | } | ||
473 | for (nr = 0; nr < ARRAY_SIZE(ADM1029_REG_FAN_DIV); nr++) { | ||
474 | data->fan_div[nr] = | ||
475 | i2c_smbus_read_byte_data(client, | ||
476 | ADM1029_REG_FAN_DIV[nr]); | ||
477 | } | ||
478 | |||
479 | data->last_updated = jiffies; | ||
480 | data->valid = 1; | ||
481 | } | ||
482 | |||
483 | mutex_unlock(&data->update_lock); | ||
484 | |||
485 | return data; | ||
486 | } | ||
487 | |||
488 | /* | ||
489 | Common module stuff | ||
490 | */ | ||
491 | static int __init sensors_adm1029_init(void) | ||
492 | { | ||
493 | |||
494 | return i2c_add_driver(&adm1029_driver); | ||
495 | } | ||
496 | |||
497 | static void __exit sensors_adm1029_exit(void) | ||
498 | { | ||
499 | |||
500 | i2c_del_driver(&adm1029_driver); | ||
501 | } | ||
502 | |||
503 | MODULE_AUTHOR("Corentin LABBE <corentin.labbe@geomatys.fr>"); | ||
504 | MODULE_DESCRIPTION("adm1029 driver"); | ||
505 | MODULE_LICENSE("GPL v2"); | ||
506 | |||
507 | module_init(sensors_adm1029_init); | ||
508 | module_exit(sensors_adm1029_exit); | ||
diff --git a/drivers/hwmon/f71805f.c b/drivers/hwmon/f71805f.c index a272cae8f60e..7c2973487122 100644 --- a/drivers/hwmon/f71805f.c +++ b/drivers/hwmon/f71805f.c | |||
@@ -146,7 +146,6 @@ superio_exit(int base) | |||
146 | struct f71805f_data { | 146 | struct f71805f_data { |
147 | unsigned short addr; | 147 | unsigned short addr; |
148 | const char *name; | 148 | const char *name; |
149 | struct mutex lock; | ||
150 | struct class_device *class_dev; | 149 | struct class_device *class_dev; |
151 | 150 | ||
152 | struct mutex update_lock; | 151 | struct mutex update_lock; |
@@ -271,50 +270,42 @@ static inline u8 temp_to_reg(long val) | |||
271 | * Device I/O access | 270 | * Device I/O access |
272 | */ | 271 | */ |
273 | 272 | ||
273 | /* Must be called with data->update_lock held, except during initialization */ | ||
274 | static u8 f71805f_read8(struct f71805f_data *data, u8 reg) | 274 | static u8 f71805f_read8(struct f71805f_data *data, u8 reg) |
275 | { | 275 | { |
276 | u8 val; | ||
277 | |||
278 | mutex_lock(&data->lock); | ||
279 | outb(reg, data->addr + ADDR_REG_OFFSET); | 276 | outb(reg, data->addr + ADDR_REG_OFFSET); |
280 | val = inb(data->addr + DATA_REG_OFFSET); | 277 | return inb(data->addr + DATA_REG_OFFSET); |
281 | mutex_unlock(&data->lock); | ||
282 | |||
283 | return val; | ||
284 | } | 278 | } |
285 | 279 | ||
280 | /* Must be called with data->update_lock held, except during initialization */ | ||
286 | static void f71805f_write8(struct f71805f_data *data, u8 reg, u8 val) | 281 | static void f71805f_write8(struct f71805f_data *data, u8 reg, u8 val) |
287 | { | 282 | { |
288 | mutex_lock(&data->lock); | ||
289 | outb(reg, data->addr + ADDR_REG_OFFSET); | 283 | outb(reg, data->addr + ADDR_REG_OFFSET); |
290 | outb(val, data->addr + DATA_REG_OFFSET); | 284 | outb(val, data->addr + DATA_REG_OFFSET); |
291 | mutex_unlock(&data->lock); | ||
292 | } | 285 | } |
293 | 286 | ||
294 | /* It is important to read the MSB first, because doing so latches the | 287 | /* It is important to read the MSB first, because doing so latches the |
295 | value of the LSB, so we are sure both bytes belong to the same value. */ | 288 | value of the LSB, so we are sure both bytes belong to the same value. |
289 | Must be called with data->update_lock held, except during initialization */ | ||
296 | static u16 f71805f_read16(struct f71805f_data *data, u8 reg) | 290 | static u16 f71805f_read16(struct f71805f_data *data, u8 reg) |
297 | { | 291 | { |
298 | u16 val; | 292 | u16 val; |
299 | 293 | ||
300 | mutex_lock(&data->lock); | ||
301 | outb(reg, data->addr + ADDR_REG_OFFSET); | 294 | outb(reg, data->addr + ADDR_REG_OFFSET); |
302 | val = inb(data->addr + DATA_REG_OFFSET) << 8; | 295 | val = inb(data->addr + DATA_REG_OFFSET) << 8; |
303 | outb(++reg, data->addr + ADDR_REG_OFFSET); | 296 | outb(++reg, data->addr + ADDR_REG_OFFSET); |
304 | val |= inb(data->addr + DATA_REG_OFFSET); | 297 | val |= inb(data->addr + DATA_REG_OFFSET); |
305 | mutex_unlock(&data->lock); | ||
306 | 298 | ||
307 | return val; | 299 | return val; |
308 | } | 300 | } |
309 | 301 | ||
302 | /* Must be called with data->update_lock held, except during initialization */ | ||
310 | static void f71805f_write16(struct f71805f_data *data, u8 reg, u16 val) | 303 | static void f71805f_write16(struct f71805f_data *data, u8 reg, u16 val) |
311 | { | 304 | { |
312 | mutex_lock(&data->lock); | ||
313 | outb(reg, data->addr + ADDR_REG_OFFSET); | 305 | outb(reg, data->addr + ADDR_REG_OFFSET); |
314 | outb(val >> 8, data->addr + DATA_REG_OFFSET); | 306 | outb(val >> 8, data->addr + DATA_REG_OFFSET); |
315 | outb(++reg, data->addr + ADDR_REG_OFFSET); | 307 | outb(++reg, data->addr + ADDR_REG_OFFSET); |
316 | outb(val & 0xff, data->addr + DATA_REG_OFFSET); | 308 | outb(val & 0xff, data->addr + DATA_REG_OFFSET); |
317 | mutex_unlock(&data->lock); | ||
318 | } | 309 | } |
319 | 310 | ||
320 | static struct f71805f_data *f71805f_update_device(struct device *dev) | 311 | static struct f71805f_data *f71805f_update_device(struct device *dev) |
@@ -1150,7 +1141,6 @@ static int __devinit f71805f_probe(struct platform_device *pdev) | |||
1150 | 1141 | ||
1151 | res = platform_get_resource(pdev, IORESOURCE_IO, 0); | 1142 | res = platform_get_resource(pdev, IORESOURCE_IO, 0); |
1152 | data->addr = res->start; | 1143 | data->addr = res->start; |
1153 | mutex_init(&data->lock); | ||
1154 | data->name = names[sio_data->kind]; | 1144 | data->name = names[sio_data->kind]; |
1155 | mutex_init(&data->update_lock); | 1145 | mutex_init(&data->update_lock); |
1156 | 1146 | ||
@@ -1300,14 +1290,11 @@ static int __init f71805f_device_add(unsigned short address, | |||
1300 | if (err) { | 1290 | if (err) { |
1301 | printk(KERN_ERR DRVNAME ": Device addition failed (%d)\n", | 1291 | printk(KERN_ERR DRVNAME ": Device addition failed (%d)\n", |
1302 | err); | 1292 | err); |
1303 | goto exit_kfree_data; | 1293 | goto exit_device_put; |
1304 | } | 1294 | } |
1305 | 1295 | ||
1306 | return 0; | 1296 | return 0; |
1307 | 1297 | ||
1308 | exit_kfree_data: | ||
1309 | kfree(pdev->dev.platform_data); | ||
1310 | pdev->dev.platform_data = NULL; | ||
1311 | exit_device_put: | 1298 | exit_device_put: |
1312 | platform_device_put(pdev); | 1299 | platform_device_put(pdev); |
1313 | exit: | 1300 | exit: |
@@ -1400,10 +1387,7 @@ exit: | |||
1400 | 1387 | ||
1401 | static void __exit f71805f_exit(void) | 1388 | static void __exit f71805f_exit(void) |
1402 | { | 1389 | { |
1403 | kfree(pdev->dev.platform_data); | ||
1404 | pdev->dev.platform_data = NULL; | ||
1405 | platform_device_unregister(pdev); | 1390 | platform_device_unregister(pdev); |
1406 | |||
1407 | platform_driver_unregister(&f71805f_driver); | 1391 | platform_driver_unregister(&f71805f_driver); |
1408 | } | 1392 | } |
1409 | 1393 | ||
diff --git a/drivers/hwmon/hwmon.c b/drivers/hwmon/hwmon.c index 106fa01cdb60..affcc00764d3 100644 --- a/drivers/hwmon/hwmon.c +++ b/drivers/hwmon/hwmon.c | |||
@@ -101,7 +101,7 @@ static void __exit hwmon_exit(void) | |||
101 | class_destroy(hwmon_class); | 101 | class_destroy(hwmon_class); |
102 | } | 102 | } |
103 | 103 | ||
104 | module_init(hwmon_init); | 104 | subsys_initcall(hwmon_init); |
105 | module_exit(hwmon_exit); | 105 | module_exit(hwmon_exit); |
106 | 106 | ||
107 | EXPORT_SYMBOL_GPL(hwmon_device_register); | 107 | EXPORT_SYMBOL_GPL(hwmon_device_register); |
diff --git a/drivers/hwmon/it87.c b/drivers/hwmon/it87.c index 1ed8b7e2c35d..62afc63708a5 100644 --- a/drivers/hwmon/it87.c +++ b/drivers/hwmon/it87.c | |||
@@ -202,15 +202,23 @@ static int DIV_TO_REG(int val) | |||
202 | } | 202 | } |
203 | #define DIV_FROM_REG(val) (1 << (val)) | 203 | #define DIV_FROM_REG(val) (1 << (val)) |
204 | 204 | ||
205 | static const unsigned int pwm_freq[8] = { | ||
206 | 48000000 / 128, | ||
207 | 24000000 / 128, | ||
208 | 12000000 / 128, | ||
209 | 8000000 / 128, | ||
210 | 6000000 / 128, | ||
211 | 3000000 / 128, | ||
212 | 1500000 / 128, | ||
213 | 750000 / 128, | ||
214 | }; | ||
215 | |||
205 | 216 | ||
206 | /* For each registered IT87, we need to keep some data in memory. That | 217 | /* For each registered chip, we need to keep some data in memory. |
207 | data is pointed to by it87_list[NR]->data. The structure itself is | 218 | The structure is dynamically allocated. */ |
208 | dynamically allocated, at the same time when a new it87 client is | ||
209 | allocated. */ | ||
210 | struct it87_data { | 219 | struct it87_data { |
211 | struct i2c_client client; | 220 | struct i2c_client client; |
212 | struct class_device *class_dev; | 221 | struct class_device *class_dev; |
213 | struct mutex lock; | ||
214 | enum chips type; | 222 | enum chips type; |
215 | 223 | ||
216 | struct mutex update_lock; | 224 | struct mutex update_lock; |
@@ -232,6 +240,7 @@ struct it87_data { | |||
232 | u8 vrm; | 240 | u8 vrm; |
233 | u32 alarms; /* Register encoding, combined */ | 241 | u32 alarms; /* Register encoding, combined */ |
234 | u8 fan_main_ctrl; /* Register value */ | 242 | u8 fan_main_ctrl; /* Register value */ |
243 | u8 fan_ctl; /* Register value */ | ||
235 | u8 manual_pwm_ctl[3]; /* manual PWM value set by user */ | 244 | u8 manual_pwm_ctl[3]; /* manual PWM value set by user */ |
236 | }; | 245 | }; |
237 | 246 | ||
@@ -519,6 +528,14 @@ static ssize_t show_pwm(struct device *dev, struct device_attribute *attr, | |||
519 | struct it87_data *data = it87_update_device(dev); | 528 | struct it87_data *data = it87_update_device(dev); |
520 | return sprintf(buf,"%d\n", data->manual_pwm_ctl[nr]); | 529 | return sprintf(buf,"%d\n", data->manual_pwm_ctl[nr]); |
521 | } | 530 | } |
531 | static ssize_t show_pwm_freq(struct device *dev, struct device_attribute *attr, | ||
532 | char *buf) | ||
533 | { | ||
534 | struct it87_data *data = it87_update_device(dev); | ||
535 | int index = (data->fan_ctl >> 4) & 0x07; | ||
536 | |||
537 | return sprintf(buf, "%u\n", pwm_freq[index]); | ||
538 | } | ||
522 | static ssize_t set_fan_min(struct device *dev, struct device_attribute *attr, | 539 | static ssize_t set_fan_min(struct device *dev, struct device_attribute *attr, |
523 | const char *buf, size_t count) | 540 | const char *buf, size_t count) |
524 | { | 541 | { |
@@ -528,9 +545,10 @@ static ssize_t set_fan_min(struct device *dev, struct device_attribute *attr, | |||
528 | struct i2c_client *client = to_i2c_client(dev); | 545 | struct i2c_client *client = to_i2c_client(dev); |
529 | struct it87_data *data = i2c_get_clientdata(client); | 546 | struct it87_data *data = i2c_get_clientdata(client); |
530 | int val = simple_strtol(buf, NULL, 10); | 547 | int val = simple_strtol(buf, NULL, 10); |
531 | u8 reg = it87_read_value(client, IT87_REG_FAN_DIV); | 548 | u8 reg; |
532 | 549 | ||
533 | mutex_lock(&data->update_lock); | 550 | mutex_lock(&data->update_lock); |
551 | reg = it87_read_value(client, IT87_REG_FAN_DIV); | ||
534 | switch (nr) { | 552 | switch (nr) { |
535 | case 0: data->fan_div[nr] = reg & 0x07; break; | 553 | case 0: data->fan_div[nr] = reg & 0x07; break; |
536 | case 1: data->fan_div[nr] = (reg >> 3) & 0x07; break; | 554 | case 1: data->fan_div[nr] = (reg >> 3) & 0x07; break; |
@@ -639,6 +657,28 @@ static ssize_t set_pwm(struct device *dev, struct device_attribute *attr, | |||
639 | mutex_unlock(&data->update_lock); | 657 | mutex_unlock(&data->update_lock); |
640 | return count; | 658 | return count; |
641 | } | 659 | } |
660 | static ssize_t set_pwm_freq(struct device *dev, | ||
661 | struct device_attribute *attr, const char *buf, size_t count) | ||
662 | { | ||
663 | struct i2c_client *client = to_i2c_client(dev); | ||
664 | struct it87_data *data = i2c_get_clientdata(client); | ||
665 | unsigned long val = simple_strtoul(buf, NULL, 10); | ||
666 | int i; | ||
667 | |||
668 | /* Search for the nearest available frequency */ | ||
669 | for (i = 0; i < 7; i++) { | ||
670 | if (val > (pwm_freq[i] + pwm_freq[i+1]) / 2) | ||
671 | break; | ||
672 | } | ||
673 | |||
674 | mutex_lock(&data->update_lock); | ||
675 | data->fan_ctl = it87_read_value(client, IT87_REG_FAN_CTL) & 0x8f; | ||
676 | data->fan_ctl |= i << 4; | ||
677 | it87_write_value(client, IT87_REG_FAN_CTL, data->fan_ctl); | ||
678 | mutex_unlock(&data->update_lock); | ||
679 | |||
680 | return count; | ||
681 | } | ||
642 | 682 | ||
643 | #define show_fan_offset(offset) \ | 683 | #define show_fan_offset(offset) \ |
644 | static SENSOR_DEVICE_ATTR(fan##offset##_input, S_IRUGO, \ | 684 | static SENSOR_DEVICE_ATTR(fan##offset##_input, S_IRUGO, \ |
@@ -656,7 +696,10 @@ show_fan_offset(3); | |||
656 | static SENSOR_DEVICE_ATTR(pwm##offset##_enable, S_IRUGO | S_IWUSR, \ | 696 | static SENSOR_DEVICE_ATTR(pwm##offset##_enable, S_IRUGO | S_IWUSR, \ |
657 | show_pwm_enable, set_pwm_enable, offset - 1); \ | 697 | show_pwm_enable, set_pwm_enable, offset - 1); \ |
658 | static SENSOR_DEVICE_ATTR(pwm##offset, S_IRUGO | S_IWUSR, \ | 698 | static SENSOR_DEVICE_ATTR(pwm##offset, S_IRUGO | S_IWUSR, \ |
659 | show_pwm, set_pwm, offset - 1); | 699 | show_pwm, set_pwm, offset - 1); \ |
700 | static DEVICE_ATTR(pwm##offset##_freq, \ | ||
701 | (offset == 1 ? S_IRUGO | S_IWUSR : S_IRUGO), \ | ||
702 | show_pwm_freq, (offset == 1 ? set_pwm_freq : NULL)); | ||
660 | 703 | ||
661 | show_pwm_offset(1); | 704 | show_pwm_offset(1); |
662 | show_pwm_offset(2); | 705 | show_pwm_offset(2); |
@@ -904,7 +947,6 @@ static int it87_detect(struct i2c_adapter *adapter) | |||
904 | } | 947 | } |
905 | 948 | ||
906 | new_client = &data->client; | 949 | new_client = &data->client; |
907 | mutex_init(&data->lock); | ||
908 | i2c_set_clientdata(new_client, data); | 950 | i2c_set_clientdata(new_client, data); |
909 | new_client->addr = isa_address; | 951 | new_client->addr = isa_address; |
910 | new_client->adapter = adapter; | 952 | new_client->adapter = adapter; |
@@ -1021,7 +1063,13 @@ static int it87_detect(struct i2c_adapter *adapter) | |||
1021 | || (err = device_create_file(&new_client->dev, | 1063 | || (err = device_create_file(&new_client->dev, |
1022 | &sensor_dev_attr_pwm2.dev_attr)) | 1064 | &sensor_dev_attr_pwm2.dev_attr)) |
1023 | || (err = device_create_file(&new_client->dev, | 1065 | || (err = device_create_file(&new_client->dev, |
1024 | &sensor_dev_attr_pwm3.dev_attr))) | 1066 | &sensor_dev_attr_pwm3.dev_attr)) |
1067 | || (err = device_create_file(&new_client->dev, | ||
1068 | &dev_attr_pwm1_freq)) | ||
1069 | || (err = device_create_file(&new_client->dev, | ||
1070 | &dev_attr_pwm2_freq)) | ||
1071 | || (err = device_create_file(&new_client->dev, | ||
1072 | &dev_attr_pwm3_freq))) | ||
1025 | goto ERROR4; | 1073 | goto ERROR4; |
1026 | } | 1074 | } |
1027 | 1075 | ||
@@ -1076,33 +1124,22 @@ static int it87_detach_client(struct i2c_client *client) | |||
1076 | return 0; | 1124 | return 0; |
1077 | } | 1125 | } |
1078 | 1126 | ||
1079 | /* ISA access must be locked explicitly! | 1127 | /* Must be called with data->update_lock held, except during initialization. |
1080 | We ignore the IT87 BUSY flag at this moment - it could lead to deadlocks, | 1128 | We ignore the IT87 BUSY flag at this moment - it could lead to deadlocks, |
1081 | would slow down the IT87 access and should not be necessary. */ | 1129 | would slow down the IT87 access and should not be necessary. */ |
1082 | static int it87_read_value(struct i2c_client *client, u8 reg) | 1130 | static int it87_read_value(struct i2c_client *client, u8 reg) |
1083 | { | 1131 | { |
1084 | struct it87_data *data = i2c_get_clientdata(client); | ||
1085 | int res; | ||
1086 | |||
1087 | mutex_lock(&data->lock); | ||
1088 | outb_p(reg, client->addr + IT87_ADDR_REG_OFFSET); | 1132 | outb_p(reg, client->addr + IT87_ADDR_REG_OFFSET); |
1089 | res = inb_p(client->addr + IT87_DATA_REG_OFFSET); | 1133 | return inb_p(client->addr + IT87_DATA_REG_OFFSET); |
1090 | mutex_unlock(&data->lock); | ||
1091 | |||
1092 | return res; | ||
1093 | } | 1134 | } |
1094 | 1135 | ||
1095 | /* ISA access must be locked explicitly! | 1136 | /* Must be called with data->update_lock held, except during initialization. |
1096 | We ignore the IT87 BUSY flag at this moment - it could lead to deadlocks, | 1137 | We ignore the IT87 BUSY flag at this moment - it could lead to deadlocks, |
1097 | would slow down the IT87 access and should not be necessary. */ | 1138 | would slow down the IT87 access and should not be necessary. */ |
1098 | static void it87_write_value(struct i2c_client *client, u8 reg, u8 value) | 1139 | static void it87_write_value(struct i2c_client *client, u8 reg, u8 value) |
1099 | { | 1140 | { |
1100 | struct it87_data *data = i2c_get_clientdata(client); | ||
1101 | |||
1102 | mutex_lock(&data->lock); | ||
1103 | outb_p(reg, client->addr + IT87_ADDR_REG_OFFSET); | 1141 | outb_p(reg, client->addr + IT87_ADDR_REG_OFFSET); |
1104 | outb_p(value, client->addr + IT87_DATA_REG_OFFSET); | 1142 | outb_p(value, client->addr + IT87_DATA_REG_OFFSET); |
1105 | mutex_unlock(&data->lock); | ||
1106 | } | 1143 | } |
1107 | 1144 | ||
1108 | /* Return 1 if and only if the PWM interface is safe to use */ | 1145 | /* Return 1 if and only if the PWM interface is safe to use */ |
@@ -1316,6 +1353,7 @@ static struct it87_data *it87_update_device(struct device *dev) | |||
1316 | (it87_read_value(client, IT87_REG_ALARM2) << 8) | | 1353 | (it87_read_value(client, IT87_REG_ALARM2) << 8) | |
1317 | (it87_read_value(client, IT87_REG_ALARM3) << 16); | 1354 | (it87_read_value(client, IT87_REG_ALARM3) << 16); |
1318 | data->fan_main_ctrl = it87_read_value(client, IT87_REG_FAN_MAIN_CTRL); | 1355 | data->fan_main_ctrl = it87_read_value(client, IT87_REG_FAN_MAIN_CTRL); |
1356 | data->fan_ctl = it87_read_value(client, IT87_REG_FAN_CTL); | ||
1319 | 1357 | ||
1320 | data->sensor = it87_read_value(client, IT87_REG_TEMP_ENABLE); | 1358 | data->sensor = it87_read_value(client, IT87_REG_TEMP_ENABLE); |
1321 | /* The 8705 does not have VID capability */ | 1359 | /* The 8705 does not have VID capability */ |
diff --git a/drivers/hwmon/lm70.c b/drivers/hwmon/lm70.c index 6ba84731b9cd..7eaae3834e15 100644 --- a/drivers/hwmon/lm70.c +++ b/drivers/hwmon/lm70.c | |||
@@ -126,7 +126,7 @@ out_dev_reg_failed: | |||
126 | return status; | 126 | return status; |
127 | } | 127 | } |
128 | 128 | ||
129 | static int __exit lm70_remove(struct spi_device *spi) | 129 | static int __devexit lm70_remove(struct spi_device *spi) |
130 | { | 130 | { |
131 | struct lm70 *p_lm70 = dev_get_drvdata(&spi->dev); | 131 | struct lm70 *p_lm70 = dev_get_drvdata(&spi->dev); |
132 | 132 | ||
diff --git a/drivers/hwmon/lm78.c b/drivers/hwmon/lm78.c index 73bc2ffc598d..886786c33916 100644 --- a/drivers/hwmon/lm78.c +++ b/drivers/hwmon/lm78.c | |||
@@ -125,10 +125,8 @@ static inline int TEMP_FROM_REG(s8 val) | |||
125 | bad. Quite a lot of bookkeeping is done. A real driver can often cut | 125 | bad. Quite a lot of bookkeeping is done. A real driver can often cut |
126 | some corners. */ | 126 | some corners. */ |
127 | 127 | ||
128 | /* For each registered LM78, we need to keep some data in memory. That | 128 | /* For each registered chip, we need to keep some data in memory. |
129 | data is pointed to by lm78_list[NR]->data. The structure itself is | 129 | The structure is dynamically allocated. */ |
130 | dynamically allocated, at the same time when a new lm78 client is | ||
131 | allocated. */ | ||
132 | struct lm78_data { | 130 | struct lm78_data { |
133 | struct i2c_client client; | 131 | struct i2c_client client; |
134 | struct class_device *class_dev; | 132 | struct class_device *class_dev; |
diff --git a/drivers/hwmon/lm85.c b/drivers/hwmon/lm85.c index 2c3293cf69d1..20a8c648280d 100644 --- a/drivers/hwmon/lm85.c +++ b/drivers/hwmon/lm85.c | |||
@@ -298,11 +298,6 @@ static int ZONE_TO_REG( int zone ) | |||
298 | #define LM85_DATA_INTERVAL (HZ + HZ / 2) | 298 | #define LM85_DATA_INTERVAL (HZ + HZ / 2) |
299 | #define LM85_CONFIG_INTERVAL (1 * 60 * HZ) | 299 | #define LM85_CONFIG_INTERVAL (1 * 60 * HZ) |
300 | 300 | ||
301 | /* For each registered LM85, we need to keep some data in memory. That | ||
302 | data is pointed to by lm85_list[NR]->data. The structure itself is | ||
303 | dynamically allocated, at the same time when a new lm85 client is | ||
304 | allocated. */ | ||
305 | |||
306 | /* LM85 can automatically adjust fan speeds based on temperature | 301 | /* LM85 can automatically adjust fan speeds based on temperature |
307 | * This structure encapsulates an entire Zone config. There are | 302 | * This structure encapsulates an entire Zone config. There are |
308 | * three zones (one for each temperature input) on the lm85 | 303 | * three zones (one for each temperature input) on the lm85 |
@@ -329,10 +324,11 @@ struct lm85_autofan { | |||
329 | u8 min_off; /* Min PWM or OFF below "limit", flag */ | 324 | u8 min_off; /* Min PWM or OFF below "limit", flag */ |
330 | }; | 325 | }; |
331 | 326 | ||
327 | /* For each registered chip, we need to keep some data in memory. | ||
328 | The structure is dynamically allocated. */ | ||
332 | struct lm85_data { | 329 | struct lm85_data { |
333 | struct i2c_client client; | 330 | struct i2c_client client; |
334 | struct class_device *class_dev; | 331 | struct class_device *class_dev; |
335 | struct mutex lock; | ||
336 | enum chips type; | 332 | enum chips type; |
337 | 333 | ||
338 | struct mutex update_lock; | 334 | struct mutex update_lock; |
diff --git a/drivers/hwmon/sis5595.c b/drivers/hwmon/sis5595.c index 95a4b5d9eaf2..3f400263fc0f 100644 --- a/drivers/hwmon/sis5595.c +++ b/drivers/hwmon/sis5595.c | |||
@@ -162,10 +162,8 @@ static inline u8 DIV_TO_REG(int val) | |||
162 | } | 162 | } |
163 | #define DIV_FROM_REG(val) (1 << (val)) | 163 | #define DIV_FROM_REG(val) (1 << (val)) |
164 | 164 | ||
165 | /* For the SIS5595, we need to keep some data in memory. That | 165 | /* For each registered chip, we need to keep some data in memory. |
166 | data is pointed to by sis5595_list[NR]->data. The structure itself is | 166 | The structure is dynamically allocated. */ |
167 | dynamically allocated, at the time when the new sis5595 client is | ||
168 | allocated. */ | ||
169 | struct sis5595_data { | 167 | struct sis5595_data { |
170 | struct i2c_client client; | 168 | struct i2c_client client; |
171 | struct class_device *class_dev; | 169 | struct class_device *class_dev; |
diff --git a/drivers/hwmon/via686a.c b/drivers/hwmon/via686a.c index f8acada0537a..9a440c8cc520 100644 --- a/drivers/hwmon/via686a.c +++ b/drivers/hwmon/via686a.c | |||
@@ -292,9 +292,8 @@ static inline long TEMP_FROM_REG10(u16 val) | |||
292 | #define DIV_FROM_REG(val) (1 << (val)) | 292 | #define DIV_FROM_REG(val) (1 << (val)) |
293 | #define DIV_TO_REG(val) ((val)==8?3:(val)==4?2:(val)==1?0:1) | 293 | #define DIV_TO_REG(val) ((val)==8?3:(val)==4?2:(val)==1?0:1) |
294 | 294 | ||
295 | /* For the VIA686A, we need to keep some data in memory. | 295 | /* For each registered chip, we need to keep some data in memory. |
296 | The structure is dynamically allocated, at the same time when a new | 296 | The structure is dynamically allocated. */ |
297 | via686a client is allocated. */ | ||
298 | struct via686a_data { | 297 | struct via686a_data { |
299 | struct i2c_client client; | 298 | struct i2c_client client; |
300 | struct class_device *class_dev; | 299 | struct class_device *class_dev; |
diff --git a/drivers/hwmon/vt1211.c b/drivers/hwmon/vt1211.c index 25cc56003d7a..89c23d6add7b 100644 --- a/drivers/hwmon/vt1211.c +++ b/drivers/hwmon/vt1211.c | |||
@@ -178,9 +178,10 @@ struct vt1211_data { | |||
178 | * Super-I/O constants and functions | 178 | * Super-I/O constants and functions |
179 | * --------------------------------------------------------------------- */ | 179 | * --------------------------------------------------------------------- */ |
180 | 180 | ||
181 | /* Configuration & data index port registers */ | 181 | /* Configuration index port registers |
182 | #define SIO_REG_CIP 0x2e | 182 | * The vt1211 can live at 2 different addresses so we need to probe both */ |
183 | #define SIO_REG_DIP 0x2f | 183 | #define SIO_REG_CIP1 0x2e |
184 | #define SIO_REG_CIP2 0x4e | ||
184 | 185 | ||
185 | /* Configuration registers */ | 186 | /* Configuration registers */ |
186 | #define SIO_VT1211_LDN 0x07 /* logical device number */ | 187 | #define SIO_VT1211_LDN 0x07 /* logical device number */ |
@@ -193,33 +194,33 @@ struct vt1211_data { | |||
193 | /* VT1211 logical device numbers */ | 194 | /* VT1211 logical device numbers */ |
194 | #define SIO_VT1211_LDN_HWMON 0x0b /* HW monitor */ | 195 | #define SIO_VT1211_LDN_HWMON 0x0b /* HW monitor */ |
195 | 196 | ||
196 | static inline void superio_outb(int reg, int val) | 197 | static inline void superio_outb(int sio_cip, int reg, int val) |
197 | { | 198 | { |
198 | outb(reg, SIO_REG_CIP); | 199 | outb(reg, sio_cip); |
199 | outb(val, SIO_REG_DIP); | 200 | outb(val, sio_cip + 1); |
200 | } | 201 | } |
201 | 202 | ||
202 | static inline int superio_inb(int reg) | 203 | static inline int superio_inb(int sio_cip, int reg) |
203 | { | 204 | { |
204 | outb(reg, SIO_REG_CIP); | 205 | outb(reg, sio_cip); |
205 | return inb(SIO_REG_DIP); | 206 | return inb(sio_cip + 1); |
206 | } | 207 | } |
207 | 208 | ||
208 | static inline void superio_select(int ldn) | 209 | static inline void superio_select(int sio_cip, int ldn) |
209 | { | 210 | { |
210 | outb(SIO_VT1211_LDN, SIO_REG_CIP); | 211 | outb(SIO_VT1211_LDN, sio_cip); |
211 | outb(ldn, SIO_REG_DIP); | 212 | outb(ldn, sio_cip + 1); |
212 | } | 213 | } |
213 | 214 | ||
214 | static inline void superio_enter(void) | 215 | static inline void superio_enter(int sio_cip) |
215 | { | 216 | { |
216 | outb(0x87, SIO_REG_CIP); | 217 | outb(0x87, sio_cip); |
217 | outb(0x87, SIO_REG_CIP); | 218 | outb(0x87, sio_cip); |
218 | } | 219 | } |
219 | 220 | ||
220 | static inline void superio_exit(void) | 221 | static inline void superio_exit(int sio_cip) |
221 | { | 222 | { |
222 | outb(0xaa, SIO_REG_CIP); | 223 | outb(0xaa, sio_cip); |
223 | } | 224 | } |
224 | 225 | ||
225 | /* --------------------------------------------------------------------- | 226 | /* --------------------------------------------------------------------- |
@@ -1263,26 +1264,26 @@ EXIT: | |||
1263 | return err; | 1264 | return err; |
1264 | } | 1265 | } |
1265 | 1266 | ||
1266 | static int __init vt1211_find(unsigned short *address) | 1267 | static int __init vt1211_find(int sio_cip, unsigned short *address) |
1267 | { | 1268 | { |
1268 | int err = -ENODEV; | 1269 | int err = -ENODEV; |
1269 | 1270 | ||
1270 | superio_enter(); | 1271 | superio_enter(sio_cip); |
1271 | 1272 | ||
1272 | if (superio_inb(SIO_VT1211_DEVID) != SIO_VT1211_ID) { | 1273 | if (superio_inb(sio_cip, SIO_VT1211_DEVID) != SIO_VT1211_ID) { |
1273 | goto EXIT; | 1274 | goto EXIT; |
1274 | } | 1275 | } |
1275 | 1276 | ||
1276 | superio_select(SIO_VT1211_LDN_HWMON); | 1277 | superio_select(sio_cip, SIO_VT1211_LDN_HWMON); |
1277 | 1278 | ||
1278 | if ((superio_inb(SIO_VT1211_ACTIVE) & 1) == 0) { | 1279 | if ((superio_inb(sio_cip, SIO_VT1211_ACTIVE) & 1) == 0) { |
1279 | printk(KERN_WARNING DRVNAME ": HW monitor is disabled, " | 1280 | printk(KERN_WARNING DRVNAME ": HW monitor is disabled, " |
1280 | "skipping\n"); | 1281 | "skipping\n"); |
1281 | goto EXIT; | 1282 | goto EXIT; |
1282 | } | 1283 | } |
1283 | 1284 | ||
1284 | *address = ((superio_inb(SIO_VT1211_BADDR) << 8) | | 1285 | *address = ((superio_inb(sio_cip, SIO_VT1211_BADDR) << 8) | |
1285 | (superio_inb(SIO_VT1211_BADDR + 1))) & 0xff00; | 1286 | (superio_inb(sio_cip, SIO_VT1211_BADDR + 1))) & 0xff00; |
1286 | if (*address == 0) { | 1287 | if (*address == 0) { |
1287 | printk(KERN_WARNING DRVNAME ": Base address is not set, " | 1288 | printk(KERN_WARNING DRVNAME ": Base address is not set, " |
1288 | "skipping\n"); | 1289 | "skipping\n"); |
@@ -1291,10 +1292,11 @@ static int __init vt1211_find(unsigned short *address) | |||
1291 | 1292 | ||
1292 | err = 0; | 1293 | err = 0; |
1293 | printk(KERN_INFO DRVNAME ": Found VT1211 chip at 0x%04x, " | 1294 | printk(KERN_INFO DRVNAME ": Found VT1211 chip at 0x%04x, " |
1294 | "revision %u\n", *address, superio_inb(SIO_VT1211_DEVREV)); | 1295 | "revision %u\n", *address, |
1296 | superio_inb(sio_cip, SIO_VT1211_DEVREV)); | ||
1295 | 1297 | ||
1296 | EXIT: | 1298 | EXIT: |
1297 | superio_exit(); | 1299 | superio_exit(sio_cip); |
1298 | return err; | 1300 | return err; |
1299 | } | 1301 | } |
1300 | 1302 | ||
@@ -1303,8 +1305,8 @@ static int __init vt1211_init(void) | |||
1303 | int err; | 1305 | int err; |
1304 | unsigned short address = 0; | 1306 | unsigned short address = 0; |
1305 | 1307 | ||
1306 | err = vt1211_find(&address); | 1308 | if ((err = vt1211_find(SIO_REG_CIP1, &address)) && |
1307 | if (err) { | 1309 | (err = vt1211_find(SIO_REG_CIP2, &address))) { |
1308 | goto EXIT; | 1310 | goto EXIT; |
1309 | } | 1311 | } |
1310 | 1312 | ||
diff --git a/drivers/hwmon/w83627ehf.c b/drivers/hwmon/w83627ehf.c index 212a1558c63b..da5828f2dfc2 100644 --- a/drivers/hwmon/w83627ehf.c +++ b/drivers/hwmon/w83627ehf.c | |||
@@ -32,8 +32,10 @@ | |||
32 | 32 | ||
33 | Supports the following chips: | 33 | Supports the following chips: |
34 | 34 | ||
35 | Chip #vin #fan #pwm #temp chip_id man_id | 35 | Chip #vin #fan #pwm #temp chip IDs man ID |
36 | w83627ehf 10 5 4 3 0x88,0xa1 0x5ca3 | 36 | w83627ehf 10 5 4 3 0x8850 0x88 0x5ca3 |
37 | 0x8860 0xa1 | ||
38 | w83627dhg 9 5 4 3 0xa020 0xc1 0x5ca3 | ||
37 | */ | 39 | */ |
38 | 40 | ||
39 | #include <linux/module.h> | 41 | #include <linux/module.h> |
@@ -55,8 +57,18 @@ static unsigned short address; | |||
55 | * Super-I/O constants and functions | 57 | * Super-I/O constants and functions |
56 | */ | 58 | */ |
57 | 59 | ||
60 | /* | ||
61 | * The three following globals are initialized in w83627ehf_find(), before | ||
62 | * the i2c-isa device is created. Otherwise, they could be stored in | ||
63 | * w83627ehf_data. This is ugly, but necessary, and when the driver is next | ||
64 | * updated to become a platform driver, the globals will disappear. | ||
65 | */ | ||
58 | static int REG; /* The register to read/write */ | 66 | static int REG; /* The register to read/write */ |
59 | static int VAL; /* The value to read/write */ | 67 | static int VAL; /* The value to read/write */ |
68 | /* The w83627ehf/ehg have 10 voltage inputs, but the w83627dhg has 9. This | ||
69 | * value is also used in w83627ehf_detect() to export a device name in sysfs | ||
70 | * (e.g. w83627ehf or w83627dhg) */ | ||
71 | static int w83627ehf_num_in; | ||
60 | 72 | ||
61 | #define W83627EHF_LD_HWM 0x0b | 73 | #define W83627EHF_LD_HWM 0x0b |
62 | 74 | ||
@@ -65,8 +77,10 @@ static int VAL; /* The value to read/write */ | |||
65 | #define SIO_REG_ENABLE 0x30 /* Logical device enable */ | 77 | #define SIO_REG_ENABLE 0x30 /* Logical device enable */ |
66 | #define SIO_REG_ADDR 0x60 /* Logical device address (2 bytes) */ | 78 | #define SIO_REG_ADDR 0x60 /* Logical device address (2 bytes) */ |
67 | 79 | ||
68 | #define SIO_W83627EHF_ID 0x8840 | 80 | #define SIO_W83627EHF_ID 0x8850 |
69 | #define SIO_ID_MASK 0xFFC0 | 81 | #define SIO_W83627EHG_ID 0x8860 |
82 | #define SIO_W83627DHG_ID 0xa020 | ||
83 | #define SIO_ID_MASK 0xFFF0 | ||
70 | 84 | ||
71 | static inline void | 85 | static inline void |
72 | superio_outb(int reg, int val) | 86 | superio_outb(int reg, int val) |
@@ -115,8 +129,12 @@ superio_exit(void) | |||
115 | 129 | ||
116 | #define W83627EHF_REG_BANK 0x4E | 130 | #define W83627EHF_REG_BANK 0x4E |
117 | #define W83627EHF_REG_CONFIG 0x40 | 131 | #define W83627EHF_REG_CONFIG 0x40 |
118 | #define W83627EHF_REG_CHIP_ID 0x49 | 132 | |
119 | #define W83627EHF_REG_MAN_ID 0x4F | 133 | /* Not currently used: |
134 | * REG_MAN_ID has the value 0x5ca3 for all supported chips. | ||
135 | * REG_CHIP_ID == 0x88/0xa1/0xc1 depending on chip model. | ||
136 | * REG_MAN_ID is at port 0x4f | ||
137 | * REG_CHIP_ID is at port 0x58 */ | ||
120 | 138 | ||
121 | static const u16 W83627EHF_REG_FAN[] = { 0x28, 0x29, 0x2a, 0x3f, 0x553 }; | 139 | static const u16 W83627EHF_REG_FAN[] = { 0x28, 0x29, 0x2a, 0x3f, 0x553 }; |
122 | static const u16 W83627EHF_REG_FAN_MIN[] = { 0x3b, 0x3c, 0x3d, 0x3e, 0x55c }; | 140 | static const u16 W83627EHF_REG_FAN_MIN[] = { 0x3b, 0x3c, 0x3d, 0x3e, 0x55c }; |
@@ -429,7 +447,7 @@ static struct w83627ehf_data *w83627ehf_update_device(struct device *dev) | |||
429 | } | 447 | } |
430 | 448 | ||
431 | /* Measured voltages and limits */ | 449 | /* Measured voltages and limits */ |
432 | for (i = 0; i < 10; i++) { | 450 | for (i = 0; i < w83627ehf_num_in; i++) { |
433 | data->in[i] = w83627ehf_read_value(client, | 451 | data->in[i] = w83627ehf_read_value(client, |
434 | W83627EHF_REG_IN(i)); | 452 | W83627EHF_REG_IN(i)); |
435 | data->in_min[i] = w83627ehf_read_value(client, | 453 | data->in_min[i] = w83627ehf_read_value(client, |
@@ -1121,7 +1139,7 @@ static void w83627ehf_device_remove_files(struct device *dev) | |||
1121 | device_remove_file(dev, &sda_sf3_arrays[i].dev_attr); | 1139 | device_remove_file(dev, &sda_sf3_arrays[i].dev_attr); |
1122 | for (i = 0; i < ARRAY_SIZE(sda_sf3_arrays_fan4); i++) | 1140 | for (i = 0; i < ARRAY_SIZE(sda_sf3_arrays_fan4); i++) |
1123 | device_remove_file(dev, &sda_sf3_arrays_fan4[i].dev_attr); | 1141 | device_remove_file(dev, &sda_sf3_arrays_fan4[i].dev_attr); |
1124 | for (i = 0; i < 10; i++) { | 1142 | for (i = 0; i < w83627ehf_num_in; i++) { |
1125 | device_remove_file(dev, &sda_in_input[i].dev_attr); | 1143 | device_remove_file(dev, &sda_in_input[i].dev_attr); |
1126 | device_remove_file(dev, &sda_in_alarm[i].dev_attr); | 1144 | device_remove_file(dev, &sda_in_alarm[i].dev_attr); |
1127 | device_remove_file(dev, &sda_in_min[i].dev_attr); | 1145 | device_remove_file(dev, &sda_in_min[i].dev_attr); |
@@ -1196,7 +1214,11 @@ static int w83627ehf_detect(struct i2c_adapter *adapter) | |||
1196 | client->flags = 0; | 1214 | client->flags = 0; |
1197 | dev = &client->dev; | 1215 | dev = &client->dev; |
1198 | 1216 | ||
1199 | strlcpy(client->name, "w83627ehf", I2C_NAME_SIZE); | 1217 | if (w83627ehf_num_in == 9) |
1218 | strlcpy(client->name, "w83627dhg", I2C_NAME_SIZE); | ||
1219 | else /* just say ehf. 627EHG is 627EHF in lead-free packaging. */ | ||
1220 | strlcpy(client->name, "w83627ehf", I2C_NAME_SIZE); | ||
1221 | |||
1200 | data->valid = 0; | 1222 | data->valid = 0; |
1201 | mutex_init(&data->update_lock); | 1223 | mutex_init(&data->update_lock); |
1202 | 1224 | ||
@@ -1246,7 +1268,7 @@ static int w83627ehf_detect(struct i2c_adapter *adapter) | |||
1246 | goto exit_remove; | 1268 | goto exit_remove; |
1247 | } | 1269 | } |
1248 | 1270 | ||
1249 | for (i = 0; i < 10; i++) | 1271 | for (i = 0; i < w83627ehf_num_in; i++) |
1250 | if ((err = device_create_file(dev, &sda_in_input[i].dev_attr)) | 1272 | if ((err = device_create_file(dev, &sda_in_input[i].dev_attr)) |
1251 | || (err = device_create_file(dev, | 1273 | || (err = device_create_file(dev, |
1252 | &sda_in_alarm[i].dev_attr)) | 1274 | &sda_in_alarm[i].dev_attr)) |
@@ -1340,7 +1362,17 @@ static int __init w83627ehf_find(int sioaddr, unsigned short *addr) | |||
1340 | 1362 | ||
1341 | val = (superio_inb(SIO_REG_DEVID) << 8) | 1363 | val = (superio_inb(SIO_REG_DEVID) << 8) |
1342 | | superio_inb(SIO_REG_DEVID + 1); | 1364 | | superio_inb(SIO_REG_DEVID + 1); |
1343 | if ((val & SIO_ID_MASK) != SIO_W83627EHF_ID) { | 1365 | switch (val & SIO_ID_MASK) { |
1366 | case SIO_W83627DHG_ID: | ||
1367 | w83627ehf_num_in = 9; | ||
1368 | break; | ||
1369 | case SIO_W83627EHF_ID: | ||
1370 | case SIO_W83627EHG_ID: | ||
1371 | w83627ehf_num_in = 10; | ||
1372 | break; | ||
1373 | default: | ||
1374 | printk(KERN_WARNING "w83627ehf: unsupported chip ID: 0x%04x\n", | ||
1375 | val); | ||
1344 | superio_exit(); | 1376 | superio_exit(); |
1345 | return -ENODEV; | 1377 | return -ENODEV; |
1346 | } | 1378 | } |
diff --git a/drivers/hwmon/w83627hf.c b/drivers/hwmon/w83627hf.c index dfdc29c77123..d7e240635b3b 100644 --- a/drivers/hwmon/w83627hf.c +++ b/drivers/hwmon/w83627hf.c | |||
@@ -286,9 +286,8 @@ static inline u8 DIV_TO_REG(long val) | |||
286 | return ((u8) i); | 286 | return ((u8) i); |
287 | } | 287 | } |
288 | 288 | ||
289 | /* For each registered chip, we need to keep some data in memory. That | 289 | /* For each registered chip, we need to keep some data in memory. |
290 | data is pointed to by w83627hf_list[NR]->data. The structure itself is | 290 | The structure is dynamically allocated. */ |
291 | dynamically allocated, at the same time when a new client is allocated. */ | ||
292 | struct w83627hf_data { | 291 | struct w83627hf_data { |
293 | struct i2c_client client; | 292 | struct i2c_client client; |
294 | struct class_device *class_dev; | 293 | struct class_device *class_dev; |
diff --git a/drivers/hwmon/w83781d.c b/drivers/hwmon/w83781d.c index 1232171c3aad..a47da3ec5472 100644 --- a/drivers/hwmon/w83781d.c +++ b/drivers/hwmon/w83781d.c | |||
@@ -221,14 +221,8 @@ DIV_TO_REG(long val, enum chips type) | |||
221 | a bit - except if there could be more than one SMBus. Groan. No solution | 221 | a bit - except if there could be more than one SMBus. Groan. No solution |
222 | for this yet. */ | 222 | for this yet. */ |
223 | 223 | ||
224 | /* This module may seem overly long and complicated. In fact, it is not so | 224 | /* For each registered chip, we need to keep some data in memory. |
225 | bad. Quite a lot of bookkeeping is done. A real driver can often cut | 225 | The structure is dynamically allocated. */ |
226 | some corners. */ | ||
227 | |||
228 | /* For each registered W83781D, we need to keep some data in memory. That | ||
229 | data is pointed to by w83781d_list[NR]->data. The structure itself is | ||
230 | dynamically allocated, at the same time when a new w83781d client is | ||
231 | allocated. */ | ||
232 | struct w83781d_data { | 226 | struct w83781d_data { |
233 | struct i2c_client client; | 227 | struct i2c_client client; |
234 | struct class_device *class_dev; | 228 | struct class_device *class_dev; |