root/lm-sensors/trunk/kernel/chips/w83781d.c @ 85

Revision 85, 35.3 KB (checked in by phil, 14 years ago)

(Phil) Tried to add remote temp sensors support to Winbond driver. My board
doesn't seem to have any sensors (I guess?), or the Windbond PDF is so
convoluted that I haven't understood it enough to get it working (another
good possibility). Oh, well. It builds and inserts, anyway.

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