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

Revision 467, 24.5 KB (checked in by frodo, 14 years ago)

Bradley M. Keryan's patches to make lm_sensors compile against
2.3.x kernels (x >= 1).

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