root/lm-sensors/trunk/kernel/chips/w83792d.c @ 3211

Revision 3211, 51.0 KB (checked in by khali, 7 years ago)

Drop useless local variable.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
Line 
1/*
2    w83792d.c - Part of lm_sensors, Linux kernel modules for hardware
3                monitoring
4    Copyright (c) 2004, 2005 Winbond Electronics Corp.
5                  Chunhao Huang
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    Note:
22    1. This driver is only for 2.4 kernel(2.4.10 or later), 2.6 kernel
23       need a different driver.
24    2. This driver is only for Winbond W83792D C version device, there
25       are also some motherboards with B version W83792D device. The
26       calculation method to in6-in7(measured value, limits) is a little
27       different between C and B version. C or B version can be identified
28       by CR[0x49h].
29    3. The function of chassis open detection need further test.
30    4. The function of vid and vrm has not been finished, because I'm NOT
31       very familiar with them. If someone can finish it, that's good,
32       then please delete this note 4.
33*/
34
35/*
36    Supports following chips:
37
38    Chip        #vin    #fanin  #pwm    #temp   wchipid vendid  i2c     ISA
39    w83792d     9       7       3       3       0x7a    0x5ca3  yes     no
40*/
41
42#include <linux/module.h>
43#include <linux/slab.h>
44#include <linux/i2c.h>
45#include <linux/i2c-proc.h>
46#include <linux/init.h>
47#include "version.h"
48#include "sensors_vid.h"
49
50/* Addresses to scan */
51static unsigned short normal_i2c[] = { SENSORS_I2C_END };
52static unsigned short normal_i2c_range[] = { 0x2c, 0x2f, SENSORS_I2C_END };
53static unsigned int normal_isa[] = { SENSORS_ISA_END };
54static unsigned int normal_isa_range[] = { SENSORS_ISA_END };
55
56/* Insmod parameters */
57SENSORS_INSMOD_1(w83792d);
58SENSORS_MODULE_PARM(force_subclients, "List of subclient addresses: " \
59                    "{bus, clientaddr, subclientaddr1, subclientaddr2}");
60
61static int init;
62MODULE_PARM(init, "i");
63MODULE_PARM_DESC(init, "Set to one for chip initialization");
64
65/* Enable/Disable w83792d debugging output */
66/* #define W83792D_DEBUG 1 */
67
68/* Constants specified below */
69#define W83792D_REG_GPIO_EN 0x1A
70#define W83792D_REG_CONFIG 0x40
71#define W83792D_REG_I2C_ADDR 0x48
72#define W83792D_REG_CHIPID 0x49   /* contains version ID: A/B/C */
73#define W83792D_REG_I2C_SUBADDR 0x4A
74#define W83792D_REG_PIN 0x4B
75#define W83792D_REG_IRQ 0x4C
76#define W83792D_REG_BANK 0x4E
77#define W83792D_REG_CHIPMAN 0x4F  /* contains the vendor ID */
78#define W83792D_REG_WCHIPID 0x58  /* contains the chip ID */
79#define W83792D_REG_VID_IN_B 0x17 /* ctroll in0/in1 's limit modifiability */
80
81static const u8 W83792D_REG_IN[9] = {
82        0x20,   /* Vcore A in DataSheet */
83        0x21,   /* Vcore B in DataSheet */
84        0x22,   /* VIN0 in DataSheet */
85        0x23,   /* VIN1 in DataSheet */
86        0x24,   /* VIN2 in DataSheet */
87        0x25,   /* VIN3 in DataSheet */
88        0x26,   /* 5VCC in DataSheet */
89        0xB0,   /* 5VSB in DataSheet */
90        0xB1    /* VBAT in DataSheet */
91};
92#define W83792D_REG_LOW_BITS1 0x3E  /* Low Bits I in DataSheet */
93#define W83792D_REG_LOW_BITS2 0x3F  /* Low Bits II in DataSheet */
94static const u8 W83792D_REG_IN_MAX[9] = {
95        0x2B,   /* Vcore A High Limit in DataSheet */
96        0x2D,   /* Vcore B High Limit in DataSheet */
97        0x2F,   /* VIN0 High Limit in DataSheet */
98        0x31,   /* VIN1 High Limit in DataSheet */
99        0x33,   /* VIN2 High Limit in DataSheet */
100        0x35,   /* VIN3 High Limit in DataSheet */
101        0x37,   /* 5VCC High Limit in DataSheet */
102        0xB4,   /* 5VSB High Limit in DataSheet */
103        0xB6    /* VBAT High Limit in DataSheet */
104};
105static const u8 W83792D_REG_IN_MIN[9] = {
106        0x2C,   /* Vcore A Low Limit in DataSheet */
107        0x2E,   /* Vcore B Low Limit in DataSheet */
108        0x30,   /* VIN0 Low Limit in DataSheet */
109        0x32,   /* VIN1 Low Limit in DataSheet */
110        0x34,   /* VIN2 Low Limit in DataSheet */
111        0x36,   /* VIN3 Low Limit in DataSheet */
112        0x38,   /* 5VCC Low Limit in DataSheet */
113        0xB5,   /* 5VSB Low Limit in DataSheet */
114        0xB7    /* VBAT Low Limit in DataSheet */
115};
116
117static const u8 W83792D_REG_FAN[7] = {
118        0x28,   /* FAN 1 Count in DataSheet */
119        0x29,   /* FAN 2 Count in DataSheet */
120        0x2A,   /* FAN 3 Count in DataSheet */
121        0xB8,   /* FAN 4 Count in DataSheet */
122        0xB9,   /* FAN 5 Count in DataSheet */
123        0xBA,   /* FAN 6 Count in DataSheet */
124        0xBE    /* FAN 7 Count in DataSheet */
125};
126static const u8 W83792D_REG_FAN_MIN[7] = {
127        0x3B,   /* FAN 1 Count Low Limit in DataSheet */
128        0x3C,   /* FAN 2 Count Low Limit in DataSheet */
129        0x3D,   /* FAN 3 Count Low Limit in DataSheet */
130        0xBB,   /* FAN 4 Count Low Limit in DataSheet */
131        0xBC,   /* FAN 5 Count Low Limit in DataSheet */
132        0xBD,   /* FAN 6 Count Low Limit in DataSheet */
133        0xBF    /* FAN 7 Count Low Limit in DataSheet */
134};
135#define W83792D_REG_FAN_CFG 0x84    /* FAN Configuration in DataSheet */
136static const u8 W83792D_REG_PWM[7] = {
137        0x81,   /* FAN 1 Duty Cycle, be used to control */
138        0x83,   /* FAN 2 Duty Cycle, be used to control */
139        0x94,   /* FAN 3 Duty Cycle, be used to control */
140        0xA3,   /* FAN 4 Duty Cycle, be used to control */
141        0xA4,   /* FAN 5 Duty Cycle, be used to control */
142        0xA5,   /* FAN 6 Duty Cycle, be used to control */
143        0xA6    /* FAN 7 Duty Cycle, be used to control */
144};
145
146#define W83792D_REG_TEMP1 0x27          /* TEMP 1 in DataSheet */
147#define W83792D_REG_TEMP1_OVER 0x39     /* TEMP 1 High Limit in DataSheet */
148#define W83792D_REG_TEMP1_HYST 0x3A     /* TEMP 1 Low Limit in DataSheet */
149static const u8 W83792D_REG_TEMP_ADD[2][7] = {
150        { 0xC0,         /* TEMP 2 in DataSheet */
151          0xC1,         /* TEMP 2(0.5 deg) in DataSheet */
152          0xC5,         /* TEMP 2 Over High part in DataSheet */
153          0xC6,         /* TEMP 2 Over Low part in DataSheet */
154          0xC3,         /* TEMP 2 Thyst High part in DataSheet */
155          0xC4,         /* TEMP 2 Thyst Low part in DataSheet */
156          0xC2 },       /* TEMP 2 Config in DataSheet */
157        { 0xC8,         /* TEMP 3 in DataSheet */
158          0xC9,         /* TEMP 3(0.5 deg) in DataSheet */
159          0xCD,         /* TEMP 3 Over High part in DataSheet */
160          0xCE,         /* TEMP 3 Over Low part in DataSheet */
161          0xCB,         /* TEMP 3 Thyst High part in DataSheet */
162          0xCC,         /* TEMP 3 Thyst Low part in DataSheet */
163          0xCA }        /* TEMP 3 Config in DataSheet */
164};
165
166static const u8 W83792D_REG_FAN_DIV[4] = {
167        0x47,   /* contains FAN2 and FAN1 Divisor */
168        0x5B,   /* contains FAN4 and FAN3 Divisor */
169        0x5C,   /* contains FAN6 and FAN5 Divisor */
170        0x9E    /* contains FAN7 Divisor. */
171};
172
173#define W83792D_REG_ALARM1 0xA9         /* realtime status register1 */
174#define W83792D_REG_ALARM2 0xAA         /* realtime status register2 */
175#define W83792D_REG_ALARM3 0xAB         /* realtime status register3 */
176#define W83792D_REG_CASE_OPEN 0x42      /* Bit 5: Case Open status bit */
177#define W83792D_REG_CASE_OPEN_CLR 0x44  /* Bit 7: Case Open CLR_CHS/Reset bit */
178
179static const u8 W83792D_REG_THERMAL[3] = {
180        0x85,   /* SmartFanI: Fan1 target value */
181        0x86,   /* SmartFanI: Fan2 target value */
182        0x96    /* SmartFanI: Fan3 target value */
183};
184
185static const u8 W83792D_REG_FAN_TOL[3] = {
186        0x87,   /* (bit3-0)SmartFan Fan1 tolerance */
187        0x87,   /* (bit7-4)SmartFan Fan2 tolerance */
188        0x97    /* (bit3-0)SmartFan Fan3 tolerance */
189};
190
191static const u8 W83792D_REG_POINTS[3][4] = {
192        { 0x85,         /* SmartFanII: Fan1 temp point 1 */
193          0xE3,         /* SmartFanII: Fan1 temp point 2 */
194          0xE4,         /* SmartFanII: Fan1 temp point 3 */
195          0xE5 },       /* SmartFanII: Fan1 temp point 4 */
196        { 0x86,         /* SmartFanII: Fan2 temp point 1 */
197          0xE6,         /* SmartFanII: Fan2 temp point 2 */
198          0xE7,         /* SmartFanII: Fan2 temp point 3 */
199          0xE8 },       /* SmartFanII: Fan2 temp point 4 */
200        { 0x96,         /* SmartFanII: Fan3 temp point 1 */
201          0xE9,         /* SmartFanII: Fan3 temp point 2 */
202          0xEA,         /* SmartFanII: Fan3 temp point 3 */
203          0xEB }        /* SmartFanII: Fan3 temp point 4 */
204};
205
206static const u8 W83792D_REG_LEVELS[3][4] = {
207        { 0x88,         /* (bit3-0) SmartFanII: Fan1 Non-Stop */
208          0x88,         /* (bit7-4) SmartFanII: Fan1 Level 1 */
209          0xE0,         /* (bit7-4) SmartFanII: Fan1 Level 2 */
210          0xE0 },       /* (bit3-0) SmartFanII: Fan1 Level 3 */
211        { 0x89,         /* (bit3-0) SmartFanII: Fan2 Non-Stop */
212          0x89,         /* (bit7-4) SmartFanII: Fan2 Level 1 */
213          0xE1,         /* (bit7-4) SmartFanII: Fan2 Level 2 */
214          0xE1 },       /* (bit3-0) SmartFanII: Fan2 Level 3 */
215        { 0x98,         /* (bit3-0) SmartFanII: Fan3 Non-Stop */
216          0x98,         /* (bit7-4) SmartFanII: Fan3 Level 1 */
217          0xE2,         /* (bit7-4) SmartFanII: Fan3 Level 2 */
218          0xE2 }        /* (bit3-0) SmartFanII: Fan3 Level 3 */
219};
220
221static inline u8 FAN_TO_REG(long rpm, int div)
222{
223        if (rpm == 0)
224                return 255;
225        rpm = SENSORS_LIMIT(rpm, 1, 1000000);
226        return SENSORS_LIMIT(1350000/(rpm * div), 1, 254);
227}
228
229#define IN_FROM_REG(nr,val) (((nr)<=1)?(val*2): \
230                                ((((nr)==6)||((nr)==7))?(val*6):(val*4)))
231#define IN_TO_REG(nr,val) (((nr)<=1)?(val/2): \
232                                ((((nr)==6)||((nr)==7))?(val/6):(val/4)))
233#define TEMP_FROM_REG(val) (((val)>0x80?(val)-0x100:(val))*10)
234#define TEMP_TO_REG(val) (SENSORS_LIMIT((val>=0)?((val)/10):((val)/10+256), 0, 255))
235#define FAN_FROM_REG(val,div) ((val)==0?-1:(val)==255?0:1350000/((val)*(div)))
236#define DIV_FROM_REG(val) (1 << (val))
237
238#ifdef W83792D_DEBUG
239#define ENTER() printk(KERN_DEBUG "w83792d: ENTERING %s, line: %d\n", __FUNCTION__, __LINE__);
240#define LEAVE() printk(KERN_DEBUG "w83792d: LEAVING %s, line: %d\n", __FUNCTION__, __LINE__);
241#else
242#define ENTER()
243#define LEAVE()
244#endif
245
246struct w83792d_data {
247        struct i2c_client client;
248        struct semaphore lock;
249        int sysctl_id;
250        enum chips type;
251
252        struct semaphore update_lock;
253        char valid;             /* !=0 if following fields are valid */
254        unsigned long last_updated;     /* In jiffies */
255
256        struct i2c_client *lm75;        /* for secondary I2C addresses */
257        /* pointer to array of 2 subclients */
258
259        u8 in[9];               /* Register value */
260        u8 in_max[9];           /* Register value */
261        u8 in_min[9];           /* Register value */
262        u16 low_bits;           /* Register value */
263        u8 has_fan;             /* Bit vector */
264        u8 fan[7];              /* Register value */
265        u8 fan_min[7];          /* Register value */
266        u8 fan_cfg;             /* Configure Fan Mode */
267        u8 temp1[3];            /* Register value */
268        u8 temp_add[2][7];      /* Register value */
269        u8 fan_div[7];          /* Fan Divisor */
270        /*u8 vid;               Register encoding, combined */
271        u8 pwm[7];              /* We only consider the first 3 set of pwm,
272                                   although 792 chip has 7 set of pwm. */
273        u8 pwm_flag[7];         /* indicates PWM or DC mode: 1->PWM; 0->DC */
274        /* u8 vrm;               VRM version */
275        u32 alarms;             /* realtime status register encoding,combined */
276        u8 chassis[2];          /* [0]->Chassis status, [1]->CLR_CHS */
277        u8 thermal_cruise[3];   /* Smart FanI: Fan1,2,3 target value */
278        u8 fan_tolerance[3];    /* Fan1,2,3 tolerance(Smart Fan I/II) */
279        u8 sf2_points[3][4];    /* Smart FanII: Fan1,2,3 temperature points */
280        u8 sf2_levels[3][4];    /* Smart FanII: Fan1,2,3 duty cycle levels */
281};
282
283
284static int w83792d_attach_adapter(struct i2c_adapter *adapter);
285static int w83792d_detect(struct i2c_adapter *adapter, int address,
286                          unsigned short flags, int kind);
287static int w83792d_detach_client(struct i2c_client *client);
288
289static inline int w83792d_read_value(struct i2c_client *client, u8 reg);
290static inline int w83792d_write_value(struct i2c_client *client, u8 reg,
291                                      u8 value);
292static void w83792d_init_client(struct i2c_client *client);
293static void w83792d_update_client(struct i2c_client *client);
294#ifdef W83792D_DEBUG
295static void w83792d_print_debug(struct w83792d_data *data);
296#endif
297static void w83792d_in(struct i2c_client *client, int operation,
298                       int ctl_name, int *nrels_mag, long *results);
299static void w83792d_fan(struct i2c_client *client, int operation,
300                        int ctl_name, int *nrels_mag, long *results);
301static void w83792d_temp(struct i2c_client *client, int operation,
302                         int ctl_name, int *nrels_mag, long *results);
303static void w83792d_temp_add(struct i2c_client *client, int operation,
304                             int ctl_name, int *nrels_mag, long *results);
305/*static void w83792d_vid(struct i2c_client *client, int operation,
306                        int ctl_name, int *nrels_mag, long *results);
307static void w83792d_vrm(struct i2c_client *client, int operation,
308                        int ctl_name, int *nrels_mag, long *results); */
309static void w83792d_fan_div(struct i2c_client *client, int operation,
310                            int ctl_name, int *nrels_mag, long *results);
311static void w83792d_alarms(struct i2c_client *client, int operation,
312                            int ctl_name, int *nrels_mag, long *results);
313static void w83792d_chassis(struct i2c_client *client, int operation,
314                            int ctl_name, int *nrels_mag, long *results);
315static void w83792d_pwm(struct i2c_client *client, int operation,
316                        int ctl_name, int *nrels_mag, long *results);
317static void w83792d_pwm_flag(struct i2c_client *client, int operation,
318                             int ctl_name, int *nrels_mag, long *results);
319static void w83792d_fan_cfg(struct i2c_client *client, int operation,
320                            int ctl_name, int *nrels_mag, long *results);
321static void w83792d_thermal_cruise(struct i2c_client *client, int operation,
322                                   int ctl_name, int *nrels_mag, long *results);
323static void w83792d_fan_tolerance(struct i2c_client *client, int operation,
324                                  int ctl_name, int *nrels_mag, long *results);
325static void w83792d_sf2_points(struct i2c_client *client, int operation,
326                                int ctl_name, int *nrels_mag, long *results);
327static void w83792d_sf2_levels(struct i2c_client *client, int operation,
328                                int ctl_name, int *nrels_mag, long *results);
329
330static struct i2c_driver w83792d_driver = {
331        .name           = "W83792D sensor driver",
332        .flags          = I2C_DF_NOTIFY,
333        .attach_adapter = w83792d_attach_adapter,
334        .detach_client  = w83792d_detach_client,
335};
336
337/* The /proc/sys entries */
338/* -- SENSORS SYSCTL START -- */
339
340#define W83792D_SYSCTL_IN0 1000
341#define W83792D_SYSCTL_IN1 1001
342#define W83792D_SYSCTL_IN2 1002
343#define W83792D_SYSCTL_IN3 1003
344#define W83792D_SYSCTL_IN4 1004
345#define W83792D_SYSCTL_IN5 1005
346#define W83792D_SYSCTL_IN6 1006
347#define W83792D_SYSCTL_IN7 1007
348#define W83792D_SYSCTL_IN8 1008
349#define W83792D_SYSCTL_FAN1 1101
350#define W83792D_SYSCTL_FAN2 1102
351#define W83792D_SYSCTL_FAN3 1103
352#define W83792D_SYSCTL_FAN4 1104
353#define W83792D_SYSCTL_FAN5 1105
354#define W83792D_SYSCTL_FAN6 1106
355#define W83792D_SYSCTL_FAN7 1107
356
357#define W83792D_SYSCTL_TEMP1 1200
358#define W83792D_SYSCTL_TEMP2 1201
359#define W83792D_SYSCTL_TEMP3 1202
360/*#define W83792D_SYSCTL_VID 1300
361#define W83792D_SYSCTL_VRM 1301*/
362#define W83792D_SYSCTL_PWM_FLAG 1400
363#define W83792D_SYSCTL_PWM1 1401
364#define W83792D_SYSCTL_PWM2 1402
365#define W83792D_SYSCTL_PWM3 1403
366#define W83792D_SYSCTL_FAN_CFG 1500     /* control Fan Mode */
367#define W83792D_SYSCTL_FAN_DIV 1501
368#define W83792D_SYSCTL_CHASSIS 1502     /* control Case Open */
369#define W83792D_SYSCTL_ALARMS 1503
370
371#define W83792D_SYSCTL_THERMAL_CRUISE 1600      /* Smart Fan I: target value */
372#define W83792D_SYSCTL_FAN_TOLERANCE 1601       /* Smart Fan I/II: tolerance */
373#define W83792D_SYSCTL_SF2_POINTS_FAN1 1602     /* Smart Fan II: Fan1 points */
374#define W83792D_SYSCTL_SF2_POINTS_FAN2 1603     /* Smart Fan II: Fan2 points */
375#define W83792D_SYSCTL_SF2_POINTS_FAN3 1604     /* Smart Fan II: Fan3 points */
376#define W83792D_SYSCTL_SF2_LEVELS_FAN1 1605     /* Smart Fan II: Fan1 levels */
377#define W83792D_SYSCTL_SF2_LEVELS_FAN2 1606     /* Smart Fan II: Fan2 levels */
378#define W83792D_SYSCTL_SF2_LEVELS_FAN3 1607     /* Smart Fan II: Fan3 levels */
379
380#define W83792D_ALARM_IN0 0x0001
381#define W83792D_ALARM_IN1 0x0002
382#define W83792D_ALARM_IN2 0x0100
383#define W83792D_ALARM_IN3 0x0200
384#define W83792D_ALARM_IN4 0x0400
385#define W83792D_ALARM_IN5 0x0800
386#define W83792D_ALARM_IN6 0x1000
387#define W83792D_ALARM_IN7 0x80000
388#define W83792D_ALARM_IN8 0x100000
389#define W83792D_ALARM_TEMP1 0x0004
390#define W83792D_ALARM_TEMP2 0x0008
391#define W83792D_ALARM_TEMP3 0x0010
392#define W83792D_ALARM_FAN1 0x0020
393#define W83792D_ALARM_FAN2 0x0040
394#define W83792D_ALARM_FAN3 0x0080
395#define W83792D_ALARM_FAN4 0x200000
396#define W83792D_ALARM_FAN5 0x400000
397#define W83792D_ALARM_FAN6 0x800000
398#define W83792D_ALARM_FAN7 0x8000
399
400/* -- SENSORS SYSCTL END -- */
401
402/* These files are created for detected chip,
403   W83792D has 9 voltages 7 fans and 3 temperatures. */
404static ctl_table w83792d_dir_table_template[] =
405{
406        {W83792D_SYSCTL_IN0, "in0", NULL, 0, 0644, NULL, &i2c_proc_real,
407         &i2c_sysctl_real, NULL, &w83792d_in},
408        {W83792D_SYSCTL_IN1, "in1", NULL, 0, 0644, NULL, &i2c_proc_real,
409         &i2c_sysctl_real, NULL, &w83792d_in},
410        {W83792D_SYSCTL_IN2, "in2", NULL, 0, 0644, NULL, &i2c_proc_real,
411         &i2c_sysctl_real, NULL, &w83792d_in},
412        {W83792D_SYSCTL_IN3, "in3", NULL, 0, 0644, NULL, &i2c_proc_real,
413         &i2c_sysctl_real, NULL, &w83792d_in},
414        {W83792D_SYSCTL_IN4, "in4", NULL, 0, 0644, NULL, &i2c_proc_real,
415         &i2c_sysctl_real, NULL, &w83792d_in},
416        {W83792D_SYSCTL_IN5, "in5", NULL, 0, 0644, NULL, &i2c_proc_real,
417         &i2c_sysctl_real, NULL, &w83792d_in},
418        {W83792D_SYSCTL_IN6, "in6", NULL, 0, 0644, NULL, &i2c_proc_real,
419         &i2c_sysctl_real, NULL, &w83792d_in},
420        {W83792D_SYSCTL_IN7, "in7", NULL, 0, 0644, NULL, &i2c_proc_real,
421         &i2c_sysctl_real, NULL, &w83792d_in},
422        {W83792D_SYSCTL_IN8, "in8", NULL, 0, 0644, NULL, &i2c_proc_real,
423         &i2c_sysctl_real, NULL, &w83792d_in},
424        {W83792D_SYSCTL_FAN1, "fan1", NULL, 0, 0644, NULL, &i2c_proc_real,
425         &i2c_sysctl_real, NULL, &w83792d_fan},
426        {W83792D_SYSCTL_FAN2, "fan2", NULL, 0, 0644, NULL, &i2c_proc_real,
427         &i2c_sysctl_real, NULL, &w83792d_fan},
428        {W83792D_SYSCTL_FAN3, "fan3", NULL, 0, 0644, NULL, &i2c_proc_real,
429         &i2c_sysctl_real, NULL, &w83792d_fan},
430        {W83792D_SYSCTL_FAN4, "fan4", NULL, 0, 0644, NULL, &i2c_proc_real,
431         &i2c_sysctl_real, NULL, &w83792d_fan},
432        {W83792D_SYSCTL_FAN5, "fan5", NULL, 0, 0644, NULL, &i2c_proc_real,
433         &i2c_sysctl_real, NULL, &w83792d_fan},
434        {W83792D_SYSCTL_FAN6, "fan6", NULL, 0, 0644, NULL, &i2c_proc_real,
435         &i2c_sysctl_real, NULL, &w83792d_fan},
436        {W83792D_SYSCTL_FAN7, "fan7", NULL, 0, 0644, NULL, &i2c_proc_real,
437         &i2c_sysctl_real, NULL, &w83792d_fan},
438        {W83792D_SYSCTL_TEMP1, "temp1", NULL, 0, 0644, NULL, &i2c_proc_real,
439         &i2c_sysctl_real, NULL, &w83792d_temp},
440        {W83792D_SYSCTL_TEMP2, "temp2", NULL, 0, 0644, NULL, &i2c_proc_real,
441         &i2c_sysctl_real, NULL, &w83792d_temp_add},
442        {W83792D_SYSCTL_TEMP3, "temp3", NULL, 0, 0644, NULL, &i2c_proc_real,
443         &i2c_sysctl_real, NULL, &w83792d_temp_add},
444        /*{W83792D_SYSCTL_VID, "vid", NULL, 0, 0444, NULL, &i2c_proc_real,
445         &i2c_sysctl_real, NULL, &w83792d_vid}, */
446        {W83792D_SYSCTL_FAN_DIV, "fan_div", NULL, 0, 0644, NULL, &i2c_proc_real,
447         &i2c_sysctl_real, NULL, &w83792d_fan_div},
448        {W83792D_SYSCTL_ALARMS, "alarms", NULL, 0, 0644, NULL,
449         &i2c_proc_real, &i2c_sysctl_real, NULL, &w83792d_alarms},
450        {W83792D_SYSCTL_CHASSIS, "chassis", NULL, 0, 0644, NULL,
451         &i2c_proc_real, &i2c_sysctl_real, NULL, &w83792d_chassis},
452        {W83792D_SYSCTL_PWM1, "pwm1", NULL, 0, 0644, NULL, &i2c_proc_real,
453         &i2c_sysctl_real, NULL, &w83792d_pwm},
454        {W83792D_SYSCTL_PWM2, "pwm2", NULL, 0, 0644, NULL, &i2c_proc_real,
455         &i2c_sysctl_real, NULL, &w83792d_pwm},
456        {W83792D_SYSCTL_PWM3, "pwm3", NULL, 0, 0644, NULL, &i2c_proc_real,
457         &i2c_sysctl_real, NULL, &w83792d_pwm},
458        {W83792D_SYSCTL_PWM_FLAG, "pwm_flag", NULL, 0, 0644, NULL, &i2c_proc_real,
459         &i2c_sysctl_real, NULL, &w83792d_pwm_flag},
460        {W83792D_SYSCTL_FAN_CFG, "fan_cfg", NULL, 0, 0644, NULL, &i2c_proc_real,
461         &i2c_sysctl_real, NULL, &w83792d_fan_cfg},
462        /*{W83792D_SYSCTL_VRM, "vrm", NULL, 0, 0644, NULL, &i2c_proc_real,
463         &i2c_sysctl_real, NULL, &w83792d_vrm},  */
464        {W83792D_SYSCTL_THERMAL_CRUISE, "thermal_cruise", NULL, 0, 0644, NULL,
465         &i2c_proc_real, &i2c_sysctl_real, NULL, &w83792d_thermal_cruise},
466        {W83792D_SYSCTL_FAN_TOLERANCE, "fan_tolerance", NULL, 0, 0644,
467         NULL, &i2c_proc_real, &i2c_sysctl_real, NULL, &w83792d_fan_tolerance},
468        {W83792D_SYSCTL_SF2_POINTS_FAN1, "sf2_points_fan1", NULL, 0, 0644, NULL,
469         &i2c_proc_real, &i2c_sysctl_real, NULL, &w83792d_sf2_points},
470        {W83792D_SYSCTL_SF2_POINTS_FAN2, "sf2_points_fan2", NULL, 0, 0644, NULL,
471         &i2c_proc_real, &i2c_sysctl_real, NULL, &w83792d_sf2_points},
472        {W83792D_SYSCTL_SF2_POINTS_FAN3, "sf2_points_fan3", NULL, 0, 0644, NULL,
473         &i2c_proc_real, &i2c_sysctl_real, NULL, &w83792d_sf2_points},
474        {W83792D_SYSCTL_SF2_LEVELS_FAN1, "sf2_levels_fan1", NULL, 0, 0644, NULL,
475         &i2c_proc_real, &i2c_sysctl_real, NULL, &w83792d_sf2_levels},
476        {W83792D_SYSCTL_SF2_LEVELS_FAN2, "sf2_levels_fan2", NULL, 0, 0644, NULL,
477         &i2c_proc_real, &i2c_sysctl_real, NULL, &w83792d_sf2_levels},
478        {W83792D_SYSCTL_SF2_LEVELS_FAN3, "sf2_levels_fan3", NULL, 0, 0644, NULL,
479         &i2c_proc_real, &i2c_sysctl_real, NULL, &w83792d_sf2_levels},
480        {0}
481};
482
483/* This function is called when:
484     * w83792d_driver is inserted (when this module is loaded), for each
485       available adapter
486     * when a new adapter is inserted (and w83792d_driver is still present) */
487static int w83792d_attach_adapter(struct i2c_adapter *adapter)
488{
489        int i_tmp;
490        ENTER()
491        i_tmp = i2c_detect(adapter, &addr_data, w83792d_detect);
492        LEAVE()
493        return i_tmp;
494}
495
496static int w83792d_detect(struct i2c_adapter *adapter, int address,
497                          unsigned short flags, int kind)
498{
499        int i, val1 = 0, val2 = 0, id;
500        struct i2c_client *new_client;
501        struct w83792d_data *data;
502        int err = 0;
503        const char *type_name = "";
504        const char *client_name = "";
505
506        ENTER()
507
508        if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA)) {
509                LEAVE()
510                goto ERROR0;
511        }
512
513        /* OK. For now, we presume we have a valid client. We now create the
514           client structure, even though we cannot fill it completely yet.
515           But it allows us to access w83792d_{read,write}_value. */
516
517        if (!(data = kmalloc(sizeof(struct w83792d_data), GFP_KERNEL))) {
518                printk(KERN_ERR "w83792d: Out of memory in w83792d_detect (new_client).\n");
519                err = -ENOMEM;
520                LEAVE()
521                goto ERROR0;
522        }
523
524        new_client = &data->client;
525        new_client->addr = address;
526        new_client->data = data;
527        new_client->adapter = adapter;
528        new_client->driver = &w83792d_driver;
529        new_client->flags = 0;
530
531        /* Now, we do the remaining detection. */
532        if (kind < 0) {
533                if (w83792d_read_value(new_client, W83792D_REG_CONFIG)&0x80) {
534                        LEAVE()
535                        goto ERROR1;
536                }
537                val1 = w83792d_read_value(new_client, W83792D_REG_BANK);
538                val2 = w83792d_read_value(new_client, W83792D_REG_CHIPMAN);
539#ifdef W83792D_DEBUG
540                printk(KERN_DEBUG "w83792d: val1 is: %d, val2 is: %d\n",
541                                                val1, val2);
542#endif
543                /* Check for Winbond ID if in bank 0 */
544                if (!(val1 & 0x07)) {  /* is Bank0 */
545                        if (((!(val1 & 0x80)) && (val2 != 0xa3)) ||
546                             ((val1 & 0x80) && (val2 != 0x5c))) {
547                                LEAVE()
548                                goto ERROR1;
549                        }
550                }
551                /* check address at 0x48. */
552                if (w83792d_read_value(new_client, W83792D_REG_I2C_ADDR)
553                                != address) {
554                        LEAVE()
555                        goto ERROR1;
556                }
557        }
558
559        /* We have either had a force parameter, or we have already detected
560           the Winbond. Put it now into bank 0 and Vendor ID High Byte */
561        w83792d_write_value(new_client, W83792D_REG_BANK,
562                            (w83792d_read_value(new_client,
563                                                W83792D_REG_BANK) & 0x78) |
564                            0x80);
565
566        /* Determine the chip type. */
567        if (kind <= 0) {
568                /* get vendor ID */
569                val2 = w83792d_read_value(new_client, W83792D_REG_CHIPMAN);
570                if (val2 != 0x5c) {  /* the vendor is NOT Winbond */
571                        LEAVE()
572                        goto ERROR1;
573                }
574                val1 = w83792d_read_value(new_client, W83792D_REG_WCHIPID);
575                if (val1 == 0x7a) {
576                        kind = w83792d;
577                } else {
578                        if (kind == 0)
579                                printk(KERN_WARNING "w83792d: Ignoring "
580                                       "'force' parameter for unknown chip "
581                                       "at adapter %d, address 0x%02x\n",
582                                       i2c_adapter_id(adapter), address);
583                        LEAVE()
584                        goto ERROR1;
585                }
586        }
587
588        if (kind == w83792d) {
589                type_name = "w83792d";
590                client_name = "W83792D chip";
591        } else {
592                printk(KERN_ERR "w83792d: Internal error: unknown kind (%d)?!?",
593                       kind);
594                LEAVE()
595                goto ERROR1;
596        }
597
598        /* Fill in the remaining client fields and put it into the global list */
599        strcpy(new_client->name, client_name);
600        data->type = kind;
601        data->valid = 0;
602        data->has_fan = 0x07; /* at least 3 fan inputs */
603        init_MUTEX(&data->update_lock);
604
605        /* Tell the I2C layer a new client has arrived */
606        if ((err = i2c_attach_client(new_client))) {
607                LEAVE()
608                goto ERROR1;
609        }
610
611        /* attach secondary i2c lm75-like clients */
612        if (!(data->lm75 = kmalloc(2 * sizeof(struct i2c_client),
613                                   GFP_KERNEL))) {
614                err = -ENOMEM;
615                goto ERROR2;
616        }
617        id = i2c_adapter_id(adapter);
618        if(force_subclients[0] == id && force_subclients[1] == address) {
619                if(force_subclients[2] < 0x48 || force_subclients[2] > 0x4b) {
620                        printk(KERN_ERR "w83792d.o: Invalid subclient address %d; must be 0x48-0x4b\n",
621                               force_subclients[2]);
622                        goto ERROR5;
623                }
624                if(force_subclients[3] < 0x4c || force_subclients[3] > 0x4f) {
625                        printk(KERN_ERR "w83792d.o: Invalid subclient address %d; must be 0x4c-0x4f\n",
626                               force_subclients[3]);
627                        goto ERROR5;
628                }
629                w83792d_write_value(new_client,
630                                    W83792D_REG_I2C_SUBADDR,
631                                    0x40 | (force_subclients[2] & 0x03) |
632                                    ((force_subclients[3] & 0x03) <<4));
633                data->lm75[0].addr = force_subclients[2];
634                data->lm75[1].addr = force_subclients[3];
635        } else {
636                val1 = w83792d_read_value(new_client,
637                                          W83792D_REG_I2C_SUBADDR);
638                data->lm75[0].addr = 0x48 + (val1 & 0x07);
639                data->lm75[1].addr = 0x48 + ((val1 >> 4) & 0x07);
640                if (data->lm75[0].addr == data->lm75[1].addr)
641                        printk(KERN_WARNING "w83792d: Subclients have the same "
642                               "address (0x%02x)! Use force_subclients.\n",
643                               data->lm75[0].addr);
644        }
645        client_name = "W83792D subclient";
646
647
648        for (i = 0; i <= 1; i++) {
649                data->lm75[i].data = NULL;      /* store all data in w83792d */
650                data->lm75[i].adapter = adapter;
651                data->lm75[i].driver = &w83792d_driver;
652                data->lm75[i].flags = 0;
653                strcpy(data->lm75[i].name, client_name);
654                if ((err = i2c_attach_client(&(data->lm75[i])))) {
655                        printk(KERN_ERR "w83792d.o: Subclient %d registration at address 0x%x failed.\n",
656                               i, data->lm75[i].addr);
657                        if (i == 1)
658                                goto ERROR6;
659                        goto ERROR5;
660                }
661        }
662
663        /* Read GPIO enable register to check if pins for fan 4,5 are used as
664           GPIO */
665        val1 = w83792d_read_value(new_client, W83792D_REG_GPIO_EN);
666        if (!(val1 & 0x40))
667                data->has_fan |= 0x08;  /* fan 4 */
668        if (!(val1 & 0x20))
669                data->has_fan |= 0x10;  /* fan 5 */
670
671        val1 = w83792d_read_value(new_client, W83792D_REG_PIN);
672        if (val1 & 0x40)
673                data->has_fan |= 0x20;  /* fan 6 */
674        if (val1 & 0x04)
675                data->has_fan |= 0x40;  /* fan 7 */
676
677        /* Register a new directory entry with module sensors */
678        if ((i = i2c_register_entry(new_client, type_name,
679                                    w83792d_dir_table_template, THIS_MODULE)) < 0) {
680                err = i;
681                goto ERROR7;
682        }
683        data->sysctl_id = i;
684
685        /* Initialize the chip */
686        w83792d_init_client(new_client);
687        LEAVE()
688        return 0;
689
690      ERROR7:
691        i2c_detach_client(&
692                          (((struct
693                             w83792d_data *) (new_client->data))->
694                           lm75[1]));
695      ERROR6:
696        i2c_detach_client(&
697                          (((struct
698                             w83792d_data *) (new_client->data))->
699                           lm75[0]));
700      ERROR5:
701        kfree(((struct w83792d_data *) (new_client->data))->lm75);
702      ERROR2:
703        i2c_detach_client(new_client);
704      ERROR1:
705        kfree(data);
706      ERROR0:
707
708        LEAVE()
709        return err;
710}
711
712static int w83792d_detach_client(struct i2c_client *client)
713{
714        int err;
715        struct w83792d_data *data = client->data;
716        ENTER()
717
718        i2c_deregister_entry(data->sysctl_id);
719
720        if ((err = i2c_detach_client(client))) {
721                printk(KERN_ERR "w83792d: Client deregistration failed, client not detached.\n");
722                LEAVE()
723                return err;
724        }
725        i2c_detach_client(&(data->lm75[0]));
726        i2c_detach_client(&(data->lm75[1]));
727        kfree(data->lm75);
728        kfree(data);
729
730        LEAVE()
731        return 0;
732}
733
734/* Read the w83792d register value, only use bank 0 of the 792 chip */
735static inline int
736w83792d_read_value(struct i2c_client *client, u8 reg)
737{
738        return i2c_smbus_read_byte_data(client, reg);
739}
740
741/* Write value into the w83792d registers, only use bank 0 of the 792 chip */
742static inline int
743w83792d_write_value(struct i2c_client *client, u8 reg, u8 value)
744{
745        return i2c_smbus_write_byte_data(client, reg, value);
746}
747
748/* Called when we have found a new W83792D. */
749static void w83792d_init_client(struct i2c_client *client)
750{
751        int temp2_cfg, temp3_cfg;
752        u8 vid_in_b;
753
754        ENTER()
755
756        if (init) {
757                w83792d_write_value(client, W83792D_REG_CONFIG, 0x80);
758        }
759        /* data->vrm = 90; */ /* maybe need to be modified! */
760
761        /* Clear the bit6 of W83792D_REG_VID_IN_B(set it into 0):
762           W83792D_REG_VID_IN_B bit6 = 0: the high/low limit of
763             vin0/vin1 can be modified by user;
764           W83792D_REG_VID_IN_B bit6 = 1: the high/low limit of
765             vin0/vin1 auto-updated, can NOT be modified by user. */
766        vid_in_b = w83792d_read_value(client, W83792D_REG_VID_IN_B);
767        w83792d_write_value(client, W83792D_REG_VID_IN_B,
768                            vid_in_b & 0xbf);
769
770        temp2_cfg = w83792d_read_value(client, W83792D_REG_TEMP_ADD[0][6]);
771        temp3_cfg = w83792d_read_value(client, W83792D_REG_TEMP_ADD[1][6]);
772        w83792d_write_value(client, W83792D_REG_TEMP_ADD[0][6],
773                            temp2_cfg & 0xe6);
774        w83792d_write_value(client, W83792D_REG_TEMP_ADD[1][6],
775                            temp3_cfg & 0xe6);
776
777        /* Start monitoring */
778        w83792d_write_value(client, W83792D_REG_CONFIG, (w83792d_read_value(
779                                client, W83792D_REG_CONFIG) & 0xf7) | 0x01);
780        LEAVE()
781}
782
783static void w83792d_update_client(struct i2c_client *client)
784{
785        struct w83792d_data *data = client->data;
786        int i, j;
787        u8 reg_array_tmp[4], pwm_array_tmp[7], reg_tmp;
788
789        down(&data->update_lock);
790
791        if (time_after(jiffies - data->last_updated, HZ * 3) ||
792            time_before(jiffies, data->last_updated) || !data->valid) {
793                pr_debug(KERN_DEBUG "Starting device update\n");
794
795                /* Update the voltages measured value and limits */
796                for (i = 0; i < 9; i++) {
797                        data->in[i] = w83792d_read_value(client,
798                                                W83792D_REG_IN[i]);
799                        data->in_max[i] = w83792d_read_value(client,
800                                                W83792D_REG_IN_MAX[i]);
801                        data->in_min[i] = w83792d_read_value(client,
802                                                W83792D_REG_IN_MIN[i]);
803                }
804                data->low_bits = w83792d_read_value(client,
805                                                W83792D_REG_LOW_BITS1) +
806                                 (w83792d_read_value(client,
807                                                W83792D_REG_LOW_BITS2) << 8);
808
809                for (i = 0; i < 7; i++) {
810                        /* Update the Fan measured value and limits */
811                        data->fan[i] = w83792d_read_value(client,
812                                                W83792D_REG_FAN[i]);
813                        data->fan_min[i] = w83792d_read_value(client,
814                                                W83792D_REG_FAN_MIN[i]);
815                        /* Update the PWM/DC Value and PWM/DC flag */
816                        pwm_array_tmp[i] = w83792d_read_value(client,
817                                                W83792D_REG_PWM[i]);
818                        data->pwm[i] = pwm_array_tmp[i] & 0x0f;
819                        data->pwm_flag[i] = pwm_array_tmp[i] >> 7;
820                }
821                data->fan_cfg = w83792d_read_value(client, W83792D_REG_FAN_CFG);
822
823                /* Update the Fan Divisor */
824                for (i = 0; i < 4; i++) {
825                        reg_array_tmp[i] = w83792d_read_value(client, W83792D_REG_FAN_DIV[i]);
826                }
827                data->fan_div[0] = reg_array_tmp[0] & 0x07;
828                data->fan_div[1] = (reg_array_tmp[0] >> 4) & 0x07;
829                data->fan_div[2] = reg_array_tmp[1] & 0x07;
830                data->fan_div[3] = (reg_array_tmp[1] >> 4) & 0x07;
831                data->fan_div[4] = reg_array_tmp[2] & 0x07;
832                data->fan_div[5] = (reg_array_tmp[2] >> 4) & 0x07;
833                data->fan_div[6] = reg_array_tmp[3] & 0x07;
834
835                /* Update the Temperature1 measured value and limits */
836                data->temp1[0] = w83792d_read_value(client, W83792D_REG_TEMP1);
837                data->temp1[1] = w83792d_read_value(client, W83792D_REG_TEMP1_OVER);
838                data->temp1[2] = w83792d_read_value(client, W83792D_REG_TEMP1_HYST);
839
840                /* Update the Temperature2/3 measured value and limits */
841                for (i = 0; i < 7; i++) {
842                        data->temp_add[0][i] = w83792d_read_value(client,
843                                                W83792D_REG_TEMP_ADD[0][i]);
844                        data->temp_add[1][i] = w83792d_read_value(client,
845                                                W83792D_REG_TEMP_ADD[1][i]);
846                }
847
848                /* Update the VID */
849                /* i = w83792d_read_value(client, W83792D_REG_FAN_DIV[0]);
850                data->vid = i & 0x0f;
851                data->vid |=
852                    (w83792d_read_value(client, W83792D_REG_CHIPID) & 0x01)
853                    << 4;   */
854
855                /* Update the realtime status */
856                data->alarms = w83792d_read_value(client, W83792D_REG_ALARM1) +
857                        (w83792d_read_value(client, W83792D_REG_ALARM2) << 8) +
858                        (w83792d_read_value(client, W83792D_REG_ALARM3) << 16);
859
860                /* Update CaseOpen status and it's CLR_CHS. */
861                data->chassis[0] = (w83792d_read_value(client,
862                                        W83792D_REG_CASE_OPEN)
863                                    >> 5) & 0x01;
864                data->chassis[1] = (w83792d_read_value(client,
865                                        W83792D_REG_CASE_OPEN_CLR)
866                                    >> 7) & 0x01;
867
868                /* Update Thermal Cruise/Smart Fan I target value */
869                for (i = 0; i < 3; i++) {
870                        data->thermal_cruise[i] =
871                                w83792d_read_value(client,
872                                        W83792D_REG_THERMAL[i]) & 0x7f;
873                }
874
875                /* Update Smart Fan I/II tolerance */
876                reg_tmp = w83792d_read_value(client, W83792D_REG_FAN_TOL[0]);
877                data->fan_tolerance[0] = reg_tmp & 0x0f;
878                data->fan_tolerance[1] = (reg_tmp >> 4) & 0x0f;
879                data->fan_tolerance[2] =
880                    w83792d_read_value(client, W83792D_REG_FAN_TOL[2]) & 0x0f;
881
882                /* Update Smart Fan II temperature points */
883                for (i = 0; i < 3; i++) {
884                        for (j = 0; j < 4; j++) {
885                                data->sf2_points[i][j] = w83792d_read_value(
886                                        client,W83792D_REG_POINTS[i][j]) & 0x7f;
887                        }
888                }
889
890                /* Update Smart Fan II duty cycle levels */
891                for (i = 0; i < 3; i++) {
892                        reg_tmp = w83792d_read_value(client,
893                                                W83792D_REG_LEVELS[i][0]);
894                        data->sf2_levels[i][0] = reg_tmp & 0x0f;
895                        data->sf2_levels[i][1] = (reg_tmp >> 4) & 0x0f;
896                        reg_tmp = w83792d_read_value(client,
897                                                W83792D_REG_LEVELS[i][2]);
898                        data->sf2_levels[i][2] = (reg_tmp >> 4) & 0x0f;
899                        data->sf2_levels[i][3] = reg_tmp & 0x0f;
900                }
901                data->last_updated = jiffies;
902                data->valid = 1;
903#ifdef W83792D_DEBUG
904                w83792d_print_debug(data);
905#endif
906        }
907        up(&data->update_lock);
908}
909
910/* This is a function used to debug the message. */
911#ifdef W83792D_DEBUG
912static void w83792d_print_debug(struct w83792d_data *data)
913{
914        int i=0, j=0;
915        printk(KERN_DEBUG "==========The following is the debug message...========\n");
916        printk(KERN_DEBUG "9 set of Voltages: =====>\n");
917        for (i=0; i<=8; i++) {
918                printk(KERN_DEBUG "vin[%d] is: 0x%x\n", i, data->in[i]);
919                printk(KERN_DEBUG "vin[%d] max is: 0x%x\n", i, data->in_max[i]);
920                printk(KERN_DEBUG "vin[%d] min is: 0x%x\n", i, data->in_min[i]);
921        }
922        printk(KERN_DEBUG "Low Bit1 is: 0x%x\n", data->low_bits & 0xff);
923        printk(KERN_DEBUG "Low Bit2 is: 0x%x\n", data->low_bits >> 8);
924        printk(KERN_DEBUG "7 set of Fan Counts and 3 set of Duty Cycles: =====>\n");
925        printk(KERN_DEBUG "fan_cfg is: 0x%x\n", data->fan_cfg);
926        for (i=0; i<=6; i++) {
927                printk(KERN_DEBUG "fan[%d] is: 0x%x\n", i, data->fan[i]);
928                printk(KERN_DEBUG "fan[%d] min is: 0x%x\n", i, data->fan_min[i]);
929                if (i<3) {
930                        printk(KERN_DEBUG "pwm[%d]     is: 0x%x\n", i, data->pwm[i]);
931                        printk(KERN_DEBUG "pwm_flag[%d] is: 0x%x\n", i, data->pwm_flag[i]);
932                }
933        }
934        printk(KERN_DEBUG "3 set of Temperatures: =====>\n");
935        printk(KERN_DEBUG "temp1 is: 0x%x\n", data->temp1[0]);
936        printk(KERN_DEBUG "temp1 high limit is: 0x%x\n", data->temp1[1]);
937        printk(KERN_DEBUG "temp1 low limit is: 0x%x\n", data->temp1[2]);
938        for (i=0; i<2; i++) {
939                for (j=0; j<7; j++) {
940                        printk(KERN_DEBUG "temp_add[%d][%d] is: 0x%x\n", i, j,
941                                        data->temp_add[i][j]);
942                }
943        }
944        for (i=0; i<=6; i++) {
945                printk(KERN_DEBUG "fan_div[%d] is: 0x%x\n", i, data->fan_div[i]);
946        }
947        printk(KERN_DEBUG "==========End of the debug message...==================\n\n");
948}
949#endif
950
951/* The next few functions are the call-back functions of the /proc/sys and
952   sysctl files. Which function is used is defined in the ctl_table in
953   the extra1 field.
954   Each function must return the magnitude (power of 10 to divide the date
955   with) if it is called with operation==SENSORS_PROC_REAL_INFO. It must
956   put a maximum of *nrels elements in results reflecting the data of this
957   file, and set *nrels to the number it actually put in it, if operation==
958   SENSORS_PROC_REAL_READ. Finally, it must get upto *nrels elements from
959   results and write them to the chip, if operations==SENSORS_PROC_REAL_WRITE.
960   Note that on SENSORS_PROC_REAL_READ, I do not check whether results is
961   large enough (by checking the incoming value of *nrels). This is not very
962   good practice, but as long as you put less than about 5 values in results,
963   you can assume it is large enough. */
964
965/* read/write voltage meaured value and limits */
966static void w83792d_in(struct i2c_client *client, int operation, int ctl_name,
967                        int *nrels_mag, long *results)
968{
969        struct w83792d_data *data = client->data;
970        int nr = ctl_name - W83792D_SYSCTL_IN0;
971
972        /* result[0]: low limit, result[1]: high limit,
973           result[2]: measured value */
974        if (operation == SENSORS_PROC_REAL_INFO)
975                *nrels_mag = 3;
976        else if (operation == SENSORS_PROC_REAL_READ) {
977                w83792d_update_client(client);
978                results[0] = IN_FROM_REG(nr, data->in_min[nr]*4);
979                results[1] = IN_FROM_REG(nr, data->in_max[nr]*4);
980                /* in7 and in8 do not have low bits, but the formula still
981                   works */
982                results[2] = IN_FROM_REG(nr, ((data->in[nr] << 2) |
983                                                ((data->low_bits >> (2 * nr))
984                                                        & 0x03)));
985                *nrels_mag = 3;
986        } else if (operation == SENSORS_PROC_REAL_WRITE) {
987                if (*nrels_mag >= 1) {
988                        /* Write Low limit into register. */
989                        data->in_min[nr] = SENSORS_LIMIT(IN_TO_REG(nr,results[0])/4,
990                                                        0, 255);
991                        w83792d_write_value(client, W83792D_REG_IN_MIN[nr],
992                                                        data->in_min[nr]);
993                }
994                if (*nrels_mag >= 2) {
995                        /* Write High limit into register. */
996                        data->in_max[nr] = SENSORS_LIMIT(IN_TO_REG(nr,results[1])/4,
997                                                        0, 255);
998                        w83792d_write_value(client, W83792D_REG_IN_MAX[nr],
999                                                        data->in_max[nr]);
1000                }
1001        }
1002}
1003
1004/* read/write fan meaured value and limits */
1005static void w83792d_fan(struct i2c_client *client, int operation, int ctl_name,
1006                 int *nrels_mag, long *results)
1007{
1008        struct w83792d_data *data = client->data;
1009        int nr = ctl_name - W83792D_SYSCTL_FAN1;
1010        u8 tmp_reg, tmp_fan_div;
1011
1012        /* result[0]: low limit, result[1]: measured value */
1013        if (operation == SENSORS_PROC_REAL_INFO)
1014                *nrels_mag = 0;
1015        else if (operation == SENSORS_PROC_REAL_READ) {
1016                w83792d_update_client(client);
1017                results[0] = FAN_FROM_REG(data->fan_min[nr],
1018                                  DIV_FROM_REG(data->fan_div[nr]));
1019                /* adjust Fan Divisor, then change RPM */
1020                do {
1021                        w83792d_update_client(client);
1022                        if ((data->fan[nr]>0x50) && (data->fan[nr]<0xff)) {
1023                        /* optimal case. 0x50 and 0xff are experience data */
1024                                results[1] = FAN_FROM_REG(data->fan[nr],
1025                                                DIV_FROM_REG(data->fan_div[nr]));
1026                                break; /* go out of the do-while loop. */
1027                        } else {
1028                                if (((data->fan_div[nr])>=0x07 &&
1029                                        (data->fan[nr])==0xff) ||
1030                                    ((data->fan_div[nr])<=0 &&
1031                                        (data->fan[nr])<0x78)) {
1032                                        results[1] = 0;
1033                                        break;
1034                                } else if ((data->fan_div[nr])<0x07 &&
1035                                         (data->fan[nr])==0xff) {
1036                                        (data->fan_div[nr])++;
1037                                        results[1] = FAN_FROM_REG(data->fan[nr],
1038                                                     DIV_FROM_REG(data->fan_div[nr]));
1039                                } else if ((data->fan_div[nr])>0 &&
1040                                          (data->fan[nr])<0x78) {
1041                                        (data->fan_div[nr])--;
1042                                        results[1] = FAN_FROM_REG(data->fan[nr],
1043                                                     DIV_FROM_REG(data->fan_div[nr]));
1044                                }
1045
1046                                tmp_reg = w83792d_read_value(client,
1047                                                W83792D_REG_FAN_DIV[nr/2]);
1048                                tmp_reg &= (nr%2 == 0) ? 0xf8 : 0x8f;
1049                                tmp_fan_div = (nr%2 == 0) ? (data->fan_div[nr])
1050                                        : (((data->fan_div[nr])<<4)&0x70);
1051                                w83792d_write_value(client,
1052                                                    W83792D_REG_FAN_DIV[nr/2],
1053                                                    tmp_reg|tmp_fan_div);
1054                        }
1055                } while (0);
1056                *nrels_mag = 2;
1057        } else if (operation == SENSORS_PROC_REAL_WRITE) {
1058                if (*nrels_mag >= 1 && (data->has_fan & (1 << nr))) {
1059                        data->fan_min[nr] = FAN_TO_REG(results[0],
1060                                            DIV_FROM_REG(data->fan_div[nr]));
1061                        w83792d_write_value(client,
1062                                             W83792D_REG_FAN_MIN[nr],
1063                                             data->fan_min[nr]);
1064                }
1065        }
1066}
1067
1068/* read/write temperature1 meaured value and limits */
1069static void w83792d_temp(struct i2c_client *client, int operation, int ctl_name,
1070                  int *nrels_mag, long *results)
1071{
1072        struct w83792d_data *data = client->data;
1073
1074        /* result[0]: high limit, result[1]: low limit
1075           result[2]: measured value, the order is different with voltage(in) */
1076        if (operation == SENSORS_PROC_REAL_INFO) {
1077                *nrels_mag = 1;
1078        } else if (operation == SENSORS_PROC_REAL_READ) {
1079                w83792d_update_client(client);
1080                results[0] = TEMP_FROM_REG(data->temp1[1]);
1081                results[1] = TEMP_FROM_REG(data->temp1[2]);
1082                results[2] = TEMP_FROM_REG(data->temp1[0]);
1083                *nrels_mag = 3;
1084        } else if (operation == SENSORS_PROC_REAL_WRITE) {
1085                if (*nrels_mag >= 1) {
1086                        data->temp1[1] = TEMP_TO_REG(results[0]);
1087                        w83792d_write_value(client, W83792D_REG_TEMP1_OVER,
1088                                            data->temp1[1]);
1089                }
1090                if (*nrels_mag >= 2) {
1091                        data->temp1[2] = TEMP_TO_REG(results[1]);
1092                        w83792d_write_value(client, W83792D_REG_TEMP1_HYST,
1093                                            data->temp1[2]);
1094                }
1095        }
1096}
1097
1098/* read/write temperature2,3 meaured value and limits */
1099static void w83792d_temp_add(struct i2c_client *client, int operation,
1100                      int ctl_name, int *nrels_mag, long *results)
1101{
1102        struct w83792d_data *data = client->data;
1103        int nr = ctl_name - W83792D_SYSCTL_TEMP2;
1104        int i=0, j=0;
1105
1106        /* result[0]: high limit, result[1]: low limit
1107           result[2]: measured value, the order is different with voltage(in) */
1108        if (operation == SENSORS_PROC_REAL_INFO)
1109                *nrels_mag = 1;
1110        else if (operation == SENSORS_PROC_REAL_READ) {
1111                w83792d_update_client(client);
1112                for (i=0; i<3; i++) {
1113                        j = (i==0) ? 2 : ((i==1)?0:1);
1114                        if ((data->temp_add[nr][i*2+1]) & 0x80) {
1115                                results[j] = TEMP_FROM_REG(data->temp_add[nr][i*2]) + 5;
1116                        } else {
1117                                results[j] = TEMP_FROM_REG(data->temp_add[nr][i*2]);
1118                        }
1119                }
1120                *nrels_mag = 3;
1121        } else if (operation == SENSORS_PROC_REAL_WRITE) {
1122                if (*nrels_mag >= 1) {
1123                        data->temp_add[nr][2] = TEMP_TO_REG(results[0]);
1124                        w83792d_write_value(client,
1125                                             W83792D_REG_TEMP_ADD[nr][2],
1126                                             data->temp_add[nr][2]);
1127                        if ((results[0]%10) == 0) {
1128                                w83792d_write_value(client,
1129                                        W83792D_REG_TEMP_ADD[nr][3], 0x00);
1130                        } else { /* consider the 0.5 degree */
1131                                w83792d_write_value(client,
1132                                        W83792D_REG_TEMP_ADD[nr][3], 0x80);
1133                        }
1134                }
1135                if (*nrels_mag >= 2) {
1136                        data->temp_add[nr][4] = TEMP_TO_REG(results[1]);
1137                        w83792d_write_value(client,
1138                                             W83792D_REG_TEMP_ADD[nr][4],
1139                                             data->temp_add[nr][4]);
1140                        if ((results[1]%10) == 0) {
1141                                w83792d_write_value(client,
1142                                        W83792D_REG_TEMP_ADD[nr][5], 0x00);
1143                        } else { /* consider the 0.5 degree */
1144                                w83792d_write_value(client,
1145                                        W83792D_REG_TEMP_ADD[nr][5], 0x80);
1146                        }
1147                }
1148        }
1149}
1150
1151/*
1152void w83792d_vid(struct i2c_client *client, int operation, int ctl_name,
1153                 int *nrels_mag, long *results)
1154{
1155        struct w83792d_data *data = client->data;
1156        if (operation == SENSORS_PROC_REAL_INFO)
1157                *nrels_mag = 3;
1158        else if (operation == SENSORS_PROC_REAL_READ) {
1159                w83792d_update_client(client);
1160                results[0] = vid_from_reg(data->vid, data->vrm);
1161                *nrels_mag = 1;
1162        }
1163}
1164
1165void w83792d_vrm(struct i2c_client *client, int operation, int ctl_name,
1166                 int *nrels_mag, long *results)
1167{
1168        struct w83792d_data *data = client->data;
1169        if (operation == SENSORS_PROC_REAL_INFO)
1170                *nrels_mag = 1;
1171        else if (operation == SENSORS_PROC_REAL_READ) {
1172                results[0] = data->vrm;
1173                *nrels_mag = 1;
1174        } else if (operation == SENSORS_PROC_REAL_WRITE) {
1175                if (*nrels_mag >= 1) {
1176                        data->vrm = results[0];
1177                }
1178        }
1179} */
1180
1181/* Read/Write Fan Divisor */
1182static void w83792d_fan_div(struct i2c_client *client, int operation,
1183                     int ctl_name, int *nrels_mag, long *results)
1184{
1185        struct w83792d_data *data = client->data;
1186        int i=0, j=0;
1187        u8 temp_reg=0, k=1, fan_div_reg=0;
1188        u8 tmp_fan_div;
1189
1190        if (operation == SENSORS_PROC_REAL_INFO)
1191                *nrels_mag = 0;
1192        else if (operation == SENSORS_PROC_REAL_READ) {
1193                w83792d_update_client(client);
1194                for (i=0; i<7; i++) {
1195                        results[i] = DIV_FROM_REG(data->fan_div[i]);
1196                }
1197                *nrels_mag = 7;
1198        } else if (operation == SENSORS_PROC_REAL_WRITE) {
1199                if (*nrels_mag < 7) {
1200                        return;
1201                }
1202                for (i=0; i<7; i++) {
1203                        temp_reg = SENSORS_LIMIT(results[i], 1, 128);
1204                        for (k=0,j=0; j<7; j++) {
1205                                temp_reg = temp_reg>>1;
1206                                if (temp_reg == 0)
1207                                        break;
1208                                k++;
1209                        }
1210                        fan_div_reg = w83792d_read_value(client,
1211                                        W83792D_REG_FAN_DIV[i/2]);
1212                        fan_div_reg &= (i%2 == 0) ? 0xf8 : 0x8f;
1213                        tmp_fan_div = (i%2 == 0) ? (k&0x07)
1214                                        : ((k<<4)&0x70);
1215                        w83792d_write_value(client,
1216                                        W83792D_REG_FAN_DIV[i/2],
1217                                        fan_div_reg|tmp_fan_div);
1218                }
1219        }
1220}
1221
1222
1223/* Under Smart Fan I mode: read/write the Fan1/2/3 target temperature */
1224static void w83792d_thermal_cruise(struct i2c_client *client, int operation,
1225                            int ctl_name, int *nrels_mag, long *results)
1226{
1227        struct w83792d_data *data = client->data;
1228        int i=0;
1229        u8 target_tmp=0, target_mask=0;
1230
1231        if (operation == SENSORS_PROC_REAL_INFO)
1232                *nrels_mag = 0;
1233        else if (operation == SENSORS_PROC_REAL_READ) {
1234                w83792d_update_client(client);
1235                for (i=0; i<3; i++) {
1236                        results[i] = data->thermal_cruise[i];
1237                }
1238                *nrels_mag = 3;
1239        } else if (operation == SENSORS_PROC_REAL_WRITE) {
1240                for (i=0; i<3; i++) {
1241                        if (*nrels_mag < (i+1)) {
1242                                return;
1243                        }
1244                        target_tmp = results[i];
1245                        target_tmp = target_tmp & 0x7f;
1246                        target_mask = w83792d_read_value(client,
1247                                                W83792D_REG_THERMAL[i]) & 0x80;
1248                        data->thermal_cruise[i] = SENSORS_LIMIT(target_tmp, 0, 255);
1249                        w83792d_write_value(client, W83792D_REG_THERMAL[i],
1250                                             (data->thermal_cruise[i])|target_mask);
1251                }
1252        }
1253}
1254
1255/* The tolerance of fan1/fan2/fan3, when using Thermal Cruise(Smart Fan I)
1256   or Smart Fan II mode. */
1257static void w83792d_fan_tolerance(struct i2c_client *client, int operation,
1258                                 int ctl_name, int *nrels_mag, long *results)
1259{
1260        struct w83792d_data *data = client->data;
1261        int i=0;
1262        u8 tol_tmp, tol_mask;
1263
1264        if (operation == SENSORS_PROC_REAL_INFO)
1265                *nrels_mag = 0;
1266        else if (operation == SENSORS_PROC_REAL_READ) {
1267                w83792d_update_client(client);
1268                for (i=0; i<3; i++) {
1269                        results[i] = data->fan_tolerance[i];
1270                }
1271                *nrels_mag = 3;
1272        } else if (operation == SENSORS_PROC_REAL_WRITE) {
1273                for (i=0; i<3; i++) {
1274                        if (*nrels_mag < (i+1)) {
1275                                return;
1276                        }
1277                        tol_mask = w83792d_read_value(client,
1278                                W83792D_REG_FAN_TOL[i]) & ((i==1)?0x0f:0xf0);
1279                        tol_tmp = SENSORS_LIMIT(results[i], 0, 15);
1280                        tol_tmp &= 0x0f;
1281                        data->fan_tolerance[i] = tol_tmp;
1282                        if (i==1) {
1283                                tol_tmp <<= 4;
1284                        }
1285                        w83792d_write_value(client, W83792D_REG_FAN_TOL[i],
1286                                             tol_mask|tol_tmp);
1287                }
1288        }
1289}
1290
1291/* Under Smart Fan II mode: read/write the Fan1/2/3 temperature points */
1292static void w83792d_sf2_points(struct i2c_client *client, int operation,
1293                        int ctl_name, int *nrels_mag, long *results)
1294{
1295        struct w83792d_data *data = client->data;
1296        int nr = ctl_name - W83792D_SYSCTL_SF2_POINTS_FAN1;
1297        int j=0;
1298        u8 mask_tmp = 0;
1299
1300        if (operation == SENSORS_PROC_REAL_INFO)
1301                *nrels_mag = 0;
1302        else if (operation == SENSORS_PROC_REAL_READ) {
1303                w83792d_update_client(client);
1304                for (j=0; j<4; j++) {
1305                        results[j] = data->sf2_points[nr][j];
1306                }
1307                *nrels_mag = 4;
1308        } else if (operation == SENSORS_PROC_REAL_WRITE) {
1309                for (j=0; j<4; j++) {
1310                        if (*nrels_mag < (j+1)) {
1311                                return;
1312                        }
1313                        data->sf2_points[nr][j] = SENSORS_LIMIT(results[j],
1314                                                        0, 127);
1315                        mask_tmp = w83792d_read_value(client,
1316                                        W83792D_REG_POINTS[nr][j]) & 0x80;
1317                        w83792d_write_value(client, W83792D_REG_POINTS[nr][j],
1318                                        mask_tmp|data->sf2_points[nr][j]);
1319                }
1320        }
1321}
1322
1323/* Smart Fan II Duty Cycle1/2/3 of Fan1/2/3.
1324   Notice that: The Non-Stop can NOT be modified by user,
1325   because it is related with some physical characters,
1326   usually set by BIOS. User's modification to it may lead to
1327   Fan's stop, then bring danger. */
1328static void w83792d_sf2_levels(struct i2c_client *client, int operation,
1329                        int ctl_name, int *nrels_mag, long *results)
1330{
1331        struct w83792d_data *data = client->data;
1332        int nr = ctl_name - W83792D_SYSCTL_SF2_LEVELS_FAN1;
1333        int j = 0;
1334        u8 mask_tmp = 0, level_tmp = 0;
1335
1336        if (operation == SENSORS_PROC_REAL_INFO)
1337                *nrels_mag = 0;
1338        else if (operation == SENSORS_PROC_REAL_READ) {
1339                w83792d_update_client(client);
1340                for (j=0; j<4; j++) {
1341                        results[j] = (data->sf2_levels[nr][j] * 100) / 15;
1342                }
1343                *nrels_mag = 4;
1344        } else if (operation == SENSORS_PROC_REAL_WRITE) {
1345                for (j=1; j<4; j++) {  /* start with 1: need ignore Non-Stop */
1346                        if (*nrels_mag < j) {
1347                                return;
1348                        }
1349                        data->sf2_levels[nr][j] =
1350                                SENSORS_LIMIT((results[j]*15)/100, 0, 15);
1351                        mask_tmp = w83792d_read_value(client, W83792D_REG_LEVELS[nr][j])
1352                                                & ((j==3) ? 0xf0 : 0x0f);
1353                        if (j==3) {
1354                                level_tmp = data->sf2_levels[nr][j];
1355                        } else {
1356                                level_tmp = data->sf2_levels[nr][j] << 4;
1357                        }
1358                        w83792d_write_value(client, W83792D_REG_LEVELS[nr][j],
1359                                                level_tmp | mask_tmp);
1360                }
1361        }
1362}
1363
1364/* get reatime status of all sensors items: voltage, temp, fan */
1365static void w83792d_alarms(struct i2c_client *client, int operation, int ctl_name,
1366                    int *nrels_mag, long *results)
1367{
1368        struct w83792d_data *data = client->data;
1369        if (operation == SENSORS_PROC_REAL_INFO)
1370                *nrels_mag = 0;
1371        else if (operation == SENSORS_PROC_REAL_READ) {
1372                w83792d_update_client(client);
1373                results[0] = data->alarms;
1374                *nrels_mag = 1;
1375        }
1376}
1377
1378/* Read/Write Chassis status and Reset Chassis. */
1379static void w83792d_chassis(struct i2c_client *client, int operation,
1380                        int ctl_name, int *nrels_mag, long *results)
1381{
1382        struct w83792d_data *data = client->data;
1383        u8 temp1 = 0, temp2 = 0;
1384
1385        if (operation == SENSORS_PROC_REAL_INFO)
1386                *nrels_mag = 0;
1387        else if (operation == SENSORS_PROC_REAL_READ) {
1388                w83792d_update_client(client);
1389                results[0] = data->chassis[0];
1390                results[1] = data->chassis[1];
1391                *nrels_mag = 2;
1392        } else if (operation == SENSORS_PROC_REAL_WRITE) {
1393                data->chassis[1] = SENSORS_LIMIT(results[1], 0 ,1);
1394                temp1 = ((data->chassis[1]) << 7) & 0x80;
1395                temp2 = w83792d_read_value(client,
1396                                W83792D_REG_CASE_OPEN_CLR) & 0x7f;
1397                w83792d_write_value(client,
1398                                W83792D_REG_CASE_OPEN_CLR,
1399                                temp1|temp2);
1400        }
1401}
1402
1403/* Read/Write PWM/DC value of Fan1,Fan2,Fan3, which controls the
1404   Fan Duty Cycle */
1405static void w83792d_pwm(struct i2c_client *client, int operation, int ctl_name,
1406                 int *nrels_mag, long *results)
1407{
1408        struct w83792d_data *data = client->data;
1409        int nr = ctl_name - W83792D_SYSCTL_PWM1;
1410        u8 pwm_mask;
1411
1412        if (operation == SENSORS_PROC_REAL_INFO)
1413                *nrels_mag = 0;
1414        else if (operation == SENSORS_PROC_REAL_READ) {
1415                w83792d_update_client(client);
1416                results[0] = data->pwm[nr];
1417                *nrels_mag = 1;
1418        } else if (operation == SENSORS_PROC_REAL_WRITE) {
1419                data->pwm[nr] = SENSORS_LIMIT(results[0], 0, 15);
1420                pwm_mask = w83792d_read_value(client,W83792D_REG_PWM[nr]) & 0xf0;
1421                w83792d_write_value(client,W83792D_REG_PWM[nr],pwm_mask|data->pwm[nr]);
1422        }
1423}
1424
1425/* Read/Write PWM/DC mode for Fan1,Fan2,Fan3:
1426   1->PWM mode, 0->DC mode */
1427static void w83792d_pwm_flag(struct i2c_client *client, int operation, int ctl_name,
1428                      int *nrels_mag, long *results)
1429{
1430        struct w83792d_data *data = client->data;
1431        int i = 0;
1432        u8 pwm_flag_mask;
1433
1434        if (operation == SENSORS_PROC_REAL_INFO)
1435                *nrels_mag = 0;
1436        else if (operation == SENSORS_PROC_REAL_READ) {
1437                w83792d_update_client(client);
1438                for (i=0; i<3; i++) {
1439                        results[i] = data->pwm_flag[i];
1440                }
1441                *nrels_mag = 3;
1442        } else if (operation == SENSORS_PROC_REAL_WRITE) {
1443                for (i=0; i<3; i++) {
1444                        if (*nrels_mag < (i+1)) {
1445                                return;
1446                        }
1447                        data->pwm_flag[i] = SENSORS_LIMIT(results[i], 0, 1);
1448                        pwm_flag_mask = w83792d_read_value(client,
1449                                                W83792D_REG_PWM[i]) & 0x7f;
1450                        w83792d_write_value(client, W83792D_REG_PWM[i],
1451                                        ((data->pwm_flag[i])<<7)|pwm_flag_mask);
1452                }
1453        }
1454}
1455
1456/* Read/Write Fan mode into:PWM/DC, Thermal Cruise(SmartFanI), SmartFanII
1457   0->PWM/DC mode, 1->Thermal Cruise mode, 2/3->SmartFanII mode */
1458static void w83792d_fan_cfg(struct i2c_client *client, int operation,
1459                     int ctl_name, int *nrels_mag, long *results)
1460{
1461        struct w83792d_data *data = client->data;
1462        u8 temp_cfg1, temp_cfg2, temp_cfg3, temp_cfg4;
1463
1464        if (operation == SENSORS_PROC_REAL_INFO)
1465                *nrels_mag = 0;
1466        else if (operation == SENSORS_PROC_REAL_READ) {
1467                w83792d_update_client(client);
1468                results[0] = (data->fan_cfg) & 0x03;      /* Fan1's Mode */
1469                results[1] = ((data->fan_cfg)>>2) & 0x03; /* Fan2's Mode */
1470                results[2] = ((data->fan_cfg)>>4) & 0x03; /* Fan3's Mode */
1471                *nrels_mag = 3;
1472        } else if (operation == SENSORS_PROC_REAL_WRITE) {
1473                if (*nrels_mag < 3) {
1474                        return;
1475                }
1476                temp_cfg1 = SENSORS_LIMIT(results[0], 0, 3);
1477                temp_cfg2 = SENSORS_LIMIT(results[1], 0, 3) << 2;
1478                temp_cfg3 = SENSORS_LIMIT(results[2], 0, 3) << 4;
1479                temp_cfg4 = w83792d_read_value(client,W83792D_REG_FAN_CFG) & 0xc0;
1480                data->fan_cfg = ((temp_cfg4|temp_cfg3)|temp_cfg2)|temp_cfg1;
1481                w83792d_write_value(client,W83792D_REG_FAN_CFG,data->fan_cfg);
1482        }
1483}
1484
1485static int __init sm_w83792d_init(void)
1486{
1487        ENTER()
1488
1489        printk(KERN_INFO "w83792d version %s (%s)\n", LM_VERSION, LM_DATE);
1490
1491        LEAVE()
1492        return i2c_add_driver(&w83792d_driver);
1493}
1494
1495static void __exit sm_w83792d_exit(void)
1496{
1497        ENTER()
1498
1499        i2c_del_driver(&w83792d_driver);
1500
1501        LEAVE()
1502}
1503
1504
1505MODULE_AUTHOR("Chunhao Huang @ Winbond");
1506MODULE_DESCRIPTION("W83792AD/D driver for linux-2.4");
1507MODULE_LICENSE("GPL");
1508
1509module_init(sm_w83792d_init);
1510module_exit(sm_w83792d_exit);
1511
Note: See TracBrowser for help on using the browser.