root/lm-sensors/trunk/kernel/chips/lm80.c @ 1015

Revision 1015, 23.0 KB (checked in by mds, 14 years ago)

Disable sensors.c and i2c-isa.h in the Module.mk files.

Leave the files there for now.
Remove old installed sensors.o in kernel/Module.mk.
sensors.c was moved to i2c-proc.c in the i2c package.
i2c-isa.h was appended to i2c.h in the i2c package.
Delete all but the SYSCTL and ALARMS definitions in sensors.h,
as the rest of the file was moved to i2c-proc.h in the i2c package.
Remove #include "i2c-isa.h" lines in all chip drivers and
in bus driver i2c-isa.c.
This all probably breaks mkpatch.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
Line 
1/*
2    lm80.c - Part of lm_sensors, Linux kernel modules for hardware
3             monitoring
4    Copyright (c) 1998, 1999  Frodo Looijaard <frodol@dds.nl>
5    and Philip Edelbrock <phil@netroedge.com>
6
7    This program is free software; you can redistribute it and/or modify
8    it under the terms of the GNU General Public License as published by
9    the Free Software Foundation; either version 2 of the License, or
10    (at your option) any later version.
11
12    This program is distributed in the hope that it will be useful,
13    but WITHOUT ANY WARRANTY; without even the implied warranty of
14    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15    GNU General Public License for more details.
16
17    You should have received a copy of the GNU General Public License
18    along with this program; if not, write to the Free Software
19    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
20*/
21
22#include <linux/version.h>
23#include <linux/module.h>
24#include <linux/malloc.h>
25#include <linux/proc_fs.h>
26#include <linux/ioport.h>
27#include <linux/sysctl.h>
28#include <asm/errno.h>
29#include <asm/io.h>
30#include <linux/types.h>
31#include <linux/i2c.h>
32#include "version.h"
33#include "sensors.h"
34#include <linux/init.h>
35
36#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,2,18)) || \
37    (LINUX_VERSION_CODE == KERNEL_VERSION(2,3,0))
38#define init_MUTEX(s) do { *(s) = MUTEX; } while(0)
39#endif
40
41#ifndef THIS_MODULE
42#define THIS_MODULE NULL
43#endif
44
45/* Addresses to scan */
46static unsigned short normal_i2c[] = { SENSORS_I2C_END };
47static unsigned short normal_i2c_range[] = { 0x20, 0x2f, SENSORS_I2C_END };
48static unsigned int normal_isa[] = { SENSORS_ISA_END };
49static unsigned int normal_isa_range[] = { SENSORS_ISA_END };
50
51/* Insmod parameters */
52SENSORS_INSMOD_1(lm80);
53
54/* Many LM80 constants specified below */
55
56/* The LM80 registers */
57#define LM80_REG_IN_MAX(nr) (0x2a + (nr) * 2)
58#define LM80_REG_IN_MIN(nr) (0x2b + (nr) * 2)
59#define LM80_REG_IN(nr) (0x20 + (nr))
60
61#define LM80_REG_FAN1_MIN 0x3c
62#define LM80_REG_FAN2_MIN 0x3d
63#define LM80_REG_FAN1 0x28
64#define LM80_REG_FAN2 0x29
65
66#define LM80_REG_TEMP 0x27
67#define LM80_REG_TEMP_HOT_MAX 0x38
68#define LM80_REG_TEMP_HOT_HYST 0x39
69#define LM80_REG_TEMP_OS_MAX 0x3a
70#define LM80_REG_TEMP_OS_HYST 0x3b
71
72#define LM80_REG_CONFIG 0x00
73#define LM80_REG_ALARM1 0x01
74#define LM80_REG_ALARM2 0x02
75#define LM80_REG_MASK1 0x03
76#define LM80_REG_MASK2 0x04
77#define LM80_REG_FANDIV 0x05
78#define LM80_REG_RES 0x06
79
80
81/* Conversions. Rounding and limit checking is only done on the TO_REG
82   variants. Note that you should be a bit careful with which arguments
83   these macros are called: arguments may be evaluated more than once.
84   Fixing this is just not worth it. */
85
86#define IN_TO_REG(val,nr) (SENSORS_LIMIT((val),0,255))
87#define IN_FROM_REG(val,nr) (val)
88
89extern inline unsigned char FAN_TO_REG(unsigned rpm, unsigned div)
90{
91        if (rpm == 0)
92                return 255;
93        rpm = SENSORS_LIMIT(rpm, 1, 1000000);
94        return SENSORS_LIMIT((1350000 + rpm * div / 2) / (rpm * div), 1,
95                             254);
96}
97
98#define FAN_FROM_REG(val,div) ((val)==0?-1:\
99                               (val)==255?0:1350000/((div)*(val)))
100
101extern inline long TEMP_FROM_REG(u16 temp)
102{
103        long res;
104
105        temp = temp >> 4;
106        if (temp < 0x0800) {
107                res = (625 * (long) temp);
108        } else {
109                res = ((long) temp - 0x01000) * 625;
110        }
111        return res / 100;
112}
113
114#define TEMP_LIMIT_FROM_REG(val) (((val)>0x80?(val)-0x100:(val))*100)
115
116#define TEMP_LIMIT_TO_REG(val) SENSORS_LIMIT(((val)<0?(((val)-50)/100):\
117                                                      ((val)+50)/100), \
118                                             0,255)
119
120#define ALARMS_FROM_REG(val) (val)
121
122#define DIV_FROM_REG(val) (1 << (val))
123#define DIV_TO_REG(val) ((val)==8?3:(val)==4?2:(val)==1?0:1)
124
125/* Initial limits */
126#define LM80_INIT_IN_0 190
127#define LM80_INIT_IN_1 190
128#define LM80_INIT_IN_2 190
129#define LM80_INIT_IN_3 190
130#define LM80_INIT_IN_4 190
131#define LM80_INIT_IN_5 190
132#define LM80_INIT_IN_6 190
133
134#define LM80_INIT_IN_PERCENTAGE 10
135
136#define LM80_INIT_IN_MIN_0 \
137        (LM80_INIT_IN_0 - LM80_INIT_IN_0 * LM80_INIT_IN_PERCENTAGE / 100)
138#define LM80_INIT_IN_MAX_0 \
139        (LM80_INIT_IN_0 + LM80_INIT_IN_0 * LM80_INIT_IN_PERCENTAGE / 100)
140#define LM80_INIT_IN_MIN_1 \
141        (LM80_INIT_IN_1 - LM80_INIT_IN_1 * LM80_INIT_IN_PERCENTAGE / 100)
142#define LM80_INIT_IN_MAX_1 \
143        (LM80_INIT_IN_1 + LM80_INIT_IN_1 * LM80_INIT_IN_PERCENTAGE / 100)
144#define LM80_INIT_IN_MIN_2 \
145        (LM80_INIT_IN_2 - LM80_INIT_IN_2 * LM80_INIT_IN_PERCENTAGE / 100)
146#define LM80_INIT_IN_MAX_2 \
147        (LM80_INIT_IN_2 + LM80_INIT_IN_2 * LM80_INIT_IN_PERCENTAGE / 100)
148#define LM80_INIT_IN_MIN_3 \
149        (LM80_INIT_IN_3 - LM80_INIT_IN_3 * LM80_INIT_IN_PERCENTAGE / 100)
150#define LM80_INIT_IN_MAX_3 \
151        (LM80_INIT_IN_3 + LM80_INIT_IN_3 * LM80_INIT_IN_PERCENTAGE / 100)
152#define LM80_INIT_IN_MIN_4 \
153        (LM80_INIT_IN_4 - LM80_INIT_IN_4 * LM80_INIT_IN_PERCENTAGE / 100)
154#define LM80_INIT_IN_MAX_4 \
155        (LM80_INIT_IN_4 + LM80_INIT_IN_4 * LM80_INIT_IN_PERCENTAGE / 100)
156#define LM80_INIT_IN_MIN_5 \
157        (LM80_INIT_IN_5 - LM80_INIT_IN_5 * LM80_INIT_IN_PERCENTAGE / 100)
158#define LM80_INIT_IN_MAX_5 \
159        (LM80_INIT_IN_5 + LM80_INIT_IN_5 * LM80_INIT_IN_PERCENTAGE / 100)
160#define LM80_INIT_IN_MIN_6 \
161        (LM80_INIT_IN_6 - LM80_INIT_IN_6 * LM80_INIT_IN_PERCENTAGE / 100)
162#define LM80_INIT_IN_MAX_6 \
163        (LM80_INIT_IN_6 + LM80_INIT_IN_6 * LM80_INIT_IN_PERCENTAGE / 100)
164
165#define LM80_INIT_FAN_MIN_1 3000
166#define LM80_INIT_FAN_MIN_2 3000
167
168#define LM80_INIT_TEMP_OS_MAX 600
169#define LM80_INIT_TEMP_OS_HYST 500
170#define LM80_INIT_TEMP_HOT_MAX 700
171#define LM80_INIT_TEMP_HOT_HYST 600
172
173#ifdef MODULE
174extern int init_module(void);
175extern int cleanup_module(void);
176#endif                          /* MODULE */
177
178/* For each registered LM80, we need to keep some data in memory. That
179   data is pointed to by lm80_list[NR]->data. The structure itself is
180   dynamically allocated, at the same time when a new lm80 client is
181   allocated. */
182struct lm80_data {
183        int sysctl_id;
184
185        struct semaphore update_lock;
186        char valid;             /* !=0 if following fields are valid */
187        unsigned long last_updated;     /* In jiffies */
188
189        u8 in[7];               /* Register value */
190        u8 in_max[7];           /* Register value */
191        u8 in_min[7];           /* Register value */
192        u8 fan[2];              /* Register value */
193        u8 fan_min[2];          /* Register value */
194        u8 fan_div[2];          /* Register encoding, shifted right */
195        u16 temp;               /* Register values, shifted right */
196        u8 temp_hot_max;        /* Register value */
197        u8 temp_hot_hyst;       /* Register value */
198        u8 temp_os_max;         /* Register value */
199        u8 temp_os_hyst;        /* Register value */
200        u16 alarms;             /* Register encoding, combined */
201};
202
203
204#ifdef MODULE
205static
206#else
207extern
208#endif
209int __init sensors_lm80_init(void);
210static int __init lm80_cleanup(void);
211
212static int lm80_attach_adapter(struct i2c_adapter *adapter);
213static int lm80_detect(struct i2c_adapter *adapter, int address,
214                       unsigned short flags, int kind);
215static int lm80_detach_client(struct i2c_client *client);
216static int lm80_command(struct i2c_client *client, unsigned int cmd,
217                        void *arg);
218static void lm80_inc_use(struct i2c_client *client);
219static void lm80_dec_use(struct i2c_client *client);
220
221static int lm80_read_value(struct i2c_client *client, u8 register);
222static int lm80_write_value(struct i2c_client *client, u8 register,
223                            u8 value);
224static void lm80_update_client(struct i2c_client *client);
225static void lm80_init_client(struct i2c_client *client);
226
227
228static void lm80_in(struct i2c_client *client, int operation, int ctl_name,
229                    int *nrels_mag, long *results);
230static void lm80_fan(struct i2c_client *client, int operation,
231                     int ctl_name, int *nrels_mag, long *results);
232static void lm80_temp(struct i2c_client *client, int operation,
233                      int ctl_name, int *nrels_mag, long *results);
234static void lm80_alarms(struct i2c_client *client, int operation,
235                        int ctl_name, int *nrels_mag, long *results);
236static void lm80_fan_div(struct i2c_client *client, int operation,
237                         int ctl_name, int *nrels_mag, long *results);
238
239static int lm80_id = 0;
240
241static struct i2c_driver lm80_driver = {
242        /* name */ "LM80 sensor driver",
243        /* id */ I2C_DRIVERID_LM80,
244        /* flags */ I2C_DF_NOTIFY,
245        /* attach_adapter */ &lm80_attach_adapter,
246        /* detach_client */ &lm80_detach_client,
247        /* command */ &lm80_command,
248        /* inc_use */ &lm80_inc_use,
249        /* dec_use */ &lm80_dec_use
250};
251
252/* Used by lm80_init/cleanup */
253static int __initdata lm80_initialized = 0;
254
255/* The /proc/sys entries */
256/* These files are created for each detected LM80. This is just a template;
257   though at first sight, you might think we could use a statically
258   allocated list, we need some way to get back to the parent - which
259   is done through one of the 'extra' fields which are initialized
260   when a new copy is allocated. */
261static ctl_table lm80_dir_table_template[] = {
262        {LM80_SYSCTL_IN0, "in0", NULL, 0, 0644, NULL, &sensors_proc_real,
263         &sensors_sysctl_real, NULL, &lm80_in},
264        {LM80_SYSCTL_IN1, "in1", NULL, 0, 0644, NULL, &sensors_proc_real,
265         &sensors_sysctl_real, NULL, &lm80_in},
266        {LM80_SYSCTL_IN2, "in2", NULL, 0, 0644, NULL, &sensors_proc_real,
267         &sensors_sysctl_real, NULL, &lm80_in},
268        {LM80_SYSCTL_IN3, "in3", NULL, 0, 0644, NULL, &sensors_proc_real,
269         &sensors_sysctl_real, NULL, &lm80_in},
270        {LM80_SYSCTL_IN4, "in4", NULL, 0, 0644, NULL, &sensors_proc_real,
271         &sensors_sysctl_real, NULL, &lm80_in},
272        {LM80_SYSCTL_IN5, "in5", NULL, 0, 0644, NULL, &sensors_proc_real,
273         &sensors_sysctl_real, NULL, &lm80_in},
274        {LM80_SYSCTL_IN6, "in6", NULL, 0, 0644, NULL, &sensors_proc_real,
275         &sensors_sysctl_real, NULL, &lm80_in},
276        {LM80_SYSCTL_FAN1, "fan1", NULL, 0, 0644, NULL, &sensors_proc_real,
277         &sensors_sysctl_real, NULL, &lm80_fan},
278        {LM80_SYSCTL_FAN2, "fan2", NULL, 0, 0644, NULL, &sensors_proc_real,
279         &sensors_sysctl_real, NULL, &lm80_fan},
280        {LM80_SYSCTL_TEMP, "temp", NULL, 0, 0644, NULL, &sensors_proc_real,
281         &sensors_sysctl_real, NULL, &lm80_temp},
282        {LM80_SYSCTL_FAN_DIV, "fan_div", NULL, 0, 0644, NULL, &sensors_proc_real,
283         &sensors_sysctl_real, NULL, &lm80_fan_div},
284        {LM80_SYSCTL_ALARMS, "alarms", NULL, 0, 0444, NULL, &sensors_proc_real,
285         &sensors_sysctl_real, NULL, &lm80_alarms},
286        {0}
287};
288
289int lm80_attach_adapter(struct i2c_adapter *adapter)
290{
291        return sensors_detect(adapter, &addr_data, lm80_detect);
292}
293
294int lm80_detect(struct i2c_adapter *adapter, int address,
295                unsigned short flags, int kind)
296{
297        int i, cur;
298        struct i2c_client *new_client;
299        struct lm80_data *data;
300        int err = 0;
301        const char *type_name, *client_name;
302
303        /* Make sure we aren't probing the ISA bus!! This is just a safety check
304           at this moment; sensors_detect really won't call us. */
305#ifdef DEBUG
306        if (i2c_is_isa_adapter(adapter)) {
307                printk
308                    ("lm80.o: lm80_detect called for an ISA bus adapter?!?\n");
309                return 0;
310        }
311#endif
312
313        if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA))
314                goto ERROR0;
315
316        /* OK. For now, we presume we have a valid client. We now create the
317           client structure, even though we cannot fill it completely yet.
318           But it allows us to access lm80_{read,write}_value. */
319        if (!(new_client = kmalloc(sizeof(struct i2c_client) +
320                                   sizeof(struct lm80_data),
321                                   GFP_KERNEL))) {
322                err = -ENOMEM;
323                goto ERROR0;
324        }
325
326        data = (struct lm80_data *) (new_client + 1);
327        new_client->addr = address;
328        new_client->data = data;
329        new_client->adapter = adapter;
330        new_client->driver = &lm80_driver;
331        new_client->flags = 0;
332
333        /* Now, we do the remaining detection. It is lousy. */
334        if (lm80_read_value(new_client, LM80_REG_ALARM2) & 0xc0)
335                goto ERROR1;
336        for (i = 0x2a; i <= 0x3d; i++) {
337                cur = i2c_smbus_read_byte_data(new_client, i);
338                if ((i2c_smbus_read_byte_data(new_client, i + 0x40) != cur)
339                    || (i2c_smbus_read_byte_data(new_client, i + 0x80) !=
340                        cur)
341                    || (i2c_smbus_read_byte_data(new_client, i + 0xc0) !=
342                        cur)) goto ERROR1;
343        }
344
345        /* Determine the chip type - only one kind supported! */
346        if (kind <= 0)
347                kind = lm80;
348
349        if (kind == lm80) {
350                type_name = "lm80";
351                client_name = "LM80 chip";
352        } else {
353#ifdef DEBUG
354                printk("lm80.o: Internal error: unknown kind (%d)?!?",
355                       kind);
356#endif
357                goto ERROR1;
358        }
359
360        /* Fill in the remaining client fields and put it into the global list */
361        strcpy(new_client->name, client_name);
362
363        new_client->id = lm80_id++;
364        data->valid = 0;
365        init_MUTEX(&data->update_lock);
366
367        /* Tell the I2C layer a new client has arrived */
368        if ((err = i2c_attach_client(new_client)))
369                goto ERROR3;
370
371        /* Register a new directory entry with module sensors */
372        if ((i = sensors_register_entry(new_client, type_name,
373                                        lm80_dir_table_template,
374                                        THIS_MODULE)) < 0) {
375                err = i;
376                goto ERROR4;
377        }
378        data->sysctl_id = i;
379
380        lm80_init_client(new_client);
381        return 0;
382
383/* OK, this is not exactly good programming practice, usually. But it is
384   very code-efficient in this case. */
385      ERROR4:
386        i2c_detach_client(new_client);
387      ERROR3:
388      ERROR1:
389        kfree(new_client);
390      ERROR0:
391        return err;
392}
393
394int lm80_detach_client(struct i2c_client *client)
395{
396        int err;
397
398        sensors_deregister_entry(((struct lm80_data *) (client->data))->
399                                 sysctl_id);
400
401        if ((err = i2c_detach_client(client))) {
402                printk
403                    ("lm80.o: Client deregistration failed, client not detached.\n");
404                return err;
405        }
406
407        kfree(client);
408
409        return 0;
410}
411
412/* No commands defined yet */
413int lm80_command(struct i2c_client *client, unsigned int cmd, void *arg)
414{
415        return 0;
416}
417
418void lm80_inc_use(struct i2c_client *client)
419{
420#ifdef MODULE
421        MOD_INC_USE_COUNT;
422#endif
423}
424
425void lm80_dec_use(struct i2c_client *client)
426{
427#ifdef MODULE
428        MOD_DEC_USE_COUNT;
429#endif
430}
431
432
433int lm80_read_value(struct i2c_client *client, u8 reg)
434{
435        return i2c_smbus_read_byte_data(client, reg);
436}
437
438int lm80_write_value(struct i2c_client *client, u8 reg, u8 value)
439{
440        return i2c_smbus_write_byte_data(client, reg, value);
441}
442
443/* Called when we have found a new LM80. It should set limits, etc. */
444void lm80_init_client(struct i2c_client *client)
445{
446        /* Reset all except Watchdog values and last conversion values
447           This sets fan-divs to 2, among others. This makes most other
448           initializations unnecessary */
449        lm80_write_value(client, LM80_REG_CONFIG, 0x80);
450        /* Set 11-bit temperature resolution */
451        lm80_write_value(client, LM80_REG_RES, 0x08);
452
453        lm80_write_value(client, LM80_REG_IN_MIN(0),
454                         IN_TO_REG(LM80_INIT_IN_MIN_0, 0));
455        lm80_write_value(client, LM80_REG_IN_MAX(0),
456                         IN_TO_REG(LM80_INIT_IN_MAX_0, 0));
457        lm80_write_value(client, LM80_REG_IN_MIN(1),
458                         IN_TO_REG(LM80_INIT_IN_MIN_1, 1));
459        lm80_write_value(client, LM80_REG_IN_MAX(1),
460                         IN_TO_REG(LM80_INIT_IN_MAX_1, 1));
461        lm80_write_value(client, LM80_REG_IN_MIN(2),
462                         IN_TO_REG(LM80_INIT_IN_MIN_2, 2));
463        lm80_write_value(client, LM80_REG_IN_MAX(2),
464                         IN_TO_REG(LM80_INIT_IN_MAX_2, 2));
465        lm80_write_value(client, LM80_REG_IN_MIN(3),
466                         IN_TO_REG(LM80_INIT_IN_MIN_3, 3));
467        lm80_write_value(client, LM80_REG_IN_MAX(3),
468                         IN_TO_REG(LM80_INIT_IN_MAX_3, 3));
469        lm80_write_value(client, LM80_REG_IN_MIN(4),
470                         IN_TO_REG(LM80_INIT_IN_MIN_4, 4));
471        lm80_write_value(client, LM80_REG_IN_MAX(4),
472                         IN_TO_REG(LM80_INIT_IN_MAX_4, 4));
473        lm80_write_value(client, LM80_REG_IN_MIN(5),
474                         IN_TO_REG(LM80_INIT_IN_MIN_5, 5));
475        lm80_write_value(client, LM80_REG_IN_MAX(5),
476                         IN_TO_REG(LM80_INIT_IN_MAX_5, 5));
477        lm80_write_value(client, LM80_REG_IN_MIN(6),
478                         IN_TO_REG(LM80_INIT_IN_MIN_6, 6));
479        lm80_write_value(client, LM80_REG_IN_MAX(6),
480                         IN_TO_REG(LM80_INIT_IN_MAX_6, 6));
481        lm80_write_value(client, LM80_REG_FAN1_MIN,
482                         FAN_TO_REG(LM80_INIT_FAN_MIN_1, 2));
483        lm80_write_value(client, LM80_REG_FAN2_MIN,
484                         FAN_TO_REG(LM80_INIT_FAN_MIN_2, 2));
485        lm80_write_value(client, LM80_REG_TEMP_HOT_MAX,
486                         TEMP_LIMIT_TO_REG(LM80_INIT_TEMP_OS_MAX));
487        lm80_write_value(client, LM80_REG_TEMP_HOT_HYST,
488                         TEMP_LIMIT_TO_REG(LM80_INIT_TEMP_OS_HYST));
489        lm80_write_value(client, LM80_REG_TEMP_OS_MAX,
490                         TEMP_LIMIT_TO_REG(LM80_INIT_TEMP_OS_MAX));
491        lm80_write_value(client, LM80_REG_TEMP_OS_HYST,
492                         TEMP_LIMIT_TO_REG(LM80_INIT_TEMP_OS_HYST));
493
494        /* Start monitoring */
495        lm80_write_value(client, LM80_REG_CONFIG, 0x01);
496}
497
498void lm80_update_client(struct i2c_client *client)
499{
500        struct lm80_data *data = client->data;
501        int i;
502
503        down(&data->update_lock);
504
505        if ((jiffies - data->last_updated > 2 * HZ) ||
506            (jiffies < data->last_updated) || !data->valid) {
507
508#ifdef DEBUG
509                printk("Starting lm80 update\n");
510#endif
511                for (i = 0; i <= 6; i++) {
512                        data->in[i] =
513                            lm80_read_value(client, LM80_REG_IN(i));
514                        data->in_min[i] =
515                            lm80_read_value(client, LM80_REG_IN_MIN(i));
516                        data->in_max[i] =
517                            lm80_read_value(client, LM80_REG_IN_MAX(i));
518                }
519                data->fan[0] = lm80_read_value(client, LM80_REG_FAN1);
520                data->fan_min[0] =
521                    lm80_read_value(client, LM80_REG_FAN1_MIN);
522                data->fan[1] = lm80_read_value(client, LM80_REG_FAN2);
523                data->fan_min[1] =
524                    lm80_read_value(client, LM80_REG_FAN2_MIN);
525
526                data->temp =
527                    (lm80_read_value(client, LM80_REG_TEMP) << 8) |
528                    (lm80_read_value(client, LM80_REG_RES) & 0xf0);
529                data->temp_os_max =
530                    lm80_read_value(client, LM80_REG_TEMP_OS_MAX);
531                data->temp_os_hyst =
532                    lm80_read_value(client, LM80_REG_TEMP_OS_HYST);
533                data->temp_hot_max =
534                    lm80_read_value(client, LM80_REG_TEMP_HOT_MAX);
535                data->temp_hot_hyst =
536                    lm80_read_value(client, LM80_REG_TEMP_HOT_HYST);
537
538                i = lm80_read_value(client, LM80_REG_FANDIV);
539                data->fan_div[0] = (i >> 2) & 0x03;
540                data->fan_div[1] = (i >> 4) & 0x03;
541                data->alarms = lm80_read_value(client, LM80_REG_ALARM1) +
542                    (lm80_read_value(client, LM80_REG_ALARM2) << 8);
543                data->last_updated = jiffies;
544                data->valid = 1;
545        }
546
547        up(&data->update_lock);
548}
549
550
551/* The next few functions are the call-back functions of the /proc/sys and
552   sysctl files. Which function is used is defined in the ctl_table in
553   the extra1 field.
554   Each function must return the magnitude (power of 10 to divide the date
555   with) if it is called with operation==SENSORS_PROC_REAL_INFO. It must
556   put a maximum of *nrels elements in results reflecting the data of this
557   file, and set *nrels to the number it actually put in it, if operation==
558   SENSORS_PROC_REAL_READ. Finally, it must get upto *nrels elements from
559   results and write them to the chip, if operations==SENSORS_PROC_REAL_WRITE.
560   Note that on SENSORS_PROC_REAL_READ, I do not check whether results is
561   large enough (by checking the incoming value of *nrels). This is not very
562   good practice, but as long as you put less than about 5 values in results,
563   you can assume it is large enough. */
564void lm80_in(struct i2c_client *client, int operation, int ctl_name,
565             int *nrels_mag, long *results)
566{
567        struct lm80_data *data = client->data;
568        int nr = ctl_name - LM80_SYSCTL_IN0;
569
570        if (operation == SENSORS_PROC_REAL_INFO)
571                *nrels_mag = 2;
572        else if (operation == SENSORS_PROC_REAL_READ) {
573                lm80_update_client(client);
574                results[0] = IN_FROM_REG(data->in_min[nr], nr);
575                results[1] = IN_FROM_REG(data->in_max[nr], nr);
576                results[2] = IN_FROM_REG(data->in[nr], nr);
577                *nrels_mag = 3;
578        } else if (operation == SENSORS_PROC_REAL_WRITE) {
579                if (*nrels_mag >= 1) {
580                        data->in_min[nr] = IN_TO_REG(results[0], nr);
581                        lm80_write_value(client, LM80_REG_IN_MIN(nr),
582                                         data->in_min[nr]);
583                }
584                if (*nrels_mag >= 2) {
585                        data->in_max[nr] = IN_TO_REG(results[1], nr);
586                        lm80_write_value(client, LM80_REG_IN_MAX(nr),
587                                         data->in_max[nr]);
588                }
589        }
590}
591
592void lm80_fan(struct i2c_client *client, int operation, int ctl_name,
593              int *nrels_mag, long *results)
594{
595        struct lm80_data *data = client->data;
596        int nr = ctl_name - LM80_SYSCTL_FAN1 + 1;
597
598        if (operation == SENSORS_PROC_REAL_INFO)
599                *nrels_mag = 0;
600        else if (operation == SENSORS_PROC_REAL_READ) {
601                lm80_update_client(client);
602                results[0] = FAN_FROM_REG(data->fan_min[nr - 1],
603                                          DIV_FROM_REG(data->
604                                                       fan_div[nr - 1]));
605                results[1] =
606                    FAN_FROM_REG(data->fan[nr - 1],
607                                 DIV_FROM_REG(data->fan_div[nr - 1]));
608                *nrels_mag = 2;
609        } else if (operation == SENSORS_PROC_REAL_WRITE) {
610                if (*nrels_mag >= 1) {
611                        data->fan_min[nr - 1] = FAN_TO_REG(results[0],
612                                                           DIV_FROM_REG
613                                                           (data->
614                                                            fan_div[nr -
615                                                                    1]));
616                        lm80_write_value(client,
617                                         nr ==
618                                         1 ? LM80_REG_FAN1_MIN :
619                                         LM80_REG_FAN2_MIN,
620                                         data->fan_min[nr - 1]);
621                }
622        }
623}
624
625
626void lm80_temp(struct i2c_client *client, int operation, int ctl_name,
627               int *nrels_mag, long *results)
628{
629        struct lm80_data *data = client->data;
630        if (operation == SENSORS_PROC_REAL_INFO)
631                *nrels_mag = 2;
632        else if (operation == SENSORS_PROC_REAL_READ) {
633                lm80_update_client(client);
634                results[0] = TEMP_LIMIT_FROM_REG(data->temp_hot_max);
635                results[1] = TEMP_LIMIT_FROM_REG(data->temp_hot_hyst);
636                results[2] = TEMP_LIMIT_FROM_REG(data->temp_os_max);
637                results[3] = TEMP_LIMIT_FROM_REG(data->temp_os_hyst);
638                results[4] = TEMP_FROM_REG(data->temp);
639                *nrels_mag = 5;
640        } else if (operation == SENSORS_PROC_REAL_WRITE) {
641                if (*nrels_mag >= 1) {
642                        data->temp_hot_max = TEMP_LIMIT_TO_REG(results[0]);
643                        lm80_write_value(client, LM80_REG_TEMP_HOT_MAX,
644                                         data->temp_hot_max);
645                }
646                if (*nrels_mag >= 2) {
647                        data->temp_hot_hyst =
648                            TEMP_LIMIT_TO_REG(results[1]);
649                        lm80_write_value(client, LM80_REG_TEMP_HOT_HYST,
650                                         data->temp_hot_hyst);
651                }
652                if (*nrels_mag >= 3) {
653                        data->temp_os_max = TEMP_LIMIT_TO_REG(results[2]);
654                        lm80_write_value(client, LM80_REG_TEMP_OS_MAX,
655                                         data->temp_os_max);
656                }
657                if (*nrels_mag >= 4) {
658                        data->temp_os_hyst = TEMP_LIMIT_TO_REG(results[3]);
659                        lm80_write_value(client, LM80_REG_TEMP_OS_HYST,
660                                         data->temp_os_hyst);
661                }
662        }
663}
664
665void lm80_alarms(struct i2c_client *client, int operation, int ctl_name,
666                 int *nrels_mag, long *results)
667{
668        struct lm80_data *data = client->data;
669        if (operation == SENSORS_PROC_REAL_INFO)
670                *nrels_mag = 0;
671        else if (operation == SENSORS_PROC_REAL_READ) {
672                lm80_update_client(client);
673                results[0] = ALARMS_FROM_REG(data->alarms);
674                *nrels_mag = 1;
675        }
676}
677
678void lm80_fan_div(struct i2c_client *client, int operation, int ctl_name,
679                  int *nrels_mag, long *results)
680{
681        struct lm80_data *data = client->data;
682        int old;
683
684        if (operation == SENSORS_PROC_REAL_INFO)
685                *nrels_mag = 0;
686        else if (operation == SENSORS_PROC_REAL_READ) {
687                lm80_update_client(client);
688                results[0] = DIV_FROM_REG(data->fan_div[0]);
689                results[1] = DIV_FROM_REG(data->fan_div[1]);
690                results[2] = 2;
691                *nrels_mag = 3;
692        } else if (operation == SENSORS_PROC_REAL_WRITE) {
693                old = lm80_read_value(client, LM80_REG_FANDIV);
694                if (*nrels_mag >= 2) {
695                        data->fan_div[1] = DIV_TO_REG(results[1]);
696                        old = (old & 0xcf) | (data->fan_div[1] << 4);
697                }
698                if (*nrels_mag >= 1) {
699                        data->fan_div[0] = DIV_TO_REG(results[0]);
700                        old = (old & 0xf3) | (data->fan_div[0] << 2);
701                        lm80_write_value(client, LM80_REG_FANDIV, old);
702                }
703        }
704}
705
706int __init sensors_lm80_init(void)
707{
708        int res;
709
710        printk("lm80.o version %s (%s)\n", LM_VERSION, LM_DATE);
711        lm80_initialized = 0;
712
713        if ((res = i2c_add_driver(&lm80_driver))) {
714                printk
715                    ("lm80.o: Driver registration failed, module not inserted.\n");
716                lm80_cleanup();
717                return res;
718        }
719        lm80_initialized++;
720        return 0;
721}
722
723int __init lm80_cleanup(void)
724{
725        int res;
726
727        if (lm80_initialized >= 1) {
728                if ((res = i2c_del_driver(&lm80_driver))) {
729                        printk
730                            ("lm80.o: Driver deregistration failed, module not removed.\n");
731                        return res;
732                }
733                lm80_initialized--;
734        }
735        return 0;
736}
737
738EXPORT_NO_SYMBOLS;
739
740#ifdef MODULE
741
742MODULE_AUTHOR
743    ("Frodo Looijaard <frodol@dds.nl> and Philip Edelbrock <phil@netroedge.com>");
744MODULE_DESCRIPTION("LM80 driver");
745
746int init_module(void)
747{
748        return sensors_lm80_init();
749}
750
751int cleanup_module(void)
752{
753        return lm80_cleanup();
754}
755
756#endif                          /* MODULE */
Note: See TracBrowser for help on using the browser.