root/lm-sensors/trunk/kernel/chips/adm1031.c @ 2580

Revision 2580, 18.9 KB (checked in by khali, 11 years ago)

Prevent fan_min overflow when changing fan_div.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
Line 
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 Analog Devices ADM1030 and ADM1031
6  Copyright (C) 2004 Alexandre d'Alton <alex@alexdalton.org>
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#include <linux/module.h>
24#include <linux/init.h>
25#include <linux/slab.h>
26#include <linux/i2c.h>
27#include <linux/i2c-proc.h>
28#include "version.h"
29
30/* Following macros take channel parameter starting from 0 */
31#define ADM1031_REG_FAN_SPEED(nr)       (0x08 + (nr))
32
33#define ADM1031_REG_FAN_DIV(nr)         (0x20 + (nr))
34#define ADM1031_REG_FAN_MIN(nr)         (0x10 + (nr))
35
36#define ADM1031_REG_TEMP_MAX(nr)        (0x14 + 4 * (nr))
37#define ADM1031_REG_TEMP_MIN(nr)        (0x15 + 4 * (nr))
38#define ADM1031_REG_TEMP_CRIT(nr)       (0x16 + 4 * (nr))
39
40#define ADM1031_REG_TEMP(nr)            (0x0a + (nr))
41#define ADM1031_REG_AUTO_TEMP(nr)       (0x24 + (nr))
42
43#define ADM1031_REG_STATUS(nr)          (0x02 + (nr))
44#define ADM1031_REG_FAN_PWM             0x22
45
46#define ADM1031_REG_CONF1               0x00
47#define ADM1031_REG_CONF2               0x01
48#define ADM1031_REG_EXT_TEMP            0x06
49
50#define ADM1031_CONF1_MONITOR_ENABLE    0x01 /* Monitoring enable */
51#define ADM1031_CONF1_PWM_INVERT        0x08 /* PWM Invert (unused) */
52#define ADM1031_CONF1_AUTO_MODE         0x80 /* Auto fan mode */
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 */
61static unsigned short normal_i2c[] = { SENSORS_I2C_END };
62static unsigned short normal_i2c_range[] = { 0x2c, 0x2e, SENSORS_I2C_END };
63static unsigned int normal_isa[] = { SENSORS_ISA_END };
64static unsigned int normal_isa_range[] = { SENSORS_ISA_END };
65
66/* Insmod parameters */
67SENSORS_INSMOD_2(adm1030, adm1031);
68
69/*
70 * Proc entries
71 * These files are created for each detected ADM1031.
72 */
73
74/* -- SENSORS SYSCTL START -- */
75
76#define ADM1031_SYSCTL_TEMP1            1200
77#define ADM1031_SYSCTL_TEMP2            1201
78#define ADM1031_SYSCTL_TEMP3            1202
79
80#define ADM1031_SYSCTL_FAN1             1210
81#define ADM1031_SYSCTL_FAN2             1211
82
83#define ADM1031_SYSCTL_FAN_DIV          1220
84
85#define ADM1031_SYSCTL_ALARMS           1250
86
87#define ADM1031_ALARM_FAN1_MIN          0x0001
88#define ADM1031_ALARM_FAN1_FLT          0x0002
89#define ADM1031_ALARM_TEMP2_HIGH        0x0004
90#define ADM1031_ALARM_TEMP2_LOW         0x0008
91#define ADM1031_ALARM_TEMP2_CRIT        0x0010
92#define ADM1031_ALARM_TEMP2_DIODE       0x0020
93#define ADM1031_ALARM_TEMP1_HIGH        0x0040
94#define ADM1031_ALARM_TEMP1_LOW         0x0080
95#define ADM1031_ALARM_FAN2_MIN          0x0100
96#define ADM1031_ALARM_FAN2_FLT          0x0200
97#define ADM1031_ALARM_TEMP3_HIGH        0x0400
98#define ADM1031_ALARM_TEMP3_LOW         0x0800
99#define ADM1031_ALARM_TEMP3_CRIT        0x1000
100#define ADM1031_ALARM_TEMP3_DIODE       0x2000
101#define ADM1031_ALARM_TEMP1_CRIT        0x4000
102#define ADM1031_ALARM_THERMAL           0x8000
103
104
105/* -- SENSORS SYSCTL END -- */
106static void adm1031_alarms(struct i2c_client *client, int operation,
107                           int ctl_name, int *nrels_mag, long *results);
108static void adm1031_temp(struct i2c_client *client, int operation,
109                         int ctl_name, int *nrels_mag, long *results);
110static void adm1031_fan(struct i2c_client *client, int operation,
111                        int ctl_name, int *nrels_mag, long *results);
112static void adm1031_fan_div(struct i2c_client *client, int operation,
113                            int ctl_name, int *nrels_mag, long *results);
114
115static ctl_table adm1031_dir_table_template[] = {
116        {ADM1031_SYSCTL_TEMP1, "temp1", NULL, 0, 0644, NULL,
117         &i2c_proc_real,
118         &i2c_sysctl_real, NULL, &adm1031_temp},
119        {ADM1031_SYSCTL_TEMP2, "temp2", NULL, 0, 0644, NULL,
120         &i2c_proc_real,
121         &i2c_sysctl_real, NULL, &adm1031_temp},
122        {ADM1031_SYSCTL_TEMP3, "temp3", NULL, 0, 0644, NULL,
123         &i2c_proc_real,
124         &i2c_sysctl_real, NULL, &adm1031_temp},
125        {ADM1031_SYSCTL_FAN1, "fan1", NULL, 0, 0644, NULL,
126         &i2c_proc_real,
127         &i2c_sysctl_real, NULL, &adm1031_fan},
128        {ADM1031_SYSCTL_FAN_DIV, "fan_div", NULL, 0, 0644, NULL,
129         &i2c_proc_real,
130         &i2c_sysctl_real, NULL, &adm1031_fan_div},
131        {ADM1031_SYSCTL_FAN2, "fan2", NULL, 0, 0644, NULL,
132         &i2c_proc_real,
133         &i2c_sysctl_real, NULL, &adm1031_fan},
134        {ADM1031_SYSCTL_ALARMS, "alarms", NULL, 0, 0444, NULL,
135         &i2c_proc_real,
136         &i2c_sysctl_real, NULL, &adm1031_alarms},
137        {0}
138};
139
140static ctl_table adm1030_dir_table_template[] = {
141        {ADM1031_SYSCTL_TEMP1, "temp1", NULL, 0, 0644, NULL,
142         &i2c_proc_real,
143         &i2c_sysctl_real, NULL, &adm1031_temp},
144        {ADM1031_SYSCTL_TEMP2, "temp2", NULL, 0, 0644, NULL,
145         &i2c_proc_real,
146         &i2c_sysctl_real, NULL, &adm1031_temp},
147        {ADM1031_SYSCTL_FAN1, "fan1", NULL, 0, 0644, NULL,
148         &i2c_proc_real,
149         &i2c_sysctl_real, NULL, &adm1031_fan},
150        {ADM1031_SYSCTL_FAN_DIV, "fan_div", NULL, 0, 0644, NULL,
151         &i2c_proc_real,
152         &i2c_sysctl_real, NULL, &adm1031_fan_div},
153        {ADM1031_SYSCTL_ALARMS, "alarms", NULL, 0, 0444, NULL,
154         &i2c_proc_real,
155         &i2c_sysctl_real, NULL, &adm1031_alarms},
156        {0}
157};
158
159
160/* Each client has this additional data */
161struct adm1031_data {
162        struct i2c_client client;
163        int sysctl_id;
164        struct semaphore update_lock;
165        int chip_type;
166        char valid;             /* !=0 if following fields are valid */
167        unsigned long last_updated;     /* In jiffies */
168
169        u16 alarms;
170        u8 conf1;
171        u8 conf2;
172        u8 fan[2];
173        u8 fan_min[2];
174        u8 fan_pwm[2];
175        u8 fan_div[2];
176        s8 temp[3];
177        u8 auto_temp[3];
178        u8 ext_temp[3];
179        s8 temp_min[3];
180        s8 temp_max[3];
181        s8 temp_crit[3];
182};
183
184static int adm1031_attach_adapter(struct i2c_adapter *adapter);
185static int adm1031_detect(struct i2c_adapter *adapter, int address,
186                          unsigned short flags, int kind);
187static void adm1031_init_client(struct i2c_client *client);
188static int adm1031_detach_client(struct i2c_client *client);
189
190static inline u8 adm1031_read_value(struct i2c_client *client, u8 reg);
191static inline int adm1031_write_value(struct i2c_client *client, u8 reg,
192                                      unsigned int value);
193
194static void adm1031_update_client(struct i2c_client *client);
195
196/* This is the driver that will be inserted */
197static struct i2c_driver adm1031_driver = {
198        .owner          = THIS_MODULE,
199        .name           = "ADM1031/ADM1030 sensor driver",
200        .flags          = I2C_DF_NOTIFY,
201        .attach_adapter = adm1031_attach_adapter,
202        .detach_client  = adm1031_detach_client,
203};
204
205static int adm1031_id = 0;
206
207#define TEMP_TO_REG(val)                ((val) < 0 ? (((val) - 500) / 1000) : \
208                                         (((val) + 500) / 1000))
209
210#define TEMP_FROM_REG(val)              ((val) * 1000)
211
212#define TEMP_FROM_REG_EXT(val,ext)      (TEMP_FROM_REG(val) + (ext) * 125)
213
214#define FAN_FROM_REG(reg,div)           ((reg) ? \
215                                         (11250 * 60) / ((reg) * (div)) : 0)
216
217#define FAN_TO_REG(reg,div)             FAN_FROM_REG(SENSORS_LIMIT(reg, 0, \
218                                                                   65535), div)
219
220#define FAN_DIV_TO_REG(val)             ((val) == 8 ? 0xc0 : \
221                                         (val) == 4 ? 0x80 : \
222                                         (val) == 1 ? 0x00 : 0x40)
223
224#define FAN_DIV_FROM_REG(reg)           (1 << (((reg)&0xc0) >> 6))
225
226#define AUTO_TEMP_OFF_FROM_REG(reg)     (((((reg) >> 3) & 0x1f) << 2) - 5)
227
228
229static int adm1031_attach_adapter(struct i2c_adapter *adapter)
230{
231        return i2c_detect(adapter, &addr_data, adm1031_detect);
232}
233
234/* This function is called by i2c_detect */
235static int
236adm1031_detect(struct i2c_adapter *adapter, int address,
237               unsigned short flags, int kind)
238{
239        struct i2c_client *new_client;
240        struct adm1031_data *data;
241        int err = 0;
242        const char *type_name = "";
243        const char *client_name = "";
244
245        if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA))
246                goto exit;
247
248        if (!(data = kmalloc(sizeof(struct adm1031_data), GFP_KERNEL))) {
249                err = -ENOMEM;
250                goto exit;
251        }
252        memset(data, 0, sizeof(struct adm1031_data));
253
254        new_client = &data->client;
255        new_client->data = data;
256        new_client->addr = address;
257        new_client->adapter = adapter;
258        new_client->driver = &adm1031_driver;
259        new_client->flags = 0;
260
261        if (kind < 0) {
262                int id, co;
263                id = i2c_smbus_read_byte_data(new_client, 0x3d);
264                co = i2c_smbus_read_byte_data(new_client, 0x3e);
265
266                if (((id != 0x31) || (id != 0x30)) && (co != 0x41))
267                        goto exit_free;
268                kind = (id == 0x30) ? adm1030 : adm1031;
269        }
270
271        if (kind <= 0)
272                kind = adm1031;
273
274        /* Given the detected chip type, set the chip name and the
275         * auto fan control helper table. */
276        if (kind == adm1030) {
277                type_name = "adm1030";
278                client_name = "ADM1030 chip";
279
280        } else if (kind == adm1031) {
281                type_name = "adm1031";
282                client_name = "ADM1031 chip";
283        }
284        data->chip_type = kind;
285
286        strcpy(new_client->name, client_name);
287
288        new_client->id = adm1031_id++;
289        data->valid = 0;
290        init_MUTEX(&data->update_lock);
291
292        /* Tell the I2C layer a new client has arrived */
293        if ((err = i2c_attach_client(new_client)))
294                goto exit_free;
295
296
297        if (kind == adm1030) {
298                if ((err = i2c_register_entry(new_client, type_name,
299                                              adm1030_dir_table_template)) < 0)
300                        goto exit_detach;
301        } else if (kind == adm1031) {
302                if ((err = i2c_register_entry(new_client, type_name,
303                                              adm1031_dir_table_template)) < 0)
304                        goto exit_detach;
305        }
306
307        data->sysctl_id = err;
308
309        /* Initialize the ADM1031 chip */
310        adm1031_init_client(new_client);
311
312        return 0;
313
314exit_detach:
315        i2c_detach_client(new_client);
316exit_free:
317        kfree(new_client);
318exit:
319        return err;
320}
321
322static int adm1031_detach_client(struct i2c_client *client)
323{
324        int ret;
325        struct adm1031_data *data = client->data;
326
327        i2c_deregister_entry(data->sysctl_id);
328        if ((ret = i2c_detach_client(client)) != 0) {
329                return ret;
330        }
331
332        kfree(client);
333        return 0;
334}
335
336static inline u8 adm1031_read_value(struct i2c_client *client, u8 reg)
337{
338        return i2c_smbus_read_byte_data(client, reg);
339}
340
341static inline int adm1031_write_value(struct i2c_client *client, u8 reg,
342                                      unsigned int value)
343{
344        return i2c_smbus_write_byte_data(client, reg, value);
345}
346
347static void adm1031_init_client(struct i2c_client *client)
348{
349        unsigned int read_val;
350        unsigned int mask;
351        struct adm1031_data *data = client->data;
352
353        mask = (ADM1031_CONF2_PWM1_ENABLE | ADM1031_CONF2_TACH1_ENABLE);
354        if (data->chip_type == adm1031) {
355                mask |= (ADM1031_CONF2_PWM2_ENABLE |
356                         ADM1031_CONF2_TACH2_ENABLE);
357        }
358        /* Initialize the ADM1031 chip (enable fan speed reading) */
359        read_val = adm1031_read_value(client, ADM1031_REG_CONF2);
360        if ((read_val | mask) != read_val) {
361                adm1031_write_value(client, ADM1031_REG_CONF2,
362                                    read_val | mask);
363        }
364
365        read_val = adm1031_read_value(client, ADM1031_REG_CONF1);
366        if ((read_val | ADM1031_CONF1_MONITOR_ENABLE) != read_val) {
367                adm1031_write_value(client, ADM1031_REG_CONF1, read_val |
368                                    ADM1031_CONF1_MONITOR_ENABLE);
369        }
370}
371
372static void adm1031_update_client(struct i2c_client *client)
373{
374        struct adm1031_data *data = client->data;
375        int chan;
376
377        down(&data->update_lock);
378
379        if ((jiffies - data->last_updated > HZ + HZ / 2) ||
380            (jiffies < data->last_updated) || !data->valid) {
381#ifdef DEBUG
382                printk(KERN_INFO "adm1031.o: Starting chip update\n");
383#endif
384                for (chan = 0;
385                     chan < ((data->chip_type == adm1031) ? 3 : 2);
386                     chan++) {
387                        u8 oldh, newh;
388
389                        oldh = adm1031_read_value(client,
390                                                  ADM1031_REG_TEMP(chan));
391                        data->ext_temp[chan] = adm1031_read_value(client,
392                                                        ADM1031_REG_EXT_TEMP);
393                        newh = adm1031_read_value(client,
394                                                  ADM1031_REG_TEMP(chan));
395                        if (newh != oldh) {
396                                data->ext_temp[chan] = adm1031_read_value(client,
397                                                        ADM1031_REG_EXT_TEMP);
398#ifdef DEBUG
399                                oldh = adm1031_read_value(client,
400                                                          ADM1031_REG_TEMP(chan));
401
402                                /* oldh is actually newer */
403                                if (newh != oldh)
404                                        printk(KERN_INFO "adm1031.o: Remote "
405                                               "temperature may be wrong.\n");
406#endif
407                        }
408                        data->temp[chan] = newh;
409
410                        data->temp_min[chan] = adm1031_read_value(client,
411                                               ADM1031_REG_TEMP_MIN(chan));
412                        data->temp_max[chan] = adm1031_read_value(client,
413                                               ADM1031_REG_TEMP_MAX(chan));
414                        data->temp_crit[chan] = adm1031_read_value(client,
415                                                ADM1031_REG_TEMP_CRIT(chan));
416                        data->auto_temp[chan] = adm1031_read_value(client,
417                                                ADM1031_REG_AUTO_TEMP(chan));
418                }
419
420                data->conf1 = adm1031_read_value(client, ADM1031_REG_CONF1);
421
422                data->alarms = adm1031_read_value(client, ADM1031_REG_STATUS(0))
423                             | (adm1031_read_value(client, ADM1031_REG_STATUS(1))
424                                << 8);
425                if (data->chip_type == adm1030) {
426                        data->alarms &= 0xc0ff;
427                }
428
429                for (chan = 0;
430                     chan < (data->chip_type == adm1030 ? 1 : 2);
431                     chan++) {
432                        data->fan_div[chan] = adm1031_read_value(client,
433                                              ADM1031_REG_FAN_DIV(chan));
434                        data->fan_min[chan] = adm1031_read_value(client,
435                                              ADM1031_REG_FAN_MIN(chan));
436                        data->fan[chan] = adm1031_read_value(client,
437                                          ADM1031_REG_FAN_SPEED(chan));
438                        data->fan_pwm[chan] = (adm1031_read_value(client,
439                                               ADM1031_REG_FAN_PWM) >> (4 * chan))
440                                              & 0x0f;
441                }
442
443                data->conf1 = adm1031_read_value(client, ADM1031_REG_CONF1);
444                data->conf2 = adm1031_read_value(client, ADM1031_REG_CONF2);
445
446                data->last_updated = jiffies;
447                data->valid = 1;
448        }
449
450        up(&data->update_lock);
451}
452
453static int __init sensors_adm1031_init(void)
454{
455        printk(KERN_INFO "adm1031.o version %s (%s)\n", LM_VERSION, LM_DATE);
456        return i2c_add_driver(&adm1031_driver);
457}
458
459static void __exit sensors_adm1031_exit(void)
460{
461        i2c_del_driver(&adm1031_driver);
462}
463
464
465static void
466adm1031_temp(struct i2c_client *client, int operation, int ctl_name,
467             int *nrels_mag, long *results)
468{
469        int ext;
470        struct adm1031_data *data = client->data;
471        int tmp;
472        int nr = ctl_name - ADM1031_SYSCTL_TEMP1;
473
474        ext = nr == 0 ?
475                ((data->ext_temp[nr] >> 6) & 0x3) * 2 :
476                (((data->ext_temp[nr] >> ((nr - 1) * 3)) & 7));
477
478        if (operation == SENSORS_PROC_REAL_INFO)
479                *nrels_mag = 3;
480        else if (operation == SENSORS_PROC_REAL_READ) {
481                adm1031_update_client(client);
482                results[0] = TEMP_FROM_REG(data->temp_max[nr]);
483                results[1] = TEMP_FROM_REG(data->temp_min[nr]);
484                results[2] = TEMP_FROM_REG(data->temp_crit[nr]);
485                results[3] = TEMP_FROM_REG_EXT(data->temp[nr], ext);
486                *nrels_mag = 4;
487        } else if (operation == SENSORS_PROC_REAL_WRITE) {
488                if (*nrels_mag >= 1) {
489                        tmp = SENSORS_LIMIT(results[0], -55000, 127000);
490                        data->temp_max[nr] = TEMP_TO_REG(tmp);
491                        adm1031_write_value(client,
492                                            ADM1031_REG_TEMP_MAX(nr),
493                                            data->temp_max[nr]);
494                }
495                if (*nrels_mag >= 2) {
496                        tmp = SENSORS_LIMIT(results[1], -55000, 127000);
497                        data->temp_min[nr] = TEMP_TO_REG(tmp);
498                        adm1031_write_value(client,
499                                            ADM1031_REG_TEMP_MIN(nr),
500                                            data->temp_min[nr]);
501                }
502                if (*nrels_mag >= 3) {
503                        tmp = SENSORS_LIMIT(results[2], -55000, 127000);
504                        data->temp_crit[nr] = TEMP_TO_REG(tmp);
505                        adm1031_write_value(client,
506                                            ADM1031_REG_TEMP_CRIT(nr),
507                                            data->temp_crit[nr]);
508                }
509        }
510}
511
512/*
513 * That function checks the cases where the fan reading is not
514 * relevant.  It is used to provide 0 as fan reading when the fan is
515 * not supposed to run.
516 */
517static int trust_fan_readings(struct adm1031_data * data, int chan)
518{
519        int res = 0;
520
521        if (data->conf1 & ADM1031_CONF1_AUTO_MODE) {
522                switch(data->conf1 & 0x60) {
523                case 0x00: /* remote temp1 controls fan1 remote temp2
524                              controls fan2 */
525                        res = chan == 0 ? data->temp[1] >
526                              AUTO_TEMP_OFF_FROM_REG(data->auto_temp[1]) :
527                              data->temp[2] >
528                              AUTO_TEMP_OFF_FROM_REG(data->auto_temp[2]);
529                        break;
530                case 0x20: /* remote temp1 controls both fans*/
531                        if (data->chip_type == adm1030)
532                                res = 0;
533                        else
534                                res = data->temp[1] >
535                                      AUTO_TEMP_OFF_FROM_REG(data->auto_temp[1]);
536                        break;
537                case 0x40: /* remote temp2 controls both fans*/
538                        if (data->chip_type == adm1030)
539                                res = 0;
540                        else
541                                res = data->temp[2] >
542                                      AUTO_TEMP_OFF_FROM_REG(data->auto_temp[2]);
543                        break;
544                case 0x60: /* max controls both fans */
545                        if (data->chip_type == adm1030){
546                                res = data->temp[0] >
547                                      AUTO_TEMP_OFF_FROM_REG(data->auto_temp[0])
548                                      || data->temp[1] >
549                                      AUTO_TEMP_OFF_FROM_REG(data->auto_temp[1]);
550                        } else {
551                                res = data->temp[0] >
552                                      AUTO_TEMP_OFF_FROM_REG(data->auto_temp[0])
553                                      || data->temp[1] >
554                                      AUTO_TEMP_OFF_FROM_REG(data->auto_temp[1])
555                                      || data->temp[2] >
556                                      AUTO_TEMP_OFF_FROM_REG(data->auto_temp[2]);
557                        }
558                        break;
559                default:
560                        res = 0;
561                        break;
562                }
563        } else {
564                res = data->fan_pwm[chan] > 0;
565        }
566
567        return res;
568}
569
570static void adm1031_fan(struct i2c_client *client, int operation,
571                        int ctl_name, int *nrels_mag, long *results)
572{
573        struct adm1031_data *data = client->data;
574        int nr = ctl_name - ADM1031_SYSCTL_FAN1;
575
576        if (operation == SENSORS_PROC_REAL_INFO)
577                *nrels_mag = 0;
578        else if (operation == SENSORS_PROC_REAL_READ) {
579                adm1031_update_client(client);
580                results[0] = FAN_FROM_REG(data->fan_min[nr],
581                             FAN_DIV_FROM_REG(data->fan_div[nr]));
582                results[1] = trust_fan_readings(data, nr) ?
583                             FAN_FROM_REG(data->fan[nr],
584                             FAN_DIV_FROM_REG(data->fan_div[nr])) : 0;
585                *nrels_mag = 2;
586        } else if (operation == SENSORS_PROC_REAL_WRITE) {
587                if (*nrels_mag >= 1) {
588                        data->fan_min[nr] = FAN_TO_REG(results[0],
589                                            FAN_DIV_FROM_REG(data->fan_div[nr]));
590                        adm1031_write_value(client,
591                                            ADM1031_REG_FAN_MIN(nr),
592                                            data->fan_min[nr]);
593                }
594        }
595}
596
597static void adm1031_fan_div(struct i2c_client *client, int operation,
598                            int ctl_name, int *nrels_mag, long *results)
599{
600        struct adm1031_data *data = client->data;
601
602        if (operation == SENSORS_PROC_REAL_INFO)
603                *nrels_mag = 0;
604        else if (operation == SENSORS_PROC_REAL_READ) {
605                adm1031_update_client(client);
606                results[0] = FAN_DIV_FROM_REG(data->fan_div[0]);
607                *nrels_mag = 1;
608                if(data->chip_type == adm1031) {
609                    results[1] = FAN_DIV_FROM_REG(data->fan_div[1]);
610                    *nrels_mag = 2;
611                }
612        } else if (operation == SENSORS_PROC_REAL_WRITE) {
613                int old_div, new_min;
614                if (*nrels_mag >= 1) {
615                        old_div = FAN_DIV_FROM_REG(data->fan_div[0]);
616                        data->fan_div[0] = FAN_DIV_TO_REG(results[0]);
617                        adm1031_write_value(client,
618                                            ADM1031_REG_FAN_DIV(0),
619                                            data->fan_div[0]);
620                        new_min = data->fan_min[0] * old_div /
621                                  FAN_DIV_FROM_REG(data->fan_div[0]);
622                        data->fan_min[0] = new_min > 0xff ? 0xff : new_min;
623                        adm1031_write_value(client,
624                                            ADM1031_REG_FAN_MIN(0),
625                                            data->fan_min[0]);
626                }
627                if (*nrels_mag >= 2) {
628                        old_div = FAN_DIV_FROM_REG(data->fan_div[1]);
629                        data->fan_div[1] = FAN_DIV_TO_REG(results[1]);
630                        adm1031_write_value(client,
631                                            ADM1031_REG_FAN_DIV(1),
632                                            data->fan_div[1]);
633                        new_min = data->fan_min[1] * old_div /
634                                  FAN_DIV_FROM_REG(data->fan_div[1]);
635                        data->fan_min[1] = new_min > 0xff ? 0xff : new_min;
636                        adm1031_write_value(client,
637                                            ADM1031_REG_FAN_MIN(1),
638                                            data->fan_min[1]);
639                }
640        }
641}
642
643static void adm1031_alarms(struct i2c_client *client, int operation,
644                           int ctl_name, int *nrels_mag, long *results)
645{
646        struct adm1031_data *data = client->data;
647        if (operation == SENSORS_PROC_REAL_INFO)
648                *nrels_mag = 0;
649        else if (operation == SENSORS_PROC_REAL_READ) {
650                adm1031_update_client(client);
651                results[0] = data->alarms;
652                *nrels_mag = 1;
653        }
654}
655
656MODULE_AUTHOR("Alexandre d'Alton <alex@alexdalton.org>");
657MODULE_DESCRIPTION("ADM1031/ADM1030 driver");
658MODULE_LICENSE("GPL");
659
660module_init(sensors_adm1031_init);
661module_exit(sensors_adm1031_exit);
Note: See TracBrowser for help on using the browser.