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

Revision 516, 28.5 KB (checked in by frodo, 14 years ago)

(Frodo) Massive commit of all things related to mkpatch. Let's just say

it works great now.

  • 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/malloc.h>
23#include <linux/proc_fs.h>
24#include <linux/ioport.h>
25#include <linux/sysctl.h>
26#include <asm/errno.h>
27#include <asm/io.h>
28#include <linux/types.h>
29#include <linux/i2c.h>
30#include "version.h"
31#include "i2c-isa.h"
32#include "sensors.h"
33#include "compat.h"
34
35#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,1,53)
36#include <linux/init.h>
37#else
38#define __init
39#define __initdata
40#endif
41
42
43/* Addresses to scan */
44static unsigned short normal_i2c[] = {SENSORS_I2C_END};
45static unsigned short normal_i2c_range[] = {0x20,0x2f,SENSORS_I2C_END};
46static unsigned int normal_isa[] = {0x0290,SENSORS_ISA_END};
47static unsigned int normal_isa_range[] = {SENSORS_ISA_END};
48
49/* Insmod parameters */
50SENSORS_INSMOD_3(lm78,lm78j,lm79);
51
52/* Many LM78 constants specified below */
53
54/* Length of ISA address segment */
55#define LM78_EXTENT 8
56
57/* Where are the ISA address/data registers relative to the base address */
58#define LM78_ADDR_REG_OFFSET 5
59#define LM78_DATA_REG_OFFSET 6
60
61/* The LM78 registers */
62#define LM78_REG_IN_MAX(nr) (0x2b + (nr) * 2)
63#define LM78_REG_IN_MIN(nr) (0x2c + (nr) * 2)
64#define LM78_REG_IN(nr) (0x20 + (nr))
65
66#define LM78_REG_FAN_MIN(nr) (0x3a + (nr))
67#define LM78_REG_FAN(nr) (0x27 + (nr))
68
69#define LM78_REG_TEMP 0x27
70#define LM78_REG_TEMP_OVER 0x39
71#define LM78_REG_TEMP_HYST 0x3a
72
73#define LM78_REG_ALARM1 0x41
74#define LM78_REG_ALARM2 0x42
75
76#define LM78_REG_VID_FANDIV 0x47
77
78#define LM78_REG_CONFIG 0x40
79#define LM78_REG_CHIPID 0x49
80#define LM78_REG_I2C_ADDR 0x48
81
82
83/* Conversions. Rounding and limit checking is only done on the TO_REG
84   variants. Note that you should be a bit careful with which arguments
85   these macros are called: arguments may be evaluated more than once.
86   Fixing this is just not worth it. */
87#define IN_TO_REG(val)  (SENSORS_LIMIT((((val) * 10 + 8)/16),0,255))
88#define IN_FROM_REG(val) (((val) *  16) / 10)
89
90extern inline u8 FAN_TO_REG(long rpm, int div)
91{
92  if (rpm == 0)
93    return 255;
94  rpm = SENSORS_LIMIT(rpm,1,1000000);
95  return SENSORS_LIMIT((1350000 + rpm*div/2) / (rpm*div),1,254);
96}
97
98#define FAN_FROM_REG(val,div) ((val)==0?-1:(val)==255?0:1350000/((val)*(div)))
99
100#define TEMP_TO_REG(val) (SENSORS_LIMIT(((val)<0?(((val)-5)/10):\
101                                                 ((val)+5)/10),0,255))
102#define TEMP_FROM_REG(val) (((val)>0x80?(val)-0x100:(val))*10)
103
104#define VID_FROM_REG(val) ((val)==0x1f?0:(val)>=0x10?510-(val)*10:\
105                           (val)>=0x06?0:205-(val)*5)
106#define ALARMS_FROM_REG(val) (val)
107
108#define DIV_TO_REG(val) ((val)==8?3:(val)==4?2:(val)==1?0:1)
109#define DIV_FROM_REG(val) (1 << (val))
110
111/* Initial limits. To keep them sane, we use the 'standard' translation as
112   specified in the LM78 sheet. Use the config file to set better limits. */
113#define LM78_INIT_IN_0 (vid==350?280:vid)
114#define LM78_INIT_IN_1 (vid==350?280:vid)
115#define LM78_INIT_IN_2 330
116#define LM78_INIT_IN_3 (((500)   * 100)/168)
117#define LM78_INIT_IN_4 (((1200)  * 10)/38)
118#define LM78_INIT_IN_5 (((-1200) * -604)/2100)
119#define LM78_INIT_IN_6 (((-500)  * -604)/909)
120
121#define LM78_INIT_IN_PERCENTAGE 10
122
123#define LM78_INIT_IN_MIN_0 \
124        (LM78_INIT_IN_0 - LM78_INIT_IN_0 * LM78_INIT_IN_PERCENTAGE / 100)
125#define LM78_INIT_IN_MAX_0 \
126        (LM78_INIT_IN_0 + LM78_INIT_IN_0 * LM78_INIT_IN_PERCENTAGE / 100)
127#define LM78_INIT_IN_MIN_1 \
128        (LM78_INIT_IN_1 - LM78_INIT_IN_1 * LM78_INIT_IN_PERCENTAGE / 100)
129#define LM78_INIT_IN_MAX_1 \
130        (LM78_INIT_IN_1 + LM78_INIT_IN_1 * LM78_INIT_IN_PERCENTAGE / 100)
131#define LM78_INIT_IN_MIN_2 \
132        (LM78_INIT_IN_2 - LM78_INIT_IN_2 * LM78_INIT_IN_PERCENTAGE / 100)
133#define LM78_INIT_IN_MAX_2 \
134        (LM78_INIT_IN_2 + LM78_INIT_IN_2 * LM78_INIT_IN_PERCENTAGE / 100)
135#define LM78_INIT_IN_MIN_3 \
136        (LM78_INIT_IN_3 - LM78_INIT_IN_3 * LM78_INIT_IN_PERCENTAGE / 100)
137#define LM78_INIT_IN_MAX_3 \
138        (LM78_INIT_IN_3 + LM78_INIT_IN_3 * LM78_INIT_IN_PERCENTAGE / 100)
139#define LM78_INIT_IN_MIN_4 \
140        (LM78_INIT_IN_4 - LM78_INIT_IN_4 * LM78_INIT_IN_PERCENTAGE / 100)
141#define LM78_INIT_IN_MAX_4 \
142        (LM78_INIT_IN_4 + LM78_INIT_IN_4 * LM78_INIT_IN_PERCENTAGE / 100)
143#define LM78_INIT_IN_MIN_5 \
144        (LM78_INIT_IN_5 - LM78_INIT_IN_5 * LM78_INIT_IN_PERCENTAGE / 100)
145#define LM78_INIT_IN_MAX_5 \
146        (LM78_INIT_IN_5 + LM78_INIT_IN_5 * LM78_INIT_IN_PERCENTAGE / 100)
147#define LM78_INIT_IN_MIN_6 \
148        (LM78_INIT_IN_6 - LM78_INIT_IN_6 * LM78_INIT_IN_PERCENTAGE / 100)
149#define LM78_INIT_IN_MAX_6 \
150        (LM78_INIT_IN_6 + LM78_INIT_IN_6 * LM78_INIT_IN_PERCENTAGE / 100)
151
152#define LM78_INIT_FAN_MIN_1 3000
153#define LM78_INIT_FAN_MIN_2 3000
154#define LM78_INIT_FAN_MIN_3 3000
155
156#define LM78_INIT_TEMP_OVER 600
157#define LM78_INIT_TEMP_HYST 500
158
159#ifdef MODULE
160extern int init_module(void);
161extern int cleanup_module(void);
162#endif /* MODULE */
163
164/* There are some complications in a module like this. First off, LM78 chips
165   may be both present on the SMBus and the ISA bus, and we have to handle
166   those cases separately at some places. Second, there might be several
167   LM78 chips available (well, actually, that is probably never done; but
168   it is a clean illustration of how to handle a case like that). Finally,
169   a specific chip may be attached to *both* ISA and SMBus, and we would
170   not like to detect it double. Fortunately, in the case of the LM78 at
171   least, a register tells us what SMBus address we are on, so that helps
172   a bit - except if there could be more than one SMBus. Groan. No solution
173   for this yet. */
174
175/* This module may seem overly long and complicated. In fact, it is not so
176   bad. Quite a lot of bookkeeping is done. A real driver can often cut
177   some corners. */
178
179/* For each registered LM78, we need to keep some data in memory. That
180   data is pointed to by lm78_list[NR]->data. The structure itself is
181   dynamically allocated, at the same time when a new lm78 client is
182   allocated. */
183struct lm78_data {
184         struct semaphore lock;
185         int sysctl_id;
186         enum chips type;
187
188         struct semaphore update_lock;
189         char valid;                 /* !=0 if following fields are valid */
190         unsigned long last_updated; /* In jiffies */
191
192         u8 in[7];                   /* Register value */
193         u8 in_max[7];               /* Register value */
194         u8 in_min[7];               /* Register value */
195         u8 fan[3];                  /* Register value */
196         u8 fan_min[3];              /* Register value */
197         u8 temp;                    /* Register value */
198         u8 temp_over;               /* Register value */
199         u8 temp_hyst;               /* Register value */
200         u8 fan_div[3];              /* Register encoding, shifted right */
201         u8 vid;                     /* Register encoding, combined */
202         u16 alarms;                 /* Register encoding, combined */
203};
204
205
206#ifdef MODULE
207static
208#else
209extern
210#endif
211       int __init sensors_lm78_init(void);
212static int __init lm78_cleanup(void);
213
214static int lm78_attach_adapter(struct i2c_adapter *adapter);
215static int lm78_detect(struct i2c_adapter *adapter, int address, int kind);
216static int lm78_detach_client(struct i2c_client *client);
217static int lm78_command(struct i2c_client *client, unsigned int cmd, 
218                        void *arg);
219static void lm78_inc_use (struct i2c_client *client);
220static void lm78_dec_use (struct i2c_client *client);
221
222static int lm78_read_value(struct i2c_client *client, u8 register);
223static int lm78_write_value(struct i2c_client *client, u8 register, u8 value);
224static void lm78_update_client(struct i2c_client *client);
225static void lm78_init_client(struct i2c_client *client);
226
227
228static void lm78_in(struct i2c_client *client, int operation, int ctl_name,
229                    int *nrels_mag, long *results);
230static void lm78_fan(struct i2c_client *client, int operation, int ctl_name,
231                     int *nrels_mag, long *results);
232static void lm78_temp(struct i2c_client *client, int operation, int ctl_name,
233                      int *nrels_mag, long *results);
234static void lm78_vid(struct i2c_client *client, int operation, int ctl_name,
235                     int *nrels_mag, long *results);
236static void lm78_alarms(struct i2c_client *client, int operation, int ctl_name,
237                        int *nrels_mag, long *results);
238static void lm78_fan_div(struct i2c_client *client, int operation, int ctl_name,
239                         int *nrels_mag, long *results);
240
241/* I choose here for semi-static LM78 allocation. Complete dynamic
242   allocation could also be used; the code needed for this would probably
243   take more memory than the datastructure takes now. */
244#define MAX_LM78_NR 8
245static struct i2c_client *lm78_list[MAX_LM78_NR];
246
247static struct i2c_driver lm78_driver = {
248  /* name */            "LM78(-J) and LM79 sensor driver",
249  /* id */              I2C_DRIVERID_LM78,
250  /* flags */           I2C_DF_NOTIFY,
251  /* attach_adapter */  &lm78_attach_adapter,
252  /* detach_client */   &lm78_detach_client,
253  /* command */         &lm78_command,
254  /* inc_use */         &lm78_inc_use,
255  /* dec_use */         &lm78_dec_use
256};
257
258/* Used by lm78_init/cleanup */
259static int __initdata lm78_initialized = 0;
260
261/* The /proc/sys entries */
262/* These files are created for each detected LM78. This is just a template;
263   though at first sight, you might think we could use a statically
264   allocated list, we need some way to get back to the parent - which
265   is done through one of the 'extra' fields which are initialized
266   when a new copy is allocated. */
267static ctl_table lm78_dir_table_template[] = {
268  { LM78_SYSCTL_IN0, "in0", NULL, 0, 0644, NULL, &sensors_proc_real,
269    &sensors_sysctl_real, NULL, &lm78_in },
270  { LM78_SYSCTL_IN1, "in1", NULL, 0, 0644, NULL, &sensors_proc_real,
271    &sensors_sysctl_real, NULL, &lm78_in },
272  { LM78_SYSCTL_IN2, "in2", NULL, 0, 0644, NULL, &sensors_proc_real,
273    &sensors_sysctl_real, NULL, &lm78_in },
274  { LM78_SYSCTL_IN3, "in3", NULL, 0, 0644, NULL, &sensors_proc_real,
275    &sensors_sysctl_real, NULL, &lm78_in },
276  { LM78_SYSCTL_IN4, "in4", NULL, 0, 0644, NULL, &sensors_proc_real,
277    &sensors_sysctl_real, NULL, &lm78_in },
278  { LM78_SYSCTL_IN5, "in5", NULL, 0, 0644, NULL, &sensors_proc_real,
279    &sensors_sysctl_real, NULL, &lm78_in },
280  { LM78_SYSCTL_IN6, "in6", NULL, 0, 0644, NULL, &sensors_proc_real,
281    &sensors_sysctl_real, NULL, &lm78_in },
282  { LM78_SYSCTL_FAN1, "fan1", NULL, 0, 0644, NULL, &sensors_proc_real,
283    &sensors_sysctl_real, NULL, &lm78_fan },
284  { LM78_SYSCTL_FAN2, "fan2", NULL, 0, 0644, NULL, &sensors_proc_real,
285    &sensors_sysctl_real, NULL, &lm78_fan },
286  { LM78_SYSCTL_FAN3, "fan3", NULL, 0, 0644, NULL, &sensors_proc_real,
287    &sensors_sysctl_real, NULL, &lm78_fan },
288  { LM78_SYSCTL_TEMP, "temp", NULL, 0, 0644, NULL, &sensors_proc_real,
289    &sensors_sysctl_real, NULL, &lm78_temp },
290  { LM78_SYSCTL_VID, "vid", NULL, 0, 0444, NULL, &sensors_proc_real,
291    &sensors_sysctl_real, NULL, &lm78_vid },
292  { LM78_SYSCTL_FAN_DIV, "fan_div", NULL, 0, 0644, NULL, &sensors_proc_real,
293    &sensors_sysctl_real, NULL, &lm78_fan_div },
294  { LM78_SYSCTL_ALARMS, "alarms", NULL, 0, 0444, NULL, &sensors_proc_real,
295    &sensors_sysctl_real, NULL, &lm78_alarms },
296  { 0 }
297};
298
299
300/* This function is called when:
301     * lm78_driver is inserted (when this module is loaded), for each
302       available adapter
303     * when a new adapter is inserted (and lm78_driver is still present) */
304int lm78_attach_adapter(struct i2c_adapter *adapter)
305{
306  return sensors_detect(adapter,&addr_data,lm78_detect);
307}
308
309/* This function is called by sensors_detect */
310int lm78_detect(struct i2c_adapter *adapter, int address, int kind)
311{
312  int i;
313  struct i2c_client *new_client;
314  struct lm78_data *data;
315  int err=0;
316  const char *type_name = "";
317  const char *client_name = "";
318  int is_isa = i2c_is_isa_adapter(adapter);
319
320  /* We need address registration for the I2C bus too. That is not yet
321     implemented. */
322  if (is_isa) {
323    if (check_region(address,LM78_EXTENT))
324      goto ERROR0;
325  }
326
327  /* Probe whether there is anything available on this address. Already
328     done for SMBus clients */
329  if (kind < 0) {
330    if (is_isa) {
331
332#define REALLY_SLOW_IO
333      /* We need the timeouts for at least some LM78-like chips. But only
334         if we read 'undefined' registers. */
335      i = inb_p(address + 1);
336      if (inb_p(address + 2) != i)
337        goto ERROR0;
338      if (inb_p(address + 3) != i)
339        goto ERROR0;
340      if (inb_p(address + 7) != i)
341        goto ERROR0;
342#undef REALLY_SLOW_IO
343     
344      /* Let's just hope nothing breaks here */
345      i = inb_p(address + 5) & 0x7f;
346      outb_p(~i & 0x7f,address+5);
347      if ((inb_p(address + 5) & 0x7f) != (~i & 0x7f)) {
348        outb_p(i,address+5);
349        return 0;
350      }
351    }
352  }
353
354  /* OK. For now, we presume we have a valid client. We now create the
355     client structure, even though we cannot fill it completely yet.
356     But it allows us to access lm78_{read,write}_value. */
357
358  if (! (new_client = kmalloc((is_isa?sizeof(struct i2c_client):
359                                      sizeof(struct i2c_client)) + 
360                              sizeof(struct lm78_data),
361                              GFP_KERNEL))) {
362    err = -ENOMEM;
363    goto ERROR0;
364  }
365
366  data = (struct lm78_data *) (((struct i2c_client *) new_client) + 1);
367  if (is_isa) 
368    init_MUTEX(&data->lock);
369  new_client->addr = address;
370  new_client->data = data;
371  new_client->adapter = adapter;
372  new_client->driver = &lm78_driver;
373 
374  /* Now, we do the remaining detection. */
375
376  if (kind < 0) {
377    if (lm78_read_value(new_client,LM78_REG_CONFIG) & 0x80)
378      goto ERROR1;
379    if (!is_isa && (lm78_read_value(new_client,LM78_REG_I2C_ADDR) != address))
380      goto ERROR1;
381  }
382   
383  /* Determine the chip type. */
384  if (kind <= 0) {
385    i = lm78_read_value(new_client,LM78_REG_CHIPID);
386    if (i == 0x00)
387      kind = lm78;
388    else if (i == 0x40)
389      kind = lm78j;
390    else if ((i & 0xfe) == 0xc0)
391      kind = lm79;
392    else {
393      if (kind == 0)
394        printk("lm78.o: Ignoring 'force' parameter for unknown chip at "
395               "adapter %d, address 0x%02x\n",i2c_adapter_id(adapter),address);
396      goto ERROR1;
397    }
398  }
399
400  if (kind == lm78) {
401    type_name = "lm78";
402    client_name = "LM78 chip";
403  } else if (kind == lm78j) {
404    type_name = "lm78-j";
405    client_name = "LM78-J chip";
406  } else if (kind == lm79) {
407    type_name = "lm79";
408    client_name = "LM79 chip";
409  } else {
410#ifdef DEBUG
411    printk("lm78.o: Internal error: unknown kind (%d)?!?",kind);
412#endif
413    goto ERROR1;
414  }
415
416  /* Reserve the ISA region */
417  if (is_isa)
418    request_region(address, LM78_EXTENT, type_name);
419
420  /* Fill in the remaining client fields and put it into the global list */
421  strcpy(new_client->name,client_name);
422  data->type = kind;
423
424  for(i = 0; i < MAX_LM78_NR; i++)
425    if (! lm78_list[i])
426      break;
427  if (i == MAX_LM78_NR) {
428    printk("lm78.o: No empty slots left, recompile and heighten "
429           "MAX_LM78_NR!\n");
430    err = -ENOMEM;
431    goto ERROR2;
432  }
433  lm78_list[i] = new_client;
434  new_client->id = i;
435  data->valid = 0;
436  init_MUTEX(&data->update_lock);
437
438  /* Tell the I2C layer a new client has arrived */
439  if ((err = i2c_attach_client(new_client)))
440    goto ERROR3;
441
442  /* Register a new directory entry with module sensors */
443  if ((i = sensors_register_entry((struct i2c_client *) new_client,
444                                  type_name,
445                                  lm78_dir_table_template)) < 0) {
446    err = i;
447    goto ERROR4;
448  }
449  data->sysctl_id = i;
450
451  /* Initialize the LM78 chip */
452  lm78_init_client((struct i2c_client *) new_client);
453  return 0;
454
455/* OK, this is not exactly good programming practice, usually. But it is
456   very code-efficient in this case. */
457
458ERROR4:
459  i2c_detach_client(new_client);
460ERROR3:
461  for (i = 0; i < MAX_LM78_NR; i++)
462    if (new_client == lm78_list[i]) 
463      lm78_list[i] = NULL;
464ERROR2:
465  if (is_isa)
466    release_region(address,LM78_EXTENT);
467ERROR1:
468  kfree(new_client);
469ERROR0:
470  return err;
471}
472
473int lm78_detach_client(struct i2c_client *client)
474{
475  int err,i;
476
477  sensors_deregister_entry(((struct lm78_data *)(client->data))->sysctl_id);
478
479  if ((err = i2c_detach_client(client))) {
480    printk("lm78.o: Client deregistration failed, client not detached.\n");
481    return err;
482  }
483
484  for (i = 0; i < MAX_LM78_NR; i++)
485    if (client == lm78_list[i])
486      break;
487  if ((i == MAX_LM78_NR)) {
488    printk("lm78.o: Client to detach not found.\n");
489    return -ENOENT;
490  }
491  lm78_list[i] = NULL;
492
493  if i2c_is_isa_client(client)
494    release_region(client->addr,LM78_EXTENT);
495  kfree(client);
496
497  return 0;
498}
499
500/* No commands defined yet */
501int lm78_command(struct i2c_client *client, unsigned int cmd, void *arg)
502{
503  return 0;
504}
505
506/* Nothing here yet */
507void lm78_inc_use (struct i2c_client *client)
508{
509#ifdef MODULE
510  MOD_INC_USE_COUNT;
511#endif
512}
513
514/* Nothing here yet */
515void lm78_dec_use (struct i2c_client *client)
516{
517#ifdef MODULE
518  MOD_DEC_USE_COUNT;
519#endif
520}
521 
522
523/* The SMBus locks itself, but ISA access must be locked explicitely!
524   We don't want to lock the whole ISA bus, so we lock each client
525   separately.
526   We ignore the LM78 BUSY flag at this moment - it could lead to deadlocks,
527   would slow down the LM78 access and should not be necessary.
528   There are some ugly typecasts here, but the good new is - they should
529   nowhere else be necessary! */
530int lm78_read_value(struct i2c_client *client, u8 reg)
531{
532  int res;
533  if (i2c_is_isa_client(client)) {
534    down(& (((struct lm78_data *) (client->data)) -> lock));
535    outb_p(reg,client->addr + 
536               LM78_ADDR_REG_OFFSET);
537    res = inb_p(client->addr + 
538                LM78_DATA_REG_OFFSET);
539    up( & (((struct lm78_data *) (client->data)) -> lock));
540    return res;
541  } else
542    return i2c_smbus_read_byte_data(client->adapter,client->addr, reg);
543}
544
545/* The SMBus locks itself, but ISA access muse be locked explicitely!
546   We don't want to lock the whole ISA bus, so we lock each client
547   separately.
548   We ignore the LM78 BUSY flag at this moment - it could lead to deadlocks,
549   would slow down the LM78 access and should not be necessary.
550   There are some ugly typecasts here, but the good new is - they should
551   nowhere else be necessary! */
552int lm78_write_value(struct i2c_client *client, u8 reg, u8 value)
553{
554  if (i2c_is_isa_client(client)) {
555    down(&(((struct lm78_data *) (client->data)) -> lock));
556    outb_p(reg,client->addr + LM78_ADDR_REG_OFFSET);
557    outb_p(value,client->addr + LM78_DATA_REG_OFFSET);
558    up(&(((struct lm78_data *) (client->data)) -> lock));
559    return 0;
560  } else
561    return i2c_smbus_write_byte_data(client->adapter, client->addr, reg,value);
562}
563
564/* Called when we have found a new LM78. It should set limits, etc. */
565void lm78_init_client(struct i2c_client *client)
566{
567  int vid;
568
569  /* Reset all except Watchdog values and last conversion values
570     This sets fan-divs to 2, among others */
571  lm78_write_value(client,LM78_REG_CONFIG,0x80);
572
573  vid = lm78_read_value(client,LM78_REG_VID_FANDIV) & 0x0f;
574  if (((struct lm78_data *) (client->data))->type == lm79)
575    vid |= (lm78_read_value(client,LM78_REG_CHIPID) & 0x01) << 4;
576  else
577    vid |= 0x10;
578  vid = VID_FROM_REG(vid);
579
580  lm78_write_value(client,LM78_REG_IN_MIN(0),IN_TO_REG(LM78_INIT_IN_MIN_0));
581  lm78_write_value(client,LM78_REG_IN_MAX(0),IN_TO_REG(LM78_INIT_IN_MAX_0));
582  lm78_write_value(client,LM78_REG_IN_MIN(1),IN_TO_REG(LM78_INIT_IN_MIN_1));
583  lm78_write_value(client,LM78_REG_IN_MAX(1),IN_TO_REG(LM78_INIT_IN_MAX_1));
584  lm78_write_value(client,LM78_REG_IN_MIN(2),IN_TO_REG(LM78_INIT_IN_MIN_2));
585  lm78_write_value(client,LM78_REG_IN_MAX(2),IN_TO_REG(LM78_INIT_IN_MAX_2));
586  lm78_write_value(client,LM78_REG_IN_MIN(3),IN_TO_REG(LM78_INIT_IN_MIN_3));
587  lm78_write_value(client,LM78_REG_IN_MAX(3),IN_TO_REG(LM78_INIT_IN_MAX_3));
588  lm78_write_value(client,LM78_REG_IN_MIN(4),IN_TO_REG(LM78_INIT_IN_MIN_4));
589  lm78_write_value(client,LM78_REG_IN_MAX(4),IN_TO_REG(LM78_INIT_IN_MAX_4));
590  lm78_write_value(client,LM78_REG_IN_MIN(5),IN_TO_REG(LM78_INIT_IN_MIN_5));
591  lm78_write_value(client,LM78_REG_IN_MAX(5),IN_TO_REG(LM78_INIT_IN_MAX_5));
592  lm78_write_value(client,LM78_REG_IN_MIN(6),IN_TO_REG(LM78_INIT_IN_MIN_6));
593  lm78_write_value(client,LM78_REG_IN_MAX(6),IN_TO_REG(LM78_INIT_IN_MAX_6));
594  lm78_write_value(client,LM78_REG_FAN_MIN(1),
595                   FAN_TO_REG(LM78_INIT_FAN_MIN_1,2));
596  lm78_write_value(client,LM78_REG_FAN_MIN(2),
597                   FAN_TO_REG(LM78_INIT_FAN_MIN_2,2));
598  lm78_write_value(client,LM78_REG_FAN_MIN(3),
599                   FAN_TO_REG(LM78_INIT_FAN_MIN_3,2));
600  lm78_write_value(client,LM78_REG_TEMP_OVER,TEMP_TO_REG(LM78_INIT_TEMP_OVER));
601  lm78_write_value(client,LM78_REG_TEMP_HYST,TEMP_TO_REG(LM78_INIT_TEMP_HYST));
602
603  /* Start monitoring */
604  lm78_write_value(client,LM78_REG_CONFIG,
605                   (lm78_read_value(client,LM78_REG_CONFIG) & 0xf7) | 0x01);
606 
607}
608
609void lm78_update_client(struct i2c_client *client)
610{
611  struct lm78_data *data = client->data;
612  int i;
613
614  down(&data->update_lock);
615
616  if ((jiffies - data->last_updated > HZ+HZ/2 ) ||
617      (jiffies < data->last_updated) || ! data->valid) {
618
619#ifdef DEBUG
620    printk("Starting lm78 update\n");
621#endif
622    for (i = 0; i <= 6; i++) {
623      data->in[i]     = lm78_read_value(client,LM78_REG_IN(i));
624      data->in_min[i] = lm78_read_value(client,LM78_REG_IN_MIN(i));
625      data->in_max[i] = lm78_read_value(client,LM78_REG_IN_MAX(i));
626    }
627    for (i = 1; i <= 3; i++) {
628      data->fan[i-1] = lm78_read_value(client,LM78_REG_FAN(i));
629      data->fan_min[i-1] = lm78_read_value(client,LM78_REG_FAN_MIN(i));
630    }
631    data->temp = lm78_read_value(client,LM78_REG_TEMP);
632    data->temp_over = lm78_read_value(client,LM78_REG_TEMP_OVER);
633    data->temp_hyst = lm78_read_value(client,LM78_REG_TEMP_HYST);
634    i = lm78_read_value(client,LM78_REG_VID_FANDIV);
635    data->vid = i & 0x0f;
636    if (data->type == lm79)
637      data->vid |= (lm78_read_value(client,LM78_REG_CHIPID) & 0x01) << 4;
638    else
639      data->vid |= 0x10;
640    data->fan_div[0] = (i >> 4) & 0x03;
641    data->fan_div[1] = i >> 6;
642    data->alarms = lm78_read_value(client,LM78_REG_ALARM1) +
643                   (lm78_read_value(client,LM78_REG_ALARM2) << 8);
644    data->last_updated = jiffies;
645    data->valid = 1;
646
647    data->fan_div[2] = 1;
648  }
649
650  up(&data->update_lock);
651}
652
653
654/* The next few functions are the call-back functions of the /proc/sys and
655   sysctl files. Which function is used is defined in the ctl_table in
656   the extra1 field.
657   Each function must return the magnitude (power of 10 to divide the date
658   with) if it is called with operation==SENSORS_PROC_REAL_INFO. It must
659   put a maximum of *nrels elements in results reflecting the data of this
660   file, and set *nrels to the number it actually put in it, if operation==
661   SENSORS_PROC_REAL_READ. Finally, it must get upto *nrels elements from
662   results and write them to the chip, if operations==SENSORS_PROC_REAL_WRITE.
663   Note that on SENSORS_PROC_REAL_READ, I do not check whether results is
664   large enough (by checking the incoming value of *nrels). This is not very
665   good practice, but as long as you put less than about 5 values in results,
666   you can assume it is large enough. */
667void lm78_in(struct i2c_client *client, int operation, int ctl_name, 
668             int *nrels_mag, long *results)
669{
670  struct lm78_data *data = client->data;
671  int nr = ctl_name - LM78_SYSCTL_IN0;
672
673  if (operation == SENSORS_PROC_REAL_INFO)
674    *nrels_mag = 2;
675  else if (operation == SENSORS_PROC_REAL_READ) {
676    lm78_update_client(client);
677    results[0] = IN_FROM_REG(data->in_min[nr]);
678    results[1] = IN_FROM_REG(data->in_max[nr]);
679    results[2] = IN_FROM_REG(data->in[nr]);
680    *nrels_mag = 3;
681  } else if (operation == SENSORS_PROC_REAL_WRITE) {
682      if (*nrels_mag >= 1) {
683        data->in_min[nr] = IN_TO_REG(results[0]);
684        lm78_write_value(client,LM78_REG_IN_MIN(nr),data->in_min[nr]);
685      }
686      if (*nrels_mag >= 2) {
687        data->in_max[nr] = IN_TO_REG(results[1]);
688        lm78_write_value(client,LM78_REG_IN_MAX(nr),data->in_max[nr]);
689      }
690  }
691}
692
693void lm78_fan(struct i2c_client *client, int operation, int ctl_name,
694              int *nrels_mag, long *results)
695{
696  struct lm78_data *data = client->data;
697  int nr = ctl_name - LM78_SYSCTL_FAN1 + 1;
698
699  if (operation == SENSORS_PROC_REAL_INFO)
700    *nrels_mag = 0;
701  else if (operation == SENSORS_PROC_REAL_READ) {
702    lm78_update_client(client);
703    results[0] = FAN_FROM_REG(data->fan_min[nr-1],
704                 DIV_FROM_REG(data->fan_div[nr-1]));
705    results[1] = FAN_FROM_REG(data->fan[nr-1],
706                 DIV_FROM_REG(data->fan_div[nr-1]));
707    *nrels_mag = 2;
708  } else if (operation == SENSORS_PROC_REAL_WRITE) {
709    if (*nrels_mag >= 1) {
710      data->fan_min[nr-1] = FAN_TO_REG(results[0],
711                            DIV_FROM_REG(data->fan_div[nr-1]));
712      lm78_write_value(client,LM78_REG_FAN_MIN(nr),data->fan_min[nr-1]);
713    }
714  }
715}
716
717
718void lm78_temp(struct i2c_client *client, int operation, int ctl_name,
719               int *nrels_mag, long *results)
720{
721  struct lm78_data *data = client->data;
722  if (operation == SENSORS_PROC_REAL_INFO)
723    *nrels_mag = 1;
724  else if (operation == SENSORS_PROC_REAL_READ) {
725    lm78_update_client(client);
726    results[0] = TEMP_FROM_REG(data->temp_over);
727    results[1] = TEMP_FROM_REG(data->temp_hyst);
728    results[2] = TEMP_FROM_REG(data->temp);
729    *nrels_mag = 3;
730  } else if (operation == SENSORS_PROC_REAL_WRITE) {
731    if (*nrels_mag >= 1) {
732      data->temp_over = TEMP_TO_REG(results[0]);
733      lm78_write_value(client,LM78_REG_TEMP_OVER,data->temp_over);
734    }
735    if (*nrels_mag >= 2) {
736      data->temp_hyst = TEMP_TO_REG(results[1]);
737      lm78_write_value(client,LM78_REG_TEMP_HYST,data->temp_hyst);
738    }
739  }
740}
741
742void lm78_vid(struct i2c_client *client, int operation, int ctl_name,
743              int *nrels_mag, long *results)
744{
745  struct lm78_data *data = client->data;
746  if (operation == SENSORS_PROC_REAL_INFO)
747    *nrels_mag = 2;
748  else if (operation == SENSORS_PROC_REAL_READ) {
749    lm78_update_client(client);
750    results[0] = VID_FROM_REG(data->vid);
751    *nrels_mag = 1;
752  }
753}
754
755void lm78_alarms(struct i2c_client *client, int operation, int ctl_name,
756                 int *nrels_mag, long *results)
757{
758  struct lm78_data *data = client->data;
759  if (operation == SENSORS_PROC_REAL_INFO)
760    *nrels_mag = 0;
761  else if (operation == SENSORS_PROC_REAL_READ) {
762    lm78_update_client(client);
763    results[0] = ALARMS_FROM_REG(data->alarms);
764    *nrels_mag = 1;
765  }
766}
767
768void lm78_fan_div(struct i2c_client *client, int operation, int ctl_name,
769                  int *nrels_mag, long *results)
770{
771  struct lm78_data *data = client->data;
772  int old;
773
774  if (operation == SENSORS_PROC_REAL_INFO)
775    *nrels_mag = 0;
776  else if (operation == SENSORS_PROC_REAL_READ) {
777    lm78_update_client(client);
778    results[0] = DIV_FROM_REG(data->fan_div[0]);
779    results[1] = DIV_FROM_REG(data->fan_div[1]);
780    results[2] = 2;
781    *nrels_mag = 3;
782  } else if (operation == SENSORS_PROC_REAL_WRITE) {
783    old = lm78_read_value(client,LM78_REG_VID_FANDIV);
784    if (*nrels_mag >= 2) {
785      data->fan_div[1] = DIV_TO_REG(results[1]);
786      old = (old & 0x3f) | (data->fan_div[1] << 6);
787    }
788    if (*nrels_mag >= 1) {
789      data->fan_div[0] = DIV_TO_REG(results[0]);
790      old = (old & 0xcf) | (data->fan_div[0] << 4);
791      lm78_write_value(client,LM78_REG_VID_FANDIV,old);
792    }
793  }
794}
795
796int __init sensors_lm78_init(void)
797{
798  int res;
799
800  printk("lm78.o version %s (%s)\n",LM_VERSION,LM_DATE);
801  lm78_initialized = 0;
802
803  if ((res =i2c_add_driver(&lm78_driver))) {
804    printk("lm78.o: Driver registration failed, module not inserted.\n");
805    lm78_cleanup();
806    return res;
807  }
808  lm78_initialized ++;
809  return 0;
810}
811
812int __init lm78_cleanup(void)
813{
814  int res;
815
816  if (lm78_initialized >= 1) {
817    if ((res = i2c_del_driver(&lm78_driver))) {
818      printk("lm78.o: Driver deregistration failed, module not removed.\n");
819      return res;
820    }
821    lm78_initialized --;
822  }
823  return 0;
824}
825
826EXPORT_NO_SYMBOLS;
827
828#ifdef MODULE
829
830MODULE_AUTHOR("Frodo Looijaard <frodol@dds.nl>");
831MODULE_DESCRIPTION("LM78, LM78-J and LM79 driver");
832
833int init_module(void)
834{
835  return sensors_lm78_init();
836}
837
838int cleanup_module(void)
839{
840  return lm78_cleanup();
841}
842
843#endif /* MODULE */
844
Note: See TracBrowser for help on using the browser.