diff options
author | Linus Torvalds <torvalds@ppc970.osdl.org> | 2005-04-16 18:20:36 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@ppc970.osdl.org> | 2005-04-16 18:20:36 -0400 |
commit | 1da177e4c3f41524e886b7f1b8a0c1fc7321cac2 (patch) | |
tree | 0bba044c4ce775e45a88a51686b5d9f90697ea9d /drivers/i2c/chips/adm1031.c |
Linux-2.6.12-rc2v2.6.12-rc2
Initial git repository build. I'm not bothering with the full history,
even though we have it. We can create a separate "historical" git
archive of that later if we want to, and in the meantime it's about
3.2GB when imported into git - space that would just make the early
git days unnecessarily complicated, when we don't have a lot of good
infrastructure for it.
Let it rip!
Diffstat (limited to 'drivers/i2c/chips/adm1031.c')
-rw-r--r-- | drivers/i2c/chips/adm1031.c | 977 |
1 files changed, 977 insertions, 0 deletions
diff --git a/drivers/i2c/chips/adm1031.c b/drivers/i2c/chips/adm1031.c new file mode 100644 index 000000000000..d4385a23f79a --- /dev/null +++ b/drivers/i2c/chips/adm1031.c | |||
@@ -0,0 +1,977 @@ | |||
1 | /* | ||
2 | adm1031.c - Part of lm_sensors, Linux kernel modules for hardware | ||
3 | monitoring | ||
4 | Based on lm75.c and lm85.c | ||
5 | Supports adm1030 / adm1031 | ||
6 | Copyright (C) 2004 Alexandre d'Alton <alex@alexdalton.org> | ||
7 | Reworked by Jean Delvare <khali@linux-fr.org> | ||
8 | |||
9 | 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 | the Free Software Foundation; either version 2 of the License, or | ||
12 | (at your option) any later version. | ||
13 | |||
14 | This program is distributed in the hope that it will be useful, | ||
15 | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
16 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
17 | GNU General Public License for more details. | ||
18 | |||
19 | You should have received a copy of the GNU General Public License | ||
20 | along with this program; if not, write to the Free Software | ||
21 | Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
22 | */ | ||
23 | |||
24 | #include <linux/module.h> | ||
25 | #include <linux/init.h> | ||
26 | #include <linux/slab.h> | ||
27 | #include <linux/jiffies.h> | ||
28 | #include <linux/i2c.h> | ||
29 | #include <linux/i2c-sensor.h> | ||
30 | |||
31 | /* Following macros takes channel parameter starting from 0 to 2 */ | ||
32 | #define ADM1031_REG_FAN_SPEED(nr) (0x08 + (nr)) | ||
33 | #define ADM1031_REG_FAN_DIV(nr) (0x20 + (nr)) | ||
34 | #define ADM1031_REG_PWM (0x22) | ||
35 | #define ADM1031_REG_FAN_MIN(nr) (0x10 + (nr)) | ||
36 | |||
37 | #define ADM1031_REG_TEMP_MAX(nr) (0x14 + 4*(nr)) | ||
38 | #define ADM1031_REG_TEMP_MIN(nr) (0x15 + 4*(nr)) | ||
39 | #define ADM1031_REG_TEMP_CRIT(nr) (0x16 + 4*(nr)) | ||
40 | |||
41 | #define ADM1031_REG_TEMP(nr) (0xa + (nr)) | ||
42 | #define ADM1031_REG_AUTO_TEMP(nr) (0x24 + (nr)) | ||
43 | |||
44 | #define ADM1031_REG_STATUS(nr) (0x2 + (nr)) | ||
45 | |||
46 | #define ADM1031_REG_CONF1 0x0 | ||
47 | #define ADM1031_REG_CONF2 0x1 | ||
48 | #define ADM1031_REG_EXT_TEMP 0x6 | ||
49 | |||
50 | #define ADM1031_CONF1_MONITOR_ENABLE 0x01 /* Monitoring enable */ | ||
51 | #define ADM1031_CONF1_PWM_INVERT 0x08 /* PWM Invert */ | ||
52 | #define ADM1031_CONF1_AUTO_MODE 0x80 /* Auto FAN */ | ||
53 | |||
54 | #define ADM1031_CONF2_PWM1_ENABLE 0x01 | ||
55 | #define ADM1031_CONF2_PWM2_ENABLE 0x02 | ||
56 | #define ADM1031_CONF2_TACH1_ENABLE 0x04 | ||
57 | #define ADM1031_CONF2_TACH2_ENABLE 0x08 | ||
58 | #define ADM1031_CONF2_TEMP_ENABLE(chan) (0x10 << (chan)) | ||
59 | |||
60 | /* Addresses to scan */ | ||
61 | static unsigned short normal_i2c[] = { 0x2c, 0x2d, 0x2e, I2C_CLIENT_END }; | ||
62 | static unsigned int normal_isa[] = { I2C_CLIENT_ISA_END }; | ||
63 | |||
64 | /* Insmod parameters */ | ||
65 | SENSORS_INSMOD_2(adm1030, adm1031); | ||
66 | |||
67 | typedef u8 auto_chan_table_t[8][2]; | ||
68 | |||
69 | /* Each client has this additional data */ | ||
70 | struct adm1031_data { | ||
71 | struct i2c_client client; | ||
72 | struct semaphore update_lock; | ||
73 | int chip_type; | ||
74 | char valid; /* !=0 if following fields are valid */ | ||
75 | unsigned long last_updated; /* In jiffies */ | ||
76 | /* The chan_select_table contains the possible configurations for | ||
77 | * auto fan control. | ||
78 | */ | ||
79 | auto_chan_table_t *chan_select_table; | ||
80 | u16 alarm; | ||
81 | u8 conf1; | ||
82 | u8 conf2; | ||
83 | u8 fan[2]; | ||
84 | u8 fan_div[2]; | ||
85 | u8 fan_min[2]; | ||
86 | u8 pwm[2]; | ||
87 | u8 old_pwm[2]; | ||
88 | s8 temp[3]; | ||
89 | u8 ext_temp[3]; | ||
90 | u8 auto_temp[3]; | ||
91 | u8 auto_temp_min[3]; | ||
92 | u8 auto_temp_off[3]; | ||
93 | u8 auto_temp_max[3]; | ||
94 | s8 temp_min[3]; | ||
95 | s8 temp_max[3]; | ||
96 | s8 temp_crit[3]; | ||
97 | }; | ||
98 | |||
99 | static int adm1031_attach_adapter(struct i2c_adapter *adapter); | ||
100 | static int adm1031_detect(struct i2c_adapter *adapter, int address, int kind); | ||
101 | static void adm1031_init_client(struct i2c_client *client); | ||
102 | static int adm1031_detach_client(struct i2c_client *client); | ||
103 | static struct adm1031_data *adm1031_update_device(struct device *dev); | ||
104 | |||
105 | /* This is the driver that will be inserted */ | ||
106 | static struct i2c_driver adm1031_driver = { | ||
107 | .owner = THIS_MODULE, | ||
108 | .name = "adm1031", | ||
109 | .flags = I2C_DF_NOTIFY, | ||
110 | .attach_adapter = adm1031_attach_adapter, | ||
111 | .detach_client = adm1031_detach_client, | ||
112 | }; | ||
113 | |||
114 | static inline u8 adm1031_read_value(struct i2c_client *client, u8 reg) | ||
115 | { | ||
116 | return i2c_smbus_read_byte_data(client, reg); | ||
117 | } | ||
118 | |||
119 | static inline int | ||
120 | adm1031_write_value(struct i2c_client *client, u8 reg, unsigned int value) | ||
121 | { | ||
122 | return i2c_smbus_write_byte_data(client, reg, value); | ||
123 | } | ||
124 | |||
125 | |||
126 | #define TEMP_TO_REG(val) (((val) < 0 ? ((val - 500) / 1000) : \ | ||
127 | ((val + 500) / 1000))) | ||
128 | |||
129 | #define TEMP_FROM_REG(val) ((val) * 1000) | ||
130 | |||
131 | #define TEMP_FROM_REG_EXT(val, ext) (TEMP_FROM_REG(val) + (ext) * 125) | ||
132 | |||
133 | #define FAN_FROM_REG(reg, div) ((reg) ? (11250 * 60) / ((reg) * (div)) : 0) | ||
134 | |||
135 | static int FAN_TO_REG(int reg, int div) | ||
136 | { | ||
137 | int tmp; | ||
138 | tmp = FAN_FROM_REG(SENSORS_LIMIT(reg, 0, 65535), div); | ||
139 | return tmp > 255 ? 255 : tmp; | ||
140 | } | ||
141 | |||
142 | #define FAN_DIV_FROM_REG(reg) (1<<(((reg)&0xc0)>>6)) | ||
143 | |||
144 | #define PWM_TO_REG(val) (SENSORS_LIMIT((val), 0, 255) >> 4) | ||
145 | #define PWM_FROM_REG(val) ((val) << 4) | ||
146 | |||
147 | #define FAN_CHAN_FROM_REG(reg) (((reg) >> 5) & 7) | ||
148 | #define FAN_CHAN_TO_REG(val, reg) \ | ||
149 | (((reg) & 0x1F) | (((val) << 5) & 0xe0)) | ||
150 | |||
151 | #define AUTO_TEMP_MIN_TO_REG(val, reg) \ | ||
152 | ((((val)/500) & 0xf8)|((reg) & 0x7)) | ||
153 | #define AUTO_TEMP_RANGE_FROM_REG(reg) (5000 * (1<< ((reg)&0x7))) | ||
154 | #define AUTO_TEMP_MIN_FROM_REG(reg) (1000 * ((((reg) >> 3) & 0x1f) << 2)) | ||
155 | |||
156 | #define AUTO_TEMP_MIN_FROM_REG_DEG(reg) ((((reg) >> 3) & 0x1f) << 2) | ||
157 | |||
158 | #define AUTO_TEMP_OFF_FROM_REG(reg) \ | ||
159 | (AUTO_TEMP_MIN_FROM_REG(reg) - 5000) | ||
160 | |||
161 | #define AUTO_TEMP_MAX_FROM_REG(reg) \ | ||
162 | (AUTO_TEMP_RANGE_FROM_REG(reg) + \ | ||
163 | AUTO_TEMP_MIN_FROM_REG(reg)) | ||
164 | |||
165 | static int AUTO_TEMP_MAX_TO_REG(int val, int reg, int pwm) | ||
166 | { | ||
167 | int ret; | ||
168 | int range = val - AUTO_TEMP_MIN_FROM_REG(reg); | ||
169 | |||
170 | range = ((val - AUTO_TEMP_MIN_FROM_REG(reg))*10)/(16 - pwm); | ||
171 | ret = ((reg & 0xf8) | | ||
172 | (range < 10000 ? 0 : | ||
173 | range < 20000 ? 1 : | ||
174 | range < 40000 ? 2 : range < 80000 ? 3 : 4)); | ||
175 | return ret; | ||
176 | } | ||
177 | |||
178 | /* FAN auto control */ | ||
179 | #define GET_FAN_AUTO_BITFIELD(data, idx) \ | ||
180 | (*(data)->chan_select_table)[FAN_CHAN_FROM_REG((data)->conf1)][idx%2] | ||
181 | |||
182 | /* The tables below contains the possible values for the auto fan | ||
183 | * control bitfields. the index in the table is the register value. | ||
184 | * MSb is the auto fan control enable bit, so the four first entries | ||
185 | * in the table disables auto fan control when both bitfields are zero. | ||
186 | */ | ||
187 | static auto_chan_table_t auto_channel_select_table_adm1031 = { | ||
188 | {0, 0}, {0, 0}, {0, 0}, {0, 0}, | ||
189 | {2 /*0b010 */ , 4 /*0b100 */ }, | ||
190 | {2 /*0b010 */ , 2 /*0b010 */ }, | ||
191 | {4 /*0b100 */ , 4 /*0b100 */ }, | ||
192 | {7 /*0b111 */ , 7 /*0b111 */ }, | ||
193 | }; | ||
194 | |||
195 | static auto_chan_table_t auto_channel_select_table_adm1030 = { | ||
196 | {0, 0}, {0, 0}, {0, 0}, {0, 0}, | ||
197 | {2 /*0b10 */ , 0}, | ||
198 | {0xff /*invalid */ , 0}, | ||
199 | {0xff /*invalid */ , 0}, | ||
200 | {3 /*0b11 */ , 0}, | ||
201 | }; | ||
202 | |||
203 | /* That function checks if a bitfield is valid and returns the other bitfield | ||
204 | * nearest match if no exact match where found. | ||
205 | */ | ||
206 | static int | ||
207 | get_fan_auto_nearest(struct adm1031_data *data, | ||
208 | int chan, u8 val, u8 reg, u8 * new_reg) | ||
209 | { | ||
210 | int i; | ||
211 | int first_match = -1, exact_match = -1; | ||
212 | u8 other_reg_val = | ||
213 | (*data->chan_select_table)[FAN_CHAN_FROM_REG(reg)][chan ? 0 : 1]; | ||
214 | |||
215 | if (val == 0) { | ||
216 | *new_reg = 0; | ||
217 | return 0; | ||
218 | } | ||
219 | |||
220 | for (i = 0; i < 8; i++) { | ||
221 | if ((val == (*data->chan_select_table)[i][chan]) && | ||
222 | ((*data->chan_select_table)[i][chan ? 0 : 1] == | ||
223 | other_reg_val)) { | ||
224 | /* We found an exact match */ | ||
225 | exact_match = i; | ||
226 | break; | ||
227 | } else if (val == (*data->chan_select_table)[i][chan] && | ||
228 | first_match == -1) { | ||
229 | /* Save the first match in case of an exact match has not been | ||
230 | * found | ||
231 | */ | ||
232 | first_match = i; | ||
233 | } | ||
234 | } | ||
235 | |||
236 | if (exact_match >= 0) { | ||
237 | *new_reg = exact_match; | ||
238 | } else if (first_match >= 0) { | ||
239 | *new_reg = first_match; | ||
240 | } else { | ||
241 | return -EINVAL; | ||
242 | } | ||
243 | return 0; | ||
244 | } | ||
245 | |||
246 | static ssize_t show_fan_auto_channel(struct device *dev, char *buf, int nr) | ||
247 | { | ||
248 | struct adm1031_data *data = adm1031_update_device(dev); | ||
249 | return sprintf(buf, "%d\n", GET_FAN_AUTO_BITFIELD(data, nr)); | ||
250 | } | ||
251 | |||
252 | static ssize_t | ||
253 | set_fan_auto_channel(struct device *dev, const char *buf, size_t count, int nr) | ||
254 | { | ||
255 | struct i2c_client *client = to_i2c_client(dev); | ||
256 | struct adm1031_data *data = i2c_get_clientdata(client); | ||
257 | int val = simple_strtol(buf, NULL, 10); | ||
258 | u8 reg; | ||
259 | int ret; | ||
260 | u8 old_fan_mode; | ||
261 | |||
262 | old_fan_mode = data->conf1; | ||
263 | |||
264 | down(&data->update_lock); | ||
265 | |||
266 | if ((ret = get_fan_auto_nearest(data, nr, val, data->conf1, ®))) { | ||
267 | up(&data->update_lock); | ||
268 | return ret; | ||
269 | } | ||
270 | if (((data->conf1 = FAN_CHAN_TO_REG(reg, data->conf1)) & ADM1031_CONF1_AUTO_MODE) ^ | ||
271 | (old_fan_mode & ADM1031_CONF1_AUTO_MODE)) { | ||
272 | if (data->conf1 & ADM1031_CONF1_AUTO_MODE){ | ||
273 | /* Switch to Auto Fan Mode | ||
274 | * Save PWM registers | ||
275 | * Set PWM registers to 33% Both */ | ||
276 | data->old_pwm[0] = data->pwm[0]; | ||
277 | data->old_pwm[1] = data->pwm[1]; | ||
278 | adm1031_write_value(client, ADM1031_REG_PWM, 0x55); | ||
279 | } else { | ||
280 | /* Switch to Manual Mode */ | ||
281 | data->pwm[0] = data->old_pwm[0]; | ||
282 | data->pwm[1] = data->old_pwm[1]; | ||
283 | /* Restore PWM registers */ | ||
284 | adm1031_write_value(client, ADM1031_REG_PWM, | ||
285 | data->pwm[0] | (data->pwm[1] << 4)); | ||
286 | } | ||
287 | } | ||
288 | data->conf1 = FAN_CHAN_TO_REG(reg, data->conf1); | ||
289 | adm1031_write_value(client, ADM1031_REG_CONF1, data->conf1); | ||
290 | up(&data->update_lock); | ||
291 | return count; | ||
292 | } | ||
293 | |||
294 | #define fan_auto_channel_offset(offset) \ | ||
295 | static ssize_t show_fan_auto_channel_##offset (struct device *dev, char *buf) \ | ||
296 | { \ | ||
297 | return show_fan_auto_channel(dev, buf, offset - 1); \ | ||
298 | } \ | ||
299 | static ssize_t set_fan_auto_channel_##offset (struct device *dev, \ | ||
300 | const char *buf, size_t count) \ | ||
301 | { \ | ||
302 | return set_fan_auto_channel(dev, buf, count, offset - 1); \ | ||
303 | } \ | ||
304 | static DEVICE_ATTR(auto_fan##offset##_channel, S_IRUGO | S_IWUSR, \ | ||
305 | show_fan_auto_channel_##offset, \ | ||
306 | set_fan_auto_channel_##offset) | ||
307 | |||
308 | fan_auto_channel_offset(1); | ||
309 | fan_auto_channel_offset(2); | ||
310 | |||
311 | /* Auto Temps */ | ||
312 | static ssize_t show_auto_temp_off(struct device *dev, char *buf, int nr) | ||
313 | { | ||
314 | struct adm1031_data *data = adm1031_update_device(dev); | ||
315 | return sprintf(buf, "%d\n", | ||
316 | AUTO_TEMP_OFF_FROM_REG(data->auto_temp[nr])); | ||
317 | } | ||
318 | static ssize_t show_auto_temp_min(struct device *dev, char *buf, int nr) | ||
319 | { | ||
320 | struct adm1031_data *data = adm1031_update_device(dev); | ||
321 | return sprintf(buf, "%d\n", | ||
322 | AUTO_TEMP_MIN_FROM_REG(data->auto_temp[nr])); | ||
323 | } | ||
324 | static ssize_t | ||
325 | set_auto_temp_min(struct device *dev, const char *buf, size_t count, int nr) | ||
326 | { | ||
327 | struct i2c_client *client = to_i2c_client(dev); | ||
328 | struct adm1031_data *data = i2c_get_clientdata(client); | ||
329 | int val = simple_strtol(buf, NULL, 10); | ||
330 | |||
331 | down(&data->update_lock); | ||
332 | data->auto_temp[nr] = AUTO_TEMP_MIN_TO_REG(val, data->auto_temp[nr]); | ||
333 | adm1031_write_value(client, ADM1031_REG_AUTO_TEMP(nr), | ||
334 | data->auto_temp[nr]); | ||
335 | up(&data->update_lock); | ||
336 | return count; | ||
337 | } | ||
338 | static ssize_t show_auto_temp_max(struct device *dev, char *buf, int nr) | ||
339 | { | ||
340 | struct adm1031_data *data = adm1031_update_device(dev); | ||
341 | return sprintf(buf, "%d\n", | ||
342 | AUTO_TEMP_MAX_FROM_REG(data->auto_temp[nr])); | ||
343 | } | ||
344 | static ssize_t | ||
345 | set_auto_temp_max(struct device *dev, const char *buf, size_t count, int nr) | ||
346 | { | ||
347 | struct i2c_client *client = to_i2c_client(dev); | ||
348 | struct adm1031_data *data = i2c_get_clientdata(client); | ||
349 | int val = simple_strtol(buf, NULL, 10); | ||
350 | |||
351 | down(&data->update_lock); | ||
352 | data->temp_max[nr] = AUTO_TEMP_MAX_TO_REG(val, data->auto_temp[nr], data->pwm[nr]); | ||
353 | adm1031_write_value(client, ADM1031_REG_AUTO_TEMP(nr), | ||
354 | data->temp_max[nr]); | ||
355 | up(&data->update_lock); | ||
356 | return count; | ||
357 | } | ||
358 | |||
359 | #define auto_temp_reg(offset) \ | ||
360 | static ssize_t show_auto_temp_##offset##_off (struct device *dev, char *buf) \ | ||
361 | { \ | ||
362 | return show_auto_temp_off(dev, buf, offset - 1); \ | ||
363 | } \ | ||
364 | static ssize_t show_auto_temp_##offset##_min (struct device *dev, char *buf) \ | ||
365 | { \ | ||
366 | return show_auto_temp_min(dev, buf, offset - 1); \ | ||
367 | } \ | ||
368 | static ssize_t show_auto_temp_##offset##_max (struct device *dev, char *buf) \ | ||
369 | { \ | ||
370 | return show_auto_temp_max(dev, buf, offset - 1); \ | ||
371 | } \ | ||
372 | static ssize_t set_auto_temp_##offset##_min (struct device *dev, \ | ||
373 | const char *buf, size_t count) \ | ||
374 | { \ | ||
375 | return set_auto_temp_min(dev, buf, count, offset - 1); \ | ||
376 | } \ | ||
377 | static ssize_t set_auto_temp_##offset##_max (struct device *dev, \ | ||
378 | const char *buf, size_t count) \ | ||
379 | { \ | ||
380 | return set_auto_temp_max(dev, buf, count, offset - 1); \ | ||
381 | } \ | ||
382 | static DEVICE_ATTR(auto_temp##offset##_off, S_IRUGO, \ | ||
383 | show_auto_temp_##offset##_off, NULL); \ | ||
384 | static DEVICE_ATTR(auto_temp##offset##_min, S_IRUGO | S_IWUSR, \ | ||
385 | show_auto_temp_##offset##_min, set_auto_temp_##offset##_min);\ | ||
386 | static DEVICE_ATTR(auto_temp##offset##_max, S_IRUGO | S_IWUSR, \ | ||
387 | show_auto_temp_##offset##_max, set_auto_temp_##offset##_max) | ||
388 | |||
389 | auto_temp_reg(1); | ||
390 | auto_temp_reg(2); | ||
391 | auto_temp_reg(3); | ||
392 | |||
393 | /* pwm */ | ||
394 | static ssize_t show_pwm(struct device *dev, char *buf, int nr) | ||
395 | { | ||
396 | struct adm1031_data *data = adm1031_update_device(dev); | ||
397 | return sprintf(buf, "%d\n", PWM_FROM_REG(data->pwm[nr])); | ||
398 | } | ||
399 | static ssize_t | ||
400 | set_pwm(struct device *dev, const char *buf, size_t count, int nr) | ||
401 | { | ||
402 | struct i2c_client *client = to_i2c_client(dev); | ||
403 | struct adm1031_data *data = i2c_get_clientdata(client); | ||
404 | int val = simple_strtol(buf, NULL, 10); | ||
405 | int reg; | ||
406 | |||
407 | down(&data->update_lock); | ||
408 | if ((data->conf1 & ADM1031_CONF1_AUTO_MODE) && | ||
409 | (((val>>4) & 0xf) != 5)) { | ||
410 | /* In automatic mode, the only PWM accepted is 33% */ | ||
411 | up(&data->update_lock); | ||
412 | return -EINVAL; | ||
413 | } | ||
414 | data->pwm[nr] = PWM_TO_REG(val); | ||
415 | reg = adm1031_read_value(client, ADM1031_REG_PWM); | ||
416 | adm1031_write_value(client, ADM1031_REG_PWM, | ||
417 | nr ? ((data->pwm[nr] << 4) & 0xf0) | (reg & 0xf) | ||
418 | : (data->pwm[nr] & 0xf) | (reg & 0xf0)); | ||
419 | up(&data->update_lock); | ||
420 | return count; | ||
421 | } | ||
422 | |||
423 | #define pwm_reg(offset) \ | ||
424 | static ssize_t show_pwm_##offset (struct device *dev, char *buf) \ | ||
425 | { \ | ||
426 | return show_pwm(dev, buf, offset - 1); \ | ||
427 | } \ | ||
428 | static ssize_t set_pwm_##offset (struct device *dev, \ | ||
429 | const char *buf, size_t count) \ | ||
430 | { \ | ||
431 | return set_pwm(dev, buf, count, offset - 1); \ | ||
432 | } \ | ||
433 | static DEVICE_ATTR(pwm##offset, S_IRUGO | S_IWUSR, \ | ||
434 | show_pwm_##offset, set_pwm_##offset) | ||
435 | |||
436 | pwm_reg(1); | ||
437 | pwm_reg(2); | ||
438 | |||
439 | /* Fans */ | ||
440 | |||
441 | /* | ||
442 | * That function checks the cases where the fan reading is not | ||
443 | * relevent. It is used to provide 0 as fan reading when the fan is | ||
444 | * not supposed to run | ||
445 | */ | ||
446 | static int trust_fan_readings(struct adm1031_data *data, int chan) | ||
447 | { | ||
448 | int res = 0; | ||
449 | |||
450 | if (data->conf1 & ADM1031_CONF1_AUTO_MODE) { | ||
451 | switch (data->conf1 & 0x60) { | ||
452 | case 0x00: /* remote temp1 controls fan1 remote temp2 controls fan2 */ | ||
453 | res = data->temp[chan+1] >= | ||
454 | AUTO_TEMP_MIN_FROM_REG_DEG(data->auto_temp[chan+1]); | ||
455 | break; | ||
456 | case 0x20: /* remote temp1 controls both fans */ | ||
457 | res = | ||
458 | data->temp[1] >= | ||
459 | AUTO_TEMP_MIN_FROM_REG_DEG(data->auto_temp[1]); | ||
460 | break; | ||
461 | case 0x40: /* remote temp2 controls both fans */ | ||
462 | res = | ||
463 | data->temp[2] >= | ||
464 | AUTO_TEMP_MIN_FROM_REG_DEG(data->auto_temp[2]); | ||
465 | break; | ||
466 | case 0x60: /* max controls both fans */ | ||
467 | res = | ||
468 | data->temp[0] >= | ||
469 | AUTO_TEMP_MIN_FROM_REG_DEG(data->auto_temp[0]) | ||
470 | || data->temp[1] >= | ||
471 | AUTO_TEMP_MIN_FROM_REG_DEG(data->auto_temp[1]) | ||
472 | || (data->chip_type == adm1031 | ||
473 | && data->temp[2] >= | ||
474 | AUTO_TEMP_MIN_FROM_REG_DEG(data->auto_temp[2])); | ||
475 | break; | ||
476 | } | ||
477 | } else { | ||
478 | res = data->pwm[chan] > 0; | ||
479 | } | ||
480 | return res; | ||
481 | } | ||
482 | |||
483 | |||
484 | static ssize_t show_fan(struct device *dev, char *buf, int nr) | ||
485 | { | ||
486 | struct adm1031_data *data = adm1031_update_device(dev); | ||
487 | int value; | ||
488 | |||
489 | value = trust_fan_readings(data, nr) ? FAN_FROM_REG(data->fan[nr], | ||
490 | FAN_DIV_FROM_REG(data->fan_div[nr])) : 0; | ||
491 | return sprintf(buf, "%d\n", value); | ||
492 | } | ||
493 | |||
494 | static ssize_t show_fan_div(struct device *dev, char *buf, int nr) | ||
495 | { | ||
496 | struct adm1031_data *data = adm1031_update_device(dev); | ||
497 | return sprintf(buf, "%d\n", FAN_DIV_FROM_REG(data->fan_div[nr])); | ||
498 | } | ||
499 | static ssize_t show_fan_min(struct device *dev, char *buf, int nr) | ||
500 | { | ||
501 | struct adm1031_data *data = adm1031_update_device(dev); | ||
502 | return sprintf(buf, "%d\n", | ||
503 | FAN_FROM_REG(data->fan_min[nr], | ||
504 | FAN_DIV_FROM_REG(data->fan_div[nr]))); | ||
505 | } | ||
506 | static ssize_t | ||
507 | set_fan_min(struct device *dev, const char *buf, size_t count, int nr) | ||
508 | { | ||
509 | struct i2c_client *client = to_i2c_client(dev); | ||
510 | struct adm1031_data *data = i2c_get_clientdata(client); | ||
511 | int val = simple_strtol(buf, NULL, 10); | ||
512 | |||
513 | down(&data->update_lock); | ||
514 | if (val) { | ||
515 | data->fan_min[nr] = | ||
516 | FAN_TO_REG(val, FAN_DIV_FROM_REG(data->fan_div[nr])); | ||
517 | } else { | ||
518 | data->fan_min[nr] = 0xff; | ||
519 | } | ||
520 | adm1031_write_value(client, ADM1031_REG_FAN_MIN(nr), data->fan_min[nr]); | ||
521 | up(&data->update_lock); | ||
522 | return count; | ||
523 | } | ||
524 | static ssize_t | ||
525 | set_fan_div(struct device *dev, const char *buf, size_t count, int nr) | ||
526 | { | ||
527 | struct i2c_client *client = to_i2c_client(dev); | ||
528 | struct adm1031_data *data = i2c_get_clientdata(client); | ||
529 | int val = simple_strtol(buf, NULL, 10); | ||
530 | u8 tmp; | ||
531 | int old_div; | ||
532 | int new_min; | ||
533 | |||
534 | tmp = val == 8 ? 0xc0 : | ||
535 | val == 4 ? 0x80 : | ||
536 | val == 2 ? 0x40 : | ||
537 | val == 1 ? 0x00 : | ||
538 | 0xff; | ||
539 | if (tmp == 0xff) | ||
540 | return -EINVAL; | ||
541 | |||
542 | down(&data->update_lock); | ||
543 | old_div = FAN_DIV_FROM_REG(data->fan_div[nr]); | ||
544 | data->fan_div[nr] = (tmp & 0xC0) | (0x3f & data->fan_div[nr]); | ||
545 | new_min = data->fan_min[nr] * old_div / | ||
546 | FAN_DIV_FROM_REG(data->fan_div[nr]); | ||
547 | data->fan_min[nr] = new_min > 0xff ? 0xff : new_min; | ||
548 | data->fan[nr] = data->fan[nr] * old_div / | ||
549 | FAN_DIV_FROM_REG(data->fan_div[nr]); | ||
550 | |||
551 | adm1031_write_value(client, ADM1031_REG_FAN_DIV(nr), | ||
552 | data->fan_div[nr]); | ||
553 | adm1031_write_value(client, ADM1031_REG_FAN_MIN(nr), | ||
554 | data->fan_min[nr]); | ||
555 | up(&data->update_lock); | ||
556 | return count; | ||
557 | } | ||
558 | |||
559 | #define fan_offset(offset) \ | ||
560 | static ssize_t show_fan_##offset (struct device *dev, char *buf) \ | ||
561 | { \ | ||
562 | return show_fan(dev, buf, offset - 1); \ | ||
563 | } \ | ||
564 | static ssize_t show_fan_##offset##_min (struct device *dev, char *buf) \ | ||
565 | { \ | ||
566 | return show_fan_min(dev, buf, offset - 1); \ | ||
567 | } \ | ||
568 | static ssize_t show_fan_##offset##_div (struct device *dev, char *buf) \ | ||
569 | { \ | ||
570 | return show_fan_div(dev, buf, offset - 1); \ | ||
571 | } \ | ||
572 | static ssize_t set_fan_##offset##_min (struct device *dev, \ | ||
573 | const char *buf, size_t count) \ | ||
574 | { \ | ||
575 | return set_fan_min(dev, buf, count, offset - 1); \ | ||
576 | } \ | ||
577 | static ssize_t set_fan_##offset##_div (struct device *dev, \ | ||
578 | const char *buf, size_t count) \ | ||
579 | { \ | ||
580 | return set_fan_div(dev, buf, count, offset - 1); \ | ||
581 | } \ | ||
582 | static DEVICE_ATTR(fan##offset##_input, S_IRUGO, show_fan_##offset, \ | ||
583 | NULL); \ | ||
584 | static DEVICE_ATTR(fan##offset##_min, S_IRUGO | S_IWUSR, \ | ||
585 | show_fan_##offset##_min, set_fan_##offset##_min); \ | ||
586 | static DEVICE_ATTR(fan##offset##_div, S_IRUGO | S_IWUSR, \ | ||
587 | show_fan_##offset##_div, set_fan_##offset##_div); \ | ||
588 | static DEVICE_ATTR(auto_fan##offset##_min_pwm, S_IRUGO | S_IWUSR, \ | ||
589 | show_pwm_##offset, set_pwm_##offset) | ||
590 | |||
591 | fan_offset(1); | ||
592 | fan_offset(2); | ||
593 | |||
594 | |||
595 | /* Temps */ | ||
596 | static ssize_t show_temp(struct device *dev, char *buf, int nr) | ||
597 | { | ||
598 | struct adm1031_data *data = adm1031_update_device(dev); | ||
599 | int ext; | ||
600 | ext = nr == 0 ? | ||
601 | ((data->ext_temp[nr] >> 6) & 0x3) * 2 : | ||
602 | (((data->ext_temp[nr] >> ((nr - 1) * 3)) & 7)); | ||
603 | return sprintf(buf, "%d\n", TEMP_FROM_REG_EXT(data->temp[nr], ext)); | ||
604 | } | ||
605 | static ssize_t show_temp_min(struct device *dev, char *buf, int nr) | ||
606 | { | ||
607 | struct adm1031_data *data = adm1031_update_device(dev); | ||
608 | return sprintf(buf, "%d\n", TEMP_FROM_REG(data->temp_min[nr])); | ||
609 | } | ||
610 | static ssize_t show_temp_max(struct device *dev, char *buf, int nr) | ||
611 | { | ||
612 | struct adm1031_data *data = adm1031_update_device(dev); | ||
613 | return sprintf(buf, "%d\n", TEMP_FROM_REG(data->temp_max[nr])); | ||
614 | } | ||
615 | static ssize_t show_temp_crit(struct device *dev, char *buf, int nr) | ||
616 | { | ||
617 | struct adm1031_data *data = adm1031_update_device(dev); | ||
618 | return sprintf(buf, "%d\n", TEMP_FROM_REG(data->temp_crit[nr])); | ||
619 | } | ||
620 | static ssize_t | ||
621 | set_temp_min(struct device *dev, const char *buf, size_t count, int nr) | ||
622 | { | ||
623 | struct i2c_client *client = to_i2c_client(dev); | ||
624 | struct adm1031_data *data = i2c_get_clientdata(client); | ||
625 | int val; | ||
626 | |||
627 | val = simple_strtol(buf, NULL, 10); | ||
628 | val = SENSORS_LIMIT(val, -55000, nr == 0 ? 127750 : 127875); | ||
629 | down(&data->update_lock); | ||
630 | data->temp_min[nr] = TEMP_TO_REG(val); | ||
631 | adm1031_write_value(client, ADM1031_REG_TEMP_MIN(nr), | ||
632 | data->temp_min[nr]); | ||
633 | up(&data->update_lock); | ||
634 | return count; | ||
635 | } | ||
636 | static ssize_t | ||
637 | set_temp_max(struct device *dev, const char *buf, size_t count, int nr) | ||
638 | { | ||
639 | struct i2c_client *client = to_i2c_client(dev); | ||
640 | struct adm1031_data *data = i2c_get_clientdata(client); | ||
641 | int val; | ||
642 | |||
643 | val = simple_strtol(buf, NULL, 10); | ||
644 | val = SENSORS_LIMIT(val, -55000, nr == 0 ? 127750 : 127875); | ||
645 | down(&data->update_lock); | ||
646 | data->temp_max[nr] = TEMP_TO_REG(val); | ||
647 | adm1031_write_value(client, ADM1031_REG_TEMP_MAX(nr), | ||
648 | data->temp_max[nr]); | ||
649 | up(&data->update_lock); | ||
650 | return count; | ||
651 | } | ||
652 | static ssize_t | ||
653 | set_temp_crit(struct device *dev, const char *buf, size_t count, int nr) | ||
654 | { | ||
655 | struct i2c_client *client = to_i2c_client(dev); | ||
656 | struct adm1031_data *data = i2c_get_clientdata(client); | ||
657 | int val; | ||
658 | |||
659 | val = simple_strtol(buf, NULL, 10); | ||
660 | val = SENSORS_LIMIT(val, -55000, nr == 0 ? 127750 : 127875); | ||
661 | down(&data->update_lock); | ||
662 | data->temp_crit[nr] = TEMP_TO_REG(val); | ||
663 | adm1031_write_value(client, ADM1031_REG_TEMP_CRIT(nr), | ||
664 | data->temp_crit[nr]); | ||
665 | up(&data->update_lock); | ||
666 | return count; | ||
667 | } | ||
668 | |||
669 | #define temp_reg(offset) \ | ||
670 | static ssize_t show_temp_##offset (struct device *dev, char *buf) \ | ||
671 | { \ | ||
672 | return show_temp(dev, buf, offset - 1); \ | ||
673 | } \ | ||
674 | static ssize_t show_temp_##offset##_min (struct device *dev, char *buf) \ | ||
675 | { \ | ||
676 | return show_temp_min(dev, buf, offset - 1); \ | ||
677 | } \ | ||
678 | static ssize_t show_temp_##offset##_max (struct device *dev, char *buf) \ | ||
679 | { \ | ||
680 | return show_temp_max(dev, buf, offset - 1); \ | ||
681 | } \ | ||
682 | static ssize_t show_temp_##offset##_crit (struct device *dev, char *buf) \ | ||
683 | { \ | ||
684 | return show_temp_crit(dev, buf, offset - 1); \ | ||
685 | } \ | ||
686 | static ssize_t set_temp_##offset##_min (struct device *dev, \ | ||
687 | const char *buf, size_t count) \ | ||
688 | { \ | ||
689 | return set_temp_min(dev, buf, count, offset - 1); \ | ||
690 | } \ | ||
691 | static ssize_t set_temp_##offset##_max (struct device *dev, \ | ||
692 | const char *buf, size_t count) \ | ||
693 | { \ | ||
694 | return set_temp_max(dev, buf, count, offset - 1); \ | ||
695 | } \ | ||
696 | static ssize_t set_temp_##offset##_crit (struct device *dev, \ | ||
697 | const char *buf, size_t count) \ | ||
698 | { \ | ||
699 | return set_temp_crit(dev, buf, count, offset - 1); \ | ||
700 | } \ | ||
701 | static DEVICE_ATTR(temp##offset##_input, S_IRUGO, show_temp_##offset, \ | ||
702 | NULL); \ | ||
703 | static DEVICE_ATTR(temp##offset##_min, S_IRUGO | S_IWUSR, \ | ||
704 | show_temp_##offset##_min, set_temp_##offset##_min); \ | ||
705 | static DEVICE_ATTR(temp##offset##_max, S_IRUGO | S_IWUSR, \ | ||
706 | show_temp_##offset##_max, set_temp_##offset##_max); \ | ||
707 | static DEVICE_ATTR(temp##offset##_crit, S_IRUGO | S_IWUSR, \ | ||
708 | show_temp_##offset##_crit, set_temp_##offset##_crit) | ||
709 | |||
710 | temp_reg(1); | ||
711 | temp_reg(2); | ||
712 | temp_reg(3); | ||
713 | |||
714 | /* Alarms */ | ||
715 | static ssize_t show_alarms(struct device *dev, char *buf) | ||
716 | { | ||
717 | struct adm1031_data *data = adm1031_update_device(dev); | ||
718 | return sprintf(buf, "%d\n", data->alarm); | ||
719 | } | ||
720 | |||
721 | static DEVICE_ATTR(alarms, S_IRUGO, show_alarms, NULL); | ||
722 | |||
723 | |||
724 | static int adm1031_attach_adapter(struct i2c_adapter *adapter) | ||
725 | { | ||
726 | if (!(adapter->class & I2C_CLASS_HWMON)) | ||
727 | return 0; | ||
728 | return i2c_detect(adapter, &addr_data, adm1031_detect); | ||
729 | } | ||
730 | |||
731 | /* This function is called by i2c_detect */ | ||
732 | static int adm1031_detect(struct i2c_adapter *adapter, int address, int kind) | ||
733 | { | ||
734 | struct i2c_client *new_client; | ||
735 | struct adm1031_data *data; | ||
736 | int err = 0; | ||
737 | const char *name = ""; | ||
738 | |||
739 | if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA)) | ||
740 | goto exit; | ||
741 | |||
742 | if (!(data = kmalloc(sizeof(struct adm1031_data), GFP_KERNEL))) { | ||
743 | err = -ENOMEM; | ||
744 | goto exit; | ||
745 | } | ||
746 | memset(data, 0, sizeof(struct adm1031_data)); | ||
747 | |||
748 | new_client = &data->client; | ||
749 | i2c_set_clientdata(new_client, data); | ||
750 | new_client->addr = address; | ||
751 | new_client->adapter = adapter; | ||
752 | new_client->driver = &adm1031_driver; | ||
753 | new_client->flags = 0; | ||
754 | |||
755 | if (kind < 0) { | ||
756 | int id, co; | ||
757 | id = i2c_smbus_read_byte_data(new_client, 0x3d); | ||
758 | co = i2c_smbus_read_byte_data(new_client, 0x3e); | ||
759 | |||
760 | if (!((id == 0x31 || id == 0x30) && co == 0x41)) | ||
761 | goto exit_free; | ||
762 | kind = (id == 0x30) ? adm1030 : adm1031; | ||
763 | } | ||
764 | |||
765 | if (kind <= 0) | ||
766 | kind = adm1031; | ||
767 | |||
768 | /* Given the detected chip type, set the chip name and the | ||
769 | * auto fan control helper table. */ | ||
770 | if (kind == adm1030) { | ||
771 | name = "adm1030"; | ||
772 | data->chan_select_table = &auto_channel_select_table_adm1030; | ||
773 | } else if (kind == adm1031) { | ||
774 | name = "adm1031"; | ||
775 | data->chan_select_table = &auto_channel_select_table_adm1031; | ||
776 | } | ||
777 | data->chip_type = kind; | ||
778 | |||
779 | strlcpy(new_client->name, name, I2C_NAME_SIZE); | ||
780 | data->valid = 0; | ||
781 | init_MUTEX(&data->update_lock); | ||
782 | |||
783 | /* Tell the I2C layer a new client has arrived */ | ||
784 | if ((err = i2c_attach_client(new_client))) | ||
785 | goto exit_free; | ||
786 | |||
787 | /* Initialize the ADM1031 chip */ | ||
788 | adm1031_init_client(new_client); | ||
789 | |||
790 | /* Register sysfs hooks */ | ||
791 | device_create_file(&new_client->dev, &dev_attr_fan1_input); | ||
792 | device_create_file(&new_client->dev, &dev_attr_fan1_div); | ||
793 | device_create_file(&new_client->dev, &dev_attr_fan1_min); | ||
794 | device_create_file(&new_client->dev, &dev_attr_pwm1); | ||
795 | device_create_file(&new_client->dev, &dev_attr_auto_fan1_channel); | ||
796 | device_create_file(&new_client->dev, &dev_attr_temp1_input); | ||
797 | device_create_file(&new_client->dev, &dev_attr_temp1_min); | ||
798 | device_create_file(&new_client->dev, &dev_attr_temp1_max); | ||
799 | device_create_file(&new_client->dev, &dev_attr_temp1_crit); | ||
800 | device_create_file(&new_client->dev, &dev_attr_temp2_input); | ||
801 | device_create_file(&new_client->dev, &dev_attr_temp2_min); | ||
802 | device_create_file(&new_client->dev, &dev_attr_temp2_max); | ||
803 | device_create_file(&new_client->dev, &dev_attr_temp2_crit); | ||
804 | |||
805 | device_create_file(&new_client->dev, &dev_attr_auto_temp1_off); | ||
806 | device_create_file(&new_client->dev, &dev_attr_auto_temp1_min); | ||
807 | device_create_file(&new_client->dev, &dev_attr_auto_temp1_max); | ||
808 | |||
809 | device_create_file(&new_client->dev, &dev_attr_auto_temp2_off); | ||
810 | device_create_file(&new_client->dev, &dev_attr_auto_temp2_min); | ||
811 | device_create_file(&new_client->dev, &dev_attr_auto_temp2_max); | ||
812 | |||
813 | device_create_file(&new_client->dev, &dev_attr_auto_fan1_min_pwm); | ||
814 | |||
815 | device_create_file(&new_client->dev, &dev_attr_alarms); | ||
816 | |||
817 | if (kind == adm1031) { | ||
818 | device_create_file(&new_client->dev, &dev_attr_fan2_input); | ||
819 | device_create_file(&new_client->dev, &dev_attr_fan2_div); | ||
820 | device_create_file(&new_client->dev, &dev_attr_fan2_min); | ||
821 | device_create_file(&new_client->dev, &dev_attr_pwm2); | ||
822 | device_create_file(&new_client->dev, | ||
823 | &dev_attr_auto_fan2_channel); | ||
824 | device_create_file(&new_client->dev, &dev_attr_temp3_input); | ||
825 | device_create_file(&new_client->dev, &dev_attr_temp3_min); | ||
826 | device_create_file(&new_client->dev, &dev_attr_temp3_max); | ||
827 | device_create_file(&new_client->dev, &dev_attr_temp3_crit); | ||
828 | device_create_file(&new_client->dev, &dev_attr_auto_temp3_off); | ||
829 | device_create_file(&new_client->dev, &dev_attr_auto_temp3_min); | ||
830 | device_create_file(&new_client->dev, &dev_attr_auto_temp3_max); | ||
831 | device_create_file(&new_client->dev, &dev_attr_auto_fan2_min_pwm); | ||
832 | } | ||
833 | |||
834 | return 0; | ||
835 | |||
836 | exit_free: | ||
837 | kfree(new_client); | ||
838 | exit: | ||
839 | return err; | ||
840 | } | ||
841 | |||
842 | static int adm1031_detach_client(struct i2c_client *client) | ||
843 | { | ||
844 | int ret; | ||
845 | if ((ret = i2c_detach_client(client)) != 0) { | ||
846 | return ret; | ||
847 | } | ||
848 | kfree(client); | ||
849 | return 0; | ||
850 | } | ||
851 | |||
852 | static void adm1031_init_client(struct i2c_client *client) | ||
853 | { | ||
854 | unsigned int read_val; | ||
855 | unsigned int mask; | ||
856 | struct adm1031_data *data = i2c_get_clientdata(client); | ||
857 | |||
858 | mask = (ADM1031_CONF2_PWM1_ENABLE | ADM1031_CONF2_TACH1_ENABLE); | ||
859 | if (data->chip_type == adm1031) { | ||
860 | mask |= (ADM1031_CONF2_PWM2_ENABLE | | ||
861 | ADM1031_CONF2_TACH2_ENABLE); | ||
862 | } | ||
863 | /* Initialize the ADM1031 chip (enables fan speed reading ) */ | ||
864 | read_val = adm1031_read_value(client, ADM1031_REG_CONF2); | ||
865 | if ((read_val | mask) != read_val) { | ||
866 | adm1031_write_value(client, ADM1031_REG_CONF2, read_val | mask); | ||
867 | } | ||
868 | |||
869 | read_val = adm1031_read_value(client, ADM1031_REG_CONF1); | ||
870 | if ((read_val | ADM1031_CONF1_MONITOR_ENABLE) != read_val) { | ||
871 | adm1031_write_value(client, ADM1031_REG_CONF1, read_val | | ||
872 | ADM1031_CONF1_MONITOR_ENABLE); | ||
873 | } | ||
874 | |||
875 | } | ||
876 | |||
877 | static struct adm1031_data *adm1031_update_device(struct device *dev) | ||
878 | { | ||
879 | struct i2c_client *client = to_i2c_client(dev); | ||
880 | struct adm1031_data *data = i2c_get_clientdata(client); | ||
881 | int chan; | ||
882 | |||
883 | down(&data->update_lock); | ||
884 | |||
885 | if (time_after(jiffies, data->last_updated + HZ + HZ / 2) | ||
886 | || !data->valid) { | ||
887 | |||
888 | dev_dbg(&client->dev, "Starting adm1031 update\n"); | ||
889 | for (chan = 0; | ||
890 | chan < ((data->chip_type == adm1031) ? 3 : 2); chan++) { | ||
891 | u8 oldh, newh; | ||
892 | |||
893 | oldh = | ||
894 | adm1031_read_value(client, ADM1031_REG_TEMP(chan)); | ||
895 | data->ext_temp[chan] = | ||
896 | adm1031_read_value(client, ADM1031_REG_EXT_TEMP); | ||
897 | newh = | ||
898 | adm1031_read_value(client, ADM1031_REG_TEMP(chan)); | ||
899 | if (newh != oldh) { | ||
900 | data->ext_temp[chan] = | ||
901 | adm1031_read_value(client, | ||
902 | ADM1031_REG_EXT_TEMP); | ||
903 | #ifdef DEBUG | ||
904 | oldh = | ||
905 | adm1031_read_value(client, | ||
906 | ADM1031_REG_TEMP(chan)); | ||
907 | |||
908 | /* oldh is actually newer */ | ||
909 | if (newh != oldh) | ||
910 | dev_warn(&client->dev, | ||
911 | "Remote temperature may be " | ||
912 | "wrong.\n"); | ||
913 | #endif | ||
914 | } | ||
915 | data->temp[chan] = newh; | ||
916 | |||
917 | data->temp_min[chan] = | ||
918 | adm1031_read_value(client, | ||
919 | ADM1031_REG_TEMP_MIN(chan)); | ||
920 | data->temp_max[chan] = | ||
921 | adm1031_read_value(client, | ||
922 | ADM1031_REG_TEMP_MAX(chan)); | ||
923 | data->temp_crit[chan] = | ||
924 | adm1031_read_value(client, | ||
925 | ADM1031_REG_TEMP_CRIT(chan)); | ||
926 | data->auto_temp[chan] = | ||
927 | adm1031_read_value(client, | ||
928 | ADM1031_REG_AUTO_TEMP(chan)); | ||
929 | |||
930 | } | ||
931 | |||
932 | data->conf1 = adm1031_read_value(client, ADM1031_REG_CONF1); | ||
933 | data->conf2 = adm1031_read_value(client, ADM1031_REG_CONF2); | ||
934 | |||
935 | data->alarm = adm1031_read_value(client, ADM1031_REG_STATUS(0)) | ||
936 | | (adm1031_read_value(client, ADM1031_REG_STATUS(1)) | ||
937 | << 8); | ||
938 | if (data->chip_type == adm1030) { | ||
939 | data->alarm &= 0xc0ff; | ||
940 | } | ||
941 | |||
942 | for (chan=0; chan<(data->chip_type == adm1030 ? 1 : 2); chan++) { | ||
943 | data->fan_div[chan] = | ||
944 | adm1031_read_value(client, ADM1031_REG_FAN_DIV(chan)); | ||
945 | data->fan_min[chan] = | ||
946 | adm1031_read_value(client, ADM1031_REG_FAN_MIN(chan)); | ||
947 | data->fan[chan] = | ||
948 | adm1031_read_value(client, ADM1031_REG_FAN_SPEED(chan)); | ||
949 | data->pwm[chan] = | ||
950 | 0xf & (adm1031_read_value(client, ADM1031_REG_PWM) >> | ||
951 | (4*chan)); | ||
952 | } | ||
953 | data->last_updated = jiffies; | ||
954 | data->valid = 1; | ||
955 | } | ||
956 | |||
957 | up(&data->update_lock); | ||
958 | |||
959 | return data; | ||
960 | } | ||
961 | |||
962 | static int __init sensors_adm1031_init(void) | ||
963 | { | ||
964 | return i2c_add_driver(&adm1031_driver); | ||
965 | } | ||
966 | |||
967 | static void __exit sensors_adm1031_exit(void) | ||
968 | { | ||
969 | i2c_del_driver(&adm1031_driver); | ||
970 | } | ||
971 | |||
972 | MODULE_AUTHOR("Alexandre d'Alton <alex@alexdalton.org>"); | ||
973 | MODULE_DESCRIPTION("ADM1031/ADM1030 driver"); | ||
974 | MODULE_LICENSE("GPL"); | ||
975 | |||
976 | module_init(sensors_adm1031_init); | ||
977 | module_exit(sensors_adm1031_exit); | ||