diff options
author | Linus Torvalds <torvalds@woody.linux-foundation.org> | 2007-05-08 15:07:28 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@woody.linux-foundation.org> | 2007-05-08 15:07:28 -0400 |
commit | 36f021b579d195cdc5fa6f3e2bab198b4bf70643 (patch) | |
tree | 96d3c97f5e5214d2aa7151c12a22a7eb345dbaa1 | |
parent | 215d06780d13fd7de629b02b61b7b7bf88ce5039 (diff) | |
parent | 1d72acf91abb327e25137ad2e371c1a788b34e45 (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: (32 commits)
Use menuconfig objects - hwmon
hwmon/smsc47b397: Use dynamic sysfs callbacks
hwmon/smsc47b397: Convert to a platform driver
hwmon/w83781d: Deprecate W83627HF support
hwmon/w83781d: Use dynamic sysfs callbacks
hwmon/w83781d: Be less i2c_client-centric
hwmon/w83781d: Clean up conversion macros
hwmon/w83781d: No longer use i2c-isa
hwmon/ams: Do not print error on systems without apple motion sensor
hwmon/ams: Fix I2C read retry logic
hwmon: New AD7416, AD7417 and AD7418 driver
hwmon/coretemp: Add documentation
hwmon: New coretemp driver
i386: Use functions from library in msr driver
i386: Add safe variants of rdmsr_on_cpu and wrmsr_on_cpu
hwmon/lm75: Use dynamic sysfs callbacks
hwmon/lm78: Use dynamic sysfs callbacks
hwmon/lm78: Be less i2c_client-centric
hwmon/lm78: No longer use i2c-isa
hwmon: New max6650 driver
...
29 files changed, 3777 insertions, 1692 deletions
diff --git a/Documentation/hwmon/coretemp b/Documentation/hwmon/coretemp new file mode 100644 index 000000000000..870cda9416e9 --- /dev/null +++ b/Documentation/hwmon/coretemp | |||
@@ -0,0 +1,36 @@ | |||
1 | Kernel driver coretemp | ||
2 | ====================== | ||
3 | |||
4 | Supported chips: | ||
5 | * All Intel Core family | ||
6 | Prefix: 'coretemp' | ||
7 | CPUID: family 0x6, models 0xe, 0xf | ||
8 | Datasheet: Intel 64 and IA-32 Architectures Software Developer's Manual | ||
9 | Volume 3A: System Programming Guide | ||
10 | |||
11 | Author: Rudolf Marek | ||
12 | |||
13 | Description | ||
14 | ----------- | ||
15 | |||
16 | This driver permits reading temperature sensor embedded inside Intel Core CPU. | ||
17 | Temperature is measured in degrees Celsius and measurement resolution is | ||
18 | 1 degree C. Valid temperatures are from 0 to TjMax degrees C, because | ||
19 | the actual value of temperature register is in fact a delta from TjMax. | ||
20 | |||
21 | Temperature known as TjMax is the maximum junction temperature of processor. | ||
22 | Intel defines this temperature as 85C or 100C. At this temperature, protection | ||
23 | mechanism will perform actions to forcibly cool down the processor. Alarm | ||
24 | may be raised, if the temperature grows enough (more than TjMax) to trigger | ||
25 | the Out-Of-Spec bit. Following table summarizes the exported sysfs files: | ||
26 | |||
27 | temp1_input - Core temperature (in millidegrees Celsius). | ||
28 | temp1_crit - Maximum junction temperature (in millidegrees Celsius). | ||
29 | temp1_crit_alarm - Set when Out-of-spec bit is set, never clears. | ||
30 | Correct CPU operation is no longer guaranteed. | ||
31 | temp1_label - Contains string "Core X", where X is processor | ||
32 | number. | ||
33 | |||
34 | The TjMax temperature is set to 85 degrees C if undocumented model specific | ||
35 | register (UMSR) 0xee has bit 30 set. If not the TjMax is 100 degrees C as | ||
36 | (sometimes) documented in processor datasheet. | ||
diff --git a/Documentation/hwmon/max6650 b/Documentation/hwmon/max6650 new file mode 100644 index 000000000000..8be7beb9e3e8 --- /dev/null +++ b/Documentation/hwmon/max6650 | |||
@@ -0,0 +1,53 @@ | |||
1 | Kernel driver max6650 | ||
2 | ===================== | ||
3 | |||
4 | Supported chips: | ||
5 | * Maxim 6650 / 6651 | ||
6 | Prefix: 'max6650' | ||
7 | Addresses scanned: I2C 0x1b, 0x1f, 0x48, 0x4b | ||
8 | Datasheet: http://pdfserv.maxim-ic.com/en/ds/MAX6650-MAX6651.pdf | ||
9 | |||
10 | Authors: | ||
11 | Hans J. Koch <hjk@linutronix.de> | ||
12 | John Morris <john.morris@spirentcom.com> | ||
13 | Claus Gindhart <claus.gindhart@kontron.com> | ||
14 | |||
15 | Description | ||
16 | ----------- | ||
17 | |||
18 | This driver implements support for the Maxim 6650/6651 | ||
19 | |||
20 | The 2 devices are very similar, but the Maxim 6550 has a reduced feature | ||
21 | set, e.g. only one fan-input, instead of 4 for the 6651. | ||
22 | |||
23 | The driver is not able to distinguish between the 2 devices. | ||
24 | |||
25 | The driver provides the following sensor accesses in sysfs: | ||
26 | |||
27 | fan1_input ro fan tachometer speed in RPM | ||
28 | fan2_input ro " | ||
29 | fan3_input ro " | ||
30 | fan4_input ro " | ||
31 | fan1_target rw desired fan speed in RPM (closed loop mode only) | ||
32 | pwm1_enable rw regulator mode, 0=full on, 1=open loop, 2=closed loop | ||
33 | pwm1 rw relative speed (0-255), 255=max. speed. | ||
34 | Used in open loop mode only. | ||
35 | fan1_div rw sets the speed range the inputs can handle. Legal | ||
36 | values are 1, 2, 4, and 8. Use lower values for | ||
37 | faster fans. | ||
38 | |||
39 | Module parameters | ||
40 | ----------------- | ||
41 | |||
42 | If your board has a BIOS that initializes the MAX6650/6651 correctly, you can | ||
43 | simply load your module without parameters. It won't touch the configuration | ||
44 | registers then. If your board BIOS doesn't initialize the chip, or you want | ||
45 | different settings, you can set the following parameters: | ||
46 | |||
47 | voltage_12V: 5=5V fan, 12=12V fan, 0=don't change | ||
48 | prescaler: Possible values are 1,2,4,8,16, or 0 for don't change | ||
49 | clock: The clock frequency in Hz of the chip the driver should assume [254000] | ||
50 | |||
51 | Please have a look at the MAX6650/6651 data sheet and make sure that you fully | ||
52 | understand the meaning of these parameters before you attempt to change them. | ||
53 | |||
diff --git a/Documentation/hwmon/smsc47m1 b/Documentation/hwmon/smsc47m1 index 04a11124f667..42c8431b3c9d 100644 --- a/Documentation/hwmon/smsc47m1 +++ b/Documentation/hwmon/smsc47m1 | |||
@@ -14,6 +14,10 @@ Supported chips: | |||
14 | http://www.smsc.com/main/datasheets/47m14x.pdf | 14 | http://www.smsc.com/main/datasheets/47m14x.pdf |
15 | http://www.smsc.com/main/tools/discontinued/47m15x.pdf | 15 | http://www.smsc.com/main/tools/discontinued/47m15x.pdf |
16 | http://www.smsc.com/main/datasheets/47m192.pdf | 16 | http://www.smsc.com/main/datasheets/47m192.pdf |
17 | * SMSC LPC47M292 | ||
18 | Addresses scanned: none, address read from Super I/O config space | ||
19 | Prefix: 'smsc47m2' | ||
20 | Datasheet: Not public | ||
17 | * SMSC LPC47M997 | 21 | * SMSC LPC47M997 |
18 | Addresses scanned: none, address read from Super I/O config space | 22 | Addresses scanned: none, address read from Super I/O config space |
19 | Prefix: 'smsc47m1' | 23 | Prefix: 'smsc47m1' |
@@ -32,9 +36,10 @@ Description | |||
32 | The Standard Microsystems Corporation (SMSC) 47M1xx Super I/O chips | 36 | The Standard Microsystems Corporation (SMSC) 47M1xx Super I/O chips |
33 | contain monitoring and PWM control circuitry for two fans. | 37 | contain monitoring and PWM control circuitry for two fans. |
34 | 38 | ||
35 | The 47M15x and 47M192 chips contain a full 'hardware monitoring block' | 39 | The LPC47M15x, LPC47M192 and LPC47M292 chips contain a full 'hardware |
36 | in addition to the fan monitoring and control. The hardware monitoring | 40 | monitoring block' in addition to the fan monitoring and control. The |
37 | block is not supported by the driver. | 41 | hardware monitoring block is not supported by this driver, use the |
42 | smsc47m192 driver for that. | ||
38 | 43 | ||
39 | No documentation is available for the 47M997, but it has the same device | 44 | No documentation is available for the 47M997, but it has the same device |
40 | ID as the 47M15x and 47M192 chips and seems to be compatible. | 45 | ID as the 47M15x and 47M192 chips and seems to be compatible. |
diff --git a/Documentation/hwmon/smsc47m192 b/Documentation/hwmon/smsc47m192 index 45d6453cd435..6d54ecb7b3f8 100644 --- a/Documentation/hwmon/smsc47m192 +++ b/Documentation/hwmon/smsc47m192 | |||
@@ -2,12 +2,13 @@ Kernel driver smsc47m192 | |||
2 | ======================== | 2 | ======================== |
3 | 3 | ||
4 | Supported chips: | 4 | Supported chips: |
5 | * SMSC LPC47M192 and LPC47M997 | 5 | * SMSC LPC47M192, LPC47M15x, LPC47M292 and LPC47M997 |
6 | Prefix: 'smsc47m192' | 6 | Prefix: 'smsc47m192' |
7 | Addresses scanned: I2C 0x2c - 0x2d | 7 | Addresses scanned: I2C 0x2c - 0x2d |
8 | Datasheet: The datasheet for LPC47M192 is publicly available from | 8 | Datasheet: The datasheet for LPC47M192 is publicly available from |
9 | http://www.smsc.com/ | 9 | http://www.smsc.com/ |
10 | The LPC47M997 is compatible for hardware monitoring. | 10 | The LPC47M15x, LPC47M292 and LPC47M997 are compatible for |
11 | hardware monitoring. | ||
11 | 12 | ||
12 | Author: Hartmut Rick <linux@rick.claranet.de> | 13 | Author: Hartmut Rick <linux@rick.claranet.de> |
13 | Special thanks to Jean Delvare for careful checking | 14 | Special thanks to Jean Delvare for careful checking |
@@ -18,7 +19,7 @@ Description | |||
18 | ----------- | 19 | ----------- |
19 | 20 | ||
20 | This driver implements support for the hardware sensor capabilities | 21 | This driver implements support for the hardware sensor capabilities |
21 | of the SMSC LPC47M192 and LPC47M997 Super-I/O chips. | 22 | of the SMSC LPC47M192 and compatible Super-I/O chips. |
22 | 23 | ||
23 | These chips support 3 temperature channels and 8 voltage inputs | 24 | These chips support 3 temperature channels and 8 voltage inputs |
24 | as well as CPU voltage VID input. | 25 | as well as CPU voltage VID input. |
diff --git a/Documentation/hwmon/sysfs-interface b/Documentation/hwmon/sysfs-interface index d73d2e8c7534..a9a18ad0d17a 100644 --- a/Documentation/hwmon/sysfs-interface +++ b/Documentation/hwmon/sysfs-interface | |||
@@ -152,6 +152,13 @@ fan[1-*]_div Fan divisor. | |||
152 | Note that this is actually an internal clock divisor, which | 152 | Note that this is actually an internal clock divisor, which |
153 | affects the measurable speed range, not the read value. | 153 | affects the measurable speed range, not the read value. |
154 | 154 | ||
155 | fan[1-*]_target | ||
156 | Desired fan speed | ||
157 | Unit: revolution/min (RPM) | ||
158 | RW | ||
159 | Only makes sense if the chip supports closed-loop fan speed | ||
160 | control based on the measured fan speed. | ||
161 | |||
155 | Also see the Alarms section for status flags associated with fans. | 162 | Also see the Alarms section for status flags associated with fans. |
156 | 163 | ||
157 | 164 | ||
diff --git a/MAINTAINERS b/MAINTAINERS index 69f3f66091b4..41a4b477c576 100644 --- a/MAINTAINERS +++ b/MAINTAINERS | |||
@@ -1040,6 +1040,12 @@ P: Simon Arlott | |||
1040 | M: cxacru@fire.lp0.eu | 1040 | M: cxacru@fire.lp0.eu |
1041 | S: Maintained | 1041 | S: Maintained |
1042 | 1042 | ||
1043 | CORETEMP HARDWARE MONITORING DRIVER | ||
1044 | P: Rudolf Marek | ||
1045 | M: r.marek@assembler.cz | ||
1046 | L: lm-sensors@lm-sensors.org | ||
1047 | S: Maintained | ||
1048 | |||
1043 | COSA/SRP SYNC SERIAL DRIVER | 1049 | COSA/SRP SYNC SERIAL DRIVER |
1044 | P: Jan "Yenya" Kasprzak | 1050 | P: Jan "Yenya" Kasprzak |
1045 | M: kas@fi.muni.cz | 1051 | M: kas@fi.muni.cz |
@@ -2314,6 +2320,12 @@ M: vandrove@vc.cvut.cz | |||
2314 | L: linux-fbdev-devel@lists.sourceforge.net (subscribers-only) | 2320 | L: linux-fbdev-devel@lists.sourceforge.net (subscribers-only) |
2315 | S: Maintained | 2321 | S: Maintained |
2316 | 2322 | ||
2323 | MAX6650 HARDWARE MONITOR AND FAN CONTROLLER DRIVER | ||
2324 | P: Hans J. Koch | ||
2325 | M: hjk@linutronix.de | ||
2326 | L: lm-sensors@lm-sensors.org | ||
2327 | S: Maintained | ||
2328 | |||
2317 | MEGARAID SCSI DRIVERS | 2329 | MEGARAID SCSI DRIVERS |
2318 | P: Neela Syam Kolli | 2330 | P: Neela Syam Kolli |
2319 | M: Neela.Kolli@engenio.com | 2331 | M: Neela.Kolli@engenio.com |
diff --git a/arch/i386/kernel/msr.c b/arch/i386/kernel/msr.c index bcaa6e9b6197..8cd0a91ce107 100644 --- a/arch/i386/kernel/msr.c +++ b/arch/i386/kernel/msr.c | |||
@@ -45,104 +45,6 @@ | |||
45 | 45 | ||
46 | static struct class *msr_class; | 46 | static struct class *msr_class; |
47 | 47 | ||
48 | static inline int wrmsr_eio(u32 reg, u32 eax, u32 edx) | ||
49 | { | ||
50 | int err; | ||
51 | |||
52 | err = wrmsr_safe(reg, eax, edx); | ||
53 | if (err) | ||
54 | err = -EIO; | ||
55 | return err; | ||
56 | } | ||
57 | |||
58 | static inline int rdmsr_eio(u32 reg, u32 *eax, u32 *edx) | ||
59 | { | ||
60 | int err; | ||
61 | |||
62 | err = rdmsr_safe(reg, eax, edx); | ||
63 | if (err) | ||
64 | err = -EIO; | ||
65 | return err; | ||
66 | } | ||
67 | |||
68 | #ifdef CONFIG_SMP | ||
69 | |||
70 | struct msr_command { | ||
71 | int err; | ||
72 | u32 reg; | ||
73 | u32 data[2]; | ||
74 | }; | ||
75 | |||
76 | static void msr_smp_wrmsr(void *cmd_block) | ||
77 | { | ||
78 | struct msr_command *cmd = (struct msr_command *)cmd_block; | ||
79 | |||
80 | cmd->err = wrmsr_eio(cmd->reg, cmd->data[0], cmd->data[1]); | ||
81 | } | ||
82 | |||
83 | static void msr_smp_rdmsr(void *cmd_block) | ||
84 | { | ||
85 | struct msr_command *cmd = (struct msr_command *)cmd_block; | ||
86 | |||
87 | cmd->err = rdmsr_eio(cmd->reg, &cmd->data[0], &cmd->data[1]); | ||
88 | } | ||
89 | |||
90 | static inline int do_wrmsr(int cpu, u32 reg, u32 eax, u32 edx) | ||
91 | { | ||
92 | struct msr_command cmd; | ||
93 | int ret; | ||
94 | |||
95 | preempt_disable(); | ||
96 | if (cpu == smp_processor_id()) { | ||
97 | ret = wrmsr_eio(reg, eax, edx); | ||
98 | } else { | ||
99 | cmd.reg = reg; | ||
100 | cmd.data[0] = eax; | ||
101 | cmd.data[1] = edx; | ||
102 | |||
103 | smp_call_function_single(cpu, msr_smp_wrmsr, &cmd, 1, 1); | ||
104 | ret = cmd.err; | ||
105 | } | ||
106 | preempt_enable(); | ||
107 | return ret; | ||
108 | } | ||
109 | |||
110 | static inline int do_rdmsr(int cpu, u32 reg, u32 * eax, u32 * edx) | ||
111 | { | ||
112 | struct msr_command cmd; | ||
113 | int ret; | ||
114 | |||
115 | preempt_disable(); | ||
116 | if (cpu == smp_processor_id()) { | ||
117 | ret = rdmsr_eio(reg, eax, edx); | ||
118 | } else { | ||
119 | cmd.reg = reg; | ||
120 | |||
121 | smp_call_function_single(cpu, msr_smp_rdmsr, &cmd, 1, 1); | ||
122 | |||
123 | *eax = cmd.data[0]; | ||
124 | *edx = cmd.data[1]; | ||
125 | |||
126 | ret = cmd.err; | ||
127 | } | ||
128 | preempt_enable(); | ||
129 | return ret; | ||
130 | } | ||
131 | |||
132 | #else /* ! CONFIG_SMP */ | ||
133 | |||
134 | static inline int do_wrmsr(int cpu, u32 reg, u32 eax, u32 edx) | ||
135 | { | ||
136 | return wrmsr_eio(reg, eax, edx); | ||
137 | } | ||
138 | |||
139 | static inline int do_rdmsr(int cpu, u32 reg, u32 *eax, u32 *edx) | ||
140 | { | ||
141 | return rdmsr_eio(reg, eax, edx); | ||
142 | } | ||
143 | |||
144 | #endif /* ! CONFIG_SMP */ | ||
145 | |||
146 | static loff_t msr_seek(struct file *file, loff_t offset, int orig) | 48 | static loff_t msr_seek(struct file *file, loff_t offset, int orig) |
147 | { | 49 | { |
148 | loff_t ret = -EINVAL; | 50 | loff_t ret = -EINVAL; |
@@ -174,9 +76,9 @@ static ssize_t msr_read(struct file *file, char __user * buf, | |||
174 | return -EINVAL; /* Invalid chunk size */ | 76 | return -EINVAL; /* Invalid chunk size */ |
175 | 77 | ||
176 | for (; count; count -= 8) { | 78 | for (; count; count -= 8) { |
177 | err = do_rdmsr(cpu, reg, &data[0], &data[1]); | 79 | err = rdmsr_safe_on_cpu(cpu, reg, &data[0], &data[1]); |
178 | if (err) | 80 | if (err) |
179 | return err; | 81 | return -EIO; |
180 | if (copy_to_user(tmp, &data, 8)) | 82 | if (copy_to_user(tmp, &data, 8)) |
181 | return -EFAULT; | 83 | return -EFAULT; |
182 | tmp += 2; | 84 | tmp += 2; |
@@ -200,9 +102,9 @@ static ssize_t msr_write(struct file *file, const char __user *buf, | |||
200 | for (; count; count -= 8) { | 102 | for (; count; count -= 8) { |
201 | if (copy_from_user(&data, tmp, 8)) | 103 | if (copy_from_user(&data, tmp, 8)) |
202 | return -EFAULT; | 104 | return -EFAULT; |
203 | err = do_wrmsr(cpu, reg, data[0], data[1]); | 105 | err = wrmsr_safe_on_cpu(cpu, reg, data[0], data[1]); |
204 | if (err) | 106 | if (err) |
205 | return err; | 107 | return -EIO; |
206 | tmp += 2; | 108 | tmp += 2; |
207 | } | 109 | } |
208 | 110 | ||
diff --git a/arch/i386/lib/msr-on-cpu.c b/arch/i386/lib/msr-on-cpu.c index 1c46bda409ff..7767962f25d3 100644 --- a/arch/i386/lib/msr-on-cpu.c +++ b/arch/i386/lib/msr-on-cpu.c | |||
@@ -6,6 +6,7 @@ | |||
6 | struct msr_info { | 6 | struct msr_info { |
7 | u32 msr_no; | 7 | u32 msr_no; |
8 | u32 l, h; | 8 | u32 l, h; |
9 | int err; | ||
9 | }; | 10 | }; |
10 | 11 | ||
11 | static void __rdmsr_on_cpu(void *info) | 12 | static void __rdmsr_on_cpu(void *info) |
@@ -15,20 +16,38 @@ static void __rdmsr_on_cpu(void *info) | |||
15 | rdmsr(rv->msr_no, rv->l, rv->h); | 16 | rdmsr(rv->msr_no, rv->l, rv->h); |
16 | } | 17 | } |
17 | 18 | ||
18 | void rdmsr_on_cpu(unsigned int cpu, u32 msr_no, u32 *l, u32 *h) | 19 | static void __rdmsr_safe_on_cpu(void *info) |
19 | { | 20 | { |
21 | struct msr_info *rv = info; | ||
22 | |||
23 | rv->err = rdmsr_safe(rv->msr_no, &rv->l, &rv->h); | ||
24 | } | ||
25 | |||
26 | static int _rdmsr_on_cpu(unsigned int cpu, u32 msr_no, u32 *l, u32 *h, int safe) | ||
27 | { | ||
28 | int err = 0; | ||
20 | preempt_disable(); | 29 | preempt_disable(); |
21 | if (smp_processor_id() == cpu) | 30 | if (smp_processor_id() == cpu) |
22 | rdmsr(msr_no, *l, *h); | 31 | if (safe) |
32 | err = rdmsr_safe(msr_no, l, h); | ||
33 | else | ||
34 | rdmsr(msr_no, *l, *h); | ||
23 | else { | 35 | else { |
24 | struct msr_info rv; | 36 | struct msr_info rv; |
25 | 37 | ||
26 | rv.msr_no = msr_no; | 38 | rv.msr_no = msr_no; |
27 | smp_call_function_single(cpu, __rdmsr_on_cpu, &rv, 0, 1); | 39 | if (safe) { |
40 | smp_call_function_single(cpu, __rdmsr_safe_on_cpu, | ||
41 | &rv, 0, 1); | ||
42 | err = rv.err; | ||
43 | } else { | ||
44 | smp_call_function_single(cpu, __rdmsr_on_cpu, &rv, 0, 1); | ||
45 | } | ||
28 | *l = rv.l; | 46 | *l = rv.l; |
29 | *h = rv.h; | 47 | *h = rv.h; |
30 | } | 48 | } |
31 | preempt_enable(); | 49 | preempt_enable(); |
50 | return err; | ||
32 | } | 51 | } |
33 | 52 | ||
34 | static void __wrmsr_on_cpu(void *info) | 53 | static void __wrmsr_on_cpu(void *info) |
@@ -38,21 +57,63 @@ static void __wrmsr_on_cpu(void *info) | |||
38 | wrmsr(rv->msr_no, rv->l, rv->h); | 57 | wrmsr(rv->msr_no, rv->l, rv->h); |
39 | } | 58 | } |
40 | 59 | ||
41 | void wrmsr_on_cpu(unsigned int cpu, u32 msr_no, u32 l, u32 h) | 60 | static void __wrmsr_safe_on_cpu(void *info) |
42 | { | 61 | { |
62 | struct msr_info *rv = info; | ||
63 | |||
64 | rv->err = wrmsr_safe(rv->msr_no, rv->l, rv->h); | ||
65 | } | ||
66 | |||
67 | static int _wrmsr_on_cpu(unsigned int cpu, u32 msr_no, u32 l, u32 h, int safe) | ||
68 | { | ||
69 | int err = 0; | ||
43 | preempt_disable(); | 70 | preempt_disable(); |
44 | if (smp_processor_id() == cpu) | 71 | if (smp_processor_id() == cpu) |
45 | wrmsr(msr_no, l, h); | 72 | if (safe) |
73 | err = wrmsr_safe(msr_no, l, h); | ||
74 | else | ||
75 | wrmsr(msr_no, l, h); | ||
46 | else { | 76 | else { |
47 | struct msr_info rv; | 77 | struct msr_info rv; |
48 | 78 | ||
49 | rv.msr_no = msr_no; | 79 | rv.msr_no = msr_no; |
50 | rv.l = l; | 80 | rv.l = l; |
51 | rv.h = h; | 81 | rv.h = h; |
52 | smp_call_function_single(cpu, __wrmsr_on_cpu, &rv, 0, 1); | 82 | if (safe) { |
83 | smp_call_function_single(cpu, __wrmsr_safe_on_cpu, | ||
84 | &rv, 0, 1); | ||
85 | err = rv.err; | ||
86 | } else { | ||
87 | smp_call_function_single(cpu, __wrmsr_on_cpu, &rv, 0, 1); | ||
88 | } | ||
53 | } | 89 | } |
54 | preempt_enable(); | 90 | preempt_enable(); |
91 | return err; | ||
92 | } | ||
93 | |||
94 | void wrmsr_on_cpu(unsigned int cpu, u32 msr_no, u32 l, u32 h) | ||
95 | { | ||
96 | _wrmsr_on_cpu(cpu, msr_no, l, h, 0); | ||
97 | } | ||
98 | |||
99 | void rdmsr_on_cpu(unsigned int cpu, u32 msr_no, u32 *l, u32 *h) | ||
100 | { | ||
101 | _rdmsr_on_cpu(cpu, msr_no, l, h, 0); | ||
102 | } | ||
103 | |||
104 | /* These "safe" variants are slower and should be used when the target MSR | ||
105 | may not actually exist. */ | ||
106 | int wrmsr_safe_on_cpu(unsigned int cpu, u32 msr_no, u32 l, u32 h) | ||
107 | { | ||
108 | return _wrmsr_on_cpu(cpu, msr_no, l, h, 1); | ||
109 | } | ||
110 | |||
111 | int rdmsr_safe_on_cpu(unsigned int cpu, u32 msr_no, u32 *l, u32 *h) | ||
112 | { | ||
113 | return _rdmsr_on_cpu(cpu, msr_no, l, h, 1); | ||
55 | } | 114 | } |
56 | 115 | ||
57 | EXPORT_SYMBOL(rdmsr_on_cpu); | 116 | EXPORT_SYMBOL(rdmsr_on_cpu); |
58 | EXPORT_SYMBOL(wrmsr_on_cpu); | 117 | EXPORT_SYMBOL(wrmsr_on_cpu); |
118 | EXPORT_SYMBOL(rdmsr_safe_on_cpu); | ||
119 | EXPORT_SYMBOL(wrmsr_safe_on_cpu); | ||
diff --git a/drivers/hwmon/Kconfig b/drivers/hwmon/Kconfig index 25b72a491702..3ba3a5221c41 100644 --- a/drivers/hwmon/Kconfig +++ b/drivers/hwmon/Kconfig | |||
@@ -2,9 +2,7 @@ | |||
2 | # Hardware monitoring chip drivers configuration | 2 | # Hardware monitoring chip drivers configuration |
3 | # | 3 | # |
4 | 4 | ||
5 | menu "Hardware Monitoring support" | 5 | menuconfig HWMON |
6 | |||
7 | config HWMON | ||
8 | tristate "Hardware Monitoring support" | 6 | tristate "Hardware Monitoring support" |
9 | default y | 7 | default y |
10 | help | 8 | help |
@@ -23,13 +21,15 @@ config HWMON | |||
23 | This support can also be built as a module. If so, the module | 21 | This support can also be built as a module. If so, the module |
24 | will be called hwmon. | 22 | will be called hwmon. |
25 | 23 | ||
24 | if HWMON | ||
25 | |||
26 | config HWMON_VID | 26 | config HWMON_VID |
27 | tristate | 27 | tristate |
28 | default n | 28 | default n |
29 | 29 | ||
30 | config SENSORS_ABITUGURU | 30 | config SENSORS_ABITUGURU |
31 | tristate "Abit uGuru" | 31 | tristate "Abit uGuru" |
32 | depends on HWMON && EXPERIMENTAL | 32 | depends on EXPERIMENTAL |
33 | help | 33 | help |
34 | If you say yes here you get support for the Abit uGuru chips | 34 | If you say yes here you get support for the Abit uGuru chips |
35 | sensor part. The voltage and frequency control parts of the Abit | 35 | sensor part. The voltage and frequency control parts of the Abit |
@@ -39,9 +39,19 @@ config SENSORS_ABITUGURU | |||
39 | This driver can also be built as a module. If so, the module | 39 | This driver can also be built as a module. If so, the module |
40 | will be called abituguru. | 40 | will be called abituguru. |
41 | 41 | ||
42 | config SENSORS_AD7418 | ||
43 | tristate "Analog Devices AD7416, AD7417 and AD7418" | ||
44 | depends on I2C && EXPERIMENTAL | ||
45 | help | ||
46 | If you say yes here you get support for the Analog Devices | ||
47 | AD7416, AD7417 and AD7418 temperature monitoring chips. | ||
48 | |||
49 | This driver can also be built as a module. If so, the module | ||
50 | will be called ad7418. | ||
51 | |||
42 | config SENSORS_ADM1021 | 52 | config SENSORS_ADM1021 |
43 | tristate "Analog Devices ADM1021 and compatibles" | 53 | tristate "Analog Devices ADM1021 and compatibles" |
44 | depends on HWMON && I2C | 54 | depends on I2C |
45 | help | 55 | help |
46 | If you say yes here you get support for Analog Devices ADM1021 | 56 | If you say yes here you get support for Analog Devices ADM1021 |
47 | and ADM1023 sensor chips and clones: Maxim MAX1617 and MAX1617A, | 57 | and ADM1023 sensor chips and clones: Maxim MAX1617 and MAX1617A, |
@@ -53,7 +63,7 @@ config SENSORS_ADM1021 | |||
53 | 63 | ||
54 | config SENSORS_ADM1025 | 64 | config SENSORS_ADM1025 |
55 | tristate "Analog Devices ADM1025 and compatibles" | 65 | tristate "Analog Devices ADM1025 and compatibles" |
56 | depends on HWMON && I2C | 66 | depends on I2C |
57 | select HWMON_VID | 67 | select HWMON_VID |
58 | help | 68 | help |
59 | If you say yes here you get support for Analog Devices ADM1025 | 69 | If you say yes here you get support for Analog Devices ADM1025 |
@@ -64,7 +74,7 @@ config SENSORS_ADM1025 | |||
64 | 74 | ||
65 | config SENSORS_ADM1026 | 75 | config SENSORS_ADM1026 |
66 | tristate "Analog Devices ADM1026 and compatibles" | 76 | tristate "Analog Devices ADM1026 and compatibles" |
67 | depends on HWMON && I2C && EXPERIMENTAL | 77 | depends on I2C && EXPERIMENTAL |
68 | select HWMON_VID | 78 | select HWMON_VID |
69 | help | 79 | help |
70 | If you say yes here you get support for Analog Devices ADM1026 | 80 | If you say yes here you get support for Analog Devices ADM1026 |
@@ -75,7 +85,7 @@ config SENSORS_ADM1026 | |||
75 | 85 | ||
76 | config SENSORS_ADM1029 | 86 | config SENSORS_ADM1029 |
77 | tristate "Analog Devices ADM1029" | 87 | tristate "Analog Devices ADM1029" |
78 | depends on HWMON && I2C && EXPERIMENTAL | 88 | depends on I2C && EXPERIMENTAL |
79 | help | 89 | help |
80 | If you say yes here you get support for Analog Devices ADM1029 | 90 | If you say yes here you get support for Analog Devices ADM1029 |
81 | sensor chip. | 91 | sensor chip. |
@@ -86,7 +96,7 @@ config SENSORS_ADM1029 | |||
86 | 96 | ||
87 | config SENSORS_ADM1031 | 97 | config SENSORS_ADM1031 |
88 | tristate "Analog Devices ADM1031 and compatibles" | 98 | tristate "Analog Devices ADM1031 and compatibles" |
89 | depends on HWMON && I2C && EXPERIMENTAL | 99 | depends on I2C && EXPERIMENTAL |
90 | help | 100 | help |
91 | If you say yes here you get support for Analog Devices ADM1031 | 101 | If you say yes here you get support for Analog Devices ADM1031 |
92 | and ADM1030 sensor chips. | 102 | and ADM1030 sensor chips. |
@@ -96,7 +106,7 @@ config SENSORS_ADM1031 | |||
96 | 106 | ||
97 | config SENSORS_ADM9240 | 107 | config SENSORS_ADM9240 |
98 | tristate "Analog Devices ADM9240 and compatibles" | 108 | tristate "Analog Devices ADM9240 and compatibles" |
99 | depends on HWMON && I2C && EXPERIMENTAL | 109 | depends on I2C && EXPERIMENTAL |
100 | select HWMON_VID | 110 | select HWMON_VID |
101 | help | 111 | help |
102 | If you say yes here you get support for Analog Devices ADM9240, | 112 | If you say yes here you get support for Analog Devices ADM9240, |
@@ -107,7 +117,7 @@ config SENSORS_ADM9240 | |||
107 | 117 | ||
108 | config SENSORS_K8TEMP | 118 | config SENSORS_K8TEMP |
109 | tristate "AMD Athlon64/FX or Opteron temperature sensor" | 119 | tristate "AMD Athlon64/FX or Opteron temperature sensor" |
110 | depends on HWMON && X86 && PCI && EXPERIMENTAL | 120 | depends on X86 && PCI && EXPERIMENTAL |
111 | help | 121 | help |
112 | If you say yes here you get support for the temperature | 122 | If you say yes here you get support for the temperature |
113 | sensor(s) inside your CPU. Supported is whole AMD K8 | 123 | sensor(s) inside your CPU. Supported is whole AMD K8 |
@@ -119,7 +129,7 @@ config SENSORS_K8TEMP | |||
119 | 129 | ||
120 | config SENSORS_AMS | 130 | config SENSORS_AMS |
121 | tristate "Apple Motion Sensor driver" | 131 | tristate "Apple Motion Sensor driver" |
122 | depends on HWMON && PPC_PMAC && !PPC64 && INPUT && ((ADB_PMU && I2C = y) || (ADB_PMU && !I2C) || I2C) && EXPERIMENTAL | 132 | depends on PPC_PMAC && !PPC64 && INPUT && ((ADB_PMU && I2C = y) || (ADB_PMU && !I2C) || I2C) && EXPERIMENTAL |
123 | help | 133 | help |
124 | Support for the motion sensor included in PowerBooks. Includes | 134 | Support for the motion sensor included in PowerBooks. Includes |
125 | implementations for PMU and I2C. | 135 | implementations for PMU and I2C. |
@@ -144,7 +154,7 @@ config SENSORS_AMS_I2C | |||
144 | 154 | ||
145 | config SENSORS_ASB100 | 155 | config SENSORS_ASB100 |
146 | tristate "Asus ASB100 Bach" | 156 | tristate "Asus ASB100 Bach" |
147 | depends on HWMON && I2C && EXPERIMENTAL | 157 | depends on I2C && EXPERIMENTAL |
148 | select HWMON_VID | 158 | select HWMON_VID |
149 | help | 159 | help |
150 | If you say yes here you get support for the ASB100 Bach sensor | 160 | If you say yes here you get support for the ASB100 Bach sensor |
@@ -155,7 +165,7 @@ config SENSORS_ASB100 | |||
155 | 165 | ||
156 | config SENSORS_ATXP1 | 166 | config SENSORS_ATXP1 |
157 | tristate "Attansic ATXP1 VID controller" | 167 | tristate "Attansic ATXP1 VID controller" |
158 | depends on HWMON && I2C && EXPERIMENTAL | 168 | depends on I2C && EXPERIMENTAL |
159 | select HWMON_VID | 169 | select HWMON_VID |
160 | help | 170 | help |
161 | If you say yes here you get support for the Attansic ATXP1 VID | 171 | If you say yes here you get support for the Attansic ATXP1 VID |
@@ -169,7 +179,7 @@ config SENSORS_ATXP1 | |||
169 | 179 | ||
170 | config SENSORS_DS1621 | 180 | config SENSORS_DS1621 |
171 | tristate "Dallas Semiconductor DS1621 and DS1625" | 181 | tristate "Dallas Semiconductor DS1621 and DS1625" |
172 | depends on HWMON && I2C | 182 | depends on I2C |
173 | help | 183 | help |
174 | If you say yes here you get support for Dallas Semiconductor | 184 | If you say yes here you get support for Dallas Semiconductor |
175 | DS1621 and DS1625 sensor chips. | 185 | DS1621 and DS1625 sensor chips. |
@@ -179,7 +189,7 @@ config SENSORS_DS1621 | |||
179 | 189 | ||
180 | config SENSORS_F71805F | 190 | config SENSORS_F71805F |
181 | tristate "Fintek F71805F/FG and F71872F/FG" | 191 | tristate "Fintek F71805F/FG and F71872F/FG" |
182 | depends on HWMON && EXPERIMENTAL | 192 | depends on EXPERIMENTAL |
183 | help | 193 | help |
184 | If you say yes here you get support for hardware monitoring | 194 | If you say yes here you get support for hardware monitoring |
185 | features of the Fintek F71805F/FG and F71872F/FG Super-I/O | 195 | features of the Fintek F71805F/FG and F71872F/FG Super-I/O |
@@ -190,7 +200,7 @@ config SENSORS_F71805F | |||
190 | 200 | ||
191 | config SENSORS_FSCHER | 201 | config SENSORS_FSCHER |
192 | tristate "FSC Hermes" | 202 | tristate "FSC Hermes" |
193 | depends on HWMON && I2C | 203 | depends on I2C |
194 | help | 204 | help |
195 | If you say yes here you get support for Fujitsu Siemens | 205 | If you say yes here you get support for Fujitsu Siemens |
196 | Computers Hermes sensor chips. | 206 | Computers Hermes sensor chips. |
@@ -200,7 +210,7 @@ config SENSORS_FSCHER | |||
200 | 210 | ||
201 | config SENSORS_FSCPOS | 211 | config SENSORS_FSCPOS |
202 | tristate "FSC Poseidon" | 212 | tristate "FSC Poseidon" |
203 | depends on HWMON && I2C | 213 | depends on I2C |
204 | help | 214 | help |
205 | If you say yes here you get support for Fujitsu Siemens | 215 | If you say yes here you get support for Fujitsu Siemens |
206 | Computers Poseidon sensor chips. | 216 | Computers Poseidon sensor chips. |
@@ -210,7 +220,7 @@ config SENSORS_FSCPOS | |||
210 | 220 | ||
211 | config SENSORS_GL518SM | 221 | config SENSORS_GL518SM |
212 | tristate "Genesys Logic GL518SM" | 222 | tristate "Genesys Logic GL518SM" |
213 | depends on HWMON && I2C | 223 | depends on I2C |
214 | help | 224 | help |
215 | If you say yes here you get support for Genesys Logic GL518SM | 225 | If you say yes here you get support for Genesys Logic GL518SM |
216 | sensor chips. | 226 | sensor chips. |
@@ -220,7 +230,7 @@ config SENSORS_GL518SM | |||
220 | 230 | ||
221 | config SENSORS_GL520SM | 231 | config SENSORS_GL520SM |
222 | tristate "Genesys Logic GL520SM" | 232 | tristate "Genesys Logic GL520SM" |
223 | depends on HWMON && I2C | 233 | depends on I2C |
224 | select HWMON_VID | 234 | select HWMON_VID |
225 | help | 235 | help |
226 | If you say yes here you get support for Genesys Logic GL520SM | 236 | If you say yes here you get support for Genesys Logic GL520SM |
@@ -229,9 +239,17 @@ config SENSORS_GL520SM | |||
229 | This driver can also be built as a module. If so, the module | 239 | This driver can also be built as a module. If so, the module |
230 | will be called gl520sm. | 240 | will be called gl520sm. |
231 | 241 | ||
242 | config SENSORS_CORETEMP | ||
243 | tristate "Intel Core (2) Duo/Solo temperature sensor" | ||
244 | depends on X86 && EXPERIMENTAL | ||
245 | help | ||
246 | If you say yes here you get support for the temperature | ||
247 | sensor inside your CPU. Supported all are all known variants | ||
248 | of Intel Core family. | ||
249 | |||
232 | config SENSORS_IT87 | 250 | config SENSORS_IT87 |
233 | tristate "ITE IT87xx and compatibles" | 251 | tristate "ITE IT87xx and compatibles" |
234 | depends on HWMON && I2C | 252 | depends on I2C |
235 | select I2C_ISA | 253 | select I2C_ISA |
236 | select HWMON_VID | 254 | select HWMON_VID |
237 | help | 255 | help |
@@ -243,7 +261,7 @@ config SENSORS_IT87 | |||
243 | 261 | ||
244 | config SENSORS_LM63 | 262 | config SENSORS_LM63 |
245 | tristate "National Semiconductor LM63" | 263 | tristate "National Semiconductor LM63" |
246 | depends on HWMON && I2C | 264 | depends on I2C |
247 | help | 265 | help |
248 | If you say yes here you get support for the National Semiconductor | 266 | If you say yes here you get support for the National Semiconductor |
249 | LM63 remote diode digital temperature sensor with integrated fan | 267 | LM63 remote diode digital temperature sensor with integrated fan |
@@ -255,7 +273,7 @@ config SENSORS_LM63 | |||
255 | 273 | ||
256 | config SENSORS_LM70 | 274 | config SENSORS_LM70 |
257 | tristate "National Semiconductor LM70" | 275 | tristate "National Semiconductor LM70" |
258 | depends on HWMON && SPI_MASTER && EXPERIMENTAL | 276 | depends on SPI_MASTER && EXPERIMENTAL |
259 | help | 277 | help |
260 | If you say yes here you get support for the National Semiconductor | 278 | If you say yes here you get support for the National Semiconductor |
261 | LM70 digital temperature sensor chip. | 279 | LM70 digital temperature sensor chip. |
@@ -265,7 +283,7 @@ config SENSORS_LM70 | |||
265 | 283 | ||
266 | config SENSORS_LM75 | 284 | config SENSORS_LM75 |
267 | tristate "National Semiconductor LM75 and compatibles" | 285 | tristate "National Semiconductor LM75 and compatibles" |
268 | depends on HWMON && I2C | 286 | depends on I2C |
269 | help | 287 | help |
270 | If you say yes here you get support for National Semiconductor LM75 | 288 | If you say yes here you get support for National Semiconductor LM75 |
271 | sensor chips and clones: Dallas Semiconductor DS75 and DS1775 (in | 289 | sensor chips and clones: Dallas Semiconductor DS75 and DS1775 (in |
@@ -280,7 +298,7 @@ config SENSORS_LM75 | |||
280 | 298 | ||
281 | config SENSORS_LM77 | 299 | config SENSORS_LM77 |
282 | tristate "National Semiconductor LM77" | 300 | tristate "National Semiconductor LM77" |
283 | depends on HWMON && I2C | 301 | depends on I2C |
284 | help | 302 | help |
285 | If you say yes here you get support for National Semiconductor LM77 | 303 | If you say yes here you get support for National Semiconductor LM77 |
286 | sensor chips. | 304 | sensor chips. |
@@ -290,8 +308,7 @@ config SENSORS_LM77 | |||
290 | 308 | ||
291 | config SENSORS_LM78 | 309 | config SENSORS_LM78 |
292 | tristate "National Semiconductor LM78 and compatibles" | 310 | tristate "National Semiconductor LM78 and compatibles" |
293 | depends on HWMON && I2C | 311 | depends on I2C |
294 | select I2C_ISA | ||
295 | select HWMON_VID | 312 | select HWMON_VID |
296 | help | 313 | help |
297 | If you say yes here you get support for National Semiconductor LM78, | 314 | If you say yes here you get support for National Semiconductor LM78, |
@@ -302,7 +319,7 @@ config SENSORS_LM78 | |||
302 | 319 | ||
303 | config SENSORS_LM80 | 320 | config SENSORS_LM80 |
304 | tristate "National Semiconductor LM80" | 321 | tristate "National Semiconductor LM80" |
305 | depends on HWMON && I2C && EXPERIMENTAL | 322 | depends on I2C && EXPERIMENTAL |
306 | help | 323 | help |
307 | If you say yes here you get support for National Semiconductor | 324 | If you say yes here you get support for National Semiconductor |
308 | LM80 sensor chips. | 325 | LM80 sensor chips. |
@@ -312,7 +329,7 @@ config SENSORS_LM80 | |||
312 | 329 | ||
313 | config SENSORS_LM83 | 330 | config SENSORS_LM83 |
314 | tristate "National Semiconductor LM83 and compatibles" | 331 | tristate "National Semiconductor LM83 and compatibles" |
315 | depends on HWMON && I2C | 332 | depends on I2C |
316 | help | 333 | help |
317 | If you say yes here you get support for National Semiconductor | 334 | If you say yes here you get support for National Semiconductor |
318 | LM82 and LM83 sensor chips. | 335 | LM82 and LM83 sensor chips. |
@@ -322,7 +339,7 @@ config SENSORS_LM83 | |||
322 | 339 | ||
323 | config SENSORS_LM85 | 340 | config SENSORS_LM85 |
324 | tristate "National Semiconductor LM85 and compatibles" | 341 | tristate "National Semiconductor LM85 and compatibles" |
325 | depends on HWMON && I2C && EXPERIMENTAL | 342 | depends on I2C && EXPERIMENTAL |
326 | select HWMON_VID | 343 | select HWMON_VID |
327 | help | 344 | help |
328 | If you say yes here you get support for National Semiconductor LM85 | 345 | If you say yes here you get support for National Semiconductor LM85 |
@@ -333,7 +350,7 @@ config SENSORS_LM85 | |||
333 | 350 | ||
334 | config SENSORS_LM87 | 351 | config SENSORS_LM87 |
335 | tristate "National Semiconductor LM87" | 352 | tristate "National Semiconductor LM87" |
336 | depends on HWMON && I2C | 353 | depends on I2C |
337 | select HWMON_VID | 354 | select HWMON_VID |
338 | help | 355 | help |
339 | If you say yes here you get support for National Semiconductor LM87 | 356 | If you say yes here you get support for National Semiconductor LM87 |
@@ -344,7 +361,7 @@ config SENSORS_LM87 | |||
344 | 361 | ||
345 | config SENSORS_LM90 | 362 | config SENSORS_LM90 |
346 | tristate "National Semiconductor LM90 and compatibles" | 363 | tristate "National Semiconductor LM90 and compatibles" |
347 | depends on HWMON && I2C | 364 | depends on I2C |
348 | help | 365 | help |
349 | If you say yes here you get support for National Semiconductor LM90, | 366 | If you say yes here you get support for National Semiconductor LM90, |
350 | LM86, LM89 and LM99, Analog Devices ADM1032 and Maxim MAX6657 and | 367 | LM86, LM89 and LM99, Analog Devices ADM1032 and Maxim MAX6657 and |
@@ -358,7 +375,7 @@ config SENSORS_LM90 | |||
358 | 375 | ||
359 | config SENSORS_LM92 | 376 | config SENSORS_LM92 |
360 | tristate "National Semiconductor LM92 and compatibles" | 377 | tristate "National Semiconductor LM92 and compatibles" |
361 | depends on HWMON && I2C | 378 | depends on I2C |
362 | help | 379 | help |
363 | If you say yes here you get support for National Semiconductor LM92 | 380 | If you say yes here you get support for National Semiconductor LM92 |
364 | and Maxim MAX6635 sensor chips. | 381 | and Maxim MAX6635 sensor chips. |
@@ -368,16 +385,26 @@ config SENSORS_LM92 | |||
368 | 385 | ||
369 | config SENSORS_MAX1619 | 386 | config SENSORS_MAX1619 |
370 | tristate "Maxim MAX1619 sensor chip" | 387 | tristate "Maxim MAX1619 sensor chip" |
371 | depends on HWMON && I2C | 388 | depends on I2C |
372 | help | 389 | help |
373 | If you say yes here you get support for MAX1619 sensor chip. | 390 | If you say yes here you get support for MAX1619 sensor chip. |
374 | 391 | ||
375 | This driver can also be built as a module. If so, the module | 392 | This driver can also be built as a module. If so, the module |
376 | will be called max1619. | 393 | will be called max1619. |
377 | 394 | ||
395 | config SENSORS_MAX6650 | ||
396 | tristate "Maxim MAX6650 sensor chip" | ||
397 | depends on I2C && EXPERIMENTAL | ||
398 | help | ||
399 | If you say yes here you get support for the MAX6650 / MAX6651 | ||
400 | sensor chips. | ||
401 | |||
402 | This driver can also be built as a module. If so, the module | ||
403 | will be called max6650. | ||
404 | |||
378 | config SENSORS_PC87360 | 405 | config SENSORS_PC87360 |
379 | tristate "National Semiconductor PC87360 family" | 406 | tristate "National Semiconductor PC87360 family" |
380 | depends on HWMON && I2C && EXPERIMENTAL | 407 | depends on I2C && EXPERIMENTAL |
381 | select I2C_ISA | 408 | select I2C_ISA |
382 | select HWMON_VID | 409 | select HWMON_VID |
383 | help | 410 | help |
@@ -392,7 +419,7 @@ config SENSORS_PC87360 | |||
392 | 419 | ||
393 | config SENSORS_PC87427 | 420 | config SENSORS_PC87427 |
394 | tristate "National Semiconductor PC87427" | 421 | tristate "National Semiconductor PC87427" |
395 | depends on HWMON && EXPERIMENTAL | 422 | depends on EXPERIMENTAL |
396 | help | 423 | help |
397 | If you say yes here you get access to the hardware monitoring | 424 | If you say yes here you get access to the hardware monitoring |
398 | functions of the National Semiconductor PC87427 Super-I/O chip. | 425 | functions of the National Semiconductor PC87427 Super-I/O chip. |
@@ -405,7 +432,7 @@ config SENSORS_PC87427 | |||
405 | 432 | ||
406 | config SENSORS_SIS5595 | 433 | config SENSORS_SIS5595 |
407 | tristate "Silicon Integrated Systems Corp. SiS5595" | 434 | tristate "Silicon Integrated Systems Corp. SiS5595" |
408 | depends on HWMON && I2C && PCI && EXPERIMENTAL | 435 | depends on I2C && PCI && EXPERIMENTAL |
409 | select I2C_ISA | 436 | select I2C_ISA |
410 | help | 437 | help |
411 | If you say yes here you get support for the integrated sensors in | 438 | If you say yes here you get support for the integrated sensors in |
@@ -416,28 +443,28 @@ config SENSORS_SIS5595 | |||
416 | 443 | ||
417 | config SENSORS_SMSC47M1 | 444 | config SENSORS_SMSC47M1 |
418 | tristate "SMSC LPC47M10x and compatibles" | 445 | tristate "SMSC LPC47M10x and compatibles" |
419 | depends on HWMON && I2C | ||
420 | select I2C_ISA | ||
421 | help | 446 | help |
422 | If you say yes here you get support for the integrated fan | 447 | If you say yes here you get support for the integrated fan |
423 | monitoring and control capabilities of the SMSC LPC47B27x, | 448 | monitoring and control capabilities of the SMSC LPC47B27x, |
424 | LPC47M10x, LPC47M112, LPC47M13x, LPC47M14x, LPC47M15x, | 449 | LPC47M10x, LPC47M112, LPC47M13x, LPC47M14x, LPC47M15x, |
425 | LPC47M192 and LPC47M997 chips. | 450 | LPC47M192, LPC47M292 and LPC47M997 chips. |
426 | 451 | ||
427 | The temperature and voltage sensor features of the LPC47M192 | 452 | The temperature and voltage sensor features of the LPC47M15x, |
428 | and LPC47M997 are supported by another driver, select also | 453 | LPC47M192, LPC47M292 and LPC47M997 are supported by another |
429 | "SMSC LPC47M192 and compatibles" below for those. | 454 | driver, select also "SMSC LPC47M192 and compatibles" below for |
455 | those. | ||
430 | 456 | ||
431 | This driver can also be built as a module. If so, the module | 457 | This driver can also be built as a module. If so, the module |
432 | will be called smsc47m1. | 458 | will be called smsc47m1. |
433 | 459 | ||
434 | config SENSORS_SMSC47M192 | 460 | config SENSORS_SMSC47M192 |
435 | tristate "SMSC LPC47M192 and compatibles" | 461 | tristate "SMSC LPC47M192 and compatibles" |
436 | depends on HWMON && I2C && EXPERIMENTAL | 462 | depends on I2C && EXPERIMENTAL |
437 | select HWMON_VID | 463 | select HWMON_VID |
438 | help | 464 | help |
439 | If you say yes here you get support for the temperature and | 465 | If you say yes here you get support for the temperature and |
440 | voltage sensors of the SMSC LPC47M192 and LPC47M997 chips. | 466 | voltage sensors of the SMSC LPC47M192, LPC47M15x, LPC47M292 |
467 | and LPC47M997 chips. | ||
441 | 468 | ||
442 | The fan monitoring and control capabilities of these chips | 469 | The fan monitoring and control capabilities of these chips |
443 | are supported by another driver, select | 470 | are supported by another driver, select |
@@ -449,8 +476,7 @@ config SENSORS_SMSC47M192 | |||
449 | 476 | ||
450 | config SENSORS_SMSC47B397 | 477 | config SENSORS_SMSC47B397 |
451 | tristate "SMSC LPC47B397-NC" | 478 | tristate "SMSC LPC47B397-NC" |
452 | depends on HWMON && I2C && EXPERIMENTAL | 479 | depends on EXPERIMENTAL |
453 | select I2C_ISA | ||
454 | help | 480 | help |
455 | If you say yes here you get support for the SMSC LPC47B397-NC | 481 | If you say yes here you get support for the SMSC LPC47B397-NC |
456 | sensor chip. | 482 | sensor chip. |
@@ -460,7 +486,7 @@ config SENSORS_SMSC47B397 | |||
460 | 486 | ||
461 | config SENSORS_VIA686A | 487 | config SENSORS_VIA686A |
462 | tristate "VIA686A" | 488 | tristate "VIA686A" |
463 | depends on HWMON && I2C && PCI | 489 | depends on I2C && PCI |
464 | select I2C_ISA | 490 | select I2C_ISA |
465 | help | 491 | help |
466 | If you say yes here you get support for the integrated sensors in | 492 | If you say yes here you get support for the integrated sensors in |
@@ -471,7 +497,7 @@ config SENSORS_VIA686A | |||
471 | 497 | ||
472 | config SENSORS_VT1211 | 498 | config SENSORS_VT1211 |
473 | tristate "VIA VT1211" | 499 | tristate "VIA VT1211" |
474 | depends on HWMON && EXPERIMENTAL | 500 | depends on EXPERIMENTAL |
475 | select HWMON_VID | 501 | select HWMON_VID |
476 | help | 502 | help |
477 | If you say yes here then you get support for hardware monitoring | 503 | If you say yes here then you get support for hardware monitoring |
@@ -482,7 +508,7 @@ config SENSORS_VT1211 | |||
482 | 508 | ||
483 | config SENSORS_VT8231 | 509 | config SENSORS_VT8231 |
484 | tristate "VIA VT8231" | 510 | tristate "VIA VT8231" |
485 | depends on HWMON && I2C && PCI && EXPERIMENTAL | 511 | depends on I2C && PCI && EXPERIMENTAL |
486 | select HWMON_VID | 512 | select HWMON_VID |
487 | select I2C_ISA | 513 | select I2C_ISA |
488 | help | 514 | help |
@@ -494,8 +520,7 @@ config SENSORS_VT8231 | |||
494 | 520 | ||
495 | config SENSORS_W83781D | 521 | config SENSORS_W83781D |
496 | tristate "Winbond W83781D, W83782D, W83783S, W83627HF, Asus AS99127F" | 522 | tristate "Winbond W83781D, W83782D, W83783S, W83627HF, Asus AS99127F" |
497 | depends on HWMON && I2C | 523 | depends on I2C |
498 | select I2C_ISA | ||
499 | select HWMON_VID | 524 | select HWMON_VID |
500 | help | 525 | help |
501 | If you say yes here you get support for the Winbond W8378x series | 526 | If you say yes here you get support for the Winbond W8378x series |
@@ -507,7 +532,7 @@ config SENSORS_W83781D | |||
507 | 532 | ||
508 | config SENSORS_W83791D | 533 | config SENSORS_W83791D |
509 | tristate "Winbond W83791D" | 534 | tristate "Winbond W83791D" |
510 | depends on HWMON && I2C && EXPERIMENTAL | 535 | depends on I2C && EXPERIMENTAL |
511 | select HWMON_VID | 536 | select HWMON_VID |
512 | help | 537 | help |
513 | If you say yes here you get support for the Winbond W83791D chip. | 538 | If you say yes here you get support for the Winbond W83791D chip. |
@@ -517,7 +542,7 @@ config SENSORS_W83791D | |||
517 | 542 | ||
518 | config SENSORS_W83792D | 543 | config SENSORS_W83792D |
519 | tristate "Winbond W83792D" | 544 | tristate "Winbond W83792D" |
520 | depends on HWMON && I2C && EXPERIMENTAL | 545 | depends on I2C && EXPERIMENTAL |
521 | help | 546 | help |
522 | If you say yes here you get support for the Winbond W83792D chip. | 547 | If you say yes here you get support for the Winbond W83792D chip. |
523 | 548 | ||
@@ -526,7 +551,7 @@ config SENSORS_W83792D | |||
526 | 551 | ||
527 | config SENSORS_W83793 | 552 | config SENSORS_W83793 |
528 | tristate "Winbond W83793" | 553 | tristate "Winbond W83793" |
529 | depends on HWMON && I2C && EXPERIMENTAL | 554 | depends on I2C && EXPERIMENTAL |
530 | select HWMON_VID | 555 | select HWMON_VID |
531 | help | 556 | help |
532 | If you say yes here you get support for the Winbond W83793 | 557 | If you say yes here you get support for the Winbond W83793 |
@@ -537,7 +562,7 @@ config SENSORS_W83793 | |||
537 | 562 | ||
538 | config SENSORS_W83L785TS | 563 | config SENSORS_W83L785TS |
539 | tristate "Winbond W83L785TS-S" | 564 | tristate "Winbond W83L785TS-S" |
540 | depends on HWMON && I2C && EXPERIMENTAL | 565 | depends on I2C && EXPERIMENTAL |
541 | help | 566 | help |
542 | If you say yes here you get support for the Winbond W83L785TS-S | 567 | If you say yes here you get support for the Winbond W83L785TS-S |
543 | sensor chip, which is used on the Asus A7N8X, among other | 568 | sensor chip, which is used on the Asus A7N8X, among other |
@@ -548,8 +573,6 @@ config SENSORS_W83L785TS | |||
548 | 573 | ||
549 | config SENSORS_W83627HF | 574 | config SENSORS_W83627HF |
550 | tristate "Winbond W83627HF, W83627THF, W83637HF, W83687THF, W83697HF" | 575 | tristate "Winbond W83627HF, W83627THF, W83637HF, W83687THF, W83697HF" |
551 | depends on HWMON && I2C | ||
552 | select I2C_ISA | ||
553 | select HWMON_VID | 576 | select HWMON_VID |
554 | help | 577 | help |
555 | If you say yes here you get support for the Winbond W836X7 series | 578 | If you say yes here you get support for the Winbond W836X7 series |
@@ -561,7 +584,7 @@ config SENSORS_W83627HF | |||
561 | 584 | ||
562 | config SENSORS_W83627EHF | 585 | config SENSORS_W83627EHF |
563 | tristate "Winbond W83627EHF" | 586 | tristate "Winbond W83627EHF" |
564 | depends on HWMON && I2C && EXPERIMENTAL | 587 | depends on I2C && EXPERIMENTAL |
565 | select I2C_ISA | 588 | select I2C_ISA |
566 | help | 589 | help |
567 | If you say yes here you get preliminary support for the hardware | 590 | If you say yes here you get preliminary support for the hardware |
@@ -577,7 +600,7 @@ config SENSORS_W83627EHF | |||
577 | 600 | ||
578 | config SENSORS_HDAPS | 601 | config SENSORS_HDAPS |
579 | tristate "IBM Hard Drive Active Protection System (hdaps)" | 602 | tristate "IBM Hard Drive Active Protection System (hdaps)" |
580 | depends on HWMON && INPUT && X86 | 603 | depends on INPUT && X86 |
581 | default n | 604 | default n |
582 | help | 605 | help |
583 | This driver provides support for the IBM Hard Drive Active Protection | 606 | This driver provides support for the IBM Hard Drive Active Protection |
@@ -620,7 +643,6 @@ config SENSORS_APPLESMC | |||
620 | 643 | ||
621 | config HWMON_DEBUG_CHIP | 644 | config HWMON_DEBUG_CHIP |
622 | bool "Hardware Monitoring Chip debugging messages" | 645 | bool "Hardware Monitoring Chip debugging messages" |
623 | depends on HWMON | ||
624 | default n | 646 | default n |
625 | help | 647 | help |
626 | Say Y here if you want the I2C chip drivers to produce a bunch of | 648 | Say Y here if you want the I2C chip drivers to produce a bunch of |
@@ -628,4 +650,4 @@ config HWMON_DEBUG_CHIP | |||
628 | a problem with I2C support and want to see more of what is going | 650 | a problem with I2C support and want to see more of what is going |
629 | on. | 651 | on. |
630 | 652 | ||
631 | endmenu | 653 | endif # HWMON |
diff --git a/drivers/hwmon/Makefile b/drivers/hwmon/Makefile index 544f8d8dff4e..cfaf338919dd 100644 --- a/drivers/hwmon/Makefile +++ b/drivers/hwmon/Makefile | |||
@@ -14,6 +14,7 @@ obj-$(CONFIG_SENSORS_W83781D) += w83781d.o | |||
14 | obj-$(CONFIG_SENSORS_W83791D) += w83791d.o | 14 | obj-$(CONFIG_SENSORS_W83791D) += w83791d.o |
15 | 15 | ||
16 | obj-$(CONFIG_SENSORS_ABITUGURU) += abituguru.o | 16 | obj-$(CONFIG_SENSORS_ABITUGURU) += abituguru.o |
17 | obj-$(CONFIG_SENSORS_AD7418) += ad7418.o | ||
17 | obj-$(CONFIG_SENSORS_ADM1021) += adm1021.o | 18 | obj-$(CONFIG_SENSORS_ADM1021) += adm1021.o |
18 | obj-$(CONFIG_SENSORS_ADM1025) += adm1025.o | 19 | obj-$(CONFIG_SENSORS_ADM1025) += adm1025.o |
19 | obj-$(CONFIG_SENSORS_ADM1026) += adm1026.o | 20 | obj-$(CONFIG_SENSORS_ADM1026) += adm1026.o |
@@ -23,6 +24,7 @@ obj-$(CONFIG_SENSORS_ADM9240) += adm9240.o | |||
23 | obj-$(CONFIG_SENSORS_APPLESMC) += applesmc.o | 24 | obj-$(CONFIG_SENSORS_APPLESMC) += applesmc.o |
24 | obj-$(CONFIG_SENSORS_AMS) += ams/ | 25 | obj-$(CONFIG_SENSORS_AMS) += ams/ |
25 | obj-$(CONFIG_SENSORS_ATXP1) += atxp1.o | 26 | obj-$(CONFIG_SENSORS_ATXP1) += atxp1.o |
27 | obj-$(CONFIG_SENSORS_CORETEMP) += coretemp.o | ||
26 | obj-$(CONFIG_SENSORS_DS1621) += ds1621.o | 28 | obj-$(CONFIG_SENSORS_DS1621) += ds1621.o |
27 | obj-$(CONFIG_SENSORS_F71805F) += f71805f.o | 29 | obj-$(CONFIG_SENSORS_F71805F) += f71805f.o |
28 | obj-$(CONFIG_SENSORS_FSCHER) += fscher.o | 30 | obj-$(CONFIG_SENSORS_FSCHER) += fscher.o |
@@ -44,6 +46,7 @@ obj-$(CONFIG_SENSORS_LM87) += lm87.o | |||
44 | obj-$(CONFIG_SENSORS_LM90) += lm90.o | 46 | obj-$(CONFIG_SENSORS_LM90) += lm90.o |
45 | obj-$(CONFIG_SENSORS_LM92) += lm92.o | 47 | obj-$(CONFIG_SENSORS_LM92) += lm92.o |
46 | obj-$(CONFIG_SENSORS_MAX1619) += max1619.o | 48 | obj-$(CONFIG_SENSORS_MAX1619) += max1619.o |
49 | obj-$(CONFIG_SENSORS_MAX6650) += max6650.o | ||
47 | obj-$(CONFIG_SENSORS_PC87360) += pc87360.o | 50 | obj-$(CONFIG_SENSORS_PC87360) += pc87360.o |
48 | obj-$(CONFIG_SENSORS_PC87427) += pc87427.o | 51 | obj-$(CONFIG_SENSORS_PC87427) += pc87427.o |
49 | obj-$(CONFIG_SENSORS_SIS5595) += sis5595.o | 52 | obj-$(CONFIG_SENSORS_SIS5595) += sis5595.o |
diff --git a/drivers/hwmon/ad7418.c b/drivers/hwmon/ad7418.c new file mode 100644 index 000000000000..cc8b624a1e51 --- /dev/null +++ b/drivers/hwmon/ad7418.c | |||
@@ -0,0 +1,373 @@ | |||
1 | /* | ||
2 | * An hwmon driver for the Analog Devices AD7416/17/18 | ||
3 | * Copyright (C) 2006-07 Tower Technologies | ||
4 | * | ||
5 | * Author: Alessandro Zummo <a.zummo@towertech.it> | ||
6 | * | ||
7 | * Based on lm75.c | ||
8 | * Copyright (C) 1998-99 Frodo Looijaard <frodol@dds.nl> | ||
9 | * | ||
10 | * This program is free software; you can redistribute it and/or modify | ||
11 | * it under the terms of the GNU General Public License, | ||
12 | * as published by the Free Software Foundation - version 2. | ||
13 | */ | ||
14 | |||
15 | #include <linux/module.h> | ||
16 | #include <linux/jiffies.h> | ||
17 | #include <linux/i2c.h> | ||
18 | #include <linux/hwmon.h> | ||
19 | #include <linux/hwmon-sysfs.h> | ||
20 | #include <linux/err.h> | ||
21 | #include <linux/mutex.h> | ||
22 | #include <linux/delay.h> | ||
23 | |||
24 | #include "lm75.h" | ||
25 | |||
26 | #define DRV_VERSION "0.3" | ||
27 | |||
28 | /* Addresses to scan */ | ||
29 | static unsigned short normal_i2c[] = { 0x28, I2C_CLIENT_END }; | ||
30 | /* Insmod parameters */ | ||
31 | I2C_CLIENT_INSMOD_3(ad7416, ad7417, ad7418); | ||
32 | |||
33 | /* AD7418 registers */ | ||
34 | #define AD7418_REG_TEMP_IN 0x00 | ||
35 | #define AD7418_REG_CONF 0x01 | ||
36 | #define AD7418_REG_TEMP_HYST 0x02 | ||
37 | #define AD7418_REG_TEMP_OS 0x03 | ||
38 | #define AD7418_REG_ADC 0x04 | ||
39 | #define AD7418_REG_CONF2 0x05 | ||
40 | |||
41 | #define AD7418_REG_ADC_CH(x) ((x) << 5) | ||
42 | #define AD7418_CH_TEMP AD7418_REG_ADC_CH(0) | ||
43 | |||
44 | static const u8 AD7418_REG_TEMP[] = { AD7418_REG_TEMP_IN, | ||
45 | AD7418_REG_TEMP_HYST, | ||
46 | AD7418_REG_TEMP_OS }; | ||
47 | |||
48 | struct ad7418_data { | ||
49 | struct i2c_client client; | ||
50 | struct class_device *class_dev; | ||
51 | struct attribute_group attrs; | ||
52 | enum chips type; | ||
53 | struct mutex lock; | ||
54 | int adc_max; /* number of ADC channels */ | ||
55 | char valid; | ||
56 | unsigned long last_updated; /* In jiffies */ | ||
57 | s16 temp[3]; /* Register values */ | ||
58 | u16 in[4]; | ||
59 | }; | ||
60 | |||
61 | static int ad7418_attach_adapter(struct i2c_adapter *adapter); | ||
62 | static int ad7418_detect(struct i2c_adapter *adapter, int address, int kind); | ||
63 | static int ad7418_detach_client(struct i2c_client *client); | ||
64 | |||
65 | static struct i2c_driver ad7418_driver = { | ||
66 | .driver = { | ||
67 | .name = "ad7418", | ||
68 | }, | ||
69 | .attach_adapter = ad7418_attach_adapter, | ||
70 | .detach_client = ad7418_detach_client, | ||
71 | }; | ||
72 | |||
73 | /* All registers are word-sized, except for the configuration registers. | ||
74 | * AD7418 uses a high-byte first convention. Do NOT use those functions to | ||
75 | * access the configuration registers CONF and CONF2, as they are byte-sized. | ||
76 | */ | ||
77 | static inline int ad7418_read(struct i2c_client *client, u8 reg) | ||
78 | { | ||
79 | return swab16(i2c_smbus_read_word_data(client, reg)); | ||
80 | } | ||
81 | |||
82 | static inline int ad7418_write(struct i2c_client *client, u8 reg, u16 value) | ||
83 | { | ||
84 | return i2c_smbus_write_word_data(client, reg, swab16(value)); | ||
85 | } | ||
86 | |||
87 | static void ad7418_init_client(struct i2c_client *client) | ||
88 | { | ||
89 | struct ad7418_data *data = i2c_get_clientdata(client); | ||
90 | |||
91 | int reg = i2c_smbus_read_byte_data(client, AD7418_REG_CONF); | ||
92 | if (reg < 0) { | ||
93 | dev_err(&client->dev, "cannot read configuration register\n"); | ||
94 | } else { | ||
95 | dev_info(&client->dev, "configuring for mode 1\n"); | ||
96 | i2c_smbus_write_byte_data(client, AD7418_REG_CONF, reg & 0xfe); | ||
97 | |||
98 | if (data->type == ad7417 || data->type == ad7418) | ||
99 | i2c_smbus_write_byte_data(client, | ||
100 | AD7418_REG_CONF2, 0x00); | ||
101 | } | ||
102 | } | ||
103 | |||
104 | static struct ad7418_data *ad7418_update_device(struct device *dev) | ||
105 | { | ||
106 | struct i2c_client *client = to_i2c_client(dev); | ||
107 | struct ad7418_data *data = i2c_get_clientdata(client); | ||
108 | |||
109 | mutex_lock(&data->lock); | ||
110 | |||
111 | if (time_after(jiffies, data->last_updated + HZ + HZ / 2) | ||
112 | || !data->valid) { | ||
113 | u8 cfg; | ||
114 | int i, ch; | ||
115 | |||
116 | /* read config register and clear channel bits */ | ||
117 | cfg = i2c_smbus_read_byte_data(client, AD7418_REG_CONF); | ||
118 | cfg &= 0x1F; | ||
119 | |||
120 | i2c_smbus_write_byte_data(client, AD7418_REG_CONF, | ||
121 | cfg | AD7418_CH_TEMP); | ||
122 | udelay(30); | ||
123 | |||
124 | for (i = 0; i < 3; i++) { | ||
125 | data->temp[i] = ad7418_read(client, AD7418_REG_TEMP[i]); | ||
126 | } | ||
127 | |||
128 | for (i = 0, ch = 4; i < data->adc_max; i++, ch--) { | ||
129 | i2c_smbus_write_byte_data(client, | ||
130 | AD7418_REG_CONF, | ||
131 | cfg | AD7418_REG_ADC_CH(ch)); | ||
132 | |||
133 | udelay(15); | ||
134 | data->in[data->adc_max - 1 - i] = | ||
135 | ad7418_read(client, AD7418_REG_ADC); | ||
136 | } | ||
137 | |||
138 | /* restore old configuration value */ | ||
139 | ad7418_write(client, AD7418_REG_CONF, cfg); | ||
140 | |||
141 | data->last_updated = jiffies; | ||
142 | data->valid = 1; | ||
143 | } | ||
144 | |||
145 | mutex_unlock(&data->lock); | ||
146 | |||
147 | return data; | ||
148 | } | ||
149 | |||
150 | static ssize_t show_temp(struct device *dev, struct device_attribute *devattr, | ||
151 | char *buf) | ||
152 | { | ||
153 | struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); | ||
154 | struct ad7418_data *data = ad7418_update_device(dev); | ||
155 | return sprintf(buf, "%d\n", | ||
156 | LM75_TEMP_FROM_REG(data->temp[attr->index])); | ||
157 | } | ||
158 | |||
159 | static ssize_t show_adc(struct device *dev, struct device_attribute *devattr, | ||
160 | char *buf) | ||
161 | { | ||
162 | struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); | ||
163 | struct ad7418_data *data = ad7418_update_device(dev); | ||
164 | |||
165 | return sprintf(buf, "%d\n", | ||
166 | ((data->in[attr->index] >> 6) * 2500 + 512) / 1024); | ||
167 | } | ||
168 | |||
169 | static ssize_t set_temp(struct device *dev, struct device_attribute *devattr, | ||
170 | const char *buf, size_t count) | ||
171 | { | ||
172 | struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); | ||
173 | struct i2c_client *client = to_i2c_client(dev); | ||
174 | struct ad7418_data *data = i2c_get_clientdata(client); | ||
175 | int temp = simple_strtol(buf, NULL, 10); | ||
176 | |||
177 | mutex_lock(&data->lock); | ||
178 | data->temp[attr->index] = LM75_TEMP_TO_REG(temp); | ||
179 | ad7418_write(client, AD7418_REG_TEMP[attr->index], data->temp[attr->index]); | ||
180 | mutex_unlock(&data->lock); | ||
181 | return count; | ||
182 | } | ||
183 | |||
184 | static SENSOR_DEVICE_ATTR(temp1_input, S_IRUGO, show_temp, NULL, 0); | ||
185 | static SENSOR_DEVICE_ATTR(temp1_max_hyst, S_IWUSR | S_IRUGO, | ||
186 | show_temp, set_temp, 1); | ||
187 | static SENSOR_DEVICE_ATTR(temp1_max, S_IWUSR | S_IRUGO, | ||
188 | show_temp, set_temp, 2); | ||
189 | |||
190 | static SENSOR_DEVICE_ATTR(in1_input, S_IRUGO, show_adc, NULL, 0); | ||
191 | static SENSOR_DEVICE_ATTR(in2_input, S_IRUGO, show_adc, NULL, 1); | ||
192 | static SENSOR_DEVICE_ATTR(in3_input, S_IRUGO, show_adc, NULL, 2); | ||
193 | static SENSOR_DEVICE_ATTR(in4_input, S_IRUGO, show_adc, NULL, 3); | ||
194 | |||
195 | static int ad7418_attach_adapter(struct i2c_adapter *adapter) | ||
196 | { | ||
197 | if (!(adapter->class & I2C_CLASS_HWMON)) | ||
198 | return 0; | ||
199 | return i2c_probe(adapter, &addr_data, ad7418_detect); | ||
200 | } | ||
201 | |||
202 | static struct attribute *ad7416_attributes[] = { | ||
203 | &sensor_dev_attr_temp1_max.dev_attr.attr, | ||
204 | &sensor_dev_attr_temp1_max_hyst.dev_attr.attr, | ||
205 | &sensor_dev_attr_temp1_input.dev_attr.attr, | ||
206 | NULL | ||
207 | }; | ||
208 | |||
209 | static struct attribute *ad7417_attributes[] = { | ||
210 | &sensor_dev_attr_temp1_max.dev_attr.attr, | ||
211 | &sensor_dev_attr_temp1_max_hyst.dev_attr.attr, | ||
212 | &sensor_dev_attr_temp1_input.dev_attr.attr, | ||
213 | &sensor_dev_attr_in1_input.dev_attr.attr, | ||
214 | &sensor_dev_attr_in2_input.dev_attr.attr, | ||
215 | &sensor_dev_attr_in3_input.dev_attr.attr, | ||
216 | &sensor_dev_attr_in4_input.dev_attr.attr, | ||
217 | NULL | ||
218 | }; | ||
219 | |||
220 | static struct attribute *ad7418_attributes[] = { | ||
221 | &sensor_dev_attr_temp1_max.dev_attr.attr, | ||
222 | &sensor_dev_attr_temp1_max_hyst.dev_attr.attr, | ||
223 | &sensor_dev_attr_temp1_input.dev_attr.attr, | ||
224 | &sensor_dev_attr_in1_input.dev_attr.attr, | ||
225 | NULL | ||
226 | }; | ||
227 | |||
228 | static int ad7418_detect(struct i2c_adapter *adapter, int address, int kind) | ||
229 | { | ||
230 | struct i2c_client *client; | ||
231 | struct ad7418_data *data; | ||
232 | int err = 0; | ||
233 | |||
234 | if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA | | ||
235 | I2C_FUNC_SMBUS_WORD_DATA)) | ||
236 | goto exit; | ||
237 | |||
238 | if (!(data = kzalloc(sizeof(struct ad7418_data), GFP_KERNEL))) { | ||
239 | err = -ENOMEM; | ||
240 | goto exit; | ||
241 | } | ||
242 | |||
243 | client = &data->client; | ||
244 | client->addr = address; | ||
245 | client->adapter = adapter; | ||
246 | client->driver = &ad7418_driver; | ||
247 | |||
248 | i2c_set_clientdata(client, data); | ||
249 | |||
250 | mutex_init(&data->lock); | ||
251 | |||
252 | /* AD7418 has a curious behaviour on registers 6 and 7. They | ||
253 | * both always read 0xC071 and are not documented on the datasheet. | ||
254 | * We use them to detect the chip. | ||
255 | */ | ||
256 | if (kind <= 0) { | ||
257 | int reg, reg6, reg7; | ||
258 | |||
259 | /* the AD7416 lies within this address range, but I have | ||
260 | * no means to check. | ||
261 | */ | ||
262 | if (address >= 0x48 && address <= 0x4f) { | ||
263 | /* XXX add tests for AD7416 here */ | ||
264 | /* data->type = ad7416; */ | ||
265 | } | ||
266 | /* here we might have AD7417 or AD7418 */ | ||
267 | else if (address >= 0x28 && address <= 0x2f) { | ||
268 | reg6 = i2c_smbus_read_word_data(client, 0x06); | ||
269 | reg7 = i2c_smbus_read_word_data(client, 0x07); | ||
270 | |||
271 | if (address == 0x28 && reg6 == 0xC071 && reg7 == 0xC071) | ||
272 | data->type = ad7418; | ||
273 | |||
274 | /* XXX add tests for AD7417 here */ | ||
275 | |||
276 | |||
277 | /* both AD7417 and AD7418 have bits 0-5 of | ||
278 | * the CONF2 register at 0 | ||
279 | */ | ||
280 | reg = i2c_smbus_read_byte_data(client, | ||
281 | AD7418_REG_CONF2); | ||
282 | if (reg & 0x3F) | ||
283 | data->type = any_chip; /* detection failed */ | ||
284 | } | ||
285 | } else { | ||
286 | dev_dbg(&adapter->dev, "detection forced\n"); | ||
287 | } | ||
288 | |||
289 | if (kind > 0) | ||
290 | data->type = kind; | ||
291 | else if (kind < 0 && data->type == any_chip) { | ||
292 | err = -ENODEV; | ||
293 | goto exit_free; | ||
294 | } | ||
295 | |||
296 | switch (data->type) { | ||
297 | case any_chip: | ||
298 | case ad7416: | ||
299 | data->adc_max = 0; | ||
300 | data->attrs.attrs = ad7416_attributes; | ||
301 | strlcpy(client->name, "ad7416", I2C_NAME_SIZE); | ||
302 | break; | ||
303 | |||
304 | case ad7417: | ||
305 | data->adc_max = 4; | ||
306 | data->attrs.attrs = ad7417_attributes; | ||
307 | strlcpy(client->name, "ad7417", I2C_NAME_SIZE); | ||
308 | break; | ||
309 | |||
310 | case ad7418: | ||
311 | data->adc_max = 1; | ||
312 | data->attrs.attrs = ad7418_attributes; | ||
313 | strlcpy(client->name, "ad7418", I2C_NAME_SIZE); | ||
314 | break; | ||
315 | } | ||
316 | |||
317 | if ((err = i2c_attach_client(client))) | ||
318 | goto exit_free; | ||
319 | |||
320 | dev_info(&client->dev, "%s chip found\n", client->name); | ||
321 | |||
322 | /* Initialize the AD7418 chip */ | ||
323 | ad7418_init_client(client); | ||
324 | |||
325 | /* Register sysfs hooks */ | ||
326 | if ((err = sysfs_create_group(&client->dev.kobj, &data->attrs))) | ||
327 | goto exit_detach; | ||
328 | |||
329 | data->class_dev = hwmon_device_register(&client->dev); | ||
330 | if (IS_ERR(data->class_dev)) { | ||
331 | err = PTR_ERR(data->class_dev); | ||
332 | goto exit_remove; | ||
333 | } | ||
334 | |||
335 | return 0; | ||
336 | |||
337 | exit_remove: | ||
338 | sysfs_remove_group(&client->dev.kobj, &data->attrs); | ||
339 | exit_detach: | ||
340 | i2c_detach_client(client); | ||
341 | exit_free: | ||
342 | kfree(data); | ||
343 | exit: | ||
344 | return err; | ||
345 | } | ||
346 | |||
347 | static int ad7418_detach_client(struct i2c_client *client) | ||
348 | { | ||
349 | struct ad7418_data *data = i2c_get_clientdata(client); | ||
350 | hwmon_device_unregister(data->class_dev); | ||
351 | sysfs_remove_group(&client->dev.kobj, &data->attrs); | ||
352 | i2c_detach_client(client); | ||
353 | kfree(data); | ||
354 | return 0; | ||
355 | } | ||
356 | |||
357 | static int __init ad7418_init(void) | ||
358 | { | ||
359 | return i2c_add_driver(&ad7418_driver); | ||
360 | } | ||
361 | |||
362 | static void __exit ad7418_exit(void) | ||
363 | { | ||
364 | i2c_del_driver(&ad7418_driver); | ||
365 | } | ||
366 | |||
367 | MODULE_AUTHOR("Alessandro Zummo <a.zummo@towertech.it>"); | ||
368 | MODULE_DESCRIPTION("AD7416/17/18 driver"); | ||
369 | MODULE_LICENSE("GPL"); | ||
370 | MODULE_VERSION(DRV_VERSION); | ||
371 | |||
372 | module_init(ad7418_init); | ||
373 | module_exit(ad7418_exit); | ||
diff --git a/drivers/hwmon/ams/ams-core.c b/drivers/hwmon/ams/ams-core.c index dbe6a32c064e..6db973739725 100644 --- a/drivers/hwmon/ams/ams-core.c +++ b/drivers/hwmon/ams/ams-core.c | |||
@@ -219,9 +219,6 @@ int __init ams_init(void) | |||
219 | /* Found PMU motion sensor */ | 219 | /* Found PMU motion sensor */ |
220 | return ams_pmu_init(np); | 220 | return ams_pmu_init(np); |
221 | #endif | 221 | #endif |
222 | |||
223 | printk(KERN_ERR "ams: No motion sensor found.\n"); | ||
224 | |||
225 | return -ENODEV; | 222 | return -ENODEV; |
226 | } | 223 | } |
227 | 224 | ||
diff --git a/drivers/hwmon/ams/ams-i2c.c b/drivers/hwmon/ams/ams-i2c.c index ccd5cefae90e..957760536a4c 100644 --- a/drivers/hwmon/ams/ams-i2c.c +++ b/drivers/hwmon/ams/ams-i2c.c | |||
@@ -85,17 +85,17 @@ static int ams_i2c_write(u8 reg, u8 value) | |||
85 | static int ams_i2c_cmd(enum ams_i2c_cmd cmd) | 85 | static int ams_i2c_cmd(enum ams_i2c_cmd cmd) |
86 | { | 86 | { |
87 | s32 result; | 87 | s32 result; |
88 | int remaining = HZ / 20; | 88 | int count = 3; |
89 | 89 | ||
90 | ams_i2c_write(AMS_COMMAND, cmd); | 90 | ams_i2c_write(AMS_COMMAND, cmd); |
91 | mdelay(5); | 91 | msleep(5); |
92 | 92 | ||
93 | while (remaining) { | 93 | while (count--) { |
94 | result = ams_i2c_read(AMS_COMMAND); | 94 | result = ams_i2c_read(AMS_COMMAND); |
95 | if (result == 0 || result & 0x80) | 95 | if (result == 0 || result & 0x80) |
96 | return 0; | 96 | return 0; |
97 | 97 | ||
98 | remaining = schedule_timeout(remaining); | 98 | schedule_timeout_uninterruptible(HZ / 20); |
99 | } | 99 | } |
100 | 100 | ||
101 | return -1; | 101 | return -1; |
diff --git a/drivers/hwmon/coretemp.c b/drivers/hwmon/coretemp.c new file mode 100644 index 000000000000..03b1f650d1c4 --- /dev/null +++ b/drivers/hwmon/coretemp.c | |||
@@ -0,0 +1,406 @@ | |||
1 | /* | ||
2 | * coretemp.c - Linux kernel module for hardware monitoring | ||
3 | * | ||
4 | * Copyright (C) 2007 Rudolf Marek <r.marek@assembler.cz> | ||
5 | * | ||
6 | * Inspired from many hwmon drivers | ||
7 | * | ||
8 | * This program is free software; you can redistribute it and/or modify | ||
9 | * it under the terms of the GNU General Public License as published by | ||
10 | * the Free Software Foundation; version 2 of the License. | ||
11 | * | ||
12 | * This program is distributed in the hope that it will be useful, | ||
13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
15 | * GNU General Public License for more details. | ||
16 | * | ||
17 | * You should have received a copy of the GNU General Public License | ||
18 | * along with this program; if not, write to the Free Software | ||
19 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA | ||
20 | * 02110-1301 USA. | ||
21 | */ | ||
22 | |||
23 | #include <linux/module.h> | ||
24 | #include <linux/delay.h> | ||
25 | #include <linux/init.h> | ||
26 | #include <linux/slab.h> | ||
27 | #include <linux/jiffies.h> | ||
28 | #include <linux/hwmon.h> | ||
29 | #include <linux/sysfs.h> | ||
30 | #include <linux/hwmon-sysfs.h> | ||
31 | #include <linux/err.h> | ||
32 | #include <linux/mutex.h> | ||
33 | #include <linux/list.h> | ||
34 | #include <linux/platform_device.h> | ||
35 | #include <linux/cpu.h> | ||
36 | #include <asm/msr.h> | ||
37 | #include <asm/processor.h> | ||
38 | |||
39 | #define DRVNAME "coretemp" | ||
40 | |||
41 | typedef enum { SHOW_TEMP, SHOW_TJMAX, SHOW_LABEL, SHOW_NAME } SHOW; | ||
42 | |||
43 | /* | ||
44 | * Functions declaration | ||
45 | */ | ||
46 | |||
47 | static struct coretemp_data *coretemp_update_device(struct device *dev); | ||
48 | |||
49 | struct coretemp_data { | ||
50 | struct class_device *class_dev; | ||
51 | struct mutex update_lock; | ||
52 | const char *name; | ||
53 | u32 id; | ||
54 | char valid; /* zero until following fields are valid */ | ||
55 | unsigned long last_updated; /* in jiffies */ | ||
56 | int temp; | ||
57 | int tjmax; | ||
58 | u8 alarm; | ||
59 | }; | ||
60 | |||
61 | static struct coretemp_data *coretemp_update_device(struct device *dev); | ||
62 | |||
63 | /* | ||
64 | * Sysfs stuff | ||
65 | */ | ||
66 | |||
67 | static ssize_t show_name(struct device *dev, struct device_attribute | ||
68 | *devattr, char *buf) | ||
69 | { | ||
70 | int ret; | ||
71 | struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); | ||
72 | struct coretemp_data *data = dev_get_drvdata(dev); | ||
73 | |||
74 | if (attr->index == SHOW_NAME) | ||
75 | ret = sprintf(buf, "%s\n", data->name); | ||
76 | else /* show label */ | ||
77 | ret = sprintf(buf, "Core %d\n", data->id); | ||
78 | return ret; | ||
79 | } | ||
80 | |||
81 | static ssize_t show_alarm(struct device *dev, struct device_attribute | ||
82 | *devattr, char *buf) | ||
83 | { | ||
84 | struct coretemp_data *data = coretemp_update_device(dev); | ||
85 | /* read the Out-of-spec log, never clear */ | ||
86 | return sprintf(buf, "%d\n", data->alarm); | ||
87 | } | ||
88 | |||
89 | static ssize_t show_temp(struct device *dev, | ||
90 | struct device_attribute *devattr, char *buf) | ||
91 | { | ||
92 | struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); | ||
93 | struct coretemp_data *data = coretemp_update_device(dev); | ||
94 | int err; | ||
95 | |||
96 | if (attr->index == SHOW_TEMP) | ||
97 | err = data->valid ? sprintf(buf, "%d\n", data->temp) : -EAGAIN; | ||
98 | else | ||
99 | err = sprintf(buf, "%d\n", data->tjmax); | ||
100 | |||
101 | return err; | ||
102 | } | ||
103 | |||
104 | static SENSOR_DEVICE_ATTR(temp1_input, S_IRUGO, show_temp, NULL, | ||
105 | SHOW_TEMP); | ||
106 | static SENSOR_DEVICE_ATTR(temp1_crit, S_IRUGO, show_temp, NULL, | ||
107 | SHOW_TJMAX); | ||
108 | static DEVICE_ATTR(temp1_crit_alarm, S_IRUGO, show_alarm, NULL); | ||
109 | static SENSOR_DEVICE_ATTR(temp1_label, S_IRUGO, show_name, NULL, SHOW_LABEL); | ||
110 | static SENSOR_DEVICE_ATTR(name, S_IRUGO, show_name, NULL, SHOW_NAME); | ||
111 | |||
112 | static struct attribute *coretemp_attributes[] = { | ||
113 | &sensor_dev_attr_name.dev_attr.attr, | ||
114 | &sensor_dev_attr_temp1_label.dev_attr.attr, | ||
115 | &dev_attr_temp1_crit_alarm.attr, | ||
116 | &sensor_dev_attr_temp1_input.dev_attr.attr, | ||
117 | &sensor_dev_attr_temp1_crit.dev_attr.attr, | ||
118 | NULL | ||
119 | }; | ||
120 | |||
121 | static const struct attribute_group coretemp_group = { | ||
122 | .attrs = coretemp_attributes, | ||
123 | }; | ||
124 | |||
125 | static struct coretemp_data *coretemp_update_device(struct device *dev) | ||
126 | { | ||
127 | struct coretemp_data *data = dev_get_drvdata(dev); | ||
128 | |||
129 | mutex_lock(&data->update_lock); | ||
130 | |||
131 | if (!data->valid || time_after(jiffies, data->last_updated + HZ)) { | ||
132 | u32 eax, edx; | ||
133 | |||
134 | data->valid = 0; | ||
135 | rdmsr_on_cpu(data->id, MSR_IA32_THERM_STATUS, &eax, &edx); | ||
136 | data->alarm = (eax >> 5) & 1; | ||
137 | /* update only if data has been valid */ | ||
138 | if (eax & 0x80000000) { | ||
139 | data->temp = data->tjmax - (((eax >> 16) | ||
140 | & 0x7f) * 1000); | ||
141 | data->valid = 1; | ||
142 | } else { | ||
143 | dev_dbg(dev, "Temperature data invalid (0x%x)\n", eax); | ||
144 | } | ||
145 | data->last_updated = jiffies; | ||
146 | } | ||
147 | |||
148 | mutex_unlock(&data->update_lock); | ||
149 | return data; | ||
150 | } | ||
151 | |||
152 | static int __devinit coretemp_probe(struct platform_device *pdev) | ||
153 | { | ||
154 | struct coretemp_data *data; | ||
155 | struct cpuinfo_x86 *c = &(cpu_data)[pdev->id]; | ||
156 | int err; | ||
157 | u32 eax, edx; | ||
158 | |||
159 | if (!(data = kzalloc(sizeof(struct coretemp_data), GFP_KERNEL))) { | ||
160 | err = -ENOMEM; | ||
161 | dev_err(&pdev->dev, "Out of memory\n"); | ||
162 | goto exit; | ||
163 | } | ||
164 | |||
165 | data->id = pdev->id; | ||
166 | data->name = "coretemp"; | ||
167 | mutex_init(&data->update_lock); | ||
168 | /* Tjmax default is 100 degrees C */ | ||
169 | data->tjmax = 100000; | ||
170 | |||
171 | /* test if we can access the THERM_STATUS MSR */ | ||
172 | err = rdmsr_safe_on_cpu(data->id, MSR_IA32_THERM_STATUS, &eax, &edx); | ||
173 | if (err) { | ||
174 | dev_err(&pdev->dev, | ||
175 | "Unable to access THERM_STATUS MSR, giving up\n"); | ||
176 | goto exit_free; | ||
177 | } | ||
178 | |||
179 | /* Some processors have Tjmax 85 following magic should detect it | ||
180 | Intel won't disclose the information without signed NDA, but | ||
181 | individuals cannot sign it. Catch(ed) 22. | ||
182 | */ | ||
183 | |||
184 | if (((c->x86_model == 0xf) && (c->x86_mask > 3)) || | ||
185 | (c->x86_model == 0xe)) { | ||
186 | err = rdmsr_safe_on_cpu(data->id, 0xee, &eax, &edx); | ||
187 | if (err) { | ||
188 | dev_warn(&pdev->dev, | ||
189 | "Unable to access MSR 0xEE, Tjmax left at %d " | ||
190 | "degrees C\n", data->tjmax/1000); | ||
191 | } else if (eax & 0x40000000) { | ||
192 | data->tjmax = 85000; | ||
193 | } | ||
194 | } | ||
195 | |||
196 | platform_set_drvdata(pdev, data); | ||
197 | |||
198 | if ((err = sysfs_create_group(&pdev->dev.kobj, &coretemp_group))) | ||
199 | goto exit_free; | ||
200 | |||
201 | data->class_dev = hwmon_device_register(&pdev->dev); | ||
202 | if (IS_ERR(data->class_dev)) { | ||
203 | err = PTR_ERR(data->class_dev); | ||
204 | dev_err(&pdev->dev, "Class registration failed (%d)\n", | ||
205 | err); | ||
206 | goto exit_class; | ||
207 | } | ||
208 | |||
209 | return 0; | ||
210 | |||
211 | exit_class: | ||
212 | sysfs_remove_group(&pdev->dev.kobj, &coretemp_group); | ||
213 | exit_free: | ||
214 | kfree(data); | ||
215 | exit: | ||
216 | return err; | ||
217 | } | ||
218 | |||
219 | static int __devexit coretemp_remove(struct platform_device *pdev) | ||
220 | { | ||
221 | struct coretemp_data *data = platform_get_drvdata(pdev); | ||
222 | |||
223 | hwmon_device_unregister(data->class_dev); | ||
224 | sysfs_remove_group(&pdev->dev.kobj, &coretemp_group); | ||
225 | platform_set_drvdata(pdev, NULL); | ||
226 | kfree(data); | ||
227 | return 0; | ||
228 | } | ||
229 | |||
230 | static struct platform_driver coretemp_driver = { | ||
231 | .driver = { | ||
232 | .owner = THIS_MODULE, | ||
233 | .name = DRVNAME, | ||
234 | }, | ||
235 | .probe = coretemp_probe, | ||
236 | .remove = __devexit_p(coretemp_remove), | ||
237 | }; | ||
238 | |||
239 | struct pdev_entry { | ||
240 | struct list_head list; | ||
241 | struct platform_device *pdev; | ||
242 | unsigned int cpu; | ||
243 | }; | ||
244 | |||
245 | static LIST_HEAD(pdev_list); | ||
246 | static DEFINE_MUTEX(pdev_list_mutex); | ||
247 | |||
248 | static int __cpuinit coretemp_device_add(unsigned int cpu) | ||
249 | { | ||
250 | int err; | ||
251 | struct platform_device *pdev; | ||
252 | struct pdev_entry *pdev_entry; | ||
253 | |||
254 | pdev = platform_device_alloc(DRVNAME, cpu); | ||
255 | if (!pdev) { | ||
256 | err = -ENOMEM; | ||
257 | printk(KERN_ERR DRVNAME ": Device allocation failed\n"); | ||
258 | goto exit; | ||
259 | } | ||
260 | |||
261 | pdev_entry = kzalloc(sizeof(struct pdev_entry), GFP_KERNEL); | ||
262 | if (!pdev_entry) { | ||
263 | err = -ENOMEM; | ||
264 | goto exit_device_put; | ||
265 | } | ||
266 | |||
267 | err = platform_device_add(pdev); | ||
268 | if (err) { | ||
269 | printk(KERN_ERR DRVNAME ": Device addition failed (%d)\n", | ||
270 | err); | ||
271 | goto exit_device_free; | ||
272 | } | ||
273 | |||
274 | pdev_entry->pdev = pdev; | ||
275 | pdev_entry->cpu = cpu; | ||
276 | mutex_lock(&pdev_list_mutex); | ||
277 | list_add_tail(&pdev_entry->list, &pdev_list); | ||
278 | mutex_unlock(&pdev_list_mutex); | ||
279 | |||
280 | return 0; | ||
281 | |||
282 | exit_device_free: | ||
283 | kfree(pdev_entry); | ||
284 | exit_device_put: | ||
285 | platform_device_put(pdev); | ||
286 | exit: | ||
287 | return err; | ||
288 | } | ||
289 | |||
290 | #ifdef CONFIG_HOTPLUG_CPU | ||
291 | void coretemp_device_remove(unsigned int cpu) | ||
292 | { | ||
293 | struct pdev_entry *p, *n; | ||
294 | mutex_lock(&pdev_list_mutex); | ||
295 | list_for_each_entry_safe(p, n, &pdev_list, list) { | ||
296 | if (p->cpu == cpu) { | ||
297 | platform_device_unregister(p->pdev); | ||
298 | list_del(&p->list); | ||
299 | kfree(p); | ||
300 | } | ||
301 | } | ||
302 | mutex_unlock(&pdev_list_mutex); | ||
303 | } | ||
304 | |||
305 | static int coretemp_cpu_callback(struct notifier_block *nfb, | ||
306 | unsigned long action, void *hcpu) | ||
307 | { | ||
308 | unsigned int cpu = (unsigned long) hcpu; | ||
309 | |||
310 | switch (action) { | ||
311 | case CPU_ONLINE: | ||
312 | coretemp_device_add(cpu); | ||
313 | break; | ||
314 | case CPU_DEAD: | ||
315 | coretemp_device_remove(cpu); | ||
316 | break; | ||
317 | } | ||
318 | return NOTIFY_OK; | ||
319 | } | ||
320 | |||
321 | static struct notifier_block __cpuinitdata coretemp_cpu_notifier = { | ||
322 | .notifier_call = coretemp_cpu_callback, | ||
323 | }; | ||
324 | #endif /* !CONFIG_HOTPLUG_CPU */ | ||
325 | |||
326 | static int __init coretemp_init(void) | ||
327 | { | ||
328 | int i, err = -ENODEV; | ||
329 | struct pdev_entry *p, *n; | ||
330 | |||
331 | printk(KERN_NOTICE DRVNAME ": This driver uses undocumented features " | ||
332 | "of Core CPU. Temperature might be wrong!\n"); | ||
333 | |||
334 | /* quick check if we run Intel */ | ||
335 | if (cpu_data[0].x86_vendor != X86_VENDOR_INTEL) | ||
336 | goto exit; | ||
337 | |||
338 | err = platform_driver_register(&coretemp_driver); | ||
339 | if (err) | ||
340 | goto exit; | ||
341 | |||
342 | for_each_online_cpu(i) { | ||
343 | struct cpuinfo_x86 *c = &(cpu_data)[i]; | ||
344 | |||
345 | /* check if family 6, models e, f */ | ||
346 | if ((c->cpuid_level < 0) || (c->x86 != 0x6) || | ||
347 | !((c->x86_model == 0xe) || (c->x86_model == 0xf))) { | ||
348 | |||
349 | /* supported CPU not found, but report the unknown | ||
350 | family 6 CPU */ | ||
351 | if ((c->x86 == 0x6) && (c->x86_model > 0xf)) | ||
352 | printk(KERN_WARNING DRVNAME ": Unknown CPU " | ||
353 | "model %x\n", c->x86_model); | ||
354 | continue; | ||
355 | } | ||
356 | |||
357 | err = coretemp_device_add(i); | ||
358 | if (err) | ||
359 | goto exit_devices_unreg; | ||
360 | } | ||
361 | if (list_empty(&pdev_list)) { | ||
362 | err = -ENODEV; | ||
363 | goto exit_driver_unreg; | ||
364 | } | ||
365 | |||
366 | #ifdef CONFIG_HOTPLUG_CPU | ||
367 | register_hotcpu_notifier(&coretemp_cpu_notifier); | ||
368 | #endif | ||
369 | return 0; | ||
370 | |||
371 | exit_devices_unreg: | ||
372 | mutex_lock(&pdev_list_mutex); | ||
373 | list_for_each_entry_safe(p, n, &pdev_list, list) { | ||
374 | platform_device_unregister(p->pdev); | ||
375 | list_del(&p->list); | ||
376 | kfree(p); | ||
377 | } | ||
378 | mutex_unlock(&pdev_list_mutex); | ||
379 | exit_driver_unreg: | ||
380 | platform_driver_unregister(&coretemp_driver); | ||
381 | exit: | ||
382 | return err; | ||
383 | } | ||
384 | |||
385 | static void __exit coretemp_exit(void) | ||
386 | { | ||
387 | struct pdev_entry *p, *n; | ||
388 | #ifdef CONFIG_HOTPLUG_CPU | ||
389 | unregister_hotcpu_notifier(&coretemp_cpu_notifier); | ||
390 | #endif | ||
391 | mutex_lock(&pdev_list_mutex); | ||
392 | list_for_each_entry_safe(p, n, &pdev_list, list) { | ||
393 | platform_device_unregister(p->pdev); | ||
394 | list_del(&p->list); | ||
395 | kfree(p); | ||
396 | } | ||
397 | mutex_unlock(&pdev_list_mutex); | ||
398 | platform_driver_unregister(&coretemp_driver); | ||
399 | } | ||
400 | |||
401 | MODULE_AUTHOR("Rudolf Marek <r.marek@assembler.cz>"); | ||
402 | MODULE_DESCRIPTION("Intel Core temperature monitor"); | ||
403 | MODULE_LICENSE("GPL"); | ||
404 | |||
405 | module_init(coretemp_init) | ||
406 | module_exit(coretemp_exit) | ||
diff --git a/drivers/hwmon/f71805f.c b/drivers/hwmon/f71805f.c index 7c2973487122..cdbe309b8fc4 100644 --- a/drivers/hwmon/f71805f.c +++ b/drivers/hwmon/f71805f.c | |||
@@ -35,6 +35,7 @@ | |||
35 | #include <linux/err.h> | 35 | #include <linux/err.h> |
36 | #include <linux/mutex.h> | 36 | #include <linux/mutex.h> |
37 | #include <linux/sysfs.h> | 37 | #include <linux/sysfs.h> |
38 | #include <linux/ioport.h> | ||
38 | #include <asm/io.h> | 39 | #include <asm/io.h> |
39 | 40 | ||
40 | static struct platform_device *pdev; | 41 | static struct platform_device *pdev; |
@@ -1140,6 +1141,13 @@ static int __devinit f71805f_probe(struct platform_device *pdev) | |||
1140 | } | 1141 | } |
1141 | 1142 | ||
1142 | res = platform_get_resource(pdev, IORESOURCE_IO, 0); | 1143 | res = platform_get_resource(pdev, IORESOURCE_IO, 0); |
1144 | if (!request_region(res->start + ADDR_REG_OFFSET, 2, DRVNAME)) { | ||
1145 | err = -EBUSY; | ||
1146 | dev_err(&pdev->dev, "Failed to request region 0x%lx-0x%lx\n", | ||
1147 | (unsigned long)(res->start + ADDR_REG_OFFSET), | ||
1148 | (unsigned long)(res->start + ADDR_REG_OFFSET + 1)); | ||
1149 | goto exit_free; | ||
1150 | } | ||
1143 | data->addr = res->start; | 1151 | data->addr = res->start; |
1144 | data->name = names[sio_data->kind]; | 1152 | data->name = names[sio_data->kind]; |
1145 | mutex_init(&data->update_lock); | 1153 | mutex_init(&data->update_lock); |
@@ -1165,7 +1173,7 @@ static int __devinit f71805f_probe(struct platform_device *pdev) | |||
1165 | 1173 | ||
1166 | /* Register sysfs interface files */ | 1174 | /* Register sysfs interface files */ |
1167 | if ((err = sysfs_create_group(&pdev->dev.kobj, &f71805f_group))) | 1175 | if ((err = sysfs_create_group(&pdev->dev.kobj, &f71805f_group))) |
1168 | goto exit_free; | 1176 | goto exit_release_region; |
1169 | if (data->has_in & (1 << 4)) { /* in4 */ | 1177 | if (data->has_in & (1 << 4)) { /* in4 */ |
1170 | if ((err = sysfs_create_group(&pdev->dev.kobj, | 1178 | if ((err = sysfs_create_group(&pdev->dev.kobj, |
1171 | &f71805f_group_optin[0]))) | 1179 | &f71805f_group_optin[0]))) |
@@ -1219,6 +1227,8 @@ exit_remove_files: | |||
1219 | for (i = 0; i < 4; i++) | 1227 | for (i = 0; i < 4; i++) |
1220 | sysfs_remove_group(&pdev->dev.kobj, &f71805f_group_optin[i]); | 1228 | sysfs_remove_group(&pdev->dev.kobj, &f71805f_group_optin[i]); |
1221 | sysfs_remove_group(&pdev->dev.kobj, &f71805f_group_pwm_freq); | 1229 | sysfs_remove_group(&pdev->dev.kobj, &f71805f_group_pwm_freq); |
1230 | exit_release_region: | ||
1231 | release_region(res->start + ADDR_REG_OFFSET, 2); | ||
1222 | exit_free: | 1232 | exit_free: |
1223 | platform_set_drvdata(pdev, NULL); | 1233 | platform_set_drvdata(pdev, NULL); |
1224 | kfree(data); | 1234 | kfree(data); |
@@ -1229,6 +1239,7 @@ exit: | |||
1229 | static int __devexit f71805f_remove(struct platform_device *pdev) | 1239 | static int __devexit f71805f_remove(struct platform_device *pdev) |
1230 | { | 1240 | { |
1231 | struct f71805f_data *data = platform_get_drvdata(pdev); | 1241 | struct f71805f_data *data = platform_get_drvdata(pdev); |
1242 | struct resource *res; | ||
1232 | int i; | 1243 | int i; |
1233 | 1244 | ||
1234 | platform_set_drvdata(pdev, NULL); | 1245 | platform_set_drvdata(pdev, NULL); |
@@ -1239,6 +1250,9 @@ static int __devexit f71805f_remove(struct platform_device *pdev) | |||
1239 | sysfs_remove_group(&pdev->dev.kobj, &f71805f_group_pwm_freq); | 1250 | sysfs_remove_group(&pdev->dev.kobj, &f71805f_group_pwm_freq); |
1240 | kfree(data); | 1251 | kfree(data); |
1241 | 1252 | ||
1253 | res = platform_get_resource(pdev, IORESOURCE_IO, 0); | ||
1254 | release_region(res->start + ADDR_REG_OFFSET, 2); | ||
1255 | |||
1242 | return 0; | 1256 | return 0; |
1243 | } | 1257 | } |
1244 | 1258 | ||
diff --git a/drivers/hwmon/hwmon-vid.c b/drivers/hwmon/hwmon-vid.c index b80f6ed5acfc..5aab23b93e24 100644 --- a/drivers/hwmon/hwmon-vid.c +++ b/drivers/hwmon/hwmon-vid.c | |||
@@ -166,16 +166,16 @@ static struct vrm_model vrm_models[] = { | |||
166 | {X86_VENDOR_INTEL, 0x6, 0xE, ANY, 14}, /* Intel Core (65 nm) */ | 166 | {X86_VENDOR_INTEL, 0x6, 0xE, ANY, 14}, /* Intel Core (65 nm) */ |
167 | {X86_VENDOR_INTEL, 0x6, 0xF, ANY, 110}, /* Intel Conroe */ | 167 | {X86_VENDOR_INTEL, 0x6, 0xF, ANY, 110}, /* Intel Conroe */ |
168 | {X86_VENDOR_INTEL, 0x6, ANY, ANY, 82}, /* any P6 */ | 168 | {X86_VENDOR_INTEL, 0x6, ANY, ANY, 82}, /* any P6 */ |
169 | {X86_VENDOR_INTEL, 0x7, ANY, ANY, 0}, /* Itanium */ | ||
170 | {X86_VENDOR_INTEL, 0xF, 0x0, ANY, 90}, /* P4 */ | 169 | {X86_VENDOR_INTEL, 0xF, 0x0, ANY, 90}, /* P4 */ |
171 | {X86_VENDOR_INTEL, 0xF, 0x1, ANY, 90}, /* P4 Willamette */ | 170 | {X86_VENDOR_INTEL, 0xF, 0x1, ANY, 90}, /* P4 Willamette */ |
172 | {X86_VENDOR_INTEL, 0xF, 0x2, ANY, 90}, /* P4 Northwood */ | 171 | {X86_VENDOR_INTEL, 0xF, 0x2, ANY, 90}, /* P4 Northwood */ |
173 | {X86_VENDOR_INTEL, 0xF, ANY, ANY, 100}, /* Prescott and above assume VRD 10 */ | 172 | {X86_VENDOR_INTEL, 0xF, ANY, ANY, 100}, /* Prescott and above assume VRD 10 */ |
174 | {X86_VENDOR_INTEL, 0x10, ANY, ANY, 0}, /* Itanium 2 */ | ||
175 | {X86_VENDOR_CENTAUR, 0x6, 0x7, ANY, 85}, /* Eden ESP/Ezra */ | 173 | {X86_VENDOR_CENTAUR, 0x6, 0x7, ANY, 85}, /* Eden ESP/Ezra */ |
176 | {X86_VENDOR_CENTAUR, 0x6, 0x8, 0x7, 85}, /* Ezra T */ | 174 | {X86_VENDOR_CENTAUR, 0x6, 0x8, 0x7, 85}, /* Ezra T */ |
177 | {X86_VENDOR_CENTAUR, 0x6, 0x9, 0x7, 85}, /* Nemiah */ | 175 | {X86_VENDOR_CENTAUR, 0x6, 0x9, 0x7, 85}, /* Nemiah */ |
178 | {X86_VENDOR_CENTAUR, 0x6, 0x9, ANY, 17}, /* C3-M */ | 176 | {X86_VENDOR_CENTAUR, 0x6, 0x9, ANY, 17}, /* C3-M, Eden-N */ |
177 | {X86_VENDOR_CENTAUR, 0x6, 0xA, 0x7, 0}, /* No information */ | ||
178 | {X86_VENDOR_CENTAUR, 0x6, 0xA, ANY, 13}, /* C7, Esther */ | ||
179 | {X86_VENDOR_UNKNOWN, ANY, ANY, ANY, 0} /* stop here */ | 179 | {X86_VENDOR_UNKNOWN, ANY, ANY, ANY, 0} /* stop here */ |
180 | }; | 180 | }; |
181 | 181 | ||
diff --git a/drivers/hwmon/lm75.c b/drivers/hwmon/lm75.c index 7c65b8bb6d72..a40166ffad12 100644 --- a/drivers/hwmon/lm75.c +++ b/drivers/hwmon/lm75.c | |||
@@ -24,6 +24,7 @@ | |||
24 | #include <linux/jiffies.h> | 24 | #include <linux/jiffies.h> |
25 | #include <linux/i2c.h> | 25 | #include <linux/i2c.h> |
26 | #include <linux/hwmon.h> | 26 | #include <linux/hwmon.h> |
27 | #include <linux/hwmon-sysfs.h> | ||
27 | #include <linux/err.h> | 28 | #include <linux/err.h> |
28 | #include <linux/mutex.h> | 29 | #include <linux/mutex.h> |
29 | #include "lm75.h" | 30 | #include "lm75.h" |
@@ -39,10 +40,12 @@ I2C_CLIENT_INSMOD_1(lm75); | |||
39 | /* Many LM75 constants specified below */ | 40 | /* Many LM75 constants specified below */ |
40 | 41 | ||
41 | /* The LM75 registers */ | 42 | /* The LM75 registers */ |
42 | #define LM75_REG_TEMP 0x00 | ||
43 | #define LM75_REG_CONF 0x01 | 43 | #define LM75_REG_CONF 0x01 |
44 | #define LM75_REG_TEMP_HYST 0x02 | 44 | static const u8 LM75_REG_TEMP[3] = { |
45 | #define LM75_REG_TEMP_OS 0x03 | 45 | 0x00, /* input */ |
46 | 0x03, /* max */ | ||
47 | 0x02, /* hyst */ | ||
48 | }; | ||
46 | 49 | ||
47 | /* Each client has this additional data */ | 50 | /* Each client has this additional data */ |
48 | struct lm75_data { | 51 | struct lm75_data { |
@@ -51,9 +54,10 @@ struct lm75_data { | |||
51 | struct mutex update_lock; | 54 | struct mutex update_lock; |
52 | char valid; /* !=0 if following fields are valid */ | 55 | char valid; /* !=0 if following fields are valid */ |
53 | unsigned long last_updated; /* In jiffies */ | 56 | unsigned long last_updated; /* In jiffies */ |
54 | u16 temp_input; /* Register values */ | 57 | u16 temp[3]; /* Register values, |
55 | u16 temp_max; | 58 | 0 = input |
56 | u16 temp_hyst; | 59 | 1 = max |
60 | 2 = hyst */ | ||
57 | }; | 61 | }; |
58 | 62 | ||
59 | static int lm75_attach_adapter(struct i2c_adapter *adapter); | 63 | static int lm75_attach_adapter(struct i2c_adapter *adapter); |
@@ -75,35 +79,36 @@ static struct i2c_driver lm75_driver = { | |||
75 | .detach_client = lm75_detach_client, | 79 | .detach_client = lm75_detach_client, |
76 | }; | 80 | }; |
77 | 81 | ||
78 | #define show(value) \ | 82 | static ssize_t show_temp(struct device *dev, struct device_attribute *da, |
79 | static ssize_t show_##value(struct device *dev, struct device_attribute *attr, char *buf) \ | 83 | char *buf) |
80 | { \ | 84 | { |
81 | struct lm75_data *data = lm75_update_device(dev); \ | 85 | struct sensor_device_attribute *attr = to_sensor_dev_attr(da); |
82 | return sprintf(buf, "%d\n", LM75_TEMP_FROM_REG(data->value)); \ | 86 | struct lm75_data *data = lm75_update_device(dev); |
87 | return sprintf(buf, "%d\n", | ||
88 | LM75_TEMP_FROM_REG(data->temp[attr->index])); | ||
83 | } | 89 | } |
84 | show(temp_max); | 90 | |
85 | show(temp_hyst); | 91 | static ssize_t set_temp(struct device *dev, struct device_attribute *da, |
86 | show(temp_input); | 92 | const char *buf, size_t count) |
87 | 93 | { | |
88 | #define set(value, reg) \ | 94 | struct sensor_device_attribute *attr = to_sensor_dev_attr(da); |
89 | static ssize_t set_##value(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) \ | 95 | struct i2c_client *client = to_i2c_client(dev); |
90 | { \ | 96 | struct lm75_data *data = i2c_get_clientdata(client); |
91 | struct i2c_client *client = to_i2c_client(dev); \ | 97 | int nr = attr->index; |
92 | struct lm75_data *data = i2c_get_clientdata(client); \ | 98 | unsigned long temp = simple_strtoul(buf, NULL, 10); |
93 | int temp = simple_strtoul(buf, NULL, 10); \ | 99 | |
94 | \ | 100 | mutex_lock(&data->update_lock); |
95 | mutex_lock(&data->update_lock); \ | 101 | data->temp[nr] = LM75_TEMP_TO_REG(temp); |
96 | data->value = LM75_TEMP_TO_REG(temp); \ | 102 | lm75_write_value(client, LM75_REG_TEMP[nr], data->temp[nr]); |
97 | lm75_write_value(client, reg, data->value); \ | 103 | mutex_unlock(&data->update_lock); |
98 | mutex_unlock(&data->update_lock); \ | 104 | return count; |
99 | return count; \ | ||
100 | } | 105 | } |
101 | set(temp_max, LM75_REG_TEMP_OS); | ||
102 | set(temp_hyst, LM75_REG_TEMP_HYST); | ||
103 | 106 | ||
104 | static DEVICE_ATTR(temp1_max, S_IWUSR | S_IRUGO, show_temp_max, set_temp_max); | 107 | static SENSOR_DEVICE_ATTR(temp1_max, S_IWUSR | S_IRUGO, |
105 | static DEVICE_ATTR(temp1_max_hyst, S_IWUSR | S_IRUGO, show_temp_hyst, set_temp_hyst); | 108 | show_temp, set_temp, 1); |
106 | static DEVICE_ATTR(temp1_input, S_IRUGO, show_temp_input, NULL); | 109 | static SENSOR_DEVICE_ATTR(temp1_max_hyst, S_IWUSR | S_IRUGO, |
110 | show_temp, set_temp, 2); | ||
111 | static SENSOR_DEVICE_ATTR(temp1_input, S_IRUGO, show_temp, NULL, 0); | ||
107 | 112 | ||
108 | static int lm75_attach_adapter(struct i2c_adapter *adapter) | 113 | static int lm75_attach_adapter(struct i2c_adapter *adapter) |
109 | { | 114 | { |
@@ -113,9 +118,9 @@ static int lm75_attach_adapter(struct i2c_adapter *adapter) | |||
113 | } | 118 | } |
114 | 119 | ||
115 | static struct attribute *lm75_attributes[] = { | 120 | static struct attribute *lm75_attributes[] = { |
116 | &dev_attr_temp1_input.attr, | 121 | &sensor_dev_attr_temp1_input.dev_attr.attr, |
117 | &dev_attr_temp1_max.attr, | 122 | &sensor_dev_attr_temp1_max.dev_attr.attr, |
118 | &dev_attr_temp1_max_hyst.attr, | 123 | &sensor_dev_attr_temp1_max_hyst.dev_attr.attr, |
119 | 124 | ||
120 | NULL | 125 | NULL |
121 | }; | 126 | }; |
@@ -283,11 +288,12 @@ static struct lm75_data *lm75_update_device(struct device *dev) | |||
283 | 288 | ||
284 | if (time_after(jiffies, data->last_updated + HZ + HZ / 2) | 289 | if (time_after(jiffies, data->last_updated + HZ + HZ / 2) |
285 | || !data->valid) { | 290 | || !data->valid) { |
291 | int i; | ||
286 | dev_dbg(&client->dev, "Starting lm75 update\n"); | 292 | dev_dbg(&client->dev, "Starting lm75 update\n"); |
287 | 293 | ||
288 | data->temp_input = lm75_read_value(client, LM75_REG_TEMP); | 294 | for (i = 0; i < ARRAY_SIZE(data->temp); i++) |
289 | data->temp_max = lm75_read_value(client, LM75_REG_TEMP_OS); | 295 | data->temp[i] = lm75_read_value(client, |
290 | data->temp_hyst = lm75_read_value(client, LM75_REG_TEMP_HYST); | 296 | LM75_REG_TEMP[i]); |
291 | data->last_updated = jiffies; | 297 | data->last_updated = jiffies; |
292 | data->valid = 1; | 298 | data->valid = 1; |
293 | } | 299 | } |
diff --git a/drivers/hwmon/lm78.c b/drivers/hwmon/lm78.c index 886786c33916..9fb572f03ba5 100644 --- a/drivers/hwmon/lm78.c +++ b/drivers/hwmon/lm78.c | |||
@@ -2,6 +2,7 @@ | |||
2 | lm78.c - Part of lm_sensors, Linux kernel modules for hardware | 2 | lm78.c - Part of lm_sensors, Linux kernel modules for hardware |
3 | monitoring | 3 | monitoring |
4 | Copyright (c) 1998, 1999 Frodo Looijaard <frodol@dds.nl> | 4 | Copyright (c) 1998, 1999 Frodo Looijaard <frodol@dds.nl> |
5 | Copyright (c) 2007 Jean Delvare <khali@linux-fr.org> | ||
5 | 6 | ||
6 | This program is free software; you can redistribute it and/or modify | 7 | This program is free software; you can redistribute it and/or modify |
7 | it under the terms of the GNU General Public License as published by | 8 | it under the terms of the GNU General Public License as published by |
@@ -23,13 +24,18 @@ | |||
23 | #include <linux/slab.h> | 24 | #include <linux/slab.h> |
24 | #include <linux/jiffies.h> | 25 | #include <linux/jiffies.h> |
25 | #include <linux/i2c.h> | 26 | #include <linux/i2c.h> |
26 | #include <linux/i2c-isa.h> | 27 | #include <linux/platform_device.h> |
28 | #include <linux/ioport.h> | ||
27 | #include <linux/hwmon.h> | 29 | #include <linux/hwmon.h> |
28 | #include <linux/hwmon-vid.h> | 30 | #include <linux/hwmon-vid.h> |
31 | #include <linux/hwmon-sysfs.h> | ||
29 | #include <linux/err.h> | 32 | #include <linux/err.h> |
30 | #include <linux/mutex.h> | 33 | #include <linux/mutex.h> |
31 | #include <asm/io.h> | 34 | #include <asm/io.h> |
32 | 35 | ||
36 | /* ISA device, if found */ | ||
37 | static struct platform_device *pdev; | ||
38 | |||
33 | /* Addresses to scan */ | 39 | /* Addresses to scan */ |
34 | static unsigned short normal_i2c[] = { 0x20, 0x21, 0x22, 0x23, 0x24, | 40 | static unsigned short normal_i2c[] = { 0x20, 0x21, 0x22, 0x23, 0x24, |
35 | 0x25, 0x26, 0x27, 0x28, 0x29, | 41 | 0x25, 0x26, 0x27, 0x28, 0x29, |
@@ -121,12 +127,8 @@ static inline int TEMP_FROM_REG(s8 val) | |||
121 | a bit - except if there could be more than one SMBus. Groan. No solution | 127 | a bit - except if there could be more than one SMBus. Groan. No solution |
122 | for this yet. */ | 128 | for this yet. */ |
123 | 129 | ||
124 | /* This module may seem overly long and complicated. In fact, it is not so | 130 | /* For ISA chips, we abuse the i2c_client addr and name fields. We also use |
125 | bad. Quite a lot of bookkeeping is done. A real driver can often cut | 131 | the driver field to differentiate between I2C and ISA chips. */ |
126 | some corners. */ | ||
127 | |||
128 | /* For each registered chip, we need to keep some data in memory. | ||
129 | The structure is dynamically allocated. */ | ||
130 | struct lm78_data { | 132 | struct lm78_data { |
131 | struct i2c_client client; | 133 | struct i2c_client client; |
132 | struct class_device *class_dev; | 134 | struct class_device *class_dev; |
@@ -152,14 +154,16 @@ struct lm78_data { | |||
152 | 154 | ||
153 | 155 | ||
154 | static int lm78_attach_adapter(struct i2c_adapter *adapter); | 156 | static int lm78_attach_adapter(struct i2c_adapter *adapter); |
155 | static int lm78_isa_attach_adapter(struct i2c_adapter *adapter); | ||
156 | static int lm78_detect(struct i2c_adapter *adapter, int address, int kind); | 157 | static int lm78_detect(struct i2c_adapter *adapter, int address, int kind); |
157 | static int lm78_detach_client(struct i2c_client *client); | 158 | static int lm78_detach_client(struct i2c_client *client); |
158 | 159 | ||
159 | static int lm78_read_value(struct i2c_client *client, u8 reg); | 160 | static int __devinit lm78_isa_probe(struct platform_device *pdev); |
160 | static int lm78_write_value(struct i2c_client *client, u8 reg, u8 value); | 161 | static int __devexit lm78_isa_remove(struct platform_device *pdev); |
162 | |||
163 | static int lm78_read_value(struct lm78_data *data, u8 reg); | ||
164 | static int lm78_write_value(struct lm78_data *data, u8 reg, u8 value); | ||
161 | static struct lm78_data *lm78_update_device(struct device *dev); | 165 | static struct lm78_data *lm78_update_device(struct device *dev); |
162 | static void lm78_init_client(struct i2c_client *client); | 166 | static void lm78_init_device(struct lm78_data *data); |
163 | 167 | ||
164 | 168 | ||
165 | static struct i2c_driver lm78_driver = { | 169 | static struct i2c_driver lm78_driver = { |
@@ -171,95 +175,78 @@ static struct i2c_driver lm78_driver = { | |||
171 | .detach_client = lm78_detach_client, | 175 | .detach_client = lm78_detach_client, |
172 | }; | 176 | }; |
173 | 177 | ||
174 | static struct i2c_driver lm78_isa_driver = { | 178 | static struct platform_driver lm78_isa_driver = { |
175 | .driver = { | 179 | .driver = { |
176 | .owner = THIS_MODULE, | 180 | .owner = THIS_MODULE, |
177 | .name = "lm78-isa", | 181 | .name = "lm78", |
178 | }, | 182 | }, |
179 | .attach_adapter = lm78_isa_attach_adapter, | 183 | .probe = lm78_isa_probe, |
180 | .detach_client = lm78_detach_client, | 184 | .remove = lm78_isa_remove, |
181 | }; | 185 | }; |
182 | 186 | ||
183 | 187 | ||
184 | /* 7 Voltages */ | 188 | /* 7 Voltages */ |
185 | static ssize_t show_in(struct device *dev, char *buf, int nr) | 189 | static ssize_t show_in(struct device *dev, struct device_attribute *da, |
190 | char *buf) | ||
186 | { | 191 | { |
192 | struct sensor_device_attribute *attr = to_sensor_dev_attr(da); | ||
187 | struct lm78_data *data = lm78_update_device(dev); | 193 | struct lm78_data *data = lm78_update_device(dev); |
188 | return sprintf(buf, "%d\n", IN_FROM_REG(data->in[nr])); | 194 | return sprintf(buf, "%d\n", IN_FROM_REG(data->in[attr->index])); |
189 | } | 195 | } |
190 | 196 | ||
191 | static ssize_t show_in_min(struct device *dev, char *buf, int nr) | 197 | static ssize_t show_in_min(struct device *dev, struct device_attribute *da, |
198 | char *buf) | ||
192 | { | 199 | { |
200 | struct sensor_device_attribute *attr = to_sensor_dev_attr(da); | ||
193 | struct lm78_data *data = lm78_update_device(dev); | 201 | struct lm78_data *data = lm78_update_device(dev); |
194 | return sprintf(buf, "%d\n", IN_FROM_REG(data->in_min[nr])); | 202 | return sprintf(buf, "%d\n", IN_FROM_REG(data->in_min[attr->index])); |
195 | } | 203 | } |
196 | 204 | ||
197 | static ssize_t show_in_max(struct device *dev, char *buf, int nr) | 205 | static ssize_t show_in_max(struct device *dev, struct device_attribute *da, |
206 | char *buf) | ||
198 | { | 207 | { |
208 | struct sensor_device_attribute *attr = to_sensor_dev_attr(da); | ||
199 | struct lm78_data *data = lm78_update_device(dev); | 209 | struct lm78_data *data = lm78_update_device(dev); |
200 | return sprintf(buf, "%d\n", IN_FROM_REG(data->in_max[nr])); | 210 | return sprintf(buf, "%d\n", IN_FROM_REG(data->in_max[attr->index])); |
201 | } | 211 | } |
202 | 212 | ||
203 | static ssize_t set_in_min(struct device *dev, const char *buf, | 213 | static ssize_t set_in_min(struct device *dev, struct device_attribute *da, |
204 | size_t count, int nr) | 214 | const char *buf, size_t count) |
205 | { | 215 | { |
206 | struct i2c_client *client = to_i2c_client(dev); | 216 | struct sensor_device_attribute *attr = to_sensor_dev_attr(da); |
207 | struct lm78_data *data = i2c_get_clientdata(client); | 217 | struct lm78_data *data = dev_get_drvdata(dev); |
208 | unsigned long val = simple_strtoul(buf, NULL, 10); | 218 | unsigned long val = simple_strtoul(buf, NULL, 10); |
219 | int nr = attr->index; | ||
209 | 220 | ||
210 | mutex_lock(&data->update_lock); | 221 | mutex_lock(&data->update_lock); |
211 | data->in_min[nr] = IN_TO_REG(val); | 222 | data->in_min[nr] = IN_TO_REG(val); |
212 | lm78_write_value(client, LM78_REG_IN_MIN(nr), data->in_min[nr]); | 223 | lm78_write_value(data, LM78_REG_IN_MIN(nr), data->in_min[nr]); |
213 | mutex_unlock(&data->update_lock); | 224 | mutex_unlock(&data->update_lock); |
214 | return count; | 225 | return count; |
215 | } | 226 | } |
216 | 227 | ||
217 | static ssize_t set_in_max(struct device *dev, const char *buf, | 228 | static ssize_t set_in_max(struct device *dev, struct device_attribute *da, |
218 | size_t count, int nr) | 229 | const char *buf, size_t count) |
219 | { | 230 | { |
220 | struct i2c_client *client = to_i2c_client(dev); | 231 | struct sensor_device_attribute *attr = to_sensor_dev_attr(da); |
221 | struct lm78_data *data = i2c_get_clientdata(client); | 232 | struct lm78_data *data = dev_get_drvdata(dev); |
222 | unsigned long val = simple_strtoul(buf, NULL, 10); | 233 | unsigned long val = simple_strtoul(buf, NULL, 10); |
234 | int nr = attr->index; | ||
223 | 235 | ||
224 | mutex_lock(&data->update_lock); | 236 | mutex_lock(&data->update_lock); |
225 | data->in_max[nr] = IN_TO_REG(val); | 237 | data->in_max[nr] = IN_TO_REG(val); |
226 | lm78_write_value(client, LM78_REG_IN_MAX(nr), data->in_max[nr]); | 238 | lm78_write_value(data, LM78_REG_IN_MAX(nr), data->in_max[nr]); |
227 | mutex_unlock(&data->update_lock); | 239 | mutex_unlock(&data->update_lock); |
228 | return count; | 240 | return count; |
229 | } | 241 | } |
230 | 242 | ||
231 | #define show_in_offset(offset) \ | 243 | #define show_in_offset(offset) \ |
232 | static ssize_t \ | 244 | static SENSOR_DEVICE_ATTR(in##offset##_input, S_IRUGO, \ |
233 | show_in##offset (struct device *dev, struct device_attribute *attr, char *buf) \ | 245 | show_in, NULL, offset); \ |
234 | { \ | 246 | static SENSOR_DEVICE_ATTR(in##offset##_min, S_IRUGO | S_IWUSR, \ |
235 | return show_in(dev, buf, offset); \ | 247 | show_in_min, set_in_min, offset); \ |
236 | } \ | 248 | static SENSOR_DEVICE_ATTR(in##offset##_max, S_IRUGO | S_IWUSR, \ |
237 | static DEVICE_ATTR(in##offset##_input, S_IRUGO, \ | 249 | show_in_max, set_in_max, offset); |
238 | show_in##offset, NULL); \ | ||
239 | static ssize_t \ | ||
240 | show_in##offset##_min (struct device *dev, struct device_attribute *attr, char *buf) \ | ||
241 | { \ | ||
242 | return show_in_min(dev, buf, offset); \ | ||
243 | } \ | ||
244 | static ssize_t \ | ||
245 | show_in##offset##_max (struct device *dev, struct device_attribute *attr, char *buf) \ | ||
246 | { \ | ||
247 | return show_in_max(dev, buf, offset); \ | ||
248 | } \ | ||
249 | static ssize_t set_in##offset##_min (struct device *dev, struct device_attribute *attr, \ | ||
250 | const char *buf, size_t count) \ | ||
251 | { \ | ||
252 | return set_in_min(dev, buf, count, offset); \ | ||
253 | } \ | ||
254 | static ssize_t set_in##offset##_max (struct device *dev, struct device_attribute *attr, \ | ||
255 | const char *buf, size_t count) \ | ||
256 | { \ | ||
257 | return set_in_max(dev, buf, count, offset); \ | ||
258 | } \ | ||
259 | static DEVICE_ATTR(in##offset##_min, S_IRUGO | S_IWUSR, \ | ||
260 | show_in##offset##_min, set_in##offset##_min); \ | ||
261 | static DEVICE_ATTR(in##offset##_max, S_IRUGO | S_IWUSR, \ | ||
262 | show_in##offset##_max, set_in##offset##_max); | ||
263 | 250 | ||
264 | show_in_offset(0); | 251 | show_in_offset(0); |
265 | show_in_offset(1); | 252 | show_in_offset(1); |
@@ -270,46 +257,49 @@ show_in_offset(5); | |||
270 | show_in_offset(6); | 257 | show_in_offset(6); |
271 | 258 | ||
272 | /* Temperature */ | 259 | /* Temperature */ |
273 | static ssize_t show_temp(struct device *dev, struct device_attribute *attr, char *buf) | 260 | static ssize_t show_temp(struct device *dev, struct device_attribute *da, |
261 | char *buf) | ||
274 | { | 262 | { |
275 | struct lm78_data *data = lm78_update_device(dev); | 263 | struct lm78_data *data = lm78_update_device(dev); |
276 | return sprintf(buf, "%d\n", TEMP_FROM_REG(data->temp)); | 264 | return sprintf(buf, "%d\n", TEMP_FROM_REG(data->temp)); |
277 | } | 265 | } |
278 | 266 | ||
279 | static ssize_t show_temp_over(struct device *dev, struct device_attribute *attr, char *buf) | 267 | static ssize_t show_temp_over(struct device *dev, struct device_attribute *da, |
268 | char *buf) | ||
280 | { | 269 | { |
281 | struct lm78_data *data = lm78_update_device(dev); | 270 | struct lm78_data *data = lm78_update_device(dev); |
282 | return sprintf(buf, "%d\n", TEMP_FROM_REG(data->temp_over)); | 271 | return sprintf(buf, "%d\n", TEMP_FROM_REG(data->temp_over)); |
283 | } | 272 | } |
284 | 273 | ||
285 | static ssize_t set_temp_over(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) | 274 | static ssize_t set_temp_over(struct device *dev, struct device_attribute *da, |
275 | const char *buf, size_t count) | ||
286 | { | 276 | { |
287 | struct i2c_client *client = to_i2c_client(dev); | 277 | struct lm78_data *data = dev_get_drvdata(dev); |
288 | struct lm78_data *data = i2c_get_clientdata(client); | ||
289 | long val = simple_strtol(buf, NULL, 10); | 278 | long val = simple_strtol(buf, NULL, 10); |
290 | 279 | ||
291 | mutex_lock(&data->update_lock); | 280 | mutex_lock(&data->update_lock); |
292 | data->temp_over = TEMP_TO_REG(val); | 281 | data->temp_over = TEMP_TO_REG(val); |
293 | lm78_write_value(client, LM78_REG_TEMP_OVER, data->temp_over); | 282 | lm78_write_value(data, LM78_REG_TEMP_OVER, data->temp_over); |
294 | mutex_unlock(&data->update_lock); | 283 | mutex_unlock(&data->update_lock); |
295 | return count; | 284 | return count; |
296 | } | 285 | } |
297 | 286 | ||
298 | static ssize_t show_temp_hyst(struct device *dev, struct device_attribute *attr, char *buf) | 287 | static ssize_t show_temp_hyst(struct device *dev, struct device_attribute *da, |
288 | char *buf) | ||
299 | { | 289 | { |
300 | struct lm78_data *data = lm78_update_device(dev); | 290 | struct lm78_data *data = lm78_update_device(dev); |
301 | return sprintf(buf, "%d\n", TEMP_FROM_REG(data->temp_hyst)); | 291 | return sprintf(buf, "%d\n", TEMP_FROM_REG(data->temp_hyst)); |
302 | } | 292 | } |
303 | 293 | ||
304 | static ssize_t set_temp_hyst(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) | 294 | static ssize_t set_temp_hyst(struct device *dev, struct device_attribute *da, |
295 | const char *buf, size_t count) | ||
305 | { | 296 | { |
306 | struct i2c_client *client = to_i2c_client(dev); | 297 | struct lm78_data *data = dev_get_drvdata(dev); |
307 | struct lm78_data *data = i2c_get_clientdata(client); | ||
308 | long val = simple_strtol(buf, NULL, 10); | 298 | long val = simple_strtol(buf, NULL, 10); |
309 | 299 | ||
310 | mutex_lock(&data->update_lock); | 300 | mutex_lock(&data->update_lock); |
311 | data->temp_hyst = TEMP_TO_REG(val); | 301 | data->temp_hyst = TEMP_TO_REG(val); |
312 | lm78_write_value(client, LM78_REG_TEMP_HYST, data->temp_hyst); | 302 | lm78_write_value(data, LM78_REG_TEMP_HYST, data->temp_hyst); |
313 | mutex_unlock(&data->update_lock); | 303 | mutex_unlock(&data->update_lock); |
314 | return count; | 304 | return count; |
315 | } | 305 | } |
@@ -321,49 +311,59 @@ static DEVICE_ATTR(temp1_max_hyst, S_IRUGO | S_IWUSR, | |||
321 | show_temp_hyst, set_temp_hyst); | 311 | show_temp_hyst, set_temp_hyst); |
322 | 312 | ||
323 | /* 3 Fans */ | 313 | /* 3 Fans */ |
324 | static ssize_t show_fan(struct device *dev, char *buf, int nr) | 314 | static ssize_t show_fan(struct device *dev, struct device_attribute *da, |
315 | char *buf) | ||
325 | { | 316 | { |
317 | struct sensor_device_attribute *attr = to_sensor_dev_attr(da); | ||
326 | struct lm78_data *data = lm78_update_device(dev); | 318 | struct lm78_data *data = lm78_update_device(dev); |
319 | int nr = attr->index; | ||
327 | return sprintf(buf, "%d\n", FAN_FROM_REG(data->fan[nr], | 320 | return sprintf(buf, "%d\n", FAN_FROM_REG(data->fan[nr], |
328 | DIV_FROM_REG(data->fan_div[nr])) ); | 321 | DIV_FROM_REG(data->fan_div[nr])) ); |
329 | } | 322 | } |
330 | 323 | ||
331 | static ssize_t show_fan_min(struct device *dev, char *buf, int nr) | 324 | static ssize_t show_fan_min(struct device *dev, struct device_attribute *da, |
325 | char *buf) | ||
332 | { | 326 | { |
327 | struct sensor_device_attribute *attr = to_sensor_dev_attr(da); | ||
333 | struct lm78_data *data = lm78_update_device(dev); | 328 | struct lm78_data *data = lm78_update_device(dev); |
329 | int nr = attr->index; | ||
334 | return sprintf(buf,"%d\n", FAN_FROM_REG(data->fan_min[nr], | 330 | return sprintf(buf,"%d\n", FAN_FROM_REG(data->fan_min[nr], |
335 | DIV_FROM_REG(data->fan_div[nr])) ); | 331 | DIV_FROM_REG(data->fan_div[nr])) ); |
336 | } | 332 | } |
337 | 333 | ||
338 | static ssize_t set_fan_min(struct device *dev, const char *buf, | 334 | static ssize_t set_fan_min(struct device *dev, struct device_attribute *da, |
339 | size_t count, int nr) | 335 | const char *buf, size_t count) |
340 | { | 336 | { |
341 | struct i2c_client *client = to_i2c_client(dev); | 337 | struct sensor_device_attribute *attr = to_sensor_dev_attr(da); |
342 | struct lm78_data *data = i2c_get_clientdata(client); | 338 | struct lm78_data *data = dev_get_drvdata(dev); |
339 | int nr = attr->index; | ||
343 | unsigned long val = simple_strtoul(buf, NULL, 10); | 340 | unsigned long val = simple_strtoul(buf, NULL, 10); |
344 | 341 | ||
345 | mutex_lock(&data->update_lock); | 342 | mutex_lock(&data->update_lock); |
346 | data->fan_min[nr] = FAN_TO_REG(val, DIV_FROM_REG(data->fan_div[nr])); | 343 | data->fan_min[nr] = FAN_TO_REG(val, DIV_FROM_REG(data->fan_div[nr])); |
347 | lm78_write_value(client, LM78_REG_FAN_MIN(nr), data->fan_min[nr]); | 344 | lm78_write_value(data, LM78_REG_FAN_MIN(nr), data->fan_min[nr]); |
348 | mutex_unlock(&data->update_lock); | 345 | mutex_unlock(&data->update_lock); |
349 | return count; | 346 | return count; |
350 | } | 347 | } |
351 | 348 | ||
352 | static ssize_t show_fan_div(struct device *dev, char *buf, int nr) | 349 | static ssize_t show_fan_div(struct device *dev, struct device_attribute *da, |
350 | char *buf) | ||
353 | { | 351 | { |
352 | struct sensor_device_attribute *attr = to_sensor_dev_attr(da); | ||
354 | struct lm78_data *data = lm78_update_device(dev); | 353 | struct lm78_data *data = lm78_update_device(dev); |
355 | return sprintf(buf, "%d\n", DIV_FROM_REG(data->fan_div[nr]) ); | 354 | return sprintf(buf, "%d\n", DIV_FROM_REG(data->fan_div[attr->index])); |
356 | } | 355 | } |
357 | 356 | ||
358 | /* Note: we save and restore the fan minimum here, because its value is | 357 | /* Note: we save and restore the fan minimum here, because its value is |
359 | determined in part by the fan divisor. This follows the principle of | 358 | determined in part by the fan divisor. This follows the principle of |
360 | least surprise; the user doesn't expect the fan minimum to change just | 359 | least surprise; the user doesn't expect the fan minimum to change just |
361 | because the divisor changed. */ | 360 | because the divisor changed. */ |
362 | static ssize_t set_fan_div(struct device *dev, const char *buf, | 361 | static ssize_t set_fan_div(struct device *dev, struct device_attribute *da, |
363 | size_t count, int nr) | 362 | const char *buf, size_t count) |
364 | { | 363 | { |
365 | struct i2c_client *client = to_i2c_client(dev); | 364 | struct sensor_device_attribute *attr = to_sensor_dev_attr(da); |
366 | struct lm78_data *data = i2c_get_clientdata(client); | 365 | struct lm78_data *data = dev_get_drvdata(dev); |
366 | int nr = attr->index; | ||
367 | unsigned long val = simple_strtoul(buf, NULL, 10); | 367 | unsigned long val = simple_strtoul(buf, NULL, 10); |
368 | unsigned long min; | 368 | unsigned long min; |
369 | u8 reg; | 369 | u8 reg; |
@@ -378,13 +378,13 @@ static ssize_t set_fan_div(struct device *dev, const char *buf, | |||
378 | case 4: data->fan_div[nr] = 2; break; | 378 | case 4: data->fan_div[nr] = 2; break; |
379 | case 8: data->fan_div[nr] = 3; break; | 379 | case 8: data->fan_div[nr] = 3; break; |
380 | default: | 380 | default: |
381 | dev_err(&client->dev, "fan_div value %ld not " | 381 | dev_err(dev, "fan_div value %ld not " |
382 | "supported. Choose one of 1, 2, 4 or 8!\n", val); | 382 | "supported. Choose one of 1, 2, 4 or 8!\n", val); |
383 | mutex_unlock(&data->update_lock); | 383 | mutex_unlock(&data->update_lock); |
384 | return -EINVAL; | 384 | return -EINVAL; |
385 | } | 385 | } |
386 | 386 | ||
387 | reg = lm78_read_value(client, LM78_REG_VID_FANDIV); | 387 | reg = lm78_read_value(data, LM78_REG_VID_FANDIV); |
388 | switch (nr) { | 388 | switch (nr) { |
389 | case 0: | 389 | case 0: |
390 | reg = (reg & 0xcf) | (data->fan_div[nr] << 4); | 390 | reg = (reg & 0xcf) | (data->fan_div[nr] << 4); |
@@ -393,63 +393,36 @@ static ssize_t set_fan_div(struct device *dev, const char *buf, | |||
393 | reg = (reg & 0x3f) | (data->fan_div[nr] << 6); | 393 | reg = (reg & 0x3f) | (data->fan_div[nr] << 6); |
394 | break; | 394 | break; |
395 | } | 395 | } |
396 | lm78_write_value(client, LM78_REG_VID_FANDIV, reg); | 396 | lm78_write_value(data, LM78_REG_VID_FANDIV, reg); |
397 | 397 | ||
398 | data->fan_min[nr] = | 398 | data->fan_min[nr] = |
399 | FAN_TO_REG(min, DIV_FROM_REG(data->fan_div[nr])); | 399 | FAN_TO_REG(min, DIV_FROM_REG(data->fan_div[nr])); |
400 | lm78_write_value(client, LM78_REG_FAN_MIN(nr), data->fan_min[nr]); | 400 | lm78_write_value(data, LM78_REG_FAN_MIN(nr), data->fan_min[nr]); |
401 | mutex_unlock(&data->update_lock); | 401 | mutex_unlock(&data->update_lock); |
402 | 402 | ||
403 | return count; | 403 | return count; |
404 | } | 404 | } |
405 | 405 | ||
406 | #define show_fan_offset(offset) \ | 406 | #define show_fan_offset(offset) \ |
407 | static ssize_t show_fan_##offset (struct device *dev, struct device_attribute *attr, char *buf) \ | 407 | static SENSOR_DEVICE_ATTR(fan##offset##_input, S_IRUGO, \ |
408 | { \ | 408 | show_fan, NULL, offset - 1); \ |
409 | return show_fan(dev, buf, offset - 1); \ | 409 | static SENSOR_DEVICE_ATTR(fan##offset##_min, S_IRUGO | S_IWUSR, \ |
410 | } \ | 410 | show_fan_min, set_fan_min, offset - 1); |
411 | static ssize_t show_fan_##offset##_min (struct device *dev, struct device_attribute *attr, char *buf) \ | ||
412 | { \ | ||
413 | return show_fan_min(dev, buf, offset - 1); \ | ||
414 | } \ | ||
415 | static ssize_t show_fan_##offset##_div (struct device *dev, struct device_attribute *attr, char *buf) \ | ||
416 | { \ | ||
417 | return show_fan_div(dev, buf, offset - 1); \ | ||
418 | } \ | ||
419 | static ssize_t set_fan_##offset##_min (struct device *dev, struct device_attribute *attr, \ | ||
420 | const char *buf, size_t count) \ | ||
421 | { \ | ||
422 | return set_fan_min(dev, buf, count, offset - 1); \ | ||
423 | } \ | ||
424 | static DEVICE_ATTR(fan##offset##_input, S_IRUGO, show_fan_##offset, NULL);\ | ||
425 | static DEVICE_ATTR(fan##offset##_min, S_IRUGO | S_IWUSR, \ | ||
426 | show_fan_##offset##_min, set_fan_##offset##_min); | ||
427 | |||
428 | static ssize_t set_fan_1_div(struct device *dev, struct device_attribute *attr, const char *buf, | ||
429 | size_t count) | ||
430 | { | ||
431 | return set_fan_div(dev, buf, count, 0) ; | ||
432 | } | ||
433 | |||
434 | static ssize_t set_fan_2_div(struct device *dev, struct device_attribute *attr, const char *buf, | ||
435 | size_t count) | ||
436 | { | ||
437 | return set_fan_div(dev, buf, count, 1) ; | ||
438 | } | ||
439 | 411 | ||
440 | show_fan_offset(1); | 412 | show_fan_offset(1); |
441 | show_fan_offset(2); | 413 | show_fan_offset(2); |
442 | show_fan_offset(3); | 414 | show_fan_offset(3); |
443 | 415 | ||
444 | /* Fan 3 divisor is locked in H/W */ | 416 | /* Fan 3 divisor is locked in H/W */ |
445 | static DEVICE_ATTR(fan1_div, S_IRUGO | S_IWUSR, | 417 | static SENSOR_DEVICE_ATTR(fan1_div, S_IRUGO | S_IWUSR, |
446 | show_fan_1_div, set_fan_1_div); | 418 | show_fan_div, set_fan_div, 0); |
447 | static DEVICE_ATTR(fan2_div, S_IRUGO | S_IWUSR, | 419 | static SENSOR_DEVICE_ATTR(fan2_div, S_IRUGO | S_IWUSR, |
448 | show_fan_2_div, set_fan_2_div); | 420 | show_fan_div, set_fan_div, 1); |
449 | static DEVICE_ATTR(fan3_div, S_IRUGO, show_fan_3_div, NULL); | 421 | static SENSOR_DEVICE_ATTR(fan3_div, S_IRUGO, show_fan_div, NULL, 2); |
450 | 422 | ||
451 | /* VID */ | 423 | /* VID */ |
452 | static ssize_t show_vid(struct device *dev, struct device_attribute *attr, char *buf) | 424 | static ssize_t show_vid(struct device *dev, struct device_attribute *da, |
425 | char *buf) | ||
453 | { | 426 | { |
454 | struct lm78_data *data = lm78_update_device(dev); | 427 | struct lm78_data *data = lm78_update_device(dev); |
455 | return sprintf(buf, "%d\n", vid_from_reg(data->vid, 82)); | 428 | return sprintf(buf, "%d\n", vid_from_reg(data->vid, 82)); |
@@ -457,7 +430,8 @@ static ssize_t show_vid(struct device *dev, struct device_attribute *attr, char | |||
457 | static DEVICE_ATTR(cpu0_vid, S_IRUGO, show_vid, NULL); | 430 | static DEVICE_ATTR(cpu0_vid, S_IRUGO, show_vid, NULL); |
458 | 431 | ||
459 | /* Alarms */ | 432 | /* Alarms */ |
460 | static ssize_t show_alarms(struct device *dev, struct device_attribute *attr, char *buf) | 433 | static ssize_t show_alarms(struct device *dev, struct device_attribute *da, |
434 | char *buf) | ||
461 | { | 435 | { |
462 | struct lm78_data *data = lm78_update_device(dev); | 436 | struct lm78_data *data = lm78_update_device(dev); |
463 | return sprintf(buf, "%u\n", data->alarms); | 437 | return sprintf(buf, "%u\n", data->alarms); |
@@ -475,45 +449,40 @@ static int lm78_attach_adapter(struct i2c_adapter *adapter) | |||
475 | return i2c_probe(adapter, &addr_data, lm78_detect); | 449 | return i2c_probe(adapter, &addr_data, lm78_detect); |
476 | } | 450 | } |
477 | 451 | ||
478 | static int lm78_isa_attach_adapter(struct i2c_adapter *adapter) | ||
479 | { | ||
480 | return lm78_detect(adapter, isa_address, -1); | ||
481 | } | ||
482 | |||
483 | static struct attribute *lm78_attributes[] = { | 452 | static struct attribute *lm78_attributes[] = { |
484 | &dev_attr_in0_input.attr, | 453 | &sensor_dev_attr_in0_input.dev_attr.attr, |
485 | &dev_attr_in0_min.attr, | 454 | &sensor_dev_attr_in0_min.dev_attr.attr, |
486 | &dev_attr_in0_max.attr, | 455 | &sensor_dev_attr_in0_max.dev_attr.attr, |
487 | &dev_attr_in1_input.attr, | 456 | &sensor_dev_attr_in1_input.dev_attr.attr, |
488 | &dev_attr_in1_min.attr, | 457 | &sensor_dev_attr_in1_min.dev_attr.attr, |
489 | &dev_attr_in1_max.attr, | 458 | &sensor_dev_attr_in1_max.dev_attr.attr, |
490 | &dev_attr_in2_input.attr, | 459 | &sensor_dev_attr_in2_input.dev_attr.attr, |
491 | &dev_attr_in2_min.attr, | 460 | &sensor_dev_attr_in2_min.dev_attr.attr, |
492 | &dev_attr_in2_max.attr, | 461 | &sensor_dev_attr_in2_max.dev_attr.attr, |
493 | &dev_attr_in3_input.attr, | 462 | &sensor_dev_attr_in3_input.dev_attr.attr, |
494 | &dev_attr_in3_min.attr, | 463 | &sensor_dev_attr_in3_min.dev_attr.attr, |
495 | &dev_attr_in3_max.attr, | 464 | &sensor_dev_attr_in3_max.dev_attr.attr, |
496 | &dev_attr_in4_input.attr, | 465 | &sensor_dev_attr_in4_input.dev_attr.attr, |
497 | &dev_attr_in4_min.attr, | 466 | &sensor_dev_attr_in4_min.dev_attr.attr, |
498 | &dev_attr_in4_max.attr, | 467 | &sensor_dev_attr_in4_max.dev_attr.attr, |
499 | &dev_attr_in5_input.attr, | 468 | &sensor_dev_attr_in5_input.dev_attr.attr, |
500 | &dev_attr_in5_min.attr, | 469 | &sensor_dev_attr_in5_min.dev_attr.attr, |
501 | &dev_attr_in5_max.attr, | 470 | &sensor_dev_attr_in5_max.dev_attr.attr, |
502 | &dev_attr_in6_input.attr, | 471 | &sensor_dev_attr_in6_input.dev_attr.attr, |
503 | &dev_attr_in6_min.attr, | 472 | &sensor_dev_attr_in6_min.dev_attr.attr, |
504 | &dev_attr_in6_max.attr, | 473 | &sensor_dev_attr_in6_max.dev_attr.attr, |
505 | &dev_attr_temp1_input.attr, | 474 | &dev_attr_temp1_input.attr, |
506 | &dev_attr_temp1_max.attr, | 475 | &dev_attr_temp1_max.attr, |
507 | &dev_attr_temp1_max_hyst.attr, | 476 | &dev_attr_temp1_max_hyst.attr, |
508 | &dev_attr_fan1_input.attr, | 477 | &sensor_dev_attr_fan1_input.dev_attr.attr, |
509 | &dev_attr_fan1_min.attr, | 478 | &sensor_dev_attr_fan1_min.dev_attr.attr, |
510 | &dev_attr_fan1_div.attr, | 479 | &sensor_dev_attr_fan1_div.dev_attr.attr, |
511 | &dev_attr_fan2_input.attr, | 480 | &sensor_dev_attr_fan2_input.dev_attr.attr, |
512 | &dev_attr_fan2_min.attr, | 481 | &sensor_dev_attr_fan2_min.dev_attr.attr, |
513 | &dev_attr_fan2_div.attr, | 482 | &sensor_dev_attr_fan2_div.dev_attr.attr, |
514 | &dev_attr_fan3_input.attr, | 483 | &sensor_dev_attr_fan3_input.dev_attr.attr, |
515 | &dev_attr_fan3_min.attr, | 484 | &sensor_dev_attr_fan3_min.dev_attr.attr, |
516 | &dev_attr_fan3_div.attr, | 485 | &sensor_dev_attr_fan3_div.dev_attr.attr, |
517 | &dev_attr_alarms.attr, | 486 | &dev_attr_alarms.attr, |
518 | &dev_attr_cpu0_vid.attr, | 487 | &dev_attr_cpu0_vid.attr, |
519 | 488 | ||
@@ -524,6 +493,17 @@ static const struct attribute_group lm78_group = { | |||
524 | .attrs = lm78_attributes, | 493 | .attrs = lm78_attributes, |
525 | }; | 494 | }; |
526 | 495 | ||
496 | /* I2C devices get this name attribute automatically, but for ISA devices | ||
497 | we must create it by ourselves. */ | ||
498 | static ssize_t show_name(struct device *dev, struct device_attribute | ||
499 | *devattr, char *buf) | ||
500 | { | ||
501 | struct lm78_data *data = dev_get_drvdata(dev); | ||
502 | |||
503 | return sprintf(buf, "%s\n", data->client.name); | ||
504 | } | ||
505 | static DEVICE_ATTR(name, S_IRUGO, show_name, NULL); | ||
506 | |||
527 | /* This function is called by i2c_probe */ | 507 | /* This function is called by i2c_probe */ |
528 | static int lm78_detect(struct i2c_adapter *adapter, int address, int kind) | 508 | static int lm78_detect(struct i2c_adapter *adapter, int address, int kind) |
529 | { | 509 | { |
@@ -531,54 +511,10 @@ static int lm78_detect(struct i2c_adapter *adapter, int address, int kind) | |||
531 | struct i2c_client *new_client; | 511 | struct i2c_client *new_client; |
532 | struct lm78_data *data; | 512 | struct lm78_data *data; |
533 | const char *client_name = ""; | 513 | const char *client_name = ""; |
534 | int is_isa = i2c_is_isa_adapter(adapter); | ||
535 | 514 | ||
536 | if (!is_isa && | 515 | if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA)) { |
537 | !i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA)) { | ||
538 | err = -ENODEV; | 516 | err = -ENODEV; |
539 | goto ERROR0; | 517 | goto ERROR1; |
540 | } | ||
541 | |||
542 | /* Reserve the ISA region */ | ||
543 | if (is_isa) | ||
544 | if (!request_region(address, LM78_EXTENT, | ||
545 | lm78_isa_driver.driver.name)) { | ||
546 | err = -EBUSY; | ||
547 | goto ERROR0; | ||
548 | } | ||
549 | |||
550 | /* Probe whether there is anything available on this address. Already | ||
551 | done for SMBus clients */ | ||
552 | if (kind < 0) { | ||
553 | if (is_isa) { | ||
554 | |||
555 | #define REALLY_SLOW_IO | ||
556 | /* We need the timeouts for at least some LM78-like | ||
557 | chips. But only if we read 'undefined' registers. */ | ||
558 | i = inb_p(address + 1); | ||
559 | if (inb_p(address + 2) != i) { | ||
560 | err = -ENODEV; | ||
561 | goto ERROR1; | ||
562 | } | ||
563 | if (inb_p(address + 3) != i) { | ||
564 | err = -ENODEV; | ||
565 | goto ERROR1; | ||
566 | } | ||
567 | if (inb_p(address + 7) != i) { | ||
568 | err = -ENODEV; | ||
569 | goto ERROR1; | ||
570 | } | ||
571 | #undef REALLY_SLOW_IO | ||
572 | |||
573 | /* Let's just hope nothing breaks here */ | ||
574 | i = inb_p(address + 5) & 0x7f; | ||
575 | outb_p(~i & 0x7f, address + 5); | ||
576 | if ((inb_p(address + 5) & 0x7f) != (~i & 0x7f)) { | ||
577 | outb_p(i, address + 5); | ||
578 | err = -ENODEV; | ||
579 | goto ERROR1; | ||
580 | } | ||
581 | } | ||
582 | } | 518 | } |
583 | 519 | ||
584 | /* OK. For now, we presume we have a valid client. We now create the | 520 | /* OK. For now, we presume we have a valid client. We now create the |
@@ -591,22 +527,19 @@ static int lm78_detect(struct i2c_adapter *adapter, int address, int kind) | |||
591 | } | 527 | } |
592 | 528 | ||
593 | new_client = &data->client; | 529 | new_client = &data->client; |
594 | if (is_isa) | ||
595 | mutex_init(&data->lock); | ||
596 | i2c_set_clientdata(new_client, data); | 530 | i2c_set_clientdata(new_client, data); |
597 | new_client->addr = address; | 531 | new_client->addr = address; |
598 | new_client->adapter = adapter; | 532 | new_client->adapter = adapter; |
599 | new_client->driver = is_isa ? &lm78_isa_driver : &lm78_driver; | 533 | new_client->driver = &lm78_driver; |
600 | new_client->flags = 0; | ||
601 | 534 | ||
602 | /* Now, we do the remaining detection. */ | 535 | /* Now, we do the remaining detection. */ |
603 | if (kind < 0) { | 536 | if (kind < 0) { |
604 | if (lm78_read_value(new_client, LM78_REG_CONFIG) & 0x80) { | 537 | if (lm78_read_value(data, LM78_REG_CONFIG) & 0x80) { |
605 | err = -ENODEV; | 538 | err = -ENODEV; |
606 | goto ERROR2; | 539 | goto ERROR2; |
607 | } | 540 | } |
608 | if (!is_isa && (lm78_read_value( | 541 | if (lm78_read_value(data, LM78_REG_I2C_ADDR) != |
609 | new_client, LM78_REG_I2C_ADDR) != address)) { | 542 | address) { |
610 | err = -ENODEV; | 543 | err = -ENODEV; |
611 | goto ERROR2; | 544 | goto ERROR2; |
612 | } | 545 | } |
@@ -614,7 +547,7 @@ static int lm78_detect(struct i2c_adapter *adapter, int address, int kind) | |||
614 | 547 | ||
615 | /* Determine the chip type. */ | 548 | /* Determine the chip type. */ |
616 | if (kind <= 0) { | 549 | if (kind <= 0) { |
617 | i = lm78_read_value(new_client, LM78_REG_CHIPID); | 550 | i = lm78_read_value(data, LM78_REG_CHIPID); |
618 | if (i == 0x00 || i == 0x20 /* LM78 */ | 551 | if (i == 0x00 || i == 0x20 /* LM78 */ |
619 | || i == 0x40) /* LM78-J */ | 552 | || i == 0x40) /* LM78-J */ |
620 | kind = lm78; | 553 | kind = lm78; |
@@ -641,21 +574,12 @@ static int lm78_detect(struct i2c_adapter *adapter, int address, int kind) | |||
641 | strlcpy(new_client->name, client_name, I2C_NAME_SIZE); | 574 | strlcpy(new_client->name, client_name, I2C_NAME_SIZE); |
642 | data->type = kind; | 575 | data->type = kind; |
643 | 576 | ||
644 | data->valid = 0; | ||
645 | mutex_init(&data->update_lock); | ||
646 | |||
647 | /* Tell the I2C layer a new client has arrived */ | 577 | /* Tell the I2C layer a new client has arrived */ |
648 | if ((err = i2c_attach_client(new_client))) | 578 | if ((err = i2c_attach_client(new_client))) |
649 | goto ERROR2; | 579 | goto ERROR2; |
650 | 580 | ||
651 | /* Initialize the LM78 chip */ | 581 | /* Initialize the LM78 chip */ |
652 | lm78_init_client(new_client); | 582 | lm78_init_device(data); |
653 | |||
654 | /* A few vars need to be filled upon startup */ | ||
655 | for (i = 0; i < 3; i++) { | ||
656 | data->fan_min[i] = lm78_read_value(new_client, | ||
657 | LM78_REG_FAN_MIN(i)); | ||
658 | } | ||
659 | 583 | ||
660 | /* Register sysfs hooks */ | 584 | /* Register sysfs hooks */ |
661 | if ((err = sysfs_create_group(&new_client->dev.kobj, &lm78_group))) | 585 | if ((err = sysfs_create_group(&new_client->dev.kobj, &lm78_group))) |
@@ -676,9 +600,6 @@ ERROR3: | |||
676 | ERROR2: | 600 | ERROR2: |
677 | kfree(data); | 601 | kfree(data); |
678 | ERROR1: | 602 | ERROR1: |
679 | if (is_isa) | ||
680 | release_region(address, LM78_EXTENT); | ||
681 | ERROR0: | ||
682 | return err; | 603 | return err; |
683 | } | 604 | } |
684 | 605 | ||
@@ -693,9 +614,77 @@ static int lm78_detach_client(struct i2c_client *client) | |||
693 | if ((err = i2c_detach_client(client))) | 614 | if ((err = i2c_detach_client(client))) |
694 | return err; | 615 | return err; |
695 | 616 | ||
696 | if(i2c_is_isa_client(client)) | 617 | kfree(data); |
697 | release_region(client->addr, LM78_EXTENT); | 618 | |
619 | return 0; | ||
620 | } | ||
621 | |||
622 | static int __devinit lm78_isa_probe(struct platform_device *pdev) | ||
623 | { | ||
624 | int err; | ||
625 | struct lm78_data *data; | ||
626 | struct resource *res; | ||
627 | const char *name; | ||
628 | |||
629 | /* Reserve the ISA region */ | ||
630 | res = platform_get_resource(pdev, IORESOURCE_IO, 0); | ||
631 | if (!request_region(res->start, LM78_EXTENT, "lm78")) { | ||
632 | err = -EBUSY; | ||
633 | goto exit; | ||
634 | } | ||
635 | |||
636 | if (!(data = kzalloc(sizeof(struct lm78_data), GFP_KERNEL))) { | ||
637 | err = -ENOMEM; | ||
638 | goto exit_release_region; | ||
639 | } | ||
640 | mutex_init(&data->lock); | ||
641 | data->client.addr = res->start; | ||
642 | i2c_set_clientdata(&data->client, data); | ||
643 | platform_set_drvdata(pdev, data); | ||
644 | |||
645 | if (lm78_read_value(data, LM78_REG_CHIPID) & 0x80) { | ||
646 | data->type = lm79; | ||
647 | name = "lm79"; | ||
648 | } else { | ||
649 | data->type = lm78; | ||
650 | name = "lm78"; | ||
651 | } | ||
652 | strlcpy(data->client.name, name, I2C_NAME_SIZE); | ||
653 | |||
654 | /* Initialize the LM78 chip */ | ||
655 | lm78_init_device(data); | ||
656 | |||
657 | /* Register sysfs hooks */ | ||
658 | if ((err = sysfs_create_group(&pdev->dev.kobj, &lm78_group)) | ||
659 | || (err = device_create_file(&pdev->dev, &dev_attr_name))) | ||
660 | goto exit_remove_files; | ||
661 | |||
662 | data->class_dev = hwmon_device_register(&pdev->dev); | ||
663 | if (IS_ERR(data->class_dev)) { | ||
664 | err = PTR_ERR(data->class_dev); | ||
665 | goto exit_remove_files; | ||
666 | } | ||
667 | |||
668 | return 0; | ||
669 | |||
670 | exit_remove_files: | ||
671 | sysfs_remove_group(&pdev->dev.kobj, &lm78_group); | ||
672 | device_remove_file(&pdev->dev, &dev_attr_name); | ||
673 | kfree(data); | ||
674 | exit_release_region: | ||
675 | release_region(res->start, LM78_EXTENT); | ||
676 | exit: | ||
677 | return err; | ||
678 | } | ||
679 | |||
680 | static int __devexit lm78_isa_remove(struct platform_device *pdev) | ||
681 | { | ||
682 | struct lm78_data *data = platform_get_drvdata(pdev); | ||
698 | 683 | ||
684 | hwmon_device_unregister(data->class_dev); | ||
685 | sysfs_remove_group(&pdev->dev.kobj, &lm78_group); | ||
686 | device_remove_file(&pdev->dev, &dev_attr_name); | ||
687 | release_region(data->client.addr, LM78_EXTENT); | ||
699 | kfree(data); | 688 | kfree(data); |
700 | 689 | ||
701 | return 0; | 690 | return 0; |
@@ -706,11 +695,12 @@ static int lm78_detach_client(struct i2c_client *client) | |||
706 | separately. | 695 | separately. |
707 | We ignore the LM78 BUSY flag at this moment - it could lead to deadlocks, | 696 | We ignore the LM78 BUSY flag at this moment - it could lead to deadlocks, |
708 | would slow down the LM78 access and should not be necessary. */ | 697 | would slow down the LM78 access and should not be necessary. */ |
709 | static int lm78_read_value(struct i2c_client *client, u8 reg) | 698 | static int lm78_read_value(struct lm78_data *data, u8 reg) |
710 | { | 699 | { |
711 | int res; | 700 | struct i2c_client *client = &data->client; |
712 | if (i2c_is_isa_client(client)) { | 701 | |
713 | struct lm78_data *data = i2c_get_clientdata(client); | 702 | if (!client->driver) { /* ISA device */ |
703 | int res; | ||
714 | mutex_lock(&data->lock); | 704 | mutex_lock(&data->lock); |
715 | outb_p(reg, client->addr + LM78_ADDR_REG_OFFSET); | 705 | outb_p(reg, client->addr + LM78_ADDR_REG_OFFSET); |
716 | res = inb_p(client->addr + LM78_DATA_REG_OFFSET); | 706 | res = inb_p(client->addr + LM78_DATA_REG_OFFSET); |
@@ -727,10 +717,11 @@ static int lm78_read_value(struct i2c_client *client, u8 reg) | |||
727 | would slow down the LM78 access and should not be necessary. | 717 | would slow down the LM78 access and should not be necessary. |
728 | There are some ugly typecasts here, but the good new is - they should | 718 | There are some ugly typecasts here, but the good new is - they should |
729 | nowhere else be necessary! */ | 719 | nowhere else be necessary! */ |
730 | static int lm78_write_value(struct i2c_client *client, u8 reg, u8 value) | 720 | static int lm78_write_value(struct lm78_data *data, u8 reg, u8 value) |
731 | { | 721 | { |
732 | if (i2c_is_isa_client(client)) { | 722 | struct i2c_client *client = &data->client; |
733 | struct lm78_data *data = i2c_get_clientdata(client); | 723 | |
724 | if (!client->driver) { /* ISA device */ | ||
734 | mutex_lock(&data->lock); | 725 | mutex_lock(&data->lock); |
735 | outb_p(reg, client->addr + LM78_ADDR_REG_OFFSET); | 726 | outb_p(reg, client->addr + LM78_ADDR_REG_OFFSET); |
736 | outb_p(value, client->addr + LM78_DATA_REG_OFFSET); | 727 | outb_p(value, client->addr + LM78_DATA_REG_OFFSET); |
@@ -740,20 +731,29 @@ static int lm78_write_value(struct i2c_client *client, u8 reg, u8 value) | |||
740 | return i2c_smbus_write_byte_data(client, reg, value); | 731 | return i2c_smbus_write_byte_data(client, reg, value); |
741 | } | 732 | } |
742 | 733 | ||
743 | static void lm78_init_client(struct i2c_client *client) | 734 | static void lm78_init_device(struct lm78_data *data) |
744 | { | 735 | { |
745 | u8 config = lm78_read_value(client, LM78_REG_CONFIG); | 736 | u8 config; |
737 | int i; | ||
746 | 738 | ||
747 | /* Start monitoring */ | 739 | /* Start monitoring */ |
748 | if (!(config & 0x01)) | 740 | config = lm78_read_value(data, LM78_REG_CONFIG); |
749 | lm78_write_value(client, LM78_REG_CONFIG, | 741 | if ((config & 0x09) != 0x01) |
742 | lm78_write_value(data, LM78_REG_CONFIG, | ||
750 | (config & 0xf7) | 0x01); | 743 | (config & 0xf7) | 0x01); |
744 | |||
745 | /* A few vars need to be filled upon startup */ | ||
746 | for (i = 0; i < 3; i++) { | ||
747 | data->fan_min[i] = lm78_read_value(data, | ||
748 | LM78_REG_FAN_MIN(i)); | ||
749 | } | ||
750 | |||
751 | mutex_init(&data->update_lock); | ||
751 | } | 752 | } |
752 | 753 | ||
753 | static struct lm78_data *lm78_update_device(struct device *dev) | 754 | static struct lm78_data *lm78_update_device(struct device *dev) |
754 | { | 755 | { |
755 | struct i2c_client *client = to_i2c_client(dev); | 756 | struct lm78_data *data = dev_get_drvdata(dev); |
756 | struct lm78_data *data = i2c_get_clientdata(client); | ||
757 | int i; | 757 | int i; |
758 | 758 | ||
759 | mutex_lock(&data->update_lock); | 759 | mutex_lock(&data->update_lock); |
@@ -761,39 +761,39 @@ static struct lm78_data *lm78_update_device(struct device *dev) | |||
761 | if (time_after(jiffies, data->last_updated + HZ + HZ / 2) | 761 | if (time_after(jiffies, data->last_updated + HZ + HZ / 2) |
762 | || !data->valid) { | 762 | || !data->valid) { |
763 | 763 | ||
764 | dev_dbg(&client->dev, "Starting lm78 update\n"); | 764 | dev_dbg(dev, "Starting lm78 update\n"); |
765 | 765 | ||
766 | for (i = 0; i <= 6; i++) { | 766 | for (i = 0; i <= 6; i++) { |
767 | data->in[i] = | 767 | data->in[i] = |
768 | lm78_read_value(client, LM78_REG_IN(i)); | 768 | lm78_read_value(data, LM78_REG_IN(i)); |
769 | data->in_min[i] = | 769 | data->in_min[i] = |
770 | lm78_read_value(client, LM78_REG_IN_MIN(i)); | 770 | lm78_read_value(data, LM78_REG_IN_MIN(i)); |
771 | data->in_max[i] = | 771 | data->in_max[i] = |
772 | lm78_read_value(client, LM78_REG_IN_MAX(i)); | 772 | lm78_read_value(data, LM78_REG_IN_MAX(i)); |
773 | } | 773 | } |
774 | for (i = 0; i < 3; i++) { | 774 | for (i = 0; i < 3; i++) { |
775 | data->fan[i] = | 775 | data->fan[i] = |
776 | lm78_read_value(client, LM78_REG_FAN(i)); | 776 | lm78_read_value(data, LM78_REG_FAN(i)); |
777 | data->fan_min[i] = | 777 | data->fan_min[i] = |
778 | lm78_read_value(client, LM78_REG_FAN_MIN(i)); | 778 | lm78_read_value(data, LM78_REG_FAN_MIN(i)); |
779 | } | 779 | } |
780 | data->temp = lm78_read_value(client, LM78_REG_TEMP); | 780 | data->temp = lm78_read_value(data, LM78_REG_TEMP); |
781 | data->temp_over = | 781 | data->temp_over = |
782 | lm78_read_value(client, LM78_REG_TEMP_OVER); | 782 | lm78_read_value(data, LM78_REG_TEMP_OVER); |
783 | data->temp_hyst = | 783 | data->temp_hyst = |
784 | lm78_read_value(client, LM78_REG_TEMP_HYST); | 784 | lm78_read_value(data, LM78_REG_TEMP_HYST); |
785 | i = lm78_read_value(client, LM78_REG_VID_FANDIV); | 785 | i = lm78_read_value(data, LM78_REG_VID_FANDIV); |
786 | data->vid = i & 0x0f; | 786 | data->vid = i & 0x0f; |
787 | if (data->type == lm79) | 787 | if (data->type == lm79) |
788 | data->vid |= | 788 | data->vid |= |
789 | (lm78_read_value(client, LM78_REG_CHIPID) & | 789 | (lm78_read_value(data, LM78_REG_CHIPID) & |
790 | 0x01) << 4; | 790 | 0x01) << 4; |
791 | else | 791 | else |
792 | data->vid |= 0x10; | 792 | data->vid |= 0x10; |
793 | data->fan_div[0] = (i >> 4) & 0x03; | 793 | data->fan_div[0] = (i >> 4) & 0x03; |
794 | data->fan_div[1] = i >> 6; | 794 | data->fan_div[1] = i >> 6; |
795 | data->alarms = lm78_read_value(client, LM78_REG_ALARM1) + | 795 | data->alarms = lm78_read_value(data, LM78_REG_ALARM1) + |
796 | (lm78_read_value(client, LM78_REG_ALARM2) << 8); | 796 | (lm78_read_value(data, LM78_REG_ALARM2) << 8); |
797 | data->last_updated = jiffies; | 797 | data->last_updated = jiffies; |
798 | data->valid = 1; | 798 | data->valid = 1; |
799 | 799 | ||
@@ -805,26 +805,154 @@ static struct lm78_data *lm78_update_device(struct device *dev) | |||
805 | return data; | 805 | return data; |
806 | } | 806 | } |
807 | 807 | ||
808 | /* return 1 if a supported chip is found, 0 otherwise */ | ||
809 | static int __init lm78_isa_found(unsigned short address) | ||
810 | { | ||
811 | int val, save, found = 0; | ||
812 | |||
813 | if (!request_region(address, LM78_EXTENT, "lm78")) | ||
814 | return 0; | ||
815 | |||
816 | #define REALLY_SLOW_IO | ||
817 | /* We need the timeouts for at least some LM78-like | ||
818 | chips. But only if we read 'undefined' registers. */ | ||
819 | val = inb_p(address + 1); | ||
820 | if (inb_p(address + 2) != val | ||
821 | || inb_p(address + 3) != val | ||
822 | || inb_p(address + 7) != val) | ||
823 | goto release; | ||
824 | #undef REALLY_SLOW_IO | ||
825 | |||
826 | /* We should be able to change the 7 LSB of the address port. The | ||
827 | MSB (busy flag) should be clear initially, set after the write. */ | ||
828 | save = inb_p(address + LM78_ADDR_REG_OFFSET); | ||
829 | if (save & 0x80) | ||
830 | goto release; | ||
831 | val = ~save & 0x7f; | ||
832 | outb_p(val, address + LM78_ADDR_REG_OFFSET); | ||
833 | if (inb_p(address + LM78_ADDR_REG_OFFSET) != (val | 0x80)) { | ||
834 | outb_p(save, address + LM78_ADDR_REG_OFFSET); | ||
835 | goto release; | ||
836 | } | ||
837 | |||
838 | /* We found a device, now see if it could be an LM78 */ | ||
839 | outb_p(LM78_REG_CONFIG, address + LM78_ADDR_REG_OFFSET); | ||
840 | val = inb_p(address + LM78_DATA_REG_OFFSET); | ||
841 | if (val & 0x80) | ||
842 | goto release; | ||
843 | outb_p(LM78_REG_I2C_ADDR, address + LM78_ADDR_REG_OFFSET); | ||
844 | val = inb_p(address + LM78_DATA_REG_OFFSET); | ||
845 | if (val < 0x03 || val > 0x77) /* Not a valid I2C address */ | ||
846 | goto release; | ||
847 | |||
848 | /* The busy flag should be clear again */ | ||
849 | if (inb_p(address + LM78_ADDR_REG_OFFSET) & 0x80) | ||
850 | goto release; | ||
851 | |||
852 | /* Explicitly prevent the misdetection of Winbond chips */ | ||
853 | outb_p(0x4f, address + LM78_ADDR_REG_OFFSET); | ||
854 | val = inb_p(address + LM78_DATA_REG_OFFSET); | ||
855 | if (val == 0xa3 || val == 0x5c) | ||
856 | goto release; | ||
857 | |||
858 | /* Explicitly prevent the misdetection of ITE chips */ | ||
859 | outb_p(0x58, address + LM78_ADDR_REG_OFFSET); | ||
860 | val = inb_p(address + LM78_DATA_REG_OFFSET); | ||
861 | if (val == 0x90) | ||
862 | goto release; | ||
863 | |||
864 | /* Determine the chip type */ | ||
865 | outb_p(LM78_REG_CHIPID, address + LM78_ADDR_REG_OFFSET); | ||
866 | val = inb_p(address + LM78_DATA_REG_OFFSET); | ||
867 | if (val == 0x00 /* LM78 */ | ||
868 | || val == 0x40 /* LM78-J */ | ||
869 | || (val & 0xfe) == 0xc0) /* LM79 */ | ||
870 | found = 1; | ||
871 | |||
872 | if (found) | ||
873 | pr_info("lm78: Found an %s chip at %#x\n", | ||
874 | val & 0x80 ? "LM79" : "LM78", (int)address); | ||
875 | |||
876 | release: | ||
877 | release_region(address, LM78_EXTENT); | ||
878 | return found; | ||
879 | } | ||
880 | |||
881 | static int __init lm78_isa_device_add(unsigned short address) | ||
882 | { | ||
883 | struct resource res = { | ||
884 | .start = address, | ||
885 | .end = address + LM78_EXTENT, | ||
886 | .name = "lm78", | ||
887 | .flags = IORESOURCE_IO, | ||
888 | }; | ||
889 | int err; | ||
890 | |||
891 | pdev = platform_device_alloc("lm78", address); | ||
892 | if (!pdev) { | ||
893 | err = -ENOMEM; | ||
894 | printk(KERN_ERR "lm78: Device allocation failed\n"); | ||
895 | goto exit; | ||
896 | } | ||
897 | |||
898 | err = platform_device_add_resources(pdev, &res, 1); | ||
899 | if (err) { | ||
900 | printk(KERN_ERR "lm78: Device resource addition failed " | ||
901 | "(%d)\n", err); | ||
902 | goto exit_device_put; | ||
903 | } | ||
904 | |||
905 | err = platform_device_add(pdev); | ||
906 | if (err) { | ||
907 | printk(KERN_ERR "lm78: Device addition failed (%d)\n", | ||
908 | err); | ||
909 | goto exit_device_put; | ||
910 | } | ||
911 | |||
912 | return 0; | ||
913 | |||
914 | exit_device_put: | ||
915 | platform_device_put(pdev); | ||
916 | exit: | ||
917 | pdev = NULL; | ||
918 | return err; | ||
919 | } | ||
920 | |||
808 | static int __init sm_lm78_init(void) | 921 | static int __init sm_lm78_init(void) |
809 | { | 922 | { |
810 | int res; | 923 | int res; |
811 | 924 | ||
812 | res = i2c_add_driver(&lm78_driver); | 925 | res = i2c_add_driver(&lm78_driver); |
813 | if (res) | 926 | if (res) |
814 | return res; | 927 | goto exit; |
815 | 928 | ||
816 | /* Don't exit if this one fails, we still want the I2C variants | 929 | if (lm78_isa_found(isa_address)) { |
817 | to work! */ | 930 | res = platform_driver_register(&lm78_isa_driver); |
818 | if (i2c_isa_add_driver(&lm78_isa_driver)) | 931 | if (res) |
819 | isa_address = 0; | 932 | goto exit_unreg_i2c_driver; |
933 | |||
934 | /* Sets global pdev as a side effect */ | ||
935 | res = lm78_isa_device_add(isa_address); | ||
936 | if (res) | ||
937 | goto exit_unreg_isa_driver; | ||
938 | } | ||
820 | 939 | ||
821 | return 0; | 940 | return 0; |
941 | |||
942 | exit_unreg_isa_driver: | ||
943 | platform_driver_unregister(&lm78_isa_driver); | ||
944 | exit_unreg_i2c_driver: | ||
945 | i2c_del_driver(&lm78_driver); | ||
946 | exit: | ||
947 | return res; | ||
822 | } | 948 | } |
823 | 949 | ||
824 | static void __exit sm_lm78_exit(void) | 950 | static void __exit sm_lm78_exit(void) |
825 | { | 951 | { |
826 | if (isa_address) | 952 | if (pdev) { |
827 | i2c_isa_del_driver(&lm78_isa_driver); | 953 | platform_device_unregister(pdev); |
954 | platform_driver_unregister(&lm78_isa_driver); | ||
955 | } | ||
828 | i2c_del_driver(&lm78_driver); | 956 | i2c_del_driver(&lm78_driver); |
829 | } | 957 | } |
830 | 958 | ||
diff --git a/drivers/hwmon/lm87.c b/drivers/hwmon/lm87.c index 3ce825489e34..988ae1c4aada 100644 --- a/drivers/hwmon/lm87.c +++ b/drivers/hwmon/lm87.c | |||
@@ -747,6 +747,7 @@ static int lm87_detect(struct i2c_adapter *adapter, int address, int kind) | |||
747 | } | 747 | } |
748 | 748 | ||
749 | if (!(data->channel & CHAN_NO_VID)) { | 749 | if (!(data->channel & CHAN_NO_VID)) { |
750 | data->vrm = vid_which_vrm(); | ||
750 | if ((err = device_create_file(&new_client->dev, | 751 | if ((err = device_create_file(&new_client->dev, |
751 | &dev_attr_cpu0_vid)) | 752 | &dev_attr_cpu0_vid)) |
752 | || (err = device_create_file(&new_client->dev, | 753 | || (err = device_create_file(&new_client->dev, |
@@ -779,7 +780,6 @@ static void lm87_init_client(struct i2c_client *client) | |||
779 | u8 config; | 780 | u8 config; |
780 | 781 | ||
781 | data->channel = lm87_read_value(client, LM87_REG_CHANNEL_MODE); | 782 | data->channel = lm87_read_value(client, LM87_REG_CHANNEL_MODE); |
782 | data->vrm = vid_which_vrm(); | ||
783 | 783 | ||
784 | config = lm87_read_value(client, LM87_REG_CONFIG); | 784 | config = lm87_read_value(client, LM87_REG_CONFIG); |
785 | if (!(config & 0x01)) { | 785 | if (!(config & 0x01)) { |
diff --git a/drivers/hwmon/max6650.c b/drivers/hwmon/max6650.c new file mode 100644 index 000000000000..8415664f33c2 --- /dev/null +++ b/drivers/hwmon/max6650.c | |||
@@ -0,0 +1,693 @@ | |||
1 | /* | ||
2 | * max6650.c - Part of lm_sensors, Linux kernel modules for hardware | ||
3 | * monitoring. | ||
4 | * | ||
5 | * (C) 2007 by Hans J. Koch <hjk@linutronix.de> | ||
6 | * | ||
7 | * based on code written by John Morris <john.morris@spirentcom.com> | ||
8 | * Copyright (c) 2003 Spirent Communications | ||
9 | * and Claus Gindhart <claus.gindhart@kontron.com> | ||
10 | * | ||
11 | * This module has only been tested with the MAX6650 chip. It should | ||
12 | * also work with the MAX6651. It does not distinguish max6650 and max6651 | ||
13 | * chips. | ||
14 | * | ||
15 | * Tha datasheet was last seen at: | ||
16 | * | ||
17 | * http://pdfserv.maxim-ic.com/en/ds/MAX6650-MAX6651.pdf | ||
18 | * | ||
19 | * This program is free software; you can redistribute it and/or modify | ||
20 | * it under the terms of the GNU General Public License as published by | ||
21 | * the Free Software Foundation; either version 2 of the License, or | ||
22 | * (at your option) any later version. | ||
23 | * | ||
24 | * This program is distributed in the hope that it will be useful, | ||
25 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
26 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
27 | * GNU General Public License for more details. | ||
28 | * | ||
29 | * You should have received a copy of the GNU General Public License | ||
30 | * along with this program; if not, write to the Free Software | ||
31 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
32 | */ | ||
33 | |||
34 | #include <linux/module.h> | ||
35 | #include <linux/init.h> | ||
36 | #include <linux/slab.h> | ||
37 | #include <linux/jiffies.h> | ||
38 | #include <linux/i2c.h> | ||
39 | #include <linux/hwmon.h> | ||
40 | #include <linux/hwmon-sysfs.h> | ||
41 | #include <linux/err.h> | ||
42 | |||
43 | /* | ||
44 | * Addresses to scan. There are four disjoint possibilities, by pin config. | ||
45 | */ | ||
46 | |||
47 | static unsigned short normal_i2c[] = {0x1b, 0x1f, 0x48, 0x4b, I2C_CLIENT_END}; | ||
48 | |||
49 | /* | ||
50 | * Insmod parameters | ||
51 | */ | ||
52 | |||
53 | /* fan_voltage: 5=5V fan, 12=12V fan, 0=don't change */ | ||
54 | static int fan_voltage; | ||
55 | /* prescaler: Possible values are 1, 2, 4, 8, 16 or 0 for don't change */ | ||
56 | static int prescaler; | ||
57 | /* clock: The clock frequency of the chip the driver should assume */ | ||
58 | static int clock = 254000; | ||
59 | |||
60 | module_param(fan_voltage, int, S_IRUGO); | ||
61 | module_param(prescaler, int, S_IRUGO); | ||
62 | module_param(clock, int, S_IRUGO); | ||
63 | |||
64 | I2C_CLIENT_INSMOD_1(max6650); | ||
65 | |||
66 | /* | ||
67 | * MAX 6650/6651 registers | ||
68 | */ | ||
69 | |||
70 | #define MAX6650_REG_SPEED 0x00 | ||
71 | #define MAX6650_REG_CONFIG 0x02 | ||
72 | #define MAX6650_REG_GPIO_DEF 0x04 | ||
73 | #define MAX6650_REG_DAC 0x06 | ||
74 | #define MAX6650_REG_ALARM_EN 0x08 | ||
75 | #define MAX6650_REG_ALARM 0x0A | ||
76 | #define MAX6650_REG_TACH0 0x0C | ||
77 | #define MAX6650_REG_TACH1 0x0E | ||
78 | #define MAX6650_REG_TACH2 0x10 | ||
79 | #define MAX6650_REG_TACH3 0x12 | ||
80 | #define MAX6650_REG_GPIO_STAT 0x14 | ||
81 | #define MAX6650_REG_COUNT 0x16 | ||
82 | |||
83 | /* | ||
84 | * Config register bits | ||
85 | */ | ||
86 | |||
87 | #define MAX6650_CFG_V12 0x08 | ||
88 | #define MAX6650_CFG_PRESCALER_MASK 0x07 | ||
89 | #define MAX6650_CFG_PRESCALER_2 0x01 | ||
90 | #define MAX6650_CFG_PRESCALER_4 0x02 | ||
91 | #define MAX6650_CFG_PRESCALER_8 0x03 | ||
92 | #define MAX6650_CFG_PRESCALER_16 0x04 | ||
93 | #define MAX6650_CFG_MODE_MASK 0x30 | ||
94 | #define MAX6650_CFG_MODE_ON 0x00 | ||
95 | #define MAX6650_CFG_MODE_OFF 0x10 | ||
96 | #define MAX6650_CFG_MODE_CLOSED_LOOP 0x20 | ||
97 | #define MAX6650_CFG_MODE_OPEN_LOOP 0x30 | ||
98 | #define MAX6650_COUNT_MASK 0x03 | ||
99 | |||
100 | /* Minimum and maximum values of the FAN-RPM */ | ||
101 | #define FAN_RPM_MIN 240 | ||
102 | #define FAN_RPM_MAX 30000 | ||
103 | |||
104 | #define DIV_FROM_REG(reg) (1 << (reg & 7)) | ||
105 | |||
106 | static int max6650_attach_adapter(struct i2c_adapter *adapter); | ||
107 | static int max6650_detect(struct i2c_adapter *adapter, int address, int kind); | ||
108 | static int max6650_init_client(struct i2c_client *client); | ||
109 | static int max6650_detach_client(struct i2c_client *client); | ||
110 | static struct max6650_data *max6650_update_device(struct device *dev); | ||
111 | |||
112 | /* | ||
113 | * Driver data (common to all clients) | ||
114 | */ | ||
115 | |||
116 | static struct i2c_driver max6650_driver = { | ||
117 | .driver = { | ||
118 | .name = "max6650", | ||
119 | }, | ||
120 | .attach_adapter = max6650_attach_adapter, | ||
121 | .detach_client = max6650_detach_client, | ||
122 | }; | ||
123 | |||
124 | /* | ||
125 | * Client data (each client gets its own) | ||
126 | */ | ||
127 | |||
128 | struct max6650_data | ||
129 | { | ||
130 | struct i2c_client client; | ||
131 | struct class_device *class_dev; | ||
132 | struct mutex update_lock; | ||
133 | char valid; /* zero until following fields are valid */ | ||
134 | unsigned long last_updated; /* in jiffies */ | ||
135 | |||
136 | /* register values */ | ||
137 | u8 speed; | ||
138 | u8 config; | ||
139 | u8 tach[4]; | ||
140 | u8 count; | ||
141 | u8 dac; | ||
142 | }; | ||
143 | |||
144 | static ssize_t get_fan(struct device *dev, struct device_attribute *devattr, | ||
145 | char *buf) | ||
146 | { | ||
147 | struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); | ||
148 | struct max6650_data *data = max6650_update_device(dev); | ||
149 | int rpm; | ||
150 | |||
151 | /* | ||
152 | * Calculation details: | ||
153 | * | ||
154 | * Each tachometer counts over an interval given by the "count" | ||
155 | * register (0.25, 0.5, 1 or 2 seconds). This module assumes | ||
156 | * that the fans produce two pulses per revolution (this seems | ||
157 | * to be the most common). | ||
158 | */ | ||
159 | |||
160 | rpm = ((data->tach[attr->index] * 120) / DIV_FROM_REG(data->count)); | ||
161 | return sprintf(buf, "%d\n", rpm); | ||
162 | } | ||
163 | |||
164 | /* | ||
165 | * Set the fan speed to the specified RPM (or read back the RPM setting). | ||
166 | * This works in closed loop mode only. Use pwm1 for open loop speed setting. | ||
167 | * | ||
168 | * The MAX6650/1 will automatically control fan speed when in closed loop | ||
169 | * mode. | ||
170 | * | ||
171 | * Assumptions: | ||
172 | * | ||
173 | * 1) The MAX6650/1 internal 254kHz clock frequency is set correctly. Use | ||
174 | * the clock module parameter if you need to fine tune this. | ||
175 | * | ||
176 | * 2) The prescaler (low three bits of the config register) has already | ||
177 | * been set to an appropriate value. Use the prescaler module parameter | ||
178 | * if your BIOS doesn't initialize the chip properly. | ||
179 | * | ||
180 | * The relevant equations are given on pages 21 and 22 of the datasheet. | ||
181 | * | ||
182 | * From the datasheet, the relevant equation when in regulation is: | ||
183 | * | ||
184 | * [fCLK / (128 x (KTACH + 1))] = 2 x FanSpeed / KSCALE | ||
185 | * | ||
186 | * where: | ||
187 | * | ||
188 | * fCLK is the oscillator frequency (either the 254kHz internal | ||
189 | * oscillator or the externally applied clock) | ||
190 | * | ||
191 | * KTACH is the value in the speed register | ||
192 | * | ||
193 | * FanSpeed is the speed of the fan in rps | ||
194 | * | ||
195 | * KSCALE is the prescaler value (1, 2, 4, 8, or 16) | ||
196 | * | ||
197 | * When reading, we need to solve for FanSpeed. When writing, we need to | ||
198 | * solve for KTACH. | ||
199 | * | ||
200 | * Note: this tachometer is completely separate from the tachometers | ||
201 | * used to measure the fan speeds. Only one fan's speed (fan1) is | ||
202 | * controlled. | ||
203 | */ | ||
204 | |||
205 | static ssize_t get_target(struct device *dev, struct device_attribute *devattr, | ||
206 | char *buf) | ||
207 | { | ||
208 | struct max6650_data *data = max6650_update_device(dev); | ||
209 | int kscale, ktach, rpm; | ||
210 | |||
211 | /* | ||
212 | * Use the datasheet equation: | ||
213 | * | ||
214 | * FanSpeed = KSCALE x fCLK / [256 x (KTACH + 1)] | ||
215 | * | ||
216 | * then multiply by 60 to give rpm. | ||
217 | */ | ||
218 | |||
219 | kscale = DIV_FROM_REG(data->config); | ||
220 | ktach = data->speed; | ||
221 | rpm = 60 * kscale * clock / (256 * (ktach + 1)); | ||
222 | return sprintf(buf, "%d\n", rpm); | ||
223 | } | ||
224 | |||
225 | static ssize_t set_target(struct device *dev, struct device_attribute *devattr, | ||
226 | const char *buf, size_t count) | ||
227 | { | ||
228 | struct i2c_client *client = to_i2c_client(dev); | ||
229 | struct max6650_data *data = i2c_get_clientdata(client); | ||
230 | int rpm = simple_strtoul(buf, NULL, 10); | ||
231 | int kscale, ktach; | ||
232 | |||
233 | rpm = SENSORS_LIMIT(rpm, FAN_RPM_MIN, FAN_RPM_MAX); | ||
234 | |||
235 | /* | ||
236 | * Divide the required speed by 60 to get from rpm to rps, then | ||
237 | * use the datasheet equation: | ||
238 | * | ||
239 | * KTACH = [(fCLK x KSCALE) / (256 x FanSpeed)] - 1 | ||
240 | */ | ||
241 | |||
242 | mutex_lock(&data->update_lock); | ||
243 | |||
244 | kscale = DIV_FROM_REG(data->config); | ||
245 | ktach = ((clock * kscale) / (256 * rpm / 60)) - 1; | ||
246 | if (ktach < 0) | ||
247 | ktach = 0; | ||
248 | if (ktach > 255) | ||
249 | ktach = 255; | ||
250 | data->speed = ktach; | ||
251 | |||
252 | i2c_smbus_write_byte_data(client, MAX6650_REG_SPEED, data->speed); | ||
253 | |||
254 | mutex_unlock(&data->update_lock); | ||
255 | |||
256 | return count; | ||
257 | } | ||
258 | |||
259 | /* | ||
260 | * Get/set the fan speed in open loop mode using pwm1 sysfs file. | ||
261 | * Speed is given as a relative value from 0 to 255, where 255 is maximum | ||
262 | * speed. Note that this is done by writing directly to the chip's DAC, | ||
263 | * it won't change the closed loop speed set by fan1_target. | ||
264 | * Also note that due to rounding errors it is possible that you don't read | ||
265 | * back exactly the value you have set. | ||
266 | */ | ||
267 | |||
268 | static ssize_t get_pwm(struct device *dev, struct device_attribute *devattr, | ||
269 | char *buf) | ||
270 | { | ||
271 | int pwm; | ||
272 | struct max6650_data *data = max6650_update_device(dev); | ||
273 | |||
274 | /* Useful range for dac is 0-180 for 12V fans and 0-76 for 5V fans. | ||
275 | Lower DAC values mean higher speeds. */ | ||
276 | if (data->config & MAX6650_CFG_V12) | ||
277 | pwm = 255 - (255 * (int)data->dac)/180; | ||
278 | else | ||
279 | pwm = 255 - (255 * (int)data->dac)/76; | ||
280 | |||
281 | if (pwm < 0) | ||
282 | pwm = 0; | ||
283 | |||
284 | return sprintf(buf, "%d\n", pwm); | ||
285 | } | ||
286 | |||
287 | static ssize_t set_pwm(struct device *dev, struct device_attribute *devattr, | ||
288 | const char *buf, size_t count) | ||
289 | { | ||
290 | struct i2c_client *client = to_i2c_client(dev); | ||
291 | struct max6650_data *data = i2c_get_clientdata(client); | ||
292 | int pwm = simple_strtoul(buf, NULL, 10); | ||
293 | |||
294 | pwm = SENSORS_LIMIT(pwm, 0, 255); | ||
295 | |||
296 | mutex_lock(&data->update_lock); | ||
297 | |||
298 | if (data->config & MAX6650_CFG_V12) | ||
299 | data->dac = 180 - (180 * pwm)/255; | ||
300 | else | ||
301 | data->dac = 76 - (76 * pwm)/255; | ||
302 | |||
303 | i2c_smbus_write_byte_data(client, MAX6650_REG_DAC, data->dac); | ||
304 | |||
305 | mutex_unlock(&data->update_lock); | ||
306 | |||
307 | return count; | ||
308 | } | ||
309 | |||
310 | /* | ||
311 | * Get/Set controller mode: | ||
312 | * Possible values: | ||
313 | * 0 = Fan always on | ||
314 | * 1 = Open loop, Voltage is set according to speed, not regulated. | ||
315 | * 2 = Closed loop, RPM for all fans regulated by fan1 tachometer | ||
316 | */ | ||
317 | |||
318 | static ssize_t get_enable(struct device *dev, struct device_attribute *devattr, | ||
319 | char *buf) | ||
320 | { | ||
321 | struct max6650_data *data = max6650_update_device(dev); | ||
322 | int mode = (data->config & MAX6650_CFG_MODE_MASK) >> 4; | ||
323 | int sysfs_modes[4] = {0, 1, 2, 1}; | ||
324 | |||
325 | return sprintf(buf, "%d\n", sysfs_modes[mode]); | ||
326 | } | ||
327 | |||
328 | static ssize_t set_enable(struct device *dev, struct device_attribute *devattr, | ||
329 | const char *buf, size_t count) | ||
330 | { | ||
331 | struct i2c_client *client = to_i2c_client(dev); | ||
332 | struct max6650_data *data = i2c_get_clientdata(client); | ||
333 | int mode = simple_strtoul(buf, NULL, 10); | ||
334 | int max6650_modes[3] = {0, 3, 2}; | ||
335 | |||
336 | if ((mode < 0)||(mode > 2)) { | ||
337 | dev_err(&client->dev, | ||
338 | "illegal value for pwm1_enable (%d)\n", mode); | ||
339 | return -EINVAL; | ||
340 | } | ||
341 | |||
342 | mutex_lock(&data->update_lock); | ||
343 | |||
344 | data->config = i2c_smbus_read_byte_data(client, MAX6650_REG_CONFIG); | ||
345 | data->config = (data->config & ~MAX6650_CFG_MODE_MASK) | ||
346 | | (max6650_modes[mode] << 4); | ||
347 | |||
348 | i2c_smbus_write_byte_data(client, MAX6650_REG_CONFIG, data->config); | ||
349 | |||
350 | mutex_unlock(&data->update_lock); | ||
351 | |||
352 | return count; | ||
353 | } | ||
354 | |||
355 | /* | ||
356 | * Read/write functions for fan1_div sysfs file. The MAX6650 has no such | ||
357 | * divider. We handle this by converting between divider and counttime: | ||
358 | * | ||
359 | * (counttime == k) <==> (divider == 2^k), k = 0, 1, 2, or 3 | ||
360 | * | ||
361 | * Lower values of k allow to connect a faster fan without the risk of | ||
362 | * counter overflow. The price is lower resolution. You can also set counttime | ||
363 | * using the module parameter. Note that the module parameter "prescaler" also | ||
364 | * influences the behaviour. Unfortunately, there's no sysfs attribute | ||
365 | * defined for that. See the data sheet for details. | ||
366 | */ | ||
367 | |||
368 | static ssize_t get_div(struct device *dev, struct device_attribute *devattr, | ||
369 | char *buf) | ||
370 | { | ||
371 | struct max6650_data *data = max6650_update_device(dev); | ||
372 | |||
373 | return sprintf(buf, "%d\n", DIV_FROM_REG(data->count)); | ||
374 | } | ||
375 | |||
376 | static ssize_t set_div(struct device *dev, struct device_attribute *devattr, | ||
377 | const char *buf, size_t count) | ||
378 | { | ||
379 | struct i2c_client *client = to_i2c_client(dev); | ||
380 | struct max6650_data *data = i2c_get_clientdata(client); | ||
381 | int div = simple_strtoul(buf, NULL, 10); | ||
382 | |||
383 | mutex_lock(&data->update_lock); | ||
384 | switch (div) { | ||
385 | case 1: | ||
386 | data->count = 0; | ||
387 | break; | ||
388 | case 2: | ||
389 | data->count = 1; | ||
390 | break; | ||
391 | case 4: | ||
392 | data->count = 2; | ||
393 | break; | ||
394 | case 8: | ||
395 | data->count = 3; | ||
396 | break; | ||
397 | default: | ||
398 | dev_err(&client->dev, | ||
399 | "illegal value for fan divider (%d)\n", div); | ||
400 | return -EINVAL; | ||
401 | } | ||
402 | |||
403 | i2c_smbus_write_byte_data(client, MAX6650_REG_COUNT, data->count); | ||
404 | mutex_unlock(&data->update_lock); | ||
405 | |||
406 | return count; | ||
407 | } | ||
408 | |||
409 | static SENSOR_DEVICE_ATTR(fan1_input, S_IRUGO, get_fan, NULL, 0); | ||
410 | static SENSOR_DEVICE_ATTR(fan2_input, S_IRUGO, get_fan, NULL, 1); | ||
411 | static SENSOR_DEVICE_ATTR(fan3_input, S_IRUGO, get_fan, NULL, 2); | ||
412 | static SENSOR_DEVICE_ATTR(fan4_input, S_IRUGO, get_fan, NULL, 3); | ||
413 | static DEVICE_ATTR(fan1_target, S_IWUSR | S_IRUGO, get_target, set_target); | ||
414 | static DEVICE_ATTR(fan1_div, S_IWUSR | S_IRUGO, get_div, set_div); | ||
415 | static DEVICE_ATTR(pwm1_enable, S_IWUSR | S_IRUGO, get_enable, set_enable); | ||
416 | static DEVICE_ATTR(pwm1, S_IWUSR | S_IRUGO, get_pwm, set_pwm); | ||
417 | |||
418 | |||
419 | static struct attribute *max6650_attrs[] = { | ||
420 | &sensor_dev_attr_fan1_input.dev_attr.attr, | ||
421 | &sensor_dev_attr_fan2_input.dev_attr.attr, | ||
422 | &sensor_dev_attr_fan3_input.dev_attr.attr, | ||
423 | &sensor_dev_attr_fan4_input.dev_attr.attr, | ||
424 | &dev_attr_fan1_target.attr, | ||
425 | &dev_attr_fan1_div.attr, | ||
426 | &dev_attr_pwm1_enable.attr, | ||
427 | &dev_attr_pwm1.attr, | ||
428 | NULL | ||
429 | }; | ||
430 | |||
431 | static struct attribute_group max6650_attr_grp = { | ||
432 | .attrs = max6650_attrs, | ||
433 | }; | ||
434 | |||
435 | /* | ||
436 | * Real code | ||
437 | */ | ||
438 | |||
439 | static int max6650_attach_adapter(struct i2c_adapter *adapter) | ||
440 | { | ||
441 | if (!(adapter->class & I2C_CLASS_HWMON)) { | ||
442 | dev_dbg(&adapter->dev, | ||
443 | "FATAL: max6650_attach_adapter class HWMON not set\n"); | ||
444 | return 0; | ||
445 | } | ||
446 | |||
447 | return i2c_probe(adapter, &addr_data, max6650_detect); | ||
448 | } | ||
449 | |||
450 | /* | ||
451 | * The following function does more than just detection. If detection | ||
452 | * succeeds, it also registers the new chip. | ||
453 | */ | ||
454 | |||
455 | static int max6650_detect(struct i2c_adapter *adapter, int address, int kind) | ||
456 | { | ||
457 | struct i2c_client *client; | ||
458 | struct max6650_data *data; | ||
459 | int err = -ENODEV; | ||
460 | |||
461 | dev_dbg(&adapter->dev, "max6650_detect called, kind = %d\n", kind); | ||
462 | |||
463 | if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA)) { | ||
464 | dev_dbg(&adapter->dev, "max6650: I2C bus doesn't support " | ||
465 | "byte read mode, skipping.\n"); | ||
466 | return 0; | ||
467 | } | ||
468 | |||
469 | if (!(data = kzalloc(sizeof(struct max6650_data), GFP_KERNEL))) { | ||
470 | dev_err(&adapter->dev, "max6650: out of memory.\n"); | ||
471 | return -ENOMEM; | ||
472 | } | ||
473 | |||
474 | client = &data->client; | ||
475 | i2c_set_clientdata(client, data); | ||
476 | client->addr = address; | ||
477 | client->adapter = adapter; | ||
478 | client->driver = &max6650_driver; | ||
479 | |||
480 | /* | ||
481 | * Now we do the remaining detection. A negative kind means that | ||
482 | * the driver was loaded with no force parameter (default), so we | ||
483 | * must both detect and identify the chip (actually there is only | ||
484 | * one possible kind of chip for now, max6650). A zero kind means that | ||
485 | * the driver was loaded with the force parameter, the detection | ||
486 | * step shall be skipped. A positive kind means that the driver | ||
487 | * was loaded with the force parameter and a given kind of chip is | ||
488 | * requested, so both the detection and the identification steps | ||
489 | * are skipped. | ||
490 | * | ||
491 | * Currently I can find no way to distinguish between a MAX6650 and | ||
492 | * a MAX6651. This driver has only been tried on the former. | ||
493 | */ | ||
494 | |||
495 | if ((kind < 0) && | ||
496 | ( (i2c_smbus_read_byte_data(client, MAX6650_REG_CONFIG) & 0xC0) | ||
497 | ||(i2c_smbus_read_byte_data(client, MAX6650_REG_GPIO_STAT) & 0xE0) | ||
498 | ||(i2c_smbus_read_byte_data(client, MAX6650_REG_ALARM_EN) & 0xE0) | ||
499 | ||(i2c_smbus_read_byte_data(client, MAX6650_REG_ALARM) & 0xE0) | ||
500 | ||(i2c_smbus_read_byte_data(client, MAX6650_REG_COUNT) & 0xFC))) { | ||
501 | dev_dbg(&adapter->dev, | ||
502 | "max6650: detection failed at 0x%02x.\n", address); | ||
503 | goto err_free; | ||
504 | } | ||
505 | |||
506 | dev_info(&adapter->dev, "max6650: chip found at 0x%02x.\n", address); | ||
507 | |||
508 | strlcpy(client->name, "max6650", I2C_NAME_SIZE); | ||
509 | mutex_init(&data->update_lock); | ||
510 | |||
511 | if ((err = i2c_attach_client(client))) { | ||
512 | dev_err(&adapter->dev, "max6650: failed to attach client.\n"); | ||
513 | goto err_free; | ||
514 | } | ||
515 | |||
516 | /* | ||
517 | * Initialize the max6650 chip | ||
518 | */ | ||
519 | if (max6650_init_client(client)) | ||
520 | goto err_detach; | ||
521 | |||
522 | err = sysfs_create_group(&client->dev.kobj, &max6650_attr_grp); | ||
523 | if (err) | ||
524 | goto err_detach; | ||
525 | |||
526 | data->class_dev = hwmon_device_register(&client->dev); | ||
527 | if (!IS_ERR(data->class_dev)) | ||
528 | return 0; | ||
529 | |||
530 | err = PTR_ERR(data->class_dev); | ||
531 | dev_err(&client->dev, "error registering hwmon device.\n"); | ||
532 | sysfs_remove_group(&client->dev.kobj, &max6650_attr_grp); | ||
533 | err_detach: | ||
534 | i2c_detach_client(client); | ||
535 | err_free: | ||
536 | kfree(data); | ||
537 | return err; | ||
538 | } | ||
539 | |||
540 | static int max6650_detach_client(struct i2c_client *client) | ||
541 | { | ||
542 | struct max6650_data *data = i2c_get_clientdata(client); | ||
543 | int err; | ||
544 | |||
545 | sysfs_remove_group(&client->dev.kobj, &max6650_attr_grp); | ||
546 | hwmon_device_unregister(data->class_dev); | ||
547 | err = i2c_detach_client(client); | ||
548 | if (!err) | ||
549 | kfree(data); | ||
550 | return err; | ||
551 | } | ||
552 | |||
553 | static int max6650_init_client(struct i2c_client *client) | ||
554 | { | ||
555 | struct max6650_data *data = i2c_get_clientdata(client); | ||
556 | int config; | ||
557 | int err = -EIO; | ||
558 | |||
559 | config = i2c_smbus_read_byte_data(client, MAX6650_REG_CONFIG); | ||
560 | |||
561 | if (config < 0) { | ||
562 | dev_err(&client->dev, "Error reading config, aborting.\n"); | ||
563 | return err; | ||
564 | } | ||
565 | |||
566 | switch (fan_voltage) { | ||
567 | case 0: | ||
568 | break; | ||
569 | case 5: | ||
570 | config &= ~MAX6650_CFG_V12; | ||
571 | break; | ||
572 | case 12: | ||
573 | config |= MAX6650_CFG_V12; | ||
574 | break; | ||
575 | default: | ||
576 | dev_err(&client->dev, | ||
577 | "illegal value for fan_voltage (%d)\n", | ||
578 | fan_voltage); | ||
579 | } | ||
580 | |||
581 | dev_info(&client->dev, "Fan voltage is set to %dV.\n", | ||
582 | (config & MAX6650_CFG_V12) ? 12 : 5); | ||
583 | |||
584 | switch (prescaler) { | ||
585 | case 0: | ||
586 | break; | ||
587 | case 1: | ||
588 | config &= ~MAX6650_CFG_PRESCALER_MASK; | ||
589 | break; | ||
590 | case 2: | ||
591 | config = (config & ~MAX6650_CFG_PRESCALER_MASK) | ||
592 | | MAX6650_CFG_PRESCALER_2; | ||
593 | break; | ||
594 | case 4: | ||
595 | config = (config & ~MAX6650_CFG_PRESCALER_MASK) | ||
596 | | MAX6650_CFG_PRESCALER_4; | ||
597 | break; | ||
598 | case 8: | ||
599 | config = (config & ~MAX6650_CFG_PRESCALER_MASK) | ||
600 | | MAX6650_CFG_PRESCALER_8; | ||
601 | break; | ||
602 | case 16: | ||
603 | config = (config & ~MAX6650_CFG_PRESCALER_MASK) | ||
604 | | MAX6650_CFG_PRESCALER_16; | ||
605 | break; | ||
606 | default: | ||
607 | dev_err(&client->dev, | ||
608 | "illegal value for prescaler (%d)\n", | ||
609 | prescaler); | ||
610 | } | ||
611 | |||
612 | dev_info(&client->dev, "Prescaler is set to %d.\n", | ||
613 | 1 << (config & MAX6650_CFG_PRESCALER_MASK)); | ||
614 | |||
615 | /* If mode is set to "full off", we change it to "open loop" and | ||
616 | * set DAC to 255, which has the same effect. We do this because | ||
617 | * there's no "full off" mode defined in hwmon specifcations. | ||
618 | */ | ||
619 | |||
620 | if ((config & MAX6650_CFG_MODE_MASK) == MAX6650_CFG_MODE_OFF) { | ||
621 | dev_dbg(&client->dev, "Change mode to open loop, full off.\n"); | ||
622 | config = (config & ~MAX6650_CFG_MODE_MASK) | ||
623 | | MAX6650_CFG_MODE_OPEN_LOOP; | ||
624 | if (i2c_smbus_write_byte_data(client, MAX6650_REG_DAC, 255)) { | ||
625 | dev_err(&client->dev, "DAC write error, aborting.\n"); | ||
626 | return err; | ||
627 | } | ||
628 | } | ||
629 | |||
630 | if (i2c_smbus_write_byte_data(client, MAX6650_REG_CONFIG, config)) { | ||
631 | dev_err(&client->dev, "Config write error, aborting.\n"); | ||
632 | return err; | ||
633 | } | ||
634 | |||
635 | data->config = config; | ||
636 | data->count = i2c_smbus_read_byte_data(client, MAX6650_REG_COUNT); | ||
637 | |||
638 | return 0; | ||
639 | } | ||
640 | |||
641 | static const u8 tach_reg[] = { | ||
642 | MAX6650_REG_TACH0, | ||
643 | MAX6650_REG_TACH1, | ||
644 | MAX6650_REG_TACH2, | ||
645 | MAX6650_REG_TACH3, | ||
646 | }; | ||
647 | |||
648 | static struct max6650_data *max6650_update_device(struct device *dev) | ||
649 | { | ||
650 | int i; | ||
651 | struct i2c_client *client = to_i2c_client(dev); | ||
652 | struct max6650_data *data = i2c_get_clientdata(client); | ||
653 | |||
654 | mutex_lock(&data->update_lock); | ||
655 | |||
656 | if (time_after(jiffies, data->last_updated + HZ) || !data->valid) { | ||
657 | data->speed = i2c_smbus_read_byte_data(client, | ||
658 | MAX6650_REG_SPEED); | ||
659 | data->config = i2c_smbus_read_byte_data(client, | ||
660 | MAX6650_REG_CONFIG); | ||
661 | for (i = 0; i < 4; i++) { | ||
662 | data->tach[i] = i2c_smbus_read_byte_data(client, | ||
663 | tach_reg[i]); | ||
664 | } | ||
665 | data->count = i2c_smbus_read_byte_data(client, | ||
666 | MAX6650_REG_COUNT); | ||
667 | data->dac = i2c_smbus_read_byte_data(client, MAX6650_REG_DAC); | ||
668 | |||
669 | data->last_updated = jiffies; | ||
670 | data->valid = 1; | ||
671 | } | ||
672 | |||
673 | mutex_unlock(&data->update_lock); | ||
674 | |||
675 | return data; | ||
676 | } | ||
677 | |||
678 | static int __init sensors_max6650_init(void) | ||
679 | { | ||
680 | return i2c_add_driver(&max6650_driver); | ||
681 | } | ||
682 | |||
683 | static void __exit sensors_max6650_exit(void) | ||
684 | { | ||
685 | i2c_del_driver(&max6650_driver); | ||
686 | } | ||
687 | |||
688 | MODULE_AUTHOR("Hans J. Koch"); | ||
689 | MODULE_DESCRIPTION("MAX6650 sensor driver"); | ||
690 | MODULE_LICENSE("GPL"); | ||
691 | |||
692 | module_init(sensors_max6650_init); | ||
693 | module_exit(sensors_max6650_exit); | ||
diff --git a/drivers/hwmon/pc87427.c b/drivers/hwmon/pc87427.c index affa21a5ccfd..29354fa26f81 100644 --- a/drivers/hwmon/pc87427.c +++ b/drivers/hwmon/pc87427.c | |||
@@ -31,6 +31,7 @@ | |||
31 | #include <linux/err.h> | 31 | #include <linux/err.h> |
32 | #include <linux/mutex.h> | 32 | #include <linux/mutex.h> |
33 | #include <linux/sysfs.h> | 33 | #include <linux/sysfs.h> |
34 | #include <linux/ioport.h> | ||
34 | #include <asm/io.h> | 35 | #include <asm/io.h> |
35 | 36 | ||
36 | static struct platform_device *pdev; | 37 | static struct platform_device *pdev; |
@@ -429,6 +430,12 @@ static int __devinit pc87427_probe(struct platform_device *pdev) | |||
429 | /* This will need to be revisited when we add support for | 430 | /* This will need to be revisited when we add support for |
430 | temperature and voltage monitoring. */ | 431 | temperature and voltage monitoring. */ |
431 | res = platform_get_resource(pdev, IORESOURCE_IO, 0); | 432 | res = platform_get_resource(pdev, IORESOURCE_IO, 0); |
433 | if (!request_region(res->start, res->end - res->start + 1, DRVNAME)) { | ||
434 | err = -EBUSY; | ||
435 | dev_err(&pdev->dev, "Failed to request region 0x%lx-0x%lx\n", | ||
436 | (unsigned long)res->start, (unsigned long)res->end); | ||
437 | goto exit_kfree; | ||
438 | } | ||
432 | data->address[0] = res->start; | 439 | data->address[0] = res->start; |
433 | 440 | ||
434 | mutex_init(&data->lock); | 441 | mutex_init(&data->lock); |
@@ -438,7 +445,7 @@ static int __devinit pc87427_probe(struct platform_device *pdev) | |||
438 | 445 | ||
439 | /* Register sysfs hooks */ | 446 | /* Register sysfs hooks */ |
440 | if ((err = device_create_file(&pdev->dev, &dev_attr_name))) | 447 | if ((err = device_create_file(&pdev->dev, &dev_attr_name))) |
441 | goto exit_kfree; | 448 | goto exit_release_region; |
442 | for (i = 0; i < 8; i++) { | 449 | for (i = 0; i < 8; i++) { |
443 | if (!(data->fan_enabled & (1 << i))) | 450 | if (!(data->fan_enabled & (1 << i))) |
444 | continue; | 451 | continue; |
@@ -462,6 +469,8 @@ exit_remove_files: | |||
462 | continue; | 469 | continue; |
463 | sysfs_remove_group(&pdev->dev.kobj, &pc87427_group_fan[i]); | 470 | sysfs_remove_group(&pdev->dev.kobj, &pc87427_group_fan[i]); |
464 | } | 471 | } |
472 | exit_release_region: | ||
473 | release_region(res->start, res->end - res->start + 1); | ||
465 | exit_kfree: | 474 | exit_kfree: |
466 | platform_set_drvdata(pdev, NULL); | 475 | platform_set_drvdata(pdev, NULL); |
467 | kfree(data); | 476 | kfree(data); |
@@ -472,6 +481,7 @@ exit: | |||
472 | static int __devexit pc87427_remove(struct platform_device *pdev) | 481 | static int __devexit pc87427_remove(struct platform_device *pdev) |
473 | { | 482 | { |
474 | struct pc87427_data *data = platform_get_drvdata(pdev); | 483 | struct pc87427_data *data = platform_get_drvdata(pdev); |
484 | struct resource *res; | ||
475 | int i; | 485 | int i; |
476 | 486 | ||
477 | platform_set_drvdata(pdev, NULL); | 487 | platform_set_drvdata(pdev, NULL); |
@@ -484,6 +494,9 @@ static int __devexit pc87427_remove(struct platform_device *pdev) | |||
484 | } | 494 | } |
485 | kfree(data); | 495 | kfree(data); |
486 | 496 | ||
497 | res = platform_get_resource(pdev, IORESOURCE_IO, 0); | ||
498 | release_region(res->start, res->end - res->start + 1); | ||
499 | |||
487 | return 0; | 500 | return 0; |
488 | } | 501 | } |
489 | 502 | ||
diff --git a/drivers/hwmon/smsc47b397.c b/drivers/hwmon/smsc47b397.c index 72b0e2d8650c..943abbd95ab5 100644 --- a/drivers/hwmon/smsc47b397.c +++ b/drivers/hwmon/smsc47b397.c | |||
@@ -30,16 +30,17 @@ | |||
30 | #include <linux/slab.h> | 30 | #include <linux/slab.h> |
31 | #include <linux/ioport.h> | 31 | #include <linux/ioport.h> |
32 | #include <linux/jiffies.h> | 32 | #include <linux/jiffies.h> |
33 | #include <linux/i2c.h> | 33 | #include <linux/platform_device.h> |
34 | #include <linux/i2c-isa.h> | ||
35 | #include <linux/hwmon.h> | 34 | #include <linux/hwmon.h> |
35 | #include <linux/hwmon-sysfs.h> | ||
36 | #include <linux/err.h> | 36 | #include <linux/err.h> |
37 | #include <linux/init.h> | 37 | #include <linux/init.h> |
38 | #include <linux/mutex.h> | 38 | #include <linux/mutex.h> |
39 | #include <asm/io.h> | 39 | #include <asm/io.h> |
40 | 40 | ||
41 | /* Address is autodetected, there is no default value */ | 41 | static struct platform_device *pdev; |
42 | static unsigned short address; | 42 | |
43 | #define DRVNAME "smsc47b397" | ||
43 | 44 | ||
44 | /* Super-I/0 registers and commands */ | 45 | /* Super-I/0 registers and commands */ |
45 | 46 | ||
@@ -91,7 +92,8 @@ static u8 smsc47b397_reg_temp[] = {0x25, 0x26, 0x27, 0x80}; | |||
91 | #define SMSC47B397_REG_FAN_MSB(nr) (0x29 + 2 * (nr)) | 92 | #define SMSC47B397_REG_FAN_MSB(nr) (0x29 + 2 * (nr)) |
92 | 93 | ||
93 | struct smsc47b397_data { | 94 | struct smsc47b397_data { |
94 | struct i2c_client client; | 95 | unsigned short addr; |
96 | const char *name; | ||
95 | struct class_device *class_dev; | 97 | struct class_device *class_dev; |
96 | struct mutex lock; | 98 | struct mutex lock; |
97 | 99 | ||
@@ -104,45 +106,43 @@ struct smsc47b397_data { | |||
104 | u8 temp[4]; | 106 | u8 temp[4]; |
105 | }; | 107 | }; |
106 | 108 | ||
107 | static int smsc47b397_read_value(struct i2c_client *client, u8 reg) | 109 | static int smsc47b397_read_value(struct smsc47b397_data* data, u8 reg) |
108 | { | 110 | { |
109 | struct smsc47b397_data *data = i2c_get_clientdata(client); | ||
110 | int res; | 111 | int res; |
111 | 112 | ||
112 | mutex_lock(&data->lock); | 113 | mutex_lock(&data->lock); |
113 | outb(reg, client->addr); | 114 | outb(reg, data->addr); |
114 | res = inb_p(client->addr + 1); | 115 | res = inb_p(data->addr + 1); |
115 | mutex_unlock(&data->lock); | 116 | mutex_unlock(&data->lock); |
116 | return res; | 117 | return res; |
117 | } | 118 | } |
118 | 119 | ||
119 | static struct smsc47b397_data *smsc47b397_update_device(struct device *dev) | 120 | static struct smsc47b397_data *smsc47b397_update_device(struct device *dev) |
120 | { | 121 | { |
121 | struct i2c_client *client = to_i2c_client(dev); | 122 | struct smsc47b397_data *data = dev_get_drvdata(dev); |
122 | struct smsc47b397_data *data = i2c_get_clientdata(client); | ||
123 | int i; | 123 | int i; |
124 | 124 | ||
125 | mutex_lock(&data->update_lock); | 125 | mutex_lock(&data->update_lock); |
126 | 126 | ||
127 | if (time_after(jiffies, data->last_updated + HZ) || !data->valid) { | 127 | if (time_after(jiffies, data->last_updated + HZ) || !data->valid) { |
128 | dev_dbg(&client->dev, "starting device update...\n"); | 128 | dev_dbg(dev, "starting device update...\n"); |
129 | 129 | ||
130 | /* 4 temperature inputs, 4 fan inputs */ | 130 | /* 4 temperature inputs, 4 fan inputs */ |
131 | for (i = 0; i < 4; i++) { | 131 | for (i = 0; i < 4; i++) { |
132 | data->temp[i] = smsc47b397_read_value(client, | 132 | data->temp[i] = smsc47b397_read_value(data, |
133 | SMSC47B397_REG_TEMP(i)); | 133 | SMSC47B397_REG_TEMP(i)); |
134 | 134 | ||
135 | /* must read LSB first */ | 135 | /* must read LSB first */ |
136 | data->fan[i] = smsc47b397_read_value(client, | 136 | data->fan[i] = smsc47b397_read_value(data, |
137 | SMSC47B397_REG_FAN_LSB(i)); | 137 | SMSC47B397_REG_FAN_LSB(i)); |
138 | data->fan[i] |= smsc47b397_read_value(client, | 138 | data->fan[i] |= smsc47b397_read_value(data, |
139 | SMSC47B397_REG_FAN_MSB(i)) << 8; | 139 | SMSC47B397_REG_FAN_MSB(i)) << 8; |
140 | } | 140 | } |
141 | 141 | ||
142 | data->last_updated = jiffies; | 142 | data->last_updated = jiffies; |
143 | data->valid = 1; | 143 | data->valid = 1; |
144 | 144 | ||
145 | dev_dbg(&client->dev, "... device update complete\n"); | 145 | dev_dbg(dev, "... device update complete\n"); |
146 | } | 146 | } |
147 | 147 | ||
148 | mutex_unlock(&data->update_lock); | 148 | mutex_unlock(&data->update_lock); |
@@ -157,24 +157,18 @@ static int temp_from_reg(u8 reg) | |||
157 | return (s8)reg * 1000; | 157 | return (s8)reg * 1000; |
158 | } | 158 | } |
159 | 159 | ||
160 | /* 0 <= nr <= 3 */ | 160 | static ssize_t show_temp(struct device *dev, struct device_attribute |
161 | static ssize_t show_temp(struct device *dev, char *buf, int nr) | 161 | *devattr, char *buf) |
162 | { | 162 | { |
163 | struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); | ||
163 | struct smsc47b397_data *data = smsc47b397_update_device(dev); | 164 | struct smsc47b397_data *data = smsc47b397_update_device(dev); |
164 | return sprintf(buf, "%d\n", temp_from_reg(data->temp[nr])); | 165 | return sprintf(buf, "%d\n", temp_from_reg(data->temp[attr->index])); |
165 | } | 166 | } |
166 | 167 | ||
167 | #define sysfs_temp(num) \ | 168 | static SENSOR_DEVICE_ATTR(temp1_input, S_IRUGO, show_temp, NULL, 0); |
168 | static ssize_t show_temp##num(struct device *dev, struct device_attribute *attr, char *buf) \ | 169 | static SENSOR_DEVICE_ATTR(temp2_input, S_IRUGO, show_temp, NULL, 1); |
169 | { \ | 170 | static SENSOR_DEVICE_ATTR(temp3_input, S_IRUGO, show_temp, NULL, 2); |
170 | return show_temp(dev, buf, num-1); \ | 171 | static SENSOR_DEVICE_ATTR(temp4_input, S_IRUGO, show_temp, NULL, 3); |
171 | } \ | ||
172 | static DEVICE_ATTR(temp##num##_input, S_IRUGO, show_temp##num, NULL) | ||
173 | |||
174 | sysfs_temp(1); | ||
175 | sysfs_temp(2); | ||
176 | sysfs_temp(3); | ||
177 | sysfs_temp(4); | ||
178 | 172 | ||
179 | /* FAN: 1 RPM/bit | 173 | /* FAN: 1 RPM/bit |
180 | REG: count of 90kHz pulses / revolution */ | 174 | REG: count of 90kHz pulses / revolution */ |
@@ -183,35 +177,37 @@ static int fan_from_reg(u16 reg) | |||
183 | return 90000 * 60 / reg; | 177 | return 90000 * 60 / reg; |
184 | } | 178 | } |
185 | 179 | ||
186 | /* 0 <= nr <= 3 */ | 180 | static ssize_t show_fan(struct device *dev, struct device_attribute |
187 | static ssize_t show_fan(struct device *dev, char *buf, int nr) | 181 | *devattr, char *buf) |
188 | { | 182 | { |
189 | struct smsc47b397_data *data = smsc47b397_update_device(dev); | 183 | struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); |
190 | return sprintf(buf, "%d\n", fan_from_reg(data->fan[nr])); | 184 | struct smsc47b397_data *data = smsc47b397_update_device(dev); |
185 | return sprintf(buf, "%d\n", fan_from_reg(data->fan[attr->index])); | ||
191 | } | 186 | } |
187 | static SENSOR_DEVICE_ATTR(fan1_input, S_IRUGO, show_fan, NULL, 0); | ||
188 | static SENSOR_DEVICE_ATTR(fan2_input, S_IRUGO, show_fan, NULL, 1); | ||
189 | static SENSOR_DEVICE_ATTR(fan3_input, S_IRUGO, show_fan, NULL, 2); | ||
190 | static SENSOR_DEVICE_ATTR(fan4_input, S_IRUGO, show_fan, NULL, 3); | ||
192 | 191 | ||
193 | #define sysfs_fan(num) \ | 192 | static ssize_t show_name(struct device *dev, struct device_attribute |
194 | static ssize_t show_fan##num(struct device *dev, struct device_attribute *attr, char *buf) \ | 193 | *devattr, char *buf) |
195 | { \ | 194 | { |
196 | return show_fan(dev, buf, num-1); \ | 195 | struct smsc47b397_data *data = dev_get_drvdata(dev); |
197 | } \ | 196 | return sprintf(buf, "%s\n", data->name); |
198 | static DEVICE_ATTR(fan##num##_input, S_IRUGO, show_fan##num, NULL) | 197 | } |
199 | 198 | static DEVICE_ATTR(name, S_IRUGO, show_name, NULL); | |
200 | sysfs_fan(1); | ||
201 | sysfs_fan(2); | ||
202 | sysfs_fan(3); | ||
203 | sysfs_fan(4); | ||
204 | 199 | ||
205 | static struct attribute *smsc47b397_attributes[] = { | 200 | static struct attribute *smsc47b397_attributes[] = { |
206 | &dev_attr_temp1_input.attr, | 201 | &sensor_dev_attr_temp1_input.dev_attr.attr, |
207 | &dev_attr_temp2_input.attr, | 202 | &sensor_dev_attr_temp2_input.dev_attr.attr, |
208 | &dev_attr_temp3_input.attr, | 203 | &sensor_dev_attr_temp3_input.dev_attr.attr, |
209 | &dev_attr_temp4_input.attr, | 204 | &sensor_dev_attr_temp4_input.dev_attr.attr, |
210 | &dev_attr_fan1_input.attr, | 205 | &sensor_dev_attr_fan1_input.dev_attr.attr, |
211 | &dev_attr_fan2_input.attr, | 206 | &sensor_dev_attr_fan2_input.dev_attr.attr, |
212 | &dev_attr_fan3_input.attr, | 207 | &sensor_dev_attr_fan3_input.dev_attr.attr, |
213 | &dev_attr_fan4_input.attr, | 208 | &sensor_dev_attr_fan4_input.dev_attr.attr, |
214 | 209 | ||
210 | &dev_attr_name.attr, | ||
215 | NULL | 211 | NULL |
216 | }; | 212 | }; |
217 | 213 | ||
@@ -219,44 +215,44 @@ static const struct attribute_group smsc47b397_group = { | |||
219 | .attrs = smsc47b397_attributes, | 215 | .attrs = smsc47b397_attributes, |
220 | }; | 216 | }; |
221 | 217 | ||
222 | static int smsc47b397_detach_client(struct i2c_client *client) | 218 | static int __devexit smsc47b397_remove(struct platform_device *pdev) |
223 | { | 219 | { |
224 | struct smsc47b397_data *data = i2c_get_clientdata(client); | 220 | struct smsc47b397_data *data = platform_get_drvdata(pdev); |
225 | int err; | 221 | struct resource *res; |
226 | 222 | ||
227 | hwmon_device_unregister(data->class_dev); | 223 | hwmon_device_unregister(data->class_dev); |
228 | sysfs_remove_group(&client->dev.kobj, &smsc47b397_group); | 224 | sysfs_remove_group(&pdev->dev.kobj, &smsc47b397_group); |
229 | 225 | res = platform_get_resource(pdev, IORESOURCE_IO, 0); | |
230 | if ((err = i2c_detach_client(client))) | 226 | release_region(res->start, SMSC_EXTENT); |
231 | return err; | ||
232 | |||
233 | release_region(client->addr, SMSC_EXTENT); | ||
234 | kfree(data); | 227 | kfree(data); |
235 | 228 | ||
236 | return 0; | 229 | return 0; |
237 | } | 230 | } |
238 | 231 | ||
239 | static int smsc47b397_detect(struct i2c_adapter *adapter); | 232 | static int smsc47b397_probe(struct platform_device *pdev); |
240 | 233 | ||
241 | static struct i2c_driver smsc47b397_driver = { | 234 | static struct platform_driver smsc47b397_driver = { |
242 | .driver = { | 235 | .driver = { |
243 | .owner = THIS_MODULE, | 236 | .owner = THIS_MODULE, |
244 | .name = "smsc47b397", | 237 | .name = DRVNAME, |
245 | }, | 238 | }, |
246 | .attach_adapter = smsc47b397_detect, | 239 | .probe = smsc47b397_probe, |
247 | .detach_client = smsc47b397_detach_client, | 240 | .remove = __devexit_p(smsc47b397_remove), |
248 | }; | 241 | }; |
249 | 242 | ||
250 | static int smsc47b397_detect(struct i2c_adapter *adapter) | 243 | static int __devinit smsc47b397_probe(struct platform_device *pdev) |
251 | { | 244 | { |
252 | struct i2c_client *new_client; | 245 | struct device *dev = &pdev->dev; |
253 | struct smsc47b397_data *data; | 246 | struct smsc47b397_data *data; |
247 | struct resource *res; | ||
254 | int err = 0; | 248 | int err = 0; |
255 | 249 | ||
256 | if (!request_region(address, SMSC_EXTENT, | 250 | res = platform_get_resource(pdev, IORESOURCE_IO, 0); |
251 | if (!request_region(res->start, SMSC_EXTENT, | ||
257 | smsc47b397_driver.driver.name)) { | 252 | smsc47b397_driver.driver.name)) { |
258 | dev_err(&adapter->dev, "Region 0x%x already in use!\n", | 253 | dev_err(dev, "Region 0x%lx-0x%lx already in use!\n", |
259 | address); | 254 | (unsigned long)res->start, |
255 | (unsigned long)res->start + SMSC_EXTENT - 1); | ||
260 | return -EBUSY; | 256 | return -EBUSY; |
261 | } | 257 | } |
262 | 258 | ||
@@ -265,25 +261,16 @@ static int smsc47b397_detect(struct i2c_adapter *adapter) | |||
265 | goto error_release; | 261 | goto error_release; |
266 | } | 262 | } |
267 | 263 | ||
268 | new_client = &data->client; | 264 | data->addr = res->start; |
269 | i2c_set_clientdata(new_client, data); | 265 | data->name = "smsc47b397"; |
270 | new_client->addr = address; | ||
271 | mutex_init(&data->lock); | 266 | mutex_init(&data->lock); |
272 | new_client->adapter = adapter; | ||
273 | new_client->driver = &smsc47b397_driver; | ||
274 | new_client->flags = 0; | ||
275 | |||
276 | strlcpy(new_client->name, "smsc47b397", I2C_NAME_SIZE); | ||
277 | |||
278 | mutex_init(&data->update_lock); | 267 | mutex_init(&data->update_lock); |
268 | platform_set_drvdata(pdev, data); | ||
279 | 269 | ||
280 | if ((err = i2c_attach_client(new_client))) | 270 | if ((err = sysfs_create_group(&dev->kobj, &smsc47b397_group))) |
281 | goto error_free; | 271 | goto error_free; |
282 | 272 | ||
283 | if ((err = sysfs_create_group(&new_client->dev.kobj, &smsc47b397_group))) | 273 | data->class_dev = hwmon_device_register(dev); |
284 | goto error_detach; | ||
285 | |||
286 | data->class_dev = hwmon_device_register(&new_client->dev); | ||
287 | if (IS_ERR(data->class_dev)) { | 274 | if (IS_ERR(data->class_dev)) { |
288 | err = PTR_ERR(data->class_dev); | 275 | err = PTR_ERR(data->class_dev); |
289 | goto error_remove; | 276 | goto error_remove; |
@@ -292,13 +279,50 @@ static int smsc47b397_detect(struct i2c_adapter *adapter) | |||
292 | return 0; | 279 | return 0; |
293 | 280 | ||
294 | error_remove: | 281 | error_remove: |
295 | sysfs_remove_group(&new_client->dev.kobj, &smsc47b397_group); | 282 | sysfs_remove_group(&dev->kobj, &smsc47b397_group); |
296 | error_detach: | ||
297 | i2c_detach_client(new_client); | ||
298 | error_free: | 283 | error_free: |
299 | kfree(data); | 284 | kfree(data); |
300 | error_release: | 285 | error_release: |
301 | release_region(address, SMSC_EXTENT); | 286 | release_region(res->start, SMSC_EXTENT); |
287 | return err; | ||
288 | } | ||
289 | |||
290 | static int __init smsc47b397_device_add(unsigned short address) | ||
291 | { | ||
292 | struct resource res = { | ||
293 | .start = address, | ||
294 | .end = address + SMSC_EXTENT - 1, | ||
295 | .name = DRVNAME, | ||
296 | .flags = IORESOURCE_IO, | ||
297 | }; | ||
298 | int err; | ||
299 | |||
300 | pdev = platform_device_alloc(DRVNAME, address); | ||
301 | if (!pdev) { | ||
302 | err = -ENOMEM; | ||
303 | printk(KERN_ERR DRVNAME ": Device allocation failed\n"); | ||
304 | goto exit; | ||
305 | } | ||
306 | |||
307 | err = platform_device_add_resources(pdev, &res, 1); | ||
308 | if (err) { | ||
309 | printk(KERN_ERR DRVNAME ": Device resource addition failed " | ||
310 | "(%d)\n", err); | ||
311 | goto exit_device_put; | ||
312 | } | ||
313 | |||
314 | err = platform_device_add(pdev); | ||
315 | if (err) { | ||
316 | printk(KERN_ERR DRVNAME ": Device addition failed (%d)\n", | ||
317 | err); | ||
318 | goto exit_device_put; | ||
319 | } | ||
320 | |||
321 | return 0; | ||
322 | |||
323 | exit_device_put: | ||
324 | platform_device_put(pdev); | ||
325 | exit: | ||
302 | return err; | 326 | return err; |
303 | } | 327 | } |
304 | 328 | ||
@@ -320,7 +344,7 @@ static int __init smsc47b397_find(unsigned short *addr) | |||
320 | *addr = (superio_inb(SUPERIO_REG_BASE_MSB) << 8) | 344 | *addr = (superio_inb(SUPERIO_REG_BASE_MSB) << 8) |
321 | | superio_inb(SUPERIO_REG_BASE_LSB); | 345 | | superio_inb(SUPERIO_REG_BASE_LSB); |
322 | 346 | ||
323 | printk(KERN_INFO "smsc47b397: found SMSC %s " | 347 | printk(KERN_INFO DRVNAME ": found SMSC %s " |
324 | "(base address 0x%04x, revision %u)\n", | 348 | "(base address 0x%04x, revision %u)\n", |
325 | id == 0x81 ? "SCH5307-NS" : "LPC47B397-NC", *addr, rev); | 349 | id == 0x81 ? "SCH5307-NS" : "LPC47B397-NC", *addr, rev); |
326 | 350 | ||
@@ -330,17 +354,33 @@ static int __init smsc47b397_find(unsigned short *addr) | |||
330 | 354 | ||
331 | static int __init smsc47b397_init(void) | 355 | static int __init smsc47b397_init(void) |
332 | { | 356 | { |
357 | unsigned short address; | ||
333 | int ret; | 358 | int ret; |
334 | 359 | ||
335 | if ((ret = smsc47b397_find(&address))) | 360 | if ((ret = smsc47b397_find(&address))) |
336 | return ret; | 361 | return ret; |
337 | 362 | ||
338 | return i2c_isa_add_driver(&smsc47b397_driver); | 363 | ret = platform_driver_register(&smsc47b397_driver); |
364 | if (ret) | ||
365 | goto exit; | ||
366 | |||
367 | /* Sets global pdev as a side effect */ | ||
368 | ret = smsc47b397_device_add(address); | ||
369 | if (ret) | ||
370 | goto exit_driver; | ||
371 | |||
372 | return 0; | ||
373 | |||
374 | exit_driver: | ||
375 | platform_driver_unregister(&smsc47b397_driver); | ||
376 | exit: | ||
377 | return ret; | ||
339 | } | 378 | } |
340 | 379 | ||
341 | static void __exit smsc47b397_exit(void) | 380 | static void __exit smsc47b397_exit(void) |
342 | { | 381 | { |
343 | i2c_isa_del_driver(&smsc47b397_driver); | 382 | platform_device_unregister(pdev); |
383 | platform_driver_unregister(&smsc47b397_driver); | ||
344 | } | 384 | } |
345 | 385 | ||
346 | MODULE_AUTHOR("Mark M. Hoffman <mhoffman@lightlink.com>"); | 386 | MODULE_AUTHOR("Mark M. Hoffman <mhoffman@lightlink.com>"); |
diff --git a/drivers/hwmon/smsc47m1.c b/drivers/hwmon/smsc47m1.c index beb881c4b2e8..1e21c8cc948f 100644 --- a/drivers/hwmon/smsc47m1.c +++ b/drivers/hwmon/smsc47m1.c | |||
@@ -3,10 +3,11 @@ | |||
3 | for hardware monitoring | 3 | for hardware monitoring |
4 | 4 | ||
5 | Supports the SMSC LPC47B27x, LPC47M10x, LPC47M112, LPC47M13x, | 5 | Supports the SMSC LPC47B27x, LPC47M10x, LPC47M112, LPC47M13x, |
6 | LPC47M14x, LPC47M15x, LPC47M192 and LPC47M997 Super-I/O chips. | 6 | LPC47M14x, LPC47M15x, LPC47M192, LPC47M292 and LPC47M997 |
7 | Super-I/O chips. | ||
7 | 8 | ||
8 | Copyright (C) 2002 Mark D. Studebaker <mdsxyz123@yahoo.com> | 9 | Copyright (C) 2002 Mark D. Studebaker <mdsxyz123@yahoo.com> |
9 | Copyright (C) 2004 Jean Delvare <khali@linux-fr.org> | 10 | Copyright (C) 2004-2007 Jean Delvare <khali@linux-fr.org> |
10 | Ported to Linux 2.6 by Gabriele Gorla <gorlik@yahoo.com> | 11 | Ported to Linux 2.6 by Gabriele Gorla <gorlik@yahoo.com> |
11 | and Jean Delvare | 12 | and Jean Delvare |
12 | 13 | ||
@@ -29,17 +30,19 @@ | |||
29 | #include <linux/slab.h> | 30 | #include <linux/slab.h> |
30 | #include <linux/ioport.h> | 31 | #include <linux/ioport.h> |
31 | #include <linux/jiffies.h> | 32 | #include <linux/jiffies.h> |
32 | #include <linux/i2c.h> | 33 | #include <linux/platform_device.h> |
33 | #include <linux/i2c-isa.h> | ||
34 | #include <linux/hwmon.h> | 34 | #include <linux/hwmon.h> |
35 | #include <linux/hwmon-sysfs.h> | ||
35 | #include <linux/err.h> | 36 | #include <linux/err.h> |
36 | #include <linux/init.h> | 37 | #include <linux/init.h> |
37 | #include <linux/mutex.h> | 38 | #include <linux/mutex.h> |
38 | #include <linux/sysfs.h> | 39 | #include <linux/sysfs.h> |
39 | #include <asm/io.h> | 40 | #include <asm/io.h> |
40 | 41 | ||
41 | /* Address is autodetected, there is no default value */ | 42 | static struct platform_device *pdev; |
42 | static unsigned short address; | 43 | |
44 | #define DRVNAME "smsc47m1" | ||
45 | enum chips { smsc47m1, smsc47m2 }; | ||
43 | 46 | ||
44 | /* Super-I/0 registers and commands */ | 47 | /* Super-I/0 registers and commands */ |
45 | 48 | ||
@@ -87,10 +90,18 @@ superio_exit(void) | |||
87 | #define SMSC47M1_REG_ALARM 0x04 | 90 | #define SMSC47M1_REG_ALARM 0x04 |
88 | #define SMSC47M1_REG_TPIN(nr) (0x34 - (nr)) | 91 | #define SMSC47M1_REG_TPIN(nr) (0x34 - (nr)) |
89 | #define SMSC47M1_REG_PPIN(nr) (0x36 - (nr)) | 92 | #define SMSC47M1_REG_PPIN(nr) (0x36 - (nr)) |
90 | #define SMSC47M1_REG_PWM(nr) (0x56 + (nr)) | ||
91 | #define SMSC47M1_REG_FANDIV 0x58 | 93 | #define SMSC47M1_REG_FANDIV 0x58 |
92 | #define SMSC47M1_REG_FAN(nr) (0x59 + (nr)) | 94 | |
93 | #define SMSC47M1_REG_FAN_PRELOAD(nr) (0x5B + (nr)) | 95 | static const u8 SMSC47M1_REG_FAN[3] = { 0x59, 0x5a, 0x6b }; |
96 | static const u8 SMSC47M1_REG_FAN_PRELOAD[3] = { 0x5b, 0x5c, 0x6c }; | ||
97 | static const u8 SMSC47M1_REG_PWM[3] = { 0x56, 0x57, 0x69 }; | ||
98 | |||
99 | #define SMSC47M2_REG_ALARM6 0x09 | ||
100 | #define SMSC47M2_REG_TPIN1 0x38 | ||
101 | #define SMSC47M2_REG_TPIN2 0x37 | ||
102 | #define SMSC47M2_REG_TPIN3 0x2d | ||
103 | #define SMSC47M2_REG_PPIN3 0x2c | ||
104 | #define SMSC47M2_REG_FANDIV3 0x6a | ||
94 | 105 | ||
95 | #define MIN_FROM_REG(reg,div) ((reg)>=192 ? 0 : \ | 106 | #define MIN_FROM_REG(reg,div) ((reg)>=192 ? 0 : \ |
96 | 983040/((192-(reg))*(div))) | 107 | 983040/((192-(reg))*(div))) |
@@ -102,45 +113,57 @@ superio_exit(void) | |||
102 | #define PWM_TO_REG(reg) (((reg) >> 1) & 0x7E) | 113 | #define PWM_TO_REG(reg) (((reg) >> 1) & 0x7E) |
103 | 114 | ||
104 | struct smsc47m1_data { | 115 | struct smsc47m1_data { |
105 | struct i2c_client client; | 116 | unsigned short addr; |
117 | const char *name; | ||
118 | enum chips type; | ||
106 | struct class_device *class_dev; | 119 | struct class_device *class_dev; |
107 | struct mutex lock; | ||
108 | 120 | ||
109 | struct mutex update_lock; | 121 | struct mutex update_lock; |
110 | unsigned long last_updated; /* In jiffies */ | 122 | unsigned long last_updated; /* In jiffies */ |
111 | 123 | ||
112 | u8 fan[2]; /* Register value */ | 124 | u8 fan[3]; /* Register value */ |
113 | u8 fan_preload[2]; /* Register value */ | 125 | u8 fan_preload[3]; /* Register value */ |
114 | u8 fan_div[2]; /* Register encoding, shifted right */ | 126 | u8 fan_div[3]; /* Register encoding, shifted right */ |
115 | u8 alarms; /* Register encoding */ | 127 | u8 alarms; /* Register encoding */ |
116 | u8 pwm[2]; /* Register value (bit 7 is enable) */ | 128 | u8 pwm[3]; /* Register value (bit 0 is disable) */ |
117 | }; | 129 | }; |
118 | 130 | ||
131 | struct smsc47m1_sio_data { | ||
132 | enum chips type; | ||
133 | }; | ||
119 | 134 | ||
120 | static int smsc47m1_detect(struct i2c_adapter *adapter); | ||
121 | static int smsc47m1_detach_client(struct i2c_client *client); | ||
122 | |||
123 | static int smsc47m1_read_value(struct i2c_client *client, u8 reg); | ||
124 | static void smsc47m1_write_value(struct i2c_client *client, u8 reg, u8 value); | ||
125 | 135 | ||
136 | static int smsc47m1_probe(struct platform_device *pdev); | ||
137 | static int smsc47m1_remove(struct platform_device *pdev); | ||
126 | static struct smsc47m1_data *smsc47m1_update_device(struct device *dev, | 138 | static struct smsc47m1_data *smsc47m1_update_device(struct device *dev, |
127 | int init); | 139 | int init); |
128 | 140 | ||
141 | static inline int smsc47m1_read_value(struct smsc47m1_data *data, u8 reg) | ||
142 | { | ||
143 | return inb_p(data->addr + reg); | ||
144 | } | ||
129 | 145 | ||
130 | static struct i2c_driver smsc47m1_driver = { | 146 | static inline void smsc47m1_write_value(struct smsc47m1_data *data, u8 reg, |
147 | u8 value) | ||
148 | { | ||
149 | outb_p(value, data->addr + reg); | ||
150 | } | ||
151 | |||
152 | static struct platform_driver smsc47m1_driver = { | ||
131 | .driver = { | 153 | .driver = { |
132 | .owner = THIS_MODULE, | 154 | .owner = THIS_MODULE, |
133 | .name = "smsc47m1", | 155 | .name = DRVNAME, |
134 | }, | 156 | }, |
135 | .attach_adapter = smsc47m1_detect, | 157 | .probe = smsc47m1_probe, |
136 | .detach_client = smsc47m1_detach_client, | 158 | .remove = __devexit_p(smsc47m1_remove), |
137 | }; | 159 | }; |
138 | 160 | ||
139 | /* nr is 0 or 1 in the callback functions below */ | 161 | static ssize_t get_fan(struct device *dev, struct device_attribute |
140 | 162 | *devattr, char *buf) | |
141 | static ssize_t get_fan(struct device *dev, char *buf, int nr) | ||
142 | { | 163 | { |
164 | struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); | ||
143 | struct smsc47m1_data *data = smsc47m1_update_device(dev, 0); | 165 | struct smsc47m1_data *data = smsc47m1_update_device(dev, 0); |
166 | int nr = attr->index; | ||
144 | /* This chip (stupidly) stops monitoring fan speed if PWM is | 167 | /* This chip (stupidly) stops monitoring fan speed if PWM is |
145 | enabled and duty cycle is 0%. This is fine if the monitoring | 168 | enabled and duty cycle is 0%. This is fine if the monitoring |
146 | and control concern the same fan, but troublesome if they are | 169 | and control concern the same fan, but troublesome if they are |
@@ -152,43 +175,54 @@ static ssize_t get_fan(struct device *dev, char *buf, int nr) | |||
152 | return sprintf(buf, "%d\n", rpm); | 175 | return sprintf(buf, "%d\n", rpm); |
153 | } | 176 | } |
154 | 177 | ||
155 | static ssize_t get_fan_min(struct device *dev, char *buf, int nr) | 178 | static ssize_t get_fan_min(struct device *dev, struct device_attribute |
179 | *devattr, char *buf) | ||
156 | { | 180 | { |
181 | struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); | ||
157 | struct smsc47m1_data *data = smsc47m1_update_device(dev, 0); | 182 | struct smsc47m1_data *data = smsc47m1_update_device(dev, 0); |
183 | int nr = attr->index; | ||
158 | int rpm = MIN_FROM_REG(data->fan_preload[nr], | 184 | int rpm = MIN_FROM_REG(data->fan_preload[nr], |
159 | DIV_FROM_REG(data->fan_div[nr])); | 185 | DIV_FROM_REG(data->fan_div[nr])); |
160 | return sprintf(buf, "%d\n", rpm); | 186 | return sprintf(buf, "%d\n", rpm); |
161 | } | 187 | } |
162 | 188 | ||
163 | static ssize_t get_fan_div(struct device *dev, char *buf, int nr) | 189 | static ssize_t get_fan_div(struct device *dev, struct device_attribute |
190 | *devattr, char *buf) | ||
164 | { | 191 | { |
192 | struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); | ||
165 | struct smsc47m1_data *data = smsc47m1_update_device(dev, 0); | 193 | struct smsc47m1_data *data = smsc47m1_update_device(dev, 0); |
166 | return sprintf(buf, "%d\n", DIV_FROM_REG(data->fan_div[nr])); | 194 | return sprintf(buf, "%d\n", DIV_FROM_REG(data->fan_div[attr->index])); |
167 | } | 195 | } |
168 | 196 | ||
169 | static ssize_t get_pwm(struct device *dev, char *buf, int nr) | 197 | static ssize_t get_pwm(struct device *dev, struct device_attribute |
198 | *devattr, char *buf) | ||
170 | { | 199 | { |
200 | struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); | ||
171 | struct smsc47m1_data *data = smsc47m1_update_device(dev, 0); | 201 | struct smsc47m1_data *data = smsc47m1_update_device(dev, 0); |
172 | return sprintf(buf, "%d\n", PWM_FROM_REG(data->pwm[nr])); | 202 | return sprintf(buf, "%d\n", PWM_FROM_REG(data->pwm[attr->index])); |
173 | } | 203 | } |
174 | 204 | ||
175 | static ssize_t get_pwm_en(struct device *dev, char *buf, int nr) | 205 | static ssize_t get_pwm_en(struct device *dev, struct device_attribute |
206 | *devattr, char *buf) | ||
176 | { | 207 | { |
208 | struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); | ||
177 | struct smsc47m1_data *data = smsc47m1_update_device(dev, 0); | 209 | struct smsc47m1_data *data = smsc47m1_update_device(dev, 0); |
178 | return sprintf(buf, "%d\n", PWM_EN_FROM_REG(data->pwm[nr])); | 210 | return sprintf(buf, "%d\n", PWM_EN_FROM_REG(data->pwm[attr->index])); |
179 | } | 211 | } |
180 | 212 | ||
181 | static ssize_t get_alarms(struct device *dev, struct device_attribute *attr, char *buf) | 213 | static ssize_t get_alarms(struct device *dev, struct device_attribute |
214 | *devattr, char *buf) | ||
182 | { | 215 | { |
183 | struct smsc47m1_data *data = smsc47m1_update_device(dev, 0); | 216 | struct smsc47m1_data *data = smsc47m1_update_device(dev, 0); |
184 | return sprintf(buf, "%d\n", data->alarms); | 217 | return sprintf(buf, "%d\n", data->alarms); |
185 | } | 218 | } |
186 | 219 | ||
187 | static ssize_t set_fan_min(struct device *dev, const char *buf, | 220 | static ssize_t set_fan_min(struct device *dev, struct device_attribute |
188 | size_t count, int nr) | 221 | *devattr, const char *buf, size_t count) |
189 | { | 222 | { |
190 | struct i2c_client *client = to_i2c_client(dev); | 223 | struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); |
191 | struct smsc47m1_data *data = i2c_get_clientdata(client); | 224 | struct smsc47m1_data *data = dev_get_drvdata(dev); |
225 | int nr = attr->index; | ||
192 | long rpmdiv, val = simple_strtol(buf, NULL, 10); | 226 | long rpmdiv, val = simple_strtol(buf, NULL, 10); |
193 | 227 | ||
194 | mutex_lock(&data->update_lock); | 228 | mutex_lock(&data->update_lock); |
@@ -200,7 +234,7 @@ static ssize_t set_fan_min(struct device *dev, const char *buf, | |||
200 | } | 234 | } |
201 | 235 | ||
202 | data->fan_preload[nr] = 192 - ((983040 + rpmdiv / 2) / rpmdiv); | 236 | data->fan_preload[nr] = 192 - ((983040 + rpmdiv / 2) / rpmdiv); |
203 | smsc47m1_write_value(client, SMSC47M1_REG_FAN_PRELOAD(nr), | 237 | smsc47m1_write_value(data, SMSC47M1_REG_FAN_PRELOAD[nr], |
204 | data->fan_preload[nr]); | 238 | data->fan_preload[nr]); |
205 | mutex_unlock(&data->update_lock); | 239 | mutex_unlock(&data->update_lock); |
206 | 240 | ||
@@ -211,12 +245,12 @@ static ssize_t set_fan_min(struct device *dev, const char *buf, | |||
211 | determined in part by the fan clock divider. This follows the principle | 245 | determined in part by the fan clock divider. This follows the principle |
212 | of least surprise; the user doesn't expect the fan minimum to change just | 246 | of least surprise; the user doesn't expect the fan minimum to change just |
213 | because the divider changed. */ | 247 | because the divider changed. */ |
214 | static ssize_t set_fan_div(struct device *dev, const char *buf, | 248 | static ssize_t set_fan_div(struct device *dev, struct device_attribute |
215 | size_t count, int nr) | 249 | *devattr, const char *buf, size_t count) |
216 | { | 250 | { |
217 | struct i2c_client *client = to_i2c_client(dev); | 251 | struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); |
218 | struct smsc47m1_data *data = i2c_get_clientdata(client); | 252 | struct smsc47m1_data *data = dev_get_drvdata(dev); |
219 | 253 | int nr = attr->index; | |
220 | long new_div = simple_strtol(buf, NULL, 10), tmp; | 254 | long new_div = simple_strtol(buf, NULL, 10), tmp; |
221 | u8 old_div = DIV_FROM_REG(data->fan_div[nr]); | 255 | u8 old_div = DIV_FROM_REG(data->fan_div[nr]); |
222 | 256 | ||
@@ -234,27 +268,38 @@ static ssize_t set_fan_div(struct device *dev, const char *buf, | |||
234 | return -EINVAL; | 268 | return -EINVAL; |
235 | } | 269 | } |
236 | 270 | ||
237 | tmp = smsc47m1_read_value(client, SMSC47M1_REG_FANDIV) & 0x0F; | 271 | switch (nr) { |
238 | tmp |= (data->fan_div[0] << 4) | (data->fan_div[1] << 6); | 272 | case 0: |
239 | smsc47m1_write_value(client, SMSC47M1_REG_FANDIV, tmp); | 273 | case 1: |
274 | tmp = smsc47m1_read_value(data, SMSC47M1_REG_FANDIV) | ||
275 | & ~(0x03 << (4 + 2 * nr)); | ||
276 | tmp |= data->fan_div[nr] << (4 + 2 * nr); | ||
277 | smsc47m1_write_value(data, SMSC47M1_REG_FANDIV, tmp); | ||
278 | break; | ||
279 | case 2: | ||
280 | tmp = smsc47m1_read_value(data, SMSC47M2_REG_FANDIV3) & 0xCF; | ||
281 | tmp |= data->fan_div[2] << 4; | ||
282 | smsc47m1_write_value(data, SMSC47M2_REG_FANDIV3, tmp); | ||
283 | break; | ||
284 | } | ||
240 | 285 | ||
241 | /* Preserve fan min */ | 286 | /* Preserve fan min */ |
242 | tmp = 192 - (old_div * (192 - data->fan_preload[nr]) | 287 | tmp = 192 - (old_div * (192 - data->fan_preload[nr]) |
243 | + new_div / 2) / new_div; | 288 | + new_div / 2) / new_div; |
244 | data->fan_preload[nr] = SENSORS_LIMIT(tmp, 0, 191); | 289 | data->fan_preload[nr] = SENSORS_LIMIT(tmp, 0, 191); |
245 | smsc47m1_write_value(client, SMSC47M1_REG_FAN_PRELOAD(nr), | 290 | smsc47m1_write_value(data, SMSC47M1_REG_FAN_PRELOAD[nr], |
246 | data->fan_preload[nr]); | 291 | data->fan_preload[nr]); |
247 | mutex_unlock(&data->update_lock); | 292 | mutex_unlock(&data->update_lock); |
248 | 293 | ||
249 | return count; | 294 | return count; |
250 | } | 295 | } |
251 | 296 | ||
252 | static ssize_t set_pwm(struct device *dev, const char *buf, | 297 | static ssize_t set_pwm(struct device *dev, struct device_attribute |
253 | size_t count, int nr) | 298 | *devattr, const char *buf, size_t count) |
254 | { | 299 | { |
255 | struct i2c_client *client = to_i2c_client(dev); | 300 | struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); |
256 | struct smsc47m1_data *data = i2c_get_clientdata(client); | 301 | struct smsc47m1_data *data = dev_get_drvdata(dev); |
257 | 302 | int nr = attr->index; | |
258 | long val = simple_strtol(buf, NULL, 10); | 303 | long val = simple_strtol(buf, NULL, 10); |
259 | 304 | ||
260 | if (val < 0 || val > 255) | 305 | if (val < 0 || val > 255) |
@@ -263,19 +308,19 @@ static ssize_t set_pwm(struct device *dev, const char *buf, | |||
263 | mutex_lock(&data->update_lock); | 308 | mutex_lock(&data->update_lock); |
264 | data->pwm[nr] &= 0x81; /* Preserve additional bits */ | 309 | data->pwm[nr] &= 0x81; /* Preserve additional bits */ |
265 | data->pwm[nr] |= PWM_TO_REG(val); | 310 | data->pwm[nr] |= PWM_TO_REG(val); |
266 | smsc47m1_write_value(client, SMSC47M1_REG_PWM(nr), | 311 | smsc47m1_write_value(data, SMSC47M1_REG_PWM[nr], |
267 | data->pwm[nr]); | 312 | data->pwm[nr]); |
268 | mutex_unlock(&data->update_lock); | 313 | mutex_unlock(&data->update_lock); |
269 | 314 | ||
270 | return count; | 315 | return count; |
271 | } | 316 | } |
272 | 317 | ||
273 | static ssize_t set_pwm_en(struct device *dev, const char *buf, | 318 | static ssize_t set_pwm_en(struct device *dev, struct device_attribute |
274 | size_t count, int nr) | 319 | *devattr, const char *buf, size_t count) |
275 | { | 320 | { |
276 | struct i2c_client *client = to_i2c_client(dev); | 321 | struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); |
277 | struct smsc47m1_data *data = i2c_get_clientdata(client); | 322 | struct smsc47m1_data *data = dev_get_drvdata(dev); |
278 | 323 | int nr = attr->index; | |
279 | long val = simple_strtol(buf, NULL, 10); | 324 | long val = simple_strtol(buf, NULL, 10); |
280 | 325 | ||
281 | if (val != 0 && val != 1) | 326 | if (val != 0 && val != 1) |
@@ -284,7 +329,7 @@ static ssize_t set_pwm_en(struct device *dev, const char *buf, | |||
284 | mutex_lock(&data->update_lock); | 329 | mutex_lock(&data->update_lock); |
285 | data->pwm[nr] &= 0xFE; /* preserve the other bits */ | 330 | data->pwm[nr] &= 0xFE; /* preserve the other bits */ |
286 | data->pwm[nr] |= !val; | 331 | data->pwm[nr] |= !val; |
287 | smsc47m1_write_value(client, SMSC47M1_REG_PWM(nr), | 332 | smsc47m1_write_value(data, SMSC47M1_REG_PWM[nr], |
288 | data->pwm[nr]); | 333 | data->pwm[nr]); |
289 | mutex_unlock(&data->update_lock); | 334 | mutex_unlock(&data->update_lock); |
290 | 335 | ||
@@ -292,79 +337,55 @@ static ssize_t set_pwm_en(struct device *dev, const char *buf, | |||
292 | } | 337 | } |
293 | 338 | ||
294 | #define fan_present(offset) \ | 339 | #define fan_present(offset) \ |
295 | static ssize_t get_fan##offset (struct device *dev, struct device_attribute *attr, char *buf) \ | 340 | static SENSOR_DEVICE_ATTR(fan##offset##_input, S_IRUGO, get_fan, \ |
296 | { \ | 341 | NULL, offset - 1); \ |
297 | return get_fan(dev, buf, offset - 1); \ | 342 | static SENSOR_DEVICE_ATTR(fan##offset##_min, S_IRUGO | S_IWUSR, \ |
298 | } \ | 343 | get_fan_min, set_fan_min, offset - 1); \ |
299 | static ssize_t get_fan##offset##_min (struct device *dev, struct device_attribute *attr, char *buf) \ | 344 | static SENSOR_DEVICE_ATTR(fan##offset##_div, S_IRUGO | S_IWUSR, \ |
300 | { \ | 345 | get_fan_div, set_fan_div, offset - 1); \ |
301 | return get_fan_min(dev, buf, offset - 1); \ | 346 | static SENSOR_DEVICE_ATTR(pwm##offset, S_IRUGO | S_IWUSR, \ |
302 | } \ | 347 | get_pwm, set_pwm, offset - 1); \ |
303 | static ssize_t set_fan##offset##_min (struct device *dev, struct device_attribute *attr, \ | 348 | static SENSOR_DEVICE_ATTR(pwm##offset##_enable, S_IRUGO | S_IWUSR, \ |
304 | const char *buf, size_t count) \ | 349 | get_pwm_en, set_pwm_en, offset - 1) |
305 | { \ | ||
306 | return set_fan_min(dev, buf, count, offset - 1); \ | ||
307 | } \ | ||
308 | static ssize_t get_fan##offset##_div (struct device *dev, struct device_attribute *attr, char *buf) \ | ||
309 | { \ | ||
310 | return get_fan_div(dev, buf, offset - 1); \ | ||
311 | } \ | ||
312 | static ssize_t set_fan##offset##_div (struct device *dev, struct device_attribute *attr, \ | ||
313 | const char *buf, size_t count) \ | ||
314 | { \ | ||
315 | return set_fan_div(dev, buf, count, offset - 1); \ | ||
316 | } \ | ||
317 | static ssize_t get_pwm##offset (struct device *dev, struct device_attribute *attr, char *buf) \ | ||
318 | { \ | ||
319 | return get_pwm(dev, buf, offset - 1); \ | ||
320 | } \ | ||
321 | static ssize_t set_pwm##offset (struct device *dev, struct device_attribute *attr, \ | ||
322 | const char *buf, size_t count) \ | ||
323 | { \ | ||
324 | return set_pwm(dev, buf, count, offset - 1); \ | ||
325 | } \ | ||
326 | static ssize_t get_pwm##offset##_en (struct device *dev, struct device_attribute *attr, char *buf) \ | ||
327 | { \ | ||
328 | return get_pwm_en(dev, buf, offset - 1); \ | ||
329 | } \ | ||
330 | static ssize_t set_pwm##offset##_en (struct device *dev, struct device_attribute *attr, \ | ||
331 | const char *buf, size_t count) \ | ||
332 | { \ | ||
333 | return set_pwm_en(dev, buf, count, offset - 1); \ | ||
334 | } \ | ||
335 | static DEVICE_ATTR(fan##offset##_input, S_IRUGO, get_fan##offset, \ | ||
336 | NULL); \ | ||
337 | static DEVICE_ATTR(fan##offset##_min, S_IRUGO | S_IWUSR, \ | ||
338 | get_fan##offset##_min, set_fan##offset##_min); \ | ||
339 | static DEVICE_ATTR(fan##offset##_div, S_IRUGO | S_IWUSR, \ | ||
340 | get_fan##offset##_div, set_fan##offset##_div); \ | ||
341 | static DEVICE_ATTR(pwm##offset, S_IRUGO | S_IWUSR, \ | ||
342 | get_pwm##offset, set_pwm##offset); \ | ||
343 | static DEVICE_ATTR(pwm##offset##_enable, S_IRUGO | S_IWUSR, \ | ||
344 | get_pwm##offset##_en, set_pwm##offset##_en); | ||
345 | 350 | ||
346 | fan_present(1); | 351 | fan_present(1); |
347 | fan_present(2); | 352 | fan_present(2); |
353 | fan_present(3); | ||
348 | 354 | ||
349 | static DEVICE_ATTR(alarms, S_IRUGO, get_alarms, NULL); | 355 | static DEVICE_ATTR(alarms, S_IRUGO, get_alarms, NULL); |
350 | 356 | ||
357 | static ssize_t show_name(struct device *dev, struct device_attribute | ||
358 | *devattr, char *buf) | ||
359 | { | ||
360 | struct smsc47m1_data *data = dev_get_drvdata(dev); | ||
361 | |||
362 | return sprintf(buf, "%s\n", data->name); | ||
363 | } | ||
364 | static DEVICE_ATTR(name, S_IRUGO, show_name, NULL); | ||
365 | |||
351 | /* Almost all sysfs files may or may not be created depending on the chip | 366 | /* Almost all sysfs files may or may not be created depending on the chip |
352 | setup so we create them individually. It is still convenient to define a | 367 | setup so we create them individually. It is still convenient to define a |
353 | group to remove them all at once. */ | 368 | group to remove them all at once. */ |
354 | static struct attribute *smsc47m1_attributes[] = { | 369 | static struct attribute *smsc47m1_attributes[] = { |
355 | &dev_attr_fan1_input.attr, | 370 | &sensor_dev_attr_fan1_input.dev_attr.attr, |
356 | &dev_attr_fan1_min.attr, | 371 | &sensor_dev_attr_fan1_min.dev_attr.attr, |
357 | &dev_attr_fan1_div.attr, | 372 | &sensor_dev_attr_fan1_div.dev_attr.attr, |
358 | &dev_attr_fan2_input.attr, | 373 | &sensor_dev_attr_fan2_input.dev_attr.attr, |
359 | &dev_attr_fan2_min.attr, | 374 | &sensor_dev_attr_fan2_min.dev_attr.attr, |
360 | &dev_attr_fan2_div.attr, | 375 | &sensor_dev_attr_fan2_div.dev_attr.attr, |
361 | 376 | &sensor_dev_attr_fan3_input.dev_attr.attr, | |
362 | &dev_attr_pwm1.attr, | 377 | &sensor_dev_attr_fan3_min.dev_attr.attr, |
363 | &dev_attr_pwm1_enable.attr, | 378 | &sensor_dev_attr_fan3_div.dev_attr.attr, |
364 | &dev_attr_pwm2.attr, | 379 | |
365 | &dev_attr_pwm2_enable.attr, | 380 | &sensor_dev_attr_pwm1.dev_attr.attr, |
381 | &sensor_dev_attr_pwm1_enable.dev_attr.attr, | ||
382 | &sensor_dev_attr_pwm2.dev_attr.attr, | ||
383 | &sensor_dev_attr_pwm2_enable.dev_attr.attr, | ||
384 | &sensor_dev_attr_pwm3.dev_attr.attr, | ||
385 | &sensor_dev_attr_pwm3_enable.dev_attr.attr, | ||
366 | 386 | ||
367 | &dev_attr_alarms.attr, | 387 | &dev_attr_alarms.attr, |
388 | &dev_attr_name.attr, | ||
368 | NULL | 389 | NULL |
369 | }; | 390 | }; |
370 | 391 | ||
@@ -372,7 +393,8 @@ static const struct attribute_group smsc47m1_group = { | |||
372 | .attrs = smsc47m1_attributes, | 393 | .attrs = smsc47m1_attributes, |
373 | }; | 394 | }; |
374 | 395 | ||
375 | static int __init smsc47m1_find(unsigned short *addr) | 396 | static int __init smsc47m1_find(unsigned short *addr, |
397 | struct smsc47m1_sio_data *sio_data) | ||
376 | { | 398 | { |
377 | u8 val; | 399 | u8 val; |
378 | 400 | ||
@@ -386,18 +408,32 @@ static int __init smsc47m1_find(unsigned short *addr) | |||
386 | * can do much more besides (device id 0x60). | 408 | * can do much more besides (device id 0x60). |
387 | * The LPC47M997 is undocumented, but seems to be compatible with | 409 | * The LPC47M997 is undocumented, but seems to be compatible with |
388 | * the LPC47M192, and has the same device id. | 410 | * the LPC47M192, and has the same device id. |
411 | * The LPC47M292 (device id 0x6B) is somewhat compatible, but it | ||
412 | * supports a 3rd fan, and the pin configuration registers are | ||
413 | * unfortunately different. | ||
389 | */ | 414 | */ |
390 | if (val == 0x51) | 415 | switch (val) { |
391 | printk(KERN_INFO "smsc47m1: Found SMSC LPC47B27x\n"); | 416 | case 0x51: |
392 | else if (val == 0x59) | 417 | pr_info(DRVNAME ": Found SMSC LPC47B27x\n"); |
393 | printk(KERN_INFO "smsc47m1: Found SMSC " | 418 | sio_data->type = smsc47m1; |
394 | "LPC47M10x/LPC47M112/LPC47M13x\n"); | 419 | break; |
395 | else if (val == 0x5F) | 420 | case 0x59: |
396 | printk(KERN_INFO "smsc47m1: Found SMSC LPC47M14x\n"); | 421 | pr_info(DRVNAME ": Found SMSC LPC47M10x/LPC47M112/LPC47M13x\n"); |
397 | else if (val == 0x60) | 422 | sio_data->type = smsc47m1; |
398 | printk(KERN_INFO "smsc47m1: Found SMSC " | 423 | break; |
399 | "LPC47M15x/LPC47M192/LPC47M997\n"); | 424 | case 0x5F: |
400 | else { | 425 | pr_info(DRVNAME ": Found SMSC LPC47M14x\n"); |
426 | sio_data->type = smsc47m1; | ||
427 | break; | ||
428 | case 0x60: | ||
429 | pr_info(DRVNAME ": Found SMSC LPC47M15x/LPC47M192/LPC47M997\n"); | ||
430 | sio_data->type = smsc47m1; | ||
431 | break; | ||
432 | case 0x6B: | ||
433 | pr_info(DRVNAME ": Found SMSC LPC47M292\n"); | ||
434 | sio_data->type = smsc47m2; | ||
435 | break; | ||
436 | default: | ||
401 | superio_exit(); | 437 | superio_exit(); |
402 | return -ENODEV; | 438 | return -ENODEV; |
403 | } | 439 | } |
@@ -407,7 +443,7 @@ static int __init smsc47m1_find(unsigned short *addr) | |||
407 | | superio_inb(SUPERIO_REG_BASE + 1); | 443 | | superio_inb(SUPERIO_REG_BASE + 1); |
408 | val = superio_inb(SUPERIO_REG_ACT); | 444 | val = superio_inb(SUPERIO_REG_ACT); |
409 | if (*addr == 0 || (val & 0x01) == 0) { | 445 | if (*addr == 0 || (val & 0x01) == 0) { |
410 | printk(KERN_INFO "smsc47m1: Device is disabled, will not use\n"); | 446 | pr_info(DRVNAME ": Device is disabled, will not use\n"); |
411 | superio_exit(); | 447 | superio_exit(); |
412 | return -ENODEV; | 448 | return -ENODEV; |
413 | } | 449 | } |
@@ -416,15 +452,25 @@ static int __init smsc47m1_find(unsigned short *addr) | |||
416 | return 0; | 452 | return 0; |
417 | } | 453 | } |
418 | 454 | ||
419 | static int smsc47m1_detect(struct i2c_adapter *adapter) | 455 | static int __devinit smsc47m1_probe(struct platform_device *pdev) |
420 | { | 456 | { |
421 | struct i2c_client *new_client; | 457 | struct device *dev = &pdev->dev; |
458 | struct smsc47m1_sio_data *sio_data = dev->platform_data; | ||
422 | struct smsc47m1_data *data; | 459 | struct smsc47m1_data *data; |
460 | struct resource *res; | ||
423 | int err = 0; | 461 | int err = 0; |
424 | int fan1, fan2, pwm1, pwm2; | 462 | int fan1, fan2, fan3, pwm1, pwm2, pwm3; |
425 | 463 | ||
426 | if (!request_region(address, SMSC_EXTENT, smsc47m1_driver.driver.name)) { | 464 | static const char *names[] = { |
427 | dev_err(&adapter->dev, "Region 0x%x already in use!\n", address); | 465 | "smsc47m1", |
466 | "smsc47m2", | ||
467 | }; | ||
468 | |||
469 | res = platform_get_resource(pdev, IORESOURCE_IO, 0); | ||
470 | if (!request_region(res->start, SMSC_EXTENT, DRVNAME)) { | ||
471 | dev_err(dev, "Region 0x%lx-0x%lx already in use!\n", | ||
472 | (unsigned long)res->start, | ||
473 | (unsigned long)res->end); | ||
428 | return -EBUSY; | 474 | return -EBUSY; |
429 | } | 475 | } |
430 | 476 | ||
@@ -433,93 +479,114 @@ static int smsc47m1_detect(struct i2c_adapter *adapter) | |||
433 | goto error_release; | 479 | goto error_release; |
434 | } | 480 | } |
435 | 481 | ||
436 | new_client = &data->client; | 482 | data->addr = res->start; |
437 | i2c_set_clientdata(new_client, data); | 483 | data->type = sio_data->type; |
438 | new_client->addr = address; | 484 | data->name = names[sio_data->type]; |
439 | mutex_init(&data->lock); | ||
440 | new_client->adapter = adapter; | ||
441 | new_client->driver = &smsc47m1_driver; | ||
442 | new_client->flags = 0; | ||
443 | |||
444 | strlcpy(new_client->name, "smsc47m1", I2C_NAME_SIZE); | ||
445 | mutex_init(&data->update_lock); | 485 | mutex_init(&data->update_lock); |
486 | platform_set_drvdata(pdev, data); | ||
446 | 487 | ||
447 | /* If no function is properly configured, there's no point in | 488 | /* If no function is properly configured, there's no point in |
448 | actually registering the chip. */ | 489 | actually registering the chip. */ |
449 | fan1 = (smsc47m1_read_value(new_client, SMSC47M1_REG_TPIN(0)) & 0x05) | 490 | pwm1 = (smsc47m1_read_value(data, SMSC47M1_REG_PPIN(0)) & 0x05) |
450 | == 0x05; | ||
451 | fan2 = (smsc47m1_read_value(new_client, SMSC47M1_REG_TPIN(1)) & 0x05) | ||
452 | == 0x05; | ||
453 | pwm1 = (smsc47m1_read_value(new_client, SMSC47M1_REG_PPIN(0)) & 0x05) | ||
454 | == 0x04; | 491 | == 0x04; |
455 | pwm2 = (smsc47m1_read_value(new_client, SMSC47M1_REG_PPIN(1)) & 0x05) | 492 | pwm2 = (smsc47m1_read_value(data, SMSC47M1_REG_PPIN(1)) & 0x05) |
456 | == 0x04; | 493 | == 0x04; |
457 | if (!(fan1 || fan2 || pwm1 || pwm2)) { | 494 | if (data->type == smsc47m2) { |
458 | dev_warn(&adapter->dev, "Device at 0x%x is not configured, " | 495 | fan1 = (smsc47m1_read_value(data, SMSC47M2_REG_TPIN1) |
459 | "will not use\n", new_client->addr); | 496 | & 0x0d) == 0x09; |
497 | fan2 = (smsc47m1_read_value(data, SMSC47M2_REG_TPIN2) | ||
498 | & 0x0d) == 0x09; | ||
499 | fan3 = (smsc47m1_read_value(data, SMSC47M2_REG_TPIN3) | ||
500 | & 0x0d) == 0x0d; | ||
501 | pwm3 = (smsc47m1_read_value(data, SMSC47M2_REG_PPIN3) | ||
502 | & 0x0d) == 0x08; | ||
503 | } else { | ||
504 | fan1 = (smsc47m1_read_value(data, SMSC47M1_REG_TPIN(0)) | ||
505 | & 0x05) == 0x05; | ||
506 | fan2 = (smsc47m1_read_value(data, SMSC47M1_REG_TPIN(1)) | ||
507 | & 0x05) == 0x05; | ||
508 | fan3 = 0; | ||
509 | pwm3 = 0; | ||
510 | } | ||
511 | if (!(fan1 || fan2 || fan3 || pwm1 || pwm2 || pwm3)) { | ||
512 | dev_warn(dev, "Device not configured, will not use\n"); | ||
460 | err = -ENODEV; | 513 | err = -ENODEV; |
461 | goto error_free; | 514 | goto error_free; |
462 | } | 515 | } |
463 | 516 | ||
464 | if ((err = i2c_attach_client(new_client))) | ||
465 | goto error_free; | ||
466 | |||
467 | /* Some values (fan min, clock dividers, pwm registers) may be | 517 | /* Some values (fan min, clock dividers, pwm registers) may be |
468 | needed before any update is triggered, so we better read them | 518 | needed before any update is triggered, so we better read them |
469 | at least once here. We don't usually do it that way, but in | 519 | at least once here. We don't usually do it that way, but in |
470 | this particular case, manually reading 5 registers out of 8 | 520 | this particular case, manually reading 5 registers out of 8 |
471 | doesn't make much sense and we're better using the existing | 521 | doesn't make much sense and we're better using the existing |
472 | function. */ | 522 | function. */ |
473 | smsc47m1_update_device(&new_client->dev, 1); | 523 | smsc47m1_update_device(dev, 1); |
474 | 524 | ||
475 | /* Register sysfs hooks */ | 525 | /* Register sysfs hooks */ |
476 | if (fan1) { | 526 | if (fan1) { |
477 | if ((err = device_create_file(&new_client->dev, | 527 | if ((err = device_create_file(dev, |
478 | &dev_attr_fan1_input)) | 528 | &sensor_dev_attr_fan1_input.dev_attr)) |
479 | || (err = device_create_file(&new_client->dev, | 529 | || (err = device_create_file(dev, |
480 | &dev_attr_fan1_min)) | 530 | &sensor_dev_attr_fan1_min.dev_attr)) |
481 | || (err = device_create_file(&new_client->dev, | 531 | || (err = device_create_file(dev, |
482 | &dev_attr_fan1_div))) | 532 | &sensor_dev_attr_fan1_div.dev_attr))) |
483 | goto error_remove_files; | 533 | goto error_remove_files; |
484 | } else | 534 | } else |
485 | dev_dbg(&new_client->dev, "Fan 1 not enabled by hardware, " | 535 | dev_dbg(dev, "Fan 1 not enabled by hardware, skipping\n"); |
486 | "skipping\n"); | ||
487 | 536 | ||
488 | if (fan2) { | 537 | if (fan2) { |
489 | if ((err = device_create_file(&new_client->dev, | 538 | if ((err = device_create_file(dev, |
490 | &dev_attr_fan2_input)) | 539 | &sensor_dev_attr_fan2_input.dev_attr)) |
491 | || (err = device_create_file(&new_client->dev, | 540 | || (err = device_create_file(dev, |
492 | &dev_attr_fan2_min)) | 541 | &sensor_dev_attr_fan2_min.dev_attr)) |
493 | || (err = device_create_file(&new_client->dev, | 542 | || (err = device_create_file(dev, |
494 | &dev_attr_fan2_div))) | 543 | &sensor_dev_attr_fan2_div.dev_attr))) |
495 | goto error_remove_files; | 544 | goto error_remove_files; |
496 | } else | 545 | } else |
497 | dev_dbg(&new_client->dev, "Fan 2 not enabled by hardware, " | 546 | dev_dbg(dev, "Fan 2 not enabled by hardware, skipping\n"); |
498 | "skipping\n"); | 547 | |
548 | if (fan3) { | ||
549 | if ((err = device_create_file(dev, | ||
550 | &sensor_dev_attr_fan3_input.dev_attr)) | ||
551 | || (err = device_create_file(dev, | ||
552 | &sensor_dev_attr_fan3_min.dev_attr)) | ||
553 | || (err = device_create_file(dev, | ||
554 | &sensor_dev_attr_fan3_div.dev_attr))) | ||
555 | goto error_remove_files; | ||
556 | } else | ||
557 | dev_dbg(dev, "Fan 3 not enabled by hardware, skipping\n"); | ||
499 | 558 | ||
500 | if (pwm1) { | 559 | if (pwm1) { |
501 | if ((err = device_create_file(&new_client->dev, | 560 | if ((err = device_create_file(dev, |
502 | &dev_attr_pwm1)) | 561 | &sensor_dev_attr_pwm1.dev_attr)) |
503 | || (err = device_create_file(&new_client->dev, | 562 | || (err = device_create_file(dev, |
504 | &dev_attr_pwm1_enable))) | 563 | &sensor_dev_attr_pwm1_enable.dev_attr))) |
505 | goto error_remove_files; | 564 | goto error_remove_files; |
506 | } else | 565 | } else |
507 | dev_dbg(&new_client->dev, "PWM 1 not enabled by hardware, " | 566 | dev_dbg(dev, "PWM 1 not enabled by hardware, skipping\n"); |
508 | "skipping\n"); | 567 | |
509 | if (pwm2) { | 568 | if (pwm2) { |
510 | if ((err = device_create_file(&new_client->dev, | 569 | if ((err = device_create_file(dev, |
511 | &dev_attr_pwm2)) | 570 | &sensor_dev_attr_pwm2.dev_attr)) |
512 | || (err = device_create_file(&new_client->dev, | 571 | || (err = device_create_file(dev, |
513 | &dev_attr_pwm2_enable))) | 572 | &sensor_dev_attr_pwm2_enable.dev_attr))) |
573 | goto error_remove_files; | ||
574 | } else | ||
575 | dev_dbg(dev, "PWM 2 not enabled by hardware, skipping\n"); | ||
576 | |||
577 | if (pwm3) { | ||
578 | if ((err = device_create_file(dev, | ||
579 | &sensor_dev_attr_pwm3.dev_attr)) | ||
580 | || (err = device_create_file(dev, | ||
581 | &sensor_dev_attr_pwm3_enable.dev_attr))) | ||
514 | goto error_remove_files; | 582 | goto error_remove_files; |
515 | } else | 583 | } else |
516 | dev_dbg(&new_client->dev, "PWM 2 not enabled by hardware, " | 584 | dev_dbg(dev, "PWM 3 not enabled by hardware, skipping\n"); |
517 | "skipping\n"); | ||
518 | 585 | ||
519 | if ((err = device_create_file(&new_client->dev, &dev_attr_alarms))) | 586 | if ((err = device_create_file(dev, &dev_attr_alarms))) |
520 | goto error_remove_files; | 587 | goto error_remove_files; |
521 | 588 | ||
522 | data->class_dev = hwmon_device_register(&new_client->dev); | 589 | data->class_dev = hwmon_device_register(dev); |
523 | if (IS_ERR(data->class_dev)) { | 590 | if (IS_ERR(data->class_dev)) { |
524 | err = PTR_ERR(data->class_dev); | 591 | err = PTR_ERR(data->class_dev); |
525 | goto error_remove_files; | 592 | goto error_remove_files; |
@@ -528,78 +595,71 @@ static int smsc47m1_detect(struct i2c_adapter *adapter) | |||
528 | return 0; | 595 | return 0; |
529 | 596 | ||
530 | error_remove_files: | 597 | error_remove_files: |
531 | sysfs_remove_group(&new_client->dev.kobj, &smsc47m1_group); | 598 | sysfs_remove_group(&dev->kobj, &smsc47m1_group); |
532 | i2c_detach_client(new_client); | ||
533 | error_free: | 599 | error_free: |
534 | kfree(data); | 600 | kfree(data); |
535 | error_release: | 601 | error_release: |
536 | release_region(address, SMSC_EXTENT); | 602 | release_region(res->start, SMSC_EXTENT); |
537 | return err; | 603 | return err; |
538 | } | 604 | } |
539 | 605 | ||
540 | static int smsc47m1_detach_client(struct i2c_client *client) | 606 | static int __devexit smsc47m1_remove(struct platform_device *pdev) |
541 | { | 607 | { |
542 | struct smsc47m1_data *data = i2c_get_clientdata(client); | 608 | struct smsc47m1_data *data = platform_get_drvdata(pdev); |
543 | int err; | 609 | struct resource *res; |
544 | 610 | ||
611 | platform_set_drvdata(pdev, NULL); | ||
545 | hwmon_device_unregister(data->class_dev); | 612 | hwmon_device_unregister(data->class_dev); |
546 | sysfs_remove_group(&client->dev.kobj, &smsc47m1_group); | 613 | sysfs_remove_group(&pdev->dev.kobj, &smsc47m1_group); |
547 | |||
548 | if ((err = i2c_detach_client(client))) | ||
549 | return err; | ||
550 | 614 | ||
551 | release_region(client->addr, SMSC_EXTENT); | 615 | res = platform_get_resource(pdev, IORESOURCE_IO, 0); |
616 | release_region(res->start, SMSC_EXTENT); | ||
552 | kfree(data); | 617 | kfree(data); |
553 | 618 | ||
554 | return 0; | 619 | return 0; |
555 | } | 620 | } |
556 | 621 | ||
557 | static int smsc47m1_read_value(struct i2c_client *client, u8 reg) | ||
558 | { | ||
559 | int res; | ||
560 | |||
561 | mutex_lock(&((struct smsc47m1_data *) i2c_get_clientdata(client))->lock); | ||
562 | res = inb_p(client->addr + reg); | ||
563 | mutex_unlock(&((struct smsc47m1_data *) i2c_get_clientdata(client))->lock); | ||
564 | return res; | ||
565 | } | ||
566 | |||
567 | static void smsc47m1_write_value(struct i2c_client *client, u8 reg, u8 value) | ||
568 | { | ||
569 | mutex_lock(&((struct smsc47m1_data *) i2c_get_clientdata(client))->lock); | ||
570 | outb_p(value, client->addr + reg); | ||
571 | mutex_unlock(&((struct smsc47m1_data *) i2c_get_clientdata(client))->lock); | ||
572 | } | ||
573 | |||
574 | static struct smsc47m1_data *smsc47m1_update_device(struct device *dev, | 622 | static struct smsc47m1_data *smsc47m1_update_device(struct device *dev, |
575 | int init) | 623 | int init) |
576 | { | 624 | { |
577 | struct i2c_client *client = to_i2c_client(dev); | 625 | struct smsc47m1_data *data = dev_get_drvdata(dev); |
578 | struct smsc47m1_data *data = i2c_get_clientdata(client); | ||
579 | 626 | ||
580 | mutex_lock(&data->update_lock); | 627 | mutex_lock(&data->update_lock); |
581 | 628 | ||
582 | if (time_after(jiffies, data->last_updated + HZ + HZ / 2) || init) { | 629 | if (time_after(jiffies, data->last_updated + HZ + HZ / 2) || init) { |
583 | int i; | 630 | int i, fan_nr; |
584 | 631 | fan_nr = data->type == smsc47m2 ? 3 : 2; | |
585 | for (i = 0; i < 2; i++) { | 632 | |
586 | data->fan[i] = smsc47m1_read_value(client, | 633 | for (i = 0; i < fan_nr; i++) { |
587 | SMSC47M1_REG_FAN(i)); | 634 | data->fan[i] = smsc47m1_read_value(data, |
588 | data->fan_preload[i] = smsc47m1_read_value(client, | 635 | SMSC47M1_REG_FAN[i]); |
589 | SMSC47M1_REG_FAN_PRELOAD(i)); | 636 | data->fan_preload[i] = smsc47m1_read_value(data, |
590 | data->pwm[i] = smsc47m1_read_value(client, | 637 | SMSC47M1_REG_FAN_PRELOAD[i]); |
591 | SMSC47M1_REG_PWM(i)); | 638 | data->pwm[i] = smsc47m1_read_value(data, |
639 | SMSC47M1_REG_PWM[i]); | ||
592 | } | 640 | } |
593 | 641 | ||
594 | i = smsc47m1_read_value(client, SMSC47M1_REG_FANDIV); | 642 | i = smsc47m1_read_value(data, SMSC47M1_REG_FANDIV); |
595 | data->fan_div[0] = (i >> 4) & 0x03; | 643 | data->fan_div[0] = (i >> 4) & 0x03; |
596 | data->fan_div[1] = i >> 6; | 644 | data->fan_div[1] = i >> 6; |
597 | 645 | ||
598 | data->alarms = smsc47m1_read_value(client, | 646 | data->alarms = smsc47m1_read_value(data, |
599 | SMSC47M1_REG_ALARM) >> 6; | 647 | SMSC47M1_REG_ALARM) >> 6; |
600 | /* Clear alarms if needed */ | 648 | /* Clear alarms if needed */ |
601 | if (data->alarms) | 649 | if (data->alarms) |
602 | smsc47m1_write_value(client, SMSC47M1_REG_ALARM, 0xC0); | 650 | smsc47m1_write_value(data, SMSC47M1_REG_ALARM, 0xC0); |
651 | |||
652 | if (fan_nr >= 3) { | ||
653 | data->fan_div[2] = (smsc47m1_read_value(data, | ||
654 | SMSC47M2_REG_FANDIV3) >> 4) & 0x03; | ||
655 | data->alarms |= (smsc47m1_read_value(data, | ||
656 | SMSC47M2_REG_ALARM6) & 0x40) >> 4; | ||
657 | /* Clear alarm if needed */ | ||
658 | if (data->alarms & 0x04) | ||
659 | smsc47m1_write_value(data, | ||
660 | SMSC47M2_REG_ALARM6, | ||
661 | 0x40); | ||
662 | } | ||
603 | 663 | ||
604 | data->last_updated = jiffies; | 664 | data->last_updated = jiffies; |
605 | } | 665 | } |
@@ -608,18 +668,86 @@ static struct smsc47m1_data *smsc47m1_update_device(struct device *dev, | |||
608 | return data; | 668 | return data; |
609 | } | 669 | } |
610 | 670 | ||
671 | static int __init smsc47m1_device_add(unsigned short address, | ||
672 | const struct smsc47m1_sio_data *sio_data) | ||
673 | { | ||
674 | struct resource res = { | ||
675 | .start = address, | ||
676 | .end = address + SMSC_EXTENT - 1, | ||
677 | .name = DRVNAME, | ||
678 | .flags = IORESOURCE_IO, | ||
679 | }; | ||
680 | int err; | ||
681 | |||
682 | pdev = platform_device_alloc(DRVNAME, address); | ||
683 | if (!pdev) { | ||
684 | err = -ENOMEM; | ||
685 | printk(KERN_ERR DRVNAME ": Device allocation failed\n"); | ||
686 | goto exit; | ||
687 | } | ||
688 | |||
689 | err = platform_device_add_resources(pdev, &res, 1); | ||
690 | if (err) { | ||
691 | printk(KERN_ERR DRVNAME ": Device resource addition failed " | ||
692 | "(%d)\n", err); | ||
693 | goto exit_device_put; | ||
694 | } | ||
695 | |||
696 | pdev->dev.platform_data = kmalloc(sizeof(struct smsc47m1_sio_data), | ||
697 | GFP_KERNEL); | ||
698 | if (!pdev->dev.platform_data) { | ||
699 | err = -ENOMEM; | ||
700 | printk(KERN_ERR DRVNAME ": Platform data allocation failed\n"); | ||
701 | goto exit_device_put; | ||
702 | } | ||
703 | memcpy(pdev->dev.platform_data, sio_data, | ||
704 | sizeof(struct smsc47m1_sio_data)); | ||
705 | |||
706 | err = platform_device_add(pdev); | ||
707 | if (err) { | ||
708 | printk(KERN_ERR DRVNAME ": Device addition failed (%d)\n", | ||
709 | err); | ||
710 | goto exit_device_put; | ||
711 | } | ||
712 | |||
713 | return 0; | ||
714 | |||
715 | exit_device_put: | ||
716 | platform_device_put(pdev); | ||
717 | exit: | ||
718 | return err; | ||
719 | } | ||
720 | |||
611 | static int __init sm_smsc47m1_init(void) | 721 | static int __init sm_smsc47m1_init(void) |
612 | { | 722 | { |
613 | if (smsc47m1_find(&address)) { | 723 | int err; |
724 | unsigned short address; | ||
725 | struct smsc47m1_sio_data sio_data; | ||
726 | |||
727 | if (smsc47m1_find(&address, &sio_data)) | ||
614 | return -ENODEV; | 728 | return -ENODEV; |
615 | } | ||
616 | 729 | ||
617 | return i2c_isa_add_driver(&smsc47m1_driver); | 730 | err = platform_driver_register(&smsc47m1_driver); |
731 | if (err) | ||
732 | goto exit; | ||
733 | |||
734 | /* Sets global pdev as a side effect */ | ||
735 | err = smsc47m1_device_add(address, &sio_data); | ||
736 | if (err) | ||
737 | goto exit_driver; | ||
738 | |||
739 | return 0; | ||
740 | |||
741 | exit_driver: | ||
742 | platform_driver_unregister(&smsc47m1_driver); | ||
743 | exit: | ||
744 | return err; | ||
618 | } | 745 | } |
619 | 746 | ||
620 | static void __exit sm_smsc47m1_exit(void) | 747 | static void __exit sm_smsc47m1_exit(void) |
621 | { | 748 | { |
622 | i2c_isa_del_driver(&smsc47m1_driver); | 749 | platform_device_unregister(pdev); |
750 | platform_driver_unregister(&smsc47m1_driver); | ||
623 | } | 751 | } |
624 | 752 | ||
625 | MODULE_AUTHOR("Mark D. Studebaker <mdsxyz123@yahoo.com>"); | 753 | MODULE_AUTHOR("Mark D. Studebaker <mdsxyz123@yahoo.com>"); |
diff --git a/drivers/hwmon/smsc47m192.c b/drivers/hwmon/smsc47m192.c index a6833f437395..a012f396f354 100644 --- a/drivers/hwmon/smsc47m192.c +++ b/drivers/hwmon/smsc47m192.c | |||
@@ -1,6 +1,6 @@ | |||
1 | /* | 1 | /* |
2 | smsc47m192.c - Support for hardware monitoring block of | 2 | smsc47m192.c - Support for hardware monitoring block of |
3 | SMSC LPC47M192 and LPC47M997 Super I/O chips | 3 | SMSC LPC47M192 and compatible Super I/O chips |
4 | 4 | ||
5 | Copyright (C) 2006 Hartmut Rick <linux@rick.claranet.de> | 5 | Copyright (C) 2006 Hartmut Rick <linux@rick.claranet.de> |
6 | 6 | ||
@@ -518,7 +518,7 @@ static int smsc47m192_detect(struct i2c_adapter *adapter, int address, | |||
518 | && (i2c_smbus_read_byte_data(client, | 518 | && (i2c_smbus_read_byte_data(client, |
519 | SMSC47M192_REG_VID4) & 0xfe) == 0x80) { | 519 | SMSC47M192_REG_VID4) & 0xfe) == 0x80) { |
520 | dev_info(&adapter->dev, | 520 | dev_info(&adapter->dev, |
521 | "found SMSC47M192 or SMSC47M997, " | 521 | "found SMSC47M192 or compatible, " |
522 | "version 2, stepping A%d\n", version & 0x0f); | 522 | "version 2, stepping A%d\n", version & 0x0f); |
523 | } else { | 523 | } else { |
524 | dev_dbg(&adapter->dev, | 524 | dev_dbg(&adapter->dev, |
diff --git a/drivers/hwmon/vt1211.c b/drivers/hwmon/vt1211.c index 89c23d6add7b..9f3e332c5b7f 100644 --- a/drivers/hwmon/vt1211.c +++ b/drivers/hwmon/vt1211.c | |||
@@ -31,6 +31,7 @@ | |||
31 | #include <linux/hwmon-vid.h> | 31 | #include <linux/hwmon-vid.h> |
32 | #include <linux/err.h> | 32 | #include <linux/err.h> |
33 | #include <linux/mutex.h> | 33 | #include <linux/mutex.h> |
34 | #include <linux/ioport.h> | ||
34 | #include <asm/io.h> | 35 | #include <asm/io.h> |
35 | 36 | ||
36 | static int uch_config = -1; | 37 | static int uch_config = -1; |
@@ -1130,6 +1131,12 @@ static int __devinit vt1211_probe(struct platform_device *pdev) | |||
1130 | } | 1131 | } |
1131 | 1132 | ||
1132 | res = platform_get_resource(pdev, IORESOURCE_IO, 0); | 1133 | res = platform_get_resource(pdev, IORESOURCE_IO, 0); |
1134 | if (!request_region(res->start, res->end - res->start + 1, DRVNAME)) { | ||
1135 | err = -EBUSY; | ||
1136 | dev_err(dev, "Failed to request region 0x%lx-0x%lx\n", | ||
1137 | (unsigned long)res->start, (unsigned long)res->end); | ||
1138 | goto EXIT_KFREE; | ||
1139 | } | ||
1133 | data->addr = res->start; | 1140 | data->addr = res->start; |
1134 | data->name = DRVNAME; | 1141 | data->name = DRVNAME; |
1135 | mutex_init(&data->update_lock); | 1142 | mutex_init(&data->update_lock); |
@@ -1197,6 +1204,8 @@ EXIT_DEV_REMOVE: | |||
1197 | dev_err(dev, "Sysfs interface creation failed (%d)\n", err); | 1204 | dev_err(dev, "Sysfs interface creation failed (%d)\n", err); |
1198 | EXIT_DEV_REMOVE_SILENT: | 1205 | EXIT_DEV_REMOVE_SILENT: |
1199 | vt1211_remove_sysfs(pdev); | 1206 | vt1211_remove_sysfs(pdev); |
1207 | release_region(res->start, res->end - res->start + 1); | ||
1208 | EXIT_KFREE: | ||
1200 | platform_set_drvdata(pdev, NULL); | 1209 | platform_set_drvdata(pdev, NULL); |
1201 | kfree(data); | 1210 | kfree(data); |
1202 | EXIT: | 1211 | EXIT: |
@@ -1206,12 +1215,16 @@ EXIT: | |||
1206 | static int __devexit vt1211_remove(struct platform_device *pdev) | 1215 | static int __devexit vt1211_remove(struct platform_device *pdev) |
1207 | { | 1216 | { |
1208 | struct vt1211_data *data = platform_get_drvdata(pdev); | 1217 | struct vt1211_data *data = platform_get_drvdata(pdev); |
1218 | struct resource *res; | ||
1209 | 1219 | ||
1210 | hwmon_device_unregister(data->class_dev); | 1220 | hwmon_device_unregister(data->class_dev); |
1211 | vt1211_remove_sysfs(pdev); | 1221 | vt1211_remove_sysfs(pdev); |
1212 | platform_set_drvdata(pdev, NULL); | 1222 | platform_set_drvdata(pdev, NULL); |
1213 | kfree(data); | 1223 | kfree(data); |
1214 | 1224 | ||
1225 | res = platform_get_resource(pdev, IORESOURCE_IO, 0); | ||
1226 | release_region(res->start, res->end - res->start + 1); | ||
1227 | |||
1215 | return 0; | 1228 | return 0; |
1216 | } | 1229 | } |
1217 | 1230 | ||
diff --git a/drivers/hwmon/w83627hf.c b/drivers/hwmon/w83627hf.c index d7e240635b3b..a5b774b07cbd 100644 --- a/drivers/hwmon/w83627hf.c +++ b/drivers/hwmon/w83627hf.c | |||
@@ -5,6 +5,7 @@ | |||
5 | Philip Edelbrock <phil@netroedge.com>, | 5 | Philip Edelbrock <phil@netroedge.com>, |
6 | and Mark Studebaker <mdsxyz123@yahoo.com> | 6 | and Mark Studebaker <mdsxyz123@yahoo.com> |
7 | Ported to 2.6 by Bernhard C. Schrenk <clemy@clemy.org> | 7 | Ported to 2.6 by Bernhard C. Schrenk <clemy@clemy.org> |
8 | Copyright (c) 2007 Jean Delvare <khali@linux-fr.org> | ||
8 | 9 | ||
9 | This program is free software; you can redistribute it and/or modify | 10 | 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 | 11 | it under the terms of the GNU General Public License as published by |
@@ -42,15 +43,20 @@ | |||
42 | #include <linux/init.h> | 43 | #include <linux/init.h> |
43 | #include <linux/slab.h> | 44 | #include <linux/slab.h> |
44 | #include <linux/jiffies.h> | 45 | #include <linux/jiffies.h> |
45 | #include <linux/i2c.h> | 46 | #include <linux/platform_device.h> |
46 | #include <linux/i2c-isa.h> | ||
47 | #include <linux/hwmon.h> | 47 | #include <linux/hwmon.h> |
48 | #include <linux/hwmon-vid.h> | 48 | #include <linux/hwmon-vid.h> |
49 | #include <linux/err.h> | 49 | #include <linux/err.h> |
50 | #include <linux/mutex.h> | 50 | #include <linux/mutex.h> |
51 | #include <linux/ioport.h> | ||
51 | #include <asm/io.h> | 52 | #include <asm/io.h> |
52 | #include "lm75.h" | 53 | #include "lm75.h" |
53 | 54 | ||
55 | static struct platform_device *pdev; | ||
56 | |||
57 | #define DRVNAME "w83627hf" | ||
58 | enum chips { w83627hf, w83627thf, w83697hf, w83637hf, w83687thf }; | ||
59 | |||
54 | static u16 force_addr; | 60 | static u16 force_addr; |
55 | module_param(force_addr, ushort, 0); | 61 | module_param(force_addr, ushort, 0); |
56 | MODULE_PARM_DESC(force_addr, | 62 | MODULE_PARM_DESC(force_addr, |
@@ -60,12 +66,6 @@ module_param(force_i2c, byte, 0); | |||
60 | MODULE_PARM_DESC(force_i2c, | 66 | MODULE_PARM_DESC(force_i2c, |
61 | "Initialize the i2c address of the sensors"); | 67 | "Initialize the i2c address of the sensors"); |
62 | 68 | ||
63 | /* The actual ISA address is read from Super-I/O configuration space */ | ||
64 | static unsigned short address; | ||
65 | |||
66 | /* Insmod parameters */ | ||
67 | enum chips { any_chip, w83627hf, w83627thf, w83697hf, w83637hf, w83687thf }; | ||
68 | |||
69 | static int reset; | 69 | static int reset; |
70 | module_param(reset, bool, 0); | 70 | module_param(reset, bool, 0); |
71 | MODULE_PARM_DESC(reset, "Set to one to reset chip on load"); | 71 | MODULE_PARM_DESC(reset, "Set to one to reset chip on load"); |
@@ -156,9 +156,9 @@ superio_exit(void) | |||
156 | #define WINB_REGION_OFFSET 5 | 156 | #define WINB_REGION_OFFSET 5 |
157 | #define WINB_REGION_SIZE 2 | 157 | #define WINB_REGION_SIZE 2 |
158 | 158 | ||
159 | /* Where are the sensors address/data registers relative to the base address */ | 159 | /* Where are the sensors address/data registers relative to the region offset */ |
160 | #define W83781D_ADDR_REG_OFFSET 5 | 160 | #define W83781D_ADDR_REG_OFFSET 0 |
161 | #define W83781D_DATA_REG_OFFSET 6 | 161 | #define W83781D_DATA_REG_OFFSET 1 |
162 | 162 | ||
163 | /* The W83781D registers */ | 163 | /* The W83781D registers */ |
164 | /* The W83782D registers for nr=7,8 are in bank 5 */ | 164 | /* The W83782D registers for nr=7,8 are in bank 5 */ |
@@ -289,7 +289,8 @@ static inline u8 DIV_TO_REG(long val) | |||
289 | /* For each registered chip, we need to keep some data in memory. | 289 | /* For each registered chip, we need to keep some data in memory. |
290 | The structure is dynamically allocated. */ | 290 | The structure is dynamically allocated. */ |
291 | struct w83627hf_data { | 291 | struct w83627hf_data { |
292 | struct i2c_client client; | 292 | unsigned short addr; |
293 | const char *name; | ||
293 | struct class_device *class_dev; | 294 | struct class_device *class_dev; |
294 | struct mutex lock; | 295 | struct mutex lock; |
295 | enum chips type; | 296 | enum chips type; |
@@ -298,9 +299,6 @@ struct w83627hf_data { | |||
298 | char valid; /* !=0 if following fields are valid */ | 299 | char valid; /* !=0 if following fields are valid */ |
299 | unsigned long last_updated; /* In jiffies */ | 300 | unsigned long last_updated; /* In jiffies */ |
300 | 301 | ||
301 | struct i2c_client *lm75; /* for secondary I2C addresses */ | ||
302 | /* pointer to array of 2 subclients */ | ||
303 | |||
304 | u8 in[9]; /* Register value */ | 302 | u8 in[9]; /* Register value */ |
305 | u8 in_max[9]; /* Register value */ | 303 | u8 in_max[9]; /* Register value */ |
306 | u8 in_min[9]; /* Register value */ | 304 | u8 in_min[9]; /* Register value */ |
@@ -327,22 +325,26 @@ struct w83627hf_data { | |||
327 | u8 vrm_ovt; /* Register value, 627THF/637HF/687THF only */ | 325 | u8 vrm_ovt; /* Register value, 627THF/637HF/687THF only */ |
328 | }; | 326 | }; |
329 | 327 | ||
328 | struct w83627hf_sio_data { | ||
329 | enum chips type; | ||
330 | }; | ||
331 | |||
330 | 332 | ||
331 | static int w83627hf_detect(struct i2c_adapter *adapter); | 333 | static int w83627hf_probe(struct platform_device *pdev); |
332 | static int w83627hf_detach_client(struct i2c_client *client); | 334 | static int w83627hf_remove(struct platform_device *pdev); |
333 | 335 | ||
334 | static int w83627hf_read_value(struct i2c_client *client, u16 reg); | 336 | static int w83627hf_read_value(struct w83627hf_data *data, u16 reg); |
335 | static int w83627hf_write_value(struct i2c_client *client, u16 reg, u16 value); | 337 | static int w83627hf_write_value(struct w83627hf_data *data, u16 reg, u16 value); |
336 | static struct w83627hf_data *w83627hf_update_device(struct device *dev); | 338 | static struct w83627hf_data *w83627hf_update_device(struct device *dev); |
337 | static void w83627hf_init_client(struct i2c_client *client); | 339 | static void w83627hf_init_device(struct platform_device *pdev); |
338 | 340 | ||
339 | static struct i2c_driver w83627hf_driver = { | 341 | static struct platform_driver w83627hf_driver = { |
340 | .driver = { | 342 | .driver = { |
341 | .owner = THIS_MODULE, | 343 | .owner = THIS_MODULE, |
342 | .name = "w83627hf", | 344 | .name = DRVNAME, |
343 | }, | 345 | }, |
344 | .attach_adapter = w83627hf_detect, | 346 | .probe = w83627hf_probe, |
345 | .detach_client = w83627hf_detach_client, | 347 | .remove = __devexit_p(w83627hf_remove), |
346 | }; | 348 | }; |
347 | 349 | ||
348 | /* following are the sysfs callback functions */ | 350 | /* following are the sysfs callback functions */ |
@@ -360,15 +362,14 @@ show_in_reg(in_max) | |||
360 | static ssize_t \ | 362 | static ssize_t \ |
361 | store_in_##reg (struct device *dev, const char *buf, size_t count, int nr) \ | 363 | store_in_##reg (struct device *dev, const char *buf, size_t count, int nr) \ |
362 | { \ | 364 | { \ |
363 | struct i2c_client *client = to_i2c_client(dev); \ | 365 | struct w83627hf_data *data = dev_get_drvdata(dev); \ |
364 | struct w83627hf_data *data = i2c_get_clientdata(client); \ | ||
365 | u32 val; \ | 366 | u32 val; \ |
366 | \ | 367 | \ |
367 | val = simple_strtoul(buf, NULL, 10); \ | 368 | val = simple_strtoul(buf, NULL, 10); \ |
368 | \ | 369 | \ |
369 | mutex_lock(&data->update_lock); \ | 370 | mutex_lock(&data->update_lock); \ |
370 | data->in_##reg[nr] = IN_TO_REG(val); \ | 371 | data->in_##reg[nr] = IN_TO_REG(val); \ |
371 | w83627hf_write_value(client, W83781D_REG_IN_##REG(nr), \ | 372 | w83627hf_write_value(data, W83781D_REG_IN_##REG(nr), \ |
372 | data->in_##reg[nr]); \ | 373 | data->in_##reg[nr]); \ |
373 | \ | 374 | \ |
374 | mutex_unlock(&data->update_lock); \ | 375 | mutex_unlock(&data->update_lock); \ |
@@ -452,8 +453,7 @@ static ssize_t show_regs_in_max0(struct device *dev, struct device_attribute *at | |||
452 | static ssize_t store_regs_in_min0(struct device *dev, struct device_attribute *attr, | 453 | static ssize_t store_regs_in_min0(struct device *dev, struct device_attribute *attr, |
453 | const char *buf, size_t count) | 454 | const char *buf, size_t count) |
454 | { | 455 | { |
455 | struct i2c_client *client = to_i2c_client(dev); | 456 | struct w83627hf_data *data = dev_get_drvdata(dev); |
456 | struct w83627hf_data *data = i2c_get_clientdata(client); | ||
457 | u32 val; | 457 | u32 val; |
458 | 458 | ||
459 | val = simple_strtoul(buf, NULL, 10); | 459 | val = simple_strtoul(buf, NULL, 10); |
@@ -472,7 +472,7 @@ static ssize_t store_regs_in_min0(struct device *dev, struct device_attribute *a | |||
472 | /* use VRM8 (standard) calculation */ | 472 | /* use VRM8 (standard) calculation */ |
473 | data->in_min[0] = IN_TO_REG(val); | 473 | data->in_min[0] = IN_TO_REG(val); |
474 | 474 | ||
475 | w83627hf_write_value(client, W83781D_REG_IN_MIN(0), data->in_min[0]); | 475 | w83627hf_write_value(data, W83781D_REG_IN_MIN(0), data->in_min[0]); |
476 | mutex_unlock(&data->update_lock); | 476 | mutex_unlock(&data->update_lock); |
477 | return count; | 477 | return count; |
478 | } | 478 | } |
@@ -480,8 +480,7 @@ static ssize_t store_regs_in_min0(struct device *dev, struct device_attribute *a | |||
480 | static ssize_t store_regs_in_max0(struct device *dev, struct device_attribute *attr, | 480 | static ssize_t store_regs_in_max0(struct device *dev, struct device_attribute *attr, |
481 | const char *buf, size_t count) | 481 | const char *buf, size_t count) |
482 | { | 482 | { |
483 | struct i2c_client *client = to_i2c_client(dev); | 483 | struct w83627hf_data *data = dev_get_drvdata(dev); |
484 | struct w83627hf_data *data = i2c_get_clientdata(client); | ||
485 | u32 val; | 484 | u32 val; |
486 | 485 | ||
487 | val = simple_strtoul(buf, NULL, 10); | 486 | val = simple_strtoul(buf, NULL, 10); |
@@ -500,7 +499,7 @@ static ssize_t store_regs_in_max0(struct device *dev, struct device_attribute *a | |||
500 | /* use VRM8 (standard) calculation */ | 499 | /* use VRM8 (standard) calculation */ |
501 | data->in_max[0] = IN_TO_REG(val); | 500 | data->in_max[0] = IN_TO_REG(val); |
502 | 501 | ||
503 | w83627hf_write_value(client, W83781D_REG_IN_MAX(0), data->in_max[0]); | 502 | w83627hf_write_value(data, W83781D_REG_IN_MAX(0), data->in_max[0]); |
504 | mutex_unlock(&data->update_lock); | 503 | mutex_unlock(&data->update_lock); |
505 | return count; | 504 | return count; |
506 | } | 505 | } |
@@ -525,8 +524,7 @@ show_fan_reg(fan_min); | |||
525 | static ssize_t | 524 | static ssize_t |
526 | store_fan_min(struct device *dev, const char *buf, size_t count, int nr) | 525 | store_fan_min(struct device *dev, const char *buf, size_t count, int nr) |
527 | { | 526 | { |
528 | struct i2c_client *client = to_i2c_client(dev); | 527 | struct w83627hf_data *data = dev_get_drvdata(dev); |
529 | struct w83627hf_data *data = i2c_get_clientdata(client); | ||
530 | u32 val; | 528 | u32 val; |
531 | 529 | ||
532 | val = simple_strtoul(buf, NULL, 10); | 530 | val = simple_strtoul(buf, NULL, 10); |
@@ -534,7 +532,7 @@ store_fan_min(struct device *dev, const char *buf, size_t count, int nr) | |||
534 | mutex_lock(&data->update_lock); | 532 | mutex_lock(&data->update_lock); |
535 | data->fan_min[nr - 1] = | 533 | data->fan_min[nr - 1] = |
536 | FAN_TO_REG(val, DIV_FROM_REG(data->fan_div[nr - 1])); | 534 | FAN_TO_REG(val, DIV_FROM_REG(data->fan_div[nr - 1])); |
537 | w83627hf_write_value(client, W83781D_REG_FAN_MIN(nr), | 535 | w83627hf_write_value(data, W83781D_REG_FAN_MIN(nr), |
538 | data->fan_min[nr - 1]); | 536 | data->fan_min[nr - 1]); |
539 | 537 | ||
540 | mutex_unlock(&data->update_lock); | 538 | mutex_unlock(&data->update_lock); |
@@ -587,8 +585,7 @@ show_temp_reg(temp_max_hyst); | |||
587 | static ssize_t \ | 585 | static ssize_t \ |
588 | store_temp_##reg (struct device *dev, const char *buf, size_t count, int nr) \ | 586 | store_temp_##reg (struct device *dev, const char *buf, size_t count, int nr) \ |
589 | { \ | 587 | { \ |
590 | struct i2c_client *client = to_i2c_client(dev); \ | 588 | struct w83627hf_data *data = dev_get_drvdata(dev); \ |
591 | struct w83627hf_data *data = i2c_get_clientdata(client); \ | ||
592 | u32 val; \ | 589 | u32 val; \ |
593 | \ | 590 | \ |
594 | val = simple_strtoul(buf, NULL, 10); \ | 591 | val = simple_strtoul(buf, NULL, 10); \ |
@@ -597,11 +594,11 @@ store_temp_##reg (struct device *dev, const char *buf, size_t count, int nr) \ | |||
597 | \ | 594 | \ |
598 | if (nr >= 2) { /* TEMP2 and TEMP3 */ \ | 595 | if (nr >= 2) { /* TEMP2 and TEMP3 */ \ |
599 | data->temp_##reg##_add[nr-2] = LM75_TEMP_TO_REG(val); \ | 596 | data->temp_##reg##_add[nr-2] = LM75_TEMP_TO_REG(val); \ |
600 | w83627hf_write_value(client, W83781D_REG_TEMP_##REG(nr), \ | 597 | w83627hf_write_value(data, W83781D_REG_TEMP_##REG(nr), \ |
601 | data->temp_##reg##_add[nr-2]); \ | 598 | data->temp_##reg##_add[nr-2]); \ |
602 | } else { /* TEMP1 */ \ | 599 | } else { /* TEMP1 */ \ |
603 | data->temp_##reg = TEMP_TO_REG(val); \ | 600 | data->temp_##reg = TEMP_TO_REG(val); \ |
604 | w83627hf_write_value(client, W83781D_REG_TEMP_##REG(nr), \ | 601 | w83627hf_write_value(data, W83781D_REG_TEMP_##REG(nr), \ |
605 | data->temp_##reg); \ | 602 | data->temp_##reg); \ |
606 | } \ | 603 | } \ |
607 | \ | 604 | \ |
@@ -659,8 +656,7 @@ show_vrm_reg(struct device *dev, struct device_attribute *attr, char *buf) | |||
659 | static ssize_t | 656 | static ssize_t |
660 | store_vrm_reg(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) | 657 | store_vrm_reg(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) |
661 | { | 658 | { |
662 | struct i2c_client *client = to_i2c_client(dev); | 659 | struct w83627hf_data *data = dev_get_drvdata(dev); |
663 | struct w83627hf_data *data = i2c_get_clientdata(client); | ||
664 | u32 val; | 660 | u32 val; |
665 | 661 | ||
666 | val = simple_strtoul(buf, NULL, 10); | 662 | val = simple_strtoul(buf, NULL, 10); |
@@ -695,8 +691,7 @@ static ssize_t | |||
695 | store_beep_reg(struct device *dev, const char *buf, size_t count, | 691 | store_beep_reg(struct device *dev, const char *buf, size_t count, |
696 | int update_mask) | 692 | int update_mask) |
697 | { | 693 | { |
698 | struct i2c_client *client = to_i2c_client(dev); | 694 | struct w83627hf_data *data = dev_get_drvdata(dev); |
699 | struct w83627hf_data *data = i2c_get_clientdata(client); | ||
700 | u32 val, val2; | 695 | u32 val, val2; |
701 | 696 | ||
702 | val = simple_strtoul(buf, NULL, 10); | 697 | val = simple_strtoul(buf, NULL, 10); |
@@ -705,18 +700,18 @@ store_beep_reg(struct device *dev, const char *buf, size_t count, | |||
705 | 700 | ||
706 | if (update_mask == BEEP_MASK) { /* We are storing beep_mask */ | 701 | if (update_mask == BEEP_MASK) { /* We are storing beep_mask */ |
707 | data->beep_mask = BEEP_MASK_TO_REG(val); | 702 | data->beep_mask = BEEP_MASK_TO_REG(val); |
708 | w83627hf_write_value(client, W83781D_REG_BEEP_INTS1, | 703 | w83627hf_write_value(data, W83781D_REG_BEEP_INTS1, |
709 | data->beep_mask & 0xff); | 704 | data->beep_mask & 0xff); |
710 | w83627hf_write_value(client, W83781D_REG_BEEP_INTS3, | 705 | w83627hf_write_value(data, W83781D_REG_BEEP_INTS3, |
711 | ((data->beep_mask) >> 16) & 0xff); | 706 | ((data->beep_mask) >> 16) & 0xff); |
712 | val2 = (data->beep_mask >> 8) & 0x7f; | 707 | val2 = (data->beep_mask >> 8) & 0x7f; |
713 | } else { /* We are storing beep_enable */ | 708 | } else { /* We are storing beep_enable */ |
714 | val2 = | 709 | val2 = |
715 | w83627hf_read_value(client, W83781D_REG_BEEP_INTS2) & 0x7f; | 710 | w83627hf_read_value(data, W83781D_REG_BEEP_INTS2) & 0x7f; |
716 | data->beep_enable = BEEP_ENABLE_TO_REG(val); | 711 | data->beep_enable = BEEP_ENABLE_TO_REG(val); |
717 | } | 712 | } |
718 | 713 | ||
719 | w83627hf_write_value(client, W83781D_REG_BEEP_INTS2, | 714 | w83627hf_write_value(data, W83781D_REG_BEEP_INTS2, |
720 | val2 | data->beep_enable << 7); | 715 | val2 | data->beep_enable << 7); |
721 | 716 | ||
722 | mutex_unlock(&data->update_lock); | 717 | mutex_unlock(&data->update_lock); |
@@ -754,8 +749,7 @@ show_fan_div_reg(struct device *dev, char *buf, int nr) | |||
754 | static ssize_t | 749 | static ssize_t |
755 | store_fan_div_reg(struct device *dev, const char *buf, size_t count, int nr) | 750 | store_fan_div_reg(struct device *dev, const char *buf, size_t count, int nr) |
756 | { | 751 | { |
757 | struct i2c_client *client = to_i2c_client(dev); | 752 | struct w83627hf_data *data = dev_get_drvdata(dev); |
758 | struct w83627hf_data *data = i2c_get_clientdata(client); | ||
759 | unsigned long min; | 753 | unsigned long min; |
760 | u8 reg; | 754 | u8 reg; |
761 | unsigned long val = simple_strtoul(buf, NULL, 10); | 755 | unsigned long val = simple_strtoul(buf, NULL, 10); |
@@ -768,19 +762,19 @@ store_fan_div_reg(struct device *dev, const char *buf, size_t count, int nr) | |||
768 | 762 | ||
769 | data->fan_div[nr] = DIV_TO_REG(val); | 763 | data->fan_div[nr] = DIV_TO_REG(val); |
770 | 764 | ||
771 | reg = (w83627hf_read_value(client, nr==2 ? W83781D_REG_PIN : W83781D_REG_VID_FANDIV) | 765 | reg = (w83627hf_read_value(data, nr==2 ? W83781D_REG_PIN : W83781D_REG_VID_FANDIV) |
772 | & (nr==0 ? 0xcf : 0x3f)) | 766 | & (nr==0 ? 0xcf : 0x3f)) |
773 | | ((data->fan_div[nr] & 0x03) << (nr==0 ? 4 : 6)); | 767 | | ((data->fan_div[nr] & 0x03) << (nr==0 ? 4 : 6)); |
774 | w83627hf_write_value(client, nr==2 ? W83781D_REG_PIN : W83781D_REG_VID_FANDIV, reg); | 768 | w83627hf_write_value(data, nr==2 ? W83781D_REG_PIN : W83781D_REG_VID_FANDIV, reg); |
775 | 769 | ||
776 | reg = (w83627hf_read_value(client, W83781D_REG_VBAT) | 770 | reg = (w83627hf_read_value(data, W83781D_REG_VBAT) |
777 | & ~(1 << (5 + nr))) | 771 | & ~(1 << (5 + nr))) |
778 | | ((data->fan_div[nr] & 0x04) << (3 + nr)); | 772 | | ((data->fan_div[nr] & 0x04) << (3 + nr)); |
779 | w83627hf_write_value(client, W83781D_REG_VBAT, reg); | 773 | w83627hf_write_value(data, W83781D_REG_VBAT, reg); |
780 | 774 | ||
781 | /* Restore fan_min */ | 775 | /* Restore fan_min */ |
782 | data->fan_min[nr] = FAN_TO_REG(min, DIV_FROM_REG(data->fan_div[nr])); | 776 | data->fan_min[nr] = FAN_TO_REG(min, DIV_FROM_REG(data->fan_div[nr])); |
783 | w83627hf_write_value(client, W83781D_REG_FAN_MIN(nr+1), data->fan_min[nr]); | 777 | w83627hf_write_value(data, W83781D_REG_FAN_MIN(nr+1), data->fan_min[nr]); |
784 | 778 | ||
785 | mutex_unlock(&data->update_lock); | 779 | mutex_unlock(&data->update_lock); |
786 | return count; | 780 | return count; |
@@ -814,8 +808,7 @@ show_pwm_reg(struct device *dev, char *buf, int nr) | |||
814 | static ssize_t | 808 | static ssize_t |
815 | store_pwm_reg(struct device *dev, const char *buf, size_t count, int nr) | 809 | store_pwm_reg(struct device *dev, const char *buf, size_t count, int nr) |
816 | { | 810 | { |
817 | struct i2c_client *client = to_i2c_client(dev); | 811 | struct w83627hf_data *data = dev_get_drvdata(dev); |
818 | struct w83627hf_data *data = i2c_get_clientdata(client); | ||
819 | u32 val; | 812 | u32 val; |
820 | 813 | ||
821 | val = simple_strtoul(buf, NULL, 10); | 814 | val = simple_strtoul(buf, NULL, 10); |
@@ -825,14 +818,14 @@ store_pwm_reg(struct device *dev, const char *buf, size_t count, int nr) | |||
825 | if (data->type == w83627thf) { | 818 | if (data->type == w83627thf) { |
826 | /* bits 0-3 are reserved in 627THF */ | 819 | /* bits 0-3 are reserved in 627THF */ |
827 | data->pwm[nr - 1] = PWM_TO_REG(val) & 0xf0; | 820 | data->pwm[nr - 1] = PWM_TO_REG(val) & 0xf0; |
828 | w83627hf_write_value(client, | 821 | w83627hf_write_value(data, |
829 | W836X7HF_REG_PWM(data->type, nr), | 822 | W836X7HF_REG_PWM(data->type, nr), |
830 | data->pwm[nr - 1] | | 823 | data->pwm[nr - 1] | |
831 | (w83627hf_read_value(client, | 824 | (w83627hf_read_value(data, |
832 | W836X7HF_REG_PWM(data->type, nr)) & 0x0f)); | 825 | W836X7HF_REG_PWM(data->type, nr)) & 0x0f)); |
833 | } else { | 826 | } else { |
834 | data->pwm[nr - 1] = PWM_TO_REG(val); | 827 | data->pwm[nr - 1] = PWM_TO_REG(val); |
835 | w83627hf_write_value(client, | 828 | w83627hf_write_value(data, |
836 | W836X7HF_REG_PWM(data->type, nr), | 829 | W836X7HF_REG_PWM(data->type, nr), |
837 | data->pwm[nr - 1]); | 830 | data->pwm[nr - 1]); |
838 | } | 831 | } |
@@ -868,8 +861,7 @@ show_sensor_reg(struct device *dev, char *buf, int nr) | |||
868 | static ssize_t | 861 | static ssize_t |
869 | store_sensor_reg(struct device *dev, const char *buf, size_t count, int nr) | 862 | store_sensor_reg(struct device *dev, const char *buf, size_t count, int nr) |
870 | { | 863 | { |
871 | struct i2c_client *client = to_i2c_client(dev); | 864 | struct w83627hf_data *data = dev_get_drvdata(dev); |
872 | struct w83627hf_data *data = i2c_get_clientdata(client); | ||
873 | u32 val, tmp; | 865 | u32 val, tmp; |
874 | 866 | ||
875 | val = simple_strtoul(buf, NULL, 10); | 867 | val = simple_strtoul(buf, NULL, 10); |
@@ -878,31 +870,31 @@ store_sensor_reg(struct device *dev, const char *buf, size_t count, int nr) | |||
878 | 870 | ||
879 | switch (val) { | 871 | switch (val) { |
880 | case 1: /* PII/Celeron diode */ | 872 | case 1: /* PII/Celeron diode */ |
881 | tmp = w83627hf_read_value(client, W83781D_REG_SCFG1); | 873 | tmp = w83627hf_read_value(data, W83781D_REG_SCFG1); |
882 | w83627hf_write_value(client, W83781D_REG_SCFG1, | 874 | w83627hf_write_value(data, W83781D_REG_SCFG1, |
883 | tmp | BIT_SCFG1[nr - 1]); | 875 | tmp | BIT_SCFG1[nr - 1]); |
884 | tmp = w83627hf_read_value(client, W83781D_REG_SCFG2); | 876 | tmp = w83627hf_read_value(data, W83781D_REG_SCFG2); |
885 | w83627hf_write_value(client, W83781D_REG_SCFG2, | 877 | w83627hf_write_value(data, W83781D_REG_SCFG2, |
886 | tmp | BIT_SCFG2[nr - 1]); | 878 | tmp | BIT_SCFG2[nr - 1]); |
887 | data->sens[nr - 1] = val; | 879 | data->sens[nr - 1] = val; |
888 | break; | 880 | break; |
889 | case 2: /* 3904 */ | 881 | case 2: /* 3904 */ |
890 | tmp = w83627hf_read_value(client, W83781D_REG_SCFG1); | 882 | tmp = w83627hf_read_value(data, W83781D_REG_SCFG1); |
891 | w83627hf_write_value(client, W83781D_REG_SCFG1, | 883 | w83627hf_write_value(data, W83781D_REG_SCFG1, |
892 | tmp | BIT_SCFG1[nr - 1]); | 884 | tmp | BIT_SCFG1[nr - 1]); |
893 | tmp = w83627hf_read_value(client, W83781D_REG_SCFG2); | 885 | tmp = w83627hf_read_value(data, W83781D_REG_SCFG2); |
894 | w83627hf_write_value(client, W83781D_REG_SCFG2, | 886 | w83627hf_write_value(data, W83781D_REG_SCFG2, |
895 | tmp & ~BIT_SCFG2[nr - 1]); | 887 | tmp & ~BIT_SCFG2[nr - 1]); |
896 | data->sens[nr - 1] = val; | 888 | data->sens[nr - 1] = val; |
897 | break; | 889 | break; |
898 | case W83781D_DEFAULT_BETA: /* thermistor */ | 890 | case W83781D_DEFAULT_BETA: /* thermistor */ |
899 | tmp = w83627hf_read_value(client, W83781D_REG_SCFG1); | 891 | tmp = w83627hf_read_value(data, W83781D_REG_SCFG1); |
900 | w83627hf_write_value(client, W83781D_REG_SCFG1, | 892 | w83627hf_write_value(data, W83781D_REG_SCFG1, |
901 | tmp & ~BIT_SCFG1[nr - 1]); | 893 | tmp & ~BIT_SCFG1[nr - 1]); |
902 | data->sens[nr - 1] = val; | 894 | data->sens[nr - 1] = val; |
903 | break; | 895 | break; |
904 | default: | 896 | default: |
905 | dev_err(&client->dev, | 897 | dev_err(dev, |
906 | "Invalid sensor type %ld; must be 1, 2, or %d\n", | 898 | "Invalid sensor type %ld; must be 1, 2, or %d\n", |
907 | (long) val, W83781D_DEFAULT_BETA); | 899 | (long) val, W83781D_DEFAULT_BETA); |
908 | break; | 900 | break; |
@@ -929,35 +921,85 @@ sysfs_sensor(1); | |||
929 | sysfs_sensor(2); | 921 | sysfs_sensor(2); |
930 | sysfs_sensor(3); | 922 | sysfs_sensor(3); |
931 | 923 | ||
932 | static int __init w83627hf_find(int sioaddr, unsigned short *addr) | 924 | static ssize_t show_name(struct device *dev, struct device_attribute |
925 | *devattr, char *buf) | ||
926 | { | ||
927 | struct w83627hf_data *data = dev_get_drvdata(dev); | ||
928 | |||
929 | return sprintf(buf, "%s\n", data->name); | ||
930 | } | ||
931 | static DEVICE_ATTR(name, S_IRUGO, show_name, NULL); | ||
932 | |||
933 | static int __init w83627hf_find(int sioaddr, unsigned short *addr, | ||
934 | struct w83627hf_sio_data *sio_data) | ||
933 | { | 935 | { |
936 | int err = -ENODEV; | ||
934 | u16 val; | 937 | u16 val; |
935 | 938 | ||
939 | static const __initdata char *names[] = { | ||
940 | "W83627HF", | ||
941 | "W83627THF", | ||
942 | "W83697HF", | ||
943 | "W83637HF", | ||
944 | "W83687THF", | ||
945 | }; | ||
946 | |||
936 | REG = sioaddr; | 947 | REG = sioaddr; |
937 | VAL = sioaddr + 1; | 948 | VAL = sioaddr + 1; |
938 | 949 | ||
939 | superio_enter(); | 950 | superio_enter(); |
940 | val= superio_inb(DEVID); | 951 | val= superio_inb(DEVID); |
941 | if(val != W627_DEVID && | 952 | switch (val) { |
942 | val != W627THF_DEVID && | 953 | case W627_DEVID: |
943 | val != W697_DEVID && | 954 | sio_data->type = w83627hf; |
944 | val != W637_DEVID && | 955 | break; |
945 | val != W687THF_DEVID) { | 956 | case W627THF_DEVID: |
946 | superio_exit(); | 957 | sio_data->type = w83627thf; |
947 | return -ENODEV; | 958 | break; |
959 | case W697_DEVID: | ||
960 | sio_data->type = w83697hf; | ||
961 | break; | ||
962 | case W637_DEVID: | ||
963 | sio_data->type = w83637hf; | ||
964 | break; | ||
965 | case W687THF_DEVID: | ||
966 | sio_data->type = w83687thf; | ||
967 | break; | ||
968 | default: | ||
969 | pr_debug(DRVNAME ": Unsupported chip (DEVID=0x%x)\n", val); | ||
970 | goto exit; | ||
948 | } | 971 | } |
949 | 972 | ||
950 | superio_select(W83627HF_LD_HWM); | 973 | superio_select(W83627HF_LD_HWM); |
974 | force_addr &= WINB_ALIGNMENT; | ||
975 | if (force_addr) { | ||
976 | printk(KERN_WARNING DRVNAME ": Forcing address 0x%x\n", | ||
977 | force_addr); | ||
978 | superio_outb(WINB_BASE_REG, force_addr >> 8); | ||
979 | superio_outb(WINB_BASE_REG + 1, force_addr & 0xff); | ||
980 | } | ||
951 | val = (superio_inb(WINB_BASE_REG) << 8) | | 981 | val = (superio_inb(WINB_BASE_REG) << 8) | |
952 | superio_inb(WINB_BASE_REG + 1); | 982 | superio_inb(WINB_BASE_REG + 1); |
953 | *addr = val & WINB_ALIGNMENT; | 983 | *addr = val & WINB_ALIGNMENT; |
954 | if (*addr == 0 && force_addr == 0) { | 984 | if (*addr == 0) { |
955 | superio_exit(); | 985 | printk(KERN_WARNING DRVNAME ": Base address not set, " |
956 | return -ENODEV; | 986 | "skipping\n"); |
987 | goto exit; | ||
957 | } | 988 | } |
958 | 989 | ||
990 | val = superio_inb(WINB_ACT_REG); | ||
991 | if (!(val & 0x01)) { | ||
992 | printk(KERN_WARNING DRVNAME ": Enabling HWM logical device\n"); | ||
993 | superio_outb(WINB_ACT_REG, val | 0x01); | ||
994 | } | ||
995 | |||
996 | err = 0; | ||
997 | pr_info(DRVNAME ": Found %s chip at %#x\n", | ||
998 | names[sio_data->type], *addr); | ||
999 | |||
1000 | exit: | ||
959 | superio_exit(); | 1001 | superio_exit(); |
960 | return 0; | 1002 | return err; |
961 | } | 1003 | } |
962 | 1004 | ||
963 | static struct attribute *w83627hf_attributes[] = { | 1005 | static struct attribute *w83627hf_attributes[] = { |
@@ -1003,6 +1045,7 @@ static struct attribute *w83627hf_attributes[] = { | |||
1003 | &dev_attr_pwm1.attr, | 1045 | &dev_attr_pwm1.attr, |
1004 | &dev_attr_pwm2.attr, | 1046 | &dev_attr_pwm2.attr, |
1005 | 1047 | ||
1048 | &dev_attr_name.attr, | ||
1006 | NULL | 1049 | NULL |
1007 | }; | 1050 | }; |
1008 | 1051 | ||
@@ -1039,161 +1082,92 @@ static const struct attribute_group w83627hf_group_opt = { | |||
1039 | .attrs = w83627hf_attributes_opt, | 1082 | .attrs = w83627hf_attributes_opt, |
1040 | }; | 1083 | }; |
1041 | 1084 | ||
1042 | static int w83627hf_detect(struct i2c_adapter *adapter) | 1085 | static int __devinit w83627hf_probe(struct platform_device *pdev) |
1043 | { | 1086 | { |
1044 | int val, kind; | 1087 | struct device *dev = &pdev->dev; |
1045 | struct i2c_client *new_client; | 1088 | struct w83627hf_sio_data *sio_data = dev->platform_data; |
1046 | struct w83627hf_data *data; | 1089 | struct w83627hf_data *data; |
1047 | int err = 0; | 1090 | struct resource *res; |
1048 | const char *client_name = ""; | 1091 | int err; |
1049 | |||
1050 | if(force_addr) | ||
1051 | address = force_addr & WINB_ALIGNMENT; | ||
1052 | 1092 | ||
1053 | if (!request_region(address + WINB_REGION_OFFSET, WINB_REGION_SIZE, | 1093 | static const char *names[] = { |
1054 | w83627hf_driver.driver.name)) { | 1094 | "w83627hf", |
1095 | "w83627thf", | ||
1096 | "w83697hf", | ||
1097 | "w83637hf", | ||
1098 | "w83687thf", | ||
1099 | }; | ||
1100 | |||
1101 | res = platform_get_resource(pdev, IORESOURCE_IO, 0); | ||
1102 | if (!request_region(res->start, WINB_REGION_SIZE, DRVNAME)) { | ||
1103 | dev_err(dev, "Failed to request region 0x%lx-0x%lx\n", | ||
1104 | (unsigned long)res->start, | ||
1105 | (unsigned long)(res->start + WINB_REGION_SIZE - 1)); | ||
1055 | err = -EBUSY; | 1106 | err = -EBUSY; |
1056 | goto ERROR0; | 1107 | goto ERROR0; |
1057 | } | 1108 | } |
1058 | 1109 | ||
1059 | if(force_addr) { | ||
1060 | printk("w83627hf.o: forcing ISA address 0x%04X\n", address); | ||
1061 | superio_enter(); | ||
1062 | superio_select(W83627HF_LD_HWM); | ||
1063 | superio_outb(WINB_BASE_REG, address >> 8); | ||
1064 | superio_outb(WINB_BASE_REG+1, address & 0xff); | ||
1065 | superio_exit(); | ||
1066 | } | ||
1067 | |||
1068 | superio_enter(); | ||
1069 | val= superio_inb(DEVID); | ||
1070 | if(val == W627_DEVID) | ||
1071 | kind = w83627hf; | ||
1072 | else if(val == W697_DEVID) | ||
1073 | kind = w83697hf; | ||
1074 | else if(val == W627THF_DEVID) | ||
1075 | kind = w83627thf; | ||
1076 | else if(val == W637_DEVID) | ||
1077 | kind = w83637hf; | ||
1078 | else if (val == W687THF_DEVID) | ||
1079 | kind = w83687thf; | ||
1080 | else { | ||
1081 | dev_info(&adapter->dev, | ||
1082 | "Unsupported chip (dev_id=0x%02X).\n", val); | ||
1083 | goto ERROR1; | ||
1084 | } | ||
1085 | |||
1086 | superio_select(W83627HF_LD_HWM); | ||
1087 | if((val = 0x01 & superio_inb(WINB_ACT_REG)) == 0) | ||
1088 | superio_outb(WINB_ACT_REG, 1); | ||
1089 | superio_exit(); | ||
1090 | |||
1091 | /* OK. For now, we presume we have a valid client. We now create the | ||
1092 | client structure, even though we cannot fill it completely yet. | ||
1093 | But it allows us to access w83627hf_{read,write}_value. */ | ||
1094 | |||
1095 | if (!(data = kzalloc(sizeof(struct w83627hf_data), GFP_KERNEL))) { | 1110 | if (!(data = kzalloc(sizeof(struct w83627hf_data), GFP_KERNEL))) { |
1096 | err = -ENOMEM; | 1111 | err = -ENOMEM; |
1097 | goto ERROR1; | 1112 | goto ERROR1; |
1098 | } | 1113 | } |
1099 | 1114 | data->addr = res->start; | |
1100 | new_client = &data->client; | 1115 | data->type = sio_data->type; |
1101 | i2c_set_clientdata(new_client, data); | 1116 | data->name = names[sio_data->type]; |
1102 | new_client->addr = address; | ||
1103 | mutex_init(&data->lock); | 1117 | mutex_init(&data->lock); |
1104 | new_client->adapter = adapter; | ||
1105 | new_client->driver = &w83627hf_driver; | ||
1106 | new_client->flags = 0; | ||
1107 | |||
1108 | |||
1109 | if (kind == w83627hf) { | ||
1110 | client_name = "w83627hf"; | ||
1111 | } else if (kind == w83627thf) { | ||
1112 | client_name = "w83627thf"; | ||
1113 | } else if (kind == w83697hf) { | ||
1114 | client_name = "w83697hf"; | ||
1115 | } else if (kind == w83637hf) { | ||
1116 | client_name = "w83637hf"; | ||
1117 | } else if (kind == w83687thf) { | ||
1118 | client_name = "w83687thf"; | ||
1119 | } | ||
1120 | |||
1121 | /* Fill in the remaining client fields and put into the global list */ | ||
1122 | strlcpy(new_client->name, client_name, I2C_NAME_SIZE); | ||
1123 | data->type = kind; | ||
1124 | data->valid = 0; | ||
1125 | mutex_init(&data->update_lock); | 1118 | mutex_init(&data->update_lock); |
1126 | 1119 | platform_set_drvdata(pdev, data); | |
1127 | /* Tell the I2C layer a new client has arrived */ | ||
1128 | if ((err = i2c_attach_client(new_client))) | ||
1129 | goto ERROR2; | ||
1130 | |||
1131 | data->lm75 = NULL; | ||
1132 | 1120 | ||
1133 | /* Initialize the chip */ | 1121 | /* Initialize the chip */ |
1134 | w83627hf_init_client(new_client); | 1122 | w83627hf_init_device(pdev); |
1135 | 1123 | ||
1136 | /* A few vars need to be filled upon startup */ | 1124 | /* A few vars need to be filled upon startup */ |
1137 | data->fan_min[0] = w83627hf_read_value(new_client, W83781D_REG_FAN_MIN(1)); | 1125 | data->fan_min[0] = w83627hf_read_value(data, W83781D_REG_FAN_MIN(1)); |
1138 | data->fan_min[1] = w83627hf_read_value(new_client, W83781D_REG_FAN_MIN(2)); | 1126 | data->fan_min[1] = w83627hf_read_value(data, W83781D_REG_FAN_MIN(2)); |
1139 | data->fan_min[2] = w83627hf_read_value(new_client, W83781D_REG_FAN_MIN(3)); | 1127 | data->fan_min[2] = w83627hf_read_value(data, W83781D_REG_FAN_MIN(3)); |
1140 | 1128 | ||
1141 | /* Register common device attributes */ | 1129 | /* Register common device attributes */ |
1142 | if ((err = sysfs_create_group(&new_client->dev.kobj, &w83627hf_group))) | 1130 | if ((err = sysfs_create_group(&dev->kobj, &w83627hf_group))) |
1143 | goto ERROR3; | 1131 | goto ERROR3; |
1144 | 1132 | ||
1145 | /* Register chip-specific device attributes */ | 1133 | /* Register chip-specific device attributes */ |
1146 | if (kind == w83627hf || kind == w83697hf) | 1134 | if (data->type == w83627hf || data->type == w83697hf) |
1147 | if ((err = device_create_file(&new_client->dev, | 1135 | if ((err = device_create_file(dev, &dev_attr_in5_input)) |
1148 | &dev_attr_in5_input)) | 1136 | || (err = device_create_file(dev, &dev_attr_in5_min)) |
1149 | || (err = device_create_file(&new_client->dev, | 1137 | || (err = device_create_file(dev, &dev_attr_in5_max)) |
1150 | &dev_attr_in5_min)) | 1138 | || (err = device_create_file(dev, &dev_attr_in6_input)) |
1151 | || (err = device_create_file(&new_client->dev, | 1139 | || (err = device_create_file(dev, &dev_attr_in6_min)) |
1152 | &dev_attr_in5_max)) | 1140 | || (err = device_create_file(dev, &dev_attr_in6_max))) |
1153 | || (err = device_create_file(&new_client->dev, | ||
1154 | &dev_attr_in6_input)) | ||
1155 | || (err = device_create_file(&new_client->dev, | ||
1156 | &dev_attr_in6_min)) | ||
1157 | || (err = device_create_file(&new_client->dev, | ||
1158 | &dev_attr_in6_max))) | ||
1159 | goto ERROR4; | 1141 | goto ERROR4; |
1160 | 1142 | ||
1161 | if (kind != w83697hf) | 1143 | if (data->type != w83697hf) |
1162 | if ((err = device_create_file(&new_client->dev, | 1144 | if ((err = device_create_file(dev, &dev_attr_in1_input)) |
1163 | &dev_attr_in1_input)) | 1145 | || (err = device_create_file(dev, &dev_attr_in1_min)) |
1164 | || (err = device_create_file(&new_client->dev, | 1146 | || (err = device_create_file(dev, &dev_attr_in1_max)) |
1165 | &dev_attr_in1_min)) | 1147 | || (err = device_create_file(dev, &dev_attr_fan3_input)) |
1166 | || (err = device_create_file(&new_client->dev, | 1148 | || (err = device_create_file(dev, &dev_attr_fan3_min)) |
1167 | &dev_attr_in1_max)) | 1149 | || (err = device_create_file(dev, &dev_attr_fan3_div)) |
1168 | || (err = device_create_file(&new_client->dev, | 1150 | || (err = device_create_file(dev, &dev_attr_temp3_input)) |
1169 | &dev_attr_fan3_input)) | 1151 | || (err = device_create_file(dev, &dev_attr_temp3_max)) |
1170 | || (err = device_create_file(&new_client->dev, | 1152 | || (err = device_create_file(dev, &dev_attr_temp3_max_hyst)) |
1171 | &dev_attr_fan3_min)) | 1153 | || (err = device_create_file(dev, &dev_attr_temp3_type))) |
1172 | || (err = device_create_file(&new_client->dev, | ||
1173 | &dev_attr_fan3_div)) | ||
1174 | || (err = device_create_file(&new_client->dev, | ||
1175 | &dev_attr_temp3_input)) | ||
1176 | || (err = device_create_file(&new_client->dev, | ||
1177 | &dev_attr_temp3_max)) | ||
1178 | || (err = device_create_file(&new_client->dev, | ||
1179 | &dev_attr_temp3_max_hyst)) | ||
1180 | || (err = device_create_file(&new_client->dev, | ||
1181 | &dev_attr_temp3_type))) | ||
1182 | goto ERROR4; | 1154 | goto ERROR4; |
1183 | 1155 | ||
1184 | if (kind != w83697hf && data->vid != 0xff) | 1156 | if (data->type != w83697hf && data->vid != 0xff) { |
1185 | if ((err = device_create_file(&new_client->dev, | 1157 | /* Convert VID to voltage based on VRM */ |
1186 | &dev_attr_cpu0_vid)) | 1158 | data->vrm = vid_which_vrm(); |
1187 | || (err = device_create_file(&new_client->dev, | 1159 | |
1188 | &dev_attr_vrm))) | 1160 | if ((err = device_create_file(dev, &dev_attr_cpu0_vid)) |
1161 | || (err = device_create_file(dev, &dev_attr_vrm))) | ||
1189 | goto ERROR4; | 1162 | goto ERROR4; |
1163 | } | ||
1190 | 1164 | ||
1191 | if (kind == w83627thf || kind == w83637hf || kind == w83687thf) | 1165 | if (data->type == w83627thf || data->type == w83637hf |
1192 | if ((err = device_create_file(&new_client->dev, | 1166 | || data->type == w83687thf) |
1193 | &dev_attr_pwm3))) | 1167 | if ((err = device_create_file(dev, &dev_attr_pwm3))) |
1194 | goto ERROR4; | 1168 | goto ERROR4; |
1195 | 1169 | ||
1196 | data->class_dev = hwmon_device_register(&new_client->dev); | 1170 | data->class_dev = hwmon_device_register(dev); |
1197 | if (IS_ERR(data->class_dev)) { | 1171 | if (IS_ERR(data->class_dev)) { |
1198 | err = PTR_ERR(data->class_dev); | 1172 | err = PTR_ERR(data->class_dev); |
1199 | goto ERROR4; | 1173 | goto ERROR4; |
@@ -1202,47 +1176,37 @@ static int w83627hf_detect(struct i2c_adapter *adapter) | |||
1202 | return 0; | 1176 | return 0; |
1203 | 1177 | ||
1204 | ERROR4: | 1178 | ERROR4: |
1205 | sysfs_remove_group(&new_client->dev.kobj, &w83627hf_group); | 1179 | sysfs_remove_group(&dev->kobj, &w83627hf_group); |
1206 | sysfs_remove_group(&new_client->dev.kobj, &w83627hf_group_opt); | 1180 | sysfs_remove_group(&dev->kobj, &w83627hf_group_opt); |
1207 | ERROR3: | 1181 | ERROR3: |
1208 | i2c_detach_client(new_client); | ||
1209 | ERROR2: | ||
1210 | kfree(data); | 1182 | kfree(data); |
1211 | ERROR1: | 1183 | ERROR1: |
1212 | release_region(address + WINB_REGION_OFFSET, WINB_REGION_SIZE); | 1184 | release_region(res->start, WINB_REGION_SIZE); |
1213 | ERROR0: | 1185 | ERROR0: |
1214 | return err; | 1186 | return err; |
1215 | } | 1187 | } |
1216 | 1188 | ||
1217 | static int w83627hf_detach_client(struct i2c_client *client) | 1189 | static int __devexit w83627hf_remove(struct platform_device *pdev) |
1218 | { | 1190 | { |
1219 | struct w83627hf_data *data = i2c_get_clientdata(client); | 1191 | struct w83627hf_data *data = platform_get_drvdata(pdev); |
1220 | int err; | 1192 | struct resource *res; |
1221 | 1193 | ||
1194 | platform_set_drvdata(pdev, NULL); | ||
1222 | hwmon_device_unregister(data->class_dev); | 1195 | hwmon_device_unregister(data->class_dev); |
1223 | 1196 | ||
1224 | sysfs_remove_group(&client->dev.kobj, &w83627hf_group); | 1197 | sysfs_remove_group(&pdev->dev.kobj, &w83627hf_group); |
1225 | sysfs_remove_group(&client->dev.kobj, &w83627hf_group_opt); | 1198 | sysfs_remove_group(&pdev->dev.kobj, &w83627hf_group_opt); |
1226 | |||
1227 | if ((err = i2c_detach_client(client))) | ||
1228 | return err; | ||
1229 | |||
1230 | release_region(client->addr + WINB_REGION_OFFSET, WINB_REGION_SIZE); | ||
1231 | kfree(data); | 1199 | kfree(data); |
1232 | 1200 | ||
1201 | res = platform_get_resource(pdev, IORESOURCE_IO, 0); | ||
1202 | release_region(res->start, WINB_REGION_SIZE); | ||
1203 | |||
1233 | return 0; | 1204 | return 0; |
1234 | } | 1205 | } |
1235 | 1206 | ||
1236 | 1207 | ||
1237 | /* | 1208 | static int w83627hf_read_value(struct w83627hf_data *data, u16 reg) |
1238 | ISA access must always be locked explicitly! | ||
1239 | We ignore the W83781D BUSY flag at this moment - it could lead to deadlocks, | ||
1240 | would slow down the W83781D access and should not be necessary. | ||
1241 | There are some ugly typecasts here, but the good news is - they should | ||
1242 | nowhere else be necessary! */ | ||
1243 | static int w83627hf_read_value(struct i2c_client *client, u16 reg) | ||
1244 | { | 1209 | { |
1245 | struct w83627hf_data *data = i2c_get_clientdata(client); | ||
1246 | int res, word_sized; | 1210 | int res, word_sized; |
1247 | 1211 | ||
1248 | mutex_lock(&data->lock); | 1212 | mutex_lock(&data->lock); |
@@ -1253,29 +1217,29 @@ static int w83627hf_read_value(struct i2c_client *client, u16 reg) | |||
1253 | || ((reg & 0x00ff) == 0x55)); | 1217 | || ((reg & 0x00ff) == 0x55)); |
1254 | if (reg & 0xff00) { | 1218 | if (reg & 0xff00) { |
1255 | outb_p(W83781D_REG_BANK, | 1219 | outb_p(W83781D_REG_BANK, |
1256 | client->addr + W83781D_ADDR_REG_OFFSET); | 1220 | data->addr + W83781D_ADDR_REG_OFFSET); |
1257 | outb_p(reg >> 8, | 1221 | outb_p(reg >> 8, |
1258 | client->addr + W83781D_DATA_REG_OFFSET); | 1222 | data->addr + W83781D_DATA_REG_OFFSET); |
1259 | } | 1223 | } |
1260 | outb_p(reg & 0xff, client->addr + W83781D_ADDR_REG_OFFSET); | 1224 | outb_p(reg & 0xff, data->addr + W83781D_ADDR_REG_OFFSET); |
1261 | res = inb_p(client->addr + W83781D_DATA_REG_OFFSET); | 1225 | res = inb_p(data->addr + W83781D_DATA_REG_OFFSET); |
1262 | if (word_sized) { | 1226 | if (word_sized) { |
1263 | outb_p((reg & 0xff) + 1, | 1227 | outb_p((reg & 0xff) + 1, |
1264 | client->addr + W83781D_ADDR_REG_OFFSET); | 1228 | data->addr + W83781D_ADDR_REG_OFFSET); |
1265 | res = | 1229 | res = |
1266 | (res << 8) + inb_p(client->addr + | 1230 | (res << 8) + inb_p(data->addr + |
1267 | W83781D_DATA_REG_OFFSET); | 1231 | W83781D_DATA_REG_OFFSET); |
1268 | } | 1232 | } |
1269 | if (reg & 0xff00) { | 1233 | if (reg & 0xff00) { |
1270 | outb_p(W83781D_REG_BANK, | 1234 | outb_p(W83781D_REG_BANK, |
1271 | client->addr + W83781D_ADDR_REG_OFFSET); | 1235 | data->addr + W83781D_ADDR_REG_OFFSET); |
1272 | outb_p(0, client->addr + W83781D_DATA_REG_OFFSET); | 1236 | outb_p(0, data->addr + W83781D_DATA_REG_OFFSET); |
1273 | } | 1237 | } |
1274 | mutex_unlock(&data->lock); | 1238 | mutex_unlock(&data->lock); |
1275 | return res; | 1239 | return res; |
1276 | } | 1240 | } |
1277 | 1241 | ||
1278 | static int w83627thf_read_gpio5(struct i2c_client *client) | 1242 | static int __devinit w83627thf_read_gpio5(struct platform_device *pdev) |
1279 | { | 1243 | { |
1280 | int res = 0xff, sel; | 1244 | int res = 0xff, sel; |
1281 | 1245 | ||
@@ -1284,7 +1248,7 @@ static int w83627thf_read_gpio5(struct i2c_client *client) | |||
1284 | 1248 | ||
1285 | /* Make sure these GPIO pins are enabled */ | 1249 | /* Make sure these GPIO pins are enabled */ |
1286 | if (!(superio_inb(W83627THF_GPIO5_EN) & (1<<3))) { | 1250 | if (!(superio_inb(W83627THF_GPIO5_EN) & (1<<3))) { |
1287 | dev_dbg(&client->dev, "GPIO5 disabled, no VID function\n"); | 1251 | dev_dbg(&pdev->dev, "GPIO5 disabled, no VID function\n"); |
1288 | goto exit; | 1252 | goto exit; |
1289 | } | 1253 | } |
1290 | 1254 | ||
@@ -1292,12 +1256,12 @@ static int w83627thf_read_gpio5(struct i2c_client *client) | |||
1292 | There must be at least five (VRM 9), and possibly 6 (VRM 10) */ | 1256 | There must be at least five (VRM 9), and possibly 6 (VRM 10) */ |
1293 | sel = superio_inb(W83627THF_GPIO5_IOSR) & 0x3f; | 1257 | sel = superio_inb(W83627THF_GPIO5_IOSR) & 0x3f; |
1294 | if ((sel & 0x1f) != 0x1f) { | 1258 | if ((sel & 0x1f) != 0x1f) { |
1295 | dev_dbg(&client->dev, "GPIO5 not configured for VID " | 1259 | dev_dbg(&pdev->dev, "GPIO5 not configured for VID " |
1296 | "function\n"); | 1260 | "function\n"); |
1297 | goto exit; | 1261 | goto exit; |
1298 | } | 1262 | } |
1299 | 1263 | ||
1300 | dev_info(&client->dev, "Reading VID from GPIO5\n"); | 1264 | dev_info(&pdev->dev, "Reading VID from GPIO5\n"); |
1301 | res = superio_inb(W83627THF_GPIO5_DR) & sel; | 1265 | res = superio_inb(W83627THF_GPIO5_DR) & sel; |
1302 | 1266 | ||
1303 | exit: | 1267 | exit: |
@@ -1305,7 +1269,7 @@ exit: | |||
1305 | return res; | 1269 | return res; |
1306 | } | 1270 | } |
1307 | 1271 | ||
1308 | static int w83687thf_read_vid(struct i2c_client *client) | 1272 | static int __devinit w83687thf_read_vid(struct platform_device *pdev) |
1309 | { | 1273 | { |
1310 | int res = 0xff; | 1274 | int res = 0xff; |
1311 | 1275 | ||
@@ -1314,13 +1278,13 @@ static int w83687thf_read_vid(struct i2c_client *client) | |||
1314 | 1278 | ||
1315 | /* Make sure these GPIO pins are enabled */ | 1279 | /* Make sure these GPIO pins are enabled */ |
1316 | if (!(superio_inb(W83687THF_VID_EN) & (1 << 2))) { | 1280 | if (!(superio_inb(W83687THF_VID_EN) & (1 << 2))) { |
1317 | dev_dbg(&client->dev, "VID disabled, no VID function\n"); | 1281 | dev_dbg(&pdev->dev, "VID disabled, no VID function\n"); |
1318 | goto exit; | 1282 | goto exit; |
1319 | } | 1283 | } |
1320 | 1284 | ||
1321 | /* Make sure the pins are configured for input */ | 1285 | /* Make sure the pins are configured for input */ |
1322 | if (!(superio_inb(W83687THF_VID_CFG) & (1 << 4))) { | 1286 | if (!(superio_inb(W83687THF_VID_CFG) & (1 << 4))) { |
1323 | dev_dbg(&client->dev, "VID configured as output, " | 1287 | dev_dbg(&pdev->dev, "VID configured as output, " |
1324 | "no VID function\n"); | 1288 | "no VID function\n"); |
1325 | goto exit; | 1289 | goto exit; |
1326 | } | 1290 | } |
@@ -1332,9 +1296,8 @@ exit: | |||
1332 | return res; | 1296 | return res; |
1333 | } | 1297 | } |
1334 | 1298 | ||
1335 | static int w83627hf_write_value(struct i2c_client *client, u16 reg, u16 value) | 1299 | static int w83627hf_write_value(struct w83627hf_data *data, u16 reg, u16 value) |
1336 | { | 1300 | { |
1337 | struct w83627hf_data *data = i2c_get_clientdata(client); | ||
1338 | int word_sized; | 1301 | int word_sized; |
1339 | 1302 | ||
1340 | mutex_lock(&data->lock); | 1303 | mutex_lock(&data->lock); |
@@ -1344,33 +1307,33 @@ static int w83627hf_write_value(struct i2c_client *client, u16 reg, u16 value) | |||
1344 | || ((reg & 0x00ff) == 0x55)); | 1307 | || ((reg & 0x00ff) == 0x55)); |
1345 | if (reg & 0xff00) { | 1308 | if (reg & 0xff00) { |
1346 | outb_p(W83781D_REG_BANK, | 1309 | outb_p(W83781D_REG_BANK, |
1347 | client->addr + W83781D_ADDR_REG_OFFSET); | 1310 | data->addr + W83781D_ADDR_REG_OFFSET); |
1348 | outb_p(reg >> 8, | 1311 | outb_p(reg >> 8, |
1349 | client->addr + W83781D_DATA_REG_OFFSET); | 1312 | data->addr + W83781D_DATA_REG_OFFSET); |
1350 | } | 1313 | } |
1351 | outb_p(reg & 0xff, client->addr + W83781D_ADDR_REG_OFFSET); | 1314 | outb_p(reg & 0xff, data->addr + W83781D_ADDR_REG_OFFSET); |
1352 | if (word_sized) { | 1315 | if (word_sized) { |
1353 | outb_p(value >> 8, | 1316 | outb_p(value >> 8, |
1354 | client->addr + W83781D_DATA_REG_OFFSET); | 1317 | data->addr + W83781D_DATA_REG_OFFSET); |
1355 | outb_p((reg & 0xff) + 1, | 1318 | outb_p((reg & 0xff) + 1, |
1356 | client->addr + W83781D_ADDR_REG_OFFSET); | 1319 | data->addr + W83781D_ADDR_REG_OFFSET); |
1357 | } | 1320 | } |
1358 | outb_p(value & 0xff, | 1321 | outb_p(value & 0xff, |
1359 | client->addr + W83781D_DATA_REG_OFFSET); | 1322 | data->addr + W83781D_DATA_REG_OFFSET); |
1360 | if (reg & 0xff00) { | 1323 | if (reg & 0xff00) { |
1361 | outb_p(W83781D_REG_BANK, | 1324 | outb_p(W83781D_REG_BANK, |
1362 | client->addr + W83781D_ADDR_REG_OFFSET); | 1325 | data->addr + W83781D_ADDR_REG_OFFSET); |
1363 | outb_p(0, client->addr + W83781D_DATA_REG_OFFSET); | 1326 | outb_p(0, data->addr + W83781D_DATA_REG_OFFSET); |
1364 | } | 1327 | } |
1365 | mutex_unlock(&data->lock); | 1328 | mutex_unlock(&data->lock); |
1366 | return 0; | 1329 | return 0; |
1367 | } | 1330 | } |
1368 | 1331 | ||
1369 | static void w83627hf_init_client(struct i2c_client *client) | 1332 | static void __devinit w83627hf_init_device(struct platform_device *pdev) |
1370 | { | 1333 | { |
1371 | struct w83627hf_data *data = i2c_get_clientdata(client); | 1334 | struct w83627hf_data *data = platform_get_drvdata(pdev); |
1372 | int i; | 1335 | int i; |
1373 | int type = data->type; | 1336 | enum chips type = data->type; |
1374 | u8 tmp; | 1337 | u8 tmp; |
1375 | 1338 | ||
1376 | if (reset) { | 1339 | if (reset) { |
@@ -1379,57 +1342,53 @@ static void w83627hf_init_client(struct i2c_client *client) | |||
1379 | speed...) so it is now optional. It might even go away if | 1342 | speed...) so it is now optional. It might even go away if |
1380 | nobody reports it as being useful, as I see very little | 1343 | nobody reports it as being useful, as I see very little |
1381 | reason why this would be needed at all. */ | 1344 | reason why this would be needed at all. */ |
1382 | dev_info(&client->dev, "If reset=1 solved a problem you were " | 1345 | dev_info(&pdev->dev, "If reset=1 solved a problem you were " |
1383 | "having, please report!\n"); | 1346 | "having, please report!\n"); |
1384 | 1347 | ||
1385 | /* save this register */ | 1348 | /* save this register */ |
1386 | i = w83627hf_read_value(client, W83781D_REG_BEEP_CONFIG); | 1349 | i = w83627hf_read_value(data, W83781D_REG_BEEP_CONFIG); |
1387 | /* Reset all except Watchdog values and last conversion values | 1350 | /* Reset all except Watchdog values and last conversion values |
1388 | This sets fan-divs to 2, among others */ | 1351 | This sets fan-divs to 2, among others */ |
1389 | w83627hf_write_value(client, W83781D_REG_CONFIG, 0x80); | 1352 | w83627hf_write_value(data, W83781D_REG_CONFIG, 0x80); |
1390 | /* Restore the register and disable power-on abnormal beep. | 1353 | /* Restore the register and disable power-on abnormal beep. |
1391 | This saves FAN 1/2/3 input/output values set by BIOS. */ | 1354 | This saves FAN 1/2/3 input/output values set by BIOS. */ |
1392 | w83627hf_write_value(client, W83781D_REG_BEEP_CONFIG, i | 0x80); | 1355 | w83627hf_write_value(data, W83781D_REG_BEEP_CONFIG, i | 0x80); |
1393 | /* Disable master beep-enable (reset turns it on). | 1356 | /* Disable master beep-enable (reset turns it on). |
1394 | Individual beeps should be reset to off but for some reason | 1357 | Individual beeps should be reset to off but for some reason |
1395 | disabling this bit helps some people not get beeped */ | 1358 | disabling this bit helps some people not get beeped */ |
1396 | w83627hf_write_value(client, W83781D_REG_BEEP_INTS2, 0); | 1359 | w83627hf_write_value(data, W83781D_REG_BEEP_INTS2, 0); |
1397 | } | 1360 | } |
1398 | 1361 | ||
1399 | /* Minimize conflicts with other winbond i2c-only clients... */ | 1362 | /* Minimize conflicts with other winbond i2c-only clients... */ |
1400 | /* disable i2c subclients... how to disable main i2c client?? */ | 1363 | /* disable i2c subclients... how to disable main i2c client?? */ |
1401 | /* force i2c address to relatively uncommon address */ | 1364 | /* force i2c address to relatively uncommon address */ |
1402 | w83627hf_write_value(client, W83781D_REG_I2C_SUBADDR, 0x89); | 1365 | w83627hf_write_value(data, W83781D_REG_I2C_SUBADDR, 0x89); |
1403 | w83627hf_write_value(client, W83781D_REG_I2C_ADDR, force_i2c); | 1366 | w83627hf_write_value(data, W83781D_REG_I2C_ADDR, force_i2c); |
1404 | 1367 | ||
1405 | /* Read VID only once */ | 1368 | /* Read VID only once */ |
1406 | if (w83627hf == data->type || w83637hf == data->type) { | 1369 | if (type == w83627hf || type == w83637hf) { |
1407 | int lo = w83627hf_read_value(client, W83781D_REG_VID_FANDIV); | 1370 | int lo = w83627hf_read_value(data, W83781D_REG_VID_FANDIV); |
1408 | int hi = w83627hf_read_value(client, W83781D_REG_CHIPID); | 1371 | int hi = w83627hf_read_value(data, W83781D_REG_CHIPID); |
1409 | data->vid = (lo & 0x0f) | ((hi & 0x01) << 4); | 1372 | data->vid = (lo & 0x0f) | ((hi & 0x01) << 4); |
1410 | } else if (w83627thf == data->type) { | 1373 | } else if (type == w83627thf) { |
1411 | data->vid = w83627thf_read_gpio5(client); | 1374 | data->vid = w83627thf_read_gpio5(pdev); |
1412 | } else if (w83687thf == data->type) { | 1375 | } else if (type == w83687thf) { |
1413 | data->vid = w83687thf_read_vid(client); | 1376 | data->vid = w83687thf_read_vid(pdev); |
1414 | } | 1377 | } |
1415 | 1378 | ||
1416 | /* Read VRM & OVT Config only once */ | 1379 | /* Read VRM & OVT Config only once */ |
1417 | if (w83627thf == data->type || w83637hf == data->type | 1380 | if (type == w83627thf || type == w83637hf || type == w83687thf) { |
1418 | || w83687thf == data->type) { | ||
1419 | data->vrm_ovt = | 1381 | data->vrm_ovt = |
1420 | w83627hf_read_value(client, W83627THF_REG_VRM_OVT_CFG); | 1382 | w83627hf_read_value(data, W83627THF_REG_VRM_OVT_CFG); |
1421 | } | 1383 | } |
1422 | 1384 | ||
1423 | /* Convert VID to voltage based on VRM */ | 1385 | tmp = w83627hf_read_value(data, W83781D_REG_SCFG1); |
1424 | data->vrm = vid_which_vrm(); | ||
1425 | |||
1426 | tmp = w83627hf_read_value(client, W83781D_REG_SCFG1); | ||
1427 | for (i = 1; i <= 3; i++) { | 1386 | for (i = 1; i <= 3; i++) { |
1428 | if (!(tmp & BIT_SCFG1[i - 1])) { | 1387 | if (!(tmp & BIT_SCFG1[i - 1])) { |
1429 | data->sens[i - 1] = W83781D_DEFAULT_BETA; | 1388 | data->sens[i - 1] = W83781D_DEFAULT_BETA; |
1430 | } else { | 1389 | } else { |
1431 | if (w83627hf_read_value | 1390 | if (w83627hf_read_value |
1432 | (client, | 1391 | (data, |
1433 | W83781D_REG_SCFG2) & BIT_SCFG2[i - 1]) | 1392 | W83781D_REG_SCFG2) & BIT_SCFG2[i - 1]) |
1434 | data->sens[i - 1] = 1; | 1393 | data->sens[i - 1] = 1; |
1435 | else | 1394 | else |
@@ -1441,38 +1400,37 @@ static void w83627hf_init_client(struct i2c_client *client) | |||
1441 | 1400 | ||
1442 | if(init) { | 1401 | if(init) { |
1443 | /* Enable temp2 */ | 1402 | /* Enable temp2 */ |
1444 | tmp = w83627hf_read_value(client, W83781D_REG_TEMP2_CONFIG); | 1403 | tmp = w83627hf_read_value(data, W83781D_REG_TEMP2_CONFIG); |
1445 | if (tmp & 0x01) { | 1404 | if (tmp & 0x01) { |
1446 | dev_warn(&client->dev, "Enabling temp2, readings " | 1405 | dev_warn(&pdev->dev, "Enabling temp2, readings " |
1447 | "might not make sense\n"); | 1406 | "might not make sense\n"); |
1448 | w83627hf_write_value(client, W83781D_REG_TEMP2_CONFIG, | 1407 | w83627hf_write_value(data, W83781D_REG_TEMP2_CONFIG, |
1449 | tmp & 0xfe); | 1408 | tmp & 0xfe); |
1450 | } | 1409 | } |
1451 | 1410 | ||
1452 | /* Enable temp3 */ | 1411 | /* Enable temp3 */ |
1453 | if (type != w83697hf) { | 1412 | if (type != w83697hf) { |
1454 | tmp = w83627hf_read_value(client, | 1413 | tmp = w83627hf_read_value(data, |
1455 | W83781D_REG_TEMP3_CONFIG); | 1414 | W83781D_REG_TEMP3_CONFIG); |
1456 | if (tmp & 0x01) { | 1415 | if (tmp & 0x01) { |
1457 | dev_warn(&client->dev, "Enabling temp3, " | 1416 | dev_warn(&pdev->dev, "Enabling temp3, " |
1458 | "readings might not make sense\n"); | 1417 | "readings might not make sense\n"); |
1459 | w83627hf_write_value(client, | 1418 | w83627hf_write_value(data, |
1460 | W83781D_REG_TEMP3_CONFIG, tmp & 0xfe); | 1419 | W83781D_REG_TEMP3_CONFIG, tmp & 0xfe); |
1461 | } | 1420 | } |
1462 | } | 1421 | } |
1463 | } | 1422 | } |
1464 | 1423 | ||
1465 | /* Start monitoring */ | 1424 | /* Start monitoring */ |
1466 | w83627hf_write_value(client, W83781D_REG_CONFIG, | 1425 | w83627hf_write_value(data, W83781D_REG_CONFIG, |
1467 | (w83627hf_read_value(client, | 1426 | (w83627hf_read_value(data, |
1468 | W83781D_REG_CONFIG) & 0xf7) | 1427 | W83781D_REG_CONFIG) & 0xf7) |
1469 | | 0x01); | 1428 | | 0x01); |
1470 | } | 1429 | } |
1471 | 1430 | ||
1472 | static struct w83627hf_data *w83627hf_update_device(struct device *dev) | 1431 | static struct w83627hf_data *w83627hf_update_device(struct device *dev) |
1473 | { | 1432 | { |
1474 | struct i2c_client *client = to_i2c_client(dev); | 1433 | struct w83627hf_data *data = dev_get_drvdata(dev); |
1475 | struct w83627hf_data *data = i2c_get_clientdata(client); | ||
1476 | int i; | 1434 | int i; |
1477 | 1435 | ||
1478 | mutex_lock(&data->update_lock); | 1436 | mutex_lock(&data->update_lock); |
@@ -1486,23 +1444,23 @@ static struct w83627hf_data *w83627hf_update_device(struct device *dev) | |||
1486 | && (i == 5 || i == 6))) | 1444 | && (i == 5 || i == 6))) |
1487 | continue; | 1445 | continue; |
1488 | data->in[i] = | 1446 | data->in[i] = |
1489 | w83627hf_read_value(client, W83781D_REG_IN(i)); | 1447 | w83627hf_read_value(data, W83781D_REG_IN(i)); |
1490 | data->in_min[i] = | 1448 | data->in_min[i] = |
1491 | w83627hf_read_value(client, | 1449 | w83627hf_read_value(data, |
1492 | W83781D_REG_IN_MIN(i)); | 1450 | W83781D_REG_IN_MIN(i)); |
1493 | data->in_max[i] = | 1451 | data->in_max[i] = |
1494 | w83627hf_read_value(client, | 1452 | w83627hf_read_value(data, |
1495 | W83781D_REG_IN_MAX(i)); | 1453 | W83781D_REG_IN_MAX(i)); |
1496 | } | 1454 | } |
1497 | for (i = 1; i <= 3; i++) { | 1455 | for (i = 1; i <= 3; i++) { |
1498 | data->fan[i - 1] = | 1456 | data->fan[i - 1] = |
1499 | w83627hf_read_value(client, W83781D_REG_FAN(i)); | 1457 | w83627hf_read_value(data, W83781D_REG_FAN(i)); |
1500 | data->fan_min[i - 1] = | 1458 | data->fan_min[i - 1] = |
1501 | w83627hf_read_value(client, | 1459 | w83627hf_read_value(data, |
1502 | W83781D_REG_FAN_MIN(i)); | 1460 | W83781D_REG_FAN_MIN(i)); |
1503 | } | 1461 | } |
1504 | for (i = 1; i <= 3; i++) { | 1462 | for (i = 1; i <= 3; i++) { |
1505 | u8 tmp = w83627hf_read_value(client, | 1463 | u8 tmp = w83627hf_read_value(data, |
1506 | W836X7HF_REG_PWM(data->type, i)); | 1464 | W836X7HF_REG_PWM(data->type, i)); |
1507 | /* bits 0-3 are reserved in 627THF */ | 1465 | /* bits 0-3 are reserved in 627THF */ |
1508 | if (data->type == w83627thf) | 1466 | if (data->type == w83627thf) |
@@ -1513,47 +1471,47 @@ static struct w83627hf_data *w83627hf_update_device(struct device *dev) | |||
1513 | break; | 1471 | break; |
1514 | } | 1472 | } |
1515 | 1473 | ||
1516 | data->temp = w83627hf_read_value(client, W83781D_REG_TEMP(1)); | 1474 | data->temp = w83627hf_read_value(data, W83781D_REG_TEMP(1)); |
1517 | data->temp_max = | 1475 | data->temp_max = |
1518 | w83627hf_read_value(client, W83781D_REG_TEMP_OVER(1)); | 1476 | w83627hf_read_value(data, W83781D_REG_TEMP_OVER(1)); |
1519 | data->temp_max_hyst = | 1477 | data->temp_max_hyst = |
1520 | w83627hf_read_value(client, W83781D_REG_TEMP_HYST(1)); | 1478 | w83627hf_read_value(data, W83781D_REG_TEMP_HYST(1)); |
1521 | data->temp_add[0] = | 1479 | data->temp_add[0] = |
1522 | w83627hf_read_value(client, W83781D_REG_TEMP(2)); | 1480 | w83627hf_read_value(data, W83781D_REG_TEMP(2)); |
1523 | data->temp_max_add[0] = | 1481 | data->temp_max_add[0] = |
1524 | w83627hf_read_value(client, W83781D_REG_TEMP_OVER(2)); | 1482 | w83627hf_read_value(data, W83781D_REG_TEMP_OVER(2)); |
1525 | data->temp_max_hyst_add[0] = | 1483 | data->temp_max_hyst_add[0] = |
1526 | w83627hf_read_value(client, W83781D_REG_TEMP_HYST(2)); | 1484 | w83627hf_read_value(data, W83781D_REG_TEMP_HYST(2)); |
1527 | if (data->type != w83697hf) { | 1485 | if (data->type != w83697hf) { |
1528 | data->temp_add[1] = | 1486 | data->temp_add[1] = |
1529 | w83627hf_read_value(client, W83781D_REG_TEMP(3)); | 1487 | w83627hf_read_value(data, W83781D_REG_TEMP(3)); |
1530 | data->temp_max_add[1] = | 1488 | data->temp_max_add[1] = |
1531 | w83627hf_read_value(client, W83781D_REG_TEMP_OVER(3)); | 1489 | w83627hf_read_value(data, W83781D_REG_TEMP_OVER(3)); |
1532 | data->temp_max_hyst_add[1] = | 1490 | data->temp_max_hyst_add[1] = |
1533 | w83627hf_read_value(client, W83781D_REG_TEMP_HYST(3)); | 1491 | w83627hf_read_value(data, W83781D_REG_TEMP_HYST(3)); |
1534 | } | 1492 | } |
1535 | 1493 | ||
1536 | i = w83627hf_read_value(client, W83781D_REG_VID_FANDIV); | 1494 | i = w83627hf_read_value(data, W83781D_REG_VID_FANDIV); |
1537 | data->fan_div[0] = (i >> 4) & 0x03; | 1495 | data->fan_div[0] = (i >> 4) & 0x03; |
1538 | data->fan_div[1] = (i >> 6) & 0x03; | 1496 | data->fan_div[1] = (i >> 6) & 0x03; |
1539 | if (data->type != w83697hf) { | 1497 | if (data->type != w83697hf) { |
1540 | data->fan_div[2] = (w83627hf_read_value(client, | 1498 | data->fan_div[2] = (w83627hf_read_value(data, |
1541 | W83781D_REG_PIN) >> 6) & 0x03; | 1499 | W83781D_REG_PIN) >> 6) & 0x03; |
1542 | } | 1500 | } |
1543 | i = w83627hf_read_value(client, W83781D_REG_VBAT); | 1501 | i = w83627hf_read_value(data, W83781D_REG_VBAT); |
1544 | data->fan_div[0] |= (i >> 3) & 0x04; | 1502 | data->fan_div[0] |= (i >> 3) & 0x04; |
1545 | data->fan_div[1] |= (i >> 4) & 0x04; | 1503 | data->fan_div[1] |= (i >> 4) & 0x04; |
1546 | if (data->type != w83697hf) | 1504 | if (data->type != w83697hf) |
1547 | data->fan_div[2] |= (i >> 5) & 0x04; | 1505 | data->fan_div[2] |= (i >> 5) & 0x04; |
1548 | data->alarms = | 1506 | data->alarms = |
1549 | w83627hf_read_value(client, W83781D_REG_ALARM1) | | 1507 | w83627hf_read_value(data, W83781D_REG_ALARM1) | |
1550 | (w83627hf_read_value(client, W83781D_REG_ALARM2) << 8) | | 1508 | (w83627hf_read_value(data, W83781D_REG_ALARM2) << 8) | |
1551 | (w83627hf_read_value(client, W83781D_REG_ALARM3) << 16); | 1509 | (w83627hf_read_value(data, W83781D_REG_ALARM3) << 16); |
1552 | i = w83627hf_read_value(client, W83781D_REG_BEEP_INTS2); | 1510 | i = w83627hf_read_value(data, W83781D_REG_BEEP_INTS2); |
1553 | data->beep_enable = i >> 7; | 1511 | data->beep_enable = i >> 7; |
1554 | data->beep_mask = ((i & 0x7f) << 8) | | 1512 | data->beep_mask = ((i & 0x7f) << 8) | |
1555 | w83627hf_read_value(client, W83781D_REG_BEEP_INTS1) | | 1513 | w83627hf_read_value(data, W83781D_REG_BEEP_INTS1) | |
1556 | w83627hf_read_value(client, W83781D_REG_BEEP_INTS3) << 16; | 1514 | w83627hf_read_value(data, W83781D_REG_BEEP_INTS3) << 16; |
1557 | data->last_updated = jiffies; | 1515 | data->last_updated = jiffies; |
1558 | data->valid = 1; | 1516 | data->valid = 1; |
1559 | } | 1517 | } |
@@ -1563,19 +1521,87 @@ static struct w83627hf_data *w83627hf_update_device(struct device *dev) | |||
1563 | return data; | 1521 | return data; |
1564 | } | 1522 | } |
1565 | 1523 | ||
1524 | static int __init w83627hf_device_add(unsigned short address, | ||
1525 | const struct w83627hf_sio_data *sio_data) | ||
1526 | { | ||
1527 | struct resource res = { | ||
1528 | .start = address + WINB_REGION_OFFSET, | ||
1529 | .end = address + WINB_REGION_OFFSET + WINB_REGION_SIZE - 1, | ||
1530 | .name = DRVNAME, | ||
1531 | .flags = IORESOURCE_IO, | ||
1532 | }; | ||
1533 | int err; | ||
1534 | |||
1535 | pdev = platform_device_alloc(DRVNAME, address); | ||
1536 | if (!pdev) { | ||
1537 | err = -ENOMEM; | ||
1538 | printk(KERN_ERR DRVNAME ": Device allocation failed\n"); | ||
1539 | goto exit; | ||
1540 | } | ||
1541 | |||
1542 | err = platform_device_add_resources(pdev, &res, 1); | ||
1543 | if (err) { | ||
1544 | printk(KERN_ERR DRVNAME ": Device resource addition failed " | ||
1545 | "(%d)\n", err); | ||
1546 | goto exit_device_put; | ||
1547 | } | ||
1548 | |||
1549 | pdev->dev.platform_data = kmalloc(sizeof(struct w83627hf_sio_data), | ||
1550 | GFP_KERNEL); | ||
1551 | if (!pdev->dev.platform_data) { | ||
1552 | err = -ENOMEM; | ||
1553 | printk(KERN_ERR DRVNAME ": Platform data allocation failed\n"); | ||
1554 | goto exit_device_put; | ||
1555 | } | ||
1556 | memcpy(pdev->dev.platform_data, sio_data, | ||
1557 | sizeof(struct w83627hf_sio_data)); | ||
1558 | |||
1559 | err = platform_device_add(pdev); | ||
1560 | if (err) { | ||
1561 | printk(KERN_ERR DRVNAME ": Device addition failed (%d)\n", | ||
1562 | err); | ||
1563 | goto exit_device_put; | ||
1564 | } | ||
1565 | |||
1566 | return 0; | ||
1567 | |||
1568 | exit_device_put: | ||
1569 | platform_device_put(pdev); | ||
1570 | exit: | ||
1571 | return err; | ||
1572 | } | ||
1573 | |||
1566 | static int __init sensors_w83627hf_init(void) | 1574 | static int __init sensors_w83627hf_init(void) |
1567 | { | 1575 | { |
1568 | if (w83627hf_find(0x2e, &address) | 1576 | int err; |
1569 | && w83627hf_find(0x4e, &address)) { | 1577 | unsigned short address; |
1578 | struct w83627hf_sio_data sio_data; | ||
1579 | |||
1580 | if (w83627hf_find(0x2e, &address, &sio_data) | ||
1581 | && w83627hf_find(0x4e, &address, &sio_data)) | ||
1570 | return -ENODEV; | 1582 | return -ENODEV; |
1571 | } | ||
1572 | 1583 | ||
1573 | return i2c_isa_add_driver(&w83627hf_driver); | 1584 | err = platform_driver_register(&w83627hf_driver); |
1585 | if (err) | ||
1586 | goto exit; | ||
1587 | |||
1588 | /* Sets global pdev as a side effect */ | ||
1589 | err = w83627hf_device_add(address, &sio_data); | ||
1590 | if (err) | ||
1591 | goto exit_driver; | ||
1592 | |||
1593 | return 0; | ||
1594 | |||
1595 | exit_driver: | ||
1596 | platform_driver_unregister(&w83627hf_driver); | ||
1597 | exit: | ||
1598 | return err; | ||
1574 | } | 1599 | } |
1575 | 1600 | ||
1576 | static void __exit sensors_w83627hf_exit(void) | 1601 | static void __exit sensors_w83627hf_exit(void) |
1577 | { | 1602 | { |
1578 | i2c_isa_del_driver(&w83627hf_driver); | 1603 | platform_device_unregister(pdev); |
1604 | platform_driver_unregister(&w83627hf_driver); | ||
1579 | } | 1605 | } |
1580 | 1606 | ||
1581 | MODULE_AUTHOR("Frodo Looijaard <frodol@dds.nl>, " | 1607 | MODULE_AUTHOR("Frodo Looijaard <frodol@dds.nl>, " |
diff --git a/drivers/hwmon/w83781d.c b/drivers/hwmon/w83781d.c index a47da3ec5472..f85b48fea1c4 100644 --- a/drivers/hwmon/w83781d.c +++ b/drivers/hwmon/w83781d.c | |||
@@ -2,8 +2,9 @@ | |||
2 | w83781d.c - Part of lm_sensors, Linux kernel modules for hardware | 2 | w83781d.c - Part of lm_sensors, Linux kernel modules for hardware |
3 | monitoring | 3 | monitoring |
4 | Copyright (c) 1998 - 2001 Frodo Looijaard <frodol@dds.nl>, | 4 | Copyright (c) 1998 - 2001 Frodo Looijaard <frodol@dds.nl>, |
5 | Philip Edelbrock <phil@netroedge.com>, | 5 | Philip Edelbrock <phil@netroedge.com>, |
6 | and Mark Studebaker <mdsxyz123@yahoo.com> | 6 | and Mark Studebaker <mdsxyz123@yahoo.com> |
7 | Copyright (c) 2007 Jean Delvare <khali@linux-fr.org> | ||
7 | 8 | ||
8 | This program is free software; you can redistribute it and/or modify | 9 | This program is free software; you can redistribute it and/or modify |
9 | it under the terms of the GNU General Public License as published by | 10 | it under the terms of the GNU General Public License as published by |
@@ -38,15 +39,20 @@ | |||
38 | #include <linux/slab.h> | 39 | #include <linux/slab.h> |
39 | #include <linux/jiffies.h> | 40 | #include <linux/jiffies.h> |
40 | #include <linux/i2c.h> | 41 | #include <linux/i2c.h> |
41 | #include <linux/i2c-isa.h> | 42 | #include <linux/platform_device.h> |
43 | #include <linux/ioport.h> | ||
42 | #include <linux/hwmon.h> | 44 | #include <linux/hwmon.h> |
43 | #include <linux/hwmon-vid.h> | 45 | #include <linux/hwmon-vid.h> |
46 | #include <linux/hwmon-sysfs.h> | ||
44 | #include <linux/sysfs.h> | 47 | #include <linux/sysfs.h> |
45 | #include <linux/err.h> | 48 | #include <linux/err.h> |
46 | #include <linux/mutex.h> | 49 | #include <linux/mutex.h> |
47 | #include <asm/io.h> | 50 | #include <asm/io.h> |
48 | #include "lm75.h" | 51 | #include "lm75.h" |
49 | 52 | ||
53 | /* ISA device, if found */ | ||
54 | static struct platform_device *pdev; | ||
55 | |||
50 | /* Addresses to scan */ | 56 | /* Addresses to scan */ |
51 | static unsigned short normal_i2c[] = { 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, | 57 | static unsigned short normal_i2c[] = { 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, |
52 | 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b, | 58 | 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b, |
@@ -75,8 +81,8 @@ MODULE_PARM_DESC(init, "Set to zero to bypass chip initialization"); | |||
75 | #define W83781D_ADDR_REG_OFFSET 5 | 81 | #define W83781D_ADDR_REG_OFFSET 5 |
76 | #define W83781D_DATA_REG_OFFSET 6 | 82 | #define W83781D_DATA_REG_OFFSET 6 |
77 | 83 | ||
78 | /* The W83781D registers */ | 84 | /* The device registers */ |
79 | /* The W83782D registers for nr=7,8 are in bank 5 */ | 85 | /* in nr from 0 to 8 */ |
80 | #define W83781D_REG_IN_MAX(nr) ((nr < 7) ? (0x2b + (nr) * 2) : \ | 86 | #define W83781D_REG_IN_MAX(nr) ((nr < 7) ? (0x2b + (nr) * 2) : \ |
81 | (0x554 + (((nr) - 7) * 2))) | 87 | (0x554 + (((nr) - 7) * 2))) |
82 | #define W83781D_REG_IN_MIN(nr) ((nr < 7) ? (0x2c + (nr) * 2) : \ | 88 | #define W83781D_REG_IN_MIN(nr) ((nr < 7) ? (0x2c + (nr) * 2) : \ |
@@ -84,12 +90,14 @@ MODULE_PARM_DESC(init, "Set to zero to bypass chip initialization"); | |||
84 | #define W83781D_REG_IN(nr) ((nr < 7) ? (0x20 + (nr)) : \ | 90 | #define W83781D_REG_IN(nr) ((nr < 7) ? (0x20 + (nr)) : \ |
85 | (0x550 + (nr) - 7)) | 91 | (0x550 + (nr) - 7)) |
86 | 92 | ||
87 | #define W83781D_REG_FAN_MIN(nr) (0x3a + (nr)) | 93 | /* fan nr from 0 to 2 */ |
88 | #define W83781D_REG_FAN(nr) (0x27 + (nr)) | 94 | #define W83781D_REG_FAN_MIN(nr) (0x3b + (nr)) |
95 | #define W83781D_REG_FAN(nr) (0x28 + (nr)) | ||
89 | 96 | ||
90 | #define W83781D_REG_BANK 0x4E | 97 | #define W83781D_REG_BANK 0x4E |
91 | #define W83781D_REG_TEMP2_CONFIG 0x152 | 98 | #define W83781D_REG_TEMP2_CONFIG 0x152 |
92 | #define W83781D_REG_TEMP3_CONFIG 0x252 | 99 | #define W83781D_REG_TEMP3_CONFIG 0x252 |
100 | /* temp nr from 1 to 3 */ | ||
93 | #define W83781D_REG_TEMP(nr) ((nr == 3) ? (0x0250) : \ | 101 | #define W83781D_REG_TEMP(nr) ((nr == 3) ? (0x0250) : \ |
94 | ((nr == 2) ? (0x0150) : \ | 102 | ((nr == 2) ? (0x0150) : \ |
95 | (0x27))) | 103 | (0x27))) |
@@ -127,19 +135,9 @@ MODULE_PARM_DESC(init, "Set to zero to bypass chip initialization"); | |||
127 | #define W83781D_REG_VBAT 0x5D | 135 | #define W83781D_REG_VBAT 0x5D |
128 | 136 | ||
129 | /* PWM 782D (1-4) and 783S (1-2) only */ | 137 | /* PWM 782D (1-4) and 783S (1-2) only */ |
130 | #define W83781D_REG_PWM1 0x5B /* 782d and 783s/627hf datasheets disagree */ | 138 | static const u8 W83781D_REG_PWM[] = { 0x5B, 0x5A, 0x5E, 0x5F }; |
131 | /* on which is which; */ | ||
132 | #define W83781D_REG_PWM2 0x5A /* We follow the 782d convention here, */ | ||
133 | /* However 782d is probably wrong. */ | ||
134 | #define W83781D_REG_PWM3 0x5E | ||
135 | #define W83781D_REG_PWM4 0x5F | ||
136 | #define W83781D_REG_PWMCLK12 0x5C | 139 | #define W83781D_REG_PWMCLK12 0x5C |
137 | #define W83781D_REG_PWMCLK34 0x45C | 140 | #define W83781D_REG_PWMCLK34 0x45C |
138 | static const u8 regpwm[] = { W83781D_REG_PWM1, W83781D_REG_PWM2, | ||
139 | W83781D_REG_PWM3, W83781D_REG_PWM4 | ||
140 | }; | ||
141 | |||
142 | #define W83781D_REG_PWM(nr) (regpwm[(nr) - 1]) | ||
143 | 141 | ||
144 | #define W83781D_REG_I2C_ADDR 0x48 | 142 | #define W83781D_REG_I2C_ADDR 0x48 |
145 | #define W83781D_REG_I2C_SUBADDR 0x4A | 143 | #define W83781D_REG_I2C_SUBADDR 0x4A |
@@ -159,12 +157,9 @@ static const u8 BIT_SCFG2[] = { 0x10, 0x20, 0x40 }; | |||
159 | #define W83781D_REG_RT_IDX 0x50 | 157 | #define W83781D_REG_RT_IDX 0x50 |
160 | #define W83781D_REG_RT_VAL 0x51 | 158 | #define W83781D_REG_RT_VAL 0x51 |
161 | 159 | ||
162 | /* Conversions. Rounding and limit checking is only done on the TO_REG | 160 | /* Conversions */ |
163 | variants. Note that you should be a bit careful with which arguments | 161 | #define IN_TO_REG(val) SENSORS_LIMIT(((val) + 8) / 16, 0, 255) |
164 | these macros are called: arguments may be evaluated more than once. | 162 | #define IN_FROM_REG(val) ((val) * 16) |
165 | Fixing this is just not worth it. */ | ||
166 | #define IN_TO_REG(val) (SENSORS_LIMIT((((val) * 10 + 8)/16),0,255)) | ||
167 | #define IN_FROM_REG(val) (((val) * 16) / 10) | ||
168 | 163 | ||
169 | static inline u8 | 164 | static inline u8 |
170 | FAN_TO_REG(long rpm, int div) | 165 | FAN_TO_REG(long rpm, int div) |
@@ -175,24 +170,24 @@ FAN_TO_REG(long rpm, int div) | |||
175 | return SENSORS_LIMIT((1350000 + rpm * div / 2) / (rpm * div), 1, 254); | 170 | return SENSORS_LIMIT((1350000 + rpm * div / 2) / (rpm * div), 1, 254); |
176 | } | 171 | } |
177 | 172 | ||
178 | #define FAN_FROM_REG(val,div) ((val) == 0 ? -1 : \ | 173 | static inline long |
179 | ((val) == 255 ? 0 : \ | 174 | FAN_FROM_REG(u8 val, int div) |
180 | 1350000 / ((val) * (div)))) | 175 | { |
176 | if (val == 0) | ||
177 | return -1; | ||
178 | if (val == 255) | ||
179 | return 0; | ||
180 | return 1350000 / (val * div); | ||
181 | } | ||
181 | 182 | ||
182 | #define TEMP_TO_REG(val) (SENSORS_LIMIT(((val) < 0 ? (val)+0x100*1000 \ | 183 | #define TEMP_TO_REG(val) SENSORS_LIMIT((val) / 1000, -127, 128) |
183 | : (val)) / 1000, 0, 0xff)) | 184 | #define TEMP_FROM_REG(val) ((val) * 1000) |
184 | #define TEMP_FROM_REG(val) (((val) & 0x80 ? (val)-0x100 : (val)) * 1000) | ||
185 | 185 | ||
186 | #define PWM_FROM_REG(val) (val) | ||
187 | #define PWM_TO_REG(val) (SENSORS_LIMIT((val),0,255)) | ||
188 | #define BEEP_MASK_FROM_REG(val,type) ((type) == as99127f ? \ | 186 | #define BEEP_MASK_FROM_REG(val,type) ((type) == as99127f ? \ |
189 | (val) ^ 0x7fff : (val)) | 187 | (val) ^ 0x7fff : (val)) |
190 | #define BEEP_MASK_TO_REG(val,type) ((type) == as99127f ? \ | 188 | #define BEEP_MASK_TO_REG(val,type) ((type) == as99127f ? \ |
191 | (~(val)) & 0x7fff : (val) & 0xffffff) | 189 | (~(val)) & 0x7fff : (val) & 0xffffff) |
192 | 190 | ||
193 | #define BEEP_ENABLE_TO_REG(val) ((val) ? 1 : 0) | ||
194 | #define BEEP_ENABLE_FROM_REG(val) ((val) ? 1 : 0) | ||
195 | |||
196 | #define DIV_FROM_REG(val) (1 << (val)) | 191 | #define DIV_FROM_REG(val) (1 << (val)) |
197 | 192 | ||
198 | static inline u8 | 193 | static inline u8 |
@@ -207,7 +202,7 @@ DIV_TO_REG(long val, enum chips type) | |||
207 | break; | 202 | break; |
208 | val >>= 1; | 203 | val >>= 1; |
209 | } | 204 | } |
210 | return ((u8) i); | 205 | return i; |
211 | } | 206 | } |
212 | 207 | ||
213 | /* There are some complications in a module like this. First off, W83781D chips | 208 | /* There are some complications in a module like this. First off, W83781D chips |
@@ -221,8 +216,8 @@ DIV_TO_REG(long val, enum chips type) | |||
221 | a bit - except if there could be more than one SMBus. Groan. No solution | 216 | a bit - except if there could be more than one SMBus. Groan. No solution |
222 | for this yet. */ | 217 | for this yet. */ |
223 | 218 | ||
224 | /* For each registered chip, we need to keep some data in memory. | 219 | /* For ISA chips, we abuse the i2c_client addr and name fields. We also use |
225 | The structure is dynamically allocated. */ | 220 | the driver field to differentiate between I2C and ISA chips. */ |
226 | struct w83781d_data { | 221 | struct w83781d_data { |
227 | struct i2c_client client; | 222 | struct i2c_client client; |
228 | struct class_device *class_dev; | 223 | struct class_device *class_dev; |
@@ -241,9 +236,9 @@ struct w83781d_data { | |||
241 | u8 in_min[9]; /* Register value - 8 & 9 for 782D only */ | 236 | u8 in_min[9]; /* Register value - 8 & 9 for 782D only */ |
242 | u8 fan[3]; /* Register value */ | 237 | u8 fan[3]; /* Register value */ |
243 | u8 fan_min[3]; /* Register value */ | 238 | u8 fan_min[3]; /* Register value */ |
244 | u8 temp; | 239 | s8 temp; /* Register value */ |
245 | u8 temp_max; /* Register value */ | 240 | s8 temp_max; /* Register value */ |
246 | u8 temp_max_hyst; /* Register value */ | 241 | s8 temp_max_hyst; /* Register value */ |
247 | u16 temp_add[2]; /* Register value */ | 242 | u16 temp_add[2]; /* Register value */ |
248 | u16 temp_max_add[2]; /* Register value */ | 243 | u16 temp_max_add[2]; /* Register value */ |
249 | u16 temp_max_hyst_add[2]; /* Register value */ | 244 | u16 temp_max_hyst_add[2]; /* Register value */ |
@@ -253,7 +248,7 @@ struct w83781d_data { | |||
253 | u32 beep_mask; /* Register encoding, combined */ | 248 | u32 beep_mask; /* Register encoding, combined */ |
254 | u8 beep_enable; /* Boolean */ | 249 | u8 beep_enable; /* Boolean */ |
255 | u8 pwm[4]; /* Register value */ | 250 | u8 pwm[4]; /* Register value */ |
256 | u8 pwmenable[4]; /* Boolean */ | 251 | u8 pwm2_enable; /* Boolean */ |
257 | u16 sens[3]; /* 782D/783S only. | 252 | u16 sens[3]; /* 782D/783S only. |
258 | 1 = pentium diode; 2 = 3904 diode; | 253 | 1 = pentium diode; 2 = 3904 diode; |
259 | 3000-5000 = thermistor beta. | 254 | 3000-5000 = thermistor beta. |
@@ -263,14 +258,16 @@ struct w83781d_data { | |||
263 | }; | 258 | }; |
264 | 259 | ||
265 | static int w83781d_attach_adapter(struct i2c_adapter *adapter); | 260 | static int w83781d_attach_adapter(struct i2c_adapter *adapter); |
266 | static int w83781d_isa_attach_adapter(struct i2c_adapter *adapter); | ||
267 | static int w83781d_detect(struct i2c_adapter *adapter, int address, int kind); | 261 | static int w83781d_detect(struct i2c_adapter *adapter, int address, int kind); |
268 | static int w83781d_detach_client(struct i2c_client *client); | 262 | static int w83781d_detach_client(struct i2c_client *client); |
269 | 263 | ||
270 | static int w83781d_read_value(struct i2c_client *client, u16 reg); | 264 | static int __devinit w83781d_isa_probe(struct platform_device *pdev); |
271 | static int w83781d_write_value(struct i2c_client *client, u16 reg, u16 value); | 265 | static int __devexit w83781d_isa_remove(struct platform_device *pdev); |
266 | |||
267 | static int w83781d_read_value(struct w83781d_data *data, u16 reg); | ||
268 | static int w83781d_write_value(struct w83781d_data *data, u16 reg, u16 value); | ||
272 | static struct w83781d_data *w83781d_update_device(struct device *dev); | 269 | static struct w83781d_data *w83781d_update_device(struct device *dev); |
273 | static void w83781d_init_client(struct i2c_client *client); | 270 | static void w83781d_init_device(struct device *dev); |
274 | 271 | ||
275 | static struct i2c_driver w83781d_driver = { | 272 | static struct i2c_driver w83781d_driver = { |
276 | .driver = { | 273 | .driver = { |
@@ -281,39 +278,44 @@ static struct i2c_driver w83781d_driver = { | |||
281 | .detach_client = w83781d_detach_client, | 278 | .detach_client = w83781d_detach_client, |
282 | }; | 279 | }; |
283 | 280 | ||
284 | static struct i2c_driver w83781d_isa_driver = { | 281 | static struct platform_driver w83781d_isa_driver = { |
285 | .driver = { | 282 | .driver = { |
286 | .owner = THIS_MODULE, | 283 | .owner = THIS_MODULE, |
287 | .name = "w83781d-isa", | 284 | .name = "w83781d", |
288 | }, | 285 | }, |
289 | .attach_adapter = w83781d_isa_attach_adapter, | 286 | .probe = w83781d_isa_probe, |
290 | .detach_client = w83781d_detach_client, | 287 | .remove = w83781d_isa_remove, |
291 | }; | 288 | }; |
292 | 289 | ||
293 | 290 | ||
294 | /* following are the sysfs callback functions */ | 291 | /* following are the sysfs callback functions */ |
295 | #define show_in_reg(reg) \ | 292 | #define show_in_reg(reg) \ |
296 | static ssize_t show_##reg (struct device *dev, char *buf, int nr) \ | 293 | static ssize_t show_##reg (struct device *dev, struct device_attribute *da, \ |
294 | char *buf) \ | ||
297 | { \ | 295 | { \ |
296 | struct sensor_device_attribute *attr = to_sensor_dev_attr(da); \ | ||
298 | struct w83781d_data *data = w83781d_update_device(dev); \ | 297 | struct w83781d_data *data = w83781d_update_device(dev); \ |
299 | return sprintf(buf,"%ld\n", (long)IN_FROM_REG(data->reg[nr] * 10)); \ | 298 | return sprintf(buf, "%ld\n", \ |
299 | (long)IN_FROM_REG(data->reg[attr->index])); \ | ||
300 | } | 300 | } |
301 | show_in_reg(in); | 301 | show_in_reg(in); |
302 | show_in_reg(in_min); | 302 | show_in_reg(in_min); |
303 | show_in_reg(in_max); | 303 | show_in_reg(in_max); |
304 | 304 | ||
305 | #define store_in_reg(REG, reg) \ | 305 | #define store_in_reg(REG, reg) \ |
306 | static ssize_t store_in_##reg (struct device *dev, const char *buf, size_t count, int nr) \ | 306 | static ssize_t store_in_##reg (struct device *dev, struct device_attribute \ |
307 | *da, const char *buf, size_t count) \ | ||
307 | { \ | 308 | { \ |
308 | struct i2c_client *client = to_i2c_client(dev); \ | 309 | struct sensor_device_attribute *attr = to_sensor_dev_attr(da); \ |
309 | struct w83781d_data *data = i2c_get_clientdata(client); \ | 310 | struct w83781d_data *data = dev_get_drvdata(dev); \ |
311 | int nr = attr->index; \ | ||
310 | u32 val; \ | 312 | u32 val; \ |
311 | \ | 313 | \ |
312 | val = simple_strtoul(buf, NULL, 10) / 10; \ | 314 | val = simple_strtoul(buf, NULL, 10); \ |
313 | \ | 315 | \ |
314 | mutex_lock(&data->update_lock); \ | 316 | mutex_lock(&data->update_lock); \ |
315 | data->in_##reg[nr] = IN_TO_REG(val); \ | 317 | data->in_##reg[nr] = IN_TO_REG(val); \ |
316 | w83781d_write_value(client, W83781D_REG_IN_##REG(nr), data->in_##reg[nr]); \ | 318 | w83781d_write_value(data, W83781D_REG_IN_##REG(nr), data->in_##reg[nr]); \ |
317 | \ | 319 | \ |
318 | mutex_unlock(&data->update_lock); \ | 320 | mutex_unlock(&data->update_lock); \ |
319 | return count; \ | 321 | return count; \ |
@@ -321,29 +323,13 @@ static ssize_t store_in_##reg (struct device *dev, const char *buf, size_t count | |||
321 | store_in_reg(MIN, min); | 323 | store_in_reg(MIN, min); |
322 | store_in_reg(MAX, max); | 324 | store_in_reg(MAX, max); |
323 | 325 | ||
324 | #define sysfs_in_offset(offset) \ | ||
325 | static ssize_t \ | ||
326 | show_regs_in_##offset (struct device *dev, struct device_attribute *attr, char *buf) \ | ||
327 | { \ | ||
328 | return show_in(dev, buf, offset); \ | ||
329 | } \ | ||
330 | static DEVICE_ATTR(in##offset##_input, S_IRUGO, show_regs_in_##offset, NULL); | ||
331 | |||
332 | #define sysfs_in_reg_offset(reg, offset) \ | ||
333 | static ssize_t show_regs_in_##reg##offset (struct device *dev, struct device_attribute *attr, char *buf) \ | ||
334 | { \ | ||
335 | return show_in_##reg (dev, buf, offset); \ | ||
336 | } \ | ||
337 | static ssize_t store_regs_in_##reg##offset (struct device *dev, struct device_attribute *attr, const char *buf, size_t count) \ | ||
338 | { \ | ||
339 | return store_in_##reg (dev, buf, count, offset); \ | ||
340 | } \ | ||
341 | static DEVICE_ATTR(in##offset##_##reg, S_IRUGO| S_IWUSR, show_regs_in_##reg##offset, store_regs_in_##reg##offset); | ||
342 | |||
343 | #define sysfs_in_offsets(offset) \ | 326 | #define sysfs_in_offsets(offset) \ |
344 | sysfs_in_offset(offset); \ | 327 | static SENSOR_DEVICE_ATTR(in##offset##_input, S_IRUGO, \ |
345 | sysfs_in_reg_offset(min, offset); \ | 328 | show_in, NULL, offset); \ |
346 | sysfs_in_reg_offset(max, offset); | 329 | static SENSOR_DEVICE_ATTR(in##offset##_min, S_IRUGO | S_IWUSR, \ |
330 | show_in_min, store_in_min, offset); \ | ||
331 | static SENSOR_DEVICE_ATTR(in##offset##_max, S_IRUGO | S_IWUSR, \ | ||
332 | show_in_max, store_in_max, offset) | ||
347 | 333 | ||
348 | sysfs_in_offsets(0); | 334 | sysfs_in_offsets(0); |
349 | sysfs_in_offsets(1); | 335 | sysfs_in_offsets(1); |
@@ -356,63 +342,56 @@ sysfs_in_offsets(7); | |||
356 | sysfs_in_offsets(8); | 342 | sysfs_in_offsets(8); |
357 | 343 | ||
358 | #define show_fan_reg(reg) \ | 344 | #define show_fan_reg(reg) \ |
359 | static ssize_t show_##reg (struct device *dev, char *buf, int nr) \ | 345 | static ssize_t show_##reg (struct device *dev, struct device_attribute *da, \ |
346 | char *buf) \ | ||
360 | { \ | 347 | { \ |
348 | struct sensor_device_attribute *attr = to_sensor_dev_attr(da); \ | ||
361 | struct w83781d_data *data = w83781d_update_device(dev); \ | 349 | struct w83781d_data *data = w83781d_update_device(dev); \ |
362 | return sprintf(buf,"%ld\n", \ | 350 | return sprintf(buf,"%ld\n", \ |
363 | FAN_FROM_REG(data->reg[nr-1], (long)DIV_FROM_REG(data->fan_div[nr-1]))); \ | 351 | FAN_FROM_REG(data->reg[attr->index], \ |
352 | DIV_FROM_REG(data->fan_div[attr->index]))); \ | ||
364 | } | 353 | } |
365 | show_fan_reg(fan); | 354 | show_fan_reg(fan); |
366 | show_fan_reg(fan_min); | 355 | show_fan_reg(fan_min); |
367 | 356 | ||
368 | static ssize_t | 357 | static ssize_t |
369 | store_fan_min(struct device *dev, const char *buf, size_t count, int nr) | 358 | store_fan_min(struct device *dev, struct device_attribute *da, |
359 | const char *buf, size_t count) | ||
370 | { | 360 | { |
371 | struct i2c_client *client = to_i2c_client(dev); | 361 | struct sensor_device_attribute *attr = to_sensor_dev_attr(da); |
372 | struct w83781d_data *data = i2c_get_clientdata(client); | 362 | struct w83781d_data *data = dev_get_drvdata(dev); |
363 | int nr = attr->index; | ||
373 | u32 val; | 364 | u32 val; |
374 | 365 | ||
375 | val = simple_strtoul(buf, NULL, 10); | 366 | val = simple_strtoul(buf, NULL, 10); |
376 | 367 | ||
377 | mutex_lock(&data->update_lock); | 368 | mutex_lock(&data->update_lock); |
378 | data->fan_min[nr - 1] = | 369 | data->fan_min[nr] = |
379 | FAN_TO_REG(val, DIV_FROM_REG(data->fan_div[nr - 1])); | 370 | FAN_TO_REG(val, DIV_FROM_REG(data->fan_div[nr])); |
380 | w83781d_write_value(client, W83781D_REG_FAN_MIN(nr), | 371 | w83781d_write_value(data, W83781D_REG_FAN_MIN(nr), |
381 | data->fan_min[nr - 1]); | 372 | data->fan_min[nr]); |
382 | 373 | ||
383 | mutex_unlock(&data->update_lock); | 374 | mutex_unlock(&data->update_lock); |
384 | return count; | 375 | return count; |
385 | } | 376 | } |
386 | 377 | ||
387 | #define sysfs_fan_offset(offset) \ | 378 | static SENSOR_DEVICE_ATTR(fan1_input, S_IRUGO, show_fan, NULL, 0); |
388 | static ssize_t show_regs_fan_##offset (struct device *dev, struct device_attribute *attr, char *buf) \ | 379 | static SENSOR_DEVICE_ATTR(fan1_min, S_IRUGO | S_IWUSR, |
389 | { \ | 380 | show_fan_min, store_fan_min, 0); |
390 | return show_fan(dev, buf, offset); \ | 381 | static SENSOR_DEVICE_ATTR(fan2_input, S_IRUGO, show_fan, NULL, 1); |
391 | } \ | 382 | static SENSOR_DEVICE_ATTR(fan2_min, S_IRUGO | S_IWUSR, |
392 | static DEVICE_ATTR(fan##offset##_input, S_IRUGO, show_regs_fan_##offset, NULL); | 383 | show_fan_min, store_fan_min, 1); |
393 | 384 | static SENSOR_DEVICE_ATTR(fan3_input, S_IRUGO, show_fan, NULL, 2); | |
394 | #define sysfs_fan_min_offset(offset) \ | 385 | static SENSOR_DEVICE_ATTR(fan3_min, S_IRUGO | S_IWUSR, |
395 | static ssize_t show_regs_fan_min##offset (struct device *dev, struct device_attribute *attr, char *buf) \ | 386 | show_fan_min, store_fan_min, 2); |
396 | { \ | ||
397 | return show_fan_min(dev, buf, offset); \ | ||
398 | } \ | ||
399 | static ssize_t store_regs_fan_min##offset (struct device *dev, struct device_attribute *attr, const char *buf, size_t count) \ | ||
400 | { \ | ||
401 | return store_fan_min(dev, buf, count, offset); \ | ||
402 | } \ | ||
403 | static DEVICE_ATTR(fan##offset##_min, S_IRUGO | S_IWUSR, show_regs_fan_min##offset, store_regs_fan_min##offset); | ||
404 | |||
405 | sysfs_fan_offset(1); | ||
406 | sysfs_fan_min_offset(1); | ||
407 | sysfs_fan_offset(2); | ||
408 | sysfs_fan_min_offset(2); | ||
409 | sysfs_fan_offset(3); | ||
410 | sysfs_fan_min_offset(3); | ||
411 | 387 | ||
412 | #define show_temp_reg(reg) \ | 388 | #define show_temp_reg(reg) \ |
413 | static ssize_t show_##reg (struct device *dev, char *buf, int nr) \ | 389 | static ssize_t show_##reg (struct device *dev, struct device_attribute *da, \ |
390 | char *buf) \ | ||
414 | { \ | 391 | { \ |
392 | struct sensor_device_attribute *attr = to_sensor_dev_attr(da); \ | ||
415 | struct w83781d_data *data = w83781d_update_device(dev); \ | 393 | struct w83781d_data *data = w83781d_update_device(dev); \ |
394 | int nr = attr->index; \ | ||
416 | if (nr >= 2) { /* TEMP2 and TEMP3 */ \ | 395 | if (nr >= 2) { /* TEMP2 and TEMP3 */ \ |
417 | return sprintf(buf,"%d\n", \ | 396 | return sprintf(buf,"%d\n", \ |
418 | LM75_TEMP_FROM_REG(data->reg##_add[nr-2])); \ | 397 | LM75_TEMP_FROM_REG(data->reg##_add[nr-2])); \ |
@@ -425,10 +404,12 @@ show_temp_reg(temp_max); | |||
425 | show_temp_reg(temp_max_hyst); | 404 | show_temp_reg(temp_max_hyst); |
426 | 405 | ||
427 | #define store_temp_reg(REG, reg) \ | 406 | #define store_temp_reg(REG, reg) \ |
428 | static ssize_t store_temp_##reg (struct device *dev, const char *buf, size_t count, int nr) \ | 407 | static ssize_t store_temp_##reg (struct device *dev, \ |
408 | struct device_attribute *da, const char *buf, size_t count) \ | ||
429 | { \ | 409 | { \ |
430 | struct i2c_client *client = to_i2c_client(dev); \ | 410 | struct sensor_device_attribute *attr = to_sensor_dev_attr(da); \ |
431 | struct w83781d_data *data = i2c_get_clientdata(client); \ | 411 | struct w83781d_data *data = dev_get_drvdata(dev); \ |
412 | int nr = attr->index; \ | ||
432 | s32 val; \ | 413 | s32 val; \ |
433 | \ | 414 | \ |
434 | val = simple_strtol(buf, NULL, 10); \ | 415 | val = simple_strtol(buf, NULL, 10); \ |
@@ -437,11 +418,11 @@ static ssize_t store_temp_##reg (struct device *dev, const char *buf, size_t cou | |||
437 | \ | 418 | \ |
438 | if (nr >= 2) { /* TEMP2 and TEMP3 */ \ | 419 | if (nr >= 2) { /* TEMP2 and TEMP3 */ \ |
439 | data->temp_##reg##_add[nr-2] = LM75_TEMP_TO_REG(val); \ | 420 | data->temp_##reg##_add[nr-2] = LM75_TEMP_TO_REG(val); \ |
440 | w83781d_write_value(client, W83781D_REG_TEMP_##REG(nr), \ | 421 | w83781d_write_value(data, W83781D_REG_TEMP_##REG(nr), \ |
441 | data->temp_##reg##_add[nr-2]); \ | 422 | data->temp_##reg##_add[nr-2]); \ |
442 | } else { /* TEMP1 */ \ | 423 | } else { /* TEMP1 */ \ |
443 | data->temp_##reg = TEMP_TO_REG(val); \ | 424 | data->temp_##reg = TEMP_TO_REG(val); \ |
444 | w83781d_write_value(client, W83781D_REG_TEMP_##REG(nr), \ | 425 | w83781d_write_value(data, W83781D_REG_TEMP_##REG(nr), \ |
445 | data->temp_##reg); \ | 426 | data->temp_##reg); \ |
446 | } \ | 427 | } \ |
447 | \ | 428 | \ |
@@ -451,29 +432,13 @@ static ssize_t store_temp_##reg (struct device *dev, const char *buf, size_t cou | |||
451 | store_temp_reg(OVER, max); | 432 | store_temp_reg(OVER, max); |
452 | store_temp_reg(HYST, max_hyst); | 433 | store_temp_reg(HYST, max_hyst); |
453 | 434 | ||
454 | #define sysfs_temp_offset(offset) \ | ||
455 | static ssize_t \ | ||
456 | show_regs_temp_##offset (struct device *dev, struct device_attribute *attr, char *buf) \ | ||
457 | { \ | ||
458 | return show_temp(dev, buf, offset); \ | ||
459 | } \ | ||
460 | static DEVICE_ATTR(temp##offset##_input, S_IRUGO, show_regs_temp_##offset, NULL); | ||
461 | |||
462 | #define sysfs_temp_reg_offset(reg, offset) \ | ||
463 | static ssize_t show_regs_temp_##reg##offset (struct device *dev, struct device_attribute *attr, char *buf) \ | ||
464 | { \ | ||
465 | return show_temp_##reg (dev, buf, offset); \ | ||
466 | } \ | ||
467 | static ssize_t store_regs_temp_##reg##offset (struct device *dev, struct device_attribute *attr, const char *buf, size_t count) \ | ||
468 | { \ | ||
469 | return store_temp_##reg (dev, buf, count, offset); \ | ||
470 | } \ | ||
471 | static DEVICE_ATTR(temp##offset##_##reg, S_IRUGO| S_IWUSR, show_regs_temp_##reg##offset, store_regs_temp_##reg##offset); | ||
472 | |||
473 | #define sysfs_temp_offsets(offset) \ | 435 | #define sysfs_temp_offsets(offset) \ |
474 | sysfs_temp_offset(offset); \ | 436 | static SENSOR_DEVICE_ATTR(temp##offset##_input, S_IRUGO, \ |
475 | sysfs_temp_reg_offset(max, offset); \ | 437 | show_temp, NULL, offset); \ |
476 | sysfs_temp_reg_offset(max_hyst, offset); | 438 | static SENSOR_DEVICE_ATTR(temp##offset##_max, S_IRUGO | S_IWUSR, \ |
439 | show_temp_max, store_temp_max, offset); \ | ||
440 | static SENSOR_DEVICE_ATTR(temp##offset##_max_hyst, S_IRUGO | S_IWUSR, \ | ||
441 | show_temp_max_hyst, store_temp_max_hyst, offset); | ||
477 | 442 | ||
478 | sysfs_temp_offsets(1); | 443 | sysfs_temp_offsets(1); |
479 | sysfs_temp_offsets(2); | 444 | sysfs_temp_offsets(2); |
@@ -498,8 +463,7 @@ show_vrm_reg(struct device *dev, struct device_attribute *attr, char *buf) | |||
498 | static ssize_t | 463 | static ssize_t |
499 | store_vrm_reg(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) | 464 | store_vrm_reg(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) |
500 | { | 465 | { |
501 | struct i2c_client *client = to_i2c_client(dev); | 466 | struct w83781d_data *data = dev_get_drvdata(dev); |
502 | struct w83781d_data *data = i2c_get_clientdata(client); | ||
503 | u32 val; | 467 | u32 val; |
504 | 468 | ||
505 | val = simple_strtoul(buf, NULL, 10); | 469 | val = simple_strtoul(buf, NULL, 10); |
@@ -528,68 +492,67 @@ static ssize_t show_beep_mask (struct device *dev, struct device_attribute *attr | |||
528 | static ssize_t show_beep_enable (struct device *dev, struct device_attribute *attr, char *buf) | 492 | static ssize_t show_beep_enable (struct device *dev, struct device_attribute *attr, char *buf) |
529 | { | 493 | { |
530 | struct w83781d_data *data = w83781d_update_device(dev); | 494 | struct w83781d_data *data = w83781d_update_device(dev); |
531 | return sprintf(buf, "%ld\n", | 495 | return sprintf(buf, "%ld\n", (long)data->beep_enable); |
532 | (long)BEEP_ENABLE_FROM_REG(data->beep_enable)); | ||
533 | } | 496 | } |
534 | 497 | ||
535 | #define BEEP_ENABLE 0 /* Store beep_enable */ | ||
536 | #define BEEP_MASK 1 /* Store beep_mask */ | ||
537 | |||
538 | static ssize_t | 498 | static ssize_t |
539 | store_beep_reg(struct device *dev, const char *buf, size_t count, | 499 | store_beep_mask(struct device *dev, struct device_attribute *attr, |
540 | int update_mask) | 500 | const char *buf, size_t count) |
541 | { | 501 | { |
542 | struct i2c_client *client = to_i2c_client(dev); | 502 | struct w83781d_data *data = dev_get_drvdata(dev); |
543 | struct w83781d_data *data = i2c_get_clientdata(client); | 503 | u32 val; |
544 | u32 val, val2; | ||
545 | 504 | ||
546 | val = simple_strtoul(buf, NULL, 10); | 505 | val = simple_strtoul(buf, NULL, 10); |
547 | 506 | ||
548 | mutex_lock(&data->update_lock); | 507 | mutex_lock(&data->update_lock); |
508 | data->beep_mask = BEEP_MASK_TO_REG(val, data->type); | ||
509 | w83781d_write_value(data, W83781D_REG_BEEP_INTS1, | ||
510 | data->beep_mask & 0xff); | ||
511 | w83781d_write_value(data, W83781D_REG_BEEP_INTS2, | ||
512 | ((data->beep_mask >> 8) & 0x7f) | ||
513 | | data->beep_enable << 7); | ||
514 | if (data->type != w83781d && data->type != as99127f) { | ||
515 | w83781d_write_value(data, W83781D_REG_BEEP_INTS3, | ||
516 | ((data->beep_mask) >> 16) & 0xff); | ||
517 | } | ||
518 | mutex_unlock(&data->update_lock); | ||
549 | 519 | ||
550 | if (update_mask == BEEP_MASK) { /* We are storing beep_mask */ | 520 | return count; |
551 | data->beep_mask = BEEP_MASK_TO_REG(val, data->type); | 521 | } |
552 | w83781d_write_value(client, W83781D_REG_BEEP_INTS1, | ||
553 | data->beep_mask & 0xff); | ||
554 | |||
555 | if ((data->type != w83781d) && (data->type != as99127f)) { | ||
556 | w83781d_write_value(client, W83781D_REG_BEEP_INTS3, | ||
557 | ((data->beep_mask) >> 16) & 0xff); | ||
558 | } | ||
559 | 522 | ||
560 | val2 = (data->beep_mask >> 8) & 0x7f; | 523 | static ssize_t |
561 | } else { /* We are storing beep_enable */ | 524 | store_beep_enable(struct device *dev, struct device_attribute *attr, |
562 | val2 = w83781d_read_value(client, W83781D_REG_BEEP_INTS2) & 0x7f; | 525 | const char *buf, size_t count) |
563 | data->beep_enable = BEEP_ENABLE_TO_REG(val); | 526 | { |
564 | } | 527 | struct w83781d_data *data = dev_get_drvdata(dev); |
528 | u32 val; | ||
565 | 529 | ||
566 | w83781d_write_value(client, W83781D_REG_BEEP_INTS2, | 530 | val = simple_strtoul(buf, NULL, 10); |
567 | val2 | data->beep_enable << 7); | 531 | if (val != 0 && val != 1) |
532 | return -EINVAL; | ||
568 | 533 | ||
534 | mutex_lock(&data->update_lock); | ||
535 | data->beep_enable = val; | ||
536 | val = w83781d_read_value(data, W83781D_REG_BEEP_INTS2) & 0x7f; | ||
537 | val |= data->beep_enable << 7; | ||
538 | w83781d_write_value(data, W83781D_REG_BEEP_INTS2, val); | ||
569 | mutex_unlock(&data->update_lock); | 539 | mutex_unlock(&data->update_lock); |
540 | |||
570 | return count; | 541 | return count; |
571 | } | 542 | } |
572 | 543 | ||
573 | #define sysfs_beep(REG, reg) \ | 544 | static DEVICE_ATTR(beep_mask, S_IRUGO | S_IWUSR, |
574 | static ssize_t show_regs_beep_##reg (struct device *dev, struct device_attribute *attr, char *buf) \ | 545 | show_beep_mask, store_beep_mask); |
575 | { \ | 546 | static DEVICE_ATTR(beep_enable, S_IRUGO | S_IWUSR, |
576 | return show_beep_##reg(dev, attr, buf); \ | 547 | show_beep_enable, store_beep_enable); |
577 | } \ | ||
578 | static ssize_t store_regs_beep_##reg (struct device *dev, struct device_attribute *attr, const char *buf, size_t count) \ | ||
579 | { \ | ||
580 | return store_beep_reg(dev, buf, count, BEEP_##REG); \ | ||
581 | } \ | ||
582 | static DEVICE_ATTR(beep_##reg, S_IRUGO | S_IWUSR, show_regs_beep_##reg, store_regs_beep_##reg); | ||
583 | |||
584 | sysfs_beep(ENABLE, enable); | ||
585 | sysfs_beep(MASK, mask); | ||
586 | 548 | ||
587 | static ssize_t | 549 | static ssize_t |
588 | show_fan_div_reg(struct device *dev, char *buf, int nr) | 550 | show_fan_div(struct device *dev, struct device_attribute *da, char *buf) |
589 | { | 551 | { |
552 | struct sensor_device_attribute *attr = to_sensor_dev_attr(da); | ||
590 | struct w83781d_data *data = w83781d_update_device(dev); | 553 | struct w83781d_data *data = w83781d_update_device(dev); |
591 | return sprintf(buf, "%ld\n", | 554 | return sprintf(buf, "%ld\n", |
592 | (long) DIV_FROM_REG(data->fan_div[nr - 1])); | 555 | (long) DIV_FROM_REG(data->fan_div[attr->index])); |
593 | } | 556 | } |
594 | 557 | ||
595 | /* Note: we save and restore the fan minimum here, because its value is | 558 | /* Note: we save and restore the fan minimum here, because its value is |
@@ -597,11 +560,13 @@ show_fan_div_reg(struct device *dev, char *buf, int nr) | |||
597 | least surprise; the user doesn't expect the fan minimum to change just | 560 | least surprise; the user doesn't expect the fan minimum to change just |
598 | because the divisor changed. */ | 561 | because the divisor changed. */ |
599 | static ssize_t | 562 | static ssize_t |
600 | store_fan_div_reg(struct device *dev, const char *buf, size_t count, int nr) | 563 | store_fan_div(struct device *dev, struct device_attribute *da, |
564 | const char *buf, size_t count) | ||
601 | { | 565 | { |
602 | struct i2c_client *client = to_i2c_client(dev); | 566 | struct sensor_device_attribute *attr = to_sensor_dev_attr(da); |
603 | struct w83781d_data *data = i2c_get_clientdata(client); | 567 | struct w83781d_data *data = dev_get_drvdata(dev); |
604 | unsigned long min; | 568 | unsigned long min; |
569 | int nr = attr->index; | ||
605 | u8 reg; | 570 | u8 reg; |
606 | unsigned long val = simple_strtoul(buf, NULL, 10); | 571 | unsigned long val = simple_strtoul(buf, NULL, 10); |
607 | 572 | ||
@@ -613,77 +578,72 @@ store_fan_div_reg(struct device *dev, const char *buf, size_t count, int nr) | |||
613 | 578 | ||
614 | data->fan_div[nr] = DIV_TO_REG(val, data->type); | 579 | data->fan_div[nr] = DIV_TO_REG(val, data->type); |
615 | 580 | ||
616 | reg = (w83781d_read_value(client, nr==2 ? W83781D_REG_PIN : W83781D_REG_VID_FANDIV) | 581 | reg = (w83781d_read_value(data, nr==2 ? W83781D_REG_PIN : W83781D_REG_VID_FANDIV) |
617 | & (nr==0 ? 0xcf : 0x3f)) | 582 | & (nr==0 ? 0xcf : 0x3f)) |
618 | | ((data->fan_div[nr] & 0x03) << (nr==0 ? 4 : 6)); | 583 | | ((data->fan_div[nr] & 0x03) << (nr==0 ? 4 : 6)); |
619 | w83781d_write_value(client, nr==2 ? W83781D_REG_PIN : W83781D_REG_VID_FANDIV, reg); | 584 | w83781d_write_value(data, nr==2 ? W83781D_REG_PIN : W83781D_REG_VID_FANDIV, reg); |
620 | 585 | ||
621 | /* w83781d and as99127f don't have extended divisor bits */ | 586 | /* w83781d and as99127f don't have extended divisor bits */ |
622 | if (data->type != w83781d && data->type != as99127f) { | 587 | if (data->type != w83781d && data->type != as99127f) { |
623 | reg = (w83781d_read_value(client, W83781D_REG_VBAT) | 588 | reg = (w83781d_read_value(data, W83781D_REG_VBAT) |
624 | & ~(1 << (5 + nr))) | 589 | & ~(1 << (5 + nr))) |
625 | | ((data->fan_div[nr] & 0x04) << (3 + nr)); | 590 | | ((data->fan_div[nr] & 0x04) << (3 + nr)); |
626 | w83781d_write_value(client, W83781D_REG_VBAT, reg); | 591 | w83781d_write_value(data, W83781D_REG_VBAT, reg); |
627 | } | 592 | } |
628 | 593 | ||
629 | /* Restore fan_min */ | 594 | /* Restore fan_min */ |
630 | data->fan_min[nr] = FAN_TO_REG(min, DIV_FROM_REG(data->fan_div[nr])); | 595 | data->fan_min[nr] = FAN_TO_REG(min, DIV_FROM_REG(data->fan_div[nr])); |
631 | w83781d_write_value(client, W83781D_REG_FAN_MIN(nr+1), data->fan_min[nr]); | 596 | w83781d_write_value(data, W83781D_REG_FAN_MIN(nr), data->fan_min[nr]); |
632 | 597 | ||
633 | mutex_unlock(&data->update_lock); | 598 | mutex_unlock(&data->update_lock); |
634 | return count; | 599 | return count; |
635 | } | 600 | } |
636 | 601 | ||
637 | #define sysfs_fan_div(offset) \ | 602 | static SENSOR_DEVICE_ATTR(fan1_div, S_IRUGO | S_IWUSR, |
638 | static ssize_t show_regs_fan_div_##offset (struct device *dev, struct device_attribute *attr, char *buf) \ | 603 | show_fan_div, store_fan_div, 0); |
639 | { \ | 604 | static SENSOR_DEVICE_ATTR(fan2_div, S_IRUGO | S_IWUSR, |
640 | return show_fan_div_reg(dev, buf, offset); \ | 605 | show_fan_div, store_fan_div, 1); |
641 | } \ | 606 | static SENSOR_DEVICE_ATTR(fan3_div, S_IRUGO | S_IWUSR, |
642 | static ssize_t store_regs_fan_div_##offset (struct device *dev, struct device_attribute *attr, const char *buf, size_t count) \ | 607 | show_fan_div, store_fan_div, 2); |
643 | { \ | ||
644 | return store_fan_div_reg(dev, buf, count, offset - 1); \ | ||
645 | } \ | ||
646 | static DEVICE_ATTR(fan##offset##_div, S_IRUGO | S_IWUSR, show_regs_fan_div_##offset, store_regs_fan_div_##offset); | ||
647 | |||
648 | sysfs_fan_div(1); | ||
649 | sysfs_fan_div(2); | ||
650 | sysfs_fan_div(3); | ||
651 | 608 | ||
652 | static ssize_t | 609 | static ssize_t |
653 | show_pwm_reg(struct device *dev, char *buf, int nr) | 610 | show_pwm(struct device *dev, struct device_attribute *da, char *buf) |
654 | { | 611 | { |
612 | struct sensor_device_attribute *attr = to_sensor_dev_attr(da); | ||
655 | struct w83781d_data *data = w83781d_update_device(dev); | 613 | struct w83781d_data *data = w83781d_update_device(dev); |
656 | return sprintf(buf, "%ld\n", (long) PWM_FROM_REG(data->pwm[nr - 1])); | 614 | return sprintf(buf, "%d\n", (int)data->pwm[attr->index]); |
657 | } | 615 | } |
658 | 616 | ||
659 | static ssize_t | 617 | static ssize_t |
660 | show_pwmenable_reg(struct device *dev, char *buf, int nr) | 618 | show_pwm2_enable(struct device *dev, struct device_attribute *da, char *buf) |
661 | { | 619 | { |
662 | struct w83781d_data *data = w83781d_update_device(dev); | 620 | struct w83781d_data *data = w83781d_update_device(dev); |
663 | return sprintf(buf, "%ld\n", (long) data->pwmenable[nr - 1]); | 621 | return sprintf(buf, "%d\n", (int)data->pwm2_enable); |
664 | } | 622 | } |
665 | 623 | ||
666 | static ssize_t | 624 | static ssize_t |
667 | store_pwm_reg(struct device *dev, const char *buf, size_t count, int nr) | 625 | store_pwm(struct device *dev, struct device_attribute *da, const char *buf, |
626 | size_t count) | ||
668 | { | 627 | { |
669 | struct i2c_client *client = to_i2c_client(dev); | 628 | struct sensor_device_attribute *attr = to_sensor_dev_attr(da); |
670 | struct w83781d_data *data = i2c_get_clientdata(client); | 629 | struct w83781d_data *data = dev_get_drvdata(dev); |
630 | int nr = attr->index; | ||
671 | u32 val; | 631 | u32 val; |
672 | 632 | ||
673 | val = simple_strtoul(buf, NULL, 10); | 633 | val = simple_strtoul(buf, NULL, 10); |
674 | 634 | ||
675 | mutex_lock(&data->update_lock); | 635 | mutex_lock(&data->update_lock); |
676 | data->pwm[nr - 1] = PWM_TO_REG(val); | 636 | data->pwm[nr] = SENSORS_LIMIT(val, 0, 255); |
677 | w83781d_write_value(client, W83781D_REG_PWM(nr), data->pwm[nr - 1]); | 637 | w83781d_write_value(data, W83781D_REG_PWM[nr], data->pwm[nr]); |
678 | mutex_unlock(&data->update_lock); | 638 | mutex_unlock(&data->update_lock); |
679 | return count; | 639 | return count; |
680 | } | 640 | } |
681 | 641 | ||
682 | static ssize_t | 642 | static ssize_t |
683 | store_pwmenable_reg(struct device *dev, const char *buf, size_t count, int nr) | 643 | store_pwm2_enable(struct device *dev, struct device_attribute *da, |
644 | const char *buf, size_t count) | ||
684 | { | 645 | { |
685 | struct i2c_client *client = to_i2c_client(dev); | 646 | struct w83781d_data *data = dev_get_drvdata(dev); |
686 | struct w83781d_data *data = i2c_get_clientdata(client); | ||
687 | u32 val, reg; | 647 | u32 val, reg; |
688 | 648 | ||
689 | val = simple_strtoul(buf, NULL, 10); | 649 | val = simple_strtoul(buf, NULL, 10); |
@@ -693,15 +653,15 @@ store_pwmenable_reg(struct device *dev, const char *buf, size_t count, int nr) | |||
693 | switch (val) { | 653 | switch (val) { |
694 | case 0: | 654 | case 0: |
695 | case 1: | 655 | case 1: |
696 | reg = w83781d_read_value(client, W83781D_REG_PWMCLK12); | 656 | reg = w83781d_read_value(data, W83781D_REG_PWMCLK12); |
697 | w83781d_write_value(client, W83781D_REG_PWMCLK12, | 657 | w83781d_write_value(data, W83781D_REG_PWMCLK12, |
698 | (reg & 0xf7) | (val << 3)); | 658 | (reg & 0xf7) | (val << 3)); |
699 | 659 | ||
700 | reg = w83781d_read_value(client, W83781D_REG_BEEP_CONFIG); | 660 | reg = w83781d_read_value(data, W83781D_REG_BEEP_CONFIG); |
701 | w83781d_write_value(client, W83781D_REG_BEEP_CONFIG, | 661 | w83781d_write_value(data, W83781D_REG_BEEP_CONFIG, |
702 | (reg & 0xef) | (!val << 4)); | 662 | (reg & 0xef) | (!val << 4)); |
703 | 663 | ||
704 | data->pwmenable[nr - 1] = val; | 664 | data->pwm2_enable = val; |
705 | break; | 665 | break; |
706 | 666 | ||
707 | default: | 667 | default: |
@@ -713,50 +673,29 @@ store_pwmenable_reg(struct device *dev, const char *buf, size_t count, int nr) | |||
713 | return count; | 673 | return count; |
714 | } | 674 | } |
715 | 675 | ||
716 | #define sysfs_pwm(offset) \ | 676 | static SENSOR_DEVICE_ATTR(pwm1, S_IRUGO | S_IWUSR, show_pwm, store_pwm, 0); |
717 | static ssize_t show_regs_pwm_##offset (struct device *dev, struct device_attribute *attr, char *buf) \ | 677 | static SENSOR_DEVICE_ATTR(pwm2, S_IRUGO | S_IWUSR, show_pwm, store_pwm, 1); |
718 | { \ | 678 | static SENSOR_DEVICE_ATTR(pwm3, S_IRUGO | S_IWUSR, show_pwm, store_pwm, 2); |
719 | return show_pwm_reg(dev, buf, offset); \ | 679 | static SENSOR_DEVICE_ATTR(pwm4, S_IRUGO | S_IWUSR, show_pwm, store_pwm, 3); |
720 | } \ | 680 | /* only PWM2 can be enabled/disabled */ |
721 | static ssize_t store_regs_pwm_##offset (struct device *dev, struct device_attribute *attr, \ | 681 | static DEVICE_ATTR(pwm2_enable, S_IRUGO | S_IWUSR, |
722 | const char *buf, size_t count) \ | 682 | show_pwm2_enable, store_pwm2_enable); |
723 | { \ | ||
724 | return store_pwm_reg(dev, buf, count, offset); \ | ||
725 | } \ | ||
726 | static DEVICE_ATTR(pwm##offset, S_IRUGO | S_IWUSR, \ | ||
727 | show_regs_pwm_##offset, store_regs_pwm_##offset); | ||
728 | |||
729 | #define sysfs_pwmenable(offset) \ | ||
730 | static ssize_t show_regs_pwmenable_##offset (struct device *dev, struct device_attribute *attr, char *buf) \ | ||
731 | { \ | ||
732 | return show_pwmenable_reg(dev, buf, offset); \ | ||
733 | } \ | ||
734 | static ssize_t store_regs_pwmenable_##offset (struct device *dev, struct device_attribute *attr, \ | ||
735 | const char *buf, size_t count) \ | ||
736 | { \ | ||
737 | return store_pwmenable_reg(dev, buf, count, offset); \ | ||
738 | } \ | ||
739 | static DEVICE_ATTR(pwm##offset##_enable, S_IRUGO | S_IWUSR, \ | ||
740 | show_regs_pwmenable_##offset, store_regs_pwmenable_##offset); | ||
741 | |||
742 | sysfs_pwm(1); | ||
743 | sysfs_pwm(2); | ||
744 | sysfs_pwmenable(2); /* only PWM2 can be enabled/disabled */ | ||
745 | sysfs_pwm(3); | ||
746 | sysfs_pwm(4); | ||
747 | 683 | ||
748 | static ssize_t | 684 | static ssize_t |
749 | show_sensor_reg(struct device *dev, char *buf, int nr) | 685 | show_sensor(struct device *dev, struct device_attribute *da, char *buf) |
750 | { | 686 | { |
687 | struct sensor_device_attribute *attr = to_sensor_dev_attr(da); | ||
751 | struct w83781d_data *data = w83781d_update_device(dev); | 688 | struct w83781d_data *data = w83781d_update_device(dev); |
752 | return sprintf(buf, "%ld\n", (long) data->sens[nr - 1]); | 689 | return sprintf(buf, "%d\n", (int)data->sens[attr->index]); |
753 | } | 690 | } |
754 | 691 | ||
755 | static ssize_t | 692 | static ssize_t |
756 | store_sensor_reg(struct device *dev, const char *buf, size_t count, int nr) | 693 | store_sensor(struct device *dev, struct device_attribute *da, |
694 | const char *buf, size_t count) | ||
757 | { | 695 | { |
758 | struct i2c_client *client = to_i2c_client(dev); | 696 | struct sensor_device_attribute *attr = to_sensor_dev_attr(da); |
759 | struct w83781d_data *data = i2c_get_clientdata(client); | 697 | struct w83781d_data *data = dev_get_drvdata(dev); |
698 | int nr = attr->index; | ||
760 | u32 val, tmp; | 699 | u32 val, tmp; |
761 | 700 | ||
762 | val = simple_strtoul(buf, NULL, 10); | 701 | val = simple_strtoul(buf, NULL, 10); |
@@ -765,28 +704,28 @@ store_sensor_reg(struct device *dev, const char *buf, size_t count, int nr) | |||
765 | 704 | ||
766 | switch (val) { | 705 | switch (val) { |
767 | case 1: /* PII/Celeron diode */ | 706 | case 1: /* PII/Celeron diode */ |
768 | tmp = w83781d_read_value(client, W83781D_REG_SCFG1); | 707 | tmp = w83781d_read_value(data, W83781D_REG_SCFG1); |
769 | w83781d_write_value(client, W83781D_REG_SCFG1, | 708 | w83781d_write_value(data, W83781D_REG_SCFG1, |
770 | tmp | BIT_SCFG1[nr - 1]); | 709 | tmp | BIT_SCFG1[nr]); |
771 | tmp = w83781d_read_value(client, W83781D_REG_SCFG2); | 710 | tmp = w83781d_read_value(data, W83781D_REG_SCFG2); |
772 | w83781d_write_value(client, W83781D_REG_SCFG2, | 711 | w83781d_write_value(data, W83781D_REG_SCFG2, |
773 | tmp | BIT_SCFG2[nr - 1]); | 712 | tmp | BIT_SCFG2[nr]); |
774 | data->sens[nr - 1] = val; | 713 | data->sens[nr] = val; |
775 | break; | 714 | break; |
776 | case 2: /* 3904 */ | 715 | case 2: /* 3904 */ |
777 | tmp = w83781d_read_value(client, W83781D_REG_SCFG1); | 716 | tmp = w83781d_read_value(data, W83781D_REG_SCFG1); |
778 | w83781d_write_value(client, W83781D_REG_SCFG1, | 717 | w83781d_write_value(data, W83781D_REG_SCFG1, |
779 | tmp | BIT_SCFG1[nr - 1]); | 718 | tmp | BIT_SCFG1[nr]); |
780 | tmp = w83781d_read_value(client, W83781D_REG_SCFG2); | 719 | tmp = w83781d_read_value(data, W83781D_REG_SCFG2); |
781 | w83781d_write_value(client, W83781D_REG_SCFG2, | 720 | w83781d_write_value(data, W83781D_REG_SCFG2, |
782 | tmp & ~BIT_SCFG2[nr - 1]); | 721 | tmp & ~BIT_SCFG2[nr]); |
783 | data->sens[nr - 1] = val; | 722 | data->sens[nr] = val; |
784 | break; | 723 | break; |
785 | case W83781D_DEFAULT_BETA: /* thermistor */ | 724 | case W83781D_DEFAULT_BETA: /* thermistor */ |
786 | tmp = w83781d_read_value(client, W83781D_REG_SCFG1); | 725 | tmp = w83781d_read_value(data, W83781D_REG_SCFG1); |
787 | w83781d_write_value(client, W83781D_REG_SCFG1, | 726 | w83781d_write_value(data, W83781D_REG_SCFG1, |
788 | tmp & ~BIT_SCFG1[nr - 1]); | 727 | tmp & ~BIT_SCFG1[nr]); |
789 | data->sens[nr - 1] = val; | 728 | data->sens[nr] = val; |
790 | break; | 729 | break; |
791 | default: | 730 | default: |
792 | dev_err(dev, "Invalid sensor type %ld; must be 1, 2, or %d\n", | 731 | dev_err(dev, "Invalid sensor type %ld; must be 1, 2, or %d\n", |
@@ -798,20 +737,22 @@ store_sensor_reg(struct device *dev, const char *buf, size_t count, int nr) | |||
798 | return count; | 737 | return count; |
799 | } | 738 | } |
800 | 739 | ||
801 | #define sysfs_sensor(offset) \ | 740 | static SENSOR_DEVICE_ATTR(temp1_type, S_IRUGO | S_IWUSR, |
802 | static ssize_t show_regs_sensor_##offset (struct device *dev, struct device_attribute *attr, char *buf) \ | 741 | show_sensor, store_sensor, 0); |
803 | { \ | 742 | static SENSOR_DEVICE_ATTR(temp2_type, S_IRUGO | S_IWUSR, |
804 | return show_sensor_reg(dev, buf, offset); \ | 743 | show_sensor, store_sensor, 0); |
805 | } \ | 744 | static SENSOR_DEVICE_ATTR(temp3_type, S_IRUGO | S_IWUSR, |
806 | static ssize_t store_regs_sensor_##offset (struct device *dev, struct device_attribute *attr, const char *buf, size_t count) \ | 745 | show_sensor, store_sensor, 0); |
807 | { \ | ||
808 | return store_sensor_reg(dev, buf, count, offset); \ | ||
809 | } \ | ||
810 | static DEVICE_ATTR(temp##offset##_type, S_IRUGO | S_IWUSR, show_regs_sensor_##offset, store_regs_sensor_##offset); | ||
811 | 746 | ||
812 | sysfs_sensor(1); | 747 | /* I2C devices get this name attribute automatically, but for ISA devices |
813 | sysfs_sensor(2); | 748 | we must create it by ourselves. */ |
814 | sysfs_sensor(3); | 749 | static ssize_t |
750 | show_name(struct device *dev, struct device_attribute *devattr, char *buf) | ||
751 | { | ||
752 | struct w83781d_data *data = dev_get_drvdata(dev); | ||
753 | return sprintf(buf, "%s\n", data->client.name); | ||
754 | } | ||
755 | static DEVICE_ATTR(name, S_IRUGO, show_name, NULL); | ||
815 | 756 | ||
816 | /* This function is called when: | 757 | /* This function is called when: |
817 | * w83781d_driver is inserted (when this module is loaded), for each | 758 | * w83781d_driver is inserted (when this module is loaded), for each |
@@ -825,12 +766,6 @@ w83781d_attach_adapter(struct i2c_adapter *adapter) | |||
825 | return i2c_probe(adapter, &addr_data, w83781d_detect); | 766 | return i2c_probe(adapter, &addr_data, w83781d_detect); |
826 | } | 767 | } |
827 | 768 | ||
828 | static int | ||
829 | w83781d_isa_attach_adapter(struct i2c_adapter *adapter) | ||
830 | { | ||
831 | return w83781d_detect(adapter, isa_address, -1); | ||
832 | } | ||
833 | |||
834 | /* Assumes that adapter is of I2C, not ISA variety. | 769 | /* Assumes that adapter is of I2C, not ISA variety. |
835 | * OTHERWISE DON'T CALL THIS | 770 | * OTHERWISE DON'T CALL THIS |
836 | */ | 771 | */ |
@@ -862,12 +797,12 @@ w83781d_detect_subclients(struct i2c_adapter *adapter, int address, int kind, | |||
862 | goto ERROR_SC_1; | 797 | goto ERROR_SC_1; |
863 | } | 798 | } |
864 | } | 799 | } |
865 | w83781d_write_value(new_client, W83781D_REG_I2C_SUBADDR, | 800 | w83781d_write_value(data, W83781D_REG_I2C_SUBADDR, |
866 | (force_subclients[2] & 0x07) | | 801 | (force_subclients[2] & 0x07) | |
867 | ((force_subclients[3] & 0x07) << 4)); | 802 | ((force_subclients[3] & 0x07) << 4)); |
868 | data->lm75[0]->addr = force_subclients[2]; | 803 | data->lm75[0]->addr = force_subclients[2]; |
869 | } else { | 804 | } else { |
870 | val1 = w83781d_read_value(new_client, W83781D_REG_I2C_SUBADDR); | 805 | val1 = w83781d_read_value(data, W83781D_REG_I2C_SUBADDR); |
871 | data->lm75[0]->addr = 0x48 + (val1 & 0x07); | 806 | data->lm75[0]->addr = 0x48 + (val1 & 0x07); |
872 | } | 807 | } |
873 | 808 | ||
@@ -937,20 +872,20 @@ ERROR_SC_0: | |||
937 | return err; | 872 | return err; |
938 | } | 873 | } |
939 | 874 | ||
940 | #define IN_UNIT_ATTRS(X) \ | 875 | #define IN_UNIT_ATTRS(X) \ |
941 | &dev_attr_in##X##_input.attr, \ | 876 | &sensor_dev_attr_in##X##_input.dev_attr.attr, \ |
942 | &dev_attr_in##X##_min.attr, \ | 877 | &sensor_dev_attr_in##X##_min.dev_attr.attr, \ |
943 | &dev_attr_in##X##_max.attr | 878 | &sensor_dev_attr_in##X##_max.dev_attr.attr |
944 | 879 | ||
945 | #define FAN_UNIT_ATTRS(X) \ | 880 | #define FAN_UNIT_ATTRS(X) \ |
946 | &dev_attr_fan##X##_input.attr, \ | 881 | &sensor_dev_attr_fan##X##_input.dev_attr.attr, \ |
947 | &dev_attr_fan##X##_min.attr, \ | 882 | &sensor_dev_attr_fan##X##_min.dev_attr.attr, \ |
948 | &dev_attr_fan##X##_div.attr | 883 | &sensor_dev_attr_fan##X##_div.dev_attr.attr |
949 | 884 | ||
950 | #define TEMP_UNIT_ATTRS(X) \ | 885 | #define TEMP_UNIT_ATTRS(X) \ |
951 | &dev_attr_temp##X##_input.attr, \ | 886 | &sensor_dev_attr_temp##X##_input.dev_attr.attr, \ |
952 | &dev_attr_temp##X##_max.attr, \ | 887 | &sensor_dev_attr_temp##X##_max.dev_attr.attr, \ |
953 | &dev_attr_temp##X##_max_hyst.attr | 888 | &sensor_dev_attr_temp##X##_max_hyst.dev_attr.attr |
954 | 889 | ||
955 | static struct attribute* w83781d_attributes[] = { | 890 | static struct attribute* w83781d_attributes[] = { |
956 | IN_UNIT_ATTRS(0), | 891 | IN_UNIT_ATTRS(0), |
@@ -980,91 +915,115 @@ static struct attribute *w83781d_attributes_opt[] = { | |||
980 | IN_UNIT_ATTRS(7), | 915 | IN_UNIT_ATTRS(7), |
981 | IN_UNIT_ATTRS(8), | 916 | IN_UNIT_ATTRS(8), |
982 | TEMP_UNIT_ATTRS(3), | 917 | TEMP_UNIT_ATTRS(3), |
983 | &dev_attr_pwm1.attr, | 918 | &sensor_dev_attr_pwm1.dev_attr.attr, |
984 | &dev_attr_pwm2.attr, | 919 | &sensor_dev_attr_pwm2.dev_attr.attr, |
920 | &sensor_dev_attr_pwm3.dev_attr.attr, | ||
921 | &sensor_dev_attr_pwm4.dev_attr.attr, | ||
985 | &dev_attr_pwm2_enable.attr, | 922 | &dev_attr_pwm2_enable.attr, |
986 | &dev_attr_pwm3.attr, | 923 | &sensor_dev_attr_temp1_type.dev_attr.attr, |
987 | &dev_attr_pwm4.attr, | 924 | &sensor_dev_attr_temp2_type.dev_attr.attr, |
988 | &dev_attr_temp1_type.attr, | 925 | &sensor_dev_attr_temp3_type.dev_attr.attr, |
989 | &dev_attr_temp2_type.attr, | ||
990 | &dev_attr_temp3_type.attr, | ||
991 | NULL | 926 | NULL |
992 | }; | 927 | }; |
993 | static const struct attribute_group w83781d_group_opt = { | 928 | static const struct attribute_group w83781d_group_opt = { |
994 | .attrs = w83781d_attributes_opt, | 929 | .attrs = w83781d_attributes_opt, |
995 | }; | 930 | }; |
996 | 931 | ||
932 | /* No clean up is done on error, it's up to the caller */ | ||
997 | static int | 933 | static int |
998 | w83781d_detect(struct i2c_adapter *adapter, int address, int kind) | 934 | w83781d_create_files(struct device *dev, int kind, int is_isa) |
999 | { | 935 | { |
1000 | int i = 0, val1 = 0, val2; | ||
1001 | struct i2c_client *client; | ||
1002 | struct device *dev; | ||
1003 | struct w83781d_data *data; | ||
1004 | int err; | 936 | int err; |
1005 | const char *client_name = ""; | ||
1006 | int is_isa = i2c_is_isa_adapter(adapter); | ||
1007 | enum vendor { winbond, asus } vendid; | ||
1008 | 937 | ||
1009 | if (!is_isa | 938 | if ((err = sysfs_create_group(&dev->kobj, &w83781d_group))) |
1010 | && !i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA)) { | 939 | return err; |
1011 | err = -EINVAL; | 940 | |
1012 | goto ERROR0; | 941 | if (kind != w83783s) { |
942 | if ((err = device_create_file(dev, | ||
943 | &sensor_dev_attr_in1_input.dev_attr)) | ||
944 | || (err = device_create_file(dev, | ||
945 | &sensor_dev_attr_in1_min.dev_attr)) | ||
946 | || (err = device_create_file(dev, | ||
947 | &sensor_dev_attr_in1_max.dev_attr))) | ||
948 | return err; | ||
949 | } | ||
950 | if (kind != as99127f && kind != w83781d && kind != w83783s) { | ||
951 | if ((err = device_create_file(dev, | ||
952 | &sensor_dev_attr_in7_input.dev_attr)) | ||
953 | || (err = device_create_file(dev, | ||
954 | &sensor_dev_attr_in7_min.dev_attr)) | ||
955 | || (err = device_create_file(dev, | ||
956 | &sensor_dev_attr_in7_max.dev_attr)) | ||
957 | || (err = device_create_file(dev, | ||
958 | &sensor_dev_attr_in8_input.dev_attr)) | ||
959 | || (err = device_create_file(dev, | ||
960 | &sensor_dev_attr_in8_min.dev_attr)) | ||
961 | || (err = device_create_file(dev, | ||
962 | &sensor_dev_attr_in8_max.dev_attr))) | ||
963 | return err; | ||
964 | } | ||
965 | if (kind != w83783s) { | ||
966 | if ((err = device_create_file(dev, | ||
967 | &sensor_dev_attr_temp3_input.dev_attr)) | ||
968 | || (err = device_create_file(dev, | ||
969 | &sensor_dev_attr_temp3_max.dev_attr)) | ||
970 | || (err = device_create_file(dev, | ||
971 | &sensor_dev_attr_temp3_max_hyst.dev_attr))) | ||
972 | return err; | ||
1013 | } | 973 | } |
1014 | 974 | ||
1015 | /* Prevent users from forcing a kind for a bus it isn't supposed | 975 | if (kind != w83781d && kind != as99127f) { |
1016 | to possibly be on */ | 976 | if ((err = device_create_file(dev, |
1017 | if (is_isa && (kind == as99127f || kind == w83783s)) { | 977 | &sensor_dev_attr_pwm1.dev_attr)) |
1018 | dev_err(&adapter->dev, | 978 | || (err = device_create_file(dev, |
1019 | "Cannot force I2C-only chip for ISA address 0x%02x.\n", | 979 | &sensor_dev_attr_pwm2.dev_attr)) |
1020 | address); | 980 | || (err = device_create_file(dev, &dev_attr_pwm2_enable))) |
1021 | err = -EINVAL; | 981 | return err; |
1022 | goto ERROR0; | ||
1023 | } | 982 | } |
1024 | 983 | if (kind == w83782d && !is_isa) { | |
1025 | if (is_isa) | 984 | if ((err = device_create_file(dev, |
1026 | if (!request_region(address, W83781D_EXTENT, | 985 | &sensor_dev_attr_pwm3.dev_attr)) |
1027 | w83781d_isa_driver.driver.name)) { | 986 | || (err = device_create_file(dev, |
1028 | dev_dbg(&adapter->dev, "Request of region " | 987 | &sensor_dev_attr_pwm4.dev_attr))) |
1029 | "0x%x-0x%x for w83781d failed\n", address, | 988 | return err; |
1030 | address + W83781D_EXTENT - 1); | 989 | } |
1031 | err = -EBUSY; | 990 | |
1032 | goto ERROR0; | 991 | if (kind != as99127f && kind != w83781d) { |
992 | if ((err = device_create_file(dev, | ||
993 | &sensor_dev_attr_temp1_type.dev_attr)) | ||
994 | || (err = device_create_file(dev, | ||
995 | &sensor_dev_attr_temp2_type.dev_attr))) | ||
996 | return err; | ||
997 | if (kind != w83783s) { | ||
998 | if ((err = device_create_file(dev, | ||
999 | &sensor_dev_attr_temp3_type.dev_attr))) | ||
1000 | return err; | ||
1033 | } | 1001 | } |
1002 | } | ||
1034 | 1003 | ||
1035 | /* Probe whether there is anything available on this address. Already | 1004 | if (is_isa) { |
1036 | done for SMBus clients */ | 1005 | err = device_create_file(&pdev->dev, &dev_attr_name); |
1037 | if (kind < 0) { | 1006 | if (err) |
1038 | if (is_isa) { | 1007 | return err; |
1008 | } | ||
1039 | 1009 | ||
1040 | #define REALLY_SLOW_IO | 1010 | return 0; |
1041 | /* We need the timeouts for at least some LM78-like | 1011 | } |
1042 | chips. But only if we read 'undefined' registers. */ | ||
1043 | i = inb_p(address + 1); | ||
1044 | if (inb_p(address + 2) != i | ||
1045 | || inb_p(address + 3) != i | ||
1046 | || inb_p(address + 7) != i) { | ||
1047 | dev_dbg(&adapter->dev, "Detection of w83781d " | ||
1048 | "chip failed at step 1\n"); | ||
1049 | err = -ENODEV; | ||
1050 | goto ERROR1; | ||
1051 | } | ||
1052 | #undef REALLY_SLOW_IO | ||
1053 | 1012 | ||
1054 | /* Let's just hope nothing breaks here */ | 1013 | static int |
1055 | i = inb_p(address + 5) & 0x7f; | 1014 | w83781d_detect(struct i2c_adapter *adapter, int address, int kind) |
1056 | outb_p(~i & 0x7f, address + 5); | 1015 | { |
1057 | val2 = inb_p(address + 5) & 0x7f; | 1016 | int val1 = 0, val2; |
1058 | if (val2 != (~i & 0x7f)) { | 1017 | struct i2c_client *client; |
1059 | outb_p(i, address + 5); | 1018 | struct device *dev; |
1060 | dev_dbg(&adapter->dev, "Detection of w83781d " | 1019 | struct w83781d_data *data; |
1061 | "chip failed at step 2 (0x%x != " | 1020 | int err; |
1062 | "0x%x at 0x%x)\n", val2, ~i & 0x7f, | 1021 | const char *client_name = ""; |
1063 | address + 5); | 1022 | enum vendor { winbond, asus } vendid; |
1064 | err = -ENODEV; | 1023 | |
1065 | goto ERROR1; | 1024 | if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA)) { |
1066 | } | 1025 | err = -EINVAL; |
1067 | } | 1026 | goto ERROR1; |
1068 | } | 1027 | } |
1069 | 1028 | ||
1070 | /* OK. For now, we presume we have a valid client. We now create the | 1029 | /* OK. For now, we presume we have a valid client. We now create the |
@@ -1081,8 +1040,7 @@ w83781d_detect(struct i2c_adapter *adapter, int address, int kind) | |||
1081 | client->addr = address; | 1040 | client->addr = address; |
1082 | mutex_init(&data->lock); | 1041 | mutex_init(&data->lock); |
1083 | client->adapter = adapter; | 1042 | client->adapter = adapter; |
1084 | client->driver = is_isa ? &w83781d_isa_driver : &w83781d_driver; | 1043 | client->driver = &w83781d_driver; |
1085 | client->flags = 0; | ||
1086 | dev = &client->dev; | 1044 | dev = &client->dev; |
1087 | 1045 | ||
1088 | /* Now, we do the remaining detection. */ | 1046 | /* Now, we do the remaining detection. */ |
@@ -1092,14 +1050,14 @@ w83781d_detect(struct i2c_adapter *adapter, int address, int kind) | |||
1092 | force_*=... parameter, and the Winbond will be reset to the right | 1050 | force_*=... parameter, and the Winbond will be reset to the right |
1093 | bank. */ | 1051 | bank. */ |
1094 | if (kind < 0) { | 1052 | if (kind < 0) { |
1095 | if (w83781d_read_value(client, W83781D_REG_CONFIG) & 0x80) { | 1053 | if (w83781d_read_value(data, W83781D_REG_CONFIG) & 0x80) { |
1096 | dev_dbg(&adapter->dev, "Detection of w83781d chip " | 1054 | dev_dbg(&adapter->dev, "Detection of w83781d chip " |
1097 | "failed at step 3\n"); | 1055 | "failed at step 3\n"); |
1098 | err = -ENODEV; | 1056 | err = -ENODEV; |
1099 | goto ERROR2; | 1057 | goto ERROR2; |
1100 | } | 1058 | } |
1101 | val1 = w83781d_read_value(client, W83781D_REG_BANK); | 1059 | val1 = w83781d_read_value(data, W83781D_REG_BANK); |
1102 | val2 = w83781d_read_value(client, W83781D_REG_CHIPMAN); | 1060 | val2 = w83781d_read_value(data, W83781D_REG_CHIPMAN); |
1103 | /* Check for Winbond or Asus ID if in bank 0 */ | 1061 | /* Check for Winbond or Asus ID if in bank 0 */ |
1104 | if ((!(val1 & 0x07)) && | 1062 | if ((!(val1 & 0x07)) && |
1105 | (((!(val1 & 0x80)) && (val2 != 0xa3) && (val2 != 0xc3)) | 1063 | (((!(val1 & 0x80)) && (val2 != 0xa3) && (val2 != 0xc3)) |
@@ -1111,10 +1069,10 @@ w83781d_detect(struct i2c_adapter *adapter, int address, int kind) | |||
1111 | } | 1069 | } |
1112 | /* If Winbond SMBus, check address at 0x48. | 1070 | /* If Winbond SMBus, check address at 0x48. |
1113 | Asus doesn't support, except for as99127f rev.2 */ | 1071 | Asus doesn't support, except for as99127f rev.2 */ |
1114 | if ((!is_isa) && (((!(val1 & 0x80)) && (val2 == 0xa3)) || | 1072 | if ((!(val1 & 0x80) && (val2 == 0xa3)) || |
1115 | ((val1 & 0x80) && (val2 == 0x5c)))) { | 1073 | ((val1 & 0x80) && (val2 == 0x5c))) { |
1116 | if (w83781d_read_value | 1074 | if (w83781d_read_value |
1117 | (client, W83781D_REG_I2C_ADDR) != address) { | 1075 | (data, W83781D_REG_I2C_ADDR) != address) { |
1118 | dev_dbg(&adapter->dev, "Detection of w83781d " | 1076 | dev_dbg(&adapter->dev, "Detection of w83781d " |
1119 | "chip failed at step 5\n"); | 1077 | "chip failed at step 5\n"); |
1120 | err = -ENODEV; | 1078 | err = -ENODEV; |
@@ -1125,14 +1083,14 @@ w83781d_detect(struct i2c_adapter *adapter, int address, int kind) | |||
1125 | 1083 | ||
1126 | /* We have either had a force parameter, or we have already detected the | 1084 | /* We have either had a force parameter, or we have already detected the |
1127 | Winbond. Put it now into bank 0 and Vendor ID High Byte */ | 1085 | Winbond. Put it now into bank 0 and Vendor ID High Byte */ |
1128 | w83781d_write_value(client, W83781D_REG_BANK, | 1086 | w83781d_write_value(data, W83781D_REG_BANK, |
1129 | (w83781d_read_value(client, W83781D_REG_BANK) | 1087 | (w83781d_read_value(data, W83781D_REG_BANK) |
1130 | & 0x78) | 0x80); | 1088 | & 0x78) | 0x80); |
1131 | 1089 | ||
1132 | /* Determine the chip type. */ | 1090 | /* Determine the chip type. */ |
1133 | if (kind <= 0) { | 1091 | if (kind <= 0) { |
1134 | /* get vendor ID */ | 1092 | /* get vendor ID */ |
1135 | val2 = w83781d_read_value(client, W83781D_REG_CHIPMAN); | 1093 | val2 = w83781d_read_value(data, W83781D_REG_CHIPMAN); |
1136 | if (val2 == 0x5c) | 1094 | if (val2 == 0x5c) |
1137 | vendid = winbond; | 1095 | vendid = winbond; |
1138 | else if (val2 == 0x12) | 1096 | else if (val2 == 0x12) |
@@ -1144,17 +1102,16 @@ w83781d_detect(struct i2c_adapter *adapter, int address, int kind) | |||
1144 | goto ERROR2; | 1102 | goto ERROR2; |
1145 | } | 1103 | } |
1146 | 1104 | ||
1147 | val1 = w83781d_read_value(client, W83781D_REG_WCHIPID); | 1105 | val1 = w83781d_read_value(data, W83781D_REG_WCHIPID); |
1148 | if ((val1 == 0x10 || val1 == 0x11) && vendid == winbond) | 1106 | if ((val1 == 0x10 || val1 == 0x11) && vendid == winbond) |
1149 | kind = w83781d; | 1107 | kind = w83781d; |
1150 | else if (val1 == 0x30 && vendid == winbond) | 1108 | else if (val1 == 0x30 && vendid == winbond) |
1151 | kind = w83782d; | 1109 | kind = w83782d; |
1152 | else if (val1 == 0x40 && vendid == winbond && !is_isa | 1110 | else if (val1 == 0x40 && vendid == winbond && address == 0x2d) |
1153 | && address == 0x2d) | ||
1154 | kind = w83783s; | 1111 | kind = w83783s; |
1155 | else if (val1 == 0x21 && vendid == winbond) | 1112 | else if (val1 == 0x21 && vendid == winbond) |
1156 | kind = w83627hf; | 1113 | kind = w83627hf; |
1157 | else if (val1 == 0x31 && !is_isa && address >= 0x28) | 1114 | else if (val1 == 0x31 && address >= 0x28) |
1158 | kind = as99127f; | 1115 | kind = as99127f; |
1159 | else { | 1116 | else { |
1160 | if (kind == 0) | 1117 | if (kind == 0) |
@@ -1182,86 +1139,23 @@ w83781d_detect(struct i2c_adapter *adapter, int address, int kind) | |||
1182 | strlcpy(client->name, client_name, I2C_NAME_SIZE); | 1139 | strlcpy(client->name, client_name, I2C_NAME_SIZE); |
1183 | data->type = kind; | 1140 | data->type = kind; |
1184 | 1141 | ||
1185 | data->valid = 0; | ||
1186 | mutex_init(&data->update_lock); | ||
1187 | |||
1188 | /* Tell the I2C layer a new client has arrived */ | 1142 | /* Tell the I2C layer a new client has arrived */ |
1189 | if ((err = i2c_attach_client(client))) | 1143 | if ((err = i2c_attach_client(client))) |
1190 | goto ERROR2; | 1144 | goto ERROR2; |
1191 | 1145 | ||
1192 | /* attach secondary i2c lm75-like clients */ | 1146 | /* attach secondary i2c lm75-like clients */ |
1193 | if (!is_isa) { | 1147 | if ((err = w83781d_detect_subclients(adapter, address, |
1194 | if ((err = w83781d_detect_subclients(adapter, address, | 1148 | kind, client))) |
1195 | kind, client))) | 1149 | goto ERROR3; |
1196 | goto ERROR3; | ||
1197 | } else { | ||
1198 | data->lm75[0] = NULL; | ||
1199 | data->lm75[1] = NULL; | ||
1200 | } | ||
1201 | 1150 | ||
1202 | /* Initialize the chip */ | 1151 | /* Initialize the chip */ |
1203 | w83781d_init_client(client); | 1152 | w83781d_init_device(dev); |
1204 | |||
1205 | /* A few vars need to be filled upon startup */ | ||
1206 | for (i = 1; i <= 3; i++) { | ||
1207 | data->fan_min[i - 1] = w83781d_read_value(client, | ||
1208 | W83781D_REG_FAN_MIN(i)); | ||
1209 | } | ||
1210 | if (kind != w83781d && kind != as99127f) | ||
1211 | for (i = 0; i < 4; i++) | ||
1212 | data->pwmenable[i] = 1; | ||
1213 | 1153 | ||
1214 | /* Register sysfs hooks */ | 1154 | /* Register sysfs hooks */ |
1215 | if ((err = sysfs_create_group(&dev->kobj, &w83781d_group))) | 1155 | err = w83781d_create_files(dev, kind, 0); |
1156 | if (err) | ||
1216 | goto ERROR4; | 1157 | goto ERROR4; |
1217 | 1158 | ||
1218 | if (kind != w83783s) { | ||
1219 | if ((err = device_create_file(dev, &dev_attr_in1_input)) | ||
1220 | || (err = device_create_file(dev, &dev_attr_in1_min)) | ||
1221 | || (err = device_create_file(dev, &dev_attr_in1_max))) | ||
1222 | goto ERROR4; | ||
1223 | } | ||
1224 | if (kind != as99127f && kind != w83781d && kind != w83783s) { | ||
1225 | if ((err = device_create_file(dev, &dev_attr_in7_input)) | ||
1226 | || (err = device_create_file(dev, &dev_attr_in7_min)) | ||
1227 | || (err = device_create_file(dev, &dev_attr_in7_max)) | ||
1228 | || (err = device_create_file(dev, &dev_attr_in8_input)) | ||
1229 | || (err = device_create_file(dev, &dev_attr_in8_min)) | ||
1230 | || (err = device_create_file(dev, &dev_attr_in8_max))) | ||
1231 | goto ERROR4; | ||
1232 | } | ||
1233 | if (kind != w83783s) { | ||
1234 | if ((err = device_create_file(dev, &dev_attr_temp3_input)) | ||
1235 | || (err = device_create_file(dev, &dev_attr_temp3_max)) | ||
1236 | || (err = device_create_file(dev, | ||
1237 | &dev_attr_temp3_max_hyst))) | ||
1238 | goto ERROR4; | ||
1239 | } | ||
1240 | |||
1241 | if (kind != w83781d && kind != as99127f) { | ||
1242 | if ((err = device_create_file(dev, &dev_attr_pwm1)) | ||
1243 | || (err = device_create_file(dev, &dev_attr_pwm2)) | ||
1244 | || (err = device_create_file(dev, &dev_attr_pwm2_enable))) | ||
1245 | goto ERROR4; | ||
1246 | } | ||
1247 | if (kind == w83782d && !is_isa) { | ||
1248 | if ((err = device_create_file(dev, &dev_attr_pwm3)) | ||
1249 | || (err = device_create_file(dev, &dev_attr_pwm4))) | ||
1250 | goto ERROR4; | ||
1251 | } | ||
1252 | |||
1253 | if (kind != as99127f && kind != w83781d) { | ||
1254 | if ((err = device_create_file(dev, &dev_attr_temp1_type)) | ||
1255 | || (err = device_create_file(dev, | ||
1256 | &dev_attr_temp2_type))) | ||
1257 | goto ERROR4; | ||
1258 | if (kind != w83783s) { | ||
1259 | if ((err = device_create_file(dev, | ||
1260 | &dev_attr_temp3_type))) | ||
1261 | goto ERROR4; | ||
1262 | } | ||
1263 | } | ||
1264 | |||
1265 | data->class_dev = hwmon_device_register(dev); | 1159 | data->class_dev = hwmon_device_register(dev); |
1266 | if (IS_ERR(data->class_dev)) { | 1160 | if (IS_ERR(data->class_dev)) { |
1267 | err = PTR_ERR(data->class_dev); | 1161 | err = PTR_ERR(data->class_dev); |
@@ -1287,9 +1181,6 @@ ERROR3: | |||
1287 | ERROR2: | 1181 | ERROR2: |
1288 | kfree(data); | 1182 | kfree(data); |
1289 | ERROR1: | 1183 | ERROR1: |
1290 | if (is_isa) | ||
1291 | release_region(address, W83781D_EXTENT); | ||
1292 | ERROR0: | ||
1293 | return err; | 1184 | return err; |
1294 | } | 1185 | } |
1295 | 1186 | ||
@@ -1305,8 +1196,6 @@ w83781d_detach_client(struct i2c_client *client) | |||
1305 | sysfs_remove_group(&client->dev.kobj, &w83781d_group); | 1196 | sysfs_remove_group(&client->dev.kobj, &w83781d_group); |
1306 | sysfs_remove_group(&client->dev.kobj, &w83781d_group_opt); | 1197 | sysfs_remove_group(&client->dev.kobj, &w83781d_group_opt); |
1307 | } | 1198 | } |
1308 | if (i2c_is_isa_client(client)) | ||
1309 | release_region(client->addr, W83781D_EXTENT); | ||
1310 | 1199 | ||
1311 | if ((err = i2c_detach_client(client))) | 1200 | if ((err = i2c_detach_client(client))) |
1312 | return err; | 1201 | return err; |
@@ -1322,6 +1211,88 @@ w83781d_detach_client(struct i2c_client *client) | |||
1322 | return 0; | 1211 | return 0; |
1323 | } | 1212 | } |
1324 | 1213 | ||
1214 | static int __devinit | ||
1215 | w83781d_isa_probe(struct platform_device *pdev) | ||
1216 | { | ||
1217 | int err, reg; | ||
1218 | struct w83781d_data *data; | ||
1219 | struct resource *res; | ||
1220 | const char *name; | ||
1221 | |||
1222 | /* Reserve the ISA region */ | ||
1223 | res = platform_get_resource(pdev, IORESOURCE_IO, 0); | ||
1224 | if (!request_region(res->start, W83781D_EXTENT, "w83781d")) { | ||
1225 | err = -EBUSY; | ||
1226 | goto exit; | ||
1227 | } | ||
1228 | |||
1229 | if (!(data = kzalloc(sizeof(struct w83781d_data), GFP_KERNEL))) { | ||
1230 | err = -ENOMEM; | ||
1231 | goto exit_release_region; | ||
1232 | } | ||
1233 | mutex_init(&data->lock); | ||
1234 | data->client.addr = res->start; | ||
1235 | i2c_set_clientdata(&data->client, data); | ||
1236 | platform_set_drvdata(pdev, data); | ||
1237 | |||
1238 | reg = w83781d_read_value(data, W83781D_REG_WCHIPID); | ||
1239 | switch (reg) { | ||
1240 | case 0x21: | ||
1241 | data->type = w83627hf; | ||
1242 | name = "w83627hf"; | ||
1243 | break; | ||
1244 | case 0x30: | ||
1245 | data->type = w83782d; | ||
1246 | name = "w83782d"; | ||
1247 | break; | ||
1248 | default: | ||
1249 | data->type = w83781d; | ||
1250 | name = "w83781d"; | ||
1251 | } | ||
1252 | strlcpy(data->client.name, name, I2C_NAME_SIZE); | ||
1253 | |||
1254 | /* Initialize the W83781D chip */ | ||
1255 | w83781d_init_device(&pdev->dev); | ||
1256 | |||
1257 | /* Register sysfs hooks */ | ||
1258 | err = w83781d_create_files(&pdev->dev, data->type, 1); | ||
1259 | if (err) | ||
1260 | goto exit_remove_files; | ||
1261 | |||
1262 | data->class_dev = hwmon_device_register(&pdev->dev); | ||
1263 | if (IS_ERR(data->class_dev)) { | ||
1264 | err = PTR_ERR(data->class_dev); | ||
1265 | goto exit_remove_files; | ||
1266 | } | ||
1267 | |||
1268 | return 0; | ||
1269 | |||
1270 | exit_remove_files: | ||
1271 | sysfs_remove_group(&pdev->dev.kobj, &w83781d_group); | ||
1272 | sysfs_remove_group(&pdev->dev.kobj, &w83781d_group_opt); | ||
1273 | device_remove_file(&pdev->dev, &dev_attr_name); | ||
1274 | kfree(data); | ||
1275 | exit_release_region: | ||
1276 | release_region(res->start, W83781D_EXTENT); | ||
1277 | exit: | ||
1278 | return err; | ||
1279 | } | ||
1280 | |||
1281 | static int __devexit | ||
1282 | w83781d_isa_remove(struct platform_device *pdev) | ||
1283 | { | ||
1284 | struct w83781d_data *data = platform_get_drvdata(pdev); | ||
1285 | |||
1286 | hwmon_device_unregister(data->class_dev); | ||
1287 | sysfs_remove_group(&pdev->dev.kobj, &w83781d_group); | ||
1288 | sysfs_remove_group(&pdev->dev.kobj, &w83781d_group_opt); | ||
1289 | device_remove_file(&pdev->dev, &dev_attr_name); | ||
1290 | release_region(data->client.addr, W83781D_EXTENT); | ||
1291 | kfree(data); | ||
1292 | |||
1293 | return 0; | ||
1294 | } | ||
1295 | |||
1325 | /* The SMBus locks itself, usually, but nothing may access the Winbond between | 1296 | /* The SMBus locks itself, usually, but nothing may access the Winbond between |
1326 | bank switches. ISA access must always be locked explicitly! | 1297 | bank switches. ISA access must always be locked explicitly! |
1327 | We ignore the W83781D BUSY flag at this moment - it could lead to deadlocks, | 1298 | We ignore the W83781D BUSY flag at this moment - it could lead to deadlocks, |
@@ -1329,14 +1300,14 @@ w83781d_detach_client(struct i2c_client *client) | |||
1329 | There are some ugly typecasts here, but the good news is - they should | 1300 | There are some ugly typecasts here, but the good news is - they should |
1330 | nowhere else be necessary! */ | 1301 | nowhere else be necessary! */ |
1331 | static int | 1302 | static int |
1332 | w83781d_read_value(struct i2c_client *client, u16 reg) | 1303 | w83781d_read_value(struct w83781d_data *data, u16 reg) |
1333 | { | 1304 | { |
1334 | struct w83781d_data *data = i2c_get_clientdata(client); | 1305 | struct i2c_client *client = &data->client; |
1335 | int res, word_sized, bank; | 1306 | int res, word_sized, bank; |
1336 | struct i2c_client *cl; | 1307 | struct i2c_client *cl; |
1337 | 1308 | ||
1338 | mutex_lock(&data->lock); | 1309 | mutex_lock(&data->lock); |
1339 | if (i2c_is_isa_client(client)) { | 1310 | if (!client->driver) { /* ISA device */ |
1340 | word_sized = (((reg & 0xff00) == 0x100) | 1311 | word_sized = (((reg & 0xff00) == 0x100) |
1341 | || ((reg & 0xff00) == 0x200)) | 1312 | || ((reg & 0xff00) == 0x200)) |
1342 | && (((reg & 0x00ff) == 0x50) | 1313 | && (((reg & 0x00ff) == 0x50) |
@@ -1398,14 +1369,14 @@ w83781d_read_value(struct i2c_client *client, u16 reg) | |||
1398 | } | 1369 | } |
1399 | 1370 | ||
1400 | static int | 1371 | static int |
1401 | w83781d_write_value(struct i2c_client *client, u16 reg, u16 value) | 1372 | w83781d_write_value(struct w83781d_data *data, u16 reg, u16 value) |
1402 | { | 1373 | { |
1403 | struct w83781d_data *data = i2c_get_clientdata(client); | 1374 | struct i2c_client *client = &data->client; |
1404 | int word_sized, bank; | 1375 | int word_sized, bank; |
1405 | struct i2c_client *cl; | 1376 | struct i2c_client *cl; |
1406 | 1377 | ||
1407 | mutex_lock(&data->lock); | 1378 | mutex_lock(&data->lock); |
1408 | if (i2c_is_isa_client(client)) { | 1379 | if (!client->driver) { /* ISA device */ |
1409 | word_sized = (((reg & 0xff00) == 0x100) | 1380 | word_sized = (((reg & 0xff00) == 0x100) |
1410 | || ((reg & 0xff00) == 0x200)) | 1381 | || ((reg & 0xff00) == 0x200)) |
1411 | && (((reg & 0x00ff) == 0x53) | 1382 | && (((reg & 0x00ff) == 0x53) |
@@ -1462,13 +1433,18 @@ w83781d_write_value(struct i2c_client *client, u16 reg, u16 value) | |||
1462 | } | 1433 | } |
1463 | 1434 | ||
1464 | static void | 1435 | static void |
1465 | w83781d_init_client(struct i2c_client *client) | 1436 | w83781d_init_device(struct device *dev) |
1466 | { | 1437 | { |
1467 | struct w83781d_data *data = i2c_get_clientdata(client); | 1438 | struct w83781d_data *data = dev_get_drvdata(dev); |
1468 | int i, p; | 1439 | int i, p; |
1469 | int type = data->type; | 1440 | int type = data->type; |
1470 | u8 tmp; | 1441 | u8 tmp; |
1471 | 1442 | ||
1443 | if (type == w83627hf) | ||
1444 | dev_info(dev, "The W83627HF chip is better supported by the " | ||
1445 | "w83627hf driver, support will be dropped from the " | ||
1446 | "w83781d driver soon\n"); | ||
1447 | |||
1472 | if (reset && type != as99127f) { /* this resets registers we don't have | 1448 | if (reset && type != as99127f) { /* this resets registers we don't have |
1473 | documentation for on the as99127f */ | 1449 | documentation for on the as99127f */ |
1474 | /* Resetting the chip has been the default for a long time, | 1450 | /* Resetting the chip has been the default for a long time, |
@@ -1477,42 +1453,42 @@ w83781d_init_client(struct i2c_client *client) | |||
1477 | It might even go away if nobody reports it as being useful, | 1453 | It might even go away if nobody reports it as being useful, |
1478 | as I see very little reason why this would be needed at | 1454 | as I see very little reason why this would be needed at |
1479 | all. */ | 1455 | all. */ |
1480 | dev_info(&client->dev, "If reset=1 solved a problem you were " | 1456 | dev_info(dev, "If reset=1 solved a problem you were " |
1481 | "having, please report!\n"); | 1457 | "having, please report!\n"); |
1482 | 1458 | ||
1483 | /* save these registers */ | 1459 | /* save these registers */ |
1484 | i = w83781d_read_value(client, W83781D_REG_BEEP_CONFIG); | 1460 | i = w83781d_read_value(data, W83781D_REG_BEEP_CONFIG); |
1485 | p = w83781d_read_value(client, W83781D_REG_PWMCLK12); | 1461 | p = w83781d_read_value(data, W83781D_REG_PWMCLK12); |
1486 | /* Reset all except Watchdog values and last conversion values | 1462 | /* Reset all except Watchdog values and last conversion values |
1487 | This sets fan-divs to 2, among others */ | 1463 | This sets fan-divs to 2, among others */ |
1488 | w83781d_write_value(client, W83781D_REG_CONFIG, 0x80); | 1464 | w83781d_write_value(data, W83781D_REG_CONFIG, 0x80); |
1489 | /* Restore the registers and disable power-on abnormal beep. | 1465 | /* Restore the registers and disable power-on abnormal beep. |
1490 | This saves FAN 1/2/3 input/output values set by BIOS. */ | 1466 | This saves FAN 1/2/3 input/output values set by BIOS. */ |
1491 | w83781d_write_value(client, W83781D_REG_BEEP_CONFIG, i | 0x80); | 1467 | w83781d_write_value(data, W83781D_REG_BEEP_CONFIG, i | 0x80); |
1492 | w83781d_write_value(client, W83781D_REG_PWMCLK12, p); | 1468 | w83781d_write_value(data, W83781D_REG_PWMCLK12, p); |
1493 | /* Disable master beep-enable (reset turns it on). | 1469 | /* Disable master beep-enable (reset turns it on). |
1494 | Individual beep_mask should be reset to off but for some reason | 1470 | Individual beep_mask should be reset to off but for some reason |
1495 | disabling this bit helps some people not get beeped */ | 1471 | disabling this bit helps some people not get beeped */ |
1496 | w83781d_write_value(client, W83781D_REG_BEEP_INTS2, 0); | 1472 | w83781d_write_value(data, W83781D_REG_BEEP_INTS2, 0); |
1497 | } | 1473 | } |
1498 | 1474 | ||
1499 | /* Disable power-on abnormal beep, as advised by the datasheet. | 1475 | /* Disable power-on abnormal beep, as advised by the datasheet. |
1500 | Already done if reset=1. */ | 1476 | Already done if reset=1. */ |
1501 | if (init && !reset && type != as99127f) { | 1477 | if (init && !reset && type != as99127f) { |
1502 | i = w83781d_read_value(client, W83781D_REG_BEEP_CONFIG); | 1478 | i = w83781d_read_value(data, W83781D_REG_BEEP_CONFIG); |
1503 | w83781d_write_value(client, W83781D_REG_BEEP_CONFIG, i | 0x80); | 1479 | w83781d_write_value(data, W83781D_REG_BEEP_CONFIG, i | 0x80); |
1504 | } | 1480 | } |
1505 | 1481 | ||
1506 | data->vrm = vid_which_vrm(); | 1482 | data->vrm = vid_which_vrm(); |
1507 | 1483 | ||
1508 | if ((type != w83781d) && (type != as99127f)) { | 1484 | if ((type != w83781d) && (type != as99127f)) { |
1509 | tmp = w83781d_read_value(client, W83781D_REG_SCFG1); | 1485 | tmp = w83781d_read_value(data, W83781D_REG_SCFG1); |
1510 | for (i = 1; i <= 3; i++) { | 1486 | for (i = 1; i <= 3; i++) { |
1511 | if (!(tmp & BIT_SCFG1[i - 1])) { | 1487 | if (!(tmp & BIT_SCFG1[i - 1])) { |
1512 | data->sens[i - 1] = W83781D_DEFAULT_BETA; | 1488 | data->sens[i - 1] = W83781D_DEFAULT_BETA; |
1513 | } else { | 1489 | } else { |
1514 | if (w83781d_read_value | 1490 | if (w83781d_read_value |
1515 | (client, | 1491 | (data, |
1516 | W83781D_REG_SCFG2) & BIT_SCFG2[i - 1]) | 1492 | W83781D_REG_SCFG2) & BIT_SCFG2[i - 1]) |
1517 | data->sens[i - 1] = 1; | 1493 | data->sens[i - 1] = 1; |
1518 | else | 1494 | else |
@@ -1525,38 +1501,46 @@ w83781d_init_client(struct i2c_client *client) | |||
1525 | 1501 | ||
1526 | if (init && type != as99127f) { | 1502 | if (init && type != as99127f) { |
1527 | /* Enable temp2 */ | 1503 | /* Enable temp2 */ |
1528 | tmp = w83781d_read_value(client, W83781D_REG_TEMP2_CONFIG); | 1504 | tmp = w83781d_read_value(data, W83781D_REG_TEMP2_CONFIG); |
1529 | if (tmp & 0x01) { | 1505 | if (tmp & 0x01) { |
1530 | dev_warn(&client->dev, "Enabling temp2, readings " | 1506 | dev_warn(dev, "Enabling temp2, readings " |
1531 | "might not make sense\n"); | 1507 | "might not make sense\n"); |
1532 | w83781d_write_value(client, W83781D_REG_TEMP2_CONFIG, | 1508 | w83781d_write_value(data, W83781D_REG_TEMP2_CONFIG, |
1533 | tmp & 0xfe); | 1509 | tmp & 0xfe); |
1534 | } | 1510 | } |
1535 | 1511 | ||
1536 | /* Enable temp3 */ | 1512 | /* Enable temp3 */ |
1537 | if (type != w83783s) { | 1513 | if (type != w83783s) { |
1538 | tmp = w83781d_read_value(client, | 1514 | tmp = w83781d_read_value(data, |
1539 | W83781D_REG_TEMP3_CONFIG); | 1515 | W83781D_REG_TEMP3_CONFIG); |
1540 | if (tmp & 0x01) { | 1516 | if (tmp & 0x01) { |
1541 | dev_warn(&client->dev, "Enabling temp3, " | 1517 | dev_warn(dev, "Enabling temp3, " |
1542 | "readings might not make sense\n"); | 1518 | "readings might not make sense\n"); |
1543 | w83781d_write_value(client, | 1519 | w83781d_write_value(data, |
1544 | W83781D_REG_TEMP3_CONFIG, tmp & 0xfe); | 1520 | W83781D_REG_TEMP3_CONFIG, tmp & 0xfe); |
1545 | } | 1521 | } |
1546 | } | 1522 | } |
1547 | } | 1523 | } |
1548 | 1524 | ||
1549 | /* Start monitoring */ | 1525 | /* Start monitoring */ |
1550 | w83781d_write_value(client, W83781D_REG_CONFIG, | 1526 | w83781d_write_value(data, W83781D_REG_CONFIG, |
1551 | (w83781d_read_value(client, | 1527 | (w83781d_read_value(data, |
1552 | W83781D_REG_CONFIG) & 0xf7) | 1528 | W83781D_REG_CONFIG) & 0xf7) |
1553 | | 0x01); | 1529 | | 0x01); |
1530 | |||
1531 | /* A few vars need to be filled upon startup */ | ||
1532 | for (i = 0; i < 3; i++) { | ||
1533 | data->fan_min[i] = w83781d_read_value(data, | ||
1534 | W83781D_REG_FAN_MIN(i)); | ||
1535 | } | ||
1536 | |||
1537 | mutex_init(&data->update_lock); | ||
1554 | } | 1538 | } |
1555 | 1539 | ||
1556 | static struct w83781d_data *w83781d_update_device(struct device *dev) | 1540 | static struct w83781d_data *w83781d_update_device(struct device *dev) |
1557 | { | 1541 | { |
1558 | struct i2c_client *client = to_i2c_client(dev); | 1542 | struct w83781d_data *data = dev_get_drvdata(dev); |
1559 | struct w83781d_data *data = i2c_get_clientdata(client); | 1543 | struct i2c_client *client = &data->client; |
1560 | int i; | 1544 | int i; |
1561 | 1545 | ||
1562 | mutex_lock(&data->update_lock); | 1546 | mutex_lock(&data->update_lock); |
@@ -1569,98 +1553,97 @@ static struct w83781d_data *w83781d_update_device(struct device *dev) | |||
1569 | if (data->type == w83783s && i == 1) | 1553 | if (data->type == w83783s && i == 1) |
1570 | continue; /* 783S has no in1 */ | 1554 | continue; /* 783S has no in1 */ |
1571 | data->in[i] = | 1555 | data->in[i] = |
1572 | w83781d_read_value(client, W83781D_REG_IN(i)); | 1556 | w83781d_read_value(data, W83781D_REG_IN(i)); |
1573 | data->in_min[i] = | 1557 | data->in_min[i] = |
1574 | w83781d_read_value(client, W83781D_REG_IN_MIN(i)); | 1558 | w83781d_read_value(data, W83781D_REG_IN_MIN(i)); |
1575 | data->in_max[i] = | 1559 | data->in_max[i] = |
1576 | w83781d_read_value(client, W83781D_REG_IN_MAX(i)); | 1560 | w83781d_read_value(data, W83781D_REG_IN_MAX(i)); |
1577 | if ((data->type != w83782d) | 1561 | if ((data->type != w83782d) |
1578 | && (data->type != w83627hf) && (i == 6)) | 1562 | && (data->type != w83627hf) && (i == 6)) |
1579 | break; | 1563 | break; |
1580 | } | 1564 | } |
1581 | for (i = 1; i <= 3; i++) { | 1565 | for (i = 0; i < 3; i++) { |
1582 | data->fan[i - 1] = | 1566 | data->fan[i] = |
1583 | w83781d_read_value(client, W83781D_REG_FAN(i)); | 1567 | w83781d_read_value(data, W83781D_REG_FAN(i)); |
1584 | data->fan_min[i - 1] = | 1568 | data->fan_min[i] = |
1585 | w83781d_read_value(client, W83781D_REG_FAN_MIN(i)); | 1569 | w83781d_read_value(data, W83781D_REG_FAN_MIN(i)); |
1586 | } | 1570 | } |
1587 | if (data->type != w83781d && data->type != as99127f) { | 1571 | if (data->type != w83781d && data->type != as99127f) { |
1588 | for (i = 1; i <= 4; i++) { | 1572 | for (i = 0; i < 4; i++) { |
1589 | data->pwm[i - 1] = | 1573 | data->pwm[i] = |
1590 | w83781d_read_value(client, | 1574 | w83781d_read_value(data, |
1591 | W83781D_REG_PWM(i)); | 1575 | W83781D_REG_PWM[i]); |
1592 | if ((data->type != w83782d | 1576 | if ((data->type != w83782d || !client->driver) |
1593 | || i2c_is_isa_client(client)) | 1577 | && i == 1) |
1594 | && i == 2) | ||
1595 | break; | 1578 | break; |
1596 | } | 1579 | } |
1597 | /* Only PWM2 can be disabled */ | 1580 | /* Only PWM2 can be disabled */ |
1598 | data->pwmenable[1] = (w83781d_read_value(client, | 1581 | data->pwm2_enable = (w83781d_read_value(data, |
1599 | W83781D_REG_PWMCLK12) & 0x08) >> 3; | 1582 | W83781D_REG_PWMCLK12) & 0x08) >> 3; |
1600 | } | 1583 | } |
1601 | 1584 | ||
1602 | data->temp = w83781d_read_value(client, W83781D_REG_TEMP(1)); | 1585 | data->temp = w83781d_read_value(data, W83781D_REG_TEMP(1)); |
1603 | data->temp_max = | 1586 | data->temp_max = |
1604 | w83781d_read_value(client, W83781D_REG_TEMP_OVER(1)); | 1587 | w83781d_read_value(data, W83781D_REG_TEMP_OVER(1)); |
1605 | data->temp_max_hyst = | 1588 | data->temp_max_hyst = |
1606 | w83781d_read_value(client, W83781D_REG_TEMP_HYST(1)); | 1589 | w83781d_read_value(data, W83781D_REG_TEMP_HYST(1)); |
1607 | data->temp_add[0] = | 1590 | data->temp_add[0] = |
1608 | w83781d_read_value(client, W83781D_REG_TEMP(2)); | 1591 | w83781d_read_value(data, W83781D_REG_TEMP(2)); |
1609 | data->temp_max_add[0] = | 1592 | data->temp_max_add[0] = |
1610 | w83781d_read_value(client, W83781D_REG_TEMP_OVER(2)); | 1593 | w83781d_read_value(data, W83781D_REG_TEMP_OVER(2)); |
1611 | data->temp_max_hyst_add[0] = | 1594 | data->temp_max_hyst_add[0] = |
1612 | w83781d_read_value(client, W83781D_REG_TEMP_HYST(2)); | 1595 | w83781d_read_value(data, W83781D_REG_TEMP_HYST(2)); |
1613 | if (data->type != w83783s) { | 1596 | if (data->type != w83783s) { |
1614 | data->temp_add[1] = | 1597 | data->temp_add[1] = |
1615 | w83781d_read_value(client, W83781D_REG_TEMP(3)); | 1598 | w83781d_read_value(data, W83781D_REG_TEMP(3)); |
1616 | data->temp_max_add[1] = | 1599 | data->temp_max_add[1] = |
1617 | w83781d_read_value(client, | 1600 | w83781d_read_value(data, |
1618 | W83781D_REG_TEMP_OVER(3)); | 1601 | W83781D_REG_TEMP_OVER(3)); |
1619 | data->temp_max_hyst_add[1] = | 1602 | data->temp_max_hyst_add[1] = |
1620 | w83781d_read_value(client, | 1603 | w83781d_read_value(data, |
1621 | W83781D_REG_TEMP_HYST(3)); | 1604 | W83781D_REG_TEMP_HYST(3)); |
1622 | } | 1605 | } |
1623 | i = w83781d_read_value(client, W83781D_REG_VID_FANDIV); | 1606 | i = w83781d_read_value(data, W83781D_REG_VID_FANDIV); |
1624 | data->vid = i & 0x0f; | 1607 | data->vid = i & 0x0f; |
1625 | data->vid |= (w83781d_read_value(client, | 1608 | data->vid |= (w83781d_read_value(data, |
1626 | W83781D_REG_CHIPID) & 0x01) << 4; | 1609 | W83781D_REG_CHIPID) & 0x01) << 4; |
1627 | data->fan_div[0] = (i >> 4) & 0x03; | 1610 | data->fan_div[0] = (i >> 4) & 0x03; |
1628 | data->fan_div[1] = (i >> 6) & 0x03; | 1611 | data->fan_div[1] = (i >> 6) & 0x03; |
1629 | data->fan_div[2] = (w83781d_read_value(client, | 1612 | data->fan_div[2] = (w83781d_read_value(data, |
1630 | W83781D_REG_PIN) >> 6) & 0x03; | 1613 | W83781D_REG_PIN) >> 6) & 0x03; |
1631 | if ((data->type != w83781d) && (data->type != as99127f)) { | 1614 | if ((data->type != w83781d) && (data->type != as99127f)) { |
1632 | i = w83781d_read_value(client, W83781D_REG_VBAT); | 1615 | i = w83781d_read_value(data, W83781D_REG_VBAT); |
1633 | data->fan_div[0] |= (i >> 3) & 0x04; | 1616 | data->fan_div[0] |= (i >> 3) & 0x04; |
1634 | data->fan_div[1] |= (i >> 4) & 0x04; | 1617 | data->fan_div[1] |= (i >> 4) & 0x04; |
1635 | data->fan_div[2] |= (i >> 5) & 0x04; | 1618 | data->fan_div[2] |= (i >> 5) & 0x04; |
1636 | } | 1619 | } |
1637 | if ((data->type == w83782d) || (data->type == w83627hf)) { | 1620 | if ((data->type == w83782d) || (data->type == w83627hf)) { |
1638 | data->alarms = w83781d_read_value(client, | 1621 | data->alarms = w83781d_read_value(data, |
1639 | W83782D_REG_ALARM1) | 1622 | W83782D_REG_ALARM1) |
1640 | | (w83781d_read_value(client, | 1623 | | (w83781d_read_value(data, |
1641 | W83782D_REG_ALARM2) << 8) | 1624 | W83782D_REG_ALARM2) << 8) |
1642 | | (w83781d_read_value(client, | 1625 | | (w83781d_read_value(data, |
1643 | W83782D_REG_ALARM3) << 16); | 1626 | W83782D_REG_ALARM3) << 16); |
1644 | } else if (data->type == w83783s) { | 1627 | } else if (data->type == w83783s) { |
1645 | data->alarms = w83781d_read_value(client, | 1628 | data->alarms = w83781d_read_value(data, |
1646 | W83782D_REG_ALARM1) | 1629 | W83782D_REG_ALARM1) |
1647 | | (w83781d_read_value(client, | 1630 | | (w83781d_read_value(data, |
1648 | W83782D_REG_ALARM2) << 8); | 1631 | W83782D_REG_ALARM2) << 8); |
1649 | } else { | 1632 | } else { |
1650 | /* No real-time status registers, fall back to | 1633 | /* No real-time status registers, fall back to |
1651 | interrupt status registers */ | 1634 | interrupt status registers */ |
1652 | data->alarms = w83781d_read_value(client, | 1635 | data->alarms = w83781d_read_value(data, |
1653 | W83781D_REG_ALARM1) | 1636 | W83781D_REG_ALARM1) |
1654 | | (w83781d_read_value(client, | 1637 | | (w83781d_read_value(data, |
1655 | W83781D_REG_ALARM2) << 8); | 1638 | W83781D_REG_ALARM2) << 8); |
1656 | } | 1639 | } |
1657 | i = w83781d_read_value(client, W83781D_REG_BEEP_INTS2); | 1640 | i = w83781d_read_value(data, W83781D_REG_BEEP_INTS2); |
1658 | data->beep_enable = i >> 7; | 1641 | data->beep_enable = i >> 7; |
1659 | data->beep_mask = ((i & 0x7f) << 8) + | 1642 | data->beep_mask = ((i & 0x7f) << 8) + |
1660 | w83781d_read_value(client, W83781D_REG_BEEP_INTS1); | 1643 | w83781d_read_value(data, W83781D_REG_BEEP_INTS1); |
1661 | if ((data->type != w83781d) && (data->type != as99127f)) { | 1644 | if ((data->type != w83781d) && (data->type != as99127f)) { |
1662 | data->beep_mask |= | 1645 | data->beep_mask |= |
1663 | w83781d_read_value(client, | 1646 | w83781d_read_value(data, |
1664 | W83781D_REG_BEEP_INTS3) << 16; | 1647 | W83781D_REG_BEEP_INTS3) << 16; |
1665 | } | 1648 | } |
1666 | data->last_updated = jiffies; | 1649 | data->last_updated = jiffies; |
@@ -1672,6 +1655,133 @@ static struct w83781d_data *w83781d_update_device(struct device *dev) | |||
1672 | return data; | 1655 | return data; |
1673 | } | 1656 | } |
1674 | 1657 | ||
1658 | /* return 1 if a supported chip is found, 0 otherwise */ | ||
1659 | static int __init | ||
1660 | w83781d_isa_found(unsigned short address) | ||
1661 | { | ||
1662 | int val, save, found = 0; | ||
1663 | |||
1664 | if (!request_region(address, W83781D_EXTENT, "w83781d")) | ||
1665 | return 0; | ||
1666 | |||
1667 | #define REALLY_SLOW_IO | ||
1668 | /* We need the timeouts for at least some W83781D-like | ||
1669 | chips. But only if we read 'undefined' registers. */ | ||
1670 | val = inb_p(address + 1); | ||
1671 | if (inb_p(address + 2) != val | ||
1672 | || inb_p(address + 3) != val | ||
1673 | || inb_p(address + 7) != val) { | ||
1674 | pr_debug("w83781d: Detection failed at step 1\n"); | ||
1675 | goto release; | ||
1676 | } | ||
1677 | #undef REALLY_SLOW_IO | ||
1678 | |||
1679 | /* We should be able to change the 7 LSB of the address port. The | ||
1680 | MSB (busy flag) should be clear initially, set after the write. */ | ||
1681 | save = inb_p(address + W83781D_ADDR_REG_OFFSET); | ||
1682 | if (save & 0x80) { | ||
1683 | pr_debug("w83781d: Detection failed at step 2\n"); | ||
1684 | goto release; | ||
1685 | } | ||
1686 | val = ~save & 0x7f; | ||
1687 | outb_p(val, address + W83781D_ADDR_REG_OFFSET); | ||
1688 | if (inb_p(address + W83781D_ADDR_REG_OFFSET) != (val | 0x80)) { | ||
1689 | outb_p(save, address + W83781D_ADDR_REG_OFFSET); | ||
1690 | pr_debug("w83781d: Detection failed at step 3\n"); | ||
1691 | goto release; | ||
1692 | } | ||
1693 | |||
1694 | /* We found a device, now see if it could be a W83781D */ | ||
1695 | outb_p(W83781D_REG_CONFIG, address + W83781D_ADDR_REG_OFFSET); | ||
1696 | val = inb_p(address + W83781D_DATA_REG_OFFSET); | ||
1697 | if (val & 0x80) { | ||
1698 | pr_debug("w83781d: Detection failed at step 4\n"); | ||
1699 | goto release; | ||
1700 | } | ||
1701 | outb_p(W83781D_REG_BANK, address + W83781D_ADDR_REG_OFFSET); | ||
1702 | save = inb_p(address + W83781D_DATA_REG_OFFSET); | ||
1703 | outb_p(W83781D_REG_CHIPMAN, address + W83781D_ADDR_REG_OFFSET); | ||
1704 | val = inb_p(address + W83781D_DATA_REG_OFFSET); | ||
1705 | if ((!(save & 0x80) && (val != 0xa3)) | ||
1706 | || ((save & 0x80) && (val != 0x5c))) { | ||
1707 | pr_debug("w83781d: Detection failed at step 5\n"); | ||
1708 | goto release; | ||
1709 | } | ||
1710 | outb_p(W83781D_REG_I2C_ADDR, address + W83781D_ADDR_REG_OFFSET); | ||
1711 | val = inb_p(address + W83781D_DATA_REG_OFFSET); | ||
1712 | if (val < 0x03 || val > 0x77) { /* Not a valid I2C address */ | ||
1713 | pr_debug("w83781d: Detection failed at step 6\n"); | ||
1714 | goto release; | ||
1715 | } | ||
1716 | |||
1717 | /* The busy flag should be clear again */ | ||
1718 | if (inb_p(address + W83781D_ADDR_REG_OFFSET) & 0x80) { | ||
1719 | pr_debug("w83781d: Detection failed at step 7\n"); | ||
1720 | goto release; | ||
1721 | } | ||
1722 | |||
1723 | /* Determine the chip type */ | ||
1724 | outb_p(W83781D_REG_BANK, address + W83781D_ADDR_REG_OFFSET); | ||
1725 | save = inb_p(address + W83781D_DATA_REG_OFFSET); | ||
1726 | outb_p(save & 0xf8, address + W83781D_DATA_REG_OFFSET); | ||
1727 | outb_p(W83781D_REG_WCHIPID, address + W83781D_ADDR_REG_OFFSET); | ||
1728 | val = inb_p(address + W83781D_DATA_REG_OFFSET); | ||
1729 | if ((val & 0xfe) == 0x10 /* W83781D */ | ||
1730 | || val == 0x30 /* W83782D */ | ||
1731 | || val == 0x21) /* W83627HF */ | ||
1732 | found = 1; | ||
1733 | |||
1734 | if (found) | ||
1735 | pr_info("w83781d: Found a %s chip at %#x\n", | ||
1736 | val == 0x21 ? "W83627HF" : | ||
1737 | val == 0x30 ? "W83782D" : "W83781D", (int)address); | ||
1738 | |||
1739 | release: | ||
1740 | release_region(address, W83781D_EXTENT); | ||
1741 | return found; | ||
1742 | } | ||
1743 | |||
1744 | static int __init | ||
1745 | w83781d_isa_device_add(unsigned short address) | ||
1746 | { | ||
1747 | struct resource res = { | ||
1748 | .start = address, | ||
1749 | .end = address + W83781D_EXTENT, | ||
1750 | .name = "w83781d", | ||
1751 | .flags = IORESOURCE_IO, | ||
1752 | }; | ||
1753 | int err; | ||
1754 | |||
1755 | pdev = platform_device_alloc("w83781d", address); | ||
1756 | if (!pdev) { | ||
1757 | err = -ENOMEM; | ||
1758 | printk(KERN_ERR "w83781d: Device allocation failed\n"); | ||
1759 | goto exit; | ||
1760 | } | ||
1761 | |||
1762 | err = platform_device_add_resources(pdev, &res, 1); | ||
1763 | if (err) { | ||
1764 | printk(KERN_ERR "w83781d: Device resource addition failed " | ||
1765 | "(%d)\n", err); | ||
1766 | goto exit_device_put; | ||
1767 | } | ||
1768 | |||
1769 | err = platform_device_add(pdev); | ||
1770 | if (err) { | ||
1771 | printk(KERN_ERR "w83781d: Device addition failed (%d)\n", | ||
1772 | err); | ||
1773 | goto exit_device_put; | ||
1774 | } | ||
1775 | |||
1776 | return 0; | ||
1777 | |||
1778 | exit_device_put: | ||
1779 | platform_device_put(pdev); | ||
1780 | exit: | ||
1781 | pdev = NULL; | ||
1782 | return err; | ||
1783 | } | ||
1784 | |||
1675 | static int __init | 1785 | static int __init |
1676 | sensors_w83781d_init(void) | 1786 | sensors_w83781d_init(void) |
1677 | { | 1787 | { |
@@ -1679,21 +1789,36 @@ sensors_w83781d_init(void) | |||
1679 | 1789 | ||
1680 | res = i2c_add_driver(&w83781d_driver); | 1790 | res = i2c_add_driver(&w83781d_driver); |
1681 | if (res) | 1791 | if (res) |
1682 | return res; | 1792 | goto exit; |
1793 | |||
1794 | if (w83781d_isa_found(isa_address)) { | ||
1795 | res = platform_driver_register(&w83781d_isa_driver); | ||
1796 | if (res) | ||
1797 | goto exit_unreg_i2c_driver; | ||
1683 | 1798 | ||
1684 | /* Don't exit if this one fails, we still want the I2C variants | 1799 | /* Sets global pdev as a side effect */ |
1685 | to work! */ | 1800 | res = w83781d_isa_device_add(isa_address); |
1686 | if (i2c_isa_add_driver(&w83781d_isa_driver)) | 1801 | if (res) |
1687 | isa_address = 0; | 1802 | goto exit_unreg_isa_driver; |
1803 | } | ||
1688 | 1804 | ||
1689 | return 0; | 1805 | return 0; |
1806 | |||
1807 | exit_unreg_isa_driver: | ||
1808 | platform_driver_unregister(&w83781d_isa_driver); | ||
1809 | exit_unreg_i2c_driver: | ||
1810 | i2c_del_driver(&w83781d_driver); | ||
1811 | exit: | ||
1812 | return res; | ||
1690 | } | 1813 | } |
1691 | 1814 | ||
1692 | static void __exit | 1815 | static void __exit |
1693 | sensors_w83781d_exit(void) | 1816 | sensors_w83781d_exit(void) |
1694 | { | 1817 | { |
1695 | if (isa_address) | 1818 | if (pdev) { |
1696 | i2c_isa_del_driver(&w83781d_isa_driver); | 1819 | platform_device_unregister(pdev); |
1820 | platform_driver_unregister(&w83781d_isa_driver); | ||
1821 | } | ||
1697 | i2c_del_driver(&w83781d_driver); | 1822 | i2c_del_driver(&w83781d_driver); |
1698 | } | 1823 | } |
1699 | 1824 | ||
diff --git a/include/asm-i386/msr.h b/include/asm-i386/msr.h index 9559894c7658..26861df52cc4 100644 --- a/include/asm-i386/msr.h +++ b/include/asm-i386/msr.h | |||
@@ -77,7 +77,7 @@ static inline unsigned long long native_read_pmc(void) | |||
77 | #ifdef CONFIG_PARAVIRT | 77 | #ifdef CONFIG_PARAVIRT |
78 | #include <asm/paravirt.h> | 78 | #include <asm/paravirt.h> |
79 | #else | 79 | #else |
80 | 80 | #include <linux/errno.h> | |
81 | /* | 81 | /* |
82 | * Access to machine-specific registers (available on 586 and better only) | 82 | * Access to machine-specific registers (available on 586 and better only) |
83 | * Note: the rd* operations modify the parameters directly (without using | 83 | * Note: the rd* operations modify the parameters directly (without using |
@@ -148,6 +148,8 @@ static inline void wrmsrl (unsigned long msr, unsigned long long val) | |||
148 | #ifdef CONFIG_SMP | 148 | #ifdef CONFIG_SMP |
149 | void rdmsr_on_cpu(unsigned int cpu, u32 msr_no, u32 *l, u32 *h); | 149 | void rdmsr_on_cpu(unsigned int cpu, u32 msr_no, u32 *l, u32 *h); |
150 | void wrmsr_on_cpu(unsigned int cpu, u32 msr_no, u32 l, u32 h); | 150 | void wrmsr_on_cpu(unsigned int cpu, u32 msr_no, u32 l, u32 h); |
151 | int rdmsr_safe_on_cpu(unsigned int cpu, u32 msr_no, u32 *l, u32 *h); | ||
152 | int wrmsr_safe_on_cpu(unsigned int cpu, u32 msr_no, u32 l, u32 h); | ||
151 | #else /* CONFIG_SMP */ | 153 | #else /* CONFIG_SMP */ |
152 | static inline void rdmsr_on_cpu(unsigned int cpu, u32 msr_no, u32 *l, u32 *h) | 154 | static inline void rdmsr_on_cpu(unsigned int cpu, u32 msr_no, u32 *l, u32 *h) |
153 | { | 155 | { |
@@ -157,6 +159,14 @@ static inline void wrmsr_on_cpu(unsigned int cpu, u32 msr_no, u32 l, u32 h) | |||
157 | { | 159 | { |
158 | wrmsr(msr_no, l, h); | 160 | wrmsr(msr_no, l, h); |
159 | } | 161 | } |
162 | static inline int rdmsr_safe_on_cpu(unsigned int cpu, u32 msr_no, u32 *l, u32 *h) | ||
163 | { | ||
164 | return rdmsr_safe(msr_no, l, h); | ||
165 | } | ||
166 | static inline int wrmsr_safe_on_cpu(unsigned int cpu, u32 msr_no, u32 l, u32 h) | ||
167 | { | ||
168 | return wrmsr_safe(msr_no, l, h); | ||
169 | } | ||
160 | #endif /* CONFIG_SMP */ | 170 | #endif /* CONFIG_SMP */ |
161 | #endif | 171 | #endif |
162 | #endif | 172 | #endif |
diff --git a/include/asm-x86_64/msr.h b/include/asm-x86_64/msr.h index a524f0325673..d5c55b80da54 100644 --- a/include/asm-x86_64/msr.h +++ b/include/asm-x86_64/msr.h | |||
@@ -4,6 +4,7 @@ | |||
4 | #include <asm/msr-index.h> | 4 | #include <asm/msr-index.h> |
5 | 5 | ||
6 | #ifndef __ASSEMBLY__ | 6 | #ifndef __ASSEMBLY__ |
7 | #include <linux/errno.h> | ||
7 | /* | 8 | /* |
8 | * Access to machine-specific registers (available on 586 and better only) | 9 | * Access to machine-specific registers (available on 586 and better only) |
9 | * Note: the rd* operations modify the parameters directly (without using | 10 | * Note: the rd* operations modify the parameters directly (without using |
@@ -162,6 +163,8 @@ static inline unsigned int cpuid_edx(unsigned int op) | |||
162 | #ifdef CONFIG_SMP | 163 | #ifdef CONFIG_SMP |
163 | void rdmsr_on_cpu(unsigned int cpu, u32 msr_no, u32 *l, u32 *h); | 164 | void rdmsr_on_cpu(unsigned int cpu, u32 msr_no, u32 *l, u32 *h); |
164 | void wrmsr_on_cpu(unsigned int cpu, u32 msr_no, u32 l, u32 h); | 165 | void wrmsr_on_cpu(unsigned int cpu, u32 msr_no, u32 l, u32 h); |
166 | int rdmsr_safe_on_cpu(unsigned int cpu, u32 msr_no, u32 *l, u32 *h); | ||
167 | int wrmsr_safe_on_cpu(unsigned int cpu, u32 msr_no, u32 l, u32 h); | ||
165 | #else /* CONFIG_SMP */ | 168 | #else /* CONFIG_SMP */ |
166 | static inline void rdmsr_on_cpu(unsigned int cpu, u32 msr_no, u32 *l, u32 *h) | 169 | static inline void rdmsr_on_cpu(unsigned int cpu, u32 msr_no, u32 *l, u32 *h) |
167 | { | 170 | { |
@@ -171,6 +174,14 @@ static inline void wrmsr_on_cpu(unsigned int cpu, u32 msr_no, u32 l, u32 h) | |||
171 | { | 174 | { |
172 | wrmsr(msr_no, l, h); | 175 | wrmsr(msr_no, l, h); |
173 | } | 176 | } |
177 | static inline int rdmsr_safe_on_cpu(unsigned int cpu, u32 msr_no, u32 *l, u32 *h) | ||
178 | { | ||
179 | return rdmsr_safe(msr_no, l, h); | ||
180 | } | ||
181 | static inline int wrmsr_safe_on_cpu(unsigned int cpu, u32 msr_no, u32 l, u32 h) | ||
182 | { | ||
183 | return wrmsr_safe(msr_no, l, h); | ||
184 | } | ||
174 | #endif /* CONFIG_SMP */ | 185 | #endif /* CONFIG_SMP */ |
175 | #endif /* __ASSEMBLY__ */ | 186 | #endif /* __ASSEMBLY__ */ |
176 | #endif /* X86_64_MSR_H */ | 187 | #endif /* X86_64_MSR_H */ |