root/lm-sensors/trunk/kernel/chips/gl520sm.c @ 513

Revision 513, 27.7 KB (checked in by frodo, 15 years ago)

First step to make it possible to integrate lm_sensors modules into

the kernel.

* <kernel/init.h> is now included for all modules
* Initialization-time only functions and variables are marked with init
* EXPORT_SYMBOL or EXPORT_NO_SYMBOLS declarations added

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
Line 
1/*
2    gl520sm.c - Part of lm_sensors, Linux kernel modules for hardware
3                monitoring
4    Copyright (c) 1998, 1999  Frodo Looijaard <frodol@dds.nl>,
5                              Kyösti Mälkki <kmalkki@cc.hut.fi>
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
23#include <linux/module.h>
24#include <linux/malloc.h>
25#include <linux/i2c.h>
26#include "sensors.h"
27#include "i2c-isa.h"
28#include "version.h"
29#include "compat.h"
30
31#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,1,53)
32#include <linux/init.h>
33#else
34#define __init
35#endif
36
37
38/* Addresses to scan */
39static unsigned short normal_i2c[] = {0x2c,0x2d,SENSORS_I2C_END};
40static unsigned short normal_i2c_range[] = {SENSORS_I2C_END};
41static unsigned int normal_isa[] = {SENSORS_ISA_END};
42static unsigned int normal_isa_range[] = {SENSORS_ISA_END};
43
44/* Insmod parameters */
45SENSORS_INSMOD_1(gl520sm);
46
47/* Many GL520 constants specified below
48One of the inputs can be configured as either temp or voltage.
49That's why _TEMP2 and _VIN4 access the same register
50*/
51
52/* The GL520 registers */
53#define GL520_REG_CHIP_ID 0x00
54#define GL520_REG_REVISION 0x01
55#define GL520_REG_VID 0x02
56#define GL520_REG_CONF 0x03
57#define GL520_REG_TEMP1 0x04
58#define GL520_REG_TEMP1_OVER 0x05
59#define GL520_REG_TEMP1_HYST 0x06
60#define GL520_REG_FAN_COUNT 0x07
61#define GL520_REG_FAN_LIMIT 0x08
62#define GL520_REG_VIN1_LIMIT 0x09
63#define GL520_REG_VIN2_LIMIT 0x0a
64#define GL520_REG_VIN3_LIMIT 0x0b
65#define GL520_REG_VDD_LIMIT 0x0c
66#define GL520_REG_VIN3 0x0d
67#define GL520_REG_VIN4 0x0e
68#define GL520_REG_TEMP2 0x0e
69#define GL520_REG_MISC 0x0f
70#define GL520_REG_ALARM 0x10
71#define GL520_REG_MASK 0x11
72#define GL520_REG_INT 0x12
73#define GL520_REG_VIN2 0x13
74#define GL520_REG_VIN1 0x14
75#define GL520_REG_VDD 0x15
76#define GL520_REG_TEMP2_OVER 0x17
77#define GL520_REG_TEMP2_HYST 0x18
78
79
80/* Conversions. Rounding and limit checking is only done on the TO_REG
81   variants. Note that you should be a bit careful with which arguments
82   these macros are called: arguments may be evaluated more than once.
83   Fixing this is just not worth it. */
84
85#define TEMP_TO_REG(val) (SENSORS_LIMIT(((((val)<0?(val)-5:(val)+5) / 10)+130),\
86                                        0,255))
87#define TEMP_FROM_REG(val) (((val) - 130) * 10)
88
89extern inline u8 FAN_TO_REG(long rpm, int div)
90{
91  if (rpm == 0)
92    return 255;
93  rpm = SENSORS_LIMIT(rpm,1,1000000);
94  return SENSORS_LIMIT((960000 + rpm*div/2) / (rpm*div),1,254);
95}
96
97#define FAN_FROM_REG(val,div) \
98 ( (val)==0 ? 0 : (val)==255 ? 0 : (960000/((val)*(div))) )
99
100#define IN_TO_REG(val) (SENSORS_LIMIT((((val)*10+8)/19),0,255))
101#define IN_FROM_REG(val) (((val)*19)/10)
102
103#define VDD_TO_REG(val) (SENSORS_LIMIT((((val)*10+11)/23),0,255))
104#define VDD_FROM_REG(val) (((val)*23)/10)
105
106#define DIV_TO_REG(val) ((val)==8?3:(val)==4?2:(val)==1?0:1)
107#define DIV_FROM_REG(val) (1 << (val))
108
109#define ALARMS_FROM_REG(val) val
110
111#define BEEP_ENABLE_TO_REG(val) ((val)?0:1)
112#define BEEP_ENABLE_FROM_REG(val) ((val)?0:1)
113
114#define BEEPS_TO_REG(val) (val)
115#define BEEPS_FROM_REG(val) (val)
116
117#define VID_FROM_REG(val) ((val)==0x1f?0:(val)>=0x10?510-(val)*10:\
118                           (val)>=0x06?0:205-(val)*5)
119
120/* Initial values */
121#define GL520_INIT_TEMP_OVER 600
122#define GL520_INIT_TEMP_HYST 500
123#define GL520_INIT_FAN_MIN_1 3000
124#define GL520_INIT_FAN_MIN_2 3000
125
126/* These are somewhat sane */
127#define GL520_INIT_VIN_1 330    /* 3.3 V */
128#define GL520_INIT_VIN_2 286    /* 12 V */
129#define GL520_INIT_VIN_3 260    /* Vcore */
130#define GL520_INIT_VDD 500      /* 5 V */
131
132#define GL520_INIT_PERCENTAGE 10
133
134#define GL520_INIT_VIN_MIN_1 \
135        (GL520_INIT_VIN_1 - GL520_INIT_VIN_1 * GL520_INIT_PERCENTAGE / 100)
136#define GL520_INIT_VIN_MAX_1 \
137        (GL520_INIT_VIN_1 + GL520_INIT_VIN_1 * GL520_INIT_PERCENTAGE / 100)
138#define GL520_INIT_VIN_MIN_2 \
139        (GL520_INIT_VIN_2 - GL520_INIT_VIN_2 * GL520_INIT_PERCENTAGE / 100)
140#define GL520_INIT_VIN_MAX_2 \
141        (GL520_INIT_VIN_2 + GL520_INIT_VIN_2 * GL520_INIT_PERCENTAGE / 100)
142#define GL520_INIT_VIN_MIN_3 \
143        (GL520_INIT_VIN_3 - GL520_INIT_VIN_3 * GL520_INIT_PERCENTAGE / 100)
144#define GL520_INIT_VIN_MAX_3 \
145        (GL520_INIT_VIN_3 + GL520_INIT_VIN_3 * GL520_INIT_PERCENTAGE / 100)
146#define GL520_INIT_VDD_MIN \
147        (GL520_INIT_VDD - GL520_INIT_VDD * GL520_INIT_PERCENTAGE / 100)
148#define GL520_INIT_VDD_MAX \
149        (GL520_INIT_VDD + GL520_INIT_VDD * GL520_INIT_PERCENTAGE / 100)
150
151
152/* Each client has this additional data */
153struct gl520_data {
154         int sysctl_id;
155         enum chips type;
156
157         struct semaphore update_lock;
158         char valid;                 /* !=0 if following fields are valid */
159         unsigned long last_updated; /* In jiffies */
160         unsigned long last_updated_v00; 
161                                     /* In jiffies (used only by rev00 chips) */
162
163         u8 voltage[5];              /* Register values; [0] = VDD */
164         u8 voltage_min[5];          /* Register values; [0] = VDD */
165         u8 voltage_max[5];          /* Register values; [0] = VDD */
166         u8 fan[2];
167         u8 fan_min[2];
168         u8 temp[2];                 /* Register values */
169         u8 temp_over[2];            /* Register values */
170         u8 temp_hyst[2];            /* Register values */
171         u8 alarms,beeps,vid;        /* Register value */
172         u8 fan_div[2];              /* Register encoding, shifted right */
173         u8 beep_enable;             /* Boolean */
174};
175
176#ifdef MODULE
177extern int init_module(void);
178extern int cleanup_module(void);
179#endif /* MODULE */
180
181static int __init gl520_init(void);
182static int __init gl520_cleanup(void);
183static int gl520_attach_adapter(struct i2c_adapter *adapter);
184static int gl520_detect(struct i2c_adapter *adapter, int address, int kind);
185static void gl520_init_client(struct i2c_client *client);
186static int gl520_detach_client(struct i2c_client *client);
187static int gl520_command(struct i2c_client *client, unsigned int cmd,
188                        void *arg);
189static void gl520_inc_use (struct i2c_client *client);
190static void gl520_dec_use (struct i2c_client *client);
191static u16 swap_bytes(u16 val);
192static int gl520_read_value(struct i2c_client *client, u8 reg);
193static int gl520_write_value(struct i2c_client *client, u8 reg, u16 value);
194static void gl520_update_client(struct i2c_client *client);
195
196static void gl520_vin(struct i2c_client *client, int operation, 
197                      int ctl_name, int *nrels_mag, long *results);
198static void gl520_vid(struct i2c_client *client, int operation, 
199                      int ctl_name, int *nrels_mag, long *results);
200static void gl520_fan(struct i2c_client *client, int operation, 
201                      int ctl_name, int *nrels_mag, long *results);
202static void gl520_temp(struct i2c_client *client, int operation, 
203                       int ctl_name, int *nrels_mag, long *results);
204static void gl520_fan_div(struct i2c_client *client, int operation, 
205                          int ctl_name, int *nrels_mag, long *results);
206static void gl520_alarms(struct i2c_client *client, int operation, 
207                         int ctl_name, int *nrels_mag, long *results);
208static void gl520_beep(struct i2c_client *client, int operation, int ctl_name, 
209                int *nrels_mag, long *results);
210static void gl520_fan1off(struct i2c_client *client, int operation,
211                int ctl_name, int *nrels_mag, long *results);
212static void gl520_config(struct i2c_client *client, int operation,
213                int ctl_name, int *nrels_mag, long *results);
214
215/* This is the driver that will be inserted */
216static struct i2c_driver gl520_driver = {
217  /* name */            "GL520SM sensor chip driver",
218  /* id */              I2C_DRIVERID_GL520,
219  /* flags */           I2C_DF_NOTIFY,
220  /* attach_adapter */  &gl520_attach_adapter,
221  /* detach_client */   &gl520_detach_client,
222  /* command */         &gl520_command,
223  /* inc_use */         &gl520_inc_use,
224  /* dec_use */         &gl520_dec_use
225};
226
227/* These files are created for each detected GL520. This is just a template;
228   though at first sight, you might think we could use a statically
229   allocated list, we need some way to get back to the parent - which
230   is done through one of the 'extra' fields which are initialized
231   when a new copy is allocated. */
232static ctl_table gl520_dir_table_template[] = {
233  { GL520_SYSCTL_VIN1, "vin1", NULL, 0, 0644, NULL, &sensors_proc_real,
234    &sensors_sysctl_real, NULL, &gl520_vin },
235  { GL520_SYSCTL_VIN2, "vin2", NULL, 0, 0644, NULL, &sensors_proc_real,
236    &sensors_sysctl_real, NULL, &gl520_vin },
237  { GL520_SYSCTL_VIN3, "vin3", NULL, 0, 0644, NULL, &sensors_proc_real,
238    &sensors_sysctl_real, NULL, &gl520_vin },
239  { GL520_SYSCTL_VIN4, "vin4", NULL, 0, 0644, NULL, &sensors_proc_real,
240    &sensors_sysctl_real, NULL, &gl520_vin },
241  { GL520_SYSCTL_VDD, "vdd", NULL, 0, 0644, NULL, &sensors_proc_real,
242    &sensors_sysctl_real, NULL, &gl520_vin },
243  { GL520_SYSCTL_VID, "vid", NULL, 0, 0444, NULL, &sensors_proc_real,
244    &sensors_sysctl_real, NULL, &gl520_vid },
245  { GL520_SYSCTL_FAN1, "fan1", NULL, 0, 0644, NULL, &sensors_proc_real,
246    &sensors_sysctl_real, NULL, &gl520_fan },
247  { GL520_SYSCTL_FAN2, "fan2", NULL, 0, 0644, NULL, &sensors_proc_real,
248    &sensors_sysctl_real, NULL, &gl520_fan },
249  { GL520_SYSCTL_TEMP1, "temp1", NULL, 0, 0644, NULL, &sensors_proc_real,
250    &sensors_sysctl_real, NULL, &gl520_temp },
251  { GL520_SYSCTL_TEMP2, "temp2", NULL, 0, 0644, NULL, &sensors_proc_real,
252    &sensors_sysctl_real, NULL, &gl520_temp },
253  { GL520_SYSCTL_FAN_DIV, "fan_div", NULL, 0, 0644, NULL, &sensors_proc_real,
254    &sensors_sysctl_real, NULL, &gl520_fan_div },
255  { GL520_SYSCTL_ALARMS, "alarms", NULL, 0, 0444, NULL, &sensors_proc_real,
256    &sensors_sysctl_real, NULL, &gl520_alarms },
257  { GL520_SYSCTL_BEEP, "beep", NULL, 0, 0644, NULL, &sensors_proc_real,
258    &sensors_sysctl_real, NULL, &gl520_beep },
259  { GL520_SYSCTL_FAN1OFF, "fan1off", NULL, 0, 0644, NULL, &sensors_proc_real,
260    &sensors_sysctl_real, NULL, &gl520_fan1off },
261  { GL520_SYSCTL_CONFIG, "config", NULL, 0, 0644, NULL, &sensors_proc_real,
262    &sensors_sysctl_real, NULL, &gl520_config },
263  { 0 }
264};
265
266/* Used by init/cleanup */
267static int __init gl520_initialized = 0;
268
269/* I choose here for semi-static GL520SM allocation. Complete dynamic
270   allocation could also be used; the code needed for this would probably
271   take more memory than the datastructure takes now. */
272#define MAX_GL520_NR 4
273static struct i2c_client *gl520_list[MAX_GL520_NR];
274
275int gl520_attach_adapter(struct i2c_adapter *adapter)
276{
277  return sensors_detect(adapter,&addr_data,gl520_detect);
278}
279
280static int gl520_detect(struct i2c_adapter *adapter, int address, int kind)
281{ 
282  int i;
283  struct i2c_client *new_client;
284  struct gl520_data *data;
285  int err=0;
286  const char *type_name = "";
287  char client_name[32];
288
289  /* Make sure we aren't probing the ISA bus!! This is just a safety check
290     at this moment; sensors_detect really won't call us. */
291#ifdef DEBUG
292  if (i2c_is_isa_adapter(adapter)) {
293    printk("gl520sm.o: gl520_detect called for an ISA bus adapter?!?\n");
294    return 0;
295  }
296#endif
297
298
299  /* We need address registration for the I2C bus too. That is not yet
300     implemented. */
301
302  /* OK. For now, we presume we have a valid client. We now create the
303     client structure, even though we cannot fill it completely yet.
304     But it allows us to access gl520_{read,write}_value. */
305
306  if (! (new_client = kmalloc(sizeof(struct i2c_client) +
307                               sizeof(struct gl520_data),
308                               GFP_KERNEL))) {
309    err = -ENOMEM;
310    goto ERROR0;
311  }
312
313  data = (struct gl520_data *) (new_client + 1);
314  new_client->addr = address;
315  new_client->data = data;
316  new_client->adapter = adapter;
317  new_client->driver = &gl520_driver;
318
319  /* Determine the chip type. */
320
321  if (gl520_read_value(new_client,GL520_REG_CHIP_ID) != 0x20) {
322     printk("gl520sm.o: Ignoring 'force' parameter for unknown chip at "
323          "adapter %d, address 0x%02x\n",i2c_adapter_id(adapter),address);
324     goto ERROR1;
325  } else {
326     kind = gl520sm;
327  }
328   
329  i = gl520_read_value(new_client,GL520_REG_REVISION);
330  if (kind == gl520sm) {
331    type_name = "gl520sm";
332    sprintf(client_name, "GL520SM Revision %02x chip", i);
333  } else {
334#ifdef DEBUG
335    printk("gl520sm.o: Internal error: unknown kind (%d)?!?",kind);
336#endif
337    goto ERROR1;
338  }
339
340  /* Fill in the remaining client fields and put it into the global list */
341  strcpy(new_client->name,client_name);
342  data->type = kind;
343
344  for(i = 0; i < MAX_GL520_NR; i++)
345    if (! gl520_list[i])
346      break;
347  if (i == MAX_GL520_NR) {
348    printk("gl520sm.o: No empty slots left, recompile and heighten "
349           "MAX_GL520_NR!\n");
350    err = -ENOMEM;
351    goto ERROR2;
352  }
353  gl520_list[i] = new_client;
354  new_client->id = i;
355  data->valid = 0;
356  init_MUTEX(&data->update_lock);
357
358  /* Tell the I2C layer a new client has arrived */
359  if ((err = i2c_attach_client(new_client)))
360    goto ERROR3;
361
362  /* Register a new directory entry with module sensors */
363  if ((i = sensors_register_entry((struct i2c_client *) new_client,
364                                  type_name,
365                                  gl520_dir_table_template)) < 0) {
366    err = i;
367    goto ERROR4;
368  }
369  data->sysctl_id = i;
370
371  /* Initialize the GL520SM chip */
372  gl520_init_client((struct i2c_client *) new_client);
373  return 0;
374
375/* OK, this is not exactly good programming practice, usually. But it is
376   very code-efficient in this case. */
377
378ERROR4:
379  i2c_detach_client(new_client);
380ERROR3:
381  for (i = 0; i < MAX_GL520_NR; i++)
382    if (new_client == gl520_list[i])
383      gl520_list[i] = NULL;
384ERROR2:
385ERROR1:
386  kfree(new_client);
387ERROR0:
388  return err;
389}
390
391
392/* Called when we have found a new GL520SM. It should set limits, etc. */
393void gl520_init_client(struct i2c_client *client)
394{
395  /* Power-on defaults (bit 7=1) */
396  gl520_write_value(client,GL520_REG_CONF,0x80); 
397
398  /* No noisy output (bit 2=1), Comparator mode (bit 3=0), two fans (bit4=0),
399     standby mode (bit6=0) */
400  gl520_write_value(client,GL520_REG_CONF,0x04); 
401
402  /* Never interrupts */
403  gl520_write_value(client,GL520_REG_MASK,0x00);
404   
405  gl520_write_value(client,GL520_REG_TEMP1_HYST,
406                    TEMP_TO_REG(GL520_INIT_TEMP_HYST));
407  gl520_write_value(client,GL520_REG_TEMP1_OVER,
408                    TEMP_TO_REG(GL520_INIT_TEMP_OVER));
409
410  gl520_write_value(client,GL520_REG_TEMP2_HYST,
411                    TEMP_TO_REG(GL520_INIT_TEMP_HYST));
412  gl520_write_value(client,GL520_REG_TEMP2_OVER,
413                    TEMP_TO_REG(GL520_INIT_TEMP_OVER));
414
415  gl520_write_value(client,GL520_REG_MISC,(DIV_TO_REG(2) << 6) | 
416                                              (DIV_TO_REG(2) << 4));
417  gl520_write_value(client,GL520_REG_FAN_LIMIT,
418                    (FAN_TO_REG(GL520_INIT_FAN_MIN_1,2) << 8) |
419                    FAN_TO_REG(GL520_INIT_FAN_MIN_2,2));
420
421  gl520_write_value(client,GL520_REG_VIN1_LIMIT,
422                    (IN_TO_REG(GL520_INIT_VIN_MAX_1) << 8) |
423                    IN_TO_REG(GL520_INIT_VIN_MIN_1));
424  gl520_write_value(client,GL520_REG_VIN2_LIMIT,
425                    (IN_TO_REG(GL520_INIT_VIN_MAX_2) << 8) |
426                    IN_TO_REG(GL520_INIT_VIN_MIN_2));
427  gl520_write_value(client,GL520_REG_VIN3_LIMIT,
428                    (IN_TO_REG(GL520_INIT_VIN_MAX_3) << 8) |
429                    IN_TO_REG(GL520_INIT_VIN_MIN_3));
430  gl520_write_value(client,GL520_REG_VDD_LIMIT,
431                    (VDD_TO_REG(GL520_INIT_VDD_MAX) << 8) |
432                    VDD_TO_REG(GL520_INIT_VDD_MIN));
433
434  /* Clear status register (bit 5=1), start (bit6=1) */
435  gl520_write_value(client,GL520_REG_CONF,0x24);
436  gl520_write_value(client,GL520_REG_CONF,0x44);
437}
438
439int gl520_detach_client(struct i2c_client *client)
440{
441  int err,i;
442
443  sensors_deregister_entry(((struct gl520_data *)(client->data))->sysctl_id);
444
445  if ((err = i2c_detach_client(client))) {
446    printk("gl520sm.o: Client deregistration failed, client not detached.\n");
447    return err;
448  }
449
450  for (i = 0; i < MAX_GL520_NR; i++)
451    if (client == gl520_list[i])
452      break;
453  if ((i == MAX_GL520_NR)) {
454    printk("gl520sm.o: Client to detach not found.\n");
455    return -ENOENT;
456  }
457  gl520_list[i] = NULL;
458
459  kfree(client);
460
461  return 0;
462}
463
464
465/* No commands defined yet */
466int gl520_command(struct i2c_client *client, unsigned int cmd, void *arg)
467{
468  return 0;
469}
470
471/* Nothing here yet */
472void gl520_inc_use (struct i2c_client *client)
473{
474#ifdef MODULE
475  MOD_INC_USE_COUNT;
476#endif
477}
478
479/* Nothing here yet */
480void gl520_dec_use (struct i2c_client *client)
481{
482#ifdef MODULE
483  MOD_DEC_USE_COUNT;
484#endif
485}
486
487u16 swap_bytes(u16 val)
488{
489  return (val >> 8) | (val << 8);
490}
491
492/* Registers 0x07 to 0x0c are word-sized, others are byte-sized
493   GL520 uses a high-byte first convention, which is exactly opposite to
494   the usual practice. */
495int gl520_read_value(struct i2c_client *client, u8 reg)
496{
497  if ((reg >= 0x07) && (reg <= 0x0c)) 
498    return swap_bytes(i2c_smbus_read_word_data(client->adapter,client->addr,reg));
499  else
500    return i2c_smbus_read_byte_data(client->adapter,client->addr,reg);
501}
502
503/* Registers 0x07 to 0x0c are word-sized, others are byte-sized
504   GL520 uses a high-byte first convention, which is exactly opposite to
505   the usual practice. */
506int gl520_write_value(struct i2c_client *client, u8 reg, u16 value)
507{
508  if ((reg >= 0x07) && (reg <= 0x0c)) 
509    return i2c_smbus_write_word_data(client->adapter,client->addr,reg,
510                                 swap_bytes(value));
511  else
512    return i2c_smbus_write_byte_data(client->adapter,client->addr,reg,value);
513}
514
515void gl520_update_client(struct i2c_client *client)
516{
517  struct gl520_data *data = client->data;
518  int val;
519
520  down(&data->update_lock);
521
522  if ((jiffies - data->last_updated > HZ+HZ/2 ) ||
523      (jiffies < data->last_updated) || ! data->valid) {
524
525#ifdef DEBUG
526    printk("Starting gl520 update\n");
527#endif
528
529    data->alarms = gl520_read_value(client,GL520_REG_INT);
530    data->beeps = gl520_read_value(client,GL520_REG_ALARM);
531
532    val = gl520_read_value(client,GL520_REG_VDD_LIMIT);
533    data->voltage_min[0] = val & 0xff;
534    data->voltage_max[0] = (val >> 8) & 0xff;
535    val = gl520_read_value(client,GL520_REG_VIN1_LIMIT);
536    data->voltage_min[1] = val & 0xff;
537    data->voltage_max[1] = (val >> 8) & 0xff;
538    val = gl520_read_value(client,GL520_REG_VIN2_LIMIT);
539    data->voltage_min[2] = val & 0xff;
540    data->voltage_max[2] = (val >> 8) & 0xff;
541    val = gl520_read_value(client,GL520_REG_VIN3_LIMIT);
542    data->voltage_min[3] = val & 0xff;
543    data->voltage_max[3] = (val >> 8) & 0xff;
544
545    data->voltage[0] = gl520_read_value(client,GL520_REG_VDD);
546    data->voltage[1] = gl520_read_value(client,GL520_REG_VIN1);
547    data->voltage[2] = gl520_read_value(client,GL520_REG_VIN2);
548    data->voltage[3] = gl520_read_value(client,GL520_REG_VIN3);
549
550    val = gl520_read_value(client,GL520_REG_FAN_COUNT);
551    data->fan[0] = (val >> 8) & 0xff;
552    data->fan[1] = val & 0xff;
553
554    val = gl520_read_value(client,GL520_REG_FAN_LIMIT);
555    data->fan_min[0] = (val >> 8) & 0xff;
556    data->fan_min[1] = val & 0xff;
557
558    data->temp[0] = gl520_read_value(client,GL520_REG_TEMP1);
559    data->temp_over[0] = gl520_read_value(client,GL520_REG_TEMP1_OVER);
560    data->temp_hyst[0] = gl520_read_value(client,GL520_REG_TEMP1_HYST);
561
562    data->temp[1] = gl520_read_value(client,GL520_REG_TEMP2);
563    data->temp_over[1] = gl520_read_value(client,GL520_REG_TEMP2_OVER);
564    data->temp_hyst[1] = gl520_read_value(client,GL520_REG_TEMP2_HYST);
565
566    val = gl520_read_value(client,GL520_REG_MISC);
567    data->fan_div[0] = (val >> 6) & 0x03;
568    data->fan_div[1] = (val >> 4) & 0x03;
569
570    if (data->fan_min[0]==0xff)
571       data->alarms &= ~GL520_ALARM_FAN1;
572       
573    if (data->fan_min[1]==0xff)
574       data->alarms &= ~GL520_ALARM_FAN2;
575       
576    val = gl520_read_value(client, GL520_REG_CONF);
577    data->beep_enable = (val >> 2) & 1;
578
579    data->last_updated = jiffies;
580    data->valid = 1;
581  }
582
583  up(&data->update_lock);
584}
585
586void gl520_temp(struct i2c_client *client, int operation, int ctl_name,
587                int *nrels_mag, long *results)
588{
589  struct gl520_data *data = client->data;
590  if (operation == SENSORS_PROC_REAL_INFO)
591    *nrels_mag = 1;
592  else if (operation == SENSORS_PROC_REAL_READ) {
593    gl520_update_client(client);
594    results[0] = TEMP_FROM_REG(data->temp_over[0]);
595    results[1] = TEMP_FROM_REG(data->temp_hyst[0]);
596    results[2] = TEMP_FROM_REG(data->temp[0]);
597    *nrels_mag = 3;
598  } else if (operation == SENSORS_PROC_REAL_WRITE) {
599    if (*nrels_mag >= 1) {
600      data->temp_over[0] = TEMP_TO_REG(results[0]);
601      gl520_write_value(client,GL520_REG_TEMP1_OVER,data->temp_over[0]);
602    }
603    if (*nrels_mag >= 2) {
604      data->temp_hyst[0] = TEMP_TO_REG(results[1]);
605      gl520_write_value(client,GL520_REG_TEMP1_HYST,data->temp_hyst[0]);
606    }
607  }
608}
609
610void gl520_vin(struct i2c_client *client, int operation, int ctl_name, 
611               int *nrels_mag, long *results)
612{
613  struct gl520_data *data = client->data;
614  int nr = ctl_name - GL520_SYSCTL_VDD;
615  int regnr,old=0;
616
617  if (operation == SENSORS_PROC_REAL_INFO)
618    *nrels_mag = 2;
619  else if (operation == SENSORS_PROC_REAL_READ) {
620    gl520_update_client(client);
621    results[0] = nr?IN_FROM_REG(data->voltage_min[nr]):
622                    VDD_FROM_REG(data->voltage_min[nr]);
623    results[1] = nr?IN_FROM_REG(data->voltage_max[nr]):
624                    VDD_FROM_REG(data->voltage_max[nr]);
625    results[2] = nr?IN_FROM_REG(data->voltage[nr]):
626                    VDD_FROM_REG(data->voltage[nr]);
627    *nrels_mag = 3;
628  } else if (operation == SENSORS_PROC_REAL_WRITE) {
629    regnr=nr==0?GL520_REG_VDD_LIMIT:nr==1?GL520_REG_VIN1_LIMIT:nr==2?
630                GL520_REG_VIN2_LIMIT:GL520_REG_VIN3_LIMIT;
631    if (*nrels_mag == 1)
632      old = gl520_read_value(client,regnr) & 0xff00;
633    if (*nrels_mag >= 2) {
634      data->voltage_max[nr] = nr?IN_TO_REG(results[1]):VDD_TO_REG(results[1]);
635      old = data->voltage_max[nr] << 8;
636    }
637    if (*nrels_mag >= 1) {
638      data->voltage_min[nr] = nr?IN_TO_REG(results[0]):VDD_TO_REG(results[0]);
639      old |= data->voltage_min[nr];
640      gl520_write_value(client,regnr,old);
641    }
642  }
643} 
644
645
646void gl520_fan(struct i2c_client *client, int operation, int ctl_name, 
647               int *nrels_mag, long *results)
648{
649  struct gl520_data *data = client->data;
650  int nr = ctl_name - GL520_SYSCTL_FAN1;
651  int old;
652
653  if (operation == SENSORS_PROC_REAL_INFO)
654    *nrels_mag = 0;
655  else if (operation == SENSORS_PROC_REAL_READ) {
656    gl520_update_client(client);
657    results[0] = FAN_FROM_REG(data->fan_min[nr],
658                 DIV_FROM_REG(data->fan_div[nr]));
659    results[1] = FAN_FROM_REG(data->fan[nr],DIV_FROM_REG(data->fan_div[nr]));
660    *nrels_mag = 2;
661  } else if (operation == SENSORS_PROC_REAL_WRITE) {
662    if (*nrels_mag >= 1) {
663      data->fan_min[nr] = FAN_TO_REG(results[0],
664                                     DIV_FROM_REG(data->fan_div[nr]));
665      old = gl520_read_value(client,GL520_REG_FAN_LIMIT);
666
667      if (nr == 0)
668        old = (old & 0x00ff) | (data->fan_min[nr] << 8);
669      else 
670        old = (old & 0xff00) | data->fan_min[nr];
671
672      gl520_write_value(client,GL520_REG_FAN_LIMIT,old);
673    }
674  }
675}
676
677
678void gl520_alarms(struct i2c_client *client, int operation, int ctl_name, 
679                  int *nrels_mag, long *results)
680{
681  struct gl520_data *data = client->data;
682  if (operation == SENSORS_PROC_REAL_INFO)
683    *nrels_mag = 0;
684  else if (operation == SENSORS_PROC_REAL_READ) {
685    gl520_update_client(client);
686    results[0] = ALARMS_FROM_REG(data->alarms);
687    *nrels_mag = 1;
688  }
689}
690
691void gl520_beep(struct i2c_client *client, int operation, int ctl_name, 
692                int *nrels_mag, long *results)
693{
694  struct gl520_data *data = client->data;
695  if (operation == SENSORS_PROC_REAL_INFO)
696    *nrels_mag = 0;
697  else if (operation == SENSORS_PROC_REAL_READ) {
698    gl520_update_client(client);
699    results[0] = BEEP_ENABLE_FROM_REG(data->beep_enable);
700    results[1] = BEEPS_FROM_REG(data->beeps);
701    *nrels_mag = 2;
702  } else if (operation == SENSORS_PROC_REAL_WRITE) {
703    if (*nrels_mag >= 1) {
704      data->beep_enable = BEEP_ENABLE_TO_REG(results[0]);
705      gl520_write_value(client,GL520_REG_CONF,
706                        (gl520_read_value(client,GL520_REG_CONF) & 0xfb) | 
707                         (data->beep_enable << 2));
708    }
709    if (*nrels_mag >= 2) {
710      data->beeps = BEEPS_TO_REG(results[1]);
711      gl520_write_value(client,GL520_REG_ALARM,data->beeps);
712    }
713  }
714}
715
716
717void gl520_fan_div(struct i2c_client *client, int operation, int ctl_name,
718                   int *nrels_mag, long *results)
719{
720  struct gl520_data *data = client->data;
721  int old;
722  if (operation == SENSORS_PROC_REAL_INFO)
723    *nrels_mag = 0;
724  else if (operation == SENSORS_PROC_REAL_READ) {
725    gl520_update_client(client);
726    results[0] = DIV_FROM_REG(data->fan_div[0]);
727    results[1] = DIV_FROM_REG(data->fan_div[1]);
728    *nrels_mag = 2;
729  } else if (operation == SENSORS_PROC_REAL_WRITE) {
730    old = gl520_read_value(client,GL520_REG_MISC);
731    if (*nrels_mag >= 2) {
732      data->fan_div[1] = DIV_TO_REG(results[1]);
733      old = (old & 0xcf) | (data->fan_div[1] << 4);
734    }
735    if (*nrels_mag >= 1) {
736      data->fan_div[0] = DIV_TO_REG(results[0]);
737      old = (old & 0x3f) | (data->fan_div[0] << 6);
738    }
739    gl520_write_value(client,GL520_REG_MISC,old);
740  }
741}
742
743void gl520_vid(struct i2c_client *client, int operation, int ctl_name,
744              int *nrels_mag, long *results)
745{
746  struct gl520_data *data = client->data;
747  if (operation == SENSORS_PROC_REAL_INFO)
748    *nrels_mag = 2;
749  else if (operation == SENSORS_PROC_REAL_READ) {
750    gl520_update_client(client);
751    results[0] = VID_FROM_REG(data->vid);
752    *nrels_mag = 1;
753  }
754}
755
756void gl520_fan1off(struct i2c_client *client, int operation, int ctl_name, 
757                int *nrels_mag, long *results)
758{
759  int old;
760  if (operation == SENSORS_PROC_REAL_INFO)
761    *nrels_mag = 0;
762  else if (operation == SENSORS_PROC_REAL_READ) {
763    results[0] = ((gl520_read_value(client, GL520_REG_MISC) & 0x04) !=0);
764    *nrels_mag = 1;
765  } else if (operation == SENSORS_PROC_REAL_WRITE) {
766    if (*nrels_mag >= 1) {
767      old = gl520_read_value(client, GL520_REG_MISC) & 0xfb;
768      if (results[0])
769        old |= 0x04;
770      gl520_write_value(client,GL520_REG_MISC,old);
771    }
772  }
773}
774
775void gl520_config(struct i2c_client *client, int operation, int ctl_name, 
776                int *nrels_mag, long *results)
777{
778  int old;
779  if (operation == SENSORS_PROC_REAL_INFO)
780    *nrels_mag = 0;
781  else if (operation == SENSORS_PROC_REAL_READ) {
782    results[0] = ((gl520_read_value(client, GL520_REG_CONF) & 0x10)==0);
783    *nrels_mag = 1;
784  } else if (operation == SENSORS_PROC_REAL_WRITE) {
785    if (*nrels_mag >= 1) {
786      old = gl520_read_value(client, GL520_REG_CONF) & 0xef;
787      if (! results[1])
788        old |= 0x10;
789      gl520_write_value(client,GL520_REG_CONF,old);
790    }
791  }
792}
793
794int __init gl520_init(void)
795{
796  int res;
797
798  printk("gl520sm.o version %s (%s)\n",LM_VERSION,LM_DATE);
799  gl520_initialized = 0;
800  if ((res = i2c_add_driver(&gl520_driver))) {
801    printk("gl520sm.o: Driver registration failed, module not inserted.\n");
802    gl520_cleanup();
803    return res;
804  }
805  gl520_initialized ++;
806  return 0;
807}
808
809int __init gl520_cleanup(void)
810{
811  int res;
812
813  if (gl520_initialized >= 1) {
814    if ((res = i2c_del_driver(&gl520_driver))) {
815      printk("gl520.o: Driver deregistration failed, module not removed.\n");
816      return res;
817    }
818    gl520_initialized --;
819  }
820
821  return 0;
822}
823
824EXPORT_NO_SYMBOLS;
825
826#ifdef MODULE
827
828MODULE_AUTHOR("Frodo Looijaard <frodol@dds.nl>");
829MODULE_DESCRIPTION("GL520SM driver");
830
831int init_module(void)
832{
833  return gl520_init();
834}
835
836int cleanup_module(void)
837{
838  return gl520_cleanup();
839}
840
841#endif /* MODULE */
842
Note: See TracBrowser for help on using the browser.