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

Revision 3217, 50.7 KB (checked in by khali, 7 years ago)

Fix fan div auto-adjust. Patch from Yuan Mu.

  • 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_set_fan_div(struct i2c_client *client,
310                                int nr, u8 newdiv);
311static void w83792d_fan_div(struct i2c_client *client, int operation,
312                            int ctl_name, int *nrels_mag, long *results);
313static void w83792d_alarms(struct i2c_client *client, int operation,
314                            int ctl_name, int *nrels_mag, long *results);
315static void w83792d_chassis(struct i2c_client *client, int operation,
316                            int ctl_name, int *nrels_mag, long *results);
317static void w83792d_pwm(struct i2c_client *client, int operation,
318                        int ctl_name, int *nrels_mag, long *results);
319static void w83792d_pwm_flag(struct i2c_client *client, int operation,
320                             int ctl_name, int *nrels_mag, long *results);
321static void w83792d_fan_cfg(struct i2c_client *client, int operation,
322                            int ctl_name, int *nrels_mag, long *results);
323static void w83792d_thermal_cruise(struct i2c_client *client, int operation,
324                                   int ctl_name, int *nrels_mag, long *results);
325static void w83792d_fan_tolerance(struct i2c_client *client, int operation,
326                                  int ctl_name, int *nrels_mag, long *results);
327static void w83792d_sf2_points(struct i2c_client *client, int operation,
328                                int ctl_name, int *nrels_mag, long *results);
329static void w83792d_sf2_levels(struct i2c_client *client, int operation,
330                                int ctl_name, int *nrels_mag, long *results);
331
332static struct i2c_driver w83792d_driver = {
333        .name           = "W83792D sensor driver",
334        .flags          = I2C_DF_NOTIFY,
335        .attach_adapter = w83792d_attach_adapter,
336        .detach_client  = w83792d_detach_client,
337};
338
339/* The /proc/sys entries */
340/* -- SENSORS SYSCTL START -- */
341
342#define W83792D_SYSCTL_IN0 1000
343#define W83792D_SYSCTL_IN1 1001
344#define W83792D_SYSCTL_IN2 1002
345#define W83792D_SYSCTL_IN3 1003
346#define W83792D_SYSCTL_IN4 1004
347#define W83792D_SYSCTL_IN5 1005
348#define W83792D_SYSCTL_IN6 1006
349#define W83792D_SYSCTL_IN7 1007
350#define W83792D_SYSCTL_IN8 1008
351#define W83792D_SYSCTL_FAN1 1101
352#define W83792D_SYSCTL_FAN2 1102
353#define W83792D_SYSCTL_FAN3 1103
354#define W83792D_SYSCTL_FAN4 1104
355#define W83792D_SYSCTL_FAN5 1105
356#define W83792D_SYSCTL_FAN6 1106
357#define W83792D_SYSCTL_FAN7 1107
358
359#define W83792D_SYSCTL_TEMP1 1200
360#define W83792D_SYSCTL_TEMP2 1201
361#define W83792D_SYSCTL_TEMP3 1202
362/*#define W83792D_SYSCTL_VID 1300
363#define W83792D_SYSCTL_VRM 1301*/
364#define W83792D_SYSCTL_PWM_FLAG 1400
365#define W83792D_SYSCTL_PWM1 1401
366#define W83792D_SYSCTL_PWM2 1402
367#define W83792D_SYSCTL_PWM3 1403
368#define W83792D_SYSCTL_FAN_CFG 1500     /* control Fan Mode */
369#define W83792D_SYSCTL_FAN_DIV 1501
370#define W83792D_SYSCTL_CHASSIS 1502     /* control Case Open */
371#define W83792D_SYSCTL_ALARMS 1503
372
373#define W83792D_SYSCTL_THERMAL_CRUISE 1600      /* Smart Fan I: target value */
374#define W83792D_SYSCTL_FAN_TOLERANCE 1601       /* Smart Fan I/II: tolerance */
375#define W83792D_SYSCTL_SF2_POINTS_FAN1 1602     /* Smart Fan II: Fan1 points */
376#define W83792D_SYSCTL_SF2_POINTS_FAN2 1603     /* Smart Fan II: Fan2 points */
377#define W83792D_SYSCTL_SF2_POINTS_FAN3 1604     /* Smart Fan II: Fan3 points */
378#define W83792D_SYSCTL_SF2_LEVELS_FAN1 1605     /* Smart Fan II: Fan1 levels */
379#define W83792D_SYSCTL_SF2_LEVELS_FAN2 1606     /* Smart Fan II: Fan2 levels */
380#define W83792D_SYSCTL_SF2_LEVELS_FAN3 1607     /* Smart Fan II: Fan3 levels */
381
382#define W83792D_ALARM_IN0 0x0001
383#define W83792D_ALARM_IN1 0x0002
384#define W83792D_ALARM_IN2 0x0100
385#define W83792D_ALARM_IN3 0x0200
386#define W83792D_ALARM_IN4 0x0400
387#define W83792D_ALARM_IN5 0x0800
388#define W83792D_ALARM_IN6 0x1000
389#define W83792D_ALARM_IN7 0x80000
390#define W83792D_ALARM_IN8 0x100000
391#define W83792D_ALARM_TEMP1 0x0004
392#define W83792D_ALARM_TEMP2 0x0008
393#define W83792D_ALARM_TEMP3 0x0010
394#define W83792D_ALARM_FAN1 0x0020
395#define W83792D_ALARM_FAN2 0x0040
396#define W83792D_ALARM_FAN3 0x0080
397#define W83792D_ALARM_FAN4 0x200000
398#define W83792D_ALARM_FAN5 0x400000
399#define W83792D_ALARM_FAN6 0x800000
400#define W83792D_ALARM_FAN7 0x8000
401
402/* -- SENSORS SYSCTL END -- */
403
404/* These files are created for detected chip,
405   W83792D has 9 voltages 7 fans and 3 temperatures. */
406static ctl_table w83792d_dir_table_template[] =
407{
408        {W83792D_SYSCTL_IN0, "in0", NULL, 0, 0644, NULL, &i2c_proc_real,
409         &i2c_sysctl_real, NULL, &w83792d_in},
410        {W83792D_SYSCTL_IN1, "in1", NULL, 0, 0644, NULL, &i2c_proc_real,
411         &i2c_sysctl_real, NULL, &w83792d_in},
412        {W83792D_SYSCTL_IN2, "in2", NULL, 0, 0644, NULL, &i2c_proc_real,
413         &i2c_sysctl_real, NULL, &w83792d_in},
414        {W83792D_SYSCTL_IN3, "in3", NULL, 0, 0644, NULL, &i2c_proc_real,
415         &i2c_sysctl_real, NULL, &w83792d_in},
416        {W83792D_SYSCTL_IN4, "in4", NULL, 0, 0644, NULL, &i2c_proc_real,
417         &i2c_sysctl_real, NULL, &w83792d_in},
418        {W83792D_SYSCTL_IN5, "in5", NULL, 0, 0644, NULL, &i2c_proc_real,
419         &i2c_sysctl_real, NULL, &w83792d_in},
420        {W83792D_SYSCTL_IN6, "in6", NULL, 0, 0644, NULL, &i2c_proc_real,
421         &i2c_sysctl_real, NULL, &w83792d_in},
422        {W83792D_SYSCTL_IN7, "in7", NULL, 0, 0644, NULL, &i2c_proc_real,
423         &i2c_sysctl_real, NULL, &w83792d_in},
424        {W83792D_SYSCTL_IN8, "in8", NULL, 0, 0644, NULL, &i2c_proc_real,
425         &i2c_sysctl_real, NULL, &w83792d_in},
426        {W83792D_SYSCTL_FAN1, "fan1", NULL, 0, 0644, NULL, &i2c_proc_real,
427         &i2c_sysctl_real, NULL, &w83792d_fan},
428        {W83792D_SYSCTL_FAN2, "fan2", NULL, 0, 0644, NULL, &i2c_proc_real,
429         &i2c_sysctl_real, NULL, &w83792d_fan},
430        {W83792D_SYSCTL_FAN3, "fan3", NULL, 0, 0644, NULL, &i2c_proc_real,
431         &i2c_sysctl_real, NULL, &w83792d_fan},
432        {W83792D_SYSCTL_FAN4, "fan4", NULL, 0, 0644, NULL, &i2c_proc_real,
433         &i2c_sysctl_real, NULL, &w83792d_fan},
434        {W83792D_SYSCTL_FAN5, "fan5", NULL, 0, 0644, NULL, &i2c_proc_real,
435         &i2c_sysctl_real, NULL, &w83792d_fan},
436        {W83792D_SYSCTL_FAN6, "fan6", NULL, 0, 0644, NULL, &i2c_proc_real,
437         &i2c_sysctl_real, NULL, &w83792d_fan},
438        {W83792D_SYSCTL_FAN7, "fan7", NULL, 0, 0644, NULL, &i2c_proc_real,
439         &i2c_sysctl_real, NULL, &w83792d_fan},
440        {W83792D_SYSCTL_TEMP1, "temp1", NULL, 0, 0644, NULL, &i2c_proc_real,
441         &i2c_sysctl_real, NULL, &w83792d_temp},
442        {W83792D_SYSCTL_TEMP2, "temp2", NULL, 0, 0644, NULL, &i2c_proc_real,
443         &i2c_sysctl_real, NULL, &w83792d_temp_add},
444        {W83792D_SYSCTL_TEMP3, "temp3", NULL, 0, 0644, NULL, &i2c_proc_real,
445         &i2c_sysctl_real, NULL, &w83792d_temp_add},
446        /*{W83792D_SYSCTL_VID, "vid", NULL, 0, 0444, NULL, &i2c_proc_real,
447         &i2c_sysctl_real, NULL, &w83792d_vid}, */
448        {W83792D_SYSCTL_FAN_DIV, "fan_div", NULL, 0, 0444, NULL, &i2c_proc_real,
449         &i2c_sysctl_real, NULL, &w83792d_fan_div},
450        {W83792D_SYSCTL_ALARMS, "alarms", NULL, 0, 0644, NULL,
451         &i2c_proc_real, &i2c_sysctl_real, NULL, &w83792d_alarms},
452        {W83792D_SYSCTL_CHASSIS, "chassis", NULL, 0, 0644, NULL,
453         &i2c_proc_real, &i2c_sysctl_real, NULL, &w83792d_chassis},
454        {W83792D_SYSCTL_PWM1, "pwm1", NULL, 0, 0644, NULL, &i2c_proc_real,
455         &i2c_sysctl_real, NULL, &w83792d_pwm},
456        {W83792D_SYSCTL_PWM2, "pwm2", NULL, 0, 0644, NULL, &i2c_proc_real,
457         &i2c_sysctl_real, NULL, &w83792d_pwm},
458        {W83792D_SYSCTL_PWM3, "pwm3", NULL, 0, 0644, NULL, &i2c_proc_real,
459         &i2c_sysctl_real, NULL, &w83792d_pwm},
460        {W83792D_SYSCTL_PWM_FLAG, "pwm_flag", NULL, 0, 0644, NULL, &i2c_proc_real,
461         &i2c_sysctl_real, NULL, &w83792d_pwm_flag},
462        {W83792D_SYSCTL_FAN_CFG, "fan_cfg", NULL, 0, 0644, NULL, &i2c_proc_real,
463         &i2c_sysctl_real, NULL, &w83792d_fan_cfg},
464        /*{W83792D_SYSCTL_VRM, "vrm", NULL, 0, 0644, NULL, &i2c_proc_real,
465         &i2c_sysctl_real, NULL, &w83792d_vrm},  */
466        {W83792D_SYSCTL_THERMAL_CRUISE, "thermal_cruise", NULL, 0, 0644, NULL,
467         &i2c_proc_real, &i2c_sysctl_real, NULL, &w83792d_thermal_cruise},
468        {W83792D_SYSCTL_FAN_TOLERANCE, "fan_tolerance", NULL, 0, 0644,
469         NULL, &i2c_proc_real, &i2c_sysctl_real, NULL, &w83792d_fan_tolerance},
470        {W83792D_SYSCTL_SF2_POINTS_FAN1, "sf2_points_fan1", NULL, 0, 0644, NULL,
471         &i2c_proc_real, &i2c_sysctl_real, NULL, &w83792d_sf2_points},
472        {W83792D_SYSCTL_SF2_POINTS_FAN2, "sf2_points_fan2", NULL, 0, 0644, NULL,
473         &i2c_proc_real, &i2c_sysctl_real, NULL, &w83792d_sf2_points},
474        {W83792D_SYSCTL_SF2_POINTS_FAN3, "sf2_points_fan3", NULL, 0, 0644, NULL,
475         &i2c_proc_real, &i2c_sysctl_real, NULL, &w83792d_sf2_points},
476        {W83792D_SYSCTL_SF2_LEVELS_FAN1, "sf2_levels_fan1", NULL, 0, 0644, NULL,
477         &i2c_proc_real, &i2c_sysctl_real, NULL, &w83792d_sf2_levels},
478        {W83792D_SYSCTL_SF2_LEVELS_FAN2, "sf2_levels_fan2", NULL, 0, 0644, NULL,
479         &i2c_proc_real, &i2c_sysctl_real, NULL, &w83792d_sf2_levels},
480        {W83792D_SYSCTL_SF2_LEVELS_FAN3, "sf2_levels_fan3", NULL, 0, 0644, NULL,
481         &i2c_proc_real, &i2c_sysctl_real, NULL, &w83792d_sf2_levels},
482        {0}
483};
484
485/* This function is called when:
486     * w83792d_driver is inserted (when this module is loaded), for each
487       available adapter
488     * when a new adapter is inserted (and w83792d_driver is still present) */
489static int w83792d_attach_adapter(struct i2c_adapter *adapter)
490{
491        int i_tmp;
492        ENTER()
493        i_tmp = i2c_detect(adapter, &addr_data, w83792d_detect);
494        LEAVE()
495        return i_tmp;
496}
497
498static int w83792d_detect(struct i2c_adapter *adapter, int address,
499                          unsigned short flags, int kind)
500{
501        int i, val1 = 0, val2 = 0, id;
502        struct i2c_client *new_client;
503        struct w83792d_data *data;
504        int err = 0;
505        const char *type_name = "";
506        const char *client_name = "";
507
508        ENTER()
509
510        if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA)) {
511                LEAVE()
512                goto ERROR0;
513        }
514
515        /* OK. For now, we presume we have a valid client. We now create the
516           client structure, even though we cannot fill it completely yet.
517           But it allows us to access w83792d_{read,write}_value. */
518
519        if (!(data = kmalloc(sizeof(struct w83792d_data), GFP_KERNEL))) {
520                printk(KERN_ERR "w83792d: Out of memory in w83792d_detect (new_client).\n");
521                err = -ENOMEM;
522                LEAVE()
523                goto ERROR0;
524        }
525
526        new_client = &data->client;
527        new_client->addr = address;
528        new_client->data = data;
529        new_client->adapter = adapter;
530        new_client->driver = &w83792d_driver;
531        new_client->flags = 0;
532
533        /* Now, we do the remaining detection. */
534        if (kind < 0) {
535                if (w83792d_read_value(new_client, W83792D_REG_CONFIG)&0x80) {
536                        LEAVE()
537                        goto ERROR1;
538                }
539                val1 = w83792d_read_value(new_client, W83792D_REG_BANK);
540                val2 = w83792d_read_value(new_client, W83792D_REG_CHIPMAN);
541#ifdef W83792D_DEBUG
542                printk(KERN_DEBUG "w83792d: val1 is: %d, val2 is: %d\n",
543                                                val1, val2);
544#endif
545                /* Check for Winbond ID if in bank 0 */
546                if (!(val1 & 0x07)) {  /* is Bank0 */
547                        if (((!(val1 & 0x80)) && (val2 != 0xa3)) ||
548                             ((val1 & 0x80) && (val2 != 0x5c))) {
549                                LEAVE()
550                                goto ERROR1;
551                        }
552                }
553                /* check address at 0x48. */
554                if (w83792d_read_value(new_client, W83792D_REG_I2C_ADDR)
555                                != address) {
556                        LEAVE()
557                        goto ERROR1;
558                }
559        }
560
561        /* We have either had a force parameter, or we have already detected
562           the Winbond. Put it now into bank 0 and Vendor ID High Byte */
563        w83792d_write_value(new_client, W83792D_REG_BANK,
564                            (w83792d_read_value(new_client,
565                                                W83792D_REG_BANK) & 0x78) |
566                            0x80);
567
568        /* Determine the chip type. */
569        if (kind <= 0) {
570                /* get vendor ID */
571                val2 = w83792d_read_value(new_client, W83792D_REG_CHIPMAN);
572                if (val2 != 0x5c) {  /* the vendor is NOT Winbond */
573                        LEAVE()
574                        goto ERROR1;
575                }
576                val1 = w83792d_read_value(new_client, W83792D_REG_WCHIPID);
577                if (val1 == 0x7a) {
578                        kind = w83792d;
579                } else {
580                        if (kind == 0)
581                                printk(KERN_WARNING "w83792d: Ignoring "
582                                       "'force' parameter for unknown chip "
583                                       "at adapter %d, address 0x%02x\n",
584                                       i2c_adapter_id(adapter), address);
585                        LEAVE()
586                        goto ERROR1;
587                }
588        }
589
590        if (kind == w83792d) {
591                type_name = "w83792d";
592                client_name = "W83792D chip";
593        } else {
594                printk(KERN_ERR "w83792d: Internal error: unknown kind (%d)?!?",
595                       kind);
596                LEAVE()
597                goto ERROR1;
598        }
599
600        /* Fill in the remaining client fields and put it into the global list */
601        strcpy(new_client->name, client_name);
602        data->type = kind;
603        data->valid = 0;
604        data->has_fan = 0x07; /* at least 3 fan inputs */
605        init_MUTEX(&data->update_lock);
606
607        /* Tell the I2C layer a new client has arrived */
608        if ((err = i2c_attach_client(new_client))) {
609                LEAVE()
610                goto ERROR1;
611        }
612
613        /* attach secondary i2c lm75-like clients */
614        if (!(data->lm75 = kmalloc(2 * sizeof(struct i2c_client),
615                                   GFP_KERNEL))) {
616                err = -ENOMEM;
617                goto ERROR2;
618        }
619        id = i2c_adapter_id(adapter);
620        if(force_subclients[0] == id && force_subclients[1] == address) {
621                if(force_subclients[2] < 0x48 || force_subclients[2] > 0x4b) {
622                        printk(KERN_ERR "w83792d.o: Invalid subclient address %d; must be 0x48-0x4b\n",
623                               force_subclients[2]);
624                        goto ERROR5;
625                }
626                if(force_subclients[3] < 0x4c || force_subclients[3] > 0x4f) {
627                        printk(KERN_ERR "w83792d.o: Invalid subclient address %d; must be 0x4c-0x4f\n",
628                               force_subclients[3]);
629                        goto ERROR5;
630                }
631                w83792d_write_value(new_client,
632                                    W83792D_REG_I2C_SUBADDR,
633                                    0x40 | (force_subclients[2] & 0x03) |
634                                    ((force_subclients[3] & 0x03) <<4));
635                data->lm75[0].addr = force_subclients[2];
636                data->lm75[1].addr = force_subclients[3];
637        } else {
638                val1 = w83792d_read_value(new_client,
639                                          W83792D_REG_I2C_SUBADDR);
640                data->lm75[0].addr = 0x48 + (val1 & 0x07);
641                data->lm75[1].addr = 0x48 + ((val1 >> 4) & 0x07);
642                if (data->lm75[0].addr == data->lm75[1].addr)
643                        printk(KERN_WARNING "w83792d: Subclients have the same "
644                               "address (0x%02x)! Use force_subclients.\n",
645                               data->lm75[0].addr);
646        }
647        client_name = "W83792D subclient";
648
649
650        for (i = 0; i <= 1; i++) {
651                data->lm75[i].data = NULL;      /* store all data in w83792d */
652                data->lm75[i].adapter = adapter;
653                data->lm75[i].driver = &w83792d_driver;
654                data->lm75[i].flags = 0;
655                strcpy(data->lm75[i].name, client_name);
656                if ((err = i2c_attach_client(&(data->lm75[i])))) {
657                        printk(KERN_ERR "w83792d.o: Subclient %d registration at address 0x%x failed.\n",
658                               i, data->lm75[i].addr);
659                        if (i == 1)
660                                goto ERROR6;
661                        goto ERROR5;
662                }
663        }
664
665        /* Read GPIO enable register to check if pins for fan 4,5 are used as
666           GPIO */
667        val1 = w83792d_read_value(new_client, W83792D_REG_GPIO_EN);
668        if (!(val1 & 0x40))
669                data->has_fan |= 0x08;  /* fan 4 */
670        if (!(val1 & 0x20))
671                data->has_fan |= 0x10;  /* fan 5 */
672
673        val1 = w83792d_read_value(new_client, W83792D_REG_PIN);
674        if (val1 & 0x40)
675                data->has_fan |= 0x20;  /* fan 6 */
676        if (val1 & 0x04)
677                data->has_fan |= 0x40;  /* fan 7 */
678
679        /* Register a new directory entry with module sensors */
680        if ((i = i2c_register_entry(new_client, type_name,
681                                    w83792d_dir_table_template, THIS_MODULE)) < 0) {
682                err = i;
683                goto ERROR7;
684        }
685        data->sysctl_id = i;
686
687        /* Initialize the chip */
688        w83792d_init_client(new_client);
689        LEAVE()
690        return 0;
691
692      ERROR7:
693        i2c_detach_client(&
694                          (((struct
695                             w83792d_data *) (new_client->data))->
696                           lm75[1]));
697      ERROR6:
698        i2c_detach_client(&
699                          (((struct
700                             w83792d_data *) (new_client->data))->
701                           lm75[0]));
702      ERROR5:
703        kfree(((struct w83792d_data *) (new_client->data))->lm75);
704      ERROR2:
705        i2c_detach_client(new_client);
706      ERROR1:
707        kfree(data);
708      ERROR0:
709
710        LEAVE()
711        return err;
712}
713
714static int w83792d_detach_client(struct i2c_client *client)
715{
716        int err;
717        struct w83792d_data *data = client->data;
718        ENTER()
719
720        i2c_deregister_entry(data->sysctl_id);
721
722        if ((err = i2c_detach_client(client))) {
723                printk(KERN_ERR "w83792d: Client deregistration failed, client not detached.\n");
724                LEAVE()
725                return err;
726        }
727        i2c_detach_client(&(data->lm75[0]));
728        i2c_detach_client(&(data->lm75[1]));
729        kfree(data->lm75);
730        kfree(data);
731
732        LEAVE()
733        return 0;
734}
735
736/* Read the w83792d register value, only use bank 0 of the 792 chip */
737static inline int
738w83792d_read_value(struct i2c_client *client, u8 reg)
739{
740        return i2c_smbus_read_byte_data(client, reg);
741}
742
743/* Write value into the w83792d registers, only use bank 0 of the 792 chip */
744static inline int
745w83792d_write_value(struct i2c_client *client, u8 reg, u8 value)
746{
747        return i2c_smbus_write_byte_data(client, reg, value);
748}
749
750/* Called when we have found a new W83792D. */
751static void w83792d_init_client(struct i2c_client *client)
752{
753        int temp2_cfg, temp3_cfg;
754        u8 vid_in_b;
755
756        ENTER()
757
758        if (init) {
759                w83792d_write_value(client, W83792D_REG_CONFIG, 0x80);
760        }
761        /* data->vrm = 90; */ /* maybe need to be modified! */
762
763        /* Clear the bit6 of W83792D_REG_VID_IN_B(set it into 0):
764           W83792D_REG_VID_IN_B bit6 = 0: the high/low limit of
765             vin0/vin1 can be modified by user;
766           W83792D_REG_VID_IN_B bit6 = 1: the high/low limit of
767             vin0/vin1 auto-updated, can NOT be modified by user. */
768        vid_in_b = w83792d_read_value(client, W83792D_REG_VID_IN_B);
769        w83792d_write_value(client, W83792D_REG_VID_IN_B,
770                            vid_in_b & 0xbf);
771
772        temp2_cfg = w83792d_read_value(client, W83792D_REG_TEMP_ADD[0][6]);
773        temp3_cfg = w83792d_read_value(client, W83792D_REG_TEMP_ADD[1][6]);
774        w83792d_write_value(client, W83792D_REG_TEMP_ADD[0][6],
775                            temp2_cfg & 0xe6);
776        w83792d_write_value(client, W83792D_REG_TEMP_ADD[1][6],
777                            temp3_cfg & 0xe6);
778
779        /* Start monitoring */
780        w83792d_write_value(client, W83792D_REG_CONFIG, (w83792d_read_value(
781                                client, W83792D_REG_CONFIG) & 0xf7) | 0x01);
782        LEAVE()
783}
784
785static void w83792d_update_client(struct i2c_client *client)
786{
787        struct w83792d_data *data = client->data;
788        int i, j;
789        u8 reg_array_tmp[4], pwm_array_tmp[7], reg_tmp;
790
791        down(&data->update_lock);
792
793        if (time_after(jiffies - data->last_updated, HZ * 3) ||
794            time_before(jiffies, data->last_updated) || !data->valid) {
795                pr_debug(KERN_DEBUG "Starting device update\n");
796
797                /* Update the voltages measured value and limits */
798                for (i = 0; i < 9; i++) {
799                        data->in[i] = w83792d_read_value(client,
800                                                W83792D_REG_IN[i]);
801                        data->in_max[i] = w83792d_read_value(client,
802                                                W83792D_REG_IN_MAX[i]);
803                        data->in_min[i] = w83792d_read_value(client,
804                                                W83792D_REG_IN_MIN[i]);
805                }
806                data->low_bits = w83792d_read_value(client,
807                                                W83792D_REG_LOW_BITS1) +
808                                 (w83792d_read_value(client,
809                                                W83792D_REG_LOW_BITS2) << 8);
810
811                for (i = 0; i < 7; i++) {
812                        /* Update the Fan measured value and limits */
813                        data->fan[i] = w83792d_read_value(client,
814                                                W83792D_REG_FAN[i]);
815                        data->fan_min[i] = w83792d_read_value(client,
816                                                W83792D_REG_FAN_MIN[i]);
817                        /* Update the PWM/DC Value and PWM/DC flag */
818                        pwm_array_tmp[i] = w83792d_read_value(client,
819                                                W83792D_REG_PWM[i]);
820                        data->pwm[i] = pwm_array_tmp[i] & 0x0f;
821                        data->pwm_flag[i] = pwm_array_tmp[i] >> 7;
822                }
823                data->fan_cfg = w83792d_read_value(client, W83792D_REG_FAN_CFG);
824
825                /* Update the Fan Divisor */
826                for (i = 0; i < 4; i++) {
827                        reg_array_tmp[i] = w83792d_read_value(client, W83792D_REG_FAN_DIV[i]);
828                }
829                data->fan_div[0] = reg_array_tmp[0] & 0x07;
830                data->fan_div[1] = (reg_array_tmp[0] >> 4) & 0x07;
831                data->fan_div[2] = reg_array_tmp[1] & 0x07;
832                data->fan_div[3] = (reg_array_tmp[1] >> 4) & 0x07;
833                data->fan_div[4] = reg_array_tmp[2] & 0x07;
834                data->fan_div[5] = (reg_array_tmp[2] >> 4) & 0x07;
835                data->fan_div[6] = reg_array_tmp[3] & 0x07;
836
837                for (i = 0; i < 7; i++) {
838                        if (!(data->has_fan & (1 << i)))
839                                continue;
840                        if (data->fan[i] == 0xff && data->fan_div[i] < 7)
841                                w83792d_set_fan_div(client, i, 7);
842                        else if (data->fan[i] < 0x70 && data->fan_div[i] > 0) {
843                                w83792d_set_fan_div(client, i,
844                                                        data->fan_div[i] - 1);
845                        } else if (data->fan[i] > 0xf8 &&
846                                                data->fan_div[i] < 7) {
847                                w83792d_set_fan_div(client, i,
848                                                        data->fan_div[i] + 1);
849                        }
850                }
851
852                /* Update the Temperature1 measured value and limits */
853                data->temp1[0] = w83792d_read_value(client, W83792D_REG_TEMP1);
854                data->temp1[1] = w83792d_read_value(client, W83792D_REG_TEMP1_OVER);
855                data->temp1[2] = w83792d_read_value(client, W83792D_REG_TEMP1_HYST);
856
857                /* Update the Temperature2/3 measured value and limits */
858                for (i = 0; i < 7; i++) {
859                        data->temp_add[0][i] = w83792d_read_value(client,
860                                                W83792D_REG_TEMP_ADD[0][i]);
861                        data->temp_add[1][i] = w83792d_read_value(client,
862                                                W83792D_REG_TEMP_ADD[1][i]);
863                }
864
865                /* Update the VID */
866                /* i = w83792d_read_value(client, W83792D_REG_FAN_DIV[0]);
867                data->vid = i & 0x0f;
868                data->vid |=
869                    (w83792d_read_value(client, W83792D_REG_CHIPID) & 0x01)
870                    << 4;   */
871
872                /* Update the realtime status */
873                data->alarms = w83792d_read_value(client, W83792D_REG_ALARM1) +
874                        (w83792d_read_value(client, W83792D_REG_ALARM2) << 8) +
875                        (w83792d_read_value(client, W83792D_REG_ALARM3) << 16);
876
877                /* Update CaseOpen status and it's CLR_CHS. */
878                data->chassis[0] = (w83792d_read_value(client,
879                                        W83792D_REG_CASE_OPEN)
880                                    >> 5) & 0x01;
881                data->chassis[1] = (w83792d_read_value(client,
882                                        W83792D_REG_CASE_OPEN_CLR)
883                                    >> 7) & 0x01;
884
885                /* Update Thermal Cruise/Smart Fan I target value */
886                for (i = 0; i < 3; i++) {
887                        data->thermal_cruise[i] =
888                                w83792d_read_value(client,
889                                        W83792D_REG_THERMAL[i]) & 0x7f;
890                }
891
892                /* Update Smart Fan I/II tolerance */
893                reg_tmp = w83792d_read_value(client, W83792D_REG_FAN_TOL[0]);
894                data->fan_tolerance[0] = reg_tmp & 0x0f;
895                data->fan_tolerance[1] = (reg_tmp >> 4) & 0x0f;
896                data->fan_tolerance[2] =
897                    w83792d_read_value(client, W83792D_REG_FAN_TOL[2]) & 0x0f;
898
899                /* Update Smart Fan II temperature points */
900                for (i = 0; i < 3; i++) {
901                        for (j = 0; j < 4; j++) {
902                                data->sf2_points[i][j] = w83792d_read_value(
903                                        client,W83792D_REG_POINTS[i][j]) & 0x7f;
904                        }
905                }
906
907                /* Update Smart Fan II duty cycle levels */
908                for (i = 0; i < 3; i++) {
909                        reg_tmp = w83792d_read_value(client,
910                                                W83792D_REG_LEVELS[i][0]);
911                        data->sf2_levels[i][0] = reg_tmp & 0x0f;
912                        data->sf2_levels[i][1] = (reg_tmp >> 4) & 0x0f;
913                        reg_tmp = w83792d_read_value(client,
914                                                W83792D_REG_LEVELS[i][2]);
915                        data->sf2_levels[i][2] = (reg_tmp >> 4) & 0x0f;
916                        data->sf2_levels[i][3] = reg_tmp & 0x0f;
917                }
918                data->last_updated = jiffies;
919                data->valid = 1;
920#ifdef W83792D_DEBUG
921                w83792d_print_debug(data);
922#endif
923        }
924        up(&data->update_lock);
925}
926
927/* This is a function used to debug the message. */
928#ifdef W83792D_DEBUG
929static void w83792d_print_debug(struct w83792d_data *data)
930{
931        int i=0, j=0;
932        printk(KERN_DEBUG "==========The following is the debug message...========\n");
933        printk(KERN_DEBUG "9 set of Voltages: =====>\n");
934        for (i=0; i<=8; i++) {
935                printk(KERN_DEBUG "vin[%d] is: 0x%x\n", i, data->in[i]);
936                printk(KERN_DEBUG "vin[%d] max is: 0x%x\n", i, data->in_max[i]);
937                printk(KERN_DEBUG "vin[%d] min is: 0x%x\n", i, data->in_min[i]);
938        }
939        printk(KERN_DEBUG "Low Bit1 is: 0x%x\n", data->low_bits & 0xff);
940        printk(KERN_DEBUG "Low Bit2 is: 0x%x\n", data->low_bits >> 8);
941        printk(KERN_DEBUG "7 set of Fan Counts and 3 set of Duty Cycles: =====>\n");
942        printk(KERN_DEBUG "fan_cfg is: 0x%x\n", data->fan_cfg);
943        for (i=0; i<=6; i++) {
944                printk(KERN_DEBUG "fan[%d] is: 0x%x\n", i, data->fan[i]);
945                printk(KERN_DEBUG "fan[%d] min is: 0x%x\n", i, data->fan_min[i]);
946                if (i<3) {
947                        printk(KERN_DEBUG "pwm[%d]     is: 0x%x\n", i, data->pwm[i]);
948                        printk(KERN_DEBUG "pwm_flag[%d] is: 0x%x\n", i, data->pwm_flag[i]);
949                }
950        }
951        printk(KERN_DEBUG "3 set of Temperatures: =====>\n");
952        printk(KERN_DEBUG "temp1 is: 0x%x\n", data->temp1[0]);
953        printk(KERN_DEBUG "temp1 high limit is: 0x%x\n", data->temp1[1]);
954        printk(KERN_DEBUG "temp1 low limit is: 0x%x\n", data->temp1[2]);
955        for (i=0; i<2; i++) {
956                for (j=0; j<7; j++) {
957                        printk(KERN_DEBUG "temp_add[%d][%d] is: 0x%x\n", i, j,
958                                        data->temp_add[i][j]);
959                }
960        }
961        for (i=0; i<=6; i++) {
962                printk(KERN_DEBUG "fan_div[%d] is: 0x%x\n", i, data->fan_div[i]);
963        }
964        printk(KERN_DEBUG "==========End of the debug message...==================\n\n");
965}
966#endif
967
968/* The next few functions are the call-back functions of the /proc/sys and
969   sysctl files. Which function is used is defined in the ctl_table in
970   the extra1 field.
971   Each function must return the magnitude (power of 10 to divide the date
972   with) if it is called with operation==SENSORS_PROC_REAL_INFO. It must
973   put a maximum of *nrels elements in results reflecting the data of this
974   file, and set *nrels to the number it actually put in it, if operation==
975   SENSORS_PROC_REAL_READ. Finally, it must get upto *nrels elements from
976   results and write them to the chip, if operations==SENSORS_PROC_REAL_WRITE.
977   Note that on SENSORS_PROC_REAL_READ, I do not check whether results is
978   large enough (by checking the incoming value of *nrels). This is not very
979   good practice, but as long as you put less than about 5 values in results,
980   you can assume it is large enough. */
981
982/* read/write voltage meaured value and limits */
983static void w83792d_in(struct i2c_client *client, int operation, int ctl_name,
984                        int *nrels_mag, long *results)
985{
986        struct w83792d_data *data = client->data;
987        int nr = ctl_name - W83792D_SYSCTL_IN0;
988
989        /* result[0]: low limit, result[1]: high limit,
990           result[2]: measured value */
991        if (operation == SENSORS_PROC_REAL_INFO)
992                *nrels_mag = 3;
993        else if (operation == SENSORS_PROC_REAL_READ) {
994                w83792d_update_client(client);
995                results[0] = IN_FROM_REG(nr, data->in_min[nr]*4);
996                results[1] = IN_FROM_REG(nr, data->in_max[nr]*4);
997                /* in7 and in8 do not have low bits, but the formula still
998                   works */
999                results[2] = IN_FROM_REG(nr, ((data->in[nr] << 2) |
1000                                                ((data->low_bits >> (2 * nr))
1001                                                        & 0x03)));
1002                *nrels_mag = 3;
1003        } else if (operation == SENSORS_PROC_REAL_WRITE) {
1004                if (*nrels_mag >= 1) {
1005                        /* Write Low limit into register. */
1006                        data->in_min[nr] = SENSORS_LIMIT(IN_TO_REG(nr,results[0])/4,
1007                                                        0, 255);
1008                        w83792d_write_value(client, W83792D_REG_IN_MIN[nr],
1009                                                        data->in_min[nr]);
1010                }
1011                if (*nrels_mag >= 2) {
1012                        /* Write High limit into register. */
1013                        data->in_max[nr] = SENSORS_LIMIT(IN_TO_REG(nr,results[1])/4,
1014                                                        0, 255);
1015                        w83792d_write_value(client, W83792D_REG_IN_MAX[nr],
1016                                                        data->in_max[nr]);
1017                }
1018        }
1019}
1020
1021static void w83792d_set_fan_div(struct i2c_client *client, int nr, u8 newdiv)
1022{
1023        struct w83792d_data *data = client->data;
1024        int min = 0;
1025        int old = 0;
1026        u8 tmp = 0;
1027
1028        newdiv = SENSORS_LIMIT(newdiv, 0, 7);
1029
1030        if (newdiv == data->fan_div[nr]) {
1031                return;
1032        }
1033
1034        min = FAN_FROM_REG(data->fan_min[nr], DIV_FROM_REG(data->fan_div[nr]));
1035        old = FAN_FROM_REG(data->fan[nr], DIV_FROM_REG(data->fan_div[nr]));
1036        data->fan_div[nr] = newdiv;
1037        tmp = w83792d_read_value(client, W83792D_REG_FAN_DIV[nr >> 1]);
1038        tmp &= (nr & 1) ? 0x8f : 0xf8;
1039        tmp |= (nr & 1) ? ((newdiv << 4) & 0x70) : (newdiv & 0x07);
1040        w83792d_write_value(client, W83792D_REG_FAN_DIV[nr >> 1], tmp);
1041        data->fan_min[nr] = FAN_TO_REG(min, DIV_FROM_REG(data->fan_div[nr]));
1042        data->fan[nr] = FAN_TO_REG(old, DIV_FROM_REG(data->fan_div[nr]));
1043        w83792d_write_value(client, W83792D_REG_FAN_MIN[nr],
1044                                data->fan_min[nr]);
1045}
1046
1047/* read/write fan meaured value and limits */
1048static void w83792d_fan(struct i2c_client *client, int operation, int ctl_name,
1049                 int *nrels_mag, long *results)
1050{
1051        struct w83792d_data *data = client->data;
1052        int nr = ctl_name - W83792D_SYSCTL_FAN1;
1053
1054        /* result[0]: low limit, result[1]: measured value */
1055        if (operation == SENSORS_PROC_REAL_INFO)
1056                *nrels_mag = 0;
1057        else if (operation == SENSORS_PROC_REAL_READ) {
1058                w83792d_update_client(client);
1059                results[0] = FAN_FROM_REG(data->fan_min[nr],
1060                                        DIV_FROM_REG(data->fan_div[nr]));
1061                results[1] = FAN_FROM_REG(data->fan[nr],
1062                                        DIV_FROM_REG(data->fan_div[nr]));
1063                if (!(data->has_fan & (1 << nr))) {
1064                        results[0] = 0;
1065                        results[1] = 0;
1066                }
1067                *nrels_mag = 2;
1068        } else if (operation == SENSORS_PROC_REAL_WRITE) {
1069                if (*nrels_mag >= 1 && (data->has_fan & (1 << nr))) {
1070                        data->fan_min[nr] = FAN_TO_REG(results[0],
1071                                            DIV_FROM_REG(data->fan_div[nr]));
1072                        w83792d_write_value(client,
1073                                             W83792D_REG_FAN_MIN[nr],
1074                                             data->fan_min[nr]);
1075                }
1076        }
1077}
1078
1079/* read/write temperature1 meaured value and limits */
1080static void w83792d_temp(struct i2c_client *client, int operation, int ctl_name,
1081                  int *nrels_mag, long *results)
1082{
1083        struct w83792d_data *data = client->data;
1084
1085        /* result[0]: high limit, result[1]: low limit
1086           result[2]: measured value, the order is different with voltage(in) */
1087        if (operation == SENSORS_PROC_REAL_INFO) {
1088                *nrels_mag = 1;
1089        } else if (operation == SENSORS_PROC_REAL_READ) {
1090                w83792d_update_client(client);
1091                results[0] = TEMP_FROM_REG(data->temp1[1]);
1092                results[1] = TEMP_FROM_REG(data->temp1[2]);
1093                results[2] = TEMP_FROM_REG(data->temp1[0]);
1094                *nrels_mag = 3;
1095        } else if (operation == SENSORS_PROC_REAL_WRITE) {
1096                if (*nrels_mag >= 1) {
1097                        data->temp1[1] = TEMP_TO_REG(results[0]);
1098                        w83792d_write_value(client, W83792D_REG_TEMP1_OVER,
1099                                            data->temp1[1]);
1100                }
1101                if (*nrels_mag >= 2) {
1102                        data->temp1[2] = TEMP_TO_REG(results[1]);
1103                        w83792d_write_value(client, W83792D_REG_TEMP1_HYST,
1104                                            data->temp1[2]);
1105                }
1106        }
1107}
1108
1109/* read/write temperature2,3 meaured value and limits */
1110static void w83792d_temp_add(struct i2c_client *client, int operation,
1111                      int ctl_name, int *nrels_mag, long *results)
1112{
1113        struct w83792d_data *data = client->data;
1114        int nr = ctl_name - W83792D_SYSCTL_TEMP2;
1115        int i=0, j=0;
1116
1117        /* result[0]: high limit, result[1]: low limit
1118           result[2]: measured value, the order is different with voltage(in) */
1119        if (operation == SENSORS_PROC_REAL_INFO)
1120                *nrels_mag = 1;
1121        else if (operation == SENSORS_PROC_REAL_READ) {
1122                w83792d_update_client(client);
1123                for (i=0; i<3; i++) {
1124                        j = (i==0) ? 2 : ((i==1)?0:1);
1125                        if ((data->temp_add[nr][i*2+1]) & 0x80) {
1126                                results[j] = TEMP_FROM_REG(data->temp_add[nr][i*2]) + 5;
1127                        } else {
1128                                results[j] = TEMP_FROM_REG(data->temp_add[nr][i*2]);
1129                        }
1130                }
1131                *nrels_mag = 3;
1132        } else if (operation == SENSORS_PROC_REAL_WRITE) {
1133                if (*nrels_mag >= 1) {
1134                        data->temp_add[nr][2] = TEMP_TO_REG(results[0]);
1135                        w83792d_write_value(client,
1136                                             W83792D_REG_TEMP_ADD[nr][2],
1137                                             data->temp_add[nr][2]);
1138                        if ((results[0]%10) == 0) {
1139                                w83792d_write_value(client,
1140                                        W83792D_REG_TEMP_ADD[nr][3], 0x00);
1141                        } else { /* consider the 0.5 degree */
1142                                w83792d_write_value(client,
1143                                        W83792D_REG_TEMP_ADD[nr][3], 0x80);
1144                        }
1145                }
1146                if (*nrels_mag >= 2) {
1147                        data->temp_add[nr][4] = TEMP_TO_REG(results[1]);
1148                        w83792d_write_value(client,
1149                                             W83792D_REG_TEMP_ADD[nr][4],
1150                                             data->temp_add[nr][4]);
1151                        if ((results[1]%10) == 0) {
1152                                w83792d_write_value(client,
1153                                        W83792D_REG_TEMP_ADD[nr][5], 0x00);
1154                        } else { /* consider the 0.5 degree */
1155                                w83792d_write_value(client,
1156                                        W83792D_REG_TEMP_ADD[nr][5], 0x80);
1157                        }
1158                }
1159        }
1160}
1161
1162/*
1163void w83792d_vid(struct i2c_client *client, int operation, int ctl_name,
1164                 int *nrels_mag, long *results)
1165{
1166        struct w83792d_data *data = client->data;
1167        if (operation == SENSORS_PROC_REAL_INFO)
1168                *nrels_mag = 3;
1169        else if (operation == SENSORS_PROC_REAL_READ) {
1170                w83792d_update_client(client);
1171                results[0] = vid_from_reg(data->vid, data->vrm);
1172                *nrels_mag = 1;
1173        }
1174}
1175
1176void w83792d_vrm(struct i2c_client *client, int operation, int ctl_name,
1177                 int *nrels_mag, long *results)
1178{
1179        struct w83792d_data *data = client->data;
1180        if (operation == SENSORS_PROC_REAL_INFO)
1181                *nrels_mag = 1;
1182        else if (operation == SENSORS_PROC_REAL_READ) {
1183                results[0] = data->vrm;
1184                *nrels_mag = 1;
1185        } else if (operation == SENSORS_PROC_REAL_WRITE) {
1186                if (*nrels_mag >= 1) {
1187                        data->vrm = results[0];
1188                }
1189        }
1190} */
1191
1192/* Read/Write Fan Divisor */
1193static void w83792d_fan_div(struct i2c_client *client, int operation,
1194                     int ctl_name, int *nrels_mag, long *results)
1195{
1196        struct w83792d_data *data = client->data;
1197        int i = 0;
1198
1199        if (operation == SENSORS_PROC_REAL_INFO)
1200                *nrels_mag = 0;
1201        else if (operation == SENSORS_PROC_REAL_READ) {
1202                w83792d_update_client(client);
1203                for (i=0; i<7; i++) {
1204                        results[i] = DIV_FROM_REG(data->fan_div[i]);
1205                }
1206                *nrels_mag = 7;
1207        }
1208}
1209
1210
1211/* Under Smart Fan I mode: read/write the Fan1/2/3 target temperature */
1212static void w83792d_thermal_cruise(struct i2c_client *client, int operation,
1213                            int ctl_name, int *nrels_mag, long *results)
1214{
1215        struct w83792d_data *data = client->data;
1216        int i=0;
1217        u8 target_tmp=0, target_mask=0;
1218
1219        if (operation == SENSORS_PROC_REAL_INFO)
1220                *nrels_mag = 0;
1221        else if (operation == SENSORS_PROC_REAL_READ) {
1222                w83792d_update_client(client);
1223                for (i=0; i<3; i++) {
1224                        results[i] = data->thermal_cruise[i];
1225                }
1226                *nrels_mag = 3;
1227        } else if (operation == SENSORS_PROC_REAL_WRITE) {
1228                for (i=0; i<3; i++) {
1229                        if (*nrels_mag < (i+1)) {
1230                                return;
1231                        }
1232                        target_tmp = results[i];
1233                        target_tmp = target_tmp & 0x7f;
1234                        target_mask = w83792d_read_value(client,
1235                                                W83792D_REG_THERMAL[i]) & 0x80;
1236                        data->thermal_cruise[i] = SENSORS_LIMIT(target_tmp, 0, 255);
1237                        w83792d_write_value(client, W83792D_REG_THERMAL[i],
1238                                             (data->thermal_cruise[i])|target_mask);
1239                }
1240        }
1241}
1242
1243/* The tolerance of fan1/fan2/fan3, when using Thermal Cruise(Smart Fan I)
1244   or Smart Fan II mode. */
1245static void w83792d_fan_tolerance(struct i2c_client *client, int operation,
1246                                 int ctl_name, int *nrels_mag, long *results)
1247{
1248        struct w83792d_data *data = client->data;
1249        int i=0;
1250        u8 tol_tmp, tol_mask;
1251
1252        if (operation == SENSORS_PROC_REAL_INFO)
1253                *nrels_mag = 0;
1254        else if (operation == SENSORS_PROC_REAL_READ) {
1255                w83792d_update_client(client);
1256                for (i=0; i<3; i++) {
1257                        results[i] = data->fan_tolerance[i];
1258                }
1259                *nrels_mag = 3;
1260        } else if (operation == SENSORS_PROC_REAL_WRITE) {
1261                for (i=0; i<3; i++) {
1262                        if (*nrels_mag < (i+1)) {
1263                                return;
1264                        }
1265                        tol_mask = w83792d_read_value(client,
1266                                W83792D_REG_FAN_TOL[i]) & ((i==1)?0x0f:0xf0);
1267                        tol_tmp = SENSORS_LIMIT(results[i], 0, 15);
1268                        tol_tmp &= 0x0f;
1269                        data->fan_tolerance[i] = tol_tmp;
1270                        if (i==1) {
1271                                tol_tmp <<= 4;
1272                        }
1273                        w83792d_write_value(client, W83792D_REG_FAN_TOL[i],
1274                                             tol_mask|tol_tmp);
1275                }
1276        }
1277}
1278
1279/* Under Smart Fan II mode: read/write the Fan1/2/3 temperature points */
1280static void w83792d_sf2_points(struct i2c_client *client, int operation,
1281                        int ctl_name, int *nrels_mag, long *results)
1282{
1283        struct w83792d_data *data = client->data;
1284        int nr = ctl_name - W83792D_SYSCTL_SF2_POINTS_FAN1;
1285        int j=0;
1286        u8 mask_tmp = 0;
1287
1288        if (operation == SENSORS_PROC_REAL_INFO)
1289                *nrels_mag = 0;
1290        else if (operation == SENSORS_PROC_REAL_READ) {
1291                w83792d_update_client(client);
1292                for (j=0; j<4; j++) {
1293                        results[j] = data->sf2_points[nr][j];
1294                }
1295                *nrels_mag = 4;
1296        } else if (operation == SENSORS_PROC_REAL_WRITE) {
1297                for (j=0; j<4; j++) {
1298                        if (*nrels_mag < (j+1)) {
1299                                return;
1300                        }
1301                        data->sf2_points[nr][j] = SENSORS_LIMIT(results[j],
1302                                                        0, 127);
1303                        mask_tmp = w83792d_read_value(client,
1304                                        W83792D_REG_POINTS[nr][j]) & 0x80;
1305                        w83792d_write_value(client, W83792D_REG_POINTS[nr][j],
1306                                        mask_tmp|data->sf2_points[nr][j]);
1307                }
1308        }
1309}
1310
1311/* Smart Fan II Duty Cycle1/2/3 of Fan1/2/3.
1312   Notice that: The Non-Stop can NOT be modified by user,
1313   because it is related with some physical characters,
1314   usually set by BIOS. User's modification to it may lead to
1315   Fan's stop, then bring danger. */
1316static void w83792d_sf2_levels(struct i2c_client *client, int operation,
1317                        int ctl_name, int *nrels_mag, long *results)
1318{
1319        struct w83792d_data *data = client->data;
1320        int nr = ctl_name - W83792D_SYSCTL_SF2_LEVELS_FAN1;
1321        int j = 0;
1322        u8 mask_tmp = 0, level_tmp = 0;
1323
1324        if (operation == SENSORS_PROC_REAL_INFO)
1325                *nrels_mag = 0;
1326        else if (operation == SENSORS_PROC_REAL_READ) {
1327                w83792d_update_client(client);
1328                for (j=0; j<4; j++) {
1329                        results[j] = (data->sf2_levels[nr][j] * 100) / 15;
1330                }
1331                *nrels_mag = 4;
1332        } else if (operation == SENSORS_PROC_REAL_WRITE) {
1333                for (j=1; j<4; j++) {  /* start with 1: need ignore Non-Stop */
1334                        if (*nrels_mag < j) {
1335                                return;
1336                        }
1337                        data->sf2_levels[nr][j] =
1338                                SENSORS_LIMIT((results[j]*15)/100, 0, 15);
1339                        mask_tmp = w83792d_read_value(client, W83792D_REG_LEVELS[nr][j])
1340                                                & ((j==3) ? 0xf0 : 0x0f);
1341                        if (j==3) {
1342                                level_tmp = data->sf2_levels[nr][j];
1343                        } else {
1344                                level_tmp = data->sf2_levels[nr][j] << 4;
1345                        }
1346                        w83792d_write_value(client, W83792D_REG_LEVELS[nr][j],
1347                                                level_tmp | mask_tmp);
1348                }
1349        }
1350}
1351
1352/* get reatime status of all sensors items: voltage, temp, fan */
1353static void w83792d_alarms(struct i2c_client *client, int operation, int ctl_name,
1354                    int *nrels_mag, long *results)
1355{
1356        struct w83792d_data *data = client->data;
1357        if (operation == SENSORS_PROC_REAL_INFO)
1358                *nrels_mag = 0;
1359        else if (operation == SENSORS_PROC_REAL_READ) {
1360                w83792d_update_client(client);
1361                results[0] = data->alarms;
1362                *nrels_mag = 1;
1363        }
1364}
1365
1366/* Read/Write Chassis status and Reset Chassis. */
1367static void w83792d_chassis(struct i2c_client *client, int operation,
1368                        int ctl_name, int *nrels_mag, long *results)
1369{
1370        struct w83792d_data *data = client->data;
1371        u8 temp1 = 0, temp2 = 0;
1372
1373        if (operation == SENSORS_PROC_REAL_INFO)
1374                *nrels_mag = 0;
1375        else if (operation == SENSORS_PROC_REAL_READ) {
1376                w83792d_update_client(client);
1377                results[0] = data->chassis[0];
1378                results[1] = data->chassis[1];
1379                *nrels_mag = 2;
1380        } else if (operation == SENSORS_PROC_REAL_WRITE) {
1381                data->chassis[1] = SENSORS_LIMIT(results[1], 0 ,1);
1382                temp1 = ((data->chassis[1]) << 7) & 0x80;
1383                temp2 = w83792d_read_value(client,
1384                                W83792D_REG_CASE_OPEN_CLR) & 0x7f;
1385                w83792d_write_value(client,
1386                                W83792D_REG_CASE_OPEN_CLR,
1387                                temp1|temp2);
1388        }
1389}
1390
1391/* Read/Write PWM/DC value of Fan1,Fan2,Fan3, which controls the
1392   Fan Duty Cycle */
1393static void w83792d_pwm(struct i2c_client *client, int operation, int ctl_name,
1394                 int *nrels_mag, long *results)
1395{
1396        struct w83792d_data *data = client->data;
1397        int nr = ctl_name - W83792D_SYSCTL_PWM1;
1398        u8 pwm_mask;
1399
1400        if (operation == SENSORS_PROC_REAL_INFO)
1401                *nrels_mag = 0;
1402        else if (operation == SENSORS_PROC_REAL_READ) {
1403                w83792d_update_client(client);
1404                results[0] = data->pwm[nr];
1405                *nrels_mag = 1;
1406        } else if (operation == SENSORS_PROC_REAL_WRITE) {
1407                data->pwm[nr] = SENSORS_LIMIT(results[0], 0, 15);
1408                pwm_mask = w83792d_read_value(client,W83792D_REG_PWM[nr]) & 0xf0;
1409                w83792d_write_value(client,W83792D_REG_PWM[nr],pwm_mask|data->pwm[nr]);
1410        }
1411}
1412
1413/* Read/Write PWM/DC mode for Fan1,Fan2,Fan3:
1414   1->PWM mode, 0->DC mode */
1415static void w83792d_pwm_flag(struct i2c_client *client, int operation, int ctl_name,
1416                      int *nrels_mag, long *results)
1417{
1418        struct w83792d_data *data = client->data;
1419        int i = 0;
1420        u8 pwm_flag_mask;
1421
1422        if (operation == SENSORS_PROC_REAL_INFO)
1423                *nrels_mag = 0;
1424        else if (operation == SENSORS_PROC_REAL_READ) {
1425                w83792d_update_client(client);
1426                for (i=0; i<3; i++) {
1427                        results[i] = data->pwm_flag[i];
1428                }
1429                *nrels_mag = 3;
1430        } else if (operation == SENSORS_PROC_REAL_WRITE) {
1431                for (i=0; i<3; i++) {
1432                        if (*nrels_mag < (i+1)) {
1433                                return;
1434                        }
1435                        data->pwm_flag[i] = SENSORS_LIMIT(results[i], 0, 1);
1436                        pwm_flag_mask = w83792d_read_value(client,
1437                                                W83792D_REG_PWM[i]) & 0x7f;
1438                        w83792d_write_value(client, W83792D_REG_PWM[i],
1439                                        ((data->pwm_flag[i])<<7)|pwm_flag_mask);
1440                }
1441        }
1442}
1443
1444/* Read/Write Fan mode into:PWM/DC, Thermal Cruise(SmartFanI), SmartFanII
1445   0->PWM/DC mode, 1->Thermal Cruise mode, 2/3->SmartFanII mode */
1446static void w83792d_fan_cfg(struct i2c_client *client, int operation,
1447                     int ctl_name, int *nrels_mag, long *results)
1448{
1449        struct w83792d_data *data = client->data;
1450        u8 temp_cfg1, temp_cfg2, temp_cfg3, temp_cfg4;
1451
1452        if (operation == SENSORS_PROC_REAL_INFO)
1453                *nrels_mag = 0;
1454        else if (operation == SENSORS_PROC_REAL_READ) {
1455                w83792d_update_client(client);
1456                results[0] = (data->fan_cfg) & 0x03;      /* Fan1's Mode */
1457                results[1] = ((data->fan_cfg)>>2) & 0x03; /* Fan2's Mode */
1458                results[2] = ((data->fan_cfg)>>4) & 0x03; /* Fan3's Mode */
1459                *nrels_mag = 3;
1460        } else if (operation == SENSORS_PROC_REAL_WRITE) {
1461                if (*nrels_mag < 3) {
1462                        return;
1463                }
1464                temp_cfg1 = SENSORS_LIMIT(results[0], 0, 3);
1465                temp_cfg2 = SENSORS_LIMIT(results[1], 0, 3) << 2;
1466                temp_cfg3 = SENSORS_LIMIT(results[2], 0, 3) << 4;
1467                temp_cfg4 = w83792d_read_value(client,W83792D_REG_FAN_CFG) & 0xc0;
1468                data->fan_cfg = ((temp_cfg4|temp_cfg3)|temp_cfg2)|temp_cfg1;
1469                w83792d_write_value(client,W83792D_REG_FAN_CFG,data->fan_cfg);
1470        }
1471}
1472
1473static int __init sm_w83792d_init(void)
1474{
1475        ENTER()
1476
1477        printk(KERN_INFO "w83792d version %s (%s)\n", LM_VERSION, LM_DATE);
1478
1479        LEAVE()
1480        return i2c_add_driver(&w83792d_driver);
1481}
1482
1483static void __exit sm_w83792d_exit(void)
1484{
1485        ENTER()
1486
1487        i2c_del_driver(&w83792d_driver);
1488
1489        LEAVE()
1490}
1491
1492
1493MODULE_AUTHOR("Chunhao Huang @ Winbond");
1494MODULE_DESCRIPTION("W83792AD/D driver for linux-2.4");
1495MODULE_LICENSE("GPL");
1496
1497module_init(sm_w83792d_init);
1498module_exit(sm_w83792d_exit);
1499
Note: See TracBrowser for help on using the browser.