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

Revision 466, 59.7 KB (checked in by frodo, 14 years ago)

Small W83781D typo fixed, new TODO list entries

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
Line 
1/*
2    w83781d.c - Part of lm_sensors, Linux kernel modules for hardware
3                monitoring
4    Copyright (c) 1998, 1999  Frodo Looijaard <frodol@dds.nl>,
5    Philip Edelbrock <phil@netroedge.com>,
6    and Mark Studebaker <mds@eng.paradyne.com>
7
8    This program is free software; you can redistribute it and/or modify
9    it under the terms of the GNU General Public License as published by
10    the Free Software Foundation; either version 2 of the License, or
11    (at your option) any later version.
12
13    This program is distributed in the hope that it will be useful,
14    but WITHOUT ANY WARRANTY; without even the implied warranty of
15    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16    GNU General Public License for more details.
17
18    You should have received a copy of the GNU General Public License
19    along with this program; if not, write to the Free Software
20    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
21*/
22
23/*
24    Supports following chips:
25
26    Chip        #vin    #fanin  #pwm    #temp   wchipid i2c     ISA
27    w83781d     7       3       0       3       0x10    yes     yes
28    w83782d     9       3       2-4     3       0x30    yes     yes
29    w83783s     5-6     3       2       1-2     0x40    yes     no
30
31*/
32
33#include <linux/module.h>
34#include <linux/malloc.h>
35#include <linux/proc_fs.h>
36#include <linux/ioport.h>
37#include <linux/sysctl.h>
38#include <asm/errno.h>
39#include <asm/io.h>
40#include <linux/types.h>
41#include "smbus.h"
42#include "version.h"
43#include "i2c-isa.h"
44#include "sensors.h"
45#include "i2c.h"
46#include "compat.h"
47
48/* RT Table support #defined so we can take it out if it gets bothersome */
49#define W83781D_RT 1
50
51/* Addresses to scan */
52static unsigned short normal_i2c[] = {SENSORS_I2C_END};
53static unsigned short normal_i2c_range[] = {0x20,0x2f,SENSORS_I2C_END};
54static unsigned int normal_isa[] = {0x0290,SENSORS_ISA_END};
55static unsigned int normal_isa_range[] = {SENSORS_ISA_END};
56
57/* Insmod parameters */
58SENSORS_INSMOD_3(w83781d,w83782d,w83783s);
59
60/* Many W83781D constants specified below */
61
62/* Length of ISA address segment */
63#define W83781D_EXTENT 8
64
65/* Where are the ISA address/data registers relative to the base address */
66#define W83781D_ADDR_REG_OFFSET 5
67#define W83781D_DATA_REG_OFFSET 6
68
69/* The W83781D registers */
70/* The W83782D registers for nr=7,8 are in bank 5 */
71#define W83781D_REG_IN_MAX(nr) ((nr < 7) ? (0x2b + (nr) * 2) : \
72                                           (0x554 + (((nr) - 7) * 2)))
73#define W83781D_REG_IN_MIN(nr) ((nr < 7) ? (0x2c + (nr) * 2) : \
74                                           (0x555 + (((nr) - 7) * 2)))
75#define W83781D_REG_IN(nr)     ((nr < 7) ? (0x20 + (nr)) : \
76                                           (0x550 + (nr) - 7))
77
78#define W83781D_REG_FAN_MIN(nr) (0x3a + (nr))
79#define W83781D_REG_FAN(nr) (0x27 + (nr))
80
81#define W83781D_REG_TEMP2 0x0150
82#define W83781D_REG_TEMP3 0x0250
83#define W83781D_REG_TEMP2_HYST 0x153
84#define W83781D_REG_TEMP3_HYST 0x253
85#define W83781D_REG_TEMP2_CONFIG 0x152
86#define W83781D_REG_TEMP3_CONFIG 0x252
87#define W83781D_REG_TEMP2_OVER 0x155
88#define W83781D_REG_TEMP3_OVER 0x255
89
90#define W83781D_REG_TEMP 0x27
91#define W83781D_REG_TEMP_OVER 0x39
92#define W83781D_REG_TEMP_HYST 0x3A
93#define W83781D_REG_BANK 0x4E
94
95#define W83781D_REG_CONFIG 0x40
96#define W83781D_REG_ALARM1 0x41
97#define W83781D_REG_ALARM2 0x42
98#define W83781D_REG_ALARM3 0x450        /* W83782D only */
99
100#define W83781D_REG_BEEP_CONFIG 0x4D
101#define W83781D_REG_BEEP_INTS1 0x56
102#define W83781D_REG_BEEP_INTS2 0x57
103#define W83781D_REG_BEEP_INTS3 0x453    /* W83782D only */
104
105#define W83781D_REG_VID_FANDIV 0x47
106
107#define W83781D_REG_CHIPID 0x49
108#define W83781D_REG_WCHIPID 0x58
109#define W83781D_REG_CHIPMAN 0x4F
110#define W83781D_REG_PIN 0x4B
111
112/* 782D/783S only */
113#define W83781D_REG_VBAT 0x5D
114
115/* PWM 782D (1-4) and 783S (1-2) only */
116#define W83781D_REG_PWM1 0x5B   /* 782d and 783s datasheets disagree */
117                                /* on which is which. */
118#define W83781D_REG_PWM2 0x5A   /* We follow the 782d convention here */
119#define W83781D_REG_PWM3 0x5E
120#define W83781D_REG_PWM4 0x5F
121#define W83781D_REG_PWMCLK12 0x5C
122#define W83781D_REG_PWMCLK34 0x45C
123static const u8 regpwm[] = {W83781D_REG_PWM1, W83781D_REG_PWM2, 
124                            W83781D_REG_PWM3, W83781D_REG_PWM4};
125#define W83781D_REG_PWM(nr) (regpwm[(nr) - 1])
126
127#define W83781D_REG_I2C_ADDR 0x48
128
129/* The following are undocumented in the data sheets however we
130   received the information in an email from Winbond tech support */
131/* Sensor selection 782D/783S only */
132#define W83781D_REG_SCFG1 0x5D
133static const u8 BIT_SCFG1[] = {0x02, 0x04, 0x08};
134#define W83781D_REG_SCFG2 0x59
135static const u8 BIT_SCFG2[] = {0x10, 0x04, 0x08};
136#define W83781D_DEFAULT_BETA 3435
137
138/* RT Table registers */
139#define W83781D_REG_RT_IDX 0x50
140#define W83781D_REG_RT_VAL 0x51
141
142/* Conversions. Rounding and limit checking is only done on the TO_REG
143   variants. Note that you should be a bit careful with which arguments
144   these macros are called: arguments may be evaluated more than once.
145   Fixing this is just not worth it. */
146#define IN_TO_REG(val)  (SENSORS_LIMIT((((val) * 10 + 8)/16),0,255))
147#define IN_FROM_REG(val) (((val) * 16) / 10)
148
149extern inline u8 FAN_TO_REG(long rpm, int div)
150{
151  if (rpm == 0)
152    return 255;
153  rpm = SENSORS_LIMIT(rpm,1,1000000);
154  return SENSORS_LIMIT((1350000 + rpm*div/2) / (rpm*div),1,254);
155}
156
157#define FAN_FROM_REG(val,div) ((val)==0?-1:(val)==255?0:1350000/((val)*(div)))
158
159#define TEMP_TO_REG(val) (SENSORS_LIMIT(((val)<0?(((val)-5)/10):\
160                                                 ((val)+5)/10),0,255))
161#define TEMP_FROM_REG(val) (((val)>0x80?(val)-0x100:(val))*10)
162
163#define TEMP_ADD_TO_REG(val)   (SENSORS_LIMIT(((((val) + 2) / 5) << 7),\
164                                              0,0xffff))
165#define TEMP_ADD_FROM_REG(val) (((val) >> 7) * 5)
166
167#define VID_FROM_REG(val) ((val)==0x1f?0:(val)>=0x10?510-(val)*10:\
168                           (val)>=0x06?0:205-(val)*5)
169#define ALARMS_FROM_REG(val) (val)
170#define PWM_FROM_REG(val) (val)
171#define PWM_TO_REG(val) (SENSORS_LIMIT((val),0,255))
172#define BEEPS_FROM_REG(val) (val)
173#define BEEPS_TO_REG(val) ((val) & 0xffff)
174
175#define BEEP_ENABLE_TO_REG(val) (val)
176#define BEEP_ENABLE_FROM_REG(val) ((val)?1:0)
177
178#define DIV_FROM_REG(val) (1 << (val))
179
180extern inline u8 DIV_TO_REG(long val, enum chips type)
181{
182  int i;
183  val = SENSORS_LIMIT(val,1,((type == w83781d) ? 8 : 128)) >> 1;
184  for(i = 0; i < 6; i++)
185  {
186    if(val == 0)
187      break;
188    val >>= 1;
189  }
190  return ((u8) i);
191}
192
193/* Initial limits */
194#define W83781D_INIT_IN_0 (vid==350?280:vid)
195#define W83781D_INIT_IN_1 (vid==350?280:vid)
196#define W83781D_INIT_IN_2 330
197#define W83781D_INIT_IN_3 (((500)   * 100)/168)
198#define W83781D_INIT_IN_4 (((1200)  * 10)/38)
199#define W83781D_INIT_IN_5 (((-1200) * -604)/2100)
200#define W83781D_INIT_IN_6 (((-500)  * -604)/909)
201#define W83781D_INIT_IN_7 (((500)   * 100)/168)
202#define W83781D_INIT_IN_8 300
203/* Initial limits for 782d/783s negative voltages */
204/* Note level shift. Change min/max below if you change these. */
205#define W83782D_INIT_IN_5 ((((-1200) + 1491) * 100)/514)
206#define W83782D_INIT_IN_6 ((( (-500)  + 771) * 100)/314)
207
208#define W83781D_INIT_IN_PERCENTAGE 10
209
210#define W83781D_INIT_IN_MIN_0 \
211        (W83781D_INIT_IN_0 - W83781D_INIT_IN_0 * W83781D_INIT_IN_PERCENTAGE \
212         / 100)
213#define W83781D_INIT_IN_MAX_0 \
214        (W83781D_INIT_IN_0 + W83781D_INIT_IN_0 * W83781D_INIT_IN_PERCENTAGE \
215         / 100)
216#define W83781D_INIT_IN_MIN_1 \
217        (W83781D_INIT_IN_1 - W83781D_INIT_IN_1 * W83781D_INIT_IN_PERCENTAGE \
218         / 100)
219#define W83781D_INIT_IN_MAX_1 \
220        (W83781D_INIT_IN_1 + W83781D_INIT_IN_1 * W83781D_INIT_IN_PERCENTAGE \
221         / 100)
222#define W83781D_INIT_IN_MIN_2 \
223        (W83781D_INIT_IN_2 - W83781D_INIT_IN_2 * W83781D_INIT_IN_PERCENTAGE \
224         / 100)
225#define W83781D_INIT_IN_MAX_2 \
226        (W83781D_INIT_IN_2 + W83781D_INIT_IN_2 * W83781D_INIT_IN_PERCENTAGE \
227         / 100)
228#define W83781D_INIT_IN_MIN_3 \
229        (W83781D_INIT_IN_3 - W83781D_INIT_IN_3 * W83781D_INIT_IN_PERCENTAGE \
230         / 100)
231#define W83781D_INIT_IN_MAX_3 \
232        (W83781D_INIT_IN_3 + W83781D_INIT_IN_3 * W83781D_INIT_IN_PERCENTAGE \
233         / 100)
234#define W83781D_INIT_IN_MIN_4 \
235        (W83781D_INIT_IN_4 - W83781D_INIT_IN_4 * W83781D_INIT_IN_PERCENTAGE \
236         / 100)
237#define W83781D_INIT_IN_MAX_4 \
238        (W83781D_INIT_IN_4 + W83781D_INIT_IN_4 * W83781D_INIT_IN_PERCENTAGE \
239         / 100)
240#define W83781D_INIT_IN_MIN_5 \
241        (W83781D_INIT_IN_5 - W83781D_INIT_IN_5 * W83781D_INIT_IN_PERCENTAGE \
242         / 100)
243#define W83781D_INIT_IN_MAX_5 \
244        (W83781D_INIT_IN_5 + W83781D_INIT_IN_5 * W83781D_INIT_IN_PERCENTAGE \
245         / 100)
246#define W83781D_INIT_IN_MIN_6 \
247        (W83781D_INIT_IN_6 - W83781D_INIT_IN_6 * W83781D_INIT_IN_PERCENTAGE \
248         / 100)
249#define W83781D_INIT_IN_MAX_6 \
250        (W83781D_INIT_IN_6 + W83781D_INIT_IN_6 * W83781D_INIT_IN_PERCENTAGE \
251         / 100)
252#define W83781D_INIT_IN_MIN_7 \
253        (W83781D_INIT_IN_7 - W83781D_INIT_IN_7 * W83781D_INIT_IN_PERCENTAGE \
254         / 100)
255#define W83781D_INIT_IN_MAX_7 \
256        (W83781D_INIT_IN_7 + W83781D_INIT_IN_7 * W83781D_INIT_IN_PERCENTAGE \
257         / 100)
258#define W83781D_INIT_IN_MIN_8 \
259        (W83781D_INIT_IN_8 - W83781D_INIT_IN_8 * W83781D_INIT_IN_PERCENTAGE \
260         / 100)
261#define W83781D_INIT_IN_MAX_8 \
262        (W83781D_INIT_IN_8 + W83781D_INIT_IN_8 * W83781D_INIT_IN_PERCENTAGE \
263         / 100)
264/* Initial limits for 782d/783s negative voltages */
265/* These aren't direct multiples because of level shift */
266/* Beware going negative - check */
267#define W83782D_INIT_IN_MIN_5_TMP \
268        (((-1200 * (100 + W83781D_INIT_IN_PERCENTAGE)) + (1491 * 100))/514)
269#define W83782D_INIT_IN_MIN_5 \
270        ((W83782D_INIT_IN_MIN_5_TMP > 0) ? W83782D_INIT_IN_MIN_5_TMP : 0)
271#define W83782D_INIT_IN_MAX_5 \
272        (((-1200 * (100 - W83781D_INIT_IN_PERCENTAGE)) + (1491 * 100))/514)
273#define W83782D_INIT_IN_MIN_6_TMP \
274        ((( -500 * (100 + W83781D_INIT_IN_PERCENTAGE)) +  (771 * 100))/314)
275#define W83782D_INIT_IN_MIN_6 \
276        ((W83782D_INIT_IN_MIN_6_TMP > 0) ? W83782D_INIT_IN_MIN_6_TMP : 0)
277#define W83782D_INIT_IN_MAX_6 \
278        ((( -500 * (100 - W83781D_INIT_IN_PERCENTAGE)) +  (771 * 100))/314)
279
280#define W83781D_INIT_FAN_MIN_1 3000
281#define W83781D_INIT_FAN_MIN_2 3000
282#define W83781D_INIT_FAN_MIN_3 3000
283
284#define W83781D_INIT_TEMP_OVER 600
285#define W83781D_INIT_TEMP_HYST 500
286#define W83781D_INIT_TEMP2_OVER 600
287#define W83781D_INIT_TEMP2_HYST 500
288#define W83781D_INIT_TEMP3_OVER 600
289#define W83781D_INIT_TEMP3_HYST 500
290
291#ifdef MODULE
292extern int init_module(void);
293extern int cleanup_module(void);
294#endif /* MODULE */
295
296/* There are some complications in a module like this. First off, W83781D chips
297   may be both present on the SMBus and the ISA bus, and we have to handle
298   those cases separately at some places. Second, there might be several
299   W83781D chips available (well, actually, that is probably never done; but
300   it is a clean illustration of how to handle a case like that). Finally,
301   a specific chip may be attached to *both* ISA and SMBus, and we would
302   not like to detect it double. Fortunately, in the case of the W83781D at
303   least, a register tells us what SMBus address we are on, so that helps
304   a bit - except if there could be more than one SMBus. Groan. No solution
305   for this yet. */
306
307/* This module may seem overly long and complicated. In fact, it is not so
308   bad. Quite a lot of bookkeeping is done. A real driver can often cut
309   some corners. */
310
311/* For each registered W83781D, we need to keep some data in memory. That
312   data is pointed to by w83781d_list[NR]->data. The structure itself is
313   dynamically allocated, at the same time when a new w83781d client is
314   allocated. */
315struct w83781d_data {
316         struct semaphore lock;
317         int sysctl_id;
318         enum chips type;
319
320         struct semaphore update_lock;
321         char valid;                 /* !=0 if following fields are valid */
322         unsigned long last_updated; /* In jiffies */
323
324         u8 in[9];                   /* Register value - 8 & 9 for 782D only */
325         u8 in_max[9];               /* Register value - 8 & 9 for 782D only */
326         u8 in_min[9];               /* Register value - 8 & 9 for 782D only */
327         u8 fan[3];                  /* Register value */
328         u8 fan_min[3];              /* Register value */
329         u8 temp;
330         u8 temp_over;               /* Register value */
331         u8 temp_hyst;               /* Register value */
332         u16 temp_add[2];            /* Register value */
333         u16 temp_add_over[2];       /* Register value */
334         u16 temp_add_hyst[2];       /* Register value */
335         u8 fan_div[3];              /* Register encoding, shifted right */
336         u8 vid;                     /* Register encoding, combined */
337         u32 alarms;                 /* Register encoding, combined */
338         u16 beeps;                  /* Register encoding, combined */
339         u8 beep_enable;             /* Boolean */
340         u8 pwm[4];                  /* Register value */                               
341         u16 sens[3];                /* 782D/783S only.
342                                        1 = pentium diode; 2 = 3904 diode;
343                                        3000-5000 = thermistor beta.
344                                        Default = 3435.
345                                        Other Betas unimplemented */
346#ifdef W83781D_RT
347         u8 rt[3][32];               /* Register value */
348#endif
349};
350
351
352static int w83781d_init(void);
353static int w83781d_cleanup(void);
354
355static int w83781d_attach_adapter(struct i2c_adapter *adapter);
356static int w83781d_detect(struct i2c_adapter *adapter, int address, int kind);
357static int w83781d_detach_client(struct i2c_client *client);
358static int w83781d_command(struct i2c_client *client, unsigned int cmd, 
359                        void *arg);
360static void w83781d_inc_use (struct i2c_client *client);
361static void w83781d_dec_use (struct i2c_client *client);
362
363static int w83781d_read_value(struct i2c_client *client, u16 register);
364static int w83781d_write_value(struct i2c_client *client, u16 register, 
365                               u16 value);
366static void w83781d_update_client(struct i2c_client *client);
367static void w83781d_init_client(struct i2c_client *client);
368
369
370static void w83781d_in(struct i2c_client *client, int operation, int ctl_name,
371                    int *nrels_mag, long *results);
372static void w83781d_fan(struct i2c_client *client, int operation, int ctl_name,
373                     int *nrels_mag, long *results);
374static void w83781d_temp(struct i2c_client *client, int operation, 
375                          int ctl_name, int *nrels_mag, long *results);
376static void w83781d_temp_add(struct i2c_client *client, int operation, 
377                          int ctl_name, int *nrels_mag, long *results);
378static void w83781d_vid(struct i2c_client *client, int operation, int ctl_name,
379                         int *nrels_mag, long *results);
380static void w83781d_alarms(struct i2c_client *client, int operation,
381                           int ctl_name, int *nrels_mag, long *results);
382static void w83781d_beep(struct i2c_client *client, int operation, int ctl_name,
383                      int *nrels_mag, long *results);
384static void w83781d_fan_div(struct i2c_client *client, int operation,
385                            int ctl_name, int *nrels_mag, long *results);
386static void w83781d_pwm(struct i2c_client *client, int operation,
387                        int ctl_name, int *nrels_mag, long *results);
388static void w83781d_sens(struct i2c_client *client, int operation,
389                        int ctl_name, int *nrels_mag, long *results);
390#ifdef W83781D_RT
391static void w83781d_rt(struct i2c_client *client, int operation,
392                        int ctl_name, int *nrels_mag, long *results);
393#endif
394
395/* I choose here for semi-static W83781D allocation. Complete dynamic
396   allocation could also be used; the code needed for this would probably
397   take more memory than the datastructure takes now. */
398#define MAX_W83781D_NR 8
399static struct i2c_client *w83781d_list[MAX_W83781D_NR];
400
401/* The driver. I choose to use type i2c_driver, as at is identical to both
402   smbus_driver and isa_driver, and clients could be of either kind */
403static struct i2c_driver w83781d_driver = {
404  /* name */            "W83781D sensor driver",
405  /* id */              I2C_DRIVERID_W83781D,
406  /* flags */           DF_NOTIFY,
407  /* attach_adapter */  &w83781d_attach_adapter,
408  /* detach_client */   &w83781d_detach_client,
409  /* command */         &w83781d_command,
410  /* inc_use */         &w83781d_inc_use,
411  /* dec_use */         &w83781d_dec_use
412};
413
414/* Used by w83781d_init/cleanup */
415static int w83781d_initialized = 0;
416
417/* The /proc/sys entries */
418/* These files are created for each detected W83781D. This is just a template;
419   though at first sight, you might think we could use a statically
420   allocated list, we need some way to get back to the parent - which
421   is done through one of the 'extra' fields which are initialized
422   when a new copy is allocated. */
423static ctl_table w83781d_dir_table_template[] = {
424  { W83781D_SYSCTL_IN0, "in0", NULL, 0, 0644, NULL, &sensors_proc_real,
425    &sensors_sysctl_real, NULL, &w83781d_in },
426  { W83781D_SYSCTL_IN1, "in1", NULL, 0, 0644, NULL, &sensors_proc_real,
427    &sensors_sysctl_real, NULL, &w83781d_in },
428  { W83781D_SYSCTL_IN2, "in2", NULL, 0, 0644, NULL, &sensors_proc_real,
429    &sensors_sysctl_real, NULL, &w83781d_in },
430  { W83781D_SYSCTL_IN3, "in3", NULL, 0, 0644, NULL, &sensors_proc_real,
431    &sensors_sysctl_real, NULL, &w83781d_in },
432  { W83781D_SYSCTL_IN4, "in4", NULL, 0, 0644, NULL, &sensors_proc_real,
433    &sensors_sysctl_real, NULL, &w83781d_in },
434  { W83781D_SYSCTL_IN5, "in5", NULL, 0, 0644, NULL, &sensors_proc_real,
435    &sensors_sysctl_real, NULL, &w83781d_in },
436  { W83781D_SYSCTL_IN6, "in6", NULL, 0, 0644, NULL, &sensors_proc_real,
437    &sensors_sysctl_real, NULL, &w83781d_in },
438  { W83781D_SYSCTL_FAN1, "fan1", NULL, 0, 0644, NULL, &sensors_proc_real,
439    &sensors_sysctl_real, NULL, &w83781d_fan },
440  { W83781D_SYSCTL_FAN2, "fan2", NULL, 0, 0644, NULL, &sensors_proc_real,
441    &sensors_sysctl_real, NULL, &w83781d_fan },
442  { W83781D_SYSCTL_FAN3, "fan3", NULL, 0, 0644, NULL, &sensors_proc_real,
443    &sensors_sysctl_real, NULL, &w83781d_fan },
444  { W83781D_SYSCTL_TEMP1, "temp1", NULL, 0, 0644, NULL, &sensors_proc_real,
445    &sensors_sysctl_real, NULL, &w83781d_temp },
446  { W83781D_SYSCTL_TEMP2, "temp2", NULL, 0, 0644, NULL, &sensors_proc_real,
447    &sensors_sysctl_real, NULL, &w83781d_temp_add },
448  { W83781D_SYSCTL_TEMP3, "temp3", NULL, 0, 0644, NULL, &sensors_proc_real,
449    &sensors_sysctl_real, NULL, &w83781d_temp_add },
450  { W83781D_SYSCTL_VID, "vid", NULL, 0, 0444, NULL, &sensors_proc_real,
451    &sensors_sysctl_real, NULL, &w83781d_vid },
452  { W83781D_SYSCTL_FAN_DIV, "fan_div", NULL, 0, 0644, NULL, &sensors_proc_real,
453    &sensors_sysctl_real, NULL, &w83781d_fan_div },
454  { W83781D_SYSCTL_ALARMS, "alarms", NULL, 0, 0444, NULL, &sensors_proc_real,
455    &sensors_sysctl_real, NULL, &w83781d_alarms },
456  { W83781D_SYSCTL_BEEP, "beep", NULL, 0, 0644, NULL, &sensors_proc_real,
457    &sensors_sysctl_real, NULL, &w83781d_beep },
458#ifdef W83781D_RT
459  { W83781D_SYSCTL_RT1, "rt1", NULL, 0, 0644, NULL, &sensors_proc_real,
460    &sensors_sysctl_real, NULL, &w83781d_rt },
461  { W83781D_SYSCTL_RT2, "rt2", NULL, 0, 0644, NULL, &sensors_proc_real,
462    &sensors_sysctl_real, NULL, &w83781d_rt },
463  { W83781D_SYSCTL_RT3, "rt3", NULL, 0, 0644, NULL, &sensors_proc_real,
464    &sensors_sysctl_real, NULL, &w83781d_rt },
465#endif
466  { 0 }
467};
468
469/* without pwm3-4 */
470static ctl_table w83782d_isa_dir_table_template[] = {
471  { W83781D_SYSCTL_IN0, "in0", NULL, 0, 0644, NULL, &sensors_proc_real,
472    &sensors_sysctl_real, NULL, &w83781d_in },
473  { W83781D_SYSCTL_IN1, "in1", NULL, 0, 0644, NULL, &sensors_proc_real,
474    &sensors_sysctl_real, NULL, &w83781d_in },
475  { W83781D_SYSCTL_IN2, "in2", NULL, 0, 0644, NULL, &sensors_proc_real,
476    &sensors_sysctl_real, NULL, &w83781d_in },
477  { W83781D_SYSCTL_IN3, "in3", NULL, 0, 0644, NULL, &sensors_proc_real,
478    &sensors_sysctl_real, NULL, &w83781d_in },
479  { W83781D_SYSCTL_IN4, "in4", NULL, 0, 0644, NULL, &sensors_proc_real,
480    &sensors_sysctl_real, NULL, &w83781d_in },
481  { W83781D_SYSCTL_IN5, "in5", NULL, 0, 0644, NULL, &sensors_proc_real,
482    &sensors_sysctl_real, NULL, &w83781d_in },
483  { W83781D_SYSCTL_IN6, "in6", NULL, 0, 0644, NULL, &sensors_proc_real,
484    &sensors_sysctl_real, NULL, &w83781d_in },
485  { W83781D_SYSCTL_IN7, "in7", NULL, 0, 0644, NULL, &sensors_proc_real,
486    &sensors_sysctl_real, NULL, &w83781d_in },
487  { W83781D_SYSCTL_IN8, "in8", NULL, 0, 0644, NULL, &sensors_proc_real,
488    &sensors_sysctl_real, NULL, &w83781d_in },
489  { W83781D_SYSCTL_FAN1, "fan1", NULL, 0, 0644, NULL, &sensors_proc_real,
490    &sensors_sysctl_real, NULL, &w83781d_fan },
491  { W83781D_SYSCTL_FAN2, "fan2", NULL, 0, 0644, NULL, &sensors_proc_real,
492    &sensors_sysctl_real, NULL, &w83781d_fan },
493  { W83781D_SYSCTL_FAN3, "fan3", NULL, 0, 0644, NULL, &sensors_proc_real,
494    &sensors_sysctl_real, NULL, &w83781d_fan },
495  { W83781D_SYSCTL_TEMP1, "temp1", NULL, 0, 0644, NULL, &sensors_proc_real,
496    &sensors_sysctl_real, NULL, &w83781d_temp },
497  { W83781D_SYSCTL_TEMP2, "temp2", NULL, 0, 0644, NULL, &sensors_proc_real,
498    &sensors_sysctl_real, NULL, &w83781d_temp_add },
499  { W83781D_SYSCTL_TEMP3, "temp3", NULL, 0, 0644, NULL, &sensors_proc_real,
500    &sensors_sysctl_real, NULL, &w83781d_temp_add },
501  { W83781D_SYSCTL_VID, "vid", NULL, 0, 0444, NULL, &sensors_proc_real,
502    &sensors_sysctl_real, NULL, &w83781d_vid },
503  { W83781D_SYSCTL_FAN_DIV, "fan_div", NULL, 0, 0644, NULL, &sensors_proc_real,
504    &sensors_sysctl_real, NULL, &w83781d_fan_div },
505  { W83781D_SYSCTL_ALARMS, "alarms", NULL, 0, 0444, NULL, &sensors_proc_real,
506    &sensors_sysctl_real, NULL, &w83781d_alarms },
507  { W83781D_SYSCTL_BEEP, "beep", NULL, 0, 0644, NULL, &sensors_proc_real,
508    &sensors_sysctl_real, NULL, &w83781d_beep },
509  { W83781D_SYSCTL_PWM1, "pwm1", NULL, 0, 0644, NULL, &sensors_proc_real,
510    &sensors_sysctl_real, NULL, &w83781d_pwm },
511  { W83781D_SYSCTL_PWM2, "pwm2", NULL, 0, 0644, NULL, &sensors_proc_real,
512    &sensors_sysctl_real, NULL, &w83781d_pwm },
513  { W83781D_SYSCTL_SENS1, "sensor1", NULL, 0, 0644, NULL, &sensors_proc_real,
514    &sensors_sysctl_real, NULL, &w83781d_sens },
515  { W83781D_SYSCTL_SENS2, "sensor2", NULL, 0, 0644, NULL, &sensors_proc_real,
516    &sensors_sysctl_real, NULL, &w83781d_sens },
517  { W83781D_SYSCTL_SENS3, "sensor3", NULL, 0, 0644, NULL, &sensors_proc_real,
518    &sensors_sysctl_real, NULL, &w83781d_sens },
519  { 0 }
520};
521
522/* with pwm3-4 */
523static ctl_table w83782d_i2c_dir_table_template[] = {
524  { W83781D_SYSCTL_IN0, "in0", NULL, 0, 0644, NULL, &sensors_proc_real,
525    &sensors_sysctl_real, NULL, &w83781d_in },
526  { W83781D_SYSCTL_IN1, "in1", NULL, 0, 0644, NULL, &sensors_proc_real,
527    &sensors_sysctl_real, NULL, &w83781d_in },
528  { W83781D_SYSCTL_IN2, "in2", NULL, 0, 0644, NULL, &sensors_proc_real,
529    &sensors_sysctl_real, NULL, &w83781d_in },
530  { W83781D_SYSCTL_IN3, "in3", NULL, 0, 0644, NULL, &sensors_proc_real,
531    &sensors_sysctl_real, NULL, &w83781d_in },
532  { W83781D_SYSCTL_IN4, "in4", NULL, 0, 0644, NULL, &sensors_proc_real,
533    &sensors_sysctl_real, NULL, &w83781d_in },
534  { W83781D_SYSCTL_IN5, "in5", NULL, 0, 0644, NULL, &sensors_proc_real,
535    &sensors_sysctl_real, NULL, &w83781d_in },
536  { W83781D_SYSCTL_IN6, "in6", NULL, 0, 0644, NULL, &sensors_proc_real,
537    &sensors_sysctl_real, NULL, &w83781d_in },
538  { W83781D_SYSCTL_IN7, "in7", NULL, 0, 0644, NULL, &sensors_proc_real,
539    &sensors_sysctl_real, NULL, &w83781d_in },
540  { W83781D_SYSCTL_IN8, "in8", NULL, 0, 0644, NULL, &sensors_proc_real,
541    &sensors_sysctl_real, NULL, &w83781d_in },
542  { W83781D_SYSCTL_FAN1, "fan1", NULL, 0, 0644, NULL, &sensors_proc_real,
543    &sensors_sysctl_real, NULL, &w83781d_fan },
544  { W83781D_SYSCTL_FAN2, "fan2", NULL, 0, 0644, NULL, &sensors_proc_real,
545    &sensors_sysctl_real, NULL, &w83781d_fan },
546  { W83781D_SYSCTL_FAN3, "fan3", NULL, 0, 0644, NULL, &sensors_proc_real,
547    &sensors_sysctl_real, NULL, &w83781d_fan },
548  { W83781D_SYSCTL_TEMP1, "temp1", NULL, 0, 0644, NULL, &sensors_proc_real,
549    &sensors_sysctl_real, NULL, &w83781d_temp },
550  { W83781D_SYSCTL_TEMP2, "temp2", NULL, 0, 0644, NULL, &sensors_proc_real,
551    &sensors_sysctl_real, NULL, &w83781d_temp_add },
552  { W83781D_SYSCTL_TEMP3, "temp3", NULL, 0, 0644, NULL, &sensors_proc_real,
553    &sensors_sysctl_real, NULL, &w83781d_temp_add },
554  { W83781D_SYSCTL_VID, "vid", NULL, 0, 0444, NULL, &sensors_proc_real,
555    &sensors_sysctl_real, NULL, &w83781d_vid },
556  { W83781D_SYSCTL_FAN_DIV, "fan_div", NULL, 0, 0644, NULL, &sensors_proc_real,
557    &sensors_sysctl_real, NULL, &w83781d_fan_div },
558  { W83781D_SYSCTL_ALARMS, "alarms", NULL, 0, 0444, NULL, &sensors_proc_real,
559    &sensors_sysctl_real, NULL, &w83781d_alarms },
560  { W83781D_SYSCTL_BEEP, "beep", NULL, 0, 0644, NULL, &sensors_proc_real,
561    &sensors_sysctl_real, NULL, &w83781d_beep },
562  { W83781D_SYSCTL_PWM1, "pwm1", NULL, 0, 0644, NULL, &sensors_proc_real,
563    &sensors_sysctl_real, NULL, &w83781d_pwm },
564  { W83781D_SYSCTL_PWM2, "pwm2", NULL, 0, 0644, NULL, &sensors_proc_real,
565    &sensors_sysctl_real, NULL, &w83781d_pwm },
566  { W83781D_SYSCTL_PWM3, "pwm3", NULL, 0, 0644, NULL, &sensors_proc_real,
567    &sensors_sysctl_real, NULL, &w83781d_pwm },
568  { W83781D_SYSCTL_PWM4, "pwm4", NULL, 0, 0644, NULL, &sensors_proc_real,
569    &sensors_sysctl_real, NULL, &w83781d_pwm },
570  { W83781D_SYSCTL_SENS1, "sensor1", NULL, 0, 0644, NULL, &sensors_proc_real,
571    &sensors_sysctl_real, NULL, &w83781d_sens },
572  { W83781D_SYSCTL_SENS2, "sensor2", NULL, 0, 0644, NULL, &sensors_proc_real,
573    &sensors_sysctl_real, NULL, &w83781d_sens },
574  { W83781D_SYSCTL_SENS3, "sensor3", NULL, 0, 0644, NULL, &sensors_proc_real,
575    &sensors_sysctl_real, NULL, &w83781d_sens },
576  { 0 }
577};
578
579static ctl_table w83783s_dir_table_template[] = {
580  { W83781D_SYSCTL_IN0, "in0", NULL, 0, 0644, NULL, &sensors_proc_real,
581    &sensors_sysctl_real, NULL, &w83781d_in },
582  /* no in1 to maintain compatibility with 781d and 782d. */
583  { W83781D_SYSCTL_IN2, "in2", NULL, 0, 0644, NULL, &sensors_proc_real,
584    &sensors_sysctl_real, NULL, &w83781d_in },
585  { W83781D_SYSCTL_IN3, "in3", NULL, 0, 0644, NULL, &sensors_proc_real,
586    &sensors_sysctl_real, NULL, &w83781d_in },
587  { W83781D_SYSCTL_IN4, "in4", NULL, 0, 0644, NULL, &sensors_proc_real,
588    &sensors_sysctl_real, NULL, &w83781d_in },
589  { W83781D_SYSCTL_IN5, "in5", NULL, 0, 0644, NULL, &sensors_proc_real,
590    &sensors_sysctl_real, NULL, &w83781d_in },
591  { W83781D_SYSCTL_IN6, "in6", NULL, 0, 0644, NULL, &sensors_proc_real,
592    &sensors_sysctl_real, NULL, &w83781d_in },
593  { W83781D_SYSCTL_FAN1, "fan1", NULL, 0, 0644, NULL, &sensors_proc_real,
594    &sensors_sysctl_real, NULL, &w83781d_fan },
595  { W83781D_SYSCTL_FAN2, "fan2", NULL, 0, 0644, NULL, &sensors_proc_real,
596    &sensors_sysctl_real, NULL, &w83781d_fan },
597  { W83781D_SYSCTL_FAN3, "fan3", NULL, 0, 0644, NULL, &sensors_proc_real,
598    &sensors_sysctl_real, NULL, &w83781d_fan },
599  { W83781D_SYSCTL_TEMP1, "temp1", NULL, 0, 0644, NULL, &sensors_proc_real,
600    &sensors_sysctl_real, NULL, &w83781d_temp },
601  { W83781D_SYSCTL_TEMP2, "temp2", NULL, 0, 0644, NULL, &sensors_proc_real,
602    &sensors_sysctl_real, NULL, &w83781d_temp_add },
603  { W83781D_SYSCTL_VID, "vid", NULL, 0, 0444, NULL, &sensors_proc_real,
604    &sensors_sysctl_real, NULL, &w83781d_vid },
605  { W83781D_SYSCTL_FAN_DIV, "fan_div", NULL, 0, 0644, NULL, &sensors_proc_real,
606    &sensors_sysctl_real, NULL, &w83781d_fan_div },
607  { W83781D_SYSCTL_ALARMS, "alarms", NULL, 0, 0444, NULL, &sensors_proc_real,
608    &sensors_sysctl_real, NULL, &w83781d_alarms },
609  { W83781D_SYSCTL_BEEP, "beep", NULL, 0, 0644, NULL, &sensors_proc_real,
610    &sensors_sysctl_real, NULL, &w83781d_beep },
611  { W83781D_SYSCTL_PWM1, "pwm1", NULL, 0, 0644, NULL, &sensors_proc_real,
612    &sensors_sysctl_real, NULL, &w83781d_pwm },
613  { W83781D_SYSCTL_PWM2, "pwm2", NULL, 0, 0644, NULL, &sensors_proc_real,
614    &sensors_sysctl_real, NULL, &w83781d_pwm },
615  { W83781D_SYSCTL_SENS1, "sensor1", NULL, 0, 0644, NULL, &sensors_proc_real,
616    &sensors_sysctl_real, NULL, &w83781d_sens },
617  { W83781D_SYSCTL_SENS2, "sensor2", NULL, 0, 0644, NULL, &sensors_proc_real,
618    &sensors_sysctl_real, NULL, &w83781d_sens },
619  { 0 }
620};
621
622
623/* This function is called when:
624     * w83781d_driver is inserted (when this module is loaded), for each
625       available adapter
626     * when a new adapter is inserted (and w83781d_driver is still present) */
627int w83781d_attach_adapter(struct i2c_adapter *adapter)
628{
629  return sensors_detect(adapter,&addr_data,w83781d_detect);
630}
631
632int w83781d_detect(struct i2c_adapter *adapter, int address, int kind)
633{
634  int i,val1,val2;
635  struct i2c_client *new_client;
636  struct w83781d_data *data;
637  int err=0;
638  const char *type_name = "";
639  const char *client_name = "";
640  int is_isa = i2c_is_isa_adapter(adapter);
641
642  /* We need address registration for the I2C bus too. That is not yet
643     implemented. */
644  if (is_isa) {
645    if (check_region(address,W83781D_EXTENT))
646      goto ERROR0;
647  }
648
649  /* Probe whether there is anything available on this address. Already
650     done for SMBus clients */
651  if (kind < 0) {
652    if (is_isa) {
653
654#define REALLY_SLOW_IO
655      /* We need the timeouts for at least some LM78-like chips. But only
656         if we read 'undefined' registers. */
657      i = inb_p(address + 1);
658      if (inb_p(address + 2) != i)
659        goto ERROR0;
660      if (inb_p(address + 3) != i)
661        goto ERROR0;
662      if (inb_p(address + 7) != i)
663        goto ERROR0;
664#undef REALLY_SLOW_IO
665
666      /* Let's just hope nothing breaks here */
667      i = inb_p(address + 5) & 0x7f;
668      outb_p(~i & 0x7f,address+5);
669      if ((inb_p(address + 5) & 0x7f) != (~i & 0x7f)) {
670        outb_p(i,address+5);
671        return 0;
672      }
673    }
674  }
675
676  /* OK. For now, we presume we have a valid client. We now create the
677     client structure, even though we cannot fill it completely yet.
678     But it allows us to access w83781d_{read,write}_value. */
679
680  if (! (new_client = kmalloc((is_isa?sizeof(struct isa_client):
681                                      sizeof(struct i2c_client)) +
682                              sizeof(struct w83781d_data),
683                              GFP_KERNEL))) {
684    err = -ENOMEM;
685    goto ERROR0;
686  }
687
688  if (is_isa) {
689    data = (struct w83781d_data *) (((struct isa_client *) new_client) + 1);
690    new_client->addr = 0;
691    ((struct isa_client *) new_client)->isa_addr = address;
692  } else {
693    data = (struct w83781d_data *) (((struct i2c_client *) new_client) + 1);
694    new_client->addr = address;
695  }
696  data->lock = MUTEX;
697  new_client->data = data;
698  new_client->adapter = adapter;
699  new_client->driver = &w83781d_driver;
700
701  /* Now, we do the remaining detection. */
702
703  /* The w8378?d may be stuck in some other bank than bank 0. This may
704     make reading other information impossible. Specify a force=... or
705     force_*=... parameter, and the Winbond will be reset to the right
706     bank. */
707  if (kind < 0) {
708    if (w83781d_read_value(new_client,W83781D_REG_CONFIG) & 0x80)
709      goto ERROR1;
710    if (!is_isa && 
711        (w83781d_read_value(new_client,W83781D_REG_I2C_ADDR) != address))
712      goto ERROR1;
713    val1 = w83781d_read_value(new_client,W83781D_REG_BANK);
714    val2 = w83781d_read_value(new_client,W83781D_REG_CHIPMAN);
715    if (!(val1 & 0x07) &&
716        ((!(val1 & 0x80) && (val2 != 0xa3)) ||
717         ((val1 & 0x80) && (val2 != 0x5c))))
718      goto ERROR1;
719  }
720
721  /* We have either had a force parameter, or we have already detected the
722     Winbond. Put it now into bank 0 */
723  w83781d_write_value(new_client,W83781D_REG_BANK,
724                      w83781d_read_value(new_client,W83781D_REG_BANK) & 0xf8);
725
726  /* Determine the chip type. */
727  if (kind <= 0) {
728    /* mask off lower bit, not reliable */
729    val1 = w83781d_read_value(new_client,W83781D_REG_WCHIPID) & 0xfe;
730    if (val1 == 0x10)
731      kind = w83781d;
732    else if (val1 == 0x30)
733      kind = w83782d;
734    else if (val1 == 0x40)
735      kind = w83783s;
736    else {
737      if (kind == 0) 
738        printk("w83781d.o: Ignoring 'force' parameter for unknown chip at"
739               "adapter %d, address 0x%02x\n",i2c_adapter_id(adapter),address);
740      goto ERROR1;
741    }
742  }
743
744  if (kind == w83781d) {
745    type_name = "w83781d";
746    client_name = "W83781D chip";
747  } else if (kind == w83782d) {
748    type_name = "w83782d";
749    client_name = "W83782D chip";
750  } else if (kind == w83783s) {
751    type_name = "w83783s";
752    client_name = "W83783S chip";
753  } else {
754#ifdef DEBUG
755    printk("w83781d.o: Internal error: unknown kind (%d)?!?",kind);
756#endif
757    goto ERROR1;
758  }
759
760  /* Reserve the ISA region */
761  if (is_isa)
762    request_region(address, W83781D_EXTENT, type_name);
763
764  /* Fill in the remaining client fields and put it into the global list */
765  strcpy(new_client->name,client_name);
766  data->type = kind;
767
768  for(i = 0; i < MAX_W83781D_NR; i++)
769    if (! w83781d_list[i])
770      break;
771  if (i == MAX_W83781D_NR) {
772    printk("w83781d.o: No empty slots left, recompile and heighten "
773           "MAX_W83781D_NR!\n");
774    err = -ENOMEM;
775    goto ERROR2;
776  }
777  w83781d_list[i] = new_client;
778  new_client->id = i;
779  data->valid = 0;
780  data->update_lock = MUTEX;
781
782  /* Tell the I2C layer a new client has arrived */
783  if ((err = i2c_attach_client(new_client)))
784    goto ERROR3;
785
786  /* Register a new directory entry with module sensors */
787  if ((i = sensors_register_entry((struct i2c_client *) new_client,
788                                  type_name,
789                                  kind == w83781d?w83781d_dir_table_template:
790                                  kind == w83783s?w83783s_dir_table_template:
791                                  is_isa?w83782d_i2c_dir_table_template:
792                                         w83782d_isa_dir_table_template)) < 0) {
793    err = i;
794    goto ERROR4;
795  }
796  data->sysctl_id = i;
797
798  /* Initialize the Winbond chip */
799  w83781d_init_client(new_client);
800  return 0;
801
802/* OK, this is not exactly good programming practice, usually. But it is
803   very code-efficient in this case. */
804
805ERROR4:
806  i2c_detach_client(new_client);
807ERROR3:
808  for (i = 0; i < MAX_W83781D_NR; i++)
809    if (new_client == w83781d_list[i])
810      w83781d_list[i] = NULL;
811ERROR2:
812  if (is_isa)
813    release_region(address,W83781D_EXTENT);
814ERROR1:
815  kfree(new_client);
816ERROR0:
817  return err;
818}
819
820int w83781d_detach_client(struct i2c_client *client)
821{
822  int err,i;
823
824  sensors_deregister_entry(((struct w83781d_data *)(client->data))->sysctl_id);
825
826  if ((err = i2c_detach_client(client))) {
827    printk("w83781d.o: Client deregistration failed, client not detached.\n");
828    return err;
829  }
830
831  for (i = 0; i < MAX_W83781D_NR; i++)
832    if (client == w83781d_list[i])
833      break;
834  if (i == MAX_W83781D_NR) {
835    printk("w83781d.o: Client to detach not found.\n");
836    return -ENOENT;
837  }
838  w83781d_list[i] = NULL;
839
840  if i2c_is_isa_client(client)
841    release_region(((struct isa_client *)client)->isa_addr,W83781D_EXTENT);
842  kfree(client);
843
844  return 0;
845}
846
847/* No commands defined yet */
848int w83781d_command(struct i2c_client *client, unsigned int cmd, void *arg)
849{
850  return 0;
851}
852
853void w83781d_inc_use (struct i2c_client *client)
854{
855#ifdef MODULE
856  MOD_INC_USE_COUNT;
857#endif
858}
859
860void w83781d_dec_use (struct i2c_client *client)
861{
862#ifdef MODULE
863  MOD_DEC_USE_COUNT;
864#endif
865}
866 
867/* The SMBus locks itself, usually, but nothing may access the Winbond between
868   bank switches. ISA access must always be locked explicitely!
869   We ignore the W83781D BUSY flag at this moment - it could lead to deadlocks,
870   would slow down the W83781D access and should not be necessary.
871   There are some ugly typecasts here, but the good new is - they should
872   nowhere else be necessary! */
873int w83781d_read_value(struct i2c_client *client, u16 reg)
874{
875  int res,word_sized;
876
877  word_sized = (((reg & 0xff00) == 0x100) || ((reg & 0xff00) == 0x200)) &&
878                                 (((reg & 0x00ff) == 0x50) || 
879                                  ((reg & 0x00ff) == 0x53) || 
880                                  ((reg & 0x00ff) == 0x55));
881  down(& (((struct w83781d_data *) (client->data)) -> lock));
882  if (i2c_is_isa_client(client)) {
883    if (reg & 0xff00) {
884      outb_p(W83781D_REG_BANK,(((struct isa_client *) client)->isa_addr) +
885                              W83781D_ADDR_REG_OFFSET);
886      outb_p(reg >> 8,(((struct isa_client *) client)->isa_addr) +
887                      W83781D_DATA_REG_OFFSET);
888    }
889    outb_p(reg & 0xff,(((struct isa_client *) client)->isa_addr) +
890                      W83781D_ADDR_REG_OFFSET);
891    res = inb_p((((struct isa_client *) client)->isa_addr) +
892                W83781D_DATA_REG_OFFSET);
893    if (word_sized) {
894      outb_p((reg & 0xff)+1,(((struct isa_client *) client)->isa_addr) +
895                        W83781D_ADDR_REG_OFFSET);
896      res = (res << 8) + inb_p((((struct isa_client *) client)->isa_addr) +
897                         W83781D_DATA_REG_OFFSET);
898    }
899    if (reg & 0xff00) {
900      outb_p(W83781D_REG_BANK,(((struct isa_client *) client)->isa_addr) +
901                              W83781D_ADDR_REG_OFFSET);
902      outb_p(0,(((struct isa_client *) client)->isa_addr) +
903               W83781D_DATA_REG_OFFSET);
904    }
905  } else {
906    if (reg & 0xff00)
907      smbus_write_byte_data(client->adapter,client->addr,W83781D_REG_BANK,
908                            reg >> 8);
909    res = smbus_read_byte_data(client->adapter,client->addr, reg);
910    if (word_sized)
911      res = (res << 8) + smbus_read_byte_data(client->adapter,client->addr, 
912                                              reg);
913    if (reg & 0xff00)
914      smbus_write_byte_data(client->adapter,client->addr,W83781D_REG_BANK,0);
915  }
916  up( & (((struct w83781d_data *) (client->data)) -> lock));
917  return res;
918}
919
920/* The SMBus locks itself, usually, but nothing may access the Winbond between
921   bank switches. ISA access must always be locked explicitely!
922   We ignore the W83781D BUSY flag at this moment - it could lead to deadlocks,
923   would slow down the W83781D access and should not be necessary.
924   There are some ugly typecasts here, but the good new is - they should
925   nowhere else be necessary! */
926int w83781d_write_value(struct i2c_client *client, u16 reg, u16 value)
927{
928  int word_sized;
929
930  word_sized = (((reg & 0xff00) == 0x100) || ((reg & 0xff00) == 0x200)) &&
931                                 (((reg & 0x00ff) == 0x50) || 
932                                  ((reg & 0x00ff) == 0x53) || 
933                                  ((reg & 0x00ff) == 0x55));
934  down( & (((struct w83781d_data *) (client->data)) -> lock));
935  if (i2c_is_isa_client(client)) {
936    if (reg & 0xff00) {
937      outb_p(W83781D_REG_BANK,(((struct isa_client *) client)->isa_addr) +
938                              W83781D_ADDR_REG_OFFSET);
939      outb_p(reg >> 8,(((struct isa_client *) client)->isa_addr) +
940                      W83781D_DATA_REG_OFFSET);
941    }
942    outb_p(reg & 0xff,(((struct isa_client *) client)->isa_addr) +
943                      W83781D_ADDR_REG_OFFSET);
944    if (word_sized) {
945      outb_p(value >> 8,(((struct isa_client *) client)->isa_addr) +
946                        W83781D_DATA_REG_OFFSET);
947      outb_p((reg & 0xff)+1,(((struct isa_client *) client)->isa_addr) +
948                        W83781D_ADDR_REG_OFFSET);
949    }
950    outb_p(value &0xff,(((struct isa_client *) client)->isa_addr) +
951                       W83781D_DATA_REG_OFFSET);
952    if (reg & 0xff00) {
953      outb_p(W83781D_REG_BANK,(((struct isa_client *) client)->isa_addr) +
954                              W83781D_ADDR_REG_OFFSET);
955      outb_p(0,(((struct isa_client *) client)->isa_addr) +
956               W83781D_DATA_REG_OFFSET);
957    }
958  } else {
959    if (reg & 0xff00)
960      smbus_write_byte_data(client->adapter,client->addr,W83781D_REG_BANK,
961                            reg >> 8);
962    if (word_sized) {
963       smbus_write_byte_data(client->adapter,client->addr, reg, value >> 8);
964       smbus_write_byte_data(client->adapter,client->addr, reg+1, value &0xff);
965    } else
966      smbus_write_byte_data(client->adapter,client->addr, reg, value &0xff);
967    if (reg & 0xff00)
968      smbus_write_byte_data(client->adapter,client->addr,W83781D_REG_BANK,0);
969  }
970  up( & (((struct w83781d_data *) (client->data)) -> lock));
971  return 0;
972}
973
974/* Called when we have found a new W83781D. It should set limits, etc. */
975void w83781d_init_client(struct i2c_client *client)
976{
977  struct w83781d_data *data = client->data;
978  int vid,i;
979  int type = data->type;
980  u8 tmp;
981
982  /* Reset all except Watchdog values and last conversion values
983     This sets fan-divs to 2, among others */
984  w83781d_write_value(client,W83781D_REG_CONFIG,0x80);
985
986  vid = w83781d_read_value(client,W83781D_REG_VID_FANDIV) & 0x0f;
987  vid |= (w83781d_read_value(client,W83781D_REG_CHIPID) & 0x01) << 4;
988  vid = VID_FROM_REG(vid);
989
990  if (type != w83781d) {
991    tmp = w83781d_read_value(client,W83781D_REG_SCFG1);
992    for (i = 1; i <= 3; i++) {
993      if(!(tmp & BIT_SCFG1[i-1])) {
994        data->sens[i-1] = W83781D_DEFAULT_BETA;
995      } else {
996        if(w83781d_read_value(client,W83781D_REG_TEMP) & BIT_SCFG2[i-1])
997          data->sens[i-1] = 1;
998        else
999          data->sens[i-1] = 2;
1000      }
1001      if((type == w83783s) && (i == 2))
1002        break;
1003    }
1004  }
1005
1006#ifdef W83781D_RT
1007/*
1008   Fill up the RT Tables.
1009   We assume that they are 32 bytes long, in order for temp 1-3.
1010   Data sheet documentation is sparse.
1011   We also assume that it is only for the 781D although I suspect
1012   that the 782D/783D support it as well....
1013*/
1014
1015  if(type == w83781d) {
1016    u16 k = 0;
1017/*
1018    Auto-indexing doesn't seem to work...
1019    w83781d_write_value(client,W83781D_REG_RT_IDX,0);
1020*/
1021    for (i = 0; i < 3; i++) {
1022      int j;
1023      for (j = 0; j < 32; j++) {
1024        w83781d_write_value(client,W83781D_REG_RT_IDX,k++);
1025        data->rt[i][j] = w83781d_read_value(client,W83781D_REG_RT_VAL);
1026      }
1027    }
1028  }
1029#endif
1030
1031  w83781d_write_value(client,W83781D_REG_IN_MIN(0),
1032                      IN_TO_REG(W83781D_INIT_IN_MIN_0));
1033  w83781d_write_value(client,W83781D_REG_IN_MAX(0),
1034                      IN_TO_REG(W83781D_INIT_IN_MAX_0));
1035  if(type != w83783s) {
1036    w83781d_write_value(client,W83781D_REG_IN_MIN(1),
1037                        IN_TO_REG(W83781D_INIT_IN_MIN_1));
1038    w83781d_write_value(client,W83781D_REG_IN_MAX(1),
1039                        IN_TO_REG(W83781D_INIT_IN_MAX_1));
1040  }
1041
1042  w83781d_write_value(client,W83781D_REG_IN_MIN(2),
1043                      IN_TO_REG(W83781D_INIT_IN_MIN_2));
1044  w83781d_write_value(client,W83781D_REG_IN_MAX(2),
1045                      IN_TO_REG(W83781D_INIT_IN_MAX_2));
1046  w83781d_write_value(client,W83781D_REG_IN_MIN(3),
1047                      IN_TO_REG(W83781D_INIT_IN_MIN_3));
1048  w83781d_write_value(client,W83781D_REG_IN_MAX(3),
1049                      IN_TO_REG(W83781D_INIT_IN_MAX_3));
1050  w83781d_write_value(client,W83781D_REG_IN_MIN(4),
1051                      IN_TO_REG(W83781D_INIT_IN_MIN_4));
1052  w83781d_write_value(client,W83781D_REG_IN_MAX(4),
1053                      IN_TO_REG(W83781D_INIT_IN_MAX_4));
1054  if (type == w83781d) {
1055    w83781d_write_value(client,W83781D_REG_IN_MIN(5),
1056                        IN_TO_REG(W83781D_INIT_IN_MIN_5));
1057    w83781d_write_value(client,W83781D_REG_IN_MAX(5),
1058                        IN_TO_REG(W83781D_INIT_IN_MAX_5));
1059  } else {
1060    w83781d_write_value(client,W83781D_REG_IN_MIN(5),
1061                        IN_TO_REG(W83782D_INIT_IN_MIN_5));
1062    w83781d_write_value(client,W83781D_REG_IN_MAX(5),
1063                        IN_TO_REG(W83782D_INIT_IN_MAX_5));
1064  }
1065  if (type == w83781d) {
1066    w83781d_write_value(client,W83781D_REG_IN_MIN(6),
1067                        IN_TO_REG(W83781D_INIT_IN_MIN_6));
1068    w83781d_write_value(client,W83781D_REG_IN_MAX(6),
1069                        IN_TO_REG(W83781D_INIT_IN_MAX_6));
1070  } else {
1071    w83781d_write_value(client,W83781D_REG_IN_MIN(6),
1072                        IN_TO_REG(W83782D_INIT_IN_MIN_6));
1073    w83781d_write_value(client,W83781D_REG_IN_MAX(6),
1074                        IN_TO_REG(W83782D_INIT_IN_MAX_6));
1075  }
1076  if (type == w83782d) {
1077    w83781d_write_value(client,W83781D_REG_IN_MIN(7),
1078                        IN_TO_REG(W83781D_INIT_IN_MIN_7));
1079    w83781d_write_value(client,W83781D_REG_IN_MAX(7),
1080                        IN_TO_REG(W83781D_INIT_IN_MAX_7));
1081    w83781d_write_value(client,W83781D_REG_IN_MIN(8),
1082                        IN_TO_REG(W83781D_INIT_IN_MIN_8));
1083    w83781d_write_value(client,W83781D_REG_IN_MAX(8),
1084                        IN_TO_REG(W83781D_INIT_IN_MAX_8));
1085  }
1086  w83781d_write_value(client,W83781D_REG_FAN_MIN(1),
1087                      FAN_TO_REG(W83781D_INIT_FAN_MIN_1,2));
1088  w83781d_write_value(client,W83781D_REG_FAN_MIN(2),
1089                      FAN_TO_REG(W83781D_INIT_FAN_MIN_2,2));
1090  w83781d_write_value(client,W83781D_REG_FAN_MIN(3),
1091                      FAN_TO_REG(W83781D_INIT_FAN_MIN_3,2));
1092
1093  w83781d_write_value(client,W83781D_REG_TEMP_OVER,
1094                      TEMP_TO_REG(W83781D_INIT_TEMP_OVER));
1095  w83781d_write_value(client,W83781D_REG_TEMP_HYST,
1096                      TEMP_TO_REG(W83781D_INIT_TEMP_HYST));
1097
1098  w83781d_write_value(client,W83781D_REG_TEMP2_OVER,
1099                      TEMP_ADD_TO_REG(W83781D_INIT_TEMP2_OVER));
1100  w83781d_write_value(client,W83781D_REG_TEMP2_HYST,
1101                      TEMP_ADD_TO_REG(W83781D_INIT_TEMP2_HYST));
1102  w83781d_write_value(client,W83781D_REG_TEMP2_CONFIG,0x00);
1103
1104  if (type != w83783s) {
1105    w83781d_write_value(client,W83781D_REG_TEMP3_OVER,
1106                        TEMP_ADD_TO_REG(W83781D_INIT_TEMP3_OVER));
1107    w83781d_write_value(client,W83781D_REG_TEMP3_HYST,
1108                        TEMP_ADD_TO_REG(W83781D_INIT_TEMP3_HYST));
1109    w83781d_write_value(client,W83781D_REG_TEMP3_CONFIG,0x00);
1110  }
1111
1112  /* Start monitoring */
1113  w83781d_write_value(client,W83781D_REG_CONFIG,
1114                   (w83781d_read_value(client,
1115                                       W83781D_REG_CONFIG) & 0xf7) | 0x01);
1116}
1117
1118void w83781d_update_client(struct i2c_client *client)
1119{
1120  struct w83781d_data *data = client->data;
1121  int i;
1122
1123  down(&data->update_lock);
1124
1125  if ((jiffies - data->last_updated > HZ+HZ/2 ) ||
1126      (jiffies < data->last_updated) || ! data->valid) {
1127
1128#ifdef DEBUG
1129    printk("Starting w83781d update\n");
1130#endif
1131    for (i = 0; i <= 8; i++) {
1132      if((data->type == w83783s)  &&  (i == 1))
1133        continue; /* 783S has no in1 */
1134      data->in[i]     = w83781d_read_value(client,W83781D_REG_IN(i));
1135      data->in_min[i] = w83781d_read_value(client,W83781D_REG_IN_MIN(i));
1136      data->in_max[i] = w83781d_read_value(client,W83781D_REG_IN_MAX(i));
1137      if((data->type != w83782d)  &&  (i == 6))
1138        break;
1139    }
1140    for (i = 1; i <= 3; i++) {
1141      data->fan[i-1] = w83781d_read_value(client,W83781D_REG_FAN(i));
1142      data->fan_min[i-1] = w83781d_read_value(client,W83781D_REG_FAN_MIN(i));
1143    }
1144    if(data->type != w83781d) {
1145      for (i = 1; i <= 4; i++) {
1146        data->pwm[i-1] = w83781d_read_value(client,W83781D_REG_PWM(i));
1147        if(((data->type == w83783s) ||
1148           ((data->type == w83782d) && i2c_is_isa_client(client)))
1149          &&  i == 2)
1150          break;
1151      }
1152    }
1153
1154    data->temp = w83781d_read_value(client,W83781D_REG_TEMP);
1155    data->temp_over = w83781d_read_value(client,W83781D_REG_TEMP_OVER);
1156    data->temp_hyst = w83781d_read_value(client,W83781D_REG_TEMP_HYST);
1157    data->temp_add[0] = w83781d_read_value(client,W83781D_REG_TEMP2);
1158    data->temp_add_over[0] = w83781d_read_value(client,W83781D_REG_TEMP2_OVER);
1159    data->temp_add_hyst[0] = w83781d_read_value(client,W83781D_REG_TEMP2_HYST);
1160    data->temp_add[1] = w83781d_read_value(client,W83781D_REG_TEMP3);
1161    data->temp_add_over[1] = w83781d_read_value(client,W83781D_REG_TEMP3_OVER);
1162    data->temp_add_hyst[1] = w83781d_read_value(client,W83781D_REG_TEMP3_HYST);
1163    i = w83781d_read_value(client,W83781D_REG_VID_FANDIV);
1164    data->vid = i & 0x0f;
1165    data->vid |= (w83781d_read_value(client,W83781D_REG_CHIPID) & 0x01) << 4;
1166    data->fan_div[0] = (i >> 4) & 0x03;
1167    data->fan_div[1] = (i >> 6) & 0x03;
1168    data->fan_div[2] = (w83781d_read_value(client,
1169                                           W83781D_REG_PIN) >> 6) & 0x03;
1170    if (data->type != w83781d) {
1171      i = w83781d_read_value(client,W83781D_REG_VBAT);
1172      data->fan_div[0] |= (i >> 3) & 0x04;
1173      data->fan_div[1] |= (i >> 4) & 0x04;
1174      data->fan_div[2] |= (i >> 5) & 0x04;
1175    }
1176    data->alarms = w83781d_read_value(client,W83781D_REG_ALARM1) +
1177                   (w83781d_read_value(client,W83781D_REG_ALARM2) << 8);
1178    if (data->type == w83782d) {
1179      data->alarms |= w83781d_read_value(client,W83781D_REG_ALARM3) << 16;
1180    }
1181    i = w83781d_read_value(client,W83781D_REG_BEEP_INTS2);
1182    data->beep_enable = i >> 7;
1183    data->beeps = ((i & 0x7f) << 8) + 
1184                  w83781d_read_value(client,W83781D_REG_BEEP_INTS1);
1185    data->last_updated = jiffies;
1186    data->valid = 1;
1187  }
1188
1189  up(&data->update_lock);
1190}
1191
1192
1193/* The next few functions are the call-back functions of the /proc/sys and
1194   sysctl files. Which function is used is defined in the ctl_table in
1195   the extra1 field.
1196   Each function must return the magnitude (power of 10 to divide the date
1197   with) if it is called with operation==SENSORS_PROC_REAL_INFO. It must
1198   put a maximum of *nrels elements in results reflecting the data of this
1199   file, and set *nrels to the number it actually put in it, if operation==
1200   SENSORS_PROC_REAL_READ. Finally, it must get upto *nrels elements from
1201   results and write them to the chip, if operations==SENSORS_PROC_REAL_WRITE.
1202   Note that on SENSORS_PROC_REAL_READ, I do not check whether results is
1203   large enough (by checking the incoming value of *nrels). This is not very
1204   good practice, but as long as you put less than about 5 values in results,
1205   you can assume it is large enough. */
1206void w83781d_in(struct i2c_client *client, int operation, int ctl_name, 
1207             int *nrels_mag, long *results)
1208{
1209  struct w83781d_data *data = client->data;
1210  int nr = ctl_name - W83781D_SYSCTL_IN0;
1211
1212  if (operation == SENSORS_PROC_REAL_INFO)
1213    *nrels_mag = 2;
1214  else if (operation == SENSORS_PROC_REAL_READ) {
1215    w83781d_update_client(client);
1216    results[0] = IN_FROM_REG(data->in_min[nr]);
1217    results[1] = IN_FROM_REG(data->in_max[nr]);
1218    results[2] = IN_FROM_REG(data->in[nr]);
1219    *nrels_mag = 3;
1220  } else if (operation == SENSORS_PROC_REAL_WRITE) {
1221      if (*nrels_mag >= 1) {
1222        data->in_min[nr] = IN_TO_REG(results[0]);
1223        w83781d_write_value(client,W83781D_REG_IN_MIN(nr),data->in_min[nr]);
1224      }
1225      if (*nrels_mag >= 2) {
1226        data->in_max[nr] = IN_TO_REG(results[1]);
1227        w83781d_write_value(client,W83781D_REG_IN_MAX(nr),data->in_max[nr]);
1228      }
1229  }
1230}
1231
1232void w83781d_fan(struct i2c_client *client, int operation, int ctl_name,
1233              int *nrels_mag, long *results)
1234{
1235  struct w83781d_data *data = client->data;
1236  int nr = ctl_name - W83781D_SYSCTL_FAN1 + 1;
1237
1238  if (operation == SENSORS_PROC_REAL_INFO)
1239    *nrels_mag = 0;
1240  else if (operation == SENSORS_PROC_REAL_READ) {
1241    w83781d_update_client(client);
1242    results[0] = FAN_FROM_REG(data->fan_min[nr-1],
1243                              DIV_FROM_REG(data->fan_div[nr-1]));
1244    results[1] = FAN_FROM_REG(data->fan[nr-1],
1245                              DIV_FROM_REG(data->fan_div[nr-1]));
1246    *nrels_mag = 2;
1247  } else if (operation == SENSORS_PROC_REAL_WRITE) {
1248    if (*nrels_mag >= 1) {
1249      data->fan_min[nr-1] = FAN_TO_REG(results[0],
1250                                       DIV_FROM_REG(data->fan_div[nr-1]));
1251      w83781d_write_value(client,W83781D_REG_FAN_MIN(nr),data->fan_min[nr-1]);
1252    }
1253  }
1254}
1255
1256void w83781d_temp(struct i2c_client *client, int operation, int ctl_name,
1257               int *nrels_mag, long *results)
1258{
1259  struct w83781d_data *data = client->data;
1260  if (operation == SENSORS_PROC_REAL_INFO)
1261    *nrels_mag = 1;
1262  else if (operation == SENSORS_PROC_REAL_READ) {
1263    w83781d_update_client(client);
1264    results[0] = TEMP_FROM_REG(data->temp_over);
1265    results[1] = TEMP_FROM_REG(data->temp_hyst);
1266    results[2] = TEMP_FROM_REG(data->temp);
1267    *nrels_mag = 3;
1268  } else if (operation == SENSORS_PROC_REAL_WRITE) {
1269    if (*nrels_mag >= 1) {
1270      data->temp_over = TEMP_TO_REG(results[0]);
1271      w83781d_write_value(client,W83781D_REG_TEMP_OVER,data->temp_over);
1272    }
1273    if (*nrels_mag >= 2) {
1274      data->temp_hyst = TEMP_TO_REG(results[1]);
1275      w83781d_write_value(client,W83781D_REG_TEMP_HYST,data->temp_hyst);
1276    }
1277  }
1278}
1279
1280void w83781d_temp_add(struct i2c_client *client, int operation, int ctl_name,
1281                      int *nrels_mag, long *results)
1282{
1283  struct w83781d_data *data = client->data;
1284  int nr = ctl_name - W83781D_SYSCTL_TEMP2;
1285
1286  if (operation == SENSORS_PROC_REAL_INFO)
1287    *nrels_mag = 1;
1288  else if (operation == SENSORS_PROC_REAL_READ) {
1289    w83781d_update_client(client);
1290    results[0] = TEMP_ADD_FROM_REG(data->temp_add_over[nr]);
1291    results[1] = TEMP_ADD_FROM_REG(data->temp_add_hyst[nr]);
1292    results[2] = TEMP_ADD_FROM_REG(data->temp_add[nr]);
1293    *nrels_mag = 3;
1294  } else if (operation == SENSORS_PROC_REAL_WRITE) {
1295    if (*nrels_mag >= 1) {
1296      data->temp_add_over[nr] = TEMP_ADD_TO_REG(results[0]);
1297      w83781d_write_value(client,
1298                          nr?W83781D_REG_TEMP3_OVER:W83781D_REG_TEMP2_OVER,
1299                          data->temp_add_over[nr]);
1300    }
1301    if (*nrels_mag >= 2) {
1302      data->temp_add_hyst[nr] = TEMP_ADD_TO_REG(results[1]);
1303      w83781d_write_value(client,
1304                          nr?W83781D_REG_TEMP3_HYST:W83781D_REG_TEMP2_HYST,
1305                          data->temp_add_hyst[nr]);
1306    }
1307  }
1308}
1309
1310
1311void w83781d_vid(struct i2c_client *client, int operation, int ctl_name,
1312              int *nrels_mag, long *results)
1313{
1314  struct w83781d_data *data = client->data;
1315  if (operation == SENSORS_PROC_REAL_INFO)
1316    *nrels_mag = 2;
1317  else if (operation == SENSORS_PROC_REAL_READ) {
1318    w83781d_update_client(client);
1319    results[0] = VID_FROM_REG(data->vid);
1320    *nrels_mag = 1;
1321  }
1322}
1323
1324void w83781d_alarms(struct i2c_client *client, int operation, int ctl_name,
1325                 int *nrels_mag, long *results)
1326{
1327  struct w83781d_data *data = client->data;
1328  if (operation == SENSORS_PROC_REAL_INFO)
1329    *nrels_mag = 0;
1330  else if (operation == SENSORS_PROC_REAL_READ) {
1331    w83781d_update_client(client);
1332    results[0] = ALARMS_FROM_REG(data->alarms);
1333    *nrels_mag = 1;
1334  }
1335}
1336
1337void w83781d_beep(struct i2c_client *client, int operation, int ctl_name,
1338                 int *nrels_mag, long *results)
1339{
1340  struct w83781d_data *data = client->data;
1341  int val;
1342
1343  if (operation == SENSORS_PROC_REAL_INFO)
1344    *nrels_mag = 0;
1345  else if (operation == SENSORS_PROC_REAL_READ) {
1346    w83781d_update_client(client);
1347    results[0] = BEEP_ENABLE_FROM_REG(data->beep_enable);
1348    results[1] = BEEPS_FROM_REG(data->beeps);
1349    *nrels_mag = 2;
1350  } else if (operation == SENSORS_PROC_REAL_WRITE) {
1351    if (*nrels_mag >= 2) {
1352      data->beeps = BEEPS_TO_REG(results[1]);
1353      w83781d_write_value(client,W83781D_REG_BEEP_INTS1,data->beeps & 0xff);
1354      val = data->beeps >> 8;
1355    } else if (*nrels_mag >= 1)
1356      val = w83781d_read_value(client,W83781D_REG_BEEP_INTS1) & 0x7f;
1357    if (*nrels_mag >= 1) {
1358      data->beep_enable = BEEP_ENABLE_TO_REG(results[0]);
1359      w83781d_write_value(client,W83781D_REG_BEEP_INTS2,
1360                          val | data->beep_enable << 7);
1361    }
1362  }
1363}
1364
1365void w83781d_fan_div(struct i2c_client *client, int operation, int ctl_name,
1366                  int *nrels_mag, long *results)
1367{
1368  struct w83781d_data *data = client->data;
1369  int old,old2,old3;
1370
1371  if (operation == SENSORS_PROC_REAL_INFO)
1372    *nrels_mag = 0;
1373  else if (operation == SENSORS_PROC_REAL_READ) {
1374    w83781d_update_client(client);
1375    results[0] = DIV_FROM_REG(data->fan_div[0]);
1376    results[1] = DIV_FROM_REG(data->fan_div[1]);
1377    results[2] = DIV_FROM_REG(data->fan_div[2]);
1378    *nrels_mag = 3;
1379  } else if (operation == SENSORS_PROC_REAL_WRITE) {
1380    old = w83781d_read_value(client,W83781D_REG_VID_FANDIV);
1381    if(data->type != w83781d)
1382    {
1383      old3 = w83781d_read_value(client,W83781D_REG_VBAT);
1384    } 
1385    if (*nrels_mag >= 3) {
1386      data->fan_div[2] = DIV_TO_REG(results[2], data->type);
1387      old2 = w83781d_read_value(client,W83781D_REG_PIN);
1388      old2 = (old2 & 0x3f) | ((data->fan_div[2] & 0x03) << 6);
1389      w83781d_write_value(client,W83781D_REG_PIN,old2);
1390      if(data->type != w83781d)
1391      {
1392        old3 = (old3 & 0x7f) | ((data->fan_div[2] & 0x04) << 5);
1393      } 
1394    }
1395    if (*nrels_mag >= 2) {
1396      data->fan_div[1] = DIV_TO_REG(results[1], data->type);
1397      old = (old & 0x3f) | ((data->fan_div[1] & 0x03) << 6);
1398      if(data->type != w83781d)
1399      {
1400        old3 = (old3 & 0xbf) | ((data->fan_div[1] & 0x04) << 4);
1401      } 
1402    }
1403    if (*nrels_mag >= 1) {
1404      data->fan_div[0] = DIV_TO_REG(results[0], data->type);
1405      old = (old & 0xcf) | ((data->fan_div[0] & 0x03) << 4);
1406      w83781d_write_value(client,W83781D_REG_VID_FANDIV,old);
1407      if(data->type != w83781d)
1408      {
1409        old3 = (old3 & 0xdf) | ((data->fan_div[0] & 0x04) << 3);
1410        w83781d_write_value(client,W83781D_REG_VBAT,old3);
1411      } 
1412    }
1413  }
1414}
1415
1416void w83781d_pwm(struct i2c_client *client, int operation, int ctl_name,
1417                 int *nrels_mag, long *results)
1418{
1419  struct w83781d_data *data = client->data;
1420  int nr = 1 + ctl_name - W83781D_SYSCTL_PWM1;
1421
1422  if (operation == SENSORS_PROC_REAL_INFO)
1423    *nrels_mag = 0;
1424  else if (operation == SENSORS_PROC_REAL_READ) {
1425    w83781d_update_client(client);
1426    results[0] = PWM_FROM_REG(data->pwm[nr-1]);
1427    *nrels_mag = 1;
1428  } else if (operation == SENSORS_PROC_REAL_WRITE) {
1429    if (*nrels_mag >= 1) {
1430      data->pwm[nr-1] = PWM_TO_REG(results[0]);
1431      w83781d_write_value(client,W83781D_REG_PWM(nr),data->pwm[nr-1]);
1432    }
1433  }
1434}
1435
1436void w83781d_sens(struct i2c_client *client, int operation, int ctl_name,
1437                 int *nrels_mag, long *results)
1438{
1439  struct w83781d_data *data = client->data;
1440  int nr = 1 + ctl_name - W83781D_SYSCTL_SENS1;
1441  u8 tmp;
1442
1443  if (operation == SENSORS_PROC_REAL_INFO)
1444    *nrels_mag = 0;
1445  else if (operation == SENSORS_PROC_REAL_READ) {
1446    results[0] = data->sens[nr-1];
1447    *nrels_mag = 1;
1448  } else if (operation == SENSORS_PROC_REAL_WRITE) {
1449    if (*nrels_mag >= 1) {
1450      switch(results[0]) {
1451        case 1:                         /* PII/Celeron diode */
1452          tmp = w83781d_read_value(client,W83781D_REG_SCFG1);
1453          w83781d_write_value(client,W83781D_REG_SCFG1, tmp | BIT_SCFG2[nr-1]);
1454          tmp = w83781d_read_value(client,W83781D_REG_SCFG2);
1455          w83781d_write_value(client,W83781D_REG_SCFG2, tmp | BIT_SCFG2[nr-1]);
1456          data->sens[nr-1] = results[0];
1457          break;
1458        case 2:                         /* 3904 */
1459          tmp = w83781d_read_value(client,W83781D_REG_SCFG1);
1460          w83781d_write_value(client,W83781D_REG_SCFG1, tmp | BIT_SCFG2[nr-1]);
1461          tmp = w83781d_read_value(client,W83781D_REG_SCFG2);
1462          w83781d_write_value(client,W83781D_REG_SCFG2,
1463                              tmp & ~BIT_SCFG2[nr-1]);
1464          data->sens[nr-1] = results[0];
1465          break;
1466        case W83781D_DEFAULT_BETA:      /* thermistor */
1467          tmp = w83781d_read_value(client,W83781D_REG_SCFG1);
1468          w83781d_write_value(client,W83781D_REG_SCFG1,
1469                              tmp & ~BIT_SCFG2[nr-1]);
1470          data->sens[nr-1] = results[0];
1471          break;
1472        default:
1473          printk("w83781d.o: Invalid sensor type %ld; must be 1, 2, or %d\n", 
1474                 results[0], W83781D_DEFAULT_BETA);
1475          break;
1476      }
1477    }
1478  }
1479}
1480
1481#ifdef W83781D_RT
1482void w83781d_rt(struct i2c_client *client, int operation, int ctl_name,
1483                 int *nrels_mag, long *results)
1484{
1485  struct w83781d_data *data = client->data;
1486  int nr = 1 + ctl_name - W83781D_SYSCTL_RT1;
1487  int i;
1488
1489  if (operation == SENSORS_PROC_REAL_INFO)
1490    *nrels_mag = 0;
1491  else if (operation == SENSORS_PROC_REAL_READ) {
1492    for(i = 0; i < 32; i++) {
1493      results[i] = data->rt[nr-1][i];
1494    }
1495    *nrels_mag = 32;
1496  } else if (operation == SENSORS_PROC_REAL_WRITE) {
1497    if(*nrels_mag > 32) *nrels_mag = 32;       
1498    for(i = 0; i < *nrels_mag; i++) {
1499      /* fixme: no bounds checking 0-255 */
1500      data->rt[nr-1][i] = results[i];
1501      w83781d_write_value(client,W83781D_REG_RT_IDX,i);
1502      w83781d_write_value(client,W83781D_REG_RT_VAL,data->rt[nr-1][i]);
1503    }
1504  }
1505}
1506#endif
1507
1508int w83781d_init(void)
1509{
1510  int res;
1511
1512  printk("w83781d.o version %s (%s)\n",LM_VERSION,LM_DATE);
1513  w83781d_initialized = 0;
1514
1515  if ((res =i2c_add_driver(&w83781d_driver))) {
1516    printk("w83781d.o: Driver registration failed, module not inserted.\n");
1517    w83781d_cleanup();
1518    return res;
1519  }
1520  w83781d_initialized ++;
1521  return 0;
1522}
1523
1524int w83781d_cleanup(void)
1525{
1526  int res;
1527
1528  if (w83781d_initialized >= 1) {
1529    if ((res = i2c_del_driver(&w83781d_driver))) {
1530      printk("w83781d.o: Driver deregistration failed, module not removed.\n");
1531      return res;
1532    }
1533    w83781d_initialized --;
1534  }
1535  return 0;
1536}
1537
1538
1539#ifdef MODULE
1540
1541MODULE_AUTHOR("Frodo Looijaard <frodol@dds.nl>, Philip Edelbrock <phil@netroedge
1542.com>, and Mark Studebaker <mds@eng.paradyne.com>");
1543MODULE_DESCRIPTION("W83781D driver");
1544
1545int init_module(void)
1546{
1547  return w83781d_init();
1548}
1549
1550int cleanup_module(void)
1551{
1552  return w83781d_cleanup();
1553}
1554
1555#endif /* MODULE */
1556
1557
1558
1559   
Note: See TracBrowser for help on using the browser.