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

Revision 1698, 32.0 KB (checked in by kmalkki, 12 years ago)

(Kyösti) some cleanups for 2.4+

Module refcounting using .owner, removing of inc/dec_use.
These require (yet unreleased) i2c 2.8.0+.

Named initializers everywhere. Unified namespace.

Cleanup for 2.5, remove EXPORT_NO_SYMBOLS, declare everything
static. Apply initcalls.

PCI device registration changes for busses started, replicating
from i2c-amd*. While everything does compile, nothing really
works. Well, maybe i2c-amd* ported back from 2.5 tree.

After updating your work directory, run

> cvs diff -u -r LAST-PRE-2-8-I2C > lm-2.8-patches-1

BEWARE: I have not even insmoded any of these yet.

To compile, you need i2c from cvs too.
For 2.4 kernel :

> cvs co -r lk2-4 i2c

For 2.5 kernel :

> cvs co i2c

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