Details | Last modification | View Log | RSS feed
Rev | Author | Line No. | Line |
---|---|---|---|
420 | giacomo | 1 | /* |
2 | w83781d.c - Part of lm_sensors, Linux kernel modules for hardware |
||
3 | monitoring |
||
4 | Copyright (c) 1998 - 2001 Frodo Looijaard <frodol@dds.nl>, |
||
5 | Philip Edelbrock <phil@netroedge.com>, |
||
6 | and Mark Studebaker <mdsxyz123@yahoo.com> |
||
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; either version 2 of the License, or |
||
11 | (at your option) any later version. |
||
12 | |||
13 | This program is distributed in the hope that it will be useful, |
||
14 | but WITHOUT ANY WARRANTY; without even the implied warranty of |
||
15 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
||
16 | GNU General Public License for more details. |
||
17 | |||
18 | You should have received a copy of the GNU General Public License |
||
19 | along with this program; if not, write to the Free Software |
||
20 | Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. |
||
21 | */ |
||
22 | |||
23 | /* |
||
24 | Supports following chips: |
||
25 | |||
26 | Chip #vin #fanin #pwm #temp wchipid vendid i2c ISA |
||
27 | as99127f 7 3 1? 3 0x30 0x12c3 yes no |
||
28 | asb100 "bach" (type_name = as99127f) 0x30 0x0694 yes no |
||
29 | w83781d 7 3 0 3 0x10 0x5ca3 yes yes |
||
30 | w83627hf 9 3 2 3 0x20 0x5ca3 yes yes(LPC) |
||
31 | w83627thf 9 3 2 3 0x90 0x5ca3 no yes(LPC) |
||
32 | w83782d 9 3 2-4 3 0x30 0x5ca3 yes yes |
||
33 | w83783s 5-6 3 2 1-2 0x40 0x5ca3 yes no |
||
34 | w83697hf 8 2 2 2 0x60 0x5ca3 no yes(LPC) |
||
35 | |||
36 | */ |
||
37 | |||
38 | #include <linux/module.h> |
||
39 | #include <linux/init.h> |
||
40 | #include <linux/slab.h> |
||
41 | #include <linux/i2c.h> |
||
42 | #include <linux/i2c-sensor.h> |
||
43 | #include <linux/i2c-vid.h> |
||
44 | #include <asm/io.h> |
||
45 | |||
46 | /* RT Table support #defined so we can take it out if it gets bothersome */ |
||
47 | #define W83781D_RT 1 |
||
48 | |||
49 | /* Addresses to scan */ |
||
50 | static unsigned short normal_i2c[] = { I2C_CLIENT_END }; |
||
51 | static unsigned short normal_i2c_range[] = { 0x20, 0x2f, I2C_CLIENT_END }; |
||
52 | static unsigned int normal_isa[] = { 0x0290, I2C_CLIENT_ISA_END }; |
||
53 | static unsigned int normal_isa_range[] = { I2C_CLIENT_ISA_END }; |
||
54 | |||
55 | /* Insmod parameters */ |
||
56 | SENSORS_INSMOD_6(w83781d, w83782d, w83783s, w83627hf, as99127f, w83697hf); |
||
57 | I2C_CLIENT_MODULE_PARM(force_subclients, "List of subclient addresses: " |
||
58 | "{bus, clientaddr, subclientaddr1, subclientaddr2}"); |
||
59 | |||
60 | static int init = 1; |
||
61 | MODULE_PARM(init, "i"); |
||
62 | MODULE_PARM_DESC(init, "Set to zero to bypass chip initialization"); |
||
63 | |||
64 | /* Constants specified below */ |
||
65 | |||
66 | /* Length of ISA address segment */ |
||
67 | #define W83781D_EXTENT 8 |
||
68 | |||
69 | /* Where are the ISA address/data registers relative to the base address */ |
||
70 | #define W83781D_ADDR_REG_OFFSET 5 |
||
71 | #define W83781D_DATA_REG_OFFSET 6 |
||
72 | |||
73 | /* The W83781D registers */ |
||
74 | /* The W83782D registers for nr=7,8 are in bank 5 */ |
||
75 | #define W83781D_REG_IN_MAX(nr) ((nr < 7) ? (0x2b + (nr) * 2) : \ |
||
76 | (0x554 + (((nr) - 7) * 2))) |
||
77 | #define W83781D_REG_IN_MIN(nr) ((nr < 7) ? (0x2c + (nr) * 2) : \ |
||
78 | (0x555 + (((nr) - 7) * 2))) |
||
79 | #define W83781D_REG_IN(nr) ((nr < 7) ? (0x20 + (nr)) : \ |
||
80 | (0x550 + (nr) - 7)) |
||
81 | |||
82 | #define W83781D_REG_FAN_MIN(nr) (0x3a + (nr)) |
||
83 | #define W83781D_REG_FAN(nr) (0x27 + (nr)) |
||
84 | |||
85 | #define W83781D_REG_BANK 0x4E |
||
86 | #define W83781D_REG_TEMP2_CONFIG 0x152 |
||
87 | #define W83781D_REG_TEMP3_CONFIG 0x252 |
||
88 | #define W83781D_REG_TEMP(nr) ((nr == 3) ? (0x0250) : \ |
||
89 | ((nr == 2) ? (0x0150) : \ |
||
90 | (0x27))) |
||
91 | #define W83781D_REG_TEMP_HYST(nr) ((nr == 3) ? (0x253) : \ |
||
92 | ((nr == 2) ? (0x153) : \ |
||
93 | (0x3A))) |
||
94 | #define W83781D_REG_TEMP_OVER(nr) ((nr == 3) ? (0x255) : \ |
||
95 | ((nr == 2) ? (0x155) : \ |
||
96 | (0x39))) |
||
97 | |||
98 | #define W83781D_REG_CONFIG 0x40 |
||
99 | #define W83781D_REG_ALARM1 0x41 |
||
100 | #define W83781D_REG_ALARM2 0x42 |
||
101 | #define W83781D_REG_ALARM3 0x450 /* not on W83781D */ |
||
102 | |||
103 | #define W83781D_REG_IRQ 0x4C |
||
104 | #define W83781D_REG_BEEP_CONFIG 0x4D |
||
105 | #define W83781D_REG_BEEP_INTS1 0x56 |
||
106 | #define W83781D_REG_BEEP_INTS2 0x57 |
||
107 | #define W83781D_REG_BEEP_INTS3 0x453 /* not on W83781D */ |
||
108 | |||
109 | #define W83781D_REG_VID_FANDIV 0x47 |
||
110 | |||
111 | #define W83781D_REG_CHIPID 0x49 |
||
112 | #define W83781D_REG_WCHIPID 0x58 |
||
113 | #define W83781D_REG_CHIPMAN 0x4F |
||
114 | #define W83781D_REG_PIN 0x4B |
||
115 | |||
116 | /* 782D/783S only */ |
||
117 | #define W83781D_REG_VBAT 0x5D |
||
118 | |||
119 | /* PWM 782D (1-4) and 783S (1-2) only */ |
||
120 | #define W83781D_REG_PWM1 0x5B /* 782d and 783s/627hf datasheets disagree */ |
||
121 | /* on which is which; */ |
||
122 | #define W83781D_REG_PWM2 0x5A /* We follow the 782d convention here, */ |
||
123 | /* However 782d is probably wrong. */ |
||
124 | #define W83781D_REG_PWM3 0x5E |
||
125 | #define W83781D_REG_PWM4 0x5F |
||
126 | #define W83781D_REG_PWMCLK12 0x5C |
||
127 | #define W83781D_REG_PWMCLK34 0x45C |
||
128 | static const u8 regpwm[] = { W83781D_REG_PWM1, W83781D_REG_PWM2, |
||
129 | W83781D_REG_PWM3, W83781D_REG_PWM4 |
||
130 | }; |
||
131 | |||
132 | #define W83781D_REG_PWM(nr) (regpwm[(nr) - 1]) |
||
133 | |||
134 | #define W83781D_REG_I2C_ADDR 0x48 |
||
135 | #define W83781D_REG_I2C_SUBADDR 0x4A |
||
136 | |||
137 | /* The following are undocumented in the data sheets however we |
||
138 | received the information in an email from Winbond tech support */ |
||
139 | /* Sensor selection - not on 781d */ |
||
140 | #define W83781D_REG_SCFG1 0x5D |
||
141 | static const u8 BIT_SCFG1[] = { 0x02, 0x04, 0x08 }; |
||
142 | |||
143 | #define W83781D_REG_SCFG2 0x59 |
||
144 | static const u8 BIT_SCFG2[] = { 0x10, 0x20, 0x40 }; |
||
145 | |||
146 | #define W83781D_DEFAULT_BETA 3435 |
||
147 | |||
148 | /* RT Table registers */ |
||
149 | #define W83781D_REG_RT_IDX 0x50 |
||
150 | #define W83781D_REG_RT_VAL 0x51 |
||
151 | |||
152 | /* Conversions. Rounding and limit checking is only done on the TO_REG |
||
153 | variants. Note that you should be a bit careful with which arguments |
||
154 | these macros are called: arguments may be evaluated more than once. |
||
155 | Fixing this is just not worth it. */ |
||
156 | #define IN_TO_REG(val) (SENSORS_LIMIT((((val) * 10 + 8)/16),0,255)) |
||
157 | #define IN_FROM_REG(val) (((val) * 16) / 10) |
||
158 | |||
159 | static inline u8 |
||
160 | FAN_TO_REG(long rpm, int div) |
||
161 | { |
||
162 | if (rpm == 0) |
||
163 | return 255; |
||
164 | rpm = SENSORS_LIMIT(rpm, 1, 1000000); |
||
165 | return SENSORS_LIMIT((1350000 + rpm * div / 2) / (rpm * div), 1, 254); |
||
166 | } |
||
167 | |||
168 | #define FAN_FROM_REG(val,div) ((val) == 0 ? -1 : \ |
||
169 | ((val) == 255 ? 0 : \ |
||
170 | 1350000 / ((val) * (div)))) |
||
171 | |||
172 | #define TEMP_TO_REG(val) (SENSORS_LIMIT(((val / 10) < 0 ? (((val / 10) - 5) / 10) : \ |
||
173 | ((val / 10) + 5) / 10), 0, 255)) |
||
174 | #define TEMP_FROM_REG(val) ((((val ) > 0x80 ? (val) - 0x100 : (val)) * 10) * 10) |
||
175 | |||
176 | #define TEMP_ADD_TO_REG(val) (SENSORS_LIMIT(((((val / 10) + 2) / 5) << 7),\ |
||
177 | 0, 0xffff)) |
||
178 | #define TEMP_ADD_FROM_REG(val) ((((val) >> 7) * 5) * 10) |
||
179 | |||
180 | #define AS99127_TEMP_ADD_TO_REG(val) (SENSORS_LIMIT((((((val / 10) + 2)*4)/10) \ |
||
181 | << 7), 0, 0xffff)) |
||
182 | #define AS99127_TEMP_ADD_FROM_REG(val) (((((val) >> 7) * 10) / 4) * 10) |
||
183 | |||
184 | #define ALARMS_FROM_REG(val) (val) |
||
185 | #define PWM_FROM_REG(val) (val) |
||
186 | #define PWM_TO_REG(val) (SENSORS_LIMIT((val),0,255)) |
||
187 | #define BEEP_MASK_FROM_REG(val) (val) |
||
188 | #define BEEP_MASK_TO_REG(val) ((val) & 0xffffff) |
||
189 | |||
190 | #define BEEP_ENABLE_TO_REG(val) ((val) ? 1 : 0) |
||
191 | #define BEEP_ENABLE_FROM_REG(val) ((val) ? 1 : 0) |
||
192 | |||
193 | #define DIV_FROM_REG(val) (1 << (val)) |
||
194 | |||
195 | static inline u8 |
||
196 | DIV_TO_REG(long val, enum chips type) |
||
197 | { |
||
198 | int i; |
||
199 | val = SENSORS_LIMIT(val, 1, |
||
200 | ((type == w83781d |
||
201 | || type == as99127f) ? 8 : 128)) >> 1; |
||
202 | for (i = 0; i < 6; i++) { |
||
203 | if (val == 0) |
||
204 | break; |
||
205 | val >>= 1; |
||
206 | } |
||
207 | return ((u8) i); |
||
208 | } |
||
209 | |||
210 | /* Initial limits */ |
||
211 | #define W83781D_INIT_IN_0 (vid == 3500 ? 280 : vid / 10) |
||
212 | #define W83781D_INIT_IN_1 (vid == 3500 ? 280 : vid / 10) |
||
213 | #define W83781D_INIT_IN_2 330 |
||
214 | #define W83781D_INIT_IN_3 (((500) * 100) / 168) |
||
215 | #define W83781D_INIT_IN_4 (((1200) * 10) / 38) |
||
216 | #define W83781D_INIT_IN_5 (((-1200) * -604) / 2100) |
||
217 | #define W83781D_INIT_IN_6 (((-500) * -604) / 909) |
||
218 | #define W83781D_INIT_IN_7 (((500) * 100) / 168) |
||
219 | #define W83781D_INIT_IN_8 300 |
||
220 | /* Initial limits for 782d/783s negative voltages */ |
||
221 | /* Note level shift. Change min/max below if you change these. */ |
||
222 | #define W83782D_INIT_IN_5 ((((-1200) + 1491) * 100)/514) |
||
223 | #define W83782D_INIT_IN_6 ((( (-500) + 771) * 100)/314) |
||
224 | |||
225 | #define W83781D_INIT_IN_PERCENTAGE 10 |
||
226 | #define W83781D_INIT_IN_MIN(val) (val - val * W83781D_INIT_IN_PERCENTAGE / 100) |
||
227 | #define W83781D_INIT_IN_MAX(val) (val + val * W83781D_INIT_IN_PERCENTAGE / 100) |
||
228 | |||
229 | #define W83781D_INIT_IN_MIN_0 W83781D_INIT_IN_MIN(W83781D_INIT_IN_0) |
||
230 | #define W83781D_INIT_IN_MAX_0 W83781D_INIT_IN_MAX(W83781D_INIT_IN_0) |
||
231 | #define W83781D_INIT_IN_MIN_1 W83781D_INIT_IN_MIN(W83781D_INIT_IN_1) |
||
232 | #define W83781D_INIT_IN_MAX_1 W83781D_INIT_IN_MAX(W83781D_INIT_IN_1) |
||
233 | #define W83781D_INIT_IN_MIN_2 W83781D_INIT_IN_MIN(W83781D_INIT_IN_2) |
||
234 | #define W83781D_INIT_IN_MAX_2 W83781D_INIT_IN_MAX(W83781D_INIT_IN_2) |
||
235 | #define W83781D_INIT_IN_MIN_3 W83781D_INIT_IN_MIN(W83781D_INIT_IN_3) |
||
236 | #define W83781D_INIT_IN_MAX_3 W83781D_INIT_IN_MAX(W83781D_INIT_IN_3) |
||
237 | #define W83781D_INIT_IN_MIN_4 W83781D_INIT_IN_MIN(W83781D_INIT_IN_4) |
||
238 | #define W83781D_INIT_IN_MAX_4 W83781D_INIT_IN_MAX(W83781D_INIT_IN_4) |
||
239 | #define W83781D_INIT_IN_MIN_5 W83781D_INIT_IN_MIN(W83781D_INIT_IN_5) |
||
240 | #define W83781D_INIT_IN_MAX_5 W83781D_INIT_IN_MAX(W83781D_INIT_IN_5) |
||
241 | #define W83781D_INIT_IN_MIN_6 W83781D_INIT_IN_MIN(W83781D_INIT_IN_6) |
||
242 | #define W83781D_INIT_IN_MAX_6 W83781D_INIT_IN_MAX(W83781D_INIT_IN_6) |
||
243 | #define W83781D_INIT_IN_MIN_7 W83781D_INIT_IN_MIN(W83781D_INIT_IN_7) |
||
244 | #define W83781D_INIT_IN_MAX_7 W83781D_INIT_IN_MAX(W83781D_INIT_IN_7) |
||
245 | #define W83781D_INIT_IN_MIN_8 W83781D_INIT_IN_MIN(W83781D_INIT_IN_8) |
||
246 | #define W83781D_INIT_IN_MAX_8 W83781D_INIT_IN_MAX(W83781D_INIT_IN_8) |
||
247 | |||
248 | /* Initial limits for 782d/783s negative voltages */ |
||
249 | /* These aren't direct multiples because of level shift */ |
||
250 | /* Beware going negative - check */ |
||
251 | #define W83782D_INIT_IN_MIN_5_TMP \ |
||
252 | (((-1200 * (100 + W83781D_INIT_IN_PERCENTAGE)) + (1491 * 100))/514) |
||
253 | #define W83782D_INIT_IN_MIN_5 \ |
||
254 | ((W83782D_INIT_IN_MIN_5_TMP > 0) ? W83782D_INIT_IN_MIN_5_TMP : 0) |
||
255 | #define W83782D_INIT_IN_MAX_5 \ |
||
256 | (((-1200 * (100 - W83781D_INIT_IN_PERCENTAGE)) + (1491 * 100))/514) |
||
257 | #define W83782D_INIT_IN_MIN_6_TMP \ |
||
258 | ((( -500 * (100 + W83781D_INIT_IN_PERCENTAGE)) + (771 * 100))/314) |
||
259 | #define W83782D_INIT_IN_MIN_6 \ |
||
260 | ((W83782D_INIT_IN_MIN_6_TMP > 0) ? W83782D_INIT_IN_MIN_6_TMP : 0) |
||
261 | #define W83782D_INIT_IN_MAX_6 \ |
||
262 | ((( -500 * (100 - W83781D_INIT_IN_PERCENTAGE)) + (771 * 100))/314) |
||
263 | |||
264 | #define W83781D_INIT_FAN_MIN_1 3000 |
||
265 | #define W83781D_INIT_FAN_MIN_2 3000 |
||
266 | #define W83781D_INIT_FAN_MIN_3 3000 |
||
267 | |||
268 | /* temp = value / 100 */ |
||
269 | #define W83781D_INIT_TEMP_OVER 6000 |
||
270 | #define W83781D_INIT_TEMP_HYST 12700 /* must be 127 for ALARM to work */ |
||
271 | #define W83781D_INIT_TEMP2_OVER 6000 |
||
272 | #define W83781D_INIT_TEMP2_HYST 5000 |
||
273 | #define W83781D_INIT_TEMP3_OVER 6000 |
||
274 | #define W83781D_INIT_TEMP3_HYST 5000 |
||
275 | |||
276 | /* There are some complications in a module like this. First off, W83781D chips |
||
277 | may be both present on the SMBus and the ISA bus, and we have to handle |
||
278 | those cases separately at some places. Second, there might be several |
||
279 | W83781D chips available (well, actually, that is probably never done; but |
||
280 | it is a clean illustration of how to handle a case like that). Finally, |
||
281 | a specific chip may be attached to *both* ISA and SMBus, and we would |
||
282 | not like to detect it double. Fortunately, in the case of the W83781D at |
||
283 | least, a register tells us what SMBus address we are on, so that helps |
||
284 | a bit - except if there could be more than one SMBus. Groan. No solution |
||
285 | for this yet. */ |
||
286 | |||
287 | /* This module may seem overly long and complicated. In fact, it is not so |
||
288 | bad. Quite a lot of bookkeeping is done. A real driver can often cut |
||
289 | some corners. */ |
||
290 | |||
291 | /* For each registered W83781D, we need to keep some data in memory. That |
||
292 | data is pointed to by w83781d_list[NR]->data. The structure itself is |
||
293 | dynamically allocated, at the same time when a new w83781d client is |
||
294 | allocated. */ |
||
295 | struct w83781d_data { |
||
296 | struct semaphore lock; |
||
297 | enum chips type; |
||
298 | |||
299 | struct semaphore update_lock; |
||
300 | char valid; /* !=0 if following fields are valid */ |
||
301 | unsigned long last_updated; /* In jiffies */ |
||
302 | |||
303 | struct i2c_client *lm75[2]; /* for secondary I2C addresses */ |
||
304 | /* array of 2 pointers to subclients */ |
||
305 | |||
306 | u8 in[9]; /* Register value - 8 & 9 for 782D only */ |
||
307 | u8 in_max[9]; /* Register value - 8 & 9 for 782D only */ |
||
308 | u8 in_min[9]; /* Register value - 8 & 9 for 782D only */ |
||
309 | u8 fan[3]; /* Register value */ |
||
310 | u8 fan_min[3]; /* Register value */ |
||
311 | u8 temp; |
||
312 | u8 temp_min; /* Register value */ |
||
313 | u8 temp_max; /* Register value */ |
||
314 | u16 temp_add[2]; /* Register value */ |
||
315 | u16 temp_max_add[2]; /* Register value */ |
||
316 | u16 temp_min_add[2]; /* Register value */ |
||
317 | u8 fan_div[3]; /* Register encoding, shifted right */ |
||
318 | u8 vid; /* Register encoding, combined */ |
||
319 | u32 alarms; /* Register encoding, combined */ |
||
320 | u32 beep_mask; /* Register encoding, combined */ |
||
321 | u8 beep_enable; /* Boolean */ |
||
322 | u8 pwm[4]; /* Register value */ |
||
323 | u8 pwmenable[4]; /* Boolean */ |
||
324 | u16 sens[3]; /* 782D/783S only. |
||
325 | 1 = pentium diode; 2 = 3904 diode; |
||
326 | 3000-5000 = thermistor beta. |
||
327 | Default = 3435. |
||
328 | Other Betas unimplemented */ |
||
329 | #ifdef W83781D_RT |
||
330 | u8 rt[3][32]; /* Register value */ |
||
331 | #endif |
||
332 | u8 vrm; |
||
333 | }; |
||
334 | |||
335 | static int w83781d_attach_adapter(struct i2c_adapter *adapter); |
||
336 | static int w83781d_detect(struct i2c_adapter *adapter, int address, int kind); |
||
337 | static int w83781d_detach_client(struct i2c_client *client); |
||
338 | |||
339 | static int w83781d_read_value(struct i2c_client *client, u16 register); |
||
340 | static int w83781d_write_value(struct i2c_client *client, u16 register, |
||
341 | u16 value); |
||
342 | static void w83781d_update_client(struct i2c_client *client); |
||
343 | static void w83781d_init_client(struct i2c_client *client); |
||
344 | |||
345 | static inline u16 swap_bytes(u16 val) |
||
346 | { |
||
347 | return (val >> 8) | (val << 8); |
||
348 | } |
||
349 | |||
350 | static struct i2c_driver w83781d_driver = { |
||
351 | .owner = THIS_MODULE, |
||
352 | .name = "w83781d", |
||
353 | .id = I2C_DRIVERID_W83781D, |
||
354 | .flags = I2C_DF_NOTIFY, |
||
355 | .attach_adapter = w83781d_attach_adapter, |
||
356 | .detach_client = w83781d_detach_client, |
||
357 | }; |
||
358 | |||
359 | /* following are the sysfs callback functions */ |
||
360 | #define show_in_reg(reg) \ |
||
361 | static ssize_t show_##reg (struct device *dev, char *buf, int nr) \ |
||
362 | { \ |
||
363 | struct i2c_client *client = to_i2c_client(dev); \ |
||
364 | struct w83781d_data *data = i2c_get_clientdata(client); \ |
||
365 | \ |
||
366 | w83781d_update_client(client); \ |
||
367 | \ |
||
368 | return sprintf(buf,"%ld\n", (long)IN_FROM_REG(data->reg[nr] * 10)); \ |
||
369 | } |
||
370 | show_in_reg(in); |
||
371 | show_in_reg(in_min); |
||
372 | show_in_reg(in_max); |
||
373 | |||
374 | #define store_in_reg(REG, reg) \ |
||
375 | static ssize_t store_in_##reg (struct device *dev, const char *buf, size_t count, int nr) \ |
||
376 | { \ |
||
377 | struct i2c_client *client = to_i2c_client(dev); \ |
||
378 | struct w83781d_data *data = i2c_get_clientdata(client); \ |
||
379 | u32 val; \ |
||
380 | \ |
||
381 | val = simple_strtoul(buf, NULL, 10) / 10; \ |
||
382 | data->in_##reg[nr] = IN_TO_REG(val); \ |
||
383 | w83781d_write_value(client, W83781D_REG_IN_##REG(nr), data->in_##reg[nr]); \ |
||
384 | \ |
||
385 | return count; \ |
||
386 | } |
||
387 | store_in_reg(MIN, min); |
||
388 | store_in_reg(MAX, max); |
||
389 | |||
390 | #define sysfs_in_offset(offset) \ |
||
391 | static ssize_t \ |
||
392 | show_regs_in_##offset (struct device *dev, char *buf) \ |
||
393 | { \ |
||
394 | return show_in(dev, buf, 0x##offset); \ |
||
395 | } \ |
||
396 | static DEVICE_ATTR(in_input##offset, S_IRUGO, show_regs_in_##offset, NULL) |
||
397 | |||
398 | #define sysfs_in_reg_offset(reg, offset) \ |
||
399 | static ssize_t show_regs_in_##reg##offset (struct device *dev, char *buf) \ |
||
400 | { \ |
||
401 | return show_in_##reg (dev, buf, 0x##offset); \ |
||
402 | } \ |
||
403 | static ssize_t store_regs_in_##reg##offset (struct device *dev, const char *buf, size_t count) \ |
||
404 | { \ |
||
405 | return store_in_##reg (dev, buf, count, 0x##offset); \ |
||
406 | } \ |
||
407 | static DEVICE_ATTR(in_##reg##offset, S_IRUGO| S_IWUSR, show_regs_in_##reg##offset, store_regs_in_##reg##offset) |
||
408 | |||
409 | #define sysfs_in_offsets(offset) \ |
||
410 | sysfs_in_offset(offset); \ |
||
411 | sysfs_in_reg_offset(min, offset); \ |
||
412 | sysfs_in_reg_offset(max, offset); |
||
413 | |||
414 | sysfs_in_offsets(0); |
||
415 | sysfs_in_offsets(1); |
||
416 | sysfs_in_offsets(2); |
||
417 | sysfs_in_offsets(3); |
||
418 | sysfs_in_offsets(4); |
||
419 | sysfs_in_offsets(5); |
||
420 | sysfs_in_offsets(6); |
||
421 | sysfs_in_offsets(7); |
||
422 | sysfs_in_offsets(8); |
||
423 | |||
424 | #define device_create_file_in(client, offset) \ |
||
425 | do { \ |
||
426 | device_create_file(&client->dev, &dev_attr_in_input##offset); \ |
||
427 | device_create_file(&client->dev, &dev_attr_in_min##offset); \ |
||
428 | device_create_file(&client->dev, &dev_attr_in_max##offset); \ |
||
429 | } while (0) |
||
430 | |||
431 | #define show_fan_reg(reg) \ |
||
432 | static ssize_t show_##reg (struct device *dev, char *buf, int nr) \ |
||
433 | { \ |
||
434 | struct i2c_client *client = to_i2c_client(dev); \ |
||
435 | struct w83781d_data *data = i2c_get_clientdata(client); \ |
||
436 | \ |
||
437 | w83781d_update_client(client); \ |
||
438 | \ |
||
439 | return sprintf(buf,"%ld\n", \ |
||
440 | FAN_FROM_REG(data->reg[nr-1], (long)DIV_FROM_REG(data->fan_div[nr-1]))); \ |
||
441 | } |
||
442 | show_fan_reg(fan); |
||
443 | show_fan_reg(fan_min); |
||
444 | |||
445 | static ssize_t |
||
446 | store_fan_min(struct device *dev, const char *buf, size_t count, int nr) |
||
447 | { |
||
448 | struct i2c_client *client = to_i2c_client(dev); |
||
449 | struct w83781d_data *data = i2c_get_clientdata(client); |
||
450 | u32 val; |
||
451 | |||
452 | val = simple_strtoul(buf, NULL, 10); |
||
453 | data->fan_min[nr - 1] = |
||
454 | FAN_TO_REG(val, DIV_FROM_REG(data->fan_div[nr - 1])); |
||
455 | w83781d_write_value(client, W83781D_REG_FAN_MIN(nr), |
||
456 | data->fan_min[nr - 1]); |
||
457 | |||
458 | return count; |
||
459 | } |
||
460 | |||
461 | #define sysfs_fan_offset(offset) \ |
||
462 | static ssize_t show_regs_fan_##offset (struct device *dev, char *buf) \ |
||
463 | { \ |
||
464 | return show_fan(dev, buf, 0x##offset); \ |
||
465 | } \ |
||
466 | static DEVICE_ATTR(fan_input##offset, S_IRUGO, show_regs_fan_##offset, NULL) |
||
467 | |||
468 | #define sysfs_fan_min_offset(offset) \ |
||
469 | static ssize_t show_regs_fan_min##offset (struct device *dev, char *buf) \ |
||
470 | { \ |
||
471 | return show_fan_min(dev, buf, 0x##offset); \ |
||
472 | } \ |
||
473 | static ssize_t store_regs_fan_min##offset (struct device *dev, const char *buf, size_t count) \ |
||
474 | { \ |
||
475 | return store_fan_min(dev, buf, count, 0x##offset); \ |
||
476 | } \ |
||
477 | static DEVICE_ATTR(fan_min##offset, S_IRUGO | S_IWUSR, show_regs_fan_min##offset, store_regs_fan_min##offset) |
||
478 | |||
479 | sysfs_fan_offset(1); |
||
480 | sysfs_fan_min_offset(1); |
||
481 | sysfs_fan_offset(2); |
||
482 | sysfs_fan_min_offset(2); |
||
483 | sysfs_fan_offset(3); |
||
484 | sysfs_fan_min_offset(3); |
||
485 | |||
486 | #define device_create_file_fan(client, offset) \ |
||
487 | do { \ |
||
488 | device_create_file(&client->dev, &dev_attr_fan_input##offset); \ |
||
489 | device_create_file(&client->dev, &dev_attr_fan_min##offset); \ |
||
490 | } while (0) |
||
491 | |||
492 | #define show_temp_reg(reg) \ |
||
493 | static ssize_t show_##reg (struct device *dev, char *buf, int nr) \ |
||
494 | { \ |
||
495 | struct i2c_client *client = to_i2c_client(dev); \ |
||
496 | struct w83781d_data *data = i2c_get_clientdata(client); \ |
||
497 | \ |
||
498 | w83781d_update_client(client); \ |
||
499 | \ |
||
500 | if (nr >= 2) { /* TEMP2 and TEMP3 */ \ |
||
501 | if (data->type == as99127f) { \ |
||
502 | return sprintf(buf,"%ld\n", \ |
||
503 | (long)AS99127_TEMP_ADD_FROM_REG(data->reg##_add[nr-2])); \ |
||
504 | } else { \ |
||
505 | return sprintf(buf,"%ld\n", \ |
||
506 | (long)TEMP_ADD_FROM_REG(data->reg##_add[nr-2])); \ |
||
507 | } \ |
||
508 | } else { /* TEMP1 */ \ |
||
509 | return sprintf(buf,"%ld\n", (long)TEMP_FROM_REG(data->reg)); \ |
||
510 | } \ |
||
511 | } |
||
512 | show_temp_reg(temp); |
||
513 | show_temp_reg(temp_min); |
||
514 | show_temp_reg(temp_max); |
||
515 | |||
516 | #define store_temp_reg(REG, reg) \ |
||
517 | static ssize_t store_temp_##reg (struct device *dev, const char *buf, size_t count, int nr) \ |
||
518 | { \ |
||
519 | struct i2c_client *client = to_i2c_client(dev); \ |
||
520 | struct w83781d_data *data = i2c_get_clientdata(client); \ |
||
521 | u32 val; \ |
||
522 | \ |
||
523 | val = simple_strtoul(buf, NULL, 10); \ |
||
524 | \ |
||
525 | if (nr >= 2) { /* TEMP2 and TEMP3 */ \ |
||
526 | if (data->type == as99127f) \ |
||
527 | data->temp_##reg##_add[nr-2] = AS99127_TEMP_ADD_TO_REG(val); \ |
||
528 | else \ |
||
529 | data->temp_##reg##_add[nr-2] = TEMP_ADD_TO_REG(val); \ |
||
530 | \ |
||
531 | w83781d_write_value(client, W83781D_REG_TEMP_##REG(nr), \ |
||
532 | data->temp_##reg##_add[nr-2]); \ |
||
533 | } else { /* TEMP1 */ \ |
||
534 | data->temp_##reg = TEMP_TO_REG(val); \ |
||
535 | w83781d_write_value(client, W83781D_REG_TEMP_##REG(nr), \ |
||
536 | data->temp_##reg); \ |
||
537 | } \ |
||
538 | \ |
||
539 | return count; \ |
||
540 | } |
||
541 | store_temp_reg(OVER, min); |
||
542 | store_temp_reg(HYST, max); |
||
543 | |||
544 | #define sysfs_temp_offset(offset) \ |
||
545 | static ssize_t \ |
||
546 | show_regs_temp_##offset (struct device *dev, char *buf) \ |
||
547 | { \ |
||
548 | return show_temp(dev, buf, 0x##offset); \ |
||
549 | } \ |
||
550 | static DEVICE_ATTR(temp_input##offset, S_IRUGO, show_regs_temp_##offset, NULL) |
||
551 | |||
552 | #define sysfs_temp_reg_offset(reg, offset) \ |
||
553 | static ssize_t show_regs_temp_##reg##offset (struct device *dev, char *buf) \ |
||
554 | { \ |
||
555 | return show_temp_##reg (dev, buf, 0x##offset); \ |
||
556 | } \ |
||
557 | static ssize_t store_regs_temp_##reg##offset (struct device *dev, const char *buf, size_t count) \ |
||
558 | { \ |
||
559 | return store_temp_##reg (dev, buf, count, 0x##offset); \ |
||
560 | } \ |
||
561 | static DEVICE_ATTR(temp_##reg##offset, S_IRUGO| S_IWUSR, show_regs_temp_##reg##offset, store_regs_temp_##reg##offset) |
||
562 | |||
563 | #define sysfs_temp_offsets(offset) \ |
||
564 | sysfs_temp_offset(offset); \ |
||
565 | sysfs_temp_reg_offset(min, offset); \ |
||
566 | sysfs_temp_reg_offset(max, offset); |
||
567 | |||
568 | sysfs_temp_offsets(1); |
||
569 | sysfs_temp_offsets(2); |
||
570 | sysfs_temp_offsets(3); |
||
571 | |||
572 | #define device_create_file_temp(client, offset) \ |
||
573 | do { \ |
||
574 | device_create_file(&client->dev, &dev_attr_temp_input##offset); \ |
||
575 | device_create_file(&client->dev, &dev_attr_temp_max##offset); \ |
||
576 | device_create_file(&client->dev, &dev_attr_temp_min##offset); \ |
||
577 | } while (0) |
||
578 | |||
579 | static ssize_t |
||
580 | show_vid_reg(struct device *dev, char *buf) |
||
581 | { |
||
582 | struct i2c_client *client = to_i2c_client(dev); |
||
583 | struct w83781d_data *data = i2c_get_clientdata(client); |
||
584 | |||
585 | w83781d_update_client(client); |
||
586 | |||
587 | return sprintf(buf, "%ld\n", (long) vid_from_reg(data->vid, data->vrm)); |
||
588 | } |
||
589 | |||
590 | static |
||
591 | DEVICE_ATTR(vid, S_IRUGO, show_vid_reg, NULL) |
||
592 | #define device_create_file_vid(client) \ |
||
593 | device_create_file(&client->dev, &dev_attr_vid); |
||
594 | static ssize_t |
||
595 | show_vrm_reg(struct device *dev, char *buf) |
||
596 | { |
||
597 | struct i2c_client *client = to_i2c_client(dev); |
||
598 | struct w83781d_data *data = i2c_get_clientdata(client); |
||
599 | |||
600 | w83781d_update_client(client); |
||
601 | |||
602 | return sprintf(buf, "%ld\n", (long) data->vrm); |
||
603 | } |
||
604 | |||
605 | static ssize_t |
||
606 | store_vrm_reg(struct device *dev, const char *buf, size_t count) |
||
607 | { |
||
608 | struct i2c_client *client = to_i2c_client(dev); |
||
609 | struct w83781d_data *data = i2c_get_clientdata(client); |
||
610 | u32 val; |
||
611 | |||
612 | val = simple_strtoul(buf, NULL, 10); |
||
613 | data->vrm = val; |
||
614 | |||
615 | return count; |
||
616 | } |
||
617 | |||
618 | static |
||
619 | DEVICE_ATTR(vrm, S_IRUGO | S_IWUSR, show_vrm_reg, store_vrm_reg) |
||
620 | #define device_create_file_vrm(client) \ |
||
621 | device_create_file(&client->dev, &dev_attr_vrm); |
||
622 | static ssize_t |
||
623 | show_alarms_reg(struct device *dev, char *buf) |
||
624 | { |
||
625 | struct i2c_client *client = to_i2c_client(dev); |
||
626 | struct w83781d_data *data = i2c_get_clientdata(client); |
||
627 | |||
628 | w83781d_update_client(client); |
||
629 | |||
630 | return sprintf(buf, "%ld\n", (long) ALARMS_FROM_REG(data->alarms)); |
||
631 | } |
||
632 | |||
633 | static |
||
634 | DEVICE_ATTR(alarms, S_IRUGO, show_alarms_reg, NULL) |
||
635 | #define device_create_file_alarms(client) \ |
||
636 | device_create_file(&client->dev, &dev_attr_alarms); |
||
637 | #define show_beep_reg(REG, reg) \ |
||
638 | static ssize_t show_beep_##reg (struct device *dev, char *buf) \ |
||
639 | { \ |
||
640 | struct i2c_client *client = to_i2c_client(dev); \ |
||
641 | struct w83781d_data *data = i2c_get_clientdata(client); \ |
||
642 | \ |
||
643 | w83781d_update_client(client); \ |
||
644 | \ |
||
645 | return sprintf(buf,"%ld\n", (long)BEEP_##REG##_FROM_REG(data->beep_##reg)); \ |
||
646 | } |
||
647 | show_beep_reg(ENABLE, enable); |
||
648 | show_beep_reg(MASK, mask); |
||
649 | |||
650 | #define BEEP_ENABLE 0 /* Store beep_enable */ |
||
651 | #define BEEP_MASK 1 /* Store beep_mask */ |
||
652 | |||
653 | static ssize_t |
||
654 | store_beep_reg(struct device *dev, const char *buf, size_t count, |
||
655 | int update_mask) |
||
656 | { |
||
657 | struct i2c_client *client = to_i2c_client(dev); |
||
658 | struct w83781d_data *data = i2c_get_clientdata(client); |
||
659 | u32 val, val2; |
||
660 | |||
661 | val = simple_strtoul(buf, NULL, 10); |
||
662 | |||
663 | if (update_mask == BEEP_MASK) { /* We are storing beep_mask */ |
||
664 | data->beep_mask = BEEP_MASK_TO_REG(val); |
||
665 | w83781d_write_value(client, W83781D_REG_BEEP_INTS1, |
||
666 | data->beep_mask & 0xff); |
||
667 | |||
668 | if ((data->type != w83781d) && (data->type != as99127f)) { |
||
669 | w83781d_write_value(client, W83781D_REG_BEEP_INTS3, |
||
670 | ((data->beep_mask) >> 16) & 0xff); |
||
671 | } |
||
672 | |||
673 | val2 = (data->beep_mask >> 8) & 0x7f; |
||
674 | } else { /* We are storing beep_enable */ |
||
675 | val2 = w83781d_read_value(client, W83781D_REG_BEEP_INTS2) & 0x7f; |
||
676 | data->beep_enable = BEEP_ENABLE_TO_REG(val); |
||
677 | } |
||
678 | |||
679 | w83781d_write_value(client, W83781D_REG_BEEP_INTS2, |
||
680 | val2 | data->beep_enable << 7); |
||
681 | |||
682 | return count; |
||
683 | } |
||
684 | |||
685 | #define sysfs_beep(REG, reg) \ |
||
686 | static ssize_t show_regs_beep_##reg (struct device *dev, char *buf) \ |
||
687 | { \ |
||
688 | return show_beep_##reg(dev, buf); \ |
||
689 | } \ |
||
690 | static ssize_t store_regs_beep_##reg (struct device *dev, const char *buf, size_t count) \ |
||
691 | { \ |
||
692 | return store_beep_reg(dev, buf, count, BEEP_##REG); \ |
||
693 | } \ |
||
694 | static DEVICE_ATTR(beep_##reg, S_IRUGO | S_IWUSR, show_regs_beep_##reg, store_regs_beep_##reg) |
||
695 | |||
696 | sysfs_beep(ENABLE, enable); |
||
697 | sysfs_beep(MASK, mask); |
||
698 | |||
699 | #define device_create_file_beep(client) \ |
||
700 | do { \ |
||
701 | device_create_file(&client->dev, &dev_attr_beep_enable); \ |
||
702 | device_create_file(&client->dev, &dev_attr_beep_mask); \ |
||
703 | } while (0) |
||
704 | |||
705 | /* w83697hf only has two fans */ |
||
706 | static ssize_t |
||
707 | show_fan_div_reg(struct device *dev, char *buf, int nr) |
||
708 | { |
||
709 | struct i2c_client *client = to_i2c_client(dev); |
||
710 | struct w83781d_data *data = i2c_get_clientdata(client); |
||
711 | |||
712 | w83781d_update_client(client); |
||
713 | |||
714 | return sprintf(buf, "%ld\n", |
||
715 | (long) DIV_FROM_REG(data->fan_div[nr - 1])); |
||
716 | } |
||
717 | |||
718 | /* w83697hf only has two fans */ |
||
719 | static ssize_t |
||
720 | store_fan_div_reg(struct device *dev, const char *buf, size_t count, int nr) |
||
721 | { |
||
722 | struct i2c_client *client = to_i2c_client(dev); |
||
723 | struct w83781d_data *data = i2c_get_clientdata(client); |
||
724 | u32 val, old, old2, old3 = 0; |
||
725 | |||
726 | val = simple_strtoul(buf, NULL, 10); |
||
727 | old = w83781d_read_value(client, W83781D_REG_VID_FANDIV); |
||
728 | |||
729 | data->fan_div[nr - 1] = DIV_TO_REG(val, data->type); |
||
730 | |||
731 | /* w83781d and as99127f don't have extended divisor bits */ |
||
732 | if ((data->type != w83781d) && data->type != as99127f) { |
||
733 | old3 = w83781d_read_value(client, W83781D_REG_VBAT); |
||
734 | } |
||
735 | if (nr >= 3 && data->type != w83697hf) { |
||
736 | old2 = w83781d_read_value(client, W83781D_REG_PIN); |
||
737 | old2 = (old2 & 0x3f) | ((data->fan_div[2] & 0x03) << 6); |
||
738 | w83781d_write_value(client, W83781D_REG_PIN, old2); |
||
739 | |||
740 | if ((data->type != w83781d) && (data->type != as99127f)) { |
||
741 | old3 = (old3 & 0x7f) | ((data->fan_div[2] & 0x04) << 5); |
||
742 | } |
||
743 | } |
||
744 | if (nr >= 2) { |
||
745 | old = (old & 0x3f) | ((data->fan_div[1] & 0x03) << 6); |
||
746 | |||
747 | if ((data->type != w83781d) && (data->type != as99127f)) { |
||
748 | old3 = (old3 & 0xbf) | ((data->fan_div[1] & 0x04) << 4); |
||
749 | } |
||
750 | } |
||
751 | if (nr >= 1) { |
||
752 | old = (old & 0xcf) | ((data->fan_div[0] & 0x03) << 4); |
||
753 | w83781d_write_value(client, W83781D_REG_VID_FANDIV, old); |
||
754 | |||
755 | if ((data->type != w83781d) && (data->type != as99127f)) { |
||
756 | old3 = (old3 & 0xdf) | ((data->fan_div[0] & 0x04) << 3); |
||
757 | w83781d_write_value(client, W83781D_REG_VBAT, old3); |
||
758 | } |
||
759 | } |
||
760 | |||
761 | return count; |
||
762 | } |
||
763 | |||
764 | #define sysfs_fan_div(offset) \ |
||
765 | static ssize_t show_regs_fan_div_##offset (struct device *dev, char *buf) \ |
||
766 | { \ |
||
767 | return show_fan_div_reg(dev, buf, offset); \ |
||
768 | } \ |
||
769 | static ssize_t store_regs_fan_div_##offset (struct device *dev, const char *buf, size_t count) \ |
||
770 | { \ |
||
771 | return store_fan_div_reg(dev, buf, count, offset); \ |
||
772 | } \ |
||
773 | static DEVICE_ATTR(fan_div##offset, S_IRUGO | S_IWUSR, show_regs_fan_div_##offset, store_regs_fan_div_##offset) |
||
774 | |||
775 | sysfs_fan_div(1); |
||
776 | sysfs_fan_div(2); |
||
777 | sysfs_fan_div(3); |
||
778 | |||
779 | #define device_create_file_fan_div(client, offset) \ |
||
780 | do { \ |
||
781 | device_create_file(&client->dev, &dev_attr_fan_div##offset); \ |
||
782 | } while (0) |
||
783 | |||
784 | /* w83697hf only has two fans */ |
||
785 | static ssize_t |
||
786 | show_pwm_reg(struct device *dev, char *buf, int nr) |
||
787 | { |
||
788 | struct i2c_client *client = to_i2c_client(dev); |
||
789 | struct w83781d_data *data = i2c_get_clientdata(client); |
||
790 | |||
791 | w83781d_update_client(client); |
||
792 | |||
793 | return sprintf(buf, "%ld\n", (long) PWM_FROM_REG(data->pwm[nr - 1])); |
||
794 | } |
||
795 | |||
796 | /* w83697hf only has two fans */ |
||
797 | static ssize_t |
||
798 | show_pwmenable_reg(struct device *dev, char *buf, int nr) |
||
799 | { |
||
800 | struct i2c_client *client = to_i2c_client(dev); |
||
801 | struct w83781d_data *data = i2c_get_clientdata(client); |
||
802 | |||
803 | w83781d_update_client(client); |
||
804 | |||
805 | return sprintf(buf, "%ld\n", (long) data->pwmenable[nr - 1]); |
||
806 | } |
||
807 | |||
808 | static ssize_t |
||
809 | store_pwm_reg(struct device *dev, const char *buf, size_t count, int nr) |
||
810 | { |
||
811 | struct i2c_client *client = to_i2c_client(dev); |
||
812 | struct w83781d_data *data = i2c_get_clientdata(client); |
||
813 | u32 val; |
||
814 | |||
815 | val = simple_strtoul(buf, NULL, 10); |
||
816 | |||
817 | data->pwm[nr - 1] = PWM_TO_REG(val); |
||
818 | w83781d_write_value(client, W83781D_REG_PWM(nr), data->pwm[nr - 1]); |
||
819 | |||
820 | return count; |
||
821 | } |
||
822 | |||
823 | static ssize_t |
||
824 | store_pwmenable_reg(struct device *dev, const char *buf, size_t count, int nr) |
||
825 | { |
||
826 | struct i2c_client *client = to_i2c_client(dev); |
||
827 | struct w83781d_data *data = i2c_get_clientdata(client); |
||
828 | u32 val, j, k; |
||
829 | |||
830 | val = simple_strtoul(buf, NULL, 10); |
||
831 | |||
832 | /* only PWM2 can be enabled/disabled */ |
||
833 | if (nr == 2) { |
||
834 | j = w83781d_read_value(client, W83781D_REG_PWMCLK12); |
||
835 | k = w83781d_read_value(client, W83781D_REG_BEEP_CONFIG); |
||
836 | |||
837 | if (val > 0) { |
||
838 | if (!(j & 0x08)) |
||
839 | w83781d_write_value(client, |
||
840 | W83781D_REG_PWMCLK12, |
||
841 | j | 0x08); |
||
842 | if (k & 0x10) |
||
843 | w83781d_write_value(client, |
||
844 | W83781D_REG_BEEP_CONFIG, |
||
845 | k & 0xef); |
||
846 | |||
847 | data->pwmenable[1] = 1; |
||
848 | } else { |
||
849 | if (j & 0x08) |
||
850 | w83781d_write_value(client, |
||
851 | W83781D_REG_PWMCLK12, |
||
852 | j & 0xf7); |
||
853 | if (!(k & 0x10)) |
||
854 | w83781d_write_value(client, |
||
855 | W83781D_REG_BEEP_CONFIG, |
||
856 | j | 0x10); |
||
857 | |||
858 | data->pwmenable[1] = 0; |
||
859 | } |
||
860 | } |
||
861 | |||
862 | return count; |
||
863 | } |
||
864 | |||
865 | #define sysfs_pwm(offset) \ |
||
866 | static ssize_t show_regs_pwm_##offset (struct device *dev, char *buf) \ |
||
867 | { \ |
||
868 | return show_pwm_reg(dev, buf, offset); \ |
||
869 | } \ |
||
870 | static ssize_t store_regs_pwm_##offset (struct device *dev, const char *buf, size_t count) \ |
||
871 | { \ |
||
872 | return store_pwm_reg(dev, buf, count, offset); \ |
||
873 | } \ |
||
874 | static DEVICE_ATTR(pwm##offset, S_IRUGO | S_IWUSR, show_regs_pwm_##offset, store_regs_pwm_##offset) |
||
875 | |||
876 | #define sysfs_pwmenable(offset) \ |
||
877 | static ssize_t show_regs_pwmenable_##offset (struct device *dev, char *buf) \ |
||
878 | { \ |
||
879 | return show_pwmenable_reg(dev, buf, offset); \ |
||
880 | } \ |
||
881 | static ssize_t store_regs_pwmenable_##offset (struct device *dev, const char *buf, size_t count) \ |
||
882 | { \ |
||
883 | return store_pwmenable_reg(dev, buf, count, offset); \ |
||
884 | } \ |
||
885 | static DEVICE_ATTR(pwm_enable##offset, S_IRUGO | S_IWUSR, show_regs_pwmenable_##offset, store_regs_pwmenable_##offset) |
||
886 | |||
887 | sysfs_pwm(1); |
||
888 | sysfs_pwm(2); |
||
889 | sysfs_pwmenable(2); /* only PWM2 can be enabled/disabled */ |
||
890 | sysfs_pwm(3); |
||
891 | sysfs_pwm(4); |
||
892 | |||
893 | #define device_create_file_pwm(client, offset) \ |
||
894 | do { \ |
||
895 | device_create_file(&client->dev, &dev_attr_pwm##offset); \ |
||
896 | } while (0) |
||
897 | |||
898 | #define device_create_file_pwmenable(client, offset) \ |
||
899 | do { \ |
||
900 | device_create_file(&client->dev, &dev_attr_pwm_enable##offset); \ |
||
901 | } while (0) |
||
902 | |||
903 | static ssize_t |
||
904 | show_sensor_reg(struct device *dev, char *buf, int nr) |
||
905 | { |
||
906 | struct i2c_client *client = to_i2c_client(dev); |
||
907 | struct w83781d_data *data = i2c_get_clientdata(client); |
||
908 | |||
909 | w83781d_update_client(client); |
||
910 | |||
911 | return sprintf(buf, "%ld\n", (long) data->sens[nr - 1]); |
||
912 | } |
||
913 | |||
914 | static ssize_t |
||
915 | store_sensor_reg(struct device *dev, const char *buf, size_t count, int nr) |
||
916 | { |
||
917 | struct i2c_client *client = to_i2c_client(dev); |
||
918 | struct w83781d_data *data = i2c_get_clientdata(client); |
||
919 | u32 val, tmp; |
||
920 | |||
921 | val = simple_strtoul(buf, NULL, 10); |
||
922 | |||
923 | switch (val) { |
||
924 | case 1: /* PII/Celeron diode */ |
||
925 | tmp = w83781d_read_value(client, W83781D_REG_SCFG1); |
||
926 | w83781d_write_value(client, W83781D_REG_SCFG1, |
||
927 | tmp | BIT_SCFG1[nr - 1]); |
||
928 | tmp = w83781d_read_value(client, W83781D_REG_SCFG2); |
||
929 | w83781d_write_value(client, W83781D_REG_SCFG2, |
||
930 | tmp | BIT_SCFG2[nr - 1]); |
||
931 | data->sens[nr - 1] = val; |
||
932 | break; |
||
933 | case 2: /* 3904 */ |
||
934 | tmp = w83781d_read_value(client, W83781D_REG_SCFG1); |
||
935 | w83781d_write_value(client, W83781D_REG_SCFG1, |
||
936 | tmp | BIT_SCFG1[nr - 1]); |
||
937 | tmp = w83781d_read_value(client, W83781D_REG_SCFG2); |
||
938 | w83781d_write_value(client, W83781D_REG_SCFG2, |
||
939 | tmp & ~BIT_SCFG2[nr - 1]); |
||
940 | data->sens[nr - 1] = val; |
||
941 | break; |
||
942 | case W83781D_DEFAULT_BETA: /* thermistor */ |
||
943 | tmp = w83781d_read_value(client, W83781D_REG_SCFG1); |
||
944 | w83781d_write_value(client, W83781D_REG_SCFG1, |
||
945 | tmp & ~BIT_SCFG1[nr - 1]); |
||
946 | data->sens[nr - 1] = val; |
||
947 | break; |
||
948 | default: |
||
949 | dev_err(&client->dev, |
||
950 | "Invalid sensor type %ld; must be 1, 2, or %d\n", |
||
951 | (long) val, W83781D_DEFAULT_BETA); |
||
952 | break; |
||
953 | } |
||
954 | |||
955 | return count; |
||
956 | } |
||
957 | |||
958 | #define sysfs_sensor(offset) \ |
||
959 | static ssize_t show_regs_sensor_##offset (struct device *dev, char *buf) \ |
||
960 | { \ |
||
961 | return show_sensor_reg(dev, buf, offset); \ |
||
962 | } \ |
||
963 | static ssize_t store_regs_sensor_##offset (struct device *dev, const char *buf, size_t count) \ |
||
964 | { \ |
||
965 | return store_sensor_reg(dev, buf, count, offset); \ |
||
966 | } \ |
||
967 | static DEVICE_ATTR(sensor##offset, S_IRUGO | S_IWUSR, show_regs_sensor_##offset, store_regs_sensor_##offset) |
||
968 | |||
969 | sysfs_sensor(1); |
||
970 | sysfs_sensor(2); |
||
971 | sysfs_sensor(3); |
||
972 | |||
973 | #define device_create_file_sensor(client, offset) \ |
||
974 | do { \ |
||
975 | device_create_file(&client->dev, &dev_attr_sensor##offset); \ |
||
976 | } while (0) |
||
977 | |||
978 | #ifdef W83781D_RT |
||
979 | static ssize_t |
||
980 | show_rt_reg(struct device *dev, char *buf, int nr) |
||
981 | { |
||
982 | struct i2c_client *client = to_i2c_client(dev); |
||
983 | struct w83781d_data *data = i2c_get_clientdata(client); |
||
984 | int i, j = 0; |
||
985 | |||
986 | w83781d_update_client(client); |
||
987 | |||
988 | for (i = 0; i < 32; i++) { |
||
989 | if (i > 0) |
||
990 | j += sprintf(buf, " %ld", (long) data->rt[nr - 1][i]); |
||
991 | else |
||
992 | j += sprintf(buf, "%ld", (long) data->rt[nr - 1][i]); |
||
993 | } |
||
994 | j += sprintf(buf, "\n"); |
||
995 | |||
996 | return j; |
||
997 | } |
||
998 | |||
999 | static ssize_t |
||
1000 | store_rt_reg(struct device *dev, const char *buf, size_t count, int nr) |
||
1001 | { |
||
1002 | struct i2c_client *client = to_i2c_client(dev); |
||
1003 | struct w83781d_data *data = i2c_get_clientdata(client); |
||
1004 | u32 val, i; |
||
1005 | |||
1006 | for (i = 0; i < count; i++) { |
||
1007 | val = simple_strtoul(buf + count, NULL, 10); |
||
1008 | |||
1009 | /* fixme: no bounds checking 0-255 */ |
||
1010 | data->rt[nr - 1][i] = val & 0xff; |
||
1011 | w83781d_write_value(client, W83781D_REG_RT_IDX, i); |
||
1012 | w83781d_write_value(client, W83781D_REG_RT_VAL, |
||
1013 | data->rt[nr - 1][i]); |
||
1014 | } |
||
1015 | |||
1016 | return count; |
||
1017 | } |
||
1018 | |||
1019 | #define sysfs_rt(offset) \ |
||
1020 | static ssize_t show_regs_rt_##offset (struct device *dev, char *buf) \ |
||
1021 | { \ |
||
1022 | return show_rt_reg(dev, buf, offset); \ |
||
1023 | } \ |
||
1024 | static ssize_t store_regs_rt_##offset (struct device *dev, const char *buf, size_t count) \ |
||
1025 | { \ |
||
1026 | return store_rt_reg(dev, buf, count, offset); \ |
||
1027 | } \ |
||
1028 | static DEVICE_ATTR(rt##offset, S_IRUGO | S_IWUSR, show_regs_rt_##offset, store_regs_rt_##offset) |
||
1029 | |||
1030 | sysfs_rt(1); |
||
1031 | sysfs_rt(2); |
||
1032 | sysfs_rt(3); |
||
1033 | |||
1034 | #define device_create_file_rt(client, offset) \ |
||
1035 | do { \ |
||
1036 | device_create_file(&client->dev, &dev_attr_rt##offset); \ |
||
1037 | } while (0) |
||
1038 | |||
1039 | #endif /* ifdef W83781D_RT */ |
||
1040 | |||
1041 | /* This function is called when: |
||
1042 | * w83781d_driver is inserted (when this module is loaded), for each |
||
1043 | available adapter |
||
1044 | * when a new adapter is inserted (and w83781d_driver is still present) */ |
||
1045 | static int |
||
1046 | w83781d_attach_adapter(struct i2c_adapter *adapter) |
||
1047 | { |
||
1048 | if (!(adapter->class & I2C_ADAP_CLASS_SMBUS)) |
||
1049 | return 0; |
||
1050 | return i2c_detect(adapter, &addr_data, w83781d_detect); |
||
1051 | } |
||
1052 | |||
1053 | /* Assumes that adapter is of I2C, not ISA variety. |
||
1054 | * OTHERWISE DON'T CALL THIS |
||
1055 | */ |
||
1056 | static int |
||
1057 | w83781d_detect_subclients(struct i2c_adapter *adapter, int address, int kind, |
||
1058 | struct i2c_client *new_client) |
||
1059 | { |
||
1060 | int i, val1 = 0, id; |
||
1061 | int err; |
||
1062 | const char *client_name; |
||
1063 | struct w83781d_data *data = i2c_get_clientdata(new_client); |
||
1064 | |||
1065 | data->lm75[0] = kmalloc(sizeof(struct i2c_client), GFP_KERNEL); |
||
1066 | if (!(data->lm75[0])) { |
||
1067 | err = -ENOMEM; |
||
1068 | goto ERROR_SC_0; |
||
1069 | } |
||
1070 | memset(data->lm75[0], 0x00, sizeof (struct i2c_client)); |
||
1071 | |||
1072 | id = i2c_adapter_id(adapter); |
||
1073 | |||
1074 | if (force_subclients[0] == id && force_subclients[1] == address) { |
||
1075 | for (i = 2; i <= 3; i++) { |
||
1076 | if (force_subclients[i] < 0x48 || |
||
1077 | force_subclients[i] > 0x4f) { |
||
1078 | dev_err(&new_client->dev, "Invalid subclient " |
||
1079 | "address %d; must be 0x48-0x4f\n", |
||
1080 | force_subclients[i]); |
||
1081 | err = -EINVAL; |
||
1082 | goto ERROR_SC_1; |
||
1083 | } |
||
1084 | } |
||
1085 | w83781d_write_value(new_client, W83781D_REG_I2C_SUBADDR, |
||
1086 | (force_subclients[2] & 0x07) | |
||
1087 | ((force_subclients[3] & 0x07) << 4)); |
||
1088 | data->lm75[0]->addr = force_subclients[2]; |
||
1089 | } else { |
||
1090 | val1 = w83781d_read_value(new_client, W83781D_REG_I2C_SUBADDR); |
||
1091 | data->lm75[0]->addr = 0x48 + (val1 & 0x07); |
||
1092 | } |
||
1093 | |||
1094 | if (kind != w83783s) { |
||
1095 | |||
1096 | data->lm75[1] = kmalloc(sizeof(struct i2c_client), GFP_KERNEL); |
||
1097 | if (!(data->lm75[1])) { |
||
1098 | err = -ENOMEM; |
||
1099 | goto ERROR_SC_1; |
||
1100 | } |
||
1101 | memset(data->lm75[1], 0x0, sizeof(struct i2c_client)); |
||
1102 | |||
1103 | if (force_subclients[0] == id && |
||
1104 | force_subclients[1] == address) { |
||
1105 | data->lm75[1]->addr = force_subclients[3]; |
||
1106 | } else { |
||
1107 | data->lm75[1]->addr = 0x48 + ((val1 >> 4) & 0x07); |
||
1108 | } |
||
1109 | if (data->lm75[0]->addr == data->lm75[1]->addr) { |
||
1110 | dev_err(&new_client->dev, |
||
1111 | "Duplicate addresses 0x%x for subclients.\n", |
||
1112 | data->lm75[0]->addr); |
||
1113 | err = -EBUSY; |
||
1114 | goto ERROR_SC_2; |
||
1115 | } |
||
1116 | } |
||
1117 | |||
1118 | if (kind == w83781d) |
||
1119 | client_name = "w83781d subclient"; |
||
1120 | else if (kind == w83782d) |
||
1121 | client_name = "w83782d subclient"; |
||
1122 | else if (kind == w83783s) |
||
1123 | client_name = "w83783s subclient"; |
||
1124 | else if (kind == w83627hf) |
||
1125 | client_name = "w83627hf subclient"; |
||
1126 | else if (kind == as99127f) |
||
1127 | client_name = "as99127f subclient"; |
||
1128 | else |
||
1129 | client_name = "unknown subclient?"; |
||
1130 | |||
1131 | for (i = 0; i <= 1; i++) { |
||
1132 | /* store all data in w83781d */ |
||
1133 | i2c_set_clientdata(data->lm75[i], NULL); |
||
1134 | data->lm75[i]->adapter = adapter; |
||
1135 | data->lm75[i]->driver = &w83781d_driver; |
||
1136 | data->lm75[i]->flags = 0; |
||
1137 | strlcpy(data->lm75[i]->name, client_name, |
||
1138 | I2C_NAME_SIZE); |
||
1139 | if ((err = i2c_attach_client(data->lm75[i]))) { |
||
1140 | dev_err(&new_client->dev, "Subclient %d " |
||
1141 | "registration at address 0x%x " |
||
1142 | "failed.\n", i, data->lm75[i]->addr); |
||
1143 | if (i == 1) |
||
1144 | goto ERROR_SC_3; |
||
1145 | goto ERROR_SC_2; |
||
1146 | } |
||
1147 | if (kind == w83783s) |
||
1148 | break; |
||
1149 | } |
||
1150 | |||
1151 | return 0; |
||
1152 | |||
1153 | /* Undo inits in case of errors */ |
||
1154 | ERROR_SC_3: |
||
1155 | i2c_detach_client(data->lm75[0]); |
||
1156 | ERROR_SC_2: |
||
1157 | if (NULL != data->lm75[1]) |
||
1158 | kfree(data->lm75[1]); |
||
1159 | ERROR_SC_1: |
||
1160 | if (NULL != data->lm75[0]) |
||
1161 | kfree(data->lm75[0]); |
||
1162 | ERROR_SC_0: |
||
1163 | return err; |
||
1164 | } |
||
1165 | |||
1166 | static int |
||
1167 | w83781d_detect(struct i2c_adapter *adapter, int address, int kind) |
||
1168 | { |
||
1169 | int i = 0, val1 = 0, val2; |
||
1170 | struct i2c_client *new_client; |
||
1171 | struct w83781d_data *data; |
||
1172 | int err; |
||
1173 | const char *client_name = ""; |
||
1174 | int is_isa = i2c_is_isa_adapter(adapter); |
||
1175 | enum vendor { winbond, asus } vendid; |
||
1176 | |||
1177 | if (!is_isa |
||
1178 | && !i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA)) { |
||
1179 | err = -EINVAL; |
||
1180 | goto ERROR0; |
||
1181 | } |
||
1182 | |||
1183 | if (is_isa) |
||
1184 | if (!request_region(address, W83781D_EXTENT, "w83781d")) { |
||
1185 | err = -EBUSY; |
||
1186 | goto ERROR0; |
||
1187 | } |
||
1188 | |||
1189 | /* Probe whether there is anything available on this address. Already |
||
1190 | done for SMBus clients */ |
||
1191 | if (kind < 0) { |
||
1192 | if (is_isa) { |
||
1193 | |||
1194 | #define REALLY_SLOW_IO |
||
1195 | /* We need the timeouts for at least some LM78-like |
||
1196 | chips. But only if we read 'undefined' registers. */ |
||
1197 | i = inb_p(address + 1); |
||
1198 | if (inb_p(address + 2) != i) { |
||
1199 | err = -ENODEV; |
||
1200 | goto ERROR1; |
||
1201 | } |
||
1202 | if (inb_p(address + 3) != i) { |
||
1203 | err = -ENODEV; |
||
1204 | goto ERROR1; |
||
1205 | } |
||
1206 | if (inb_p(address + 7) != i) { |
||
1207 | err = -ENODEV; |
||
1208 | goto ERROR1; |
||
1209 | } |
||
1210 | #undef REALLY_SLOW_IO |
||
1211 | |||
1212 | /* Let's just hope nothing breaks here */ |
||
1213 | i = inb_p(address + 5) & 0x7f; |
||
1214 | outb_p(~i & 0x7f, address + 5); |
||
1215 | if ((inb_p(address + 5) & 0x7f) != (~i & 0x7f)) { |
||
1216 | outb_p(i, address + 5); |
||
1217 | err = -ENODEV; |
||
1218 | goto ERROR1; |
||
1219 | } |
||
1220 | } |
||
1221 | } |
||
1222 | |||
1223 | /* OK. For now, we presume we have a valid client. We now create the |
||
1224 | client structure, even though we cannot fill it completely yet. |
||
1225 | But it allows us to access w83781d_{read,write}_value. */ |
||
1226 | |||
1227 | if (!(new_client = kmalloc(sizeof (struct i2c_client) + |
||
1228 | sizeof (struct w83781d_data), GFP_KERNEL))) { |
||
1229 | err = -ENOMEM; |
||
1230 | goto ERROR1; |
||
1231 | } |
||
1232 | |||
1233 | memset(new_client, 0x00, sizeof (struct i2c_client) + |
||
1234 | sizeof (struct w83781d_data)); |
||
1235 | |||
1236 | data = (struct w83781d_data *) (new_client + 1); |
||
1237 | i2c_set_clientdata(new_client, data); |
||
1238 | new_client->addr = address; |
||
1239 | init_MUTEX(&data->lock); |
||
1240 | new_client->adapter = adapter; |
||
1241 | new_client->driver = &w83781d_driver; |
||
1242 | new_client->flags = 0; |
||
1243 | |||
1244 | /* Now, we do the remaining detection. */ |
||
1245 | |||
1246 | /* The w8378?d may be stuck in some other bank than bank 0. This may |
||
1247 | make reading other information impossible. Specify a force=... or |
||
1248 | force_*=... parameter, and the Winbond will be reset to the right |
||
1249 | bank. */ |
||
1250 | if (kind < 0) { |
||
1251 | if (w83781d_read_value(new_client, W83781D_REG_CONFIG) & 0x80){ |
||
1252 | err = -ENODEV; |
||
1253 | goto ERROR2; |
||
1254 | } |
||
1255 | val1 = w83781d_read_value(new_client, W83781D_REG_BANK); |
||
1256 | val2 = w83781d_read_value(new_client, W83781D_REG_CHIPMAN); |
||
1257 | /* Check for Winbond or Asus ID if in bank 0 */ |
||
1258 | if ((!(val1 & 0x07)) && |
||
1259 | (((!(val1 & 0x80)) && (val2 != 0xa3) && (val2 != 0xc3) |
||
1260 | && (val2 != 0x94)) |
||
1261 | || ((val1 & 0x80) && (val2 != 0x5c) && (val2 != 0x12) |
||
1262 | && (val2 != 0x06)))) { |
||
1263 | err = -ENODEV; |
||
1264 | goto ERROR2; |
||
1265 | } |
||
1266 | /* If Winbond SMBus, check address at 0x48. |
||
1267 | Asus doesn't support */ |
||
1268 | if ((!is_isa) && (((!(val1 & 0x80)) && (val2 == 0xa3)) || |
||
1269 | ((val1 & 0x80) && (val2 == 0x5c)))) { |
||
1270 | if (w83781d_read_value |
||
1271 | (new_client, W83781D_REG_I2C_ADDR) != address) { |
||
1272 | err = -ENODEV; |
||
1273 | goto ERROR2; |
||
1274 | } |
||
1275 | } |
||
1276 | } |
||
1277 | |||
1278 | /* We have either had a force parameter, or we have already detected the |
||
1279 | Winbond. Put it now into bank 0 and Vendor ID High Byte */ |
||
1280 | w83781d_write_value(new_client, W83781D_REG_BANK, |
||
1281 | (w83781d_read_value(new_client, |
||
1282 | W83781D_REG_BANK) & 0x78) | |
||
1283 | 0x80); |
||
1284 | |||
1285 | /* Determine the chip type. */ |
||
1286 | if (kind <= 0) { |
||
1287 | /* get vendor ID */ |
||
1288 | val2 = w83781d_read_value(new_client, W83781D_REG_CHIPMAN); |
||
1289 | if (val2 == 0x5c) |
||
1290 | vendid = winbond; |
||
1291 | else if ((val2 == 0x12) || (val2 == 0x06)) |
||
1292 | vendid = asus; |
||
1293 | else { |
||
1294 | err = -ENODEV; |
||
1295 | goto ERROR2; |
||
1296 | } |
||
1297 | |||
1298 | /* mask off lower bit, not reliable */ |
||
1299 | val1 = |
||
1300 | w83781d_read_value(new_client, W83781D_REG_WCHIPID) & 0xfe; |
||
1301 | if (val1 == 0x10 && vendid == winbond) |
||
1302 | kind = w83781d; |
||
1303 | else if (val1 == 0x30 && vendid == winbond) |
||
1304 | kind = w83782d; |
||
1305 | else if (val1 == 0x40 && vendid == winbond && !is_isa) |
||
1306 | kind = w83783s; |
||
1307 | else if ((val1 == 0x20 || val1 == 0x90) && vendid == winbond) |
||
1308 | kind = w83627hf; |
||
1309 | else if (val1 == 0x30 && vendid == asus && !is_isa) |
||
1310 | kind = as99127f; |
||
1311 | else if (val1 == 0x60 && vendid == winbond && is_isa) |
||
1312 | kind = w83697hf; |
||
1313 | else { |
||
1314 | if (kind == 0) |
||
1315 | dev_warn(&new_client->dev, |
||
1316 | "Ignoring 'force' parameter for unknown chip at" |
||
1317 | "adapter %d, address 0x%02x\n", |
||
1318 | i2c_adapter_id(adapter), address); |
||
1319 | err = -EINVAL; |
||
1320 | goto ERROR2; |
||
1321 | } |
||
1322 | } |
||
1323 | |||
1324 | if (kind == w83781d) { |
||
1325 | client_name = "w83781d"; |
||
1326 | } else if (kind == w83782d) { |
||
1327 | client_name = "w83782d"; |
||
1328 | } else if (kind == w83783s) { |
||
1329 | client_name = "w83783s"; |
||
1330 | } else if (kind == w83627hf) { |
||
1331 | if (val1 == 0x90) |
||
1332 | client_name = "w83627thf"; |
||
1333 | else |
||
1334 | client_name = "w83627hf"; |
||
1335 | } else if (kind == as99127f) { |
||
1336 | client_name = "as99127f"; |
||
1337 | } else if (kind == w83697hf) { |
||
1338 | client_name = "w83697hf"; |
||
1339 | } else { |
||
1340 | dev_err(&new_client->dev, "Internal error: unknown " |
||
1341 | "kind (%d)?!?", kind); |
||
1342 | err = -ENODEV; |
||
1343 | goto ERROR2; |
||
1344 | } |
||
1345 | |||
1346 | /* Fill in the remaining client fields and put into the global list */ |
||
1347 | strlcpy(new_client->name, client_name, I2C_NAME_SIZE); |
||
1348 | data->type = kind; |
||
1349 | |||
1350 | data->valid = 0; |
||
1351 | init_MUTEX(&data->update_lock); |
||
1352 | |||
1353 | /* Tell the I2C layer a new client has arrived */ |
||
1354 | if ((err = i2c_attach_client(new_client))) |
||
1355 | goto ERROR2; |
||
1356 | |||
1357 | /* attach secondary i2c lm75-like clients */ |
||
1358 | if (!is_isa) { |
||
1359 | if ((err = w83781d_detect_subclients(adapter, address, |
||
1360 | kind, new_client))) |
||
1361 | goto ERROR3; |
||
1362 | } else { |
||
1363 | data->lm75[0] = NULL; |
||
1364 | data->lm75[1] = NULL; |
||
1365 | } |
||
1366 | |||
1367 | /* Initialize the chip */ |
||
1368 | w83781d_init_client(new_client); |
||
1369 | |||
1370 | /* Register sysfs hooks */ |
||
1371 | device_create_file_in(new_client, 0); |
||
1372 | if (kind != w83783s && kind != w83697hf) |
||
1373 | device_create_file_in(new_client, 1); |
||
1374 | device_create_file_in(new_client, 2); |
||
1375 | device_create_file_in(new_client, 3); |
||
1376 | device_create_file_in(new_client, 4); |
||
1377 | device_create_file_in(new_client, 5); |
||
1378 | device_create_file_in(new_client, 6); |
||
1379 | if (kind != as99127f && kind != w83781d && kind != w83783s) { |
||
1380 | device_create_file_in(new_client, 7); |
||
1381 | device_create_file_in(new_client, 8); |
||
1382 | } |
||
1383 | |||
1384 | device_create_file_fan(new_client, 1); |
||
1385 | device_create_file_fan(new_client, 2); |
||
1386 | if (kind != w83697hf) |
||
1387 | device_create_file_fan(new_client, 3); |
||
1388 | |||
1389 | device_create_file_temp(new_client, 1); |
||
1390 | device_create_file_temp(new_client, 2); |
||
1391 | if (kind != w83783s && kind != w83697hf) |
||
1392 | device_create_file_temp(new_client, 3); |
||
1393 | |||
1394 | if (kind != w83697hf) |
||
1395 | device_create_file_vid(new_client); |
||
1396 | |||
1397 | if (kind != w83697hf) |
||
1398 | device_create_file_vrm(new_client); |
||
1399 | |||
1400 | device_create_file_fan_div(new_client, 1); |
||
1401 | device_create_file_fan_div(new_client, 2); |
||
1402 | if (kind != w83697hf) |
||
1403 | device_create_file_fan_div(new_client, 3); |
||
1404 | |||
1405 | device_create_file_alarms(new_client); |
||
1406 | |||
1407 | device_create_file_beep(new_client); |
||
1408 | |||
1409 | if (kind != w83781d) { |
||
1410 | device_create_file_pwm(new_client, 1); |
||
1411 | device_create_file_pwm(new_client, 2); |
||
1412 | device_create_file_pwmenable(new_client, 2); |
||
1413 | } |
||
1414 | if (kind == w83782d && !is_isa) { |
||
1415 | device_create_file_pwm(new_client, 3); |
||
1416 | device_create_file_pwm(new_client, 4); |
||
1417 | } |
||
1418 | |||
1419 | if (kind != as99127f && kind != w83781d) { |
||
1420 | device_create_file_sensor(new_client, 1); |
||
1421 | device_create_file_sensor(new_client, 2); |
||
1422 | if (kind != w83783s && kind != w83697hf) |
||
1423 | device_create_file_sensor(new_client, 3); |
||
1424 | } |
||
1425 | #ifdef W83781D_RT |
||
1426 | if (kind == w83781d) { |
||
1427 | device_create_file_rt(new_client, 1); |
||
1428 | device_create_file_rt(new_client, 2); |
||
1429 | device_create_file_rt(new_client, 3); |
||
1430 | } |
||
1431 | #endif |
||
1432 | |||
1433 | return 0; |
||
1434 | |||
1435 | ERROR3: |
||
1436 | i2c_detach_client(new_client); |
||
1437 | ERROR2: |
||
1438 | kfree(new_client); |
||
1439 | ERROR1: |
||
1440 | if (is_isa) |
||
1441 | release_region(address, W83781D_EXTENT); |
||
1442 | ERROR0: |
||
1443 | return err; |
||
1444 | } |
||
1445 | |||
1446 | static int |
||
1447 | w83781d_detach_client(struct i2c_client *client) |
||
1448 | { |
||
1449 | int err; |
||
1450 | |||
1451 | if (i2c_is_isa_client(client)) |
||
1452 | release_region(client->addr, W83781D_EXTENT); |
||
1453 | |||
1454 | if ((err = i2c_detach_client(client))) { |
||
1455 | dev_err(&client->dev, |
||
1456 | "Client deregistration failed, client not detached.\n"); |
||
1457 | return err; |
||
1458 | } |
||
1459 | |||
1460 | kfree(client); |
||
1461 | |||
1462 | return 0; |
||
1463 | } |
||
1464 | |||
1465 | /* The SMBus locks itself, usually, but nothing may access the Winbond between |
||
1466 | bank switches. ISA access must always be locked explicitly! |
||
1467 | We ignore the W83781D BUSY flag at this moment - it could lead to deadlocks, |
||
1468 | would slow down the W83781D access and should not be necessary. |
||
1469 | There are some ugly typecasts here, but the good news is - they should |
||
1470 | nowhere else be necessary! */ |
||
1471 | static int |
||
1472 | w83781d_read_value(struct i2c_client *client, u16 reg) |
||
1473 | { |
||
1474 | struct w83781d_data *data = i2c_get_clientdata(client); |
||
1475 | int res, word_sized, bank; |
||
1476 | struct i2c_client *cl; |
||
1477 | |||
1478 | down(&data->lock); |
||
1479 | if (i2c_is_isa_client(client)) { |
||
1480 | word_sized = (((reg & 0xff00) == 0x100) |
||
1481 | || ((reg & 0xff00) == 0x200)) |
||
1482 | && (((reg & 0x00ff) == 0x50) |
||
1483 | || ((reg & 0x00ff) == 0x53) |
||
1484 | || ((reg & 0x00ff) == 0x55)); |
||
1485 | if (reg & 0xff00) { |
||
1486 | outb_p(W83781D_REG_BANK, |
||
1487 | client->addr + W83781D_ADDR_REG_OFFSET); |
||
1488 | outb_p(reg >> 8, |
||
1489 | client->addr + W83781D_DATA_REG_OFFSET); |
||
1490 | } |
||
1491 | outb_p(reg & 0xff, client->addr + W83781D_ADDR_REG_OFFSET); |
||
1492 | res = inb_p(client->addr + W83781D_DATA_REG_OFFSET); |
||
1493 | if (word_sized) { |
||
1494 | outb_p((reg & 0xff) + 1, |
||
1495 | client->addr + W83781D_ADDR_REG_OFFSET); |
||
1496 | res = |
||
1497 | (res << 8) + inb_p(client->addr + |
||
1498 | W83781D_DATA_REG_OFFSET); |
||
1499 | } |
||
1500 | if (reg & 0xff00) { |
||
1501 | outb_p(W83781D_REG_BANK, |
||
1502 | client->addr + W83781D_ADDR_REG_OFFSET); |
||
1503 | outb_p(0, client->addr + W83781D_DATA_REG_OFFSET); |
||
1504 | } |
||
1505 | } else { |
||
1506 | bank = (reg >> 8) & 0x0f; |
||
1507 | if (bank > 2) |
||
1508 | /* switch banks */ |
||
1509 | i2c_smbus_write_byte_data(client, W83781D_REG_BANK, |
||
1510 | bank); |
||
1511 | if (bank == 0 || bank > 2) { |
||
1512 | res = i2c_smbus_read_byte_data(client, reg & 0xff); |
||
1513 | } else { |
||
1514 | /* switch to subclient */ |
||
1515 | cl = data->lm75[bank - 1]; |
||
1516 | /* convert from ISA to LM75 I2C addresses */ |
||
1517 | switch (reg & 0xff) { |
||
1518 | case 0x50: /* TEMP */ |
||
1519 | res = |
||
1520 | swap_bytes(i2c_smbus_read_word_data(cl, 0)); |
||
1521 | break; |
||
1522 | case 0x52: /* CONFIG */ |
||
1523 | res = i2c_smbus_read_byte_data(cl, 1); |
||
1524 | break; |
||
1525 | case 0x53: /* HYST */ |
||
1526 | res = |
||
1527 | swap_bytes(i2c_smbus_read_word_data(cl, 2)); |
||
1528 | break; |
||
1529 | case 0x55: /* OVER */ |
||
1530 | default: |
||
1531 | res = |
||
1532 | swap_bytes(i2c_smbus_read_word_data(cl, 3)); |
||
1533 | break; |
||
1534 | } |
||
1535 | } |
||
1536 | if (bank > 2) |
||
1537 | i2c_smbus_write_byte_data(client, W83781D_REG_BANK, 0); |
||
1538 | } |
||
1539 | up(&data->lock); |
||
1540 | return res; |
||
1541 | } |
||
1542 | |||
1543 | static int |
||
1544 | w83781d_write_value(struct i2c_client *client, u16 reg, u16 value) |
||
1545 | { |
||
1546 | struct w83781d_data *data = i2c_get_clientdata(client); |
||
1547 | int word_sized, bank; |
||
1548 | struct i2c_client *cl; |
||
1549 | |||
1550 | down(&data->lock); |
||
1551 | if (i2c_is_isa_client(client)) { |
||
1552 | word_sized = (((reg & 0xff00) == 0x100) |
||
1553 | || ((reg & 0xff00) == 0x200)) |
||
1554 | && (((reg & 0x00ff) == 0x53) |
||
1555 | || ((reg & 0x00ff) == 0x55)); |
||
1556 | if (reg & 0xff00) { |
||
1557 | outb_p(W83781D_REG_BANK, |
||
1558 | client->addr + W83781D_ADDR_REG_OFFSET); |
||
1559 | outb_p(reg >> 8, |
||
1560 | client->addr + W83781D_DATA_REG_OFFSET); |
||
1561 | } |
||
1562 | outb_p(reg & 0xff, client->addr + W83781D_ADDR_REG_OFFSET); |
||
1563 | if (word_sized) { |
||
1564 | outb_p(value >> 8, |
||
1565 | client->addr + W83781D_DATA_REG_OFFSET); |
||
1566 | outb_p((reg & 0xff) + 1, |
||
1567 | client->addr + W83781D_ADDR_REG_OFFSET); |
||
1568 | } |
||
1569 | outb_p(value & 0xff, client->addr + W83781D_DATA_REG_OFFSET); |
||
1570 | if (reg & 0xff00) { |
||
1571 | outb_p(W83781D_REG_BANK, |
||
1572 | client->addr + W83781D_ADDR_REG_OFFSET); |
||
1573 | outb_p(0, client->addr + W83781D_DATA_REG_OFFSET); |
||
1574 | } |
||
1575 | } else { |
||
1576 | bank = (reg >> 8) & 0x0f; |
||
1577 | if (bank > 2) |
||
1578 | /* switch banks */ |
||
1579 | i2c_smbus_write_byte_data(client, W83781D_REG_BANK, |
||
1580 | bank); |
||
1581 | if (bank == 0 || bank > 2) { |
||
1582 | i2c_smbus_write_byte_data(client, reg & 0xff, |
||
1583 | value & 0xff); |
||
1584 | } else { |
||
1585 | /* switch to subclient */ |
||
1586 | cl = data->lm75[bank - 1]; |
||
1587 | /* convert from ISA to LM75 I2C addresses */ |
||
1588 | switch (reg & 0xff) { |
||
1589 | case 0x52: /* CONFIG */ |
||
1590 | i2c_smbus_write_byte_data(cl, 1, value & 0xff); |
||
1591 | break; |
||
1592 | case 0x53: /* HYST */ |
||
1593 | i2c_smbus_write_word_data(cl, 2, |
||
1594 | swap_bytes(value)); |
||
1595 | break; |
||
1596 | case 0x55: /* OVER */ |
||
1597 | i2c_smbus_write_word_data(cl, 3, |
||
1598 | swap_bytes(value)); |
||
1599 | break; |
||
1600 | } |
||
1601 | } |
||
1602 | if (bank > 2) |
||
1603 | i2c_smbus_write_byte_data(client, W83781D_REG_BANK, 0); |
||
1604 | } |
||
1605 | up(&data->lock); |
||
1606 | return 0; |
||
1607 | } |
||
1608 | |||
1609 | /* Called when we have found a new W83781D. It should set limits, etc. */ |
||
1610 | static void |
||
1611 | w83781d_init_client(struct i2c_client *client) |
||
1612 | { |
||
1613 | struct w83781d_data *data = i2c_get_clientdata(client); |
||
1614 | int vid = 0, i, p; |
||
1615 | int type = data->type; |
||
1616 | u8 tmp; |
||
1617 | |||
1618 | if (init && type != as99127f) { /* this resets registers we don't have |
||
1619 | documentation for on the as99127f */ |
||
1620 | /* save these registers */ |
||
1621 | i = w83781d_read_value(client, W83781D_REG_BEEP_CONFIG); |
||
1622 | p = w83781d_read_value(client, W83781D_REG_PWMCLK12); |
||
1623 | /* Reset all except Watchdog values and last conversion values |
||
1624 | This sets fan-divs to 2, among others */ |
||
1625 | w83781d_write_value(client, W83781D_REG_CONFIG, 0x80); |
||
1626 | /* Restore the registers and disable power-on abnormal beep. |
||
1627 | This saves FAN 1/2/3 input/output values set by BIOS. */ |
||
1628 | w83781d_write_value(client, W83781D_REG_BEEP_CONFIG, i | 0x80); |
||
1629 | w83781d_write_value(client, W83781D_REG_PWMCLK12, p); |
||
1630 | /* Disable master beep-enable (reset turns it on). |
||
1631 | Individual beep_mask should be reset to off but for some reason |
||
1632 | disabling this bit helps some people not get beeped */ |
||
1633 | w83781d_write_value(client, W83781D_REG_BEEP_INTS2, 0); |
||
1634 | } |
||
1635 | |||
1636 | if (type != w83697hf) { |
||
1637 | vid = w83781d_read_value(client, W83781D_REG_VID_FANDIV) & 0x0f; |
||
1638 | vid |= |
||
1639 | (w83781d_read_value(client, W83781D_REG_CHIPID) & 0x01) << |
||
1640 | 4; |
||
1641 | data->vrm = DEFAULT_VRM; |
||
1642 | vid = vid_from_reg(vid, data->vrm); |
||
1643 | } |
||
1644 | |||
1645 | if ((type != w83781d) && (type != as99127f)) { |
||
1646 | tmp = w83781d_read_value(client, W83781D_REG_SCFG1); |
||
1647 | for (i = 1; i <= 3; i++) { |
||
1648 | if (!(tmp & BIT_SCFG1[i - 1])) { |
||
1649 | data->sens[i - 1] = W83781D_DEFAULT_BETA; |
||
1650 | } else { |
||
1651 | if (w83781d_read_value |
||
1652 | (client, |
||
1653 | W83781D_REG_SCFG2) & BIT_SCFG2[i - 1]) |
||
1654 | data->sens[i - 1] = 1; |
||
1655 | else |
||
1656 | data->sens[i - 1] = 2; |
||
1657 | } |
||
1658 | if ((type == w83783s || type == w83697hf) && (i == 2)) |
||
1659 | break; |
||
1660 | } |
||
1661 | } |
||
1662 | #ifdef W83781D_RT |
||
1663 | /* |
||
1664 | Fill up the RT Tables. |
||
1665 | We assume that they are 32 bytes long, in order for temp 1-3. |
||
1666 | Data sheet documentation is sparse. |
||
1667 | We also assume that it is only for the 781D although I suspect |
||
1668 | that the others support it as well.... |
||
1669 | */ |
||
1670 | |||
1671 | if (init && type == w83781d) { |
||
1672 | u16 k = 0; |
||
1673 | /* |
||
1674 | Auto-indexing doesn't seem to work... |
||
1675 | w83781d_write_value(client,W83781D_REG_RT_IDX,0); |
||
1676 | */ |
||
1677 | for (i = 0; i < 3; i++) { |
||
1678 | int j; |
||
1679 | for (j = 0; j < 32; j++) { |
||
1680 | w83781d_write_value(client, |
||
1681 | W83781D_REG_RT_IDX, k++); |
||
1682 | data->rt[i][j] = |
||
1683 | w83781d_read_value(client, |
||
1684 | W83781D_REG_RT_VAL); |
||
1685 | } |
||
1686 | } |
||
1687 | } |
||
1688 | #endif /* W83781D_RT */ |
||
1689 | |||
1690 | if (init) { |
||
1691 | w83781d_write_value(client, W83781D_REG_IN_MIN(0), |
||
1692 | IN_TO_REG(W83781D_INIT_IN_MIN_0)); |
||
1693 | w83781d_write_value(client, W83781D_REG_IN_MAX(0), |
||
1694 | IN_TO_REG(W83781D_INIT_IN_MAX_0)); |
||
1695 | if (type != w83783s && type != w83697hf) { |
||
1696 | w83781d_write_value(client, W83781D_REG_IN_MIN(1), |
||
1697 | IN_TO_REG(W83781D_INIT_IN_MIN_1)); |
||
1698 | w83781d_write_value(client, W83781D_REG_IN_MAX(1), |
||
1699 | IN_TO_REG(W83781D_INIT_IN_MAX_1)); |
||
1700 | } |
||
1701 | |||
1702 | w83781d_write_value(client, W83781D_REG_IN_MIN(2), |
||
1703 | IN_TO_REG(W83781D_INIT_IN_MIN_2)); |
||
1704 | w83781d_write_value(client, W83781D_REG_IN_MAX(2), |
||
1705 | IN_TO_REG(W83781D_INIT_IN_MAX_2)); |
||
1706 | w83781d_write_value(client, W83781D_REG_IN_MIN(3), |
||
1707 | IN_TO_REG(W83781D_INIT_IN_MIN_3)); |
||
1708 | w83781d_write_value(client, W83781D_REG_IN_MAX(3), |
||
1709 | IN_TO_REG(W83781D_INIT_IN_MAX_3)); |
||
1710 | w83781d_write_value(client, W83781D_REG_IN_MIN(4), |
||
1711 | IN_TO_REG(W83781D_INIT_IN_MIN_4)); |
||
1712 | w83781d_write_value(client, W83781D_REG_IN_MAX(4), |
||
1713 | IN_TO_REG(W83781D_INIT_IN_MAX_4)); |
||
1714 | if (type == w83781d || type == as99127f) { |
||
1715 | w83781d_write_value(client, W83781D_REG_IN_MIN(5), |
||
1716 | IN_TO_REG(W83781D_INIT_IN_MIN_5)); |
||
1717 | w83781d_write_value(client, W83781D_REG_IN_MAX(5), |
||
1718 | IN_TO_REG(W83781D_INIT_IN_MAX_5)); |
||
1719 | } else { |
||
1720 | w83781d_write_value(client, W83781D_REG_IN_MIN(5), |
||
1721 | IN_TO_REG(W83782D_INIT_IN_MIN_5)); |
||
1722 | w83781d_write_value(client, W83781D_REG_IN_MAX(5), |
||
1723 | IN_TO_REG(W83782D_INIT_IN_MAX_5)); |
||
1724 | } |
||
1725 | if (type == w83781d || type == as99127f) { |
||
1726 | w83781d_write_value(client, W83781D_REG_IN_MIN(6), |
||
1727 | IN_TO_REG(W83781D_INIT_IN_MIN_6)); |
||
1728 | w83781d_write_value(client, W83781D_REG_IN_MAX(6), |
||
1729 | IN_TO_REG(W83781D_INIT_IN_MAX_6)); |
||
1730 | } else { |
||
1731 | w83781d_write_value(client, W83781D_REG_IN_MIN(6), |
||
1732 | IN_TO_REG(W83782D_INIT_IN_MIN_6)); |
||
1733 | w83781d_write_value(client, W83781D_REG_IN_MAX(6), |
||
1734 | IN_TO_REG(W83782D_INIT_IN_MAX_6)); |
||
1735 | } |
||
1736 | if ((type == w83782d) || (type == w83627hf) || |
||
1737 | (type == w83697hf)) { |
||
1738 | w83781d_write_value(client, W83781D_REG_IN_MIN(7), |
||
1739 | IN_TO_REG(W83781D_INIT_IN_MIN_7)); |
||
1740 | w83781d_write_value(client, W83781D_REG_IN_MAX(7), |
||
1741 | IN_TO_REG(W83781D_INIT_IN_MAX_7)); |
||
1742 | w83781d_write_value(client, W83781D_REG_IN_MIN(8), |
||
1743 | IN_TO_REG(W83781D_INIT_IN_MIN_8)); |
||
1744 | w83781d_write_value(client, W83781D_REG_IN_MAX(8), |
||
1745 | IN_TO_REG(W83781D_INIT_IN_MAX_8)); |
||
1746 | w83781d_write_value(client, W83781D_REG_VBAT, |
||
1747 | (w83781d_read_value |
||
1748 | (client, |
||
1749 | W83781D_REG_VBAT) | 0x01)); |
||
1750 | } |
||
1751 | w83781d_write_value(client, W83781D_REG_FAN_MIN(1), |
||
1752 | FAN_TO_REG(W83781D_INIT_FAN_MIN_1, 2)); |
||
1753 | w83781d_write_value(client, W83781D_REG_FAN_MIN(2), |
||
1754 | FAN_TO_REG(W83781D_INIT_FAN_MIN_2, 2)); |
||
1755 | if (type != w83697hf) { |
||
1756 | w83781d_write_value(client, W83781D_REG_FAN_MIN(3), |
||
1757 | FAN_TO_REG(W83781D_INIT_FAN_MIN_3, |
||
1758 | 2)); |
||
1759 | } |
||
1760 | |||
1761 | w83781d_write_value(client, W83781D_REG_TEMP_OVER(1), |
||
1762 | TEMP_TO_REG(W83781D_INIT_TEMP_OVER)); |
||
1763 | w83781d_write_value(client, W83781D_REG_TEMP_HYST(1), |
||
1764 | TEMP_TO_REG(W83781D_INIT_TEMP_HYST)); |
||
1765 | |||
1766 | if (type == as99127f) { |
||
1767 | w83781d_write_value(client, W83781D_REG_TEMP_OVER(2), |
||
1768 | AS99127_TEMP_ADD_TO_REG |
||
1769 | (W83781D_INIT_TEMP2_OVER)); |
||
1770 | w83781d_write_value(client, W83781D_REG_TEMP_HYST(2), |
||
1771 | AS99127_TEMP_ADD_TO_REG |
||
1772 | (W83781D_INIT_TEMP2_HYST)); |
||
1773 | } else { |
||
1774 | w83781d_write_value(client, W83781D_REG_TEMP_OVER(2), |
||
1775 | TEMP_ADD_TO_REG |
||
1776 | (W83781D_INIT_TEMP2_OVER)); |
||
1777 | w83781d_write_value(client, W83781D_REG_TEMP_HYST(2), |
||
1778 | TEMP_ADD_TO_REG |
||
1779 | (W83781D_INIT_TEMP2_HYST)); |
||
1780 | } |
||
1781 | w83781d_write_value(client, W83781D_REG_TEMP2_CONFIG, 0x00); |
||
1782 | |||
1783 | if (type == as99127f) { |
||
1784 | w83781d_write_value(client, W83781D_REG_TEMP_OVER(3), |
||
1785 | AS99127_TEMP_ADD_TO_REG |
||
1786 | (W83781D_INIT_TEMP3_OVER)); |
||
1787 | w83781d_write_value(client, W83781D_REG_TEMP_HYST(3), |
||
1788 | AS99127_TEMP_ADD_TO_REG |
||
1789 | (W83781D_INIT_TEMP3_HYST)); |
||
1790 | } else if (type != w83783s && type != w83697hf) { |
||
1791 | w83781d_write_value(client, W83781D_REG_TEMP_OVER(3), |
||
1792 | TEMP_ADD_TO_REG |
||
1793 | (W83781D_INIT_TEMP3_OVER)); |
||
1794 | w83781d_write_value(client, W83781D_REG_TEMP_HYST(3), |
||
1795 | TEMP_ADD_TO_REG |
||
1796 | (W83781D_INIT_TEMP3_HYST)); |
||
1797 | } |
||
1798 | if (type != w83783s && type != w83697hf) { |
||
1799 | w83781d_write_value(client, W83781D_REG_TEMP3_CONFIG, |
||
1800 | 0x00); |
||
1801 | } |
||
1802 | if (type != w83781d) { |
||
1803 | /* enable comparator mode for temp2 and temp3 so |
||
1804 | alarm indication will work correctly */ |
||
1805 | w83781d_write_value(client, W83781D_REG_IRQ, 0x41); |
||
1806 | for (i = 0; i < 3; i++) |
||
1807 | data->pwmenable[i] = 1; |
||
1808 | } |
||
1809 | } |
||
1810 | |||
1811 | /* Start monitoring */ |
||
1812 | w83781d_write_value(client, W83781D_REG_CONFIG, |
||
1813 | (w83781d_read_value(client, |
||
1814 | W83781D_REG_CONFIG) & 0xf7) |
||
1815 | | 0x01); |
||
1816 | } |
||
1817 | |||
1818 | static void |
||
1819 | w83781d_update_client(struct i2c_client *client) |
||
1820 | { |
||
1821 | struct w83781d_data *data = i2c_get_clientdata(client); |
||
1822 | int i; |
||
1823 | |||
1824 | down(&data->update_lock); |
||
1825 | |||
1826 | if (time_after |
||
1827 | (jiffies - data->last_updated, (unsigned long) (HZ + HZ / 2)) |
||
1828 | || time_before(jiffies, data->last_updated) || !data->valid) { |
||
1829 | pr_debug(KERN_DEBUG "Starting device update\n"); |
||
1830 | |||
1831 | for (i = 0; i <= 8; i++) { |
||
1832 | if ((data->type == w83783s || data->type == w83697hf) |
||
1833 | && (i == 1)) |
||
1834 | continue; /* 783S has no in1 */ |
||
1835 | data->in[i] = |
||
1836 | w83781d_read_value(client, W83781D_REG_IN(i)); |
||
1837 | data->in_min[i] = |
||
1838 | w83781d_read_value(client, W83781D_REG_IN_MIN(i)); |
||
1839 | data->in_max[i] = |
||
1840 | w83781d_read_value(client, W83781D_REG_IN_MAX(i)); |
||
1841 | if ((data->type != w83782d) && (data->type != w83697hf) |
||
1842 | && (data->type != w83627hf) && (i == 6)) |
||
1843 | break; |
||
1844 | } |
||
1845 | for (i = 1; i <= 3; i++) { |
||
1846 | data->fan[i - 1] = |
||
1847 | w83781d_read_value(client, W83781D_REG_FAN(i)); |
||
1848 | data->fan_min[i - 1] = |
||
1849 | w83781d_read_value(client, W83781D_REG_FAN_MIN(i)); |
||
1850 | } |
||
1851 | if (data->type != w83781d) { |
||
1852 | for (i = 1; i <= 4; i++) { |
||
1853 | data->pwm[i - 1] = |
||
1854 | w83781d_read_value(client, |
||
1855 | W83781D_REG_PWM(i)); |
||
1856 | if (((data->type == w83783s) |
||
1857 | || (data->type == w83627hf) |
||
1858 | || (data->type == as99127f) |
||
1859 | || (data->type == w83697hf) |
||
1860 | || ((data->type == w83782d) |
||
1861 | && i2c_is_isa_client(client))) |
||
1862 | && i == 2) |
||
1863 | break; |
||
1864 | } |
||
1865 | } |
||
1866 | |||
1867 | data->temp = w83781d_read_value(client, W83781D_REG_TEMP(1)); |
||
1868 | data->temp_min = |
||
1869 | w83781d_read_value(client, W83781D_REG_TEMP_OVER(1)); |
||
1870 | data->temp_max = |
||
1871 | w83781d_read_value(client, W83781D_REG_TEMP_HYST(1)); |
||
1872 | data->temp_add[0] = |
||
1873 | w83781d_read_value(client, W83781D_REG_TEMP(2)); |
||
1874 | data->temp_max_add[0] = |
||
1875 | w83781d_read_value(client, W83781D_REG_TEMP_OVER(2)); |
||
1876 | data->temp_min_add[0] = |
||
1877 | w83781d_read_value(client, W83781D_REG_TEMP_HYST(2)); |
||
1878 | if (data->type != w83783s && data->type != w83697hf) { |
||
1879 | data->temp_add[1] = |
||
1880 | w83781d_read_value(client, W83781D_REG_TEMP(3)); |
||
1881 | data->temp_max_add[1] = |
||
1882 | w83781d_read_value(client, |
||
1883 | W83781D_REG_TEMP_OVER(3)); |
||
1884 | data->temp_min_add[1] = |
||
1885 | w83781d_read_value(client, |
||
1886 | W83781D_REG_TEMP_HYST(3)); |
||
1887 | } |
||
1888 | i = w83781d_read_value(client, W83781D_REG_VID_FANDIV); |
||
1889 | if (data->type != w83697hf) { |
||
1890 | data->vid = i & 0x0f; |
||
1891 | data->vid |= |
||
1892 | (w83781d_read_value(client, W83781D_REG_CHIPID) & |
||
1893 | 0x01) |
||
1894 | << 4; |
||
1895 | } |
||
1896 | data->fan_div[0] = (i >> 4) & 0x03; |
||
1897 | data->fan_div[1] = (i >> 6) & 0x03; |
||
1898 | if (data->type != w83697hf) { |
||
1899 | data->fan_div[2] = (w83781d_read_value(client, |
||
1900 | W83781D_REG_PIN) |
||
1901 | >> 6) & 0x03; |
||
1902 | } |
||
1903 | if ((data->type != w83781d) && (data->type != as99127f)) { |
||
1904 | i = w83781d_read_value(client, W83781D_REG_VBAT); |
||
1905 | data->fan_div[0] |= (i >> 3) & 0x04; |
||
1906 | data->fan_div[1] |= (i >> 4) & 0x04; |
||
1907 | if (data->type != w83697hf) |
||
1908 | data->fan_div[2] |= (i >> 5) & 0x04; |
||
1909 | } |
||
1910 | data->alarms = |
||
1911 | w83781d_read_value(client, |
||
1912 | W83781D_REG_ALARM1) + |
||
1913 | (w83781d_read_value(client, W83781D_REG_ALARM2) << 8); |
||
1914 | if ((data->type == w83782d) || (data->type == w83627hf)) { |
||
1915 | data->alarms |= |
||
1916 | w83781d_read_value(client, |
||
1917 | W83781D_REG_ALARM3) << 16; |
||
1918 | } |
||
1919 | i = w83781d_read_value(client, W83781D_REG_BEEP_INTS2); |
||
1920 | data->beep_enable = i >> 7; |
||
1921 | data->beep_mask = ((i & 0x7f) << 8) + |
||
1922 | w83781d_read_value(client, W83781D_REG_BEEP_INTS1); |
||
1923 | if ((data->type != w83781d) && (data->type != as99127f)) { |
||
1924 | data->beep_mask |= |
||
1925 | w83781d_read_value(client, |
||
1926 | W83781D_REG_BEEP_INTS3) << 16; |
||
1927 | } |
||
1928 | data->last_updated = jiffies; |
||
1929 | data->valid = 1; |
||
1930 | } |
||
1931 | |||
1932 | up(&data->update_lock); |
||
1933 | } |
||
1934 | |||
1935 | static int __init |
||
1936 | sensors_w83781d_init(void) |
||
1937 | { |
||
1938 | return i2c_add_driver(&w83781d_driver); |
||
1939 | } |
||
1940 | |||
1941 | static void __exit |
||
1942 | sensors_w83781d_exit(void) |
||
1943 | { |
||
1944 | i2c_del_driver(&w83781d_driver); |
||
1945 | } |
||
1946 | |||
1947 | MODULE_AUTHOR("Frodo Looijaard <frodol@dds.nl>, " |
||
1948 | "Philip Edelbrock <phil@netroedge.com>, " |
||
1949 | "and Mark Studebaker <mdsxyz123@yahoo.com>"); |
||
1950 | MODULE_DESCRIPTION("W83781D driver"); |
||
1951 | MODULE_LICENSE("GPL"); |
||
1952 | |||
1953 | module_init(sensors_w83781d_init); |
||
1954 | module_exit(sensors_w83781d_exit); |