root/lm-sensors/trunk/kernel/chips/lm87.c @ 1285

Revision 1285, 32.7 KB (checked in by mds, 12 years ago)

fixed initial limit settings for in0, in1, in5 - tkt #788

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
Line 
1/*
2    LM87.c - Part of lm_sensors, Linux kernel modules for hardware
3             monitoring
4    Copyright (c) 2000  Frodo Looijaard <frodol@dds.nl>
5                        Philip Edelbrock <phil@netroedge.com>
6                        Stephen Rousset <stephen.rousset@rocketlogix.com>
7                        Dan Eaton <dan.eaton@rocketlogix.com>
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
25#include <linux/version.h>
26#include <linux/module.h>
27#include <linux/slab.h>
28#include <linux/proc_fs.h>
29#include <linux/ioport.h>
30#include <linux/sysctl.h>
31#include <asm/errno.h>
32#include <asm/io.h>
33#include <linux/types.h>
34#include <linux/i2c.h>
35#include "version.h"
36#include "sensors.h"
37#include <linux/init.h>
38
39/* Chip configuration settings.  These should be set to reflect the
40HARDWARE configuration of your chip.  By default (read: when all of
41these are left commented out), this driver assumes that the
42configuration is the same as National's defaults for the Channel Mode
43register.
44
45Set to '1' the appropriate defines, as nessesary:
46
47 - External temp sensors 2 (possible second CPU temp)
48   This will disable the 2.5V and Vccp2 readings.
49   Ironically, National decided that you can read the
50   temperature of a second CPU or it's core voltage,
51   but not both!  Comment out if FAULT is reported.  */
52
53/* #define LM87_EXT2 1 */
54
55/* Aux analog input. When enabled, the Fan 1 reading
56   will be disabled */
57
58/* #define LM87_AIN1 1 */
59
60/* Aux analog input 2. When enabled, the Fan 2 reading
61   will be disabled */
62
63/* #define LM87_AIN2 1 */
64
65/* Internal Vcc is 5V instead of 3.3V */
66
67/* #define LM87_5V_VCC 1 */
68
69/* That's the end of the hardware config defines.  I would have made
70   them insmod params, but it would be too much work. ;') */
71
72
73#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,2,18)) || \
74    (LINUX_VERSION_CODE == KERNEL_VERSION(2,3,0))
75#define init_MUTEX(s) do { *(s) = MUTEX; } while(0)
76#endif
77
78#if LINUX_VERSION_CODE < KERNEL_VERSION(2,3,13)
79#define THIS_MODULE NULL
80#endif
81
82/* Addresses to scan */
83static unsigned short normal_i2c[] = { SENSORS_I2C_END };
84static unsigned short normal_i2c_range[] = { 0x2c, 0x2e, SENSORS_I2C_END };
85static unsigned int normal_isa[] = { SENSORS_ISA_END };
86static unsigned int normal_isa_range[] = { SENSORS_ISA_END };
87
88/* Insmod parameters */
89SENSORS_INSMOD_1(lm87);
90
91/* The following is the calculation for the register offset
92 * for the monitored items minimum and maximum locations.
93 */
94#define LM87_REG_IN_MAX(nr) (0x2b + ((nr) * 2))
95#define LM87_REG_IN_MIN(nr) (0x2c + ((nr) * 2))
96#define LM87_REG_IN(nr) (0x20 + (nr))
97
98/* Initial limits */
99
100/*
101 * LM87 register definition
102 *
103 */
104
105      /* The LM87 registers */
106#define LM87_INT_TEMP_HI_LIMIT_LOCKABLE  0x13
107#define LM87_EXT_TEMP_HI_LIMIT_LOCKABLE  0x14
108#define LM87_REG_TEST                    0x15
109#define LM87_REG_CHANNEL_MODE            0x16
110#define LM87_REG_INT_TEMP_HI_LIMIT       0x17
111#define LM87_REG_EXT_TEMP_HI_LIMIT       0x18
112#define LM87_REG_ANALOG_OUT              0x19
113
114      /* These are all read-only */
115#define LM87_REG_2_5V_EXT_TEMP_2         0x20
116#define LM87_REG_VCCP1                   0x21
117#define LM87_REG_3_3V                    0x22 
118#define LM87_REG_5V                      0x23
119#define LM87_REG_12V                     0x24
120#define LM87_REG_VCCP2                   0x25
121#define LM87_REG_EXT_TEMP_1              0x26
122#define LM87_REG_INT_TEMP                0x27  /* LM87 temp. */
123#define LM87_REG_FAN1_AIN1               0x28
124#define LM87_REG_FAN2_AIN2               0x29
125
126/* These are read/write */
127#define LM87_REG_AIN1_LOW                0x1A
128#define LM87_REG_AIN2_LOW                0x1B
129#define LM87_REG_2_5V_EXT_TEMP_2_HIGH    0x2B 
130#define LM87_REG_2_5V_EXT_TEMP_2_LOW     0x2C 
131#define LM87_REG_VCCP1_HIGH              0x2D 
132#define LM87_REG_VCCP1_LOW               0x2E 
133#define LM87_REG_3_3V_HIGH               0x2F
134#define LM87_REG_3_3V_LOW                0x30
135#define LM87_REG_5V_HIGH                 0x31
136#define LM87_REG_5V_LOW                  0x32
137#define LM87_REG_12V_HIGH                0x33
138#define LM87_REG_12V_LOW                 0x34
139#define LM87_REG_VCCP2_HIGH              0x35
140#define LM87_REG_VCCP2_LOW               0x36
141#define LM87_REG_EXT_TEMP_1_HIGH         0x37   
142#define LM87_REG_EXT_TEMP_1_LOW          0x38 
143#define LM87_REG_INT_TEMP_HIGH           0x39 
144#define LM87_REG_INT_TEMP_LOW            0x3A 
145#define LM87_REG_FAN1_AIN1_LIMIT         0x3B
146#define LM87_REG_FAN2_AIN2_LIMIT         0x3C
147#define LM87_REG_COMPANY_ID              0x3E
148#define LM87_REG_DIE_REV                 0x3F
149
150#define LM87_REG_CONFIG                  0x40
151#define LM87_REG_INT1_STAT               0x41
152#define LM87_REG_INT2_STAT               0x42
153#define LM87_REG_INT1_MASK               0x43
154#define LM87_REG_INT2_MASK               0x44
155#define LM87_REG_CHASSIS_CLEAR           0x46
156#define LM87_REG_VID_FAN_DIV             0x47
157#define LM87_REG_VID4                    0x49
158#define LM87_REG_CONFIG_2                0x4A
159#define LM87_REG_INTRPT_STATUS_1_MIRROR  0x4C
160#define LM87_REG_INTRPT_STATUS_2_MIRROR  0x4D
161#define LM87_REG_SMBALERT_NUM_ENABLE     0x80
162
163
164
165/* Conversions. Rounding and limit checking is only done on the TO_REG
166   variants. Note that you should be a bit careful with which arguments
167   these macros are called: arguments may be evaluated more than once.
168   Fixing this is just not worth it. */
169
170#define IN_TO_REG(val,nr) (SENSORS_LIMIT(((val) & 0xff),0,255))
171#define IN_FROM_REG(val,nr) (val)
172
173extern inline u8 FAN_TO_REG(long rpm, int div)
174{
175        if (rpm == 0)
176                return 255;
177        rpm = SENSORS_LIMIT(rpm, 1, 1000000);
178        return SENSORS_LIMIT((1350000 + rpm * div / 2) / (rpm * div), 1,
179                             254);
180}
181
182#define FAN_FROM_REG(val,div) ((val)==0?-1:\
183                               (val)==255?0:1350000/((div)*(val)))
184
185#define TEMP_FROM_REG(temp)  (temp * 10)
186
187#define TEMP_LIMIT_FROM_REG(val) (((val)>0x80?(val)-0x100:(val))*10)
188
189#define TEMP_LIMIT_TO_REG(val) SENSORS_LIMIT(((val)<0?(((val)-5)/10):\
190                                                      ((val)+5)/10),0,255)
191#if 0
192#define TEMP_FROM_REG(temp) \
193   ((temp)<256?((((temp)&0x1fe) >> 1) * 10)      + ((temp) & 1) * 5:  \
194               ((((temp)&0x1fe) >> 1) -255) * 10 - ((temp) & 1) * 5)  \
195
196#define TEMP_LIMIT_FROM_REG(val) (val)
197
198#define TEMP_LIMIT_TO_REG(val) SENSORS_LIMIT((val),0,255)
199#endif
200
201
202#define ALARMS_FROM_REG(val) (val)
203
204#define DIV_FROM_REG(val) (1 << (val))
205#define DIV_TO_REG(val) ((val)==1?0:((val)==8?3:((val)==4?2:1)))
206
207#define VID_FROM_REG(val) ((val)==0x1f?0:(val)>=0x10?510-(val)*10:\
208                           205-(val)*5)
209                           
210#define LM87_INIT_FAN_MIN 3000
211
212#define LM87_INIT_EXT_TEMP_MAX 600
213#define LM87_INIT_EXT_TEMP_MIN 100
214#define LM87_INIT_INT_TEMP_MAX 600
215#define LM87_INIT_INT_TEMP_MIN 100
216
217#ifdef MODULE
218extern int init_module(void);
219extern int cleanup_module(void);
220#endif                          /* MODULE */
221
222/* For each registered LM87, we need to keep some data in memory. That
223   data is pointed to by LM87_list[NR]->data. The structure itself is
224   dynamically allocated, at the same time when a new LM87 client is
225   allocated. */
226struct lm87_data {
227        int sysctl_id;
228        enum chips type;
229
230        struct semaphore update_lock;
231        char valid;             /* !=0 if following fields are valid */
232        unsigned long last_updated;     /* In jiffies */
233
234        u8  in[6];              /* Register value */
235        u8  in_max[6];          /* Register value */
236        u8  in_min[6];          /* Register value */
237        u8  ain1;               /* Register value */
238        u8  ain1_min;           /* Register value */
239        u8  ain1_max;           /* Register value */
240        u8  ain2;               /* Register value */
241        u8  ain2_min;           /* Register value */
242        u8  ain2_max;           /* Register value */
243        u8  fan;                /* Register value */
244        u8  fan_min;            /* Register value */
245        u8  fan_div;            /* Register encoding, shifted right */
246        u8  fan2;               /* Register value */
247        u8  fan2_min;           /* Register value */
248        u8  fan2_div;           /* Register encoding, shifted right */
249        int ext2_temp;          /* Temp, shifted right */
250        int ext_temp;           /* Temp, shifted right */
251        int int_temp;           /* Temp, shifted right */
252        u8  ext_temp_max;       /* Register value */
253        u8  ext_temp_min;       /* Register value */
254        u8  ext2_temp_max;      /* Register value */
255        u8  ext2_temp_min;      /* Register value */
256        u8  int_temp_max;       /* Register value */
257        u8  int_temp_min;       /* Register value */
258        u16 alarms;             /* Register encoding, combined */
259        u8  analog_out;         /* Register value */
260        u8  vid;                /* Register value combined */
261};
262
263#ifdef MODULE
264static
265#else
266extern
267#endif
268int __init sensors_lm87_init(void);
269static int __init lm87_cleanup(void);
270
271static int lm87_attach_adapter(struct i2c_adapter *adapter);
272static int lm87_detect(struct i2c_adapter *adapter, int address,
273                          unsigned short flags, int kind);
274static int lm87_detach_client(struct i2c_client *client);
275static int lm87_command(struct i2c_client *client, unsigned int cmd,
276                           void *arg);
277static void lm87_inc_use(struct i2c_client *client);
278static void lm87_dec_use(struct i2c_client *client);
279
280static int lm87_read_value(struct i2c_client *client, u8 register);
281static int lm87_write_value(struct i2c_client *client, u8 register,
282                               u8 value);
283static void lm87_update_client(struct i2c_client *client);
284static void lm87_init_client(struct i2c_client *client);
285
286
287static void lm87_in(struct i2c_client *client, int operation,
288                       int ctl_name, int *nrels_mag, long *results);
289#if defined (LM87_AIN1) || defined (LM87_AIN2)
290static void lm87_ain(struct i2c_client *client, int operation,
291                       int ctl_name, int *nrels_mag, long *results);
292#endif
293static void lm87_fan(struct i2c_client *client, int operation,
294                        int ctl_name, int *nrels_mag, long *results);
295static void lm87_temp(struct i2c_client *client, int operation,
296                         int ctl_name, int *nrels_mag, long *results);
297static void lm87_alarms(struct i2c_client *client, int operation,
298                           int ctl_name, int *nrels_mag, long *results);
299static void lm87_fan_div(struct i2c_client *client, int operation,
300                            int ctl_name, int *nrels_mag, long *results);
301static void lm87_analog_out(struct i2c_client *client, int operation,
302                               int ctl_name, int *nrels_mag,
303                               long *results);
304static void lm87_vid(struct i2c_client *client, int operation,
305                        int ctl_name, int *nrels_mag, long *results);
306
307/* I choose here for semi-static LM87 allocation. Complete dynamic
308   allocation could also be used; the code needed for this would probably
309   take more memory than the datastructure takes now. */
310static int lm87_id = 0;
311
312static struct i2c_driver LM87_driver = {
313        /* name */          "LM87 sensor driver",
314        /* id */             I2C_DRIVERID_LM87,
315        /* flags */          I2C_DF_NOTIFY,
316        /* attach_adapter */ &lm87_attach_adapter,
317        /* detach_client */  &lm87_detach_client,
318        /* command */        &lm87_command,
319        /* inc_use */        &lm87_inc_use,
320        /* dec_use */        &lm87_dec_use
321};
322
323/* Used by LM87_init/cleanup */
324static int __initdata lm87_initialized = 0;
325
326/* The /proc/sys entries */
327/* These files are created for each detected LM87. This is just a template;
328   though at first sight, you might think we could use a statically
329   allocated list, we need some way to get back to the parent - which
330   is done through one of the 'extra' fields which are initialized
331   when a new copy is allocated. */
332
333static ctl_table LM87_dir_table_template[] = {
334#ifdef LM87_AIN1
335        {LM87_SYSCTL_AIN1, "ain1", NULL, 0, 0644, NULL, &i2c_proc_real,
336          &i2c_sysctl_real, NULL, &lm87_ain},
337#endif
338#ifdef LM87_AIN2
339        {LM87_SYSCTL_AIN2, "ain2", NULL, 0, 0644, NULL, &i2c_proc_real,
340          &i2c_sysctl_real, NULL, &lm87_ain},
341#endif
342#ifndef LM87_EXT2
343        {LM87_SYSCTL_IN0, "in0", NULL, 0, 0644, NULL, &i2c_proc_real,
344          &i2c_sysctl_real, NULL, &lm87_in},
345        {LM87_SYSCTL_IN5, "in5", NULL, 0, 0644, NULL, &i2c_proc_real,
346          &i2c_sysctl_real, NULL, &lm87_in},
347#endif
348        {LM87_SYSCTL_IN1, "in1", NULL, 0, 0644, NULL, &i2c_proc_real,
349          &i2c_sysctl_real, NULL, &lm87_in},
350        {LM87_SYSCTL_IN2, "in2", NULL, 0, 0644, NULL, &i2c_proc_real,
351          &i2c_sysctl_real, NULL, &lm87_in},
352        {LM87_SYSCTL_IN3, "in3", NULL, 0, 0644, NULL, &i2c_proc_real,
353          &i2c_sysctl_real, NULL, &lm87_in},
354        {LM87_SYSCTL_IN4, "in4", NULL, 0, 0644, NULL, &i2c_proc_real,
355          &i2c_sysctl_real, NULL, &lm87_in},
356#ifndef LM87_AIN1
357        {LM87_SYSCTL_FAN1, "fan", NULL, 0, 0644, NULL, &i2c_proc_real,
358          &i2c_sysctl_real, NULL, &lm87_fan},
359        {LM87_SYSCTL_FAN_DIV, "fan_div", NULL, 0, 0644, NULL, &i2c_proc_real,
360          &i2c_sysctl_real, NULL, &lm87_fan_div},
361#define LM87_FANDIV_FLAG
362#endif
363#ifndef LM87_AIN2
364        {LM87_SYSCTL_FAN2, "fan2", NULL, 0, 0644, NULL, &i2c_proc_real,
365          &i2c_sysctl_real, NULL, &lm87_fan},
366#ifndef LM87_FANDIV_FLAG
367        {LM87_SYSCTL_FAN_DIV, "fan_div", NULL, 0, 0644, NULL, &i2c_proc_real,
368          &i2c_sysctl_real, NULL, &lm87_fan_div},
369#endif /* LM87_FANDIV_FLAG */
370#endif /* LM87_AIN2 */
371#ifdef LM87_EXT2
372        {LM87_SYSCTL_TEMP3, "temp3", NULL, 0, 0644, NULL, &i2c_proc_real,
373          &i2c_sysctl_real, NULL, &lm87_temp},
374#endif
375        {LM87_SYSCTL_TEMP2, "temp2", NULL, 0, 0644, NULL, &i2c_proc_real,
376          &i2c_sysctl_real, NULL, &lm87_temp},
377        {LM87_SYSCTL_TEMP1, "temp1", NULL, 0, 0644, NULL, &i2c_proc_real,
378          &i2c_sysctl_real, NULL, &lm87_temp},
379        {LM87_SYSCTL_ALARMS, "alarms", NULL, 0, 0444, NULL, &i2c_proc_real,
380          &i2c_sysctl_real, NULL, &lm87_alarms},
381        {LM87_SYSCTL_ANALOG_OUT, "analog_out", NULL, 0, 0644, NULL, &i2c_proc_real,
382          &i2c_sysctl_real, NULL, &lm87_analog_out},
383        {LM87_SYSCTL_VID, "vid", NULL, 0, 0444, NULL, &i2c_proc_real,
384          &i2c_sysctl_real, NULL, &lm87_vid},
385        {0}
386};
387
388int lm87_attach_adapter(struct i2c_adapter *adapter)
389{
390        int error;
391        struct i2c_client_address_data  lm87_client_data;
392
393        lm87_client_data.normal_i2c       = addr_data.normal_i2c;
394        lm87_client_data.normal_i2c_range = addr_data.normal_i2c_range;
395        lm87_client_data.probe            = addr_data.probe;
396        lm87_client_data.probe_range      = addr_data.probe_range;
397        lm87_client_data.ignore           = addr_data.ignore;
398        lm87_client_data.ignore_range     = addr_data.ignore_range;
399        lm87_client_data.force            = addr_data.forces->force;
400
401        error = i2c_probe(adapter, &lm87_client_data, lm87_detect);
402        i2c_detect(adapter, &addr_data, lm87_detect);
403
404        return error;
405}
406
407static int lm87_detect(struct i2c_adapter *adapter, int address,
408                          unsigned short flags, int kind)
409{
410        int i;
411        struct i2c_client *new_client;
412        struct lm87_data *data;
413        int err = 0;
414        const char *type_name = "";
415        const char *client_name = "";
416
417        if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA))
418                goto ERROR0;
419
420        /* OK. For now, we presume we have a valid client. We now create the
421           client structure, even though we cannot fill it completely yet.
422           But it allows us to access LM87_{read,write}_value. */
423
424        if (!(new_client = kmalloc(sizeof(struct i2c_client) +
425                                   sizeof(struct lm87_data),
426                                   GFP_KERNEL))) {
427                err = -ENOMEM;
428                goto ERROR0;
429        }
430
431        data = (struct lm87_data *) (new_client + 1);
432        new_client->addr = address;
433        new_client->data = data;
434        new_client->adapter = adapter;
435        new_client->driver = &LM87_driver;
436        new_client->flags = 0;
437
438        /* Now, we do the remaining detection. */
439
440        if (kind < 0) {
441                if (((lm87_read_value(new_client, LM87_REG_CONFIG) & 0x80)
442                     != 0x00) ||
443                    (lm87_read_value(new_client, LM87_REG_COMPANY_ID) != 0x02))
444               goto ERROR1;
445        }
446
447        /* Fill in the remaining client fields and put into the global list */
448        type_name = "lm87";
449        client_name = "LM87 chip";
450        strcpy(new_client->name, client_name);
451        data->type = kind;
452
453        new_client->id = lm87_id++;
454        data->valid = 0;
455        init_MUTEX(&data->update_lock);
456
457        /* Tell the I2C layer a new client has arrived */
458        if ((err = i2c_attach_client(new_client)))
459                goto ERROR3;
460
461        /* Register a new directory entry with module sensors */
462        if ((i = i2c_register_entry(new_client,
463                                        type_name,
464                                        LM87_dir_table_template,
465                                        THIS_MODULE)) < 0) {
466                err = i;
467                goto ERROR4;
468        }
469        data->sysctl_id = i;
470
471        /* Initialize the LM87 chip */
472        lm87_init_client(new_client);
473        return 0;
474
475/* OK, this is not exactly good programming practice, usually. But it is
476   very code-efficient in this case. */
477
478      ERROR4:
479        i2c_detach_client(new_client);
480      ERROR3:
481      ERROR1:
482        kfree(new_client);
483      ERROR0:
484        return err;
485}
486
487int lm87_detach_client(struct i2c_client *client)
488{
489        int err;
490
491        i2c_deregister_entry(((struct lm87_data *) (client->data))->
492                                 sysctl_id);
493
494        if ((err = i2c_detach_client(client))) {
495                printk
496                    ("lm87.o: Client deregistration failed, client not detached.\n");
497                return err;
498        }
499
500        kfree(client);
501
502        return 0;
503
504}
505
506/* No commands defined yet */
507int lm87_command(struct i2c_client *client, unsigned int cmd, void *arg)
508{
509        return 0;
510}
511
512void lm87_inc_use(struct i2c_client *client)
513{
514#ifdef MODULE
515        MOD_INC_USE_COUNT;
516#endif
517}
518
519void lm87_dec_use(struct i2c_client *client)
520{
521#ifdef MODULE
522        MOD_DEC_USE_COUNT;
523#endif
524}
525
526int lm87_read_value(struct i2c_client *client, u8 reg)
527{
528        return 0xFF & i2c_smbus_read_byte_data(client, reg);
529}
530
531int lm87_write_value(struct i2c_client *client, u8 reg, u8 value)
532{
533        return i2c_smbus_write_byte_data(client, reg, value);
534}
535
536/* Called when we have found a new LM87. It should set limits, etc. */
537void lm87_init_client(struct i2c_client *client)
538{
539        int vid;
540        u8 v;
541
542        /* Reset all except Watchdog values and last conversion values
543           This sets fan-divs to 2, among others. This makes most other
544           initializations unnecessary */
545        lm87_write_value(client, LM87_REG_CONFIG, 0x80);
546
547        /* Setup Channel Mode register for configuration of monitoring
548         * Default is 00000000b
549         *      bit 0 - Configures Fan 1/AIN 1 input (1 = AIN)
550         *      bit 1 - Configures Fan 2/AIN 2 input (1 = AIN)
551         *      bit 2 - Configures 2.5V&Vccp2/D2 input (1 = 2nd Therm.)
552         *      bit 3 - Configures Vcc for 5V/3.3V reading (0 = 3.3V)
553         *      bit 4 - Configures IRQ0 Enable if = 1
554         *      bit 5 - Configures IRQ1 Enable if = 1
555         *      bit 6 - Configures IRQ2 Enable if = 1
556         *      bit 7 - Configures VID/IRQ input as interrupts if = 1
557         */
558
559/* I know, not clean, but it works. :'p */
560        lm87_write_value(client, LM87_REG_CHANNEL_MODE,
561#ifdef LM87_AIN1
562 0x01
563#else
5640
565#endif
566 | 
567#ifdef LM87_AIN2
568 0x02
569#else
5700
571#endif
572 |
573#ifdef LM87_EXT2
574 0x04
575#else
5760
577#endif
578 | 
579#ifdef LM87_5V_VCC
5800x08
581#else   
5820
583#endif
584        );
585
586        /* Set IN (voltage) initial limits to sane values  +/- 5% */
587        lm87_write_value(client, LM87_REG_IN_MIN(0),182);
588        lm87_write_value(client, LM87_REG_IN_MAX(0),202);
589        lm87_write_value(client, LM87_REG_IN_MIN(2),182);
590        lm87_write_value(client, LM87_REG_IN_MAX(2),202);
591        lm87_write_value(client, LM87_REG_IN_MIN(3),182);
592        lm87_write_value(client, LM87_REG_IN_MAX(3),202);
593        lm87_write_value(client, LM87_REG_IN_MIN(4),182);
594        lm87_write_value(client, LM87_REG_IN_MAX(4),202);
595
596        /* Set CPU core voltage limits relative to vid readings +/- 5% */
597        v = (lm87_read_value(client, LM87_REG_VID_FAN_DIV) & 0x0f)
598                    | ((lm87_read_value(client, LM87_REG_VID4) & 0x01)
599                    << 4 );
600        vid = VID_FROM_REG(v);
601        v = vid * 95 * 192 / 27000;
602        lm87_write_value(client, LM87_REG_IN_MIN(1), v);
603        lm87_write_value(client, LM87_REG_IN_MIN(5), v);
604        v = vid * 105 * 192 / 27000;
605        lm87_write_value(client, LM87_REG_IN_MAX(1), v);
606        lm87_write_value(client, LM87_REG_IN_MAX(5), v);
607
608        /* Set Temp initial limits to sane values */
609        lm87_write_value(client, LM87_REG_EXT_TEMP_1_HIGH,
610                            TEMP_LIMIT_TO_REG(LM87_INIT_EXT_TEMP_MAX));
611        lm87_write_value(client, LM87_REG_EXT_TEMP_1_LOW,
612                            TEMP_LIMIT_TO_REG(LM87_INIT_EXT_TEMP_MIN));
613#ifdef LM87_EXT2
614        lm87_write_value(client, LM87_REG_2_5V_EXT_TEMP_2_HIGH,
615                            TEMP_LIMIT_TO_REG(LM87_INIT_EXT_TEMP_MAX));
616        lm87_write_value(client, LM87_REG_2_5V_EXT_TEMP_2_LOW,
617                            TEMP_LIMIT_TO_REG(LM87_INIT_EXT_TEMP_MIN));
618#endif
619        lm87_write_value(client, LM87_REG_INT_TEMP_HIGH,
620                            TEMP_LIMIT_TO_REG(LM87_INIT_INT_TEMP_MAX));
621        lm87_write_value(client, LM87_REG_INT_TEMP_LOW,
622                            TEMP_LIMIT_TO_REG(LM87_INIT_INT_TEMP_MIN));
623
624#ifndef LM87_AIN1
625        lm87_write_value(client, LM87_REG_FAN1_AIN1_LIMIT,
626                            FAN_TO_REG(LM87_INIT_FAN_MIN, 2));
627#endif
628#ifndef LM87_AIN2
629        lm87_write_value(client, LM87_REG_FAN2_AIN2_LIMIT,
630                            FAN_TO_REG(LM87_INIT_FAN_MIN, 2));
631#endif
632
633        /* Start monitoring */
634        lm87_write_value(client, LM87_REG_CONFIG, 0x01);
635}
636
637void lm87_update_client(struct i2c_client *client)
638{
639        struct lm87_data *data = client->data;
640        int i;
641
642        down(&data->update_lock);
643
644        if ((jiffies - data->last_updated > HZ) ||  /* 1 sec cache */
645            (jiffies < data->last_updated)      || 
646             !data->valid) {
647                for (i = 0; i <= 5; i++) { 
648                 data->in[i] = 
649                    lm87_read_value(client,LM87_REG_IN(i));
650                 data->in_min[i] = 
651                    lm87_read_value(client,LM87_REG_IN_MIN(i));
652                 data->in_max[i] = 
653                    lm87_read_value(client,LM87_REG_IN_MAX(i));
654                }
655                 data->ain1 = 
656                    lm87_read_value(client,LM87_REG_FAN1_AIN1);
657                 data->ain1_min =
658                    lm87_read_value(client,LM87_REG_AIN1_LOW);
659                 data->ain1_max =
660                    lm87_read_value(client,LM87_REG_FAN1_AIN1_LIMIT);
661                 data->ain2 = 
662                    lm87_read_value(client,LM87_REG_FAN2_AIN2);
663                 data->ain2_min =
664                    lm87_read_value(client,LM87_REG_AIN2_LOW);
665                 data->ain2_max =
666                    lm87_read_value(client,LM87_REG_FAN2_AIN2_LIMIT);
667
668                data->fan =
669                    lm87_read_value(client, LM87_REG_FAN1_AIN1);
670                data->fan_min =
671                    lm87_read_value(client, LM87_REG_FAN1_AIN1_LIMIT);
672                data->fan2 =
673                    lm87_read_value(client, LM87_REG_FAN2_AIN2);
674                data->fan2_min =
675                    lm87_read_value(client, LM87_REG_FAN2_AIN2_LIMIT);
676
677                data->ext2_temp =
678                    lm87_read_value(client, LM87_REG_2_5V_EXT_TEMP_2);
679                data->ext_temp =
680                    lm87_read_value(client, LM87_REG_EXT_TEMP_1);
681                data->int_temp =
682                    lm87_read_value(client, LM87_REG_INT_TEMP);
683
684                data->ext2_temp_max =
685                    lm87_read_value(client, LM87_REG_2_5V_EXT_TEMP_2_HIGH);
686                data->ext2_temp_min =
687                    lm87_read_value(client, LM87_REG_2_5V_EXT_TEMP_2_LOW);
688
689                data->ext_temp_max =
690                    lm87_read_value(client, LM87_REG_EXT_TEMP_1_HIGH);
691                data->ext_temp_min =
692                    lm87_read_value(client, LM87_REG_EXT_TEMP_1_LOW);
693
694                data->int_temp_max =
695                    lm87_read_value(client, LM87_REG_INT_TEMP_HIGH);
696                data->int_temp_min =
697                    lm87_read_value(client, LM87_REG_INT_TEMP_LOW);
698
699                i = lm87_read_value(client, LM87_REG_VID_FAN_DIV);
700                data->fan_div = (i >> 4) & 0x03;
701                data->fan2_div = (i >> 6) & 0x03;
702                data->vid = i & 0x0f;
703                data->vid |=
704                    (lm87_read_value(client, LM87_REG_VID4) & 0x01)
705                    << 4;
706                data->alarms =
707                    lm87_read_value(client, LM87_REG_INT1_STAT) +
708                    (lm87_read_value(client, LM87_REG_INT2_STAT) << 8);
709                data->analog_out =
710                    lm87_read_value(client, LM87_REG_ANALOG_OUT);
711                data->last_updated = jiffies;
712                data->valid = 1;
713        }
714        up(&data->update_lock);
715}
716
717
718/* The next few functions are the call-back functions of the /proc/sys and
719   sysctl files. Which function is used is defined in the ctl_table in
720   the extra1 field.
721   Each function must return the magnitude (power of 10 to divide the date
722   with) if it is called with operation==SENSORS_PROC_REAL_INFO. It must
723   put a maximum of *nrels elements in results reflecting the data of this
724   file, and set *nrels to the number it actually put in it, if operation==
725   SENSORS_PROC_REAL_READ. Finally, it must get upto *nrels elements from
726   results and write them to the chip, if operations==SENSORS_PROC_REAL_WRITE.
727   Note that on SENSORS_PROC_REAL_READ, I do not check whether results is
728   large enough (by checking the incoming value of *nrels). This is not very
729   good practice, but as long as you put less than about 5 values in results,
730   you can assume it is large enough. */
731void lm87_in(struct i2c_client *client, int operation, int ctl_name,
732                int *nrels_mag, long *results)
733{
734        long scales[6] = { 250, 270, 
735#ifdef LM87_5V_VCC
736500,
737#else
738330,
739#endif
740                500, 1200, 270 };
741
742        struct lm87_data *data = client->data;
743        int nr = ctl_name - LM87_SYSCTL_IN0;
744
745        if (operation == SENSORS_PROC_REAL_INFO)
746                *nrels_mag = 2;
747        else if (operation == SENSORS_PROC_REAL_READ) {
748                lm87_update_client(client);
749                results[0] =
750                    ((long)data->in_min[nr] * scales[nr]) / 192;
751                results[1] =
752                    ((long)data->in_max[nr] * scales[nr]) / 192;
753                results[2] =
754                    ((long)data->in[nr] * scales[nr]) / 192;
755                *nrels_mag = 3;
756        } else if (operation == SENSORS_PROC_REAL_WRITE) {
757                if (*nrels_mag >= 1) {
758                        data->in_min[nr] =
759                            (results[0] * 192) / scales[nr];
760                        lm87_write_value(client, LM87_REG_IN_MIN(nr),
761                                            data->in_min[nr]);
762                }
763                if (*nrels_mag >= 2) {
764                        data->in_max[nr] =
765                            (results[1] * 192) / scales[nr];
766                        lm87_write_value(client, LM87_REG_IN_MAX(nr),
767                                            data->in_max[nr]);
768                }
769        }
770}
771
772#if defined (LM87_AIN1) || defined (LM87_AIN2)
773void lm87_ain(struct i2c_client *client, int operation, int ctl_name,
774                int *nrels_mag, long *results)
775{
776        struct lm87_data *data = client->data;
777
778        if (operation == SENSORS_PROC_REAL_INFO)
779                *nrels_mag = 0;
780        else if (operation == SENSORS_PROC_REAL_READ) {
781                lm87_update_client(client);
782                if (ctl_name == LM87_SYSCTL_AIN1) {
783                 results[0] = data->ain1_min;
784                 results[1] = data->ain1_max;
785                 results[2] = data->ain1;
786                } else {
787                 results[0] = data->ain2_min;
788                 results[1] = data->ain2_max;
789                 results[2] = data->ain2;
790                }
791                *nrels_mag = 3;
792        } else if (operation == SENSORS_PROC_REAL_WRITE) {
793                if (*nrels_mag >= 1) {
794                 if (ctl_name == LM87_SYSCTL_AIN1) {
795                        data->ain1_min = results[0];
796                        lm87_write_value(client, LM87_REG_AIN1_LOW,
797                                            data->ain1_min);
798                 } else {
799                        data->ain2_min = results[0];
800                        lm87_write_value(client, LM87_REG_AIN2_LOW,
801                                            data->ain2_min);
802                 }
803                }
804                if (*nrels_mag >= 2) {
805                 if (ctl_name == LM87_SYSCTL_AIN1) {
806                        data->ain1_max = results[1];
807                        lm87_write_value(client, LM87_REG_FAN1_AIN1_LIMIT,
808                                            data->ain1_max);
809                 } else {
810                        data->ain2_max = results[1];
811                        lm87_write_value(client, LM87_REG_FAN2_AIN2_LIMIT,
812                                            data->ain2_max);
813                 }
814                }
815        }
816}
817#endif
818
819void lm87_fan(struct i2c_client *client, int operation, int ctl_name,
820                 int *nrels_mag, long *results)
821{
822        struct lm87_data *data = client->data;
823
824        if (operation == SENSORS_PROC_REAL_INFO)
825                *nrels_mag = 0;
826        else if (operation == SENSORS_PROC_REAL_READ) {
827                lm87_update_client(client);
828                if (ctl_name == LM87_SYSCTL_FAN1) {
829                 results[0] = FAN_FROM_REG(data->fan_min,
830                                          DIV_FROM_REG(data->fan_div));
831                 results[1] = FAN_FROM_REG(data->fan, 
832                                         DIV_FROM_REG(data->fan_div));
833                } else {
834                 results[0] = FAN_FROM_REG(data->fan2_min,
835                                          DIV_FROM_REG(data->fan2_div));
836                 results[1] = FAN_FROM_REG(data->fan2, 
837                                         DIV_FROM_REG(data->fan2_div));
838                }
839                *nrels_mag = 2;
840        } else if (operation == SENSORS_PROC_REAL_WRITE) {
841                if (*nrels_mag >= 0) {
842                        if (ctl_name == LM87_SYSCTL_FAN1) {
843                         data->fan_min = FAN_TO_REG(results[0],
844                                                   DIV_FROM_REG
845                                                   (data->fan_div));
846                         lm87_write_value(client, LM87_REG_FAN1_AIN1_LIMIT,
847                                            data->fan_min);
848                        } else {
849                         data->fan2_min = FAN_TO_REG(results[0],
850                                                   DIV_FROM_REG
851                                                   (data->fan2_div));
852                         lm87_write_value(client, LM87_REG_FAN2_AIN2_LIMIT,
853                                            data->fan2_min);
854                        }
855                }
856        }
857}
858
859
860void lm87_temp(struct i2c_client *client, int operation, int ctl_name,
861                  int *nrels_mag, long *results)
862{
863        struct lm87_data *data = client->data;
864
865        if (operation == SENSORS_PROC_REAL_INFO)
866                *nrels_mag = 1;
867        else if (operation == SENSORS_PROC_REAL_READ) 
868        {
869           lm87_update_client(client);
870
871           /* find out which temp. is being requested */
872           if (ctl_name == LM87_SYSCTL_TEMP3) 
873           {
874                results[0] = TEMP_LIMIT_FROM_REG(data->ext2_temp_max);
875                results[1] = TEMP_LIMIT_FROM_REG(data->ext2_temp_min);
876                results[2] = TEMP_FROM_REG(data->ext2_temp);
877           }
878           else if(ctl_name == LM87_SYSCTL_TEMP2)
879           {
880                results[0] = TEMP_LIMIT_FROM_REG(data->ext_temp_max);
881                results[1] = TEMP_LIMIT_FROM_REG(data->ext_temp_min);
882                results[2] = TEMP_FROM_REG(data->ext_temp);
883           }
884           else if(ctl_name == LM87_SYSCTL_TEMP1)
885           {
886                results[0] = TEMP_LIMIT_FROM_REG(data->int_temp_max);
887                results[1] = TEMP_LIMIT_FROM_REG(data->int_temp_min);
888                results[2] = TEMP_FROM_REG(data->int_temp);
889           }
890           *nrels_mag = 3;
891        } else if (operation == SENSORS_PROC_REAL_WRITE) {
892                if (*nrels_mag >= 1) {
893                   if (ctl_name == LM87_SYSCTL_TEMP3) {
894                        data->ext2_temp_max = TEMP_LIMIT_TO_REG(results[0]);
895                        lm87_write_value(client, LM87_REG_2_5V_EXT_TEMP_2_HIGH,
896                                            data->ext2_temp_max);
897                   }
898                   if (ctl_name == LM87_SYSCTL_TEMP2) {
899                        data->ext_temp_max = TEMP_LIMIT_TO_REG(results[0]);
900                        lm87_write_value(client, LM87_REG_EXT_TEMP_1_HIGH,
901                                            data->int_temp_max);
902                   }
903                   if (ctl_name == LM87_SYSCTL_TEMP1) {
904                        data->int_temp_max = TEMP_LIMIT_TO_REG(results[0]);
905                        lm87_write_value(client, LM87_REG_INT_TEMP_HIGH,
906                                            data->int_temp_max);
907                   }
908                }
909                if (*nrels_mag >= 2) {
910                   if (ctl_name == LM87_SYSCTL_TEMP3) {
911                        data->ext2_temp_min = TEMP_LIMIT_TO_REG(results[1]);
912                        lm87_write_value(client, LM87_REG_2_5V_EXT_TEMP_2_LOW,
913                                            data->ext2_temp_min);
914                   }
915                   if (ctl_name == LM87_SYSCTL_TEMP2) {
916                        data->ext_temp_min = TEMP_LIMIT_TO_REG(results[1]);
917                        lm87_write_value(client, LM87_REG_EXT_TEMP_1_LOW,
918                                            data->int_temp_min);
919                   }
920                   if (ctl_name == LM87_SYSCTL_TEMP1) {
921                        data->int_temp_min = TEMP_LIMIT_TO_REG(results[1]);
922                        lm87_write_value(client, LM87_REG_INT_TEMP_LOW,
923                                            data->int_temp_min);
924                   }
925                }
926        }
927}
928
929void lm87_alarms(struct i2c_client *client, int operation, int ctl_name,
930                    int *nrels_mag, long *results)
931{
932        struct lm87_data *data = client->data;
933        if (operation == SENSORS_PROC_REAL_INFO)
934                *nrels_mag = 0;
935        else if (operation == SENSORS_PROC_REAL_READ) {
936                lm87_update_client(client);
937                results[0] = ALARMS_FROM_REG(data->alarms);
938                *nrels_mag = 1;
939        }
940}
941
942void lm87_fan_div(struct i2c_client *client, int operation,
943                     int ctl_name, int *nrels_mag, long *results)
944{
945/* This gets a little hairy depending on the hardware config */
946
947        struct lm87_data *data = client->data;
948        int old;
949
950        if (operation == SENSORS_PROC_REAL_INFO)
951                *nrels_mag = 0;
952        else if (operation == SENSORS_PROC_REAL_READ) {
953                lm87_update_client(client);
954#ifndef LM87_AIN1
955                results[0] = DIV_FROM_REG(data->fan_div);
956# ifndef LM87_AIN2
957                results[1] = DIV_FROM_REG(data->fan2_div);
958                *nrels_mag = 2;
959# else
960                *nrels_mag = 1;
961# endif
962#else /* Must be referring to fan 2 */
963                results[0] = DIV_FROM_REG(data->fan2_div);
964                *nrels_mag = 1;
965#endif
966        } else if (operation == SENSORS_PROC_REAL_WRITE) {
967                old = lm87_read_value(client, LM87_REG_VID_FAN_DIV);
968/* Note: it's OK to change fan2 div even if fan2 isn't enabled */
969#ifndef LM87_AIN1
970                if (*nrels_mag >= 2) {
971                        data->fan2_div = DIV_TO_REG(results[1]);
972                        old = (old & 0x3f) | (data->fan2_div << 6);
973                }
974                if (*nrels_mag >= 1) {
975                        data->fan_div = DIV_TO_REG(results[0]);
976                        old = (old & 0xcf) | (data->fan_div << 4);
977                        lm87_write_value(client, LM87_REG_VID_FAN_DIV, old);
978                }
979#else /* Must be referring to fan 2 */
980                if (*nrels_mag >= 1) {
981                        data->fan2_div = DIV_TO_REG(results[0]);
982                        old = (old & 0xcf) | (data->fan2_div << 6);
983                        lm87_write_value(client, LM87_REG_VID_FAN_DIV, old);
984                }
985#endif
986        }
987}
988
989void lm87_analog_out(struct i2c_client *client, int operation,
990                        int ctl_name, int *nrels_mag, long *results)
991{
992        struct lm87_data *data = client->data;
993
994        if (operation == SENSORS_PROC_REAL_INFO)
995                *nrels_mag = 0;
996        else if (operation == SENSORS_PROC_REAL_READ) {
997                lm87_update_client(client);
998                results[0] = data->analog_out;
999                *nrels_mag = 1;
1000        } else if (operation == SENSORS_PROC_REAL_WRITE) {
1001                if (*nrels_mag >= 1) {
1002                        data->analog_out = results[0];
1003                        lm87_write_value(client, LM87_REG_ANALOG_OUT,
1004                                            data->analog_out);
1005                }
1006        }
1007}
1008
1009void lm87_vid(struct i2c_client *client, int operation, int ctl_name,
1010                 int *nrels_mag, long *results)
1011{
1012        struct lm87_data *data = client->data;
1013
1014        if (operation == SENSORS_PROC_REAL_INFO)
1015                *nrels_mag = 2;
1016        else if (operation == SENSORS_PROC_REAL_READ) {
1017                lm87_update_client(client);
1018                results[0] = VID_FROM_REG(data->vid);
1019        *nrels_mag = 1;
1020        }
1021}
1022
1023int __init sensors_lm87_init(void)
1024{
1025        int res;
1026
1027        printk("lm87.o version %s (%s)\n", LM_VERSION, LM_DATE);
1028        lm87_initialized = 0;
1029
1030        if ((res = i2c_add_driver(&LM87_driver))) {
1031                printk
1032                    ("lm87.o: Driver registration failed, module not inserted.\n");
1033                lm87_cleanup();
1034                return res;
1035        }
1036        lm87_initialized++;
1037        return 0;
1038}
1039
1040int __init lm87_cleanup(void)
1041{
1042        int res;
1043
1044        if (lm87_initialized >= 1) {
1045                if ((res = i2c_del_driver(&LM87_driver))) {
1046                        printk
1047                            ("lm87.o: Driver deregistration failed, module not removed.\n");
1048                        return res;
1049                }
1050                lm87_initialized--;
1051        }
1052        return 0;
1053}
1054
1055EXPORT_NO_SYMBOLS;
1056
1057#ifdef MODULE
1058#ifdef MODULE_LICENSE
1059MODULE_LICENSE("GPL");
1060#endif
1061
1062MODULE_AUTHOR
1063    ("Frodo Looijaard <frodol@dds.nl>,
1064      Philip Edelbrock <phil@netroedge.com>, 
1065      Mark Studebaker <mdsxyz123@yahoo.com>,
1066      and Stephen Rousset <stephen.rousset@rocketlogix.com>");
1067
1068MODULE_DESCRIPTION("LM87 driver");
1069
1070int init_module(void)
1071{
1072        return sensors_lm87_init();
1073}
1074
1075int cleanup_module(void)
1076{
1077        return lm87_cleanup();
1078}
1079
1080#endif                          /* MODULE */
Note: See TracBrowser for help on using the browser.