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

Revision 113, 25.1 KB (checked in by frodo, 14 years ago)

Several minor things

* sensors.conf.eg now contains LM80 declarations
* i2c/i2c-core.c again displays which adapters and clients are found and

connected, but it does not track the calls to transfer functions in dmesg

* Slight alarms computation bug in lm78.c repaired
* First hacks at lm80.c; expect a fully working version later today

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
Line 
1
2/*
3    lm80.c - Part of lm_sensors, Linux kernel modules for hardware
4             monitoring
5    Copyright (c) 1998  Frodo Looijaard <frodol@dds.nl>
6    and Philip Edelbrock <phil@netroedge.com>
7
8    This program is free software; you can redistribute it and/or modify
9    it under the terms of the GNU General Public License as published by
10    the Free Software Foundation; either version 2 of the License, or
11    (at your option) any later version.
12
13    This program is distributed in the hope that it will be useful,
14    but WITHOUT ANY WARRANTY; without even the implied warranty of
15    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16    GNU General Public License for more details.
17
18    You should have received a copy of the GNU General Public License
19    along with this program; if not, write to the Free Software
20    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
21*/
22
23#include <linux/module.h>
24#include <linux/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 "smbus.h"
32#include "version.h"
33#include "isa.h"
34#include "sensors.h"
35#include "i2c.h"
36#include "compat.h"
37
38/* Many LM80 constants specified below */
39
40/* The LM80 registers */
41#define LM80_REG_IN_MAX(nr) (0x2a + (nr) * 2)
42#define LM80_REG_IN_MIN(nr) (0x2b + (nr) * 2)
43#define LM80_REG_IN(nr) (0x20 + (nr))
44
45#define LM80_REG_FAN_MIN(nr) (0x3b + (nr))
46#define LM80_REG_FAN(nr) (0x27 + (nr))
47
48#define LM80_REG_TEMP 0x27
49#define LM80_REG_TEMP_OVER 0x39
50#define LM80_REG_TEMP_HYST 0x3a
51
52#define LM80_REG_ALARM1 0x41
53#define LM80_REG_ALARM2 0x42
54
55#define LM80_REG_VID_FANDIV 0x47
56
57#define LM80_REG_CONFIG 0x40
58#define LM80_REG_CHIPID 0x49
59
60
61/* Conversions. Rounding is only done on the TO_REG variants. */
62#define IN_TO_REG(val,nr) (((((val) * 100000 / lm80_in_conv[nr]) + 8) / 16) \
63                           & 0xff)
64#define IN_FROM_REG(val,nr) (((val) *  16 * lm80_in_conv[nr]) / 100000)
65
66#define FAN_TO_REG(val) ((val)==0?255:((1350000+(val))/((val)*2)) & 0xff)
67#define FAN_FROM_REG(val) ((val)==0?-1:(val)==255?0:1350000/((val)*2))
68
69#define TEMP_TO_REG(val) (((val)<0?(((val)-5)/10)&0xff:((val)+5)/10) & 0xff)
70#define TEMP_FROM_REG(val) (((val)>0x80?(val)-0x100:(val))*10)
71
72#define VID_FROM_REG(val) ((val)==0x1f?0:(val)>=0x10?510-(val)*10:\
73                           (val)>=0x06?0:205-(val)*5)
74#define ALARMS_FROM_REG(val) (val)
75
76#define DIV_FROM_REG(val) (1 << (val))
77#define DIV_TO_REG(val) ((val)==8?3:(val)==4?2:(val)==1?0:1)
78
79/* Initial limits */
80#define LM80_INIT_IN_0 (vid==350?280:vid)
81#define LM80_INIT_IN_1 (vid==350?280:vid)
82#define LM80_INIT_IN_2 330
83#define LM80_INIT_IN_3 500
84#define LM80_INIT_IN_4 1200
85#define LM80_INIT_IN_5 -1200
86#define LM80_INIT_IN_6 -500
87
88#define LM80_INIT_IN_PERCENTAGE 10
89
90#define LM80_INIT_IN_MIN_0 \
91        (LM80_INIT_IN_0 - LM80_INIT_IN_0 * LM80_INIT_IN_PERCENTAGE / 100)
92#define LM80_INIT_IN_MAX_0 \
93        (LM80_INIT_IN_0 + LM80_INIT_IN_0 * LM80_INIT_IN_PERCENTAGE / 100)
94#define LM80_INIT_IN_MIN_1 \
95        (LM80_INIT_IN_1 - LM80_INIT_IN_1 * LM80_INIT_IN_PERCENTAGE / 100)
96#define LM80_INIT_IN_MAX_1 \
97        (LM80_INIT_IN_1 + LM80_INIT_IN_1 * LM80_INIT_IN_PERCENTAGE / 100)
98#define LM80_INIT_IN_MIN_2 \
99        (LM80_INIT_IN_2 - LM80_INIT_IN_2 * LM80_INIT_IN_PERCENTAGE / 100)
100#define LM80_INIT_IN_MAX_2 \
101        (LM80_INIT_IN_2 + LM80_INIT_IN_2 * LM80_INIT_IN_PERCENTAGE / 100)
102#define LM80_INIT_IN_MIN_3 \
103        (LM80_INIT_IN_3 - LM80_INIT_IN_3 * LM80_INIT_IN_PERCENTAGE / 100)
104#define LM80_INIT_IN_MAX_3 \
105        (LM80_INIT_IN_3 + LM80_INIT_IN_3 * LM80_INIT_IN_PERCENTAGE / 100)
106#define LM80_INIT_IN_MIN_4 \
107        (LM80_INIT_IN_4 - LM80_INIT_IN_4 * LM80_INIT_IN_PERCENTAGE / 100)
108#define LM80_INIT_IN_MAX_4 \
109        (LM80_INIT_IN_4 + LM80_INIT_IN_4 * LM80_INIT_IN_PERCENTAGE / 100)
110#define LM80_INIT_IN_MIN_5 \
111        (LM80_INIT_IN_5 - LM80_INIT_IN_5 * LM80_INIT_IN_PERCENTAGE / 100)
112#define LM80_INIT_IN_MAX_5 \
113        (LM80_INIT_IN_5 + LM80_INIT_IN_5 * LM80_INIT_IN_PERCENTAGE / 100)
114#define LM80_INIT_IN_MIN_6 \
115        (LM80_INIT_IN_6 - LM80_INIT_IN_6 * LM80_INIT_IN_PERCENTAGE / 100)
116#define LM80_INIT_IN_MAX_6 \
117        (LM80_INIT_IN_6 + LM80_INIT_IN_6 * LM80_INIT_IN_PERCENTAGE / 100)
118
119#define LM80_INIT_FAN_MIN_1 3000
120#define LM80_INIT_FAN_MIN_2 3000
121#define LM80_INIT_FAN_MIN_3 3000
122
123#define LM80_INIT_TEMP_OVER 600
124#define LM80_INIT_TEMP_HYST 500
125
126#ifdef MODULE
127extern int init_module(void);
128extern int cleanup_module(void);
129#endif /* MODULE */
130
131/* This module may seem overly long and complicated. In fact, it is not so
132   bad. Quite a lot of bookkeeping is done. A real driver can often cut
133   some corners. */
134
135/* For each registered LM80, we need to keep some data in memory. That
136   data is pointed to by lm80_list[NR]->data. The structure itself is
137   dynamically allocated, at the same time when a new lm80 client is
138   allocated. */
139struct lm80_data {
140         struct semaphore lock;
141         int sysctl_id;
142
143         struct semaphore update_lock;
144         char valid;                 /* !=0 if following fields are valid */
145         unsigned long last_updated; /* In jiffies */
146
147         u8 in[7];                   /* Register value */
148         u8 in_max[7];               /* Register value */
149         u8 in_min[7];               /* Register value */
150         u8 fan[3];                  /* Register value */
151         u8 fan_min[3];              /* Register value */
152         u8 temp;                    /* Register value */
153         u8 temp_over;               /* Register value */
154         u8 temp_hyst;               /* Register value */
155         u8 fan_div[2];              /* Register encoding, shifted right */
156         u8 vid;                     /* Register encoding, combined */
157         u16 alarms;                 /* Register encoding, combined */
158};
159
160
161static int lm80_init(void);
162static int lm80_cleanup(void);
163
164static int lm80_attach_adapter(struct i2c_adapter *adapter);
165static int lm80_detect_smbus(struct i2c_adapter *adapter);
166static int lm80_detach_client(struct i2c_client *client);
167static int lm80_detach_smbus(struct i2c_client *client);
168static int lm80_new_client(struct i2c_adapter *adapter,
169                           struct i2c_client *new_client);
170static void lm80_remove_client(struct i2c_client *client);
171static int lm80_command(struct i2c_client *client, unsigned int cmd, 
172                        void *arg);
173static void lm80_inc_use (struct i2c_client *client);
174static void lm80_dec_use (struct i2c_client *client);
175
176static int lm80_read_value(struct i2c_client *client, u8 register);
177static int lm80_write_value(struct i2c_client *client, u8 register, u8 value);
178static void lm80_update_client(struct i2c_client *client);
179static void lm80_init_client(struct i2c_client *client);
180
181
182static void lm80_in(struct i2c_client *client, int operation, int ctl_name,
183                    int *nrels_mag, long *results);
184static void lm80_fan(struct i2c_client *client, int operation, int ctl_name,
185                     int *nrels_mag, long *results);
186static void lm80_temp(struct i2c_client *client, int operation, int ctl_name,
187                      int *nrels_mag, long *results);
188static void lm80_vid(struct i2c_client *client, int operation, int ctl_name,
189                     int *nrels_mag, long *results);
190static void lm80_alarms(struct i2c_client *client, int operation, int ctl_name,
191                        int *nrels_mag, long *results);
192static void lm80_fan_div(struct i2c_client *client, int operation, int ctl_name,
193                         int *nrels_mag, long *results);
194
195/* I choose here for semi-static LM80 allocation. Complete dynamic
196   allocation could also be used; the code needed for this would probably
197   take more memory than the datastructure takes now. */
198#define MAX_LM80_NR 4
199static struct i2c_client *lm80_list[MAX_LM80_NR];
200
201/* The driver. I choose to use type i2c_driver, as at is identical to both
202   smbus_driver and isa_driver, and clients could be of either kind */
203static struct i2c_driver lm80_driver = {
204  /* name */            "LM80 sensor driver",
205  /* id */              I2C_DRIVERID_LM80,
206  /* flags */           DF_NOTIFY,
207  /* attach_adapter */  &lm80_attach_adapter,
208  /* detach_client */   &lm80_detach_client,
209  /* command */         &lm80_command,
210  /* inc_use */         &lm80_inc_use,
211  /* dec_use */         &lm80_dec_use
212};
213
214/* Used by lm80_init/cleanup */
215static int lm80_initialized = 0;
216
217/* The /proc/sys entries */
218/* These files are created for each detected LM80. This is just a template;
219   though at first sight, you might think we could use a statically
220   allocated list, we need some way to get back to the parent - which
221   is done through one of the 'extra' fields which are initialized
222   when a new copy is allocated. */
223static ctl_table lm80_dir_table_template[] = {
224  { LM80_SYSCTL_IN0, "in0", NULL, 0, 0644, NULL, &sensors_proc_real,
225    &sensors_sysctl_real, NULL, &lm80_in },
226  { LM80_SYSCTL_IN1, "in1", NULL, 0, 0644, NULL, &sensors_proc_real,
227    &sensors_sysctl_real, NULL, &lm80_in },
228  { LM80_SYSCTL_IN2, "in2", NULL, 0, 0644, NULL, &sensors_proc_real,
229    &sensors_sysctl_real, NULL, &lm80_in },
230  { LM80_SYSCTL_IN3, "in3", NULL, 0, 0644, NULL, &sensors_proc_real,
231    &sensors_sysctl_real, NULL, &lm80_in },
232  { LM80_SYSCTL_IN4, "in4", NULL, 0, 0644, NULL, &sensors_proc_real,
233    &sensors_sysctl_real, NULL, &lm80_in },
234  { LM80_SYSCTL_IN5, "in5", NULL, 0, 0644, NULL, &sensors_proc_real,
235    &sensors_sysctl_real, NULL, &lm80_in },
236  { LM80_SYSCTL_IN6, "in6", NULL, 0, 0644, NULL, &sensors_proc_real,
237    &sensors_sysctl_real, NULL, &lm80_in },
238  { LM80_SYSCTL_FAN1, "fan1", NULL, 0, 0644, NULL, &sensors_proc_real,
239    &sensors_sysctl_real, NULL, &lm80_fan },
240  { LM80_SYSCTL_FAN2, "fan2", NULL, 0, 0644, NULL, &sensors_proc_real,
241    &sensors_sysctl_real, NULL, &lm80_fan },
242  { LM80_SYSCTL_FAN3, "fan3", NULL, 0, 0644, NULL, &sensors_proc_real,
243    &sensors_sysctl_real, NULL, &lm80_fan },
244  { LM80_SYSCTL_TEMP, "temp", NULL, 0, 0644, NULL, &sensors_proc_real,
245    &sensors_sysctl_real, NULL, &lm80_temp },
246  { LM80_SYSCTL_VID, "vid", NULL, 0, 0644, NULL, &sensors_proc_real,
247    &sensors_sysctl_real, NULL, &lm80_vid },
248  { LM80_SYSCTL_FAN_DIV, "fan_div", NULL, 0, 0644, NULL, &sensors_proc_real,
249    &sensors_sysctl_real, NULL, &lm80_fan_div },
250  { LM80_SYSCTL_ALARMS, "alarms", NULL, 0, 0644, NULL, &sensors_proc_real,
251    &sensors_sysctl_real, NULL, &lm80_alarms },
252  { 0 }
253};
254
255
256/* This function is called when:
257     * lm80_driver is inserted (when this module is loaded), for each
258       available adapter
259     * when a new adapter is inserted (and lm80_driver is still present) */
260int lm80_attach_adapter(struct i2c_adapter *adapter)
261{
262    return lm80_detect_smbus(adapter);
263}
264
265/* This function is called whenever a client should be removed:
266    * lm80_driver is removed (when this module is unloaded)
267    * when an adapter is removed which has a lm80 client (and lm80_driver
268      is still present). */
269int lm80_detach_client(struct i2c_client *client)
270{
271    return lm80_detach_smbus(client);
272}
273
274int lm80_detect_smbus(struct i2c_adapter *adapter)
275{
276  int address,err;
277  struct i2c_client *new_client;
278  const char *type_name,*client_name;
279
280  /* OK, this is no detection. I know. It will do for now, though.  */
281  err = 0;
282  for (address = 0x20; (! err) && (address <= 0x2f); address ++) {
283
284    /* Later on, we will keep a list of registered addresses for each
285       adapter, and check whether they are used here */
286
287    if (smbus_read_byte_data(adapter,address,LM80_REG_CONFIG) < 0) 
288      continue;
289
290    /* Real detection code goes here */
291
292    err = smbus_read_byte_data(adapter,address,LM80_REG_CHIPID) & 0xfe;
293
294    printk("lm80.o: LM80 detected\n");
295    type_name = "lm80";
296    client_name = "LM80 chip";
297
298
299    /* Allocate space for a new client structure. To counter memory
300       ragmentation somewhat, we only do one kmalloc. */
301    if (! (new_client = kmalloc(sizeof(struct i2c_client) + 
302                                sizeof(struct lm80_data),
303                               GFP_KERNEL))) {
304      err = -ENOMEM;
305      continue;
306    }
307
308    /* Fill the new client structure with data */
309    new_client->data = (struct lm80_data *) (new_client + 1);
310    new_client->addr = address;
311    strcpy(new_client->name,client_name);
312    if ((err = lm80_new_client(adapter,new_client)))
313      goto ERROR2;
314
315    /* Tell i2c-core a new client has arrived */
316    if ((err = i2c_attach_client(new_client))) 
317      goto ERROR3;
318
319    /* Register a new directory entry with module sensors */
320    if ((err = sensors_register_entry(new_client,type_name,
321                                      lm80_dir_table_template)) < 0)
322      goto ERROR4;
323    ((struct lm80_data *) (new_client->data))->sysctl_id = err;
324    err = 0;
325
326    /* Initialize the LM80 chip */
327    lm80_init_client(new_client);
328    continue;
329
330/* OK, this is not exactly good programming practice, usually. But it is
331   very code-efficient in this case. */
332ERROR4:
333    i2c_detach_client(new_client);
334ERROR3:
335    lm80_remove_client((struct i2c_client *) new_client);
336ERROR2:
337    kfree(new_client);
338  }
339  return err;
340}
341
342int lm80_detach_smbus(struct i2c_client *client)
343{
344  int err,i;
345  for (i = 0; i < MAX_LM80_NR; i++)
346    if (client == lm80_list[i])
347      break;
348  if ((i == MAX_LM80_NR)) {
349    printk("lm80.o: Client to detach not found.\n");
350    return -ENOENT;
351  }
352
353  sensors_deregister_entry(((struct lm80_data *)(client->data))->sysctl_id);
354
355  if ((err = i2c_detach_client(client))) {
356    printk("lm80.o: Client deregistration failed, client not detached.\n");
357    return err;
358  }
359  lm80_remove_client(client);
360  kfree(client);
361  return 0;
362}
363
364
365/* Find a free slot, and initialize most of the fields */
366int lm80_new_client(struct i2c_adapter *adapter,
367                    struct i2c_client *new_client)
368{
369  int i;
370  struct lm80_data *data;
371
372  /* First, seek out an empty slot */
373  for(i = 0; i < MAX_LM80_NR; i++)
374    if (! lm80_list[i])
375      break;
376  if (i == MAX_LM80_NR) {
377    printk("lm80.o: No empty slots left, recompile and heighten "
378           "MAX_LM80_NR!\n");
379    return -ENOMEM;
380  }
381 
382  lm80_list[i] = new_client;
383  new_client->id = i;
384  new_client->adapter = adapter;
385  new_client->driver = &lm80_driver;
386  data = new_client->data;
387  data->valid = 0;
388  data->lock = MUTEX;
389  data->update_lock = MUTEX;
390  return 0;
391}
392
393/* Inverse of lm80_new_client */
394void lm80_remove_client(struct i2c_client *client)
395{
396  int i;
397  for (i = 0; i < MAX_LM80_NR; i++)
398    if (client == lm80_list[i]) 
399      lm80_list[i] = NULL;
400}
401
402/* No commands defined yet */
403int lm80_command(struct i2c_client *client, unsigned int cmd, void *arg)
404{
405  return 0;
406}
407
408/* Nothing here yet */
409void lm80_inc_use (struct i2c_client *client)
410{
411#ifdef MODULE
412  MOD_INC_USE_COUNT;
413#endif
414}
415
416/* Nothing here yet */
417void lm80_dec_use (struct i2c_client *client)
418{
419#ifdef MODULE
420  MOD_DEC_USE_COUNT;
421#endif
422}
423 
424
425/* The SMBus locks itself, but ISA access must be locked explicitely!
426   We ignore the LM80 BUSY flag at this moment - it could lead to deadlocks,
427   would slow down the LM80 access and should not be necessary.
428   There are some ugly typecasts here, but the good new is - they should
429   nowhere else be necessary! */
430int lm80_read_value(struct i2c_client *client, u8 reg)
431{
432  int res;
433  if (i2c_is_isa_client(client)) {
434    down((struct semaphore *) (client->data));
435    outb_p(reg,(((struct isa_client *) client)->isa_addr) + 
436               LM80_ADDR_REG_OFFSET);
437    res = inb_p((((struct isa_client *) client)->isa_addr) + 
438                LM80_DATA_REG_OFFSET);
439    up((struct semaphore *) (client->data));
440    return res;
441  } else
442    return smbus_read_byte_data(client->adapter,client->addr, reg);
443}
444
445/* The SMBus locks itself, but ISA access muse be locked explicitely!
446   We ignore the LM80 BUSY flag at this moment - it could lead to deadlocks,
447   would slow down the LM80 access and should not be necessary.
448   There are some ugly typecasts here, but the good new is - they should
449   nowhere else be necessary! */
450int lm80_write_value(struct i2c_client *client, u8 reg, u8 value)
451{
452  if (i2c_is_isa_client(client)) {
453    down((struct semaphore *) (client->data));
454    outb_p(reg,((struct isa_client *) client)->isa_addr + LM80_ADDR_REG_OFFSET);
455    outb_p(value,((struct isa_client *) client)->isa_addr + LM80_DATA_REG_OFFSET);
456    up((struct semaphore *) (client->data));
457    return 0;
458  } else
459    return smbus_write_byte_data(client->adapter, client->addr, reg,value);
460}
461
462/* Called when we have found a new LM80. It should set limits, etc. */
463void lm80_init_client(struct i2c_client *client)
464{
465  int vid;
466
467  /* Reset all except Watchdog values and last conversion values
468     This sets fan-divs to 2, among others */
469  lm80_write_value(client,LM80_REG_CONFIG,0x80);
470
471  vid = lm80_read_value(client,LM80_REG_VID_FANDIV) & 0x0f;
472  vid |= (lm80_read_value(client,LM80_REG_CHIPID) & 0x01) >> 4;
473  vid = VID_FROM_REG(vid);
474
475  lm80_write_value(client,LM80_REG_IN_MIN(0),IN_TO_REG(LM80_INIT_IN_MIN_0,0));
476  lm80_write_value(client,LM80_REG_IN_MAX(0),IN_TO_REG(LM80_INIT_IN_MAX_0,0));
477  lm80_write_value(client,LM80_REG_IN_MIN(1),IN_TO_REG(LM80_INIT_IN_MIN_1,1));
478  lm80_write_value(client,LM80_REG_IN_MAX(1),IN_TO_REG(LM80_INIT_IN_MAX_1,1));
479  lm80_write_value(client,LM80_REG_IN_MIN(2),IN_TO_REG(LM80_INIT_IN_MIN_2,2));
480  lm80_write_value(client,LM80_REG_IN_MAX(2),IN_TO_REG(LM80_INIT_IN_MAX_2,2));
481  lm80_write_value(client,LM80_REG_IN_MIN(3),IN_TO_REG(LM80_INIT_IN_MIN_3,3));
482  lm80_write_value(client,LM80_REG_IN_MAX(3),IN_TO_REG(LM80_INIT_IN_MAX_3,3));
483  lm80_write_value(client,LM80_REG_IN_MIN(4),IN_TO_REG(LM80_INIT_IN_MIN_4,4));
484  lm80_write_value(client,LM80_REG_IN_MAX(4),IN_TO_REG(LM80_INIT_IN_MAX_4,4));
485  lm80_write_value(client,LM80_REG_IN_MIN(5),IN_TO_REG(LM80_INIT_IN_MIN_5,5));
486  lm80_write_value(client,LM80_REG_IN_MAX(5),IN_TO_REG(LM80_INIT_IN_MAX_5,5));
487  lm80_write_value(client,LM80_REG_IN_MIN(6),IN_TO_REG(LM80_INIT_IN_MIN_6,6));
488  lm80_write_value(client,LM80_REG_IN_MAX(6),IN_TO_REG(LM80_INIT_IN_MAX_6,6));
489  lm80_write_value(client,LM80_REG_FAN_MIN(1),FAN_TO_REG(LM80_INIT_FAN_MIN_1));
490  lm80_write_value(client,LM80_REG_FAN_MIN(2),FAN_TO_REG(LM80_INIT_FAN_MIN_2));
491  lm80_write_value(client,LM80_REG_FAN_MIN(3),FAN_TO_REG(LM80_INIT_FAN_MIN_3));
492  lm80_write_value(client,LM80_REG_TEMP_OVER,TEMP_TO_REG(LM80_INIT_TEMP_OVER));
493  lm80_write_value(client,LM80_REG_TEMP_HYST,TEMP_TO_REG(LM80_INIT_TEMP_HYST));
494
495  /* Start monitoring */
496  lm80_write_value(client,LM80_REG_CONFIG,
497                   (lm80_read_value(client,LM80_REG_CONFIG) & 0xf7) | 0x01);
498 
499}
500
501void lm80_update_client(struct i2c_client *client)
502{
503  struct lm80_data *data = client->data;
504  int i;
505
506  down(&data->update_lock);
507
508  if ((jiffies - data->last_updated > HZ+HZ/2 ) ||
509      (jiffies < data->last_updated) || ! data->valid) {
510
511#ifdef DEBUG
512    printk("Starting lm80 update\n");
513#endif
514    for (i = 0; i <= 6; i++) {
515      data->in[i]     = lm80_read_value(client,LM80_REG_IN(i));
516      data->in_min[i] = lm80_read_value(client,LM80_REG_IN_MIN(i));
517      data->in_max[i] = lm80_read_value(client,LM80_REG_IN_MAX(i));
518    }
519    for (i = 1; i <= 3; i++) {
520      data->fan[i-1] = lm80_read_value(client,LM80_REG_FAN(i));
521      data->fan_min[i-1] = lm80_read_value(client,LM80_REG_FAN_MIN(i));
522    }
523    data->temp = lm80_read_value(client,LM80_REG_TEMP);
524    data->temp_over = lm80_read_value(client,LM80_REG_TEMP_OVER);
525    data->temp_hyst = lm80_read_value(client,LM80_REG_TEMP_HYST);
526    i = lm80_read_value(client,LM80_REG_VID_FANDIV);
527    data->vid = i & 0x0f;
528    data->vid |= (lm80_read_value(client,LM80_REG_CHIPID) & 0x01) >> 4;
529    data->fan_div[0] = (i >> 4) & 0x03;
530    data->fan_div[1] = i >> 6;
531    data->alarms = lm80_read_value(client,LM80_REG_ALARM1) +
532                   (lm80_read_value(client,LM80_REG_ALARM2) >> 8);
533    data->last_updated = jiffies;
534    data->valid = 1;
535  }
536
537  up(&data->update_lock);
538}
539
540
541/* The next few functions are the call-back functions of the /proc/sys and
542   sysctl files. Which function is used is defined in the ctl_table in
543   the extra1 field.
544   Each function must return the magnitude (power of 10 to divide the date
545   with) if it is called with operation==SENSORS_PROC_REAL_INFO. It must
546   put a maximum of *nrels elements in results reflecting the data of this
547   file, and set *nrels to the number it actually put in it, if operation==
548   SENSORS_PROC_REAL_READ. Finally, it must get upto *nrels elements from
549   results and write them to the chip, if operations==SENSORS_PROC_REAL_WRITE.
550   Note that on SENSORS_PROC_REAL_READ, I do not check whether results is
551   large enough (by checking the incoming value of *nrels). This is not very
552   good practice, but as long as you put less than about 5 values in results,
553   you can assume it is large enough. */
554void lm80_in(struct i2c_client *client, int operation, int ctl_name, 
555             int *nrels_mag, long *results)
556{
557  struct lm80_data *data = client->data;
558  int nr = ctl_name - LM80_SYSCTL_IN0;
559
560  if (operation == SENSORS_PROC_REAL_INFO)
561    *nrels_mag = 2;
562  else if (operation == SENSORS_PROC_REAL_READ) {
563    lm80_update_client(client);
564    results[0] = IN_FROM_REG(data->in_min[nr],nr);
565    results[1] = IN_FROM_REG(data->in_max[nr],nr);
566    results[2] = IN_FROM_REG(data->in[nr],nr);
567    *nrels_mag = 3;
568  } else if (operation == SENSORS_PROC_REAL_WRITE) {
569      if (*nrels_mag >= 1) {
570        data->in_min[nr] = IN_TO_REG(results[0],nr);
571        lm80_write_value(client,LM80_REG_IN_MIN(nr),data->in_min[nr]);
572      }
573      if (*nrels_mag >= 2) {
574        data->in_max[nr] = IN_TO_REG(results[1],nr);
575        lm80_write_value(client,LM80_REG_IN_MAX(nr),data->in_max[nr]);
576      }
577  }
578}
579
580void lm80_fan(struct i2c_client *client, int operation, int ctl_name,
581              int *nrels_mag, long *results)
582{
583  struct lm80_data *data = client->data;
584  int nr = ctl_name - LM80_SYSCTL_FAN1 + 1;
585
586  if (operation == SENSORS_PROC_REAL_INFO)
587    *nrels_mag = 0;
588  else if (operation == SENSORS_PROC_REAL_READ) {
589    lm80_update_client(client);
590    results[0] = FAN_FROM_REG(data->fan_min[nr-1]);
591    results[1] = FAN_FROM_REG(data->fan[nr-1]);
592    *nrels_mag = 2;
593  } else if (operation == SENSORS_PROC_REAL_WRITE) {
594    if (*nrels_mag >= 1) {
595      data->fan_min[nr-1] = FAN_TO_REG(results[0]);
596      lm80_write_value(client,LM80_REG_FAN_MIN(nr),data->fan_min[nr-1]);
597    }
598  }
599}
600
601
602void lm80_temp(struct i2c_client *client, int operation, int ctl_name,
603               int *nrels_mag, long *results)
604{
605  struct lm80_data *data = client->data;
606  if (operation == SENSORS_PROC_REAL_INFO)
607    *nrels_mag = 1;
608  else if (operation == SENSORS_PROC_REAL_READ) {
609    lm80_update_client(client);
610    results[0] = TEMP_FROM_REG(data->temp_over);
611    results[1] = TEMP_FROM_REG(data->temp_hyst);
612    results[2] = TEMP_FROM_REG(data->temp);
613    *nrels_mag = 3;
614  } else if (operation == SENSORS_PROC_REAL_WRITE) {
615    if (*nrels_mag >= 1) {
616      data->temp_over = TEMP_TO_REG(results[0]);
617      lm80_write_value(client,LM80_REG_TEMP_OVER,data->temp_over);
618    }
619    if (*nrels_mag >= 2) {
620      data->temp_hyst = TEMP_TO_REG(results[1]);
621      lm80_write_value(client,LM80_REG_TEMP_HYST,data->temp_hyst);
622    }
623  }
624}
625
626void lm80_vid(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] = VID_FROM_REG(data->vid);
635    *nrels_mag = 1;
636  }
637}
638
639void lm80_alarms(struct i2c_client *client, int operation, int ctl_name,
640                 int *nrels_mag, long *results)
641{
642  struct lm80_data *data = client->data;
643  if (operation == SENSORS_PROC_REAL_INFO)
644    *nrels_mag = 0;
645  else if (operation == SENSORS_PROC_REAL_READ) {
646    lm80_update_client(client);
647    results[0] = ALARMS_FROM_REG(data->alarms);
648    *nrels_mag = 1;
649  }
650}
651
652void lm80_fan_div(struct i2c_client *client, int operation, int ctl_name,
653                  int *nrels_mag, long *results)
654{
655  struct lm80_data *data = client->data;
656  int old;
657
658  if (operation == SENSORS_PROC_REAL_INFO)
659    *nrels_mag = 0;
660  else if (operation == SENSORS_PROC_REAL_READ) {
661    lm80_update_client(client);
662    results[0] = DIV_FROM_REG(data->fan_div[0]);
663    results[1] = DIV_FROM_REG(data->fan_div[1]);
664    results[2] = 2;
665    *nrels_mag = 3;
666  } else if (operation == SENSORS_PROC_REAL_WRITE) {
667    old = lm80_read_value(client,LM80_REG_VID_FANDIV);
668    if (*nrels_mag >= 2) {
669      data->fan_div[1] = DIV_TO_REG(results[1]);
670      old = (old & 0x3f) | (data->fan_div[1] << 6);
671    }
672    if (*nrels_mag >= 1) {
673      data->fan_div[0] = DIV_TO_REG(results[0]);
674      old = (old & 0xcf) | (data->fan_div[0] << 4);
675      lm80_write_value(client,LM80_REG_VID_FANDIV,old);
676    }
677  }
678}
679
680int lm80_init(void)
681{
682  int res;
683
684  printk("lm80.o version %s (%s)\n",LM_VERSION,LM_DATE);
685  lm80_initialized = 0;
686
687  if ((res =i2c_add_driver(&lm80_driver))) {
688    printk("lm80.o: Driver registration failed, module not inserted.\n");
689    lm80_cleanup();
690    return res;
691  }
692  lm80_initialized ++;
693  return 0;
694}
695
696int lm80_cleanup(void)
697{
698  int res;
699
700  if (lm80_initialized >= 1) {
701    if ((res = i2c_del_driver(&lm80_driver))) {
702      printk("lm80.o: Driver deregistration failed, module not removed.\n");
703      return res;
704    }
705    lm80_initialized --;
706  }
707  return 0;
708}
709
710
711#ifdef MODULE
712
713MODULE_AUTHOR("Frodo Looijaard <frodol@dds.nl> and Philip Edelbrock <phil@netroedge.com>");
714MODULE_DESCRIPTION("LM80 driver");
715
716int init_module(void)
717{
718  return lm80_init();
719}
720
721int cleanup_module(void)
722{
723  return lm80_cleanup();
724}
725
726#endif /* MODULE */
727
Note: See TracBrowser for help on using the browser.