aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/i2c
diff options
context:
space:
mode:
authorGrant Coady <grant_lkml@dodo.com.au>2005-04-30 07:41:29 -0400
committerGreg Kroah-Hartman <gregkh@suse.de>2005-06-22 00:51:53 -0400
commit40b5cda28aafe3744d8808c21f7959e472a9ecb1 (patch)
treecd332f677f3c7855fcd026300cf284af08d0846b /drivers/i2c
parenta551ef79d9413727f76d22dc47b5b15d1d03073b (diff)
[PATCH] I2C: add new hardware monitor driver: adm9240
Completion of Michiel Rook's port of adm9240 to 2.6 with addition of auto fan clock divider based on Jean Delvare's algorithm, and replaces scaling macros with static inlines. Signed-off-by: Grant Coady <gcoady@gmail.com> Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
Diffstat (limited to 'drivers/i2c')
-rw-r--r--drivers/i2c/chips/Kconfig11
-rw-r--r--drivers/i2c/chips/Makefile1
-rw-r--r--drivers/i2c/chips/adm9240.c768
3 files changed, 780 insertions, 0 deletions
diff --git a/drivers/i2c/chips/Kconfig b/drivers/i2c/chips/Kconfig
index 67be4c988ca6..3c8863f26c7e 100644
--- a/drivers/i2c/chips/Kconfig
+++ b/drivers/i2c/chips/Kconfig
@@ -51,6 +51,17 @@ config SENSORS_ADM1031
51 This driver can also be built as a module. If so, the module 51 This driver can also be built as a module. If so, the module
52 will be called adm1031. 52 will be called adm1031.
53 53
54config SENSORS_ADM9240
55 tristate "Analog Devices ADM9240 and compatibles"
56 depends on I2C && EXPERIMENTAL
57 select I2C_SENSOR
58 help
59 If you say yes here you get support for Analog Devices ADM9240,
60 Dallas DS1780, National Semiconductor LM81 sensor chips.
61
62 This driver can also be built as a module. If so, the module
63 will be called adm9240.
64
54config SENSORS_ASB100 65config SENSORS_ASB100
55 tristate "Asus ASB100 Bach" 66 tristate "Asus ASB100 Bach"
56 depends on I2C && EXPERIMENTAL 67 depends on I2C && EXPERIMENTAL
diff --git a/drivers/i2c/chips/Makefile b/drivers/i2c/chips/Makefile
index 6fadd78f9cf6..247fc982a6d2 100644
--- a/drivers/i2c/chips/Makefile
+++ b/drivers/i2c/chips/Makefile
@@ -11,6 +11,7 @@ obj-$(CONFIG_SENSORS_ADM1021) += adm1021.o
11obj-$(CONFIG_SENSORS_ADM1025) += adm1025.o 11obj-$(CONFIG_SENSORS_ADM1025) += adm1025.o
12obj-$(CONFIG_SENSORS_ADM1026) += adm1026.o 12obj-$(CONFIG_SENSORS_ADM1026) += adm1026.o
13obj-$(CONFIG_SENSORS_ADM1031) += adm1031.o 13obj-$(CONFIG_SENSORS_ADM1031) += adm1031.o
14obj-$(CONFIG_SENSORS_ADM9240) += adm9240.o
14obj-$(CONFIG_SENSORS_ATXP1) += atxp1.o 15obj-$(CONFIG_SENSORS_ATXP1) += atxp1.o
15obj-$(CONFIG_SENSORS_DS1337) += ds1337.o 16obj-$(CONFIG_SENSORS_DS1337) += ds1337.o
16obj-$(CONFIG_SENSORS_DS1621) += ds1621.o 17obj-$(CONFIG_SENSORS_DS1621) += ds1621.o
diff --git a/drivers/i2c/chips/adm9240.c b/drivers/i2c/chips/adm9240.c
new file mode 100644
index 000000000000..0b67eab15d2d
--- /dev/null
+++ b/drivers/i2c/chips/adm9240.c
@@ -0,0 +1,768 @@
1/*
2 * adm9240.c Part of lm_sensors, Linux kernel modules for hardware
3 * monitoring
4 *
5 * Copyright (C) 1999 Frodo Looijaard <frodol@dds.nl>
6 * Philip Edelbrock <phil@netroedge.com>
7 * Copyright (C) 2003 Michiel Rook <michiel@grendelproject.nl>
8 * Copyright (C) 2005 Grant Coady <gcoady@gmail.com> with valuable
9 * guidance from Jean Delvare
10 *
11 * Driver supports Analog Devices ADM9240
12 * Dallas Semiconductor DS1780
13 * National Semiconductor LM81
14 *
15 * ADM9240 is the reference, DS1780 and LM81 are register compatibles
16 *
17 * Voltage Six inputs are scaled by chip, VID also reported
18 * Temperature Chip temperature to 0.5'C, maximum and max_hysteris
19 * Fans 2 fans, low speed alarm, automatic fan clock divider
20 * Alarms 16-bit map of active alarms
21 * Analog Out 0..1250 mV output
22 *
23 * Chassis Intrusion: clear CI latch with 'echo 1 > chassis_clear'
24 *
25 * Test hardware: Intel SE440BX-2 desktop motherboard --Grant
26 *
27 * LM81 extended temp reading not implemented
28 *
29 * This program is free software; you can redistribute it and/or modify
30 * it under the terms of the GNU General Public License as published by
31 * the Free Software Foundation; either version 2 of the License, or
32 * (at your option) any later version.
33 *
34 * This program is distributed in the hope that it will be useful,
35 * but WITHOUT ANY WARRANTY; without even the implied warranty of
36 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
37 * GNU General Public License for more details.
38 *
39 * You should have received a copy of the GNU General Public License
40 * along with this program; if not, write to the Free Software
41 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
42 */
43
44#include <linux/init.h>
45#include <linux/module.h>
46#include <linux/slab.h>
47#include <linux/i2c.h>
48#include <linux/i2c-sensor.h>
49#include <linux/i2c-vid.h>
50
51/* Addresses to scan */
52static unsigned short normal_i2c[] = { 0x2c, 0x2d, 0x2e, 0x2f,
53 I2C_CLIENT_END };
54
55static unsigned int normal_isa[] = { I2C_CLIENT_ISA_END };
56
57/* Insmod parameters */
58SENSORS_INSMOD_3(adm9240, ds1780, lm81);
59
60/* ADM9240 registers */
61#define ADM9240_REG_MAN_ID 0x3e
62#define ADM9240_REG_DIE_REV 0x3f
63#define ADM9240_REG_CONFIG 0x40
64
65#define ADM9240_REG_IN(nr) (0x20 + (nr)) /* 0..5 */
66#define ADM9240_REG_IN_MAX(nr) (0x2b + (nr) * 2)
67#define ADM9240_REG_IN_MIN(nr) (0x2c + (nr) * 2)
68#define ADM9240_REG_FAN(nr) (0x28 + (nr)) /* 0..1 */
69#define ADM9240_REG_FAN_MIN(nr) (0x3b + (nr))
70#define ADM9240_REG_INT(nr) (0x41 + (nr))
71#define ADM9240_REG_INT_MASK(nr) (0x43 + (nr))
72#define ADM9240_REG_TEMP 0x27
73#define ADM9240_REG_TEMP_HIGH 0x39
74#define ADM9240_REG_TEMP_HYST 0x3a
75#define ADM9240_REG_ANALOG_OUT 0x19
76#define ADM9240_REG_CHASSIS_CLEAR 0x46
77#define ADM9240_REG_VID_FAN_DIV 0x47
78#define ADM9240_REG_I2C_ADDR 0x48
79#define ADM9240_REG_VID4 0x49
80#define ADM9240_REG_TEMP_CONF 0x4b
81
82/* generalised scaling with integer rounding */
83static inline int SCALE(long val, int mul, int div)
84{
85 if (val < 0)
86 return (val * mul - div / 2) / div;
87 else
88 return (val * mul + div / 2) / div;
89}
90
91/* adm9240 internally scales voltage measurements */
92static const u16 nom_mv[] = { 2500, 2700, 3300, 5000, 12000, 2700 };
93
94static inline unsigned int IN_FROM_REG(u8 reg, int n)
95{
96 return SCALE(reg, nom_mv[n], 192);
97}
98
99static inline u8 IN_TO_REG(unsigned long val, int n)
100{
101 return SENSORS_LIMIT(SCALE(val, 192, nom_mv[n]), 0, 255);
102}
103
104/* temperature range: -40..125, 127 disables temperature alarm */
105static inline s8 TEMP_TO_REG(long val)
106{
107 return SENSORS_LIMIT(SCALE(val, 1, 1000), -40, 127);
108}
109
110/* two fans, each with low fan speed limit */
111static inline unsigned int FAN_FROM_REG(u8 reg, u8 div)
112{
113 if (!reg) /* error */
114 return -1;
115
116 if (reg == 255)
117 return 0;
118
119 return SCALE(1350000, 1, reg * div);
120}
121
122/* analog out 0..1250mV */
123static inline u8 AOUT_TO_REG(unsigned long val)
124{
125 return SENSORS_LIMIT(SCALE(val, 255, 1250), 0, 255);
126}
127
128static inline unsigned int AOUT_FROM_REG(u8 reg)
129{
130 return SCALE(reg, 1250, 255);
131}
132
133static int adm9240_attach_adapter(struct i2c_adapter *adapter);
134static int adm9240_detect(struct i2c_adapter *adapter, int address, int kind);
135static void adm9240_init_client(struct i2c_client *client);
136static int adm9240_detach_client(struct i2c_client *client);
137static struct adm9240_data *adm9240_update_device(struct device *dev);
138
139/* driver data */
140static struct i2c_driver adm9240_driver = {
141 .owner = THIS_MODULE,
142 .name = "adm9240",
143 .id = I2C_DRIVERID_ADM9240,
144 .flags = I2C_DF_NOTIFY,
145 .attach_adapter = adm9240_attach_adapter,
146 .detach_client = adm9240_detach_client,
147};
148
149/* per client data */
150struct adm9240_data {
151 enum chips type;
152 struct i2c_client client;
153 struct semaphore update_lock;
154 char valid;
155 unsigned long last_updated_measure;
156 unsigned long last_updated_config;
157
158 u8 in[6]; /* ro in0_input */
159 u8 in_max[6]; /* rw in0_max */
160 u8 in_min[6]; /* rw in0_min */
161 u8 fan[2]; /* ro fan1_input */
162 u8 fan_min[2]; /* rw fan1_min */
163 u8 fan_div[2]; /* rw fan1_div, read-only accessor */
164 s16 temp; /* ro temp1_input, 9-bit sign-extended */
165 s8 temp_high; /* rw temp1_max */
166 s8 temp_hyst; /* rw temp1_max_hyst */
167 u16 alarms; /* ro alarms */
168 u8 aout; /* rw analog_out */
169 u8 vid; /* ro vid */
170 u8 vrm; /* -- vrm set on startup, no accessor */
171};
172
173/* i2c byte read/write interface */
174static int adm9240_read_value(struct i2c_client *client, u8 reg)
175{
176 return i2c_smbus_read_byte_data(client, reg);
177}
178
179static int adm9240_write_value(struct i2c_client *client, u8 reg, u8 value)
180{
181 return i2c_smbus_write_byte_data(client, reg, value);
182}
183
184/*** sysfs accessors ***/
185
186/* temperature */
187#define show_temp(value, scale) \
188static ssize_t show_##value(struct device *dev, char *buf) \
189{ \
190 struct adm9240_data *data = adm9240_update_device(dev); \
191 return sprintf(buf, "%d\n", data->value * scale); \
192}
193show_temp(temp_high, 1000);
194show_temp(temp_hyst, 1000);
195show_temp(temp, 500);
196
197#define set_temp(value, reg) \
198static ssize_t set_##value(struct device *dev, const char *buf, \
199 size_t count) \
200{ \
201 struct i2c_client *client = to_i2c_client(dev); \
202 struct adm9240_data *data = adm9240_update_device(dev); \
203 long temp = simple_strtoul(buf, NULL, 10); \
204 \
205 down(&data->update_lock); \
206 data->value = TEMP_TO_REG(temp); \
207 adm9240_write_value(client, reg, data->value); \
208 up(&data->update_lock); \
209 return count; \
210}
211
212set_temp(temp_high, ADM9240_REG_TEMP_HIGH);
213set_temp(temp_hyst, ADM9240_REG_TEMP_HYST);
214
215static DEVICE_ATTR(temp1_max, S_IWUSR | S_IRUGO,
216 show_temp_high, set_temp_high);
217static DEVICE_ATTR(temp1_max_hyst, S_IWUSR | S_IRUGO,
218 show_temp_hyst, set_temp_hyst);
219static DEVICE_ATTR(temp1_input, S_IRUGO, show_temp, NULL);
220
221/* voltage */
222static ssize_t show_in(struct device *dev, char *buf, int nr)
223{
224 struct adm9240_data *data = adm9240_update_device(dev);
225 return sprintf(buf, "%d\n", IN_FROM_REG(data->in[nr], nr));
226}
227
228static ssize_t show_in_min(struct device *dev, char *buf, int nr)
229{
230 struct adm9240_data *data = adm9240_update_device(dev);
231 return sprintf(buf, "%d\n", IN_FROM_REG(data->in_min[nr], nr));
232}
233
234static ssize_t show_in_max(struct device *dev, char *buf, int nr)
235{
236 struct adm9240_data *data = adm9240_update_device(dev);
237 return sprintf(buf, "%d\n", IN_FROM_REG(data->in_max[nr], nr));
238}
239
240static ssize_t set_in_min(struct device *dev, const char *buf,
241 size_t count, int nr)
242{
243 struct i2c_client *client = to_i2c_client(dev);
244 struct adm9240_data *data = i2c_get_clientdata(client);
245 unsigned long val = simple_strtoul(buf, NULL, 10);
246
247 down(&data->update_lock);
248 data->in_min[nr] = IN_TO_REG(val, nr);
249 adm9240_write_value(client, ADM9240_REG_IN_MIN(nr), data->in_min[nr]);
250 up(&data->update_lock);
251 return count;
252}
253
254static ssize_t set_in_max(struct device *dev, const char *buf,
255 size_t count, int nr)
256{
257 struct i2c_client *client = to_i2c_client(dev);
258 struct adm9240_data *data = i2c_get_clientdata(client);
259 unsigned long val = simple_strtoul(buf, NULL, 10);
260
261 down(&data->update_lock);
262 data->in_max[nr] = IN_TO_REG(val, nr);
263 adm9240_write_value(client, ADM9240_REG_IN_MAX(nr), data->in_max[nr]);
264 up(&data->update_lock);
265 return count;
266}
267
268#define show_in_offset(offset) \
269static ssize_t show_in##offset(struct device *dev, char *buf) \
270{ \
271 return show_in(dev, buf, offset); \
272} \
273static DEVICE_ATTR(in##offset##_input, S_IRUGO, show_in##offset, NULL); \
274static ssize_t show_in##offset##_min(struct device *dev, char *buf) \
275{ \
276 return show_in_min(dev, buf, offset); \
277} \
278static ssize_t show_in##offset##_max(struct device *dev, char *buf) \
279{ \
280 return show_in_max(dev, buf, offset); \
281} \
282static ssize_t \
283set_in##offset##_min(struct device *dev, const char *buf, size_t count) \
284{ \
285 return set_in_min(dev, buf, count, offset); \
286} \
287static ssize_t \
288set_in##offset##_max(struct device *dev, const char *buf, size_t count) \
289{ \
290 return set_in_max(dev, buf, count, offset); \
291} \
292static DEVICE_ATTR(in##offset##_min, S_IRUGO | S_IWUSR, \
293 show_in##offset##_min, set_in##offset##_min); \
294static DEVICE_ATTR(in##offset##_max, S_IRUGO | S_IWUSR, \
295 show_in##offset##_max, set_in##offset##_max);
296
297show_in_offset(0);
298show_in_offset(1);
299show_in_offset(2);
300show_in_offset(3);
301show_in_offset(4);
302show_in_offset(5);
303
304/* fans */
305static ssize_t show_fan(struct device *dev, char *buf, int nr)
306{
307 struct adm9240_data *data = adm9240_update_device(dev);
308 return sprintf(buf, "%d\n", FAN_FROM_REG(data->fan[nr],
309 1 << data->fan_div[nr]));
310}
311
312static ssize_t show_fan_min(struct device *dev, char *buf, int nr)
313{
314 struct adm9240_data *data = adm9240_update_device(dev);
315 return sprintf(buf, "%d\n", FAN_FROM_REG(data->fan_min[nr],
316 1 << data->fan_div[nr]));
317}
318
319static ssize_t show_fan_div(struct device *dev, char *buf, int nr)
320{
321 struct adm9240_data *data = adm9240_update_device(dev);
322 return sprintf(buf, "%d\n", 1 << data->fan_div[nr]);
323}
324
325/* write new fan div, callers must hold data->update_lock */
326static void adm9240_write_fan_div(struct i2c_client *client, int nr,
327 u8 fan_div)
328{
329 u8 reg, old, shift = (nr + 2) * 2;
330
331 reg = adm9240_read_value(client, ADM9240_REG_VID_FAN_DIV);
332 old = (reg >> shift) & 3;
333 reg &= ~(3 << shift);
334 reg |= (fan_div << shift);
335 adm9240_write_value(client, ADM9240_REG_VID_FAN_DIV, reg);
336 dev_dbg(&client->dev, "fan%d clock divider changed from %u "
337 "to %u\n", nr + 1, 1 << old, 1 << fan_div);
338}
339
340/*
341 * set fan speed low limit:
342 *
343 * - value is zero: disable fan speed low limit alarm
344 *
345 * - value is below fan speed measurement range: enable fan speed low
346 * limit alarm to be asserted while fan speed too slow to measure
347 *
348 * - otherwise: select fan clock divider to suit fan speed low limit,
349 * measurement code may adjust registers to ensure fan speed reading
350 */
351static ssize_t set_fan_min(struct device *dev, const char *buf,
352 size_t count, int nr)
353{
354 struct i2c_client *client = to_i2c_client(dev);
355 struct adm9240_data *data = i2c_get_clientdata(client);
356 unsigned long val = simple_strtoul(buf, NULL, 10);
357 u8 new_div;
358
359 down(&data->update_lock);
360
361 if (!val) {
362 data->fan_min[nr] = 255;
363 new_div = data->fan_div[nr];
364
365 dev_dbg(&client->dev, "fan%u low limit set disabled\n",
366 nr + 1);
367
368 } else if (val < 1350000 / (8 * 254)) {
369 new_div = 3;
370 data->fan_min[nr] = 254;
371
372 dev_dbg(&client->dev, "fan%u low limit set minimum %u\n",
373 nr + 1, FAN_FROM_REG(254, 1 << new_div));
374
375 } else {
376 unsigned int new_min = 1350000 / val;
377
378 new_div = 0;
379 while (new_min > 192 && new_div < 3) {
380 new_div++;
381 new_min /= 2;
382 }
383 if (!new_min) /* keep > 0 */
384 new_min++;
385
386 data->fan_min[nr] = new_min;
387
388 dev_dbg(&client->dev, "fan%u low limit set fan speed %u\n",
389 nr + 1, FAN_FROM_REG(new_min, 1 << new_div));
390 }
391
392 if (new_div != data->fan_div[nr]) {
393 data->fan_div[nr] = new_div;
394 adm9240_write_fan_div(client, nr, new_div);
395 }
396 adm9240_write_value(client, ADM9240_REG_FAN_MIN(nr),
397 data->fan_min[nr]);
398
399 up(&data->update_lock);
400 return count;
401}
402
403#define show_fan_offset(offset) \
404static ssize_t show_fan_##offset (struct device *dev, char *buf) \
405{ \
406return show_fan(dev, buf, offset - 1); \
407} \
408static ssize_t show_fan_##offset##_div (struct device *dev, char *buf) \
409{ \
410return show_fan_div(dev, buf, offset - 1); \
411} \
412static ssize_t show_fan_##offset##_min (struct device *dev, char *buf) \
413{ \
414return show_fan_min(dev, buf, offset - 1); \
415} \
416static ssize_t set_fan_##offset##_min (struct device *dev, \
417const char *buf, size_t count) \
418{ \
419return set_fan_min(dev, buf, count, offset - 1); \
420} \
421static DEVICE_ATTR(fan##offset##_input, S_IRUGO, \
422 show_fan_##offset, NULL); \
423static DEVICE_ATTR(fan##offset##_div, S_IRUGO, \
424 show_fan_##offset##_div, NULL); \
425static DEVICE_ATTR(fan##offset##_min, S_IRUGO | S_IWUSR, \
426 show_fan_##offset##_min, set_fan_##offset##_min);
427
428show_fan_offset(1);
429show_fan_offset(2);
430
431/* alarms */
432static ssize_t show_alarms(struct device *dev, char *buf)
433{
434 struct adm9240_data *data = adm9240_update_device(dev);
435 return sprintf(buf, "%u\n", data->alarms);
436}
437static DEVICE_ATTR(alarms, S_IRUGO, show_alarms, NULL);
438
439/* vid */
440static ssize_t show_vid(struct device *dev, char *buf)
441{
442 struct adm9240_data *data = adm9240_update_device(dev);
443 return sprintf(buf, "%d\n", vid_from_reg(data->vid, data->vrm));
444}
445static DEVICE_ATTR(cpu0_vid, S_IRUGO, show_vid, NULL);
446
447/* analog output */
448static ssize_t show_aout(struct device *dev, char *buf)
449{
450 struct adm9240_data *data = adm9240_update_device(dev);
451 return sprintf(buf, "%d\n", AOUT_FROM_REG(data->aout));
452}
453
454static ssize_t set_aout(struct device *dev, const char *buf, size_t count)
455{
456 struct i2c_client *client = to_i2c_client(dev);
457 struct adm9240_data *data = i2c_get_clientdata(client);
458 unsigned long val = simple_strtol(buf, NULL, 10);
459
460 down(&data->update_lock);
461 data->aout = AOUT_TO_REG(val);
462 adm9240_write_value(client, ADM9240_REG_ANALOG_OUT, data->aout);
463 up(&data->update_lock);
464 return count;
465}
466static DEVICE_ATTR(aout_output, S_IRUGO | S_IWUSR, show_aout, set_aout);
467
468/* chassis_clear */
469static ssize_t chassis_clear(struct device *dev, const char *buf, size_t count)
470{
471 struct i2c_client *client = to_i2c_client(dev);
472 unsigned long val = simple_strtol(buf, NULL, 10);
473
474 if (val == 1) {
475 adm9240_write_value(client, ADM9240_REG_CHASSIS_CLEAR, 0x80);
476 dev_dbg(&client->dev, "chassis intrusion latch cleared\n");
477 }
478 return count;
479}
480static DEVICE_ATTR(chassis_clear, S_IWUSR, NULL, chassis_clear);
481
482
483/*** sensor chip detect and driver install ***/
484
485static int adm9240_detect(struct i2c_adapter *adapter, int address, int kind)
486{
487 struct i2c_client *new_client;
488 struct adm9240_data *data;
489 int err = 0;
490 const char *name = "";
491 u8 man_id, die_rev;
492
493 if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA))
494 goto exit;
495
496 if (!(data = kmalloc(sizeof(struct adm9240_data), GFP_KERNEL))) {
497 err = -ENOMEM;
498 goto exit;
499 }
500 memset(data, 0, sizeof(struct adm9240_data));
501
502 new_client = &data->client;
503 i2c_set_clientdata(new_client, data);
504 new_client->addr = address;
505 new_client->adapter = adapter;
506 new_client->driver = &adm9240_driver;
507 new_client->flags = 0;
508
509 if (kind == 0) {
510 kind = adm9240;
511 }
512
513 if (kind < 0) {
514
515 /* verify chip: reg address should match i2c address */
516 if (adm9240_read_value(new_client, ADM9240_REG_I2C_ADDR)
517 != address) {
518 dev_err(&adapter->dev, "detect fail: address match, "
519 "0x%02x\n", address);
520 goto exit_free;
521 }
522
523 /* check known chip manufacturer */
524 man_id = adm9240_read_value(new_client, ADM9240_REG_MAN_ID);
525
526 if (man_id == 0x23) {
527 kind = adm9240;
528 } else if (man_id == 0xda) {
529 kind = ds1780;
530 } else if (man_id == 0x01) {
531 kind = lm81;
532 } else {
533 dev_err(&adapter->dev, "detect fail: unknown manuf, "
534 "0x%02x\n", man_id);
535 goto exit_free;
536 }
537
538 /* successful detect, print chip info */
539 die_rev = adm9240_read_value(new_client, ADM9240_REG_DIE_REV);
540 dev_info(&adapter->dev, "found %s revision %u\n",
541 man_id == 0x23 ? "ADM9240" :
542 man_id == 0xda ? "DS1780" : "LM81", die_rev);
543 }
544
545 /* either forced or detected chip kind */
546 if (kind == adm9240) {
547 name = "adm9240";
548 } else if (kind == ds1780) {
549 name = "ds1780";
550 } else if (kind == lm81) {
551 name = "lm81";
552 }
553
554 /* fill in the remaining client fields and attach */
555 strlcpy(new_client->name, name, I2C_NAME_SIZE);
556 data->type = kind;
557 init_MUTEX(&data->update_lock);
558
559 if ((err = i2c_attach_client(new_client)))
560 goto exit_free;
561
562 adm9240_init_client(new_client);
563
564 /* populate sysfs filesystem */
565 device_create_file(&new_client->dev, &dev_attr_in0_input);
566 device_create_file(&new_client->dev, &dev_attr_in0_min);
567 device_create_file(&new_client->dev, &dev_attr_in0_max);
568 device_create_file(&new_client->dev, &dev_attr_in1_input);
569 device_create_file(&new_client->dev, &dev_attr_in1_min);
570 device_create_file(&new_client->dev, &dev_attr_in1_max);
571 device_create_file(&new_client->dev, &dev_attr_in2_input);
572 device_create_file(&new_client->dev, &dev_attr_in2_min);
573 device_create_file(&new_client->dev, &dev_attr_in2_max);
574 device_create_file(&new_client->dev, &dev_attr_in3_input);
575 device_create_file(&new_client->dev, &dev_attr_in3_min);
576 device_create_file(&new_client->dev, &dev_attr_in3_max);
577 device_create_file(&new_client->dev, &dev_attr_in4_input);
578 device_create_file(&new_client->dev, &dev_attr_in4_min);
579 device_create_file(&new_client->dev, &dev_attr_in4_max);
580 device_create_file(&new_client->dev, &dev_attr_in5_input);
581 device_create_file(&new_client->dev, &dev_attr_in5_min);
582 device_create_file(&new_client->dev, &dev_attr_in5_max);
583 device_create_file(&new_client->dev, &dev_attr_temp1_max);
584 device_create_file(&new_client->dev, &dev_attr_temp1_max_hyst);
585 device_create_file(&new_client->dev, &dev_attr_temp1_input);
586 device_create_file(&new_client->dev, &dev_attr_fan1_input);
587 device_create_file(&new_client->dev, &dev_attr_fan1_div);
588 device_create_file(&new_client->dev, &dev_attr_fan1_min);
589 device_create_file(&new_client->dev, &dev_attr_fan2_input);
590 device_create_file(&new_client->dev, &dev_attr_fan2_div);
591 device_create_file(&new_client->dev, &dev_attr_fan2_min);
592 device_create_file(&new_client->dev, &dev_attr_alarms);
593 device_create_file(&new_client->dev, &dev_attr_aout_output);
594 device_create_file(&new_client->dev, &dev_attr_chassis_clear);
595 device_create_file(&new_client->dev, &dev_attr_cpu0_vid);
596
597 return 0;
598exit_free:
599 kfree(new_client);
600exit:
601 return err;
602}
603
604static int adm9240_attach_adapter(struct i2c_adapter *adapter)
605{
606 if (!(adapter->class & I2C_CLASS_HWMON))
607 return 0;
608 return i2c_detect(adapter, &addr_data, adm9240_detect);
609}
610
611static int adm9240_detach_client(struct i2c_client *client)
612{
613 int err;
614
615 if ((err = i2c_detach_client(client))) {
616 dev_err(&client->dev, "Client deregistration failed, "
617 "client not detached.\n");
618 return err;
619 }
620
621 kfree(i2c_get_clientdata(client));
622 return 0;
623}
624
625static void adm9240_init_client(struct i2c_client *client)
626{
627 struct adm9240_data *data = i2c_get_clientdata(client);
628 u8 conf = adm9240_read_value(client, ADM9240_REG_CONFIG);
629 u8 mode = adm9240_read_value(client, ADM9240_REG_TEMP_CONF) & 3;
630
631 data->vrm = i2c_which_vrm(); /* need this to report vid as mV */
632
633 if (conf & 1) { /* measurement cycle running: report state */
634
635 dev_info(&client->dev, "status: config 0x%02x mode %u\n",
636 conf, mode);
637
638 } else { /* cold start: open limits before starting chip */
639 int i;
640
641 for (i = 0; i < 6; i++)
642 {
643 adm9240_write_value(client,
644 ADM9240_REG_IN_MIN(i), 0);
645 adm9240_write_value(client,
646 ADM9240_REG_IN_MAX(i), 255);
647 }
648 adm9240_write_value(client, ADM9240_REG_FAN_MIN(0), 255);
649 adm9240_write_value(client, ADM9240_REG_FAN_MIN(1), 255);
650 adm9240_write_value(client, ADM9240_REG_TEMP_HIGH, 127);
651 adm9240_write_value(client, ADM9240_REG_TEMP_HYST, 127);
652
653 /* start measurement cycle */
654 adm9240_write_value(client, ADM9240_REG_CONFIG, 1);
655
656 dev_info(&client->dev, "cold start: config was 0x%02x "
657 "mode %u\n", conf, mode);
658 }
659}
660
661static struct adm9240_data *adm9240_update_device(struct device *dev)
662{
663 struct i2c_client *client = to_i2c_client(dev);
664 struct adm9240_data *data = i2c_get_clientdata(client);
665 int i;
666
667 down(&data->update_lock);
668
669 /* minimum measurement cycle: 1.75 seconds */
670 if (time_after(jiffies, data->last_updated_measure + (HZ * 7 / 4))
671 || !data->valid) {
672
673 for (i = 0; i < 6; i++) /* read voltages */
674 {
675 data->in[i] = adm9240_read_value(client,
676 ADM9240_REG_IN(i));
677 }
678 data->alarms = adm9240_read_value(client,
679 ADM9240_REG_INT(0)) |
680 adm9240_read_value(client,
681 ADM9240_REG_INT(1)) << 8;
682
683 /* read temperature: assume temperature changes less than
684 * 0.5'C per two measurement cycles thus ignore possible
685 * but unlikely aliasing error on lsb reading. --Grant */
686 data->temp = ((adm9240_read_value(client,
687 ADM9240_REG_TEMP) << 8) |
688 adm9240_read_value(client,
689 ADM9240_REG_TEMP_CONF)) / 128;
690
691 for (i = 0; i < 2; i++) /* read fans */
692 {
693 data->fan[i] = adm9240_read_value(client,
694 ADM9240_REG_FAN(i));
695
696 /* adjust fan clock divider on overflow */
697 if (data->valid && data->fan[i] == 255 &&
698 data->fan_div[i] < 3) {
699
700 adm9240_write_fan_div(client, i,
701 ++data->fan_div[i]);
702
703 /* adjust fan_min if active, but not to 0 */
704 if (data->fan_min[i] < 255 &&
705 data->fan_min[i] >= 2)
706 data->fan_min[i] /= 2;
707 }
708 }
709 data->last_updated_measure = jiffies;
710 }
711
712 /* minimum config reading cycle: 300 seconds */
713 if (time_after(jiffies, data->last_updated_config + (HZ * 300))
714 || !data->valid) {
715
716 for (i = 0; i < 6; i++)
717 {
718 data->in_min[i] = adm9240_read_value(client,
719 ADM9240_REG_IN_MIN(i));
720 data->in_max[i] = adm9240_read_value(client,
721 ADM9240_REG_IN_MAX(i));
722 }
723 for (i = 0; i < 2; i++)
724 {
725 data->fan_min[i] = adm9240_read_value(client,
726 ADM9240_REG_FAN_MIN(i));
727 }
728 data->temp_high = adm9240_read_value(client,
729 ADM9240_REG_TEMP_HIGH);
730 data->temp_hyst = adm9240_read_value(client,
731 ADM9240_REG_TEMP_HYST);
732
733 /* read fan divs and 5-bit VID */
734 i = adm9240_read_value(client, ADM9240_REG_VID_FAN_DIV);
735 data->fan_div[0] = (i >> 4) & 3;
736 data->fan_div[1] = (i >> 6) & 3;
737 data->vid = i & 0x0f;
738 data->vid |= (adm9240_read_value(client,
739 ADM9240_REG_VID4) & 1) << 4;
740 /* read analog out */
741 data->aout = adm9240_read_value(client,
742 ADM9240_REG_ANALOG_OUT);
743
744 data->last_updated_config = jiffies;
745 data->valid = 1;
746 }
747 up(&data->update_lock);
748 return data;
749}
750
751static int __init sensors_adm9240_init(void)
752{
753 return i2c_add_driver(&adm9240_driver);
754}
755
756static void __exit sensors_adm9240_exit(void)
757{
758 i2c_del_driver(&adm9240_driver);
759}
760
761MODULE_AUTHOR("Michiel Rook <michiel@grendelproject.nl>, "
762 "Grant Coady <gcoady@gmail.com> and others");
763MODULE_DESCRIPTION("ADM9240/DS1780/LM81 driver");
764MODULE_LICENSE("GPL");
765
766module_init(sensors_adm9240_init);
767module_exit(sensors_adm9240_exit);
768