root/lm-sensors/trunk/src/w83781d.c @ 86

Revision 86, 35.9 KB (checked in by phil, 14 years ago)

(Phil) Temp2 and 3 are working!!! :') No mutex on the bank setting
yet, though.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
Line 
1
2/*
3    w83781d.c - A Linux module for reading sensor data.
4    Copyright (c) 1998  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 "isa.h"
33#include "sensors.h"
34#include "i2c.h"
35#include "compat.h"
36
37/* Many W83781D constants specified below */
38
39/* Length of ISA address segment */
40#define W83781D_EXTENT 8
41
42/* Where are the ISA address/data registers relative to the base address */
43#define W83781D_ADDR_REG_OFFSET 5
44#define W83781D_DATA_REG_OFFSET 6
45
46/* The W83781D registers */
47#define W83781D_REG_IN_MAX(nr) (0x2b + (nr) * 2)
48#define W83781D_REG_IN_MIN(nr) (0x2c + (nr) * 2)
49#define W83781D_REG_IN(nr) (0x20 + (nr))
50
51#define W83781D_REG_FAN_MIN(nr) (0x3a + (nr))
52#define W83781D_REG_FAN(nr) (0x27 + (nr))
53
54#define W83781D_REG_TEMP23 0x50
55#define W83781D_REG_TEMP_HYST23 0x53
56#define W83781D_REG_TEMP_CONFIG23 0x52
57#define W83781D_REG_TEMP_OVER23 0x55
58#define W83781D_REG_TEMP 0x27
59#define W83781D_REG_TEMP_OVER 0x39
60#define W83781D_REG_TEMP_HYST 0x3A
61#define W83781D_REG_TEMP_CONFIG 0x52
62#define W83781D_REG_TEMP_SEL 0x4E
63
64#define W83781D_REG_CONFIG 0x40
65#define W83781D_REG_ALARM1 0x41
66#define W83781D_REG_ALARM2 0x42
67
68#define W83781D_REG_VID_FANDIV 0x47
69
70#define W83781D_REG_CHIPID 0x58
71#define W83781D_REG_CHIPMAN 0x4F
72
73
74/* Conversions. Rounding is only done on the TO_REG variants. */
75static int w83781d_in_conv[7] = {10000, 10000, 10000, 16892, 38000, 
76                              -34768, -15050 };
77#define IN_TO_REG(val,nr) (((((val) * 100000 / w83781d_in_conv[nr]) + 8) / 16) \
78                           & 0xff)
79#define IN_FROM_REG(val,nr) (((val) *  16 * w83781d_in_conv[nr]) / 100000)
80
81#define FAN_TO_REG(val) ((val)==0?255:((1350000+(val))/((val)*2)) & 0xff)
82#define FAN_FROM_REG(val) ((val)==0?-1:(val)==255?0:1350000/((val)*2))
83
84#define TEMP_TO_REG(val) (((val)<0?(((val)-5)/10)&0xff:((val)+5)/10) & 0xff)
85#define TEMP_FROM_REG(val) (((val)>0x80?(val)-0x100:(val))*10)
86
87#define VID_FROM_REG(val) ((val)==0x1f?0:(val)>=0x10?510-(val)*10:\
88                           (val)>=0x06?0:205-(val)*5)
89#define ALARMS_FROM_REG(val) (val)
90
91#define DIV_FROM_REG(val) (1 << (val))
92#define DIV_TO_REG(val) ((val)==8?3:(val)==4?2:(val)==1?0:1)
93
94/* Initial limits */
95#define W83781D_INIT_IN_0 (vid==350?280:vid)
96#define W83781D_INIT_IN_1 (vid==350?280:vid)
97#define W83781D_INIT_IN_2 330
98#define W83781D_INIT_IN_3 500
99#define W83781D_INIT_IN_4 1200
100#define W83781D_INIT_IN_5 -1200
101#define W83781D_INIT_IN_6 -500
102
103#define W83781D_INIT_IN_PERCENTAGE 10
104
105#define W83781D_INIT_IN_MIN_0 \
106        (W83781D_INIT_IN_0 - W83781D_INIT_IN_0 * W83781D_INIT_IN_PERCENTAGE / 100)
107#define W83781D_INIT_IN_MAX_0 \
108        (W83781D_INIT_IN_0 + W83781D_INIT_IN_0 * W83781D_INIT_IN_PERCENTAGE / 100)
109#define W83781D_INIT_IN_MIN_1 \
110        (W83781D_INIT_IN_1 - W83781D_INIT_IN_1 * W83781D_INIT_IN_PERCENTAGE / 100)
111#define W83781D_INIT_IN_MAX_1 \
112        (W83781D_INIT_IN_1 + W83781D_INIT_IN_1 * W83781D_INIT_IN_PERCENTAGE / 100)
113#define W83781D_INIT_IN_MIN_2 \
114        (W83781D_INIT_IN_2 - W83781D_INIT_IN_2 * W83781D_INIT_IN_PERCENTAGE / 100)
115#define W83781D_INIT_IN_MAX_2 \
116        (W83781D_INIT_IN_2 + W83781D_INIT_IN_2 * W83781D_INIT_IN_PERCENTAGE / 100)
117#define W83781D_INIT_IN_MIN_3 \
118        (W83781D_INIT_IN_3 - W83781D_INIT_IN_3 * W83781D_INIT_IN_PERCENTAGE / 100)
119#define W83781D_INIT_IN_MAX_3 \
120        (W83781D_INIT_IN_3 + W83781D_INIT_IN_3 * W83781D_INIT_IN_PERCENTAGE / 100)
121#define W83781D_INIT_IN_MIN_4 \
122        (W83781D_INIT_IN_4 - W83781D_INIT_IN_4 * W83781D_INIT_IN_PERCENTAGE / 100)
123#define W83781D_INIT_IN_MAX_4 \
124        (W83781D_INIT_IN_4 + W83781D_INIT_IN_4 * W83781D_INIT_IN_PERCENTAGE / 100)
125#define W83781D_INIT_IN_MIN_5 \
126        (W83781D_INIT_IN_5 - W83781D_INIT_IN_5 * W83781D_INIT_IN_PERCENTAGE / 100)
127#define W83781D_INIT_IN_MAX_5 \
128        (W83781D_INIT_IN_5 + W83781D_INIT_IN_5 * W83781D_INIT_IN_PERCENTAGE / 100)
129#define W83781D_INIT_IN_MIN_6 \
130        (W83781D_INIT_IN_6 - W83781D_INIT_IN_6 * W83781D_INIT_IN_PERCENTAGE / 100)
131#define W83781D_INIT_IN_MAX_6 \
132        (W83781D_INIT_IN_6 + W83781D_INIT_IN_6 * W83781D_INIT_IN_PERCENTAGE / 100)
133
134#define W83781D_INIT_FAN_MIN_1 3000
135#define W83781D_INIT_FAN_MIN_2 3000
136#define W83781D_INIT_FAN_MIN_3 3000
137
138#define W83781D_INIT_TEMP_OVER 600
139#define W83781D_INIT_TEMP_HYST 500
140
141#ifdef MODULE
142extern int init_module(void);
143extern int cleanup_module(void);
144#endif /* MODULE */
145
146/* There are some complications in a module like this. First off, W83781D chips
147   may be both present on the SMBus and the ISA bus, and we have to handle
148   those cases separately at some places. Second, there might be several
149   W83781D chips available (well, actually, that is probably never done; but
150   it is a clean illustration of how to handle a case like that). Finally,
151   a specific chip may be attached to *both* ISA and SMBus, and we would
152   not like to detect it double. Fortunately, in the case of the W83781D at
153   least, a register tells us what SMBus address we are on, so that helps
154   a bit - except if there could be more than one SMBus. Groan. No solution
155   for this yet. */
156
157/* This module may seem overly long and complicated. In fact, it is not so
158   bad. Quite a lot of bookkeeping is done. A real driver can often cut
159   some corners. */
160
161/* For each registered W83781D, we need to keep some data in memory. That
162   data is pointed to by w83781d_list[NR]->data. The structure itself is
163   dynamically allocated, at the same time when a new w83781d client is
164   allocated. */
165struct w83781d_data {
166         struct semaphore lock;
167         int sysctl_id;
168
169         struct semaphore update_lock;
170         char valid;                 /* !=0 if following fields are valid */
171         unsigned long last_updated; /* In jiffies */
172
173         u8 in[7];                   /* Register value */
174         u8 in_max[7];               /* Register value */
175         u8 in_min[7];               /* Register value */
176         u8 fan[3];                  /* Register value */
177         u8 fan_min[3];              /* Register value */
178         u8 temp[3];                    /* Register value */
179         u8 temp_over[3];               /* Register value */
180         u8 temp_hyst[3];               /* Register value */
181         u8 fan_div[2];              /* Register encoding, shifted right */
182         u8 vid;                     /* Register encoding, combined */
183         u16 alarms;                 /* Register encoding, combined */
184};
185
186
187static int w83781d_init(void);
188static int w83781d_cleanup(void);
189
190static int w83781d_attach_adapter(struct i2c_adapter *adapter);
191static int w83781d_detect_isa(struct isa_adapter *adapter);
192static int w83781d_detect_smbus(struct i2c_adapter *adapter);
193static int w83781d_detach_client(struct i2c_client *client);
194static int w83781d_detach_isa(struct isa_client *client);
195static int w83781d_detach_smbus(struct i2c_client *client);
196static int w83781d_new_client(struct i2c_adapter *adapter,
197                           struct i2c_client *new_client);
198static void w83781d_remove_client(struct i2c_client *client);
199static int w83781d_command(struct i2c_client *client, unsigned int cmd, 
200                        void *arg);
201static void w83781d_inc_use (struct i2c_client *client);
202static void w83781d_dec_use (struct i2c_client *client);
203
204static int w83781d_read_value(struct i2c_client *client, u8 register);
205static int w83781d_write_value(struct i2c_client *client, u8 register, u8 value);
206static void w83781d_update_client(struct i2c_client *client);
207static void w83781d_init_client(struct i2c_client *client);
208
209
210static void w83781d_in(struct i2c_client *client, int operation, int ctl_name,
211                    int *nrels_mag, long *results);
212static void w83781d_fan(struct i2c_client *client, int operation, int ctl_name,
213                     int *nrels_mag, long *results);
214static void w83781d_temp(struct i2c_client *client, int operation, int ctl_name,
215                      int *nrels_mag, long *results,int tempnum);
216static void w83781d_temp1(struct i2c_client *client, int operation, int ctl_name,
217                      int *nrels_mag, long *results);
218static void w83781d_temp2(struct i2c_client *client, int operation, int ctl_name,
219                      int *nrels_mag, long *results);
220static void w83781d_temp3(struct i2c_client *client, int operation, int ctl_name,
221                      int *nrels_mag, long *results);
222static void w83781d_vid(struct i2c_client *client, int operation, int ctl_name,
223                     int *nrels_mag, long *results);
224static void w83781d_alarms(struct i2c_client *client, int operation, int ctl_name,
225                        int *nrels_mag, long *results);
226static void w83781d_fan_div(struct i2c_client *client, int operation, int ctl_name,
227                         int *nrels_mag, long *results);
228
229/* I choose here for semi-static W83781D allocation. Complete dynamic
230   allocation could also be used; the code needed for this would probably
231   take more memory than the datastructure takes now. */
232#define MAX_W83781D_NR 4
233static struct i2c_client *w83781d_list[MAX_W83781D_NR];
234
235/* The driver. I choose to use type i2c_driver, as at is identical to both
236   smbus_driver and isa_driver, and clients could be of either kind */
237static struct i2c_driver w83781d_driver = {
238  /* name */            "W83781D sensor driver",
239  /* id */              I2C_DRIVERID_W83781D,
240  /* flags */           DF_NOTIFY,
241  /* attach_adapter */  &w83781d_attach_adapter,
242  /* detach_client */   &w83781d_detach_client,
243  /* command */         &w83781d_command,
244  /* inc_use */         &w83781d_inc_use,
245  /* dec_use */         &w83781d_dec_use
246};
247
248/* Used by w83781d_init/cleanup */
249static int w83781d_initialized = 0;
250
251/* The /proc/sys entries */
252/* These files are created for each detected W83781D. This is just a template;
253   though at first sight, you might think we could use a statically
254   allocated list, we need some way to get back to the parent - which
255   is done through one of the 'extra' fields which are initialized
256   when a new copy is allocated. */
257static ctl_table w83781d_dir_table_template[] = {
258  { W83781D_SYSCTL_IN0, "in0", NULL, 0, 0644, NULL, &sensors_proc_real,
259    &sensors_sysctl_real, NULL, &w83781d_in },
260  { W83781D_SYSCTL_IN1, "in1", NULL, 0, 0644, NULL, &sensors_proc_real,
261    &sensors_sysctl_real, NULL, &w83781d_in },
262  { W83781D_SYSCTL_IN2, "in2", NULL, 0, 0644, NULL, &sensors_proc_real,
263    &sensors_sysctl_real, NULL, &w83781d_in },
264  { W83781D_SYSCTL_IN3, "in3", NULL, 0, 0644, NULL, &sensors_proc_real,
265    &sensors_sysctl_real, NULL, &w83781d_in },
266  { W83781D_SYSCTL_IN4, "in4", NULL, 0, 0644, NULL, &sensors_proc_real,
267    &sensors_sysctl_real, NULL, &w83781d_in },
268  { W83781D_SYSCTL_IN5, "in5", NULL, 0, 0644, NULL, &sensors_proc_real,
269    &sensors_sysctl_real, NULL, &w83781d_in },
270  { W83781D_SYSCTL_IN6, "in6", NULL, 0, 0644, NULL, &sensors_proc_real,
271    &sensors_sysctl_real, NULL, &w83781d_in },
272  { W83781D_SYSCTL_FAN1, "fan1", NULL, 0, 0644, NULL, &sensors_proc_real,
273    &sensors_sysctl_real, NULL, &w83781d_fan },
274  { W83781D_SYSCTL_FAN2, "fan2", NULL, 0, 0644, NULL, &sensors_proc_real,
275    &sensors_sysctl_real, NULL, &w83781d_fan },
276  { W83781D_SYSCTL_FAN3, "fan3", NULL, 0, 0644, NULL, &sensors_proc_real,
277    &sensors_sysctl_real, NULL, &w83781d_fan },
278  { W83781D_SYSCTL_TEMP, "temp", NULL, 0, 0644, NULL, &sensors_proc_real,
279    &sensors_sysctl_real, NULL, &w83781d_temp1 },
280  { W83781D_SYSCTL_TEMP2, "temp2", NULL, 0, 0644, NULL, &sensors_proc_real,
281    &sensors_sysctl_real, NULL, &w83781d_temp2 },
282  { W83781D_SYSCTL_TEMP3, "temp3", NULL, 0, 0644, NULL, &sensors_proc_real,
283    &sensors_sysctl_real, NULL, &w83781d_temp3 },
284  { W83781D_SYSCTL_VID, "vid", NULL, 0, 0644, NULL, &sensors_proc_real,
285    &sensors_sysctl_real, NULL, &w83781d_vid },
286  { W83781D_SYSCTL_FAN_DIV, "fan_div", NULL, 0, 0644, NULL, &sensors_proc_real,
287    &sensors_sysctl_real, NULL, &w83781d_fan_div },
288  { W83781D_SYSCTL_ALARMS, "alarms", NULL, 0, 0644, NULL, &sensors_proc_real,
289    &sensors_sysctl_real, NULL, &w83781d_alarms },
290  { 0 }
291};
292
293
294/* This function is called when:
295     * w83781d_driver is inserted (when this module is loaded), for each
296       available adapter
297     * when a new adapter is inserted (and w83781d_driver is still present) */
298int w83781d_attach_adapter(struct i2c_adapter *adapter)
299{
300  if (i2c_is_isa_adapter(adapter))
301    return w83781d_detect_isa((struct isa_adapter *) adapter);
302  else
303    return w83781d_detect_smbus(adapter);
304}
305
306/* This function is called whenever a client should be removed:
307    * w83781d_driver is removed (when this module is unloaded)
308    * when an adapter is removed which has a w83781d client (and w83781d_driver
309      is still present). */
310int w83781d_detach_client(struct i2c_client *client)
311{
312  if (i2c_is_isa_client(client))
313    return w83781d_detach_isa((struct isa_client *) client);
314  else
315    return w83781d_detach_smbus(client);
316}
317
318/* Detect whether there is a W83781D on the ISA bus, register and initialize
319   it. */
320int w83781d_detect_isa(struct isa_adapter *adapter)
321{
322  int address,err;
323  struct isa_client *new_client;
324  const char *type_name;
325  const char *client_name;
326
327  /* OK, this is no detection. I know. It will do for now, though.  */
328
329  err = 0;
330  for (address = 0x290; (! err) && (address <= 0x290); address += 0x08) {
331    if (check_region(address, W83781D_EXTENT))
332      continue;
333
334    /* Awful, but true: unused port addresses should return 0xff */
335    if ((inb_p(address + 1) != 0xff) || (inb_p(address + 2) != 0xff) ||
336       (inb_p(address + 3) != 0xff) || (inb_p(address + 7) != 0xff))
337      continue;
338   
339    if (inb_p(address + W83781D_ADDR_REG_OFFSET) == 0xff) {
340      outb_p(0x00,address + W83781D_ADDR_REG_OFFSET);
341      if (inb_p(address + W83781D_ADDR_REG_OFFSET) == 0xff)
342        continue;
343    }
344   
345    /* Real detection code goes here */
346
347    outb_p(W83781D_REG_CHIPID,address + W83781D_ADDR_REG_OFFSET);
348    err = inb_p(address + W83781D_DATA_REG_OFFSET) & 0xfe;
349
350    if (err != 0x20) {
351      printk("w83781d.o: Winbond W83781D detected (ISA addr=0x%X)\n",address);
352      type_name = "w83781d";
353      client_name = "Winbond W83781D chip";
354    } else {
355 #ifdef DEBUG
356     printk("83781d.o: Winbond W83781D not detected (ISA)\n");
357 #endif
358     continue;
359    }
360
361    request_region(address, W83781D_EXTENT, type_name);
362
363    /* Allocate space for a new client structure */
364    if (! (new_client = kmalloc(sizeof(struct isa_client) + 
365                                sizeof(struct w83781d_data),
366                               GFP_KERNEL)))
367    {
368      err=-ENOMEM;
369      goto ERROR1;
370    } 
371
372    /* Fill the new client structure with data */
373    new_client->data = (struct w83781d_data *) (new_client + 1);
374    new_client->addr = 0;
375    strcpy(new_client->name,client_name);
376    new_client->isa_addr = address;
377    if ((err = w83781d_new_client((struct i2c_adapter *) adapter,
378                               (struct i2c_client *) new_client)))
379      goto ERROR2;
380
381    /* Tell i2c-core a new client has arrived */
382    if ((err = isa_attach_client(new_client)))
383      goto ERROR3;
384   
385    /* Register a new directory entry with module sensors */
386    if ((err = sensors_register_entry((struct i2c_client *) new_client,
387                                      type_name,
388                                      w83781d_dir_table_template)) < 0)
389      goto ERROR4;
390    ((struct w83781d_data *) (new_client->data)) -> sysctl_id = err;
391    err = 0;
392
393    /* Initialize the W83781D chip */
394    w83781d_init_client((struct i2c_client *) new_client);
395    continue;
396
397/* OK, this is not exactly good programming practice, usually. But it is
398   very code-efficient in this case. */
399
400ERROR4:
401    isa_detach_client(new_client);
402ERROR3:
403    w83781d_remove_client((struct i2c_client *) new_client);
404ERROR2:
405    kfree(new_client);
406ERROR1:
407    release_region(address, W83781D_EXTENT);
408  }
409  return err;
410
411}
412
413/* Deregister and remove a W83781D client */
414int w83781d_detach_isa(struct isa_client *client)
415{
416  int err,i;
417  for (i = 0; i < MAX_W83781D_NR; i++)
418    if ((client == (struct isa_client *) (w83781d_list[i])))
419      break;
420  if (i == MAX_W83781D_NR) {
421    printk("w83781d.o: Client to detach not found.\n");
422    return -ENOENT;
423  }
424
425  sensors_deregister_entry(((struct w83781d_data *)(client->data))->sysctl_id);
426
427  if ((err = isa_detach_client(client))) {
428    printk("w83781d.o: Client deregistration failed, client not detached.\n");
429    return err;
430  }
431  w83781d_remove_client((struct i2c_client *) client);
432  release_region(client->isa_addr,W83781D_EXTENT);
433  kfree(client);
434  return 0;
435}
436
437int w83781d_detect_smbus(struct i2c_adapter *adapter)
438{
439  int address,err;
440  struct i2c_client *new_client;
441  const char *type_name,*client_name;
442
443  /* OK, this is no detection. I know. It will do for now, though.  */
444  err = 0;
445  for (address = 0x20; (! err) && (address <= 0x2f); address ++) {
446
447    /* Later on, we will keep a list of registered addresses for each
448       adapter, and check whether they are used here */
449
450    if (smbus_read_byte_data(adapter,address,W83781D_REG_CONFIG) < 0) 
451      continue;
452
453    err = smbus_read_byte_data(adapter,address,W83781D_REG_CHIPID);
454   
455    if (err == 0x20) {
456      printk("w83781d.o: Winbond W83781D detected (SMBus addr 0x%X)\n",address);
457      type_name = "w83781d";
458      client_name = "Winbond W83781D chip";
459    } else {
460 #ifdef DEBUG
461     printk("83781d.o: Winbond W83781D not detected (SMBus/I2C)\n");
462 #endif
463     continue;
464    }
465
466    /* Allocate space for a new client structure. To counter memory
467       ragmentation somewhat, we only do one kmalloc. */
468    if (! (new_client = kmalloc(sizeof(struct i2c_client) + 
469                                sizeof(struct w83781d_data),
470                               GFP_KERNEL))) {
471      err = -ENOMEM;
472      continue;
473    }
474
475    /* Fill the new client structure with data */
476    new_client->data = (struct w83781d_data *) (new_client + 1);
477    new_client->addr = address;
478    strcpy(new_client->name,client_name);
479    if ((err = w83781d_new_client(adapter,new_client)))
480      goto ERROR2;
481
482    /* Tell i2c-core a new client has arrived */
483    if ((err = i2c_attach_client(new_client))) 
484      goto ERROR3;
485
486    /* Register a new directory entry with module sensors */
487    if ((err = sensors_register_entry(new_client,type_name,
488                                      w83781d_dir_table_template)) < 0)
489      goto ERROR4;
490    ((struct w83781d_data *) (new_client->data))->sysctl_id = err;
491    err = 0;
492
493    /* Initialize the W83781D chip */
494    w83781d_init_client(new_client);
495    continue;
496
497/* OK, this is not exactly good programming practice, usually. But it is
498   very code-efficient in this case. */
499ERROR4:
500    i2c_detach_client(new_client);
501ERROR3:
502    w83781d_remove_client((struct i2c_client *) new_client);
503ERROR2:
504    kfree(new_client);
505  }
506  return err;
507}
508
509int w83781d_detach_smbus(struct i2c_client *client)
510{
511  int err,i;
512  for (i = 0; i < MAX_W83781D_NR; i++)
513    if (client == w83781d_list[i])
514      break;
515  if ((i == MAX_W83781D_NR)) {
516    printk("w83781d.o: Client to detach not found.\n");
517    return -ENOENT;
518  }
519
520  sensors_deregister_entry(((struct w83781d_data *)(client->data))->sysctl_id);
521
522  if ((err = i2c_detach_client(client))) {
523    printk("w83781d.o: Client deregistration failed, client not detached.\n");
524    return err;
525  }
526  w83781d_remove_client(client);
527  kfree(client);
528  return 0;
529}
530
531
532/* Find a free slot, and initialize most of the fields */
533int w83781d_new_client(struct i2c_adapter *adapter,
534                    struct i2c_client *new_client)
535{
536  int i;
537  struct w83781d_data *data;
538
539  /* First, seek out an empty slot */
540  for(i = 0; i < MAX_W83781D_NR; i++)
541    if (! w83781d_list[i])
542      break;
543  if (i == MAX_W83781D_NR) {
544    printk("w83781d.o: No empty slots left, recompile and heighten "
545           "MAX_W83781D_NR!\n");
546    return -ENOMEM;
547  }
548 
549  w83781d_list[i] = new_client;
550  new_client->id = i;
551  new_client->adapter = adapter;
552  new_client->driver = &w83781d_driver;
553  data = new_client->data;
554  data->valid = 0;
555  data->lock = MUTEX;
556  data->update_lock = MUTEX;
557  return 0;
558}
559
560/* Inverse of w83781d_new_client */
561void w83781d_remove_client(struct i2c_client *client)
562{
563  int i;
564  for (i = 0; i < MAX_W83781D_NR; i++)
565    if (client == w83781d_list[i]) 
566      w83781d_list[i] = NULL;
567}
568
569/* No commands defined yet */
570int w83781d_command(struct i2c_client *client, unsigned int cmd, void *arg)
571{
572  return 0;
573}
574
575/* Nothing here yet */
576void w83781d_inc_use (struct i2c_client *client)
577{
578#ifdef MODULE
579  MOD_INC_USE_COUNT;
580#endif
581}
582
583/* Nothing here yet */
584void w83781d_dec_use (struct i2c_client *client)
585{
586#ifdef MODULE
587  MOD_DEC_USE_COUNT;
588#endif
589}
590 
591
592/* The SMBus locks itself, but ISA access must be locked explicitely!
593   We ignore the W83781D BUSY flag at this moment - it could lead to deadlocks,
594   would slow down the W83781D access and should not be necessary.
595   There are some ugly typecasts here, but the good new is - they should
596   nowhere else be necessary! */
597int w83781d_read_value(struct i2c_client *client, u8 reg)
598{
599  int res;
600  if (i2c_is_isa_client(client)) {
601    down((struct semaphore *) (client->data));
602    outb_p(reg,(((struct isa_client *) client)->isa_addr) + 
603               W83781D_ADDR_REG_OFFSET);
604    res = inb_p((((struct isa_client *) client)->isa_addr) + 
605                W83781D_DATA_REG_OFFSET);
606    up((struct semaphore *) (client->data));
607    return res;
608  } else
609    return smbus_read_byte_data(client->adapter,client->addr, reg);
610}
611
612/* The SMBus locks itself, but ISA access muse be locked explicitely!
613   We ignore the W83781D BUSY flag at this moment - it could lead to deadlocks,
614   would slow down the W83781D access and should not be necessary.
615   There are some ugly typecasts here, but the good new is - they should
616   nowhere else be necessary! */
617int w83781d_write_value(struct i2c_client *client, u8 reg, u8 value)
618{
619  if (i2c_is_isa_client(client)) {
620    down((struct semaphore *) (client->data));
621    outb_p(reg,((struct isa_client *) client)->isa_addr + W83781D_ADDR_REG_OFFSET);
622    outb_p(value,((struct isa_client *) client)->isa_addr + W83781D_DATA_REG_OFFSET);
623    up((struct semaphore *) (client->data));
624    return 0;
625  } else
626    return smbus_write_byte_data(client->adapter, client->addr, reg,value);
627}
628
629/* Called when we have found a new W83781D. It should set limits, etc. */
630void w83781d_init_client(struct i2c_client *client)
631{
632  int vid;
633
634  /* Reset all except Watchdog values and last conversion values
635     This sets fan-divs to 2, among others */
636  w83781d_write_value(client,W83781D_REG_CONFIG,0x80);
637
638  vid = w83781d_read_value(client,W83781D_REG_VID_FANDIV) & 0x0f;
639  vid |= (w83781d_read_value(client,W83781D_REG_CHIPID) & 0x01) >> 4;
640  vid = VID_FROM_REG(vid);
641
642  w83781d_write_value(client,W83781D_REG_IN_MIN(0),IN_TO_REG(W83781D_INIT_IN_MIN_0,0));
643  w83781d_write_value(client,W83781D_REG_IN_MAX(0),IN_TO_REG(W83781D_INIT_IN_MAX_0,0));
644  w83781d_write_value(client,W83781D_REG_IN_MIN(1),IN_TO_REG(W83781D_INIT_IN_MIN_1,1));
645  w83781d_write_value(client,W83781D_REG_IN_MAX(1),IN_TO_REG(W83781D_INIT_IN_MAX_1,1));
646  w83781d_write_value(client,W83781D_REG_IN_MIN(2),IN_TO_REG(W83781D_INIT_IN_MIN_2,2));
647  w83781d_write_value(client,W83781D_REG_IN_MAX(2),IN_TO_REG(W83781D_INIT_IN_MAX_2,2));
648  w83781d_write_value(client,W83781D_REG_IN_MIN(3),IN_TO_REG(W83781D_INIT_IN_MIN_3,3));
649  w83781d_write_value(client,W83781D_REG_IN_MAX(3),IN_TO_REG(W83781D_INIT_IN_MAX_3,3));
650  w83781d_write_value(client,W83781D_REG_IN_MIN(4),IN_TO_REG(W83781D_INIT_IN_MIN_4,4));
651  w83781d_write_value(client,W83781D_REG_IN_MAX(4),IN_TO_REG(W83781D_INIT_IN_MAX_4,4));
652  w83781d_write_value(client,W83781D_REG_IN_MIN(5),IN_TO_REG(W83781D_INIT_IN_MIN_5,5));
653  w83781d_write_value(client,W83781D_REG_IN_MAX(5),IN_TO_REG(W83781D_INIT_IN_MAX_5,5));
654  w83781d_write_value(client,W83781D_REG_IN_MIN(6),IN_TO_REG(W83781D_INIT_IN_MIN_6,6));
655  w83781d_write_value(client,W83781D_REG_IN_MAX(6),IN_TO_REG(W83781D_INIT_IN_MAX_6,6));
656  w83781d_write_value(client,W83781D_REG_FAN_MIN(1),FAN_TO_REG(W83781D_INIT_FAN_MIN_1));
657  w83781d_write_value(client,W83781D_REG_FAN_MIN(2),FAN_TO_REG(W83781D_INIT_FAN_MIN_2));
658  w83781d_write_value(client,W83781D_REG_FAN_MIN(3),FAN_TO_REG(W83781D_INIT_FAN_MIN_3));
659  /* Init Temp Sensor1 */
660  w83781d_write_value(client,W83781D_REG_TEMP_SEL,0x00);/* Switch Banks! */
661  w83781d_write_value(client,W83781D_REG_TEMP_OVER,TEMP_TO_REG(W83781D_INIT_TEMP_OVER));
662  w83781d_write_value(client,W83781D_REG_TEMP_HYST,TEMP_TO_REG(W83781D_INIT_TEMP_HYST));
663  w83781d_write_value(client,W83781D_REG_TEMP_CONFIG,0x00);
664  /* Init Temp Sensor2 */
665  w83781d_write_value(client,W83781D_REG_TEMP_SEL,0x01);/* Switch Banks! */
666  w83781d_write_value(client,W83781D_REG_TEMP_OVER23,TEMP_TO_REG(W83781D_INIT_TEMP_OVER));
667  w83781d_write_value(client,W83781D_REG_TEMP_OVER23 + 1,0);
668  w83781d_write_value(client,W83781D_REG_TEMP_HYST23,TEMP_TO_REG(W83781D_INIT_TEMP_HYST));
669  w83781d_write_value(client,W83781D_REG_TEMP_HYST23 + 1,0);
670  w83781d_write_value(client,W83781D_REG_TEMP_CONFIG23,0x00);
671  /* Init Temp Sensor3 */
672  w83781d_write_value(client,W83781D_REG_TEMP_SEL,0x02);/* Switch Banks! */
673  w83781d_write_value(client,W83781D_REG_TEMP_OVER23,TEMP_TO_REG(W83781D_INIT_TEMP_OVER));
674  w83781d_write_value(client,W83781D_REG_TEMP_OVER23 + 1,0);
675  w83781d_write_value(client,W83781D_REG_TEMP_HYST23,TEMP_TO_REG(W83781D_INIT_TEMP_HYST));
676  w83781d_write_value(client,W83781D_REG_TEMP_HYST23 + 1,0);
677  w83781d_write_value(client,W83781D_REG_TEMP_CONFIG23,0x00);
678  w83781d_write_value(client,W83781D_REG_TEMP_SEL,0x00);/* Switch Banks! */
679
680  /* Start monitoring */
681  w83781d_write_value(client,W83781D_REG_CONFIG,
682                   (w83781d_read_value(client,W83781D_REG_CONFIG) & 0xf7) | 0x01);
683 
684}
685
686void w83781d_update_client(struct i2c_client *client)
687{
688  struct w83781d_data *data = client->data;
689  int i;
690
691  down(&data->update_lock);
692
693  if ((jiffies - data->last_updated > HZ+HZ/2 ) ||
694      (jiffies < data->last_updated) || ! data->valid) {
695
696#ifdef DEBUG
697    printk("Starting w83781d update\n");
698#endif
699    for (i = 0; i <= 6; i++) {
700      data->in[i]     = w83781d_read_value(client,W83781D_REG_IN(i));
701      data->in_min[i] = w83781d_read_value(client,W83781D_REG_IN_MIN(i));
702      data->in_max[i] = w83781d_read_value(client,W83781D_REG_IN_MAX(i));
703    }
704    for (i = 1; i <= 3; i++) {
705      data->fan[i-1] = w83781d_read_value(client,W83781D_REG_FAN(i));
706      data->fan_min[i-1] = w83781d_read_value(client,W83781D_REG_FAN_MIN(i));
707    }
708    data->temp[0] = w83781d_read_value(client,W83781D_REG_TEMP);
709    data->temp_over[0] = w83781d_read_value(client,W83781D_REG_TEMP_OVER);
710    data->temp_hyst[0] = w83781d_read_value(client,W83781D_REG_TEMP_HYST);
711    w83781d_write_value(client,W83781D_REG_TEMP_SEL,1);/* Switch Banks!! */
712    data->temp[1] = w83781d_read_value(client,W83781D_REG_TEMP23);
713    data->temp_over[1] = w83781d_read_value(client,W83781D_REG_TEMP_OVER23);
714    data->temp_hyst[1] = w83781d_read_value(client,W83781D_REG_TEMP_HYST23);
715    w83781d_write_value(client,W83781D_REG_TEMP_SEL,2);/* Switch Banks!! */
716    data->temp[2] = w83781d_read_value(client,W83781D_REG_TEMP23);
717    data->temp_over[2] = w83781d_read_value(client,W83781D_REG_TEMP_OVER23);
718    data->temp_hyst[2] = w83781d_read_value(client,W83781D_REG_TEMP_HYST23);
719    w83781d_write_value(client,W83781D_REG_TEMP_SEL,0);/* Switch Banks!! */
720    i = w83781d_read_value(client,W83781D_REG_VID_FANDIV);
721    data->vid = i & 0x0f;
722    data->vid |= (w83781d_read_value(client,W83781D_REG_CHIPID) & 0x01) >> 4;
723    data->fan_div[0] = (i >> 4) & 0x03;
724    data->fan_div[1] = i >> 6;
725    data->alarms = w83781d_read_value(client,W83781D_REG_ALARM1) +
726                   (w83781d_read_value(client,W83781D_REG_ALARM2) >> 8);
727    data->last_updated = jiffies;
728    data->valid = 1;
729  }
730
731  up(&data->update_lock);
732}
733
734
735/* The next few functions are the call-back functions of the /proc/sys and
736   sysctl files. Which function is used is defined in the ctl_table in
737   the extra1 field.
738   Each function must return the magnitude (power of 10 to divide the date
739   with) if it is called with operation==SENSORS_PROC_REAL_INFO. It must
740   put a maximum of *nrels elements in results reflecting the data of this
741   file, and set *nrels to the number it actually put in it, if operation==
742   SENSORS_PROC_REAL_READ. Finally, it must get upto *nrels elements from
743   results and write them to the chip, if operations==SENSORS_PROC_REAL_WRITE.
744   Note that on SENSORS_PROC_REAL_READ, I do not check whether results is
745   large enough (by checking the incoming value of *nrels). This is not very
746   good practice, but as long as you put less than about 5 values in results,
747   you can assume it is large enough. */
748void w83781d_in(struct i2c_client *client, int operation, int ctl_name, 
749             int *nrels_mag, long *results)
750{
751  struct w83781d_data *data = client->data;
752  int nr = ctl_name - W83781D_SYSCTL_IN0;
753
754  if (operation == SENSORS_PROC_REAL_INFO)
755    *nrels_mag = 2;
756  else if (operation == SENSORS_PROC_REAL_READ) {
757    w83781d_update_client(client);
758    results[0] = IN_FROM_REG(data->in_min[nr],nr);
759    results[1] = IN_FROM_REG(data->in_max[nr],nr);
760    results[2] = IN_FROM_REG(data->in[nr],nr);
761    *nrels_mag = 3;
762  } else if (operation == SENSORS_PROC_REAL_WRITE) {
763      if (*nrels_mag >= 1) {
764        data->in_min[nr] = IN_TO_REG(results[0],nr);
765        w83781d_write_value(client,W83781D_REG_IN_MIN(nr),data->in_min[nr]);
766      }
767      if (*nrels_mag >= 2) {
768        data->in_max[nr] = IN_TO_REG(results[1],nr);
769        w83781d_write_value(client,W83781D_REG_IN_MAX(nr),data->in_max[nr]);
770      }
771  }
772}
773
774void w83781d_fan(struct i2c_client *client, int operation, int ctl_name,
775              int *nrels_mag, long *results)
776{
777  struct w83781d_data *data = client->data;
778  int nr = ctl_name - W83781D_SYSCTL_FAN1 + 1;
779
780  if (operation == SENSORS_PROC_REAL_INFO)
781    *nrels_mag = 0;
782  else if (operation == SENSORS_PROC_REAL_READ) {
783    w83781d_update_client(client);
784    results[0] = FAN_FROM_REG(data->fan_min[nr-1]);
785    results[1] = FAN_FROM_REG(data->fan[nr-1]);
786    *nrels_mag = 2;
787  } else if (operation == SENSORS_PROC_REAL_WRITE) {
788    if (*nrels_mag >= 1) {
789      data->fan_min[nr-1] = FAN_TO_REG(results[0]);
790      w83781d_write_value(client,W83781D_REG_FAN_MIN(nr),data->fan_min[nr-1]);
791    }
792  }
793}
794
795
796void w83781d_temp(struct i2c_client *client, int operation, int ctl_name,
797               int *nrels_mag, long *results,int tempnum )
798{
799  struct w83781d_data *data = client->data;
800  if (operation == SENSORS_PROC_REAL_INFO)
801    *nrels_mag = 1;
802  else if (operation == SENSORS_PROC_REAL_READ) {
803    w83781d_update_client(client);
804    results[0] = TEMP_FROM_REG(data->temp_over[tempnum - 1]);
805    results[1] = TEMP_FROM_REG(data->temp_hyst[tempnum - 1]);
806    results[2] = TEMP_FROM_REG(data->temp[tempnum - 1]);
807    *nrels_mag = 3;
808  } else if (operation == SENSORS_PROC_REAL_WRITE) {
809    if (tempnum == 3) {
810     w83781d_write_value(client,W83781D_REG_TEMP_SEL,0x02);/* Switch Banks!! */
811     if (*nrels_mag >= 1) {
812       data->temp_over[2] = TEMP_TO_REG(results[0]);
813       w83781d_write_value(client,W83781D_REG_TEMP_OVER23,data->temp_over[2]);
814       w83781d_write_value(client,W83781D_REG_TEMP_OVER23 + 1,0);
815     }
816     if (*nrels_mag >= 2) {
817       data->temp_hyst[2] = TEMP_TO_REG(results[1]);
818       w83781d_write_value(client,W83781D_REG_TEMP_HYST23,data->temp_hyst[2]);
819       w83781d_write_value(client,W83781D_REG_TEMP_HYST23 + 1,0);
820     }
821     w83781d_write_value(client,W83781D_REG_TEMP_SEL,0x0);/* Switch Banks!! */
822    } else if (tempnum == 2) {
823     w83781d_write_value(client,W83781D_REG_TEMP_SEL,0x01);/* Switch Banks!! */
824     if (*nrels_mag >= 1) {
825       data->temp_over[1] = TEMP_TO_REG(results[0]);
826       w83781d_write_value(client,W83781D_REG_TEMP_OVER23,data->temp_over[1]);
827       w83781d_write_value(client,W83781D_REG_TEMP_OVER23 + 1,0);
828     }
829     if (*nrels_mag >= 2) {
830       data->temp_hyst[1] = TEMP_TO_REG(results[1]);
831       w83781d_write_value(client,W83781D_REG_TEMP_HYST23,data->temp_hyst[1]);
832       w83781d_write_value(client,W83781D_REG_TEMP_HYST23 + 1,0);
833     }
834     w83781d_write_value(client,W83781D_REG_TEMP_SEL,0x0);/* Switch Banks!! */
835    } else {
836     if (*nrels_mag >= 1) {
837       data->temp_over[0] = TEMP_TO_REG(results[0]);
838       w83781d_write_value(client,W83781D_REG_TEMP_OVER,data->temp_over[0]);
839     }
840     if (*nrels_mag >= 2) {
841       data->temp_hyst[0] = TEMP_TO_REG(results[1]);
842       w83781d_write_value(client,W83781D_REG_TEMP_HYST,data->temp_hyst[0]);
843     }
844    }
845  }
846}
847
848/* Change back! */
849
850void w83781d_temp1(struct i2c_client *client, int operation, int ctl_name,
851               int *nrels_mag, long *results) {
852
853  w83781d_temp(client,operation,ctl_name,nrels_mag,results,1);
854}
855
856
857void w83781d_temp2(struct i2c_client *client, int operation, int ctl_name,
858               int *nrels_mag, long *results) {
859               
860  w83781d_temp(client,operation,ctl_name,nrels_mag,results,2);
861}
862
863
864void w83781d_temp3(struct i2c_client *client, int operation, int ctl_name,
865               int *nrels_mag, long *results) {
866               
867  w83781d_temp(client,operation,ctl_name,nrels_mag,results,3);
868}
869
870
871void w83781d_vid(struct i2c_client *client, int operation, int ctl_name,
872              int *nrels_mag, long *results)
873{
874  struct w83781d_data *data = client->data;
875  if (operation == SENSORS_PROC_REAL_INFO)
876    *nrels_mag = 2;
877  else if (operation == SENSORS_PROC_REAL_READ) {
878    w83781d_update_client(client);
879    results[0] = VID_FROM_REG(data->vid);
880    *nrels_mag = 1;
881  }
882}
883
884void w83781d_alarms(struct i2c_client *client, int operation, int ctl_name,
885                 int *nrels_mag, long *results)
886{
887  struct w83781d_data *data = client->data;
888  if (operation == SENSORS_PROC_REAL_INFO)
889    *nrels_mag = 0;
890  else if (operation == SENSORS_PROC_REAL_READ) {
891    w83781d_update_client(client);
892    results[0] = ALARMS_FROM_REG(data->alarms);
893    *nrels_mag = 1;
894  }
895}
896
897void w83781d_fan_div(struct i2c_client *client, int operation, int ctl_name,
898                  int *nrels_mag, long *results)
899{
900  struct w83781d_data *data = client->data;
901  int old;
902
903  if (operation == SENSORS_PROC_REAL_INFO)
904    *nrels_mag = 0;
905  else if (operation == SENSORS_PROC_REAL_READ) {
906    w83781d_update_client(client);
907    results[0] = DIV_FROM_REG(data->fan_div[0]);
908    results[1] = DIV_FROM_REG(data->fan_div[1]);
909    results[2] = 2;
910    *nrels_mag = 3;
911  } else if (operation == SENSORS_PROC_REAL_WRITE) {
912    old = w83781d_read_value(client,W83781D_REG_VID_FANDIV);
913    if (*nrels_mag >= 2) {
914      data->fan_div[1] = DIV_TO_REG(results[1]);
915      old = (old & 0x3f) | (data->fan_div[1] << 6);
916    }
917    if (*nrels_mag >= 1) {
918      data->fan_div[0] = DIV_TO_REG(results[0]);
919      old = (old & 0xcf) | (data->fan_div[0] << 4);
920      w83781d_write_value(client,W83781D_REG_VID_FANDIV,old);
921    }
922  }
923}
924
925int w83781d_init(void)
926{
927  int res;
928
929  printk("w83781d.o version %s (%s)\n",LM_VERSION,LM_DATE);
930  w83781d_initialized = 0;
931
932  if ((res =i2c_add_driver(&w83781d_driver))) {
933    printk("w83781d.o: Driver registration failed, module not inserted.\n");
934    w83781d_cleanup();
935    return res;
936  }
937  w83781d_initialized ++;
938  return 0;
939}
940
941int w83781d_cleanup(void)
942{
943  int res;
944
945  if (w83781d_initialized >= 1) {
946    if ((res = i2c_del_driver(&w83781d_driver))) {
947      printk("w83781d.o: Driver deregistration failed, module not removed.\n");
948      return res;
949    }
950    w83781d_initialized --;
951  }
952  return 0;
953}
954
955
956#ifdef MODULE
957
958MODULE_AUTHOR("Frodo Looijaard <frodol@dds.nl> and Philip Edelbrock <phil@netroedge.com>");
959MODULE_DESCRIPTION("W83781D driver");
960
961int init_module(void)
962{
963  return w83781d_init();
964}
965
966int cleanup_module(void)
967{
968  return w83781d_cleanup();
969}
970
971#endif /* MODULE */
972
Note: See TracBrowser for help on using the browser.