root/lm-sensors/trunk/kernel/chips/lm78.c @ 2286

Revision 2286, 23.1 KB (checked in by khali, 9 years ago)

Do not include unneeded headers.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
Line 
1/*
2    lm78.c - Part of lm_sensors, Linux kernel modules for hardware
3             monitoring
4    Copyright (c) 1998, 1999  Frodo Looijaard <frodol@dds.nl>
5
6    This program is free software; you can redistribute it and/or modify
7    it under the terms of the GNU General Public License as published by
8    the Free Software Foundation; either version 2 of the License, or
9    (at your option) any later version.
10
11    This program is distributed in the hope that it will be useful,
12    but WITHOUT ANY WARRANTY; without even the implied warranty of
13    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14    GNU General Public License for more details.
15
16    You should have received a copy of the GNU General Public License
17    along with this program; if not, write to the Free Software
18    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
19*/
20
21#include <linux/module.h>
22#include <linux/slab.h>
23#include <linux/ioport.h>
24#include <linux/i2c.h>
25#include <linux/i2c-proc.h>
26#include <linux/init.h>
27#include <asm/io.h>
28#include "version.h"
29
30MODULE_LICENSE("GPL");
31
32/* Addresses to scan */
33static unsigned short normal_i2c[] = { SENSORS_I2C_END };
34static unsigned short normal_i2c_range[] = { 0x20, 0x2f, SENSORS_I2C_END };
35static unsigned int normal_isa[] = { 0x0290, SENSORS_ISA_END };
36static unsigned int normal_isa_range[] = { SENSORS_ISA_END };
37
38/* Insmod parameters */
39SENSORS_INSMOD_3(lm78, lm78j, lm79);
40
41/* Many LM78 constants specified below */
42
43/* Length of ISA address segment */
44#define LM78_EXTENT 8
45
46/* Where are the ISA address/data registers relative to the base address */
47#define LM78_ADDR_REG_OFFSET 5
48#define LM78_DATA_REG_OFFSET 6
49
50/* The LM78 registers */
51#define LM78_REG_IN_MAX(nr) (0x2b + (nr) * 2)
52#define LM78_REG_IN_MIN(nr) (0x2c + (nr) * 2)
53#define LM78_REG_IN(nr) (0x20 + (nr))
54
55#define LM78_REG_FAN_MIN(nr) (0x3a + (nr))
56#define LM78_REG_FAN(nr) (0x27 + (nr))
57
58#define LM78_REG_TEMP 0x27
59#define LM78_REG_TEMP_OVER 0x39
60#define LM78_REG_TEMP_HYST 0x3a
61
62#define LM78_REG_ALARM1 0x41
63#define LM78_REG_ALARM2 0x42
64
65#define LM78_REG_VID_FANDIV 0x47
66
67#define LM78_REG_CONFIG 0x40
68#define LM78_REG_CHIPID 0x49
69#define LM78_REG_I2C_ADDR 0x48
70
71
72/* Conversions. Limit checking is only done on the TO_REG
73   variants. Note that you should be a bit careful with which arguments
74   these macros are called: arguments may be evaluated more than once.
75   Fixing this is just not worth it. */
76#define IN_TO_REG(val)  (SENSORS_LIMIT((((val) * 10 + 8)/16),0,255))
77#define IN_FROM_REG(val) (((val) *  16 + 5) / 10)
78
79static inline u8 FAN_TO_REG(long rpm, int div)
80{
81        if (rpm == 0)
82                return 255;
83        rpm = SENSORS_LIMIT(rpm, 1, 1000000);
84        return SENSORS_LIMIT((1350000 + rpm * div / 2) / (rpm * div), 1,
85                             254);
86}
87
88#define FAN_FROM_REG(val,div) ((val)==0?-1:(val)==255?0:1350000/((val)*(div)))
89
90#define TEMP_TO_REG(val) (SENSORS_LIMIT(((val)<0?(((val)-5)/10):\
91                                                 ((val)+5)/10),0,255))
92#define TEMP_FROM_REG(val) (((val)>0x80?(val)-0x100:(val))*10)
93
94#define VID_FROM_REG(val) ((val)==0x1f?0:(val)>=0x10?510-(val)*10:\
95                           205-(val)*5)
96#define ALARMS_FROM_REG(val) (val)
97
98#define DIV_TO_REG(val) ((val)==8?3:(val)==4?2:(val)==1?0:1)
99#define DIV_FROM_REG(val) (1 << (val))
100
101/* There are some complications in a module like this. First off, LM78 chips
102   may be both present on the SMBus and the ISA bus, and we have to handle
103   those cases separately at some places. Second, there might be several
104   LM78 chips available (well, actually, that is probably never done; but
105   it is a clean illustration of how to handle a case like that). Finally,
106   a specific chip may be attached to *both* ISA and SMBus, and we would
107   not like to detect it double. Fortunately, in the case of the LM78 at
108   least, a register tells us what SMBus address we are on, so that helps
109   a bit - except if there could be more than one SMBus. Groan. No solution
110   for this yet. */
111
112/* This module may seem overly long and complicated. In fact, it is not so
113   bad. Quite a lot of bookkeeping is done. A real driver can often cut
114   some corners. */
115
116/* For each registered LM78, we need to keep some data in memory. That
117   data is pointed to by lm78_list[NR]->data. The structure itself is
118   dynamically allocated, at the same time when a new lm78 client is
119   allocated. */
120struct lm78_data {
121        struct semaphore lock;
122        int sysctl_id;
123        enum chips type;
124
125        struct semaphore update_lock;
126        char valid;             /* !=0 if following fields are valid */
127        unsigned long last_updated;     /* In jiffies */
128
129        u8 in[7];               /* Register value */
130        u8 in_max[7];           /* Register value */
131        u8 in_min[7];           /* Register value */
132        u8 fan[3];              /* Register value */
133        u8 fan_min[3];          /* Register value */
134        u8 temp;                /* Register value */
135        u8 temp_over;           /* Register value */
136        u8 temp_hyst;           /* Register value */
137        u8 fan_div[3];          /* Register encoding, shifted right */
138        u8 vid;                 /* Register encoding, combined */
139        u16 alarms;             /* Register encoding, combined */
140};
141
142
143static int lm78_attach_adapter(struct i2c_adapter *adapter);
144static int lm78_detect(struct i2c_adapter *adapter, int address,
145                       unsigned short flags, int kind);
146static int lm78_detach_client(struct i2c_client *client);
147
148static int lm78_read_value(struct i2c_client *client, u8 register);
149static int lm78_write_value(struct i2c_client *client, u8 register,
150                            u8 value);
151static void lm78_update_client(struct i2c_client *client);
152static void lm78_init_client(struct i2c_client *client);
153
154
155static void lm78_in(struct i2c_client *client, int operation, int ctl_name,
156                    int *nrels_mag, long *results);
157static void lm78_fan(struct i2c_client *client, int operation,
158                     int ctl_name, int *nrels_mag, long *results);
159static void lm78_temp(struct i2c_client *client, int operation,
160                      int ctl_name, int *nrels_mag, long *results);
161static void lm78_vid(struct i2c_client *client, int operation,
162                     int ctl_name, int *nrels_mag, long *results);
163static void lm78_alarms(struct i2c_client *client, int operation,
164                        int ctl_name, int *nrels_mag, long *results);
165static void lm78_fan_div(struct i2c_client *client, int operation,
166                         int ctl_name, int *nrels_mag, long *results);
167
168static struct i2c_driver lm78_driver = {
169        .owner          = THIS_MODULE,
170        .name           = "LM78(-J) and LM79 sensor driver",
171        .id             = I2C_DRIVERID_LM78,
172        .flags          = I2C_DF_NOTIFY,
173        .attach_adapter = lm78_attach_adapter,
174        .detach_client  = lm78_detach_client,
175};
176
177static int lm78_id = 0;
178
179/* The /proc/sys entries */
180
181/* -- SENSORS SYSCTL START -- */
182#define LM78_SYSCTL_IN0 1000    /* Volts * 100 */
183#define LM78_SYSCTL_IN1 1001
184#define LM78_SYSCTL_IN2 1002
185#define LM78_SYSCTL_IN3 1003
186#define LM78_SYSCTL_IN4 1004
187#define LM78_SYSCTL_IN5 1005
188#define LM78_SYSCTL_IN6 1006
189#define LM78_SYSCTL_FAN1 1101   /* Rotations/min */
190#define LM78_SYSCTL_FAN2 1102
191#define LM78_SYSCTL_FAN3 1103
192#define LM78_SYSCTL_TEMP 1200   /* Degrees Celcius * 10 */
193#define LM78_SYSCTL_VID 1300    /* Volts * 100 */
194#define LM78_SYSCTL_FAN_DIV 2000        /* 1, 2, 4 or 8 */
195#define LM78_SYSCTL_ALARMS 2001 /* bitvector */
196
197#define LM78_ALARM_IN0 0x0001
198#define LM78_ALARM_IN1 0x0002
199#define LM78_ALARM_IN2 0x0004
200#define LM78_ALARM_IN3 0x0008
201#define LM78_ALARM_IN4 0x0100
202#define LM78_ALARM_IN5 0x0200
203#define LM78_ALARM_IN6 0x0400
204#define LM78_ALARM_FAN1 0x0040
205#define LM78_ALARM_FAN2 0x0080
206#define LM78_ALARM_FAN3 0x0800
207#define LM78_ALARM_TEMP 0x0010
208#define LM78_ALARM_BTI 0x0020
209#define LM78_ALARM_CHAS 0x1000
210#define LM78_ALARM_FIFO 0x2000
211#define LM78_ALARM_SMI_IN 0x4000
212
213/* -- SENSORS SYSCTL END -- */
214
215/* These files are created for each detected LM78. This is just a template;
216   though at first sight, you might think we could use a statically
217   allocated list, we need some way to get back to the parent - which
218   is done through one of the 'extra' fields which are initialized
219   when a new copy is allocated. */
220static ctl_table lm78_dir_table_template[] = {
221        {LM78_SYSCTL_IN0, "in0", NULL, 0, 0644, NULL, &i2c_proc_real,
222         &i2c_sysctl_real, NULL, &lm78_in},
223        {LM78_SYSCTL_IN1, "in1", NULL, 0, 0644, NULL, &i2c_proc_real,
224         &i2c_sysctl_real, NULL, &lm78_in},
225        {LM78_SYSCTL_IN2, "in2", NULL, 0, 0644, NULL, &i2c_proc_real,
226         &i2c_sysctl_real, NULL, &lm78_in},
227        {LM78_SYSCTL_IN3, "in3", NULL, 0, 0644, NULL, &i2c_proc_real,
228         &i2c_sysctl_real, NULL, &lm78_in},
229        {LM78_SYSCTL_IN4, "in4", NULL, 0, 0644, NULL, &i2c_proc_real,
230         &i2c_sysctl_real, NULL, &lm78_in},
231        {LM78_SYSCTL_IN5, "in5", NULL, 0, 0644, NULL, &i2c_proc_real,
232         &i2c_sysctl_real, NULL, &lm78_in},
233        {LM78_SYSCTL_IN6, "in6", NULL, 0, 0644, NULL, &i2c_proc_real,
234         &i2c_sysctl_real, NULL, &lm78_in},
235        {LM78_SYSCTL_FAN1, "fan1", NULL, 0, 0644, NULL, &i2c_proc_real,
236         &i2c_sysctl_real, NULL, &lm78_fan},
237        {LM78_SYSCTL_FAN2, "fan2", NULL, 0, 0644, NULL, &i2c_proc_real,
238         &i2c_sysctl_real, NULL, &lm78_fan},
239        {LM78_SYSCTL_FAN3, "fan3", NULL, 0, 0644, NULL, &i2c_proc_real,
240         &i2c_sysctl_real, NULL, &lm78_fan},
241        {LM78_SYSCTL_TEMP, "temp", NULL, 0, 0644, NULL, &i2c_proc_real,
242         &i2c_sysctl_real, NULL, &lm78_temp},
243        {LM78_SYSCTL_VID, "vid", NULL, 0, 0444, NULL, &i2c_proc_real,
244         &i2c_sysctl_real, NULL, &lm78_vid},
245        {LM78_SYSCTL_FAN_DIV, "fan_div", NULL, 0, 0644, NULL, &i2c_proc_real,
246         &i2c_sysctl_real, NULL, &lm78_fan_div},
247        {LM78_SYSCTL_ALARMS, "alarms", NULL, 0, 0444, NULL, &i2c_proc_real,
248         &i2c_sysctl_real, NULL, &lm78_alarms},
249        {0}
250};
251
252
253/* This function is called when:
254     * lm78_driver is inserted (when this module is loaded), for each
255       available adapter
256     * when a new adapter is inserted (and lm78_driver is still present) */
257static int lm78_attach_adapter(struct i2c_adapter *adapter)
258{
259        return i2c_detect(adapter, &addr_data, lm78_detect);
260}
261
262/* This function is called by i2c_detect */
263int lm78_detect(struct i2c_adapter *adapter, int address,
264                unsigned short flags, int kind)
265{
266        int i;
267        struct i2c_client *new_client;
268        struct lm78_data *data;
269        int err = 0;
270        const char *type_name = "";
271        const char *client_name = "";
272        int is_isa = i2c_is_isa_adapter(adapter);
273
274        if (!is_isa
275            && !i2c_check_functionality(adapter,
276                                        I2C_FUNC_SMBUS_BYTE_DATA)) goto
277                    ERROR0;
278
279        if (is_isa) {
280                if (check_region(address, LM78_EXTENT))
281                        goto ERROR0;
282        }
283
284        /* Probe whether there is anything available on this address. Already
285           done for SMBus clients */
286        if (kind < 0) {
287                if (is_isa) {
288
289#define REALLY_SLOW_IO
290                        /* We need the timeouts for at least some LM78-like chips. But only
291                           if we read 'undefined' registers. */
292                        i = inb_p(address + 1);
293                        if (inb_p(address + 2) != i)
294                                goto ERROR0;
295                        if (inb_p(address + 3) != i)
296                                goto ERROR0;
297                        if (inb_p(address + 7) != i)
298                                goto ERROR0;
299#undef REALLY_SLOW_IO
300
301                        /* Let's just hope nothing breaks here */
302                        i = inb_p(address + 5) & 0x7f;
303                        outb_p(~i & 0x7f, address + 5);
304                        if ((inb_p(address + 5) & 0x7f) != (~i & 0x7f)) {
305                                outb_p(i, address + 5);
306                                return 0;
307                        }
308                }
309        }
310
311        /* OK. For now, we presume we have a valid client. We now create the
312           client structure, even though we cannot fill it completely yet.
313           But it allows us to access lm78_{read,write}_value. */
314
315        if (!(new_client = kmalloc((sizeof(struct i2c_client)) +
316                                   sizeof(struct lm78_data),
317                                   GFP_KERNEL))) {
318                err = -ENOMEM;
319                goto ERROR0;
320        }
321
322        data = (struct lm78_data *) (new_client + 1);
323        if (is_isa)
324                init_MUTEX(&data->lock);
325        new_client->addr = address;
326        new_client->data = data;
327        new_client->adapter = adapter;
328        new_client->driver = &lm78_driver;
329        new_client->flags = 0;
330
331        /* Now, we do the remaining detection. */
332
333        if (kind < 0) {
334                if (lm78_read_value(new_client, LM78_REG_CONFIG) & 0x80)
335                        goto ERROR1;
336                if (!is_isa
337                    && (lm78_read_value(new_client, LM78_REG_I2C_ADDR) !=
338                        address)) goto ERROR1;
339        }
340
341        /* Determine the chip type. */
342        if (kind <= 0) {
343                i = lm78_read_value(new_client, LM78_REG_CHIPID);
344                if (i == 0x00 || i == 0x20)
345                        kind = lm78;
346                else if (i == 0x40)
347                        kind = lm78j;
348                else if ((i & 0xfe) == 0xc0)
349                        kind = lm79;
350                else {
351                        if (kind == 0)
352                                printk
353                                    ("lm78.o: Ignoring 'force' parameter for unknown chip at "
354                                     "adapter %d, address 0x%02x\n",
355                                     i2c_adapter_id(adapter), address);
356                        goto ERROR1;
357                }
358        }
359
360        if (kind == lm78) {
361                type_name = "lm78";
362                client_name = "LM78 chip";
363        } else if (kind == lm78j) {
364                type_name = "lm78-j";
365                client_name = "LM78-J chip";
366        } else if (kind == lm79) {
367                type_name = "lm79";
368                client_name = "LM79 chip";
369        } else {
370#ifdef DEBUG
371                printk("lm78.o: Internal error: unknown kind (%d)?!?",
372                       kind);
373#endif
374                goto ERROR1;
375        }
376
377        /* Reserve the ISA region */
378        if (is_isa)
379                request_region(address, LM78_EXTENT, type_name);
380
381        /* Fill in the remaining client fields and put it into the global list */
382        strcpy(new_client->name, client_name);
383        data->type = kind;
384
385        new_client->id = lm78_id++;
386        data->valid = 0;
387        init_MUTEX(&data->update_lock);
388
389        /* Tell the I2C layer a new client has arrived */
390        if ((err = i2c_attach_client(new_client)))
391                goto ERROR3;
392
393        /* Register a new directory entry with module sensors */
394        if ((i = i2c_register_entry(new_client,
395                                        type_name,
396                                        lm78_dir_table_template)) < 0) {
397                err = i;
398                goto ERROR4;
399        }
400        data->sysctl_id = i;
401
402        /* Initialize the LM78 chip */
403        lm78_init_client(new_client);
404        return 0;
405
406/* OK, this is not exactly good programming practice, usually. But it is
407   very code-efficient in this case. */
408
409      ERROR4:
410        i2c_detach_client(new_client);
411      ERROR3:
412        if (is_isa)
413                release_region(address, LM78_EXTENT);
414      ERROR1:
415        kfree(new_client);
416      ERROR0:
417        return err;
418}
419
420static int lm78_detach_client(struct i2c_client *client)
421{
422        int err;
423
424        i2c_deregister_entry(((struct lm78_data *) (client->data))->
425                                 sysctl_id);
426
427        if ((err = i2c_detach_client(client))) {
428                printk
429                    ("lm78.o: Client deregistration failed, client not detached.\n");
430                return err;
431        }
432
433        if(i2c_is_isa_client(client))
434                release_region(client->addr, LM78_EXTENT);
435        kfree(client);
436
437        return 0;
438}
439
440/* The SMBus locks itself, but ISA access must be locked explicitely!
441   We don't want to lock the whole ISA bus, so we lock each client
442   separately.
443   We ignore the LM78 BUSY flag at this moment - it could lead to deadlocks,
444   would slow down the LM78 access and should not be necessary.
445   There are some ugly typecasts here, but the good new is - they should
446   nowhere else be necessary! */
447static int lm78_read_value(struct i2c_client *client, u8 reg)
448{
449        int res;
450        if (i2c_is_isa_client(client)) {
451                down(&(((struct lm78_data *) (client->data))->lock));
452                outb_p(reg, client->addr + LM78_ADDR_REG_OFFSET);
453                res = inb_p(client->addr + LM78_DATA_REG_OFFSET);
454                up(&(((struct lm78_data *) (client->data))->lock));
455                return res;
456        } else
457                return i2c_smbus_read_byte_data(client, reg);
458}
459
460/* The SMBus locks itself, but ISA access muse be locked explicitely!
461   We don't want to lock the whole ISA bus, so we lock each client
462   separately.
463   We ignore the LM78 BUSY flag at this moment - it could lead to deadlocks,
464   would slow down the LM78 access and should not be necessary.
465   There are some ugly typecasts here, but the good new is - they should
466   nowhere else be necessary! */
467static int lm78_write_value(struct i2c_client *client, u8 reg, u8 value)
468{
469        if (i2c_is_isa_client(client)) {
470                down(&(((struct lm78_data *) (client->data))->lock));
471                outb_p(reg, client->addr + LM78_ADDR_REG_OFFSET);
472                outb_p(value, client->addr + LM78_DATA_REG_OFFSET);
473                up(&(((struct lm78_data *) (client->data))->lock));
474                return 0;
475        } else
476                return i2c_smbus_write_byte_data(client, reg, value);
477}
478
479/* Called when we have found a new LM78. It should set limits, etc. */
480static void lm78_init_client(struct i2c_client *client)
481{
482        int vid;
483
484        /* Reset all except Watchdog values and last conversion values
485           This sets fan-divs to 2, among others */
486        lm78_write_value(client, LM78_REG_CONFIG, 0x80);
487
488        vid = lm78_read_value(client, LM78_REG_VID_FANDIV) & 0x0f;
489        if (((struct lm78_data *) (client->data))->type == lm79)
490                vid |=
491                    (lm78_read_value(client, LM78_REG_CHIPID) & 0x01) << 4;
492        else
493                vid |= 0x10;
494        vid = VID_FROM_REG(vid);
495
496        /* Start monitoring */
497        lm78_write_value(client, LM78_REG_CONFIG,
498                         (lm78_read_value(client, LM78_REG_CONFIG) & 0xf7)
499                         | 0x01);
500
501}
502
503static void lm78_update_client(struct i2c_client *client)
504{
505        struct lm78_data *data = client->data;
506        int i;
507
508        down(&data->update_lock);
509
510        if ((jiffies - data->last_updated > HZ + HZ / 2) ||
511            (jiffies < data->last_updated) || !data->valid) {
512
513#ifdef DEBUG
514                printk("Starting lm78 update\n");
515#endif
516                for (i = 0; i <= 6; i++) {
517                        data->in[i] =
518                            lm78_read_value(client, LM78_REG_IN(i));
519                        data->in_min[i] =
520                            lm78_read_value(client, LM78_REG_IN_MIN(i));
521                        data->in_max[i] =
522                            lm78_read_value(client, LM78_REG_IN_MAX(i));
523                }
524                for (i = 1; i <= 3; i++) {
525                        data->fan[i - 1] =
526                            lm78_read_value(client, LM78_REG_FAN(i));
527                        data->fan_min[i - 1] =
528                            lm78_read_value(client, LM78_REG_FAN_MIN(i));
529                }
530                data->temp = lm78_read_value(client, LM78_REG_TEMP);
531                data->temp_over =
532                    lm78_read_value(client, LM78_REG_TEMP_OVER);
533                data->temp_hyst =
534                    lm78_read_value(client, LM78_REG_TEMP_HYST);
535                i = lm78_read_value(client, LM78_REG_VID_FANDIV);
536                data->vid = i & 0x0f;
537                if (data->type == lm79)
538                        data->vid |=
539                            (lm78_read_value(client, LM78_REG_CHIPID) &
540                             0x01) << 4;
541                else
542                        data->vid |= 0x10;
543                data->fan_div[0] = (i >> 4) & 0x03;
544                data->fan_div[1] = i >> 6;
545                data->alarms = lm78_read_value(client, LM78_REG_ALARM1) +
546                    (lm78_read_value(client, LM78_REG_ALARM2) << 8);
547                data->last_updated = jiffies;
548                data->valid = 1;
549
550                data->fan_div[2] = 1;
551        }
552
553        up(&data->update_lock);
554}
555
556
557/* The next few functions are the call-back functions of the /proc/sys and
558   sysctl files. Which function is used is defined in the ctl_table in
559   the extra1 field.
560   Each function must return the magnitude (power of 10 to divide the date
561   with) if it is called with operation==SENSORS_PROC_REAL_INFO. It must
562   put a maximum of *nrels elements in results reflecting the data of this
563   file, and set *nrels to the number it actually put in it, if operation==
564   SENSORS_PROC_REAL_READ. Finally, it must get upto *nrels elements from
565   results and write them to the chip, if operations==SENSORS_PROC_REAL_WRITE.
566   Note that on SENSORS_PROC_REAL_READ, I do not check whether results is
567   large enough (by checking the incoming value of *nrels). This is not very
568   good practice, but as long as you put less than about 5 values in results,
569   you can assume it is large enough. */
570void lm78_in(struct i2c_client *client, int operation, int ctl_name,
571             int *nrels_mag, long *results)
572{
573        struct lm78_data *data = client->data;
574        int nr = ctl_name - LM78_SYSCTL_IN0;
575
576        if (operation == SENSORS_PROC_REAL_INFO)
577                *nrels_mag = 2;
578        else if (operation == SENSORS_PROC_REAL_READ) {
579                lm78_update_client(client);
580                results[0] = IN_FROM_REG(data->in_min[nr]);
581                results[1] = IN_FROM_REG(data->in_max[nr]);
582                results[2] = IN_FROM_REG(data->in[nr]);
583                *nrels_mag = 3;
584        } else if (operation == SENSORS_PROC_REAL_WRITE) {
585                if (*nrels_mag >= 1) {
586                        data->in_min[nr] = IN_TO_REG(results[0]);
587                        lm78_write_value(client, LM78_REG_IN_MIN(nr),
588                                         data->in_min[nr]);
589                }
590                if (*nrels_mag >= 2) {
591                        data->in_max[nr] = IN_TO_REG(results[1]);
592                        lm78_write_value(client, LM78_REG_IN_MAX(nr),
593                                         data->in_max[nr]);
594                }
595        }
596}
597
598void lm78_fan(struct i2c_client *client, int operation, int ctl_name,
599              int *nrels_mag, long *results)
600{
601        struct lm78_data *data = client->data;
602        int nr = ctl_name - LM78_SYSCTL_FAN1 + 1;
603
604        if (operation == SENSORS_PROC_REAL_INFO)
605                *nrels_mag = 0;
606        else if (operation == SENSORS_PROC_REAL_READ) {
607                lm78_update_client(client);
608                results[0] = FAN_FROM_REG(data->fan_min[nr - 1],
609                                          DIV_FROM_REG(data->
610                                                       fan_div[nr - 1]));
611                results[1] =
612                    FAN_FROM_REG(data->fan[nr - 1],
613                                 DIV_FROM_REG(data->fan_div[nr - 1]));
614                *nrels_mag = 2;
615        } else if (operation == SENSORS_PROC_REAL_WRITE) {
616                if (*nrels_mag >= 1) {
617                        data->fan_min[nr - 1] = FAN_TO_REG(results[0],
618                                                           DIV_FROM_REG
619                                                           (data->
620                                                            fan_div[nr -
621                                                                    1]));
622                        lm78_write_value(client, LM78_REG_FAN_MIN(nr),
623                                         data->fan_min[nr - 1]);
624                }
625        }
626}
627
628
629void lm78_temp(struct i2c_client *client, int operation, int ctl_name,
630               int *nrels_mag, long *results)
631{
632        struct lm78_data *data = client->data;
633        if (operation == SENSORS_PROC_REAL_INFO)
634                *nrels_mag = 1;
635        else if (operation == SENSORS_PROC_REAL_READ) {
636                lm78_update_client(client);
637                results[0] = TEMP_FROM_REG(data->temp_over);
638                results[1] = TEMP_FROM_REG(data->temp_hyst);
639                results[2] = TEMP_FROM_REG(data->temp);
640                *nrels_mag = 3;
641        } else if (operation == SENSORS_PROC_REAL_WRITE) {
642                if (*nrels_mag >= 1) {
643                        data->temp_over = TEMP_TO_REG(results[0]);
644                        lm78_write_value(client, LM78_REG_TEMP_OVER,
645                                         data->temp_over);
646                }
647                if (*nrels_mag >= 2) {
648                        data->temp_hyst = TEMP_TO_REG(results[1]);
649                        lm78_write_value(client, LM78_REG_TEMP_HYST,
650                                         data->temp_hyst);
651                }
652        }
653}
654
655void lm78_vid(struct i2c_client *client, int operation, int ctl_name,
656              int *nrels_mag, long *results)
657{
658        struct lm78_data *data = client->data;
659        if (operation == SENSORS_PROC_REAL_INFO)
660                *nrels_mag = 2;
661        else if (operation == SENSORS_PROC_REAL_READ) {
662                lm78_update_client(client);
663                results[0] = VID_FROM_REG(data->vid);
664                *nrels_mag = 1;
665        }
666}
667
668void lm78_alarms(struct i2c_client *client, int operation, int ctl_name,
669                 int *nrels_mag, long *results)
670{
671        struct lm78_data *data = client->data;
672        if (operation == SENSORS_PROC_REAL_INFO)
673                *nrels_mag = 0;
674        else if (operation == SENSORS_PROC_REAL_READ) {
675                lm78_update_client(client);
676                results[0] = ALARMS_FROM_REG(data->alarms);
677                *nrels_mag = 1;
678        }
679}
680
681/* Note: we save and restore the fan minimum here, because its value is
682   determined in part by the fan divisor.  This follows the principle of
683   least surprise: the user doesn't expect the fan minimum to change just
684   because the divisor changed. */
685void lm78_fan_div(struct i2c_client *client, int operation, int ctl_name,
686                  int *nrels_mag, long *results)
687{
688        struct lm78_data *data = client->data;
689        int old, min;
690
691        if (operation == SENSORS_PROC_REAL_INFO)
692                *nrels_mag = 0;
693        else if (operation == SENSORS_PROC_REAL_READ) {
694                lm78_update_client(client);
695                results[0] = DIV_FROM_REG(data->fan_div[0]);
696                results[1] = DIV_FROM_REG(data->fan_div[1]);
697                results[2] = 2;
698                *nrels_mag = 3;
699        } else if (operation == SENSORS_PROC_REAL_WRITE) {
700                old = lm78_read_value(client, LM78_REG_VID_FANDIV);
701                if (*nrels_mag >= 2) {
702                        min = FAN_FROM_REG(data->fan_min[1], 
703                                        DIV_FROM_REG(data->fan_div[1]));
704                        data->fan_div[1] = DIV_TO_REG(results[1]);
705                        old = (old & 0x3f) | (data->fan_div[1] << 6);
706                        data->fan_min[1] = FAN_TO_REG(min,
707                                        DIV_FROM_REG(data->fan_div[1]));
708                        lm78_write_value(client, LM78_REG_FAN_MIN(2),
709                                        data->fan_min[1]);
710                }
711                if (*nrels_mag >= 1) {
712                        min = FAN_FROM_REG(data->fan_min[0],
713                                        DIV_FROM_REG(data->fan_div[0]));
714                        data->fan_div[0] = DIV_TO_REG(results[0]);
715                        old = (old & 0xcf) | (data->fan_div[0] << 4);
716                        data->fan_min[0] = FAN_TO_REG(min,
717                                        DIV_FROM_REG(data->fan_div[0]));
718                        lm78_write_value(client, LM78_REG_FAN_MIN(1),
719                                        data->fan_min[0]);
720                        lm78_write_value(client, LM78_REG_VID_FANDIV, old);
721                }
722        }
723}
724
725static int __init sm_lm78_init(void)
726{
727        printk("lm78.o version %s (%s)\n", LM_VERSION, LM_DATE);
728        return i2c_add_driver(&lm78_driver);
729}
730
731static void __exit sm_lm78_exit(void)
732{
733        i2c_del_driver(&lm78_driver);
734}
735
736
737
738MODULE_AUTHOR("Frodo Looijaard <frodol@dds.nl>");
739MODULE_DESCRIPTION("LM78, LM78-J and LM79 driver");
740
741module_init(sm_lm78_init);
742module_exit(sm_lm78_exit);
Note: See TracBrowser for help on using the browser.