root/lm-sensors/trunk/kernel/chips/via686a.c @ 2458

Revision 2458, 29.9 KB (checked in by khali, 9 years ago)

Fix voltage roundings.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
Line 
1/*
2    via686a.c - Part of lm_sensors, Linux kernel modules
3                for hardware monitoring
4               
5    Copyright (c) 1998 - 2002  Frodo Looijaard <frodol@dds.nl>,
6                        Kyösti Mälkki <kmalkki@cc.hut.fi>,
7                        Mark Studebaker <mdsxyz123@yahoo.com>,
8                        and Bob Dougherty <bobd@stanford.edu>
9    (Some conversion-factor data were contributed by Jonathan Teh Soon Yew
10    <j.teh@iname.com> and Alex van Kaam <darkside@chello.nl>.)
11
12    This program is free software; you can redistribute it and/or modify
13    it under the terms of the GNU General Public License as published by
14    the Free Software Foundation; either version 2 of the License, or
15    (at your option) any later version.
16
17    This program is distributed in the hope that it will be useful,
18    but WITHOUT ANY WARRANTY; without even the implied warranty of
19    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
20    GNU General Public License for more details.
21
22    You should have received a copy of the GNU General Public License
23    along with this program; if not, write to the Free Software
24    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
25*/
26
27/*
28    Supports the Via VT82C686A, VT82C686B south bridges.
29    Reports all as a 686A.
30    See doc/chips/via686a for details.
31    Warning - only supports a single device.
32*/
33
34#include <linux/module.h>
35#include <linux/slab.h>
36#include <linux/pci.h>
37#include <linux/delay.h>
38#include <linux/i2c.h>
39#include <linux/i2c-proc.h>
40#include <linux/init.h>
41#include <asm/io.h>
42#include "version.h"
43
44
45/* If force_addr is set to anything different from 0, we forcibly enable
46   the device at the given address. */
47static int force_addr = 0;
48MODULE_PARM(force_addr, "i");
49MODULE_PARM_DESC(force_addr,
50                 "Initialize the base address of the sensors");
51
52/* Addresses to scan.
53   Note that we can't determine the ISA address until we have initialized
54   our module */
55static unsigned short normal_i2c[] = { SENSORS_I2C_END };
56static unsigned short normal_i2c_range[] = { SENSORS_I2C_END };
57static unsigned int normal_isa[] = { 0x0000, SENSORS_ISA_END };
58static unsigned int normal_isa_range[] = { SENSORS_ISA_END };
59
60/* Insmod parameters */
61SENSORS_INSMOD_1(via686a);
62
63/*
64   The Via 686a southbridge has a LM78-like chip integrated on the same IC.
65   This driver is a customized copy of lm78.c
66*/
67
68/* Many VIA686A constants specified below */
69
70/* Length of ISA address segment */
71#define VIA686A_EXTENT 0x80
72#define VIA686A_BASE_REG 0x70
73#define VIA686A_ENABLE_REG 0x74
74
75/* The VIA686A registers */
76/* ins numbered 0-4 */
77#define VIA686A_REG_IN_MAX(nr) (0x2b + ((nr) * 2))
78#define VIA686A_REG_IN_MIN(nr) (0x2c + ((nr) * 2))
79#define VIA686A_REG_IN(nr)     (0x22 + (nr))
80
81/* fans numbered 1-2 */
82#define VIA686A_REG_FAN_MIN(nr) (0x3a + (nr))
83#define VIA686A_REG_FAN(nr)     (0x28 + (nr))
84
85// the following values are as speced by VIA:
86static const u8 regtemp[] = { 0x20, 0x21, 0x1f };
87static const u8 regover[] = { 0x39, 0x3d, 0x1d };
88static const u8 reghyst[] = { 0x3a, 0x3e, 0x1e };
89
90/* temps numbered 1-3 */
91#define VIA686A_REG_TEMP(nr)            (regtemp[(nr) - 1])
92#define VIA686A_REG_TEMP_OVER(nr)       (regover[(nr) - 1])
93#define VIA686A_REG_TEMP_HYST(nr)       (reghyst[(nr) - 1])
94#define VIA686A_REG_TEMP_LOW1   0x4b    // bits 7-6
95#define VIA686A_REG_TEMP_LOW23  0x49    // 2 = bits 5-4, 3 = bits 7-6
96
97#define VIA686A_REG_ALARM1 0x41
98#define VIA686A_REG_ALARM2 0x42
99#define VIA686A_REG_FANDIV 0x47
100#define VIA686A_REG_CONFIG 0x40
101// The following register sets temp interrupt mode (bits 1-0 for temp1,
102// 3-2 for temp2, 5-4 for temp3).  Modes are:
103//    00 interrupt stays as long as value is out-of-range
104//    01 interrupt is cleared once register is read (default)
105//    10 comparator mode- like 00, but ignores hysteresis
106//    11 same as 00
107#define VIA686A_REG_TEMP_MODE 0x4b
108// We'll just assume that you want to set all 3 simultaneously:
109#define VIA686A_TEMP_MODE_MASK 0x3F
110#define VIA686A_TEMP_MODE_CONTINUOUS (0x00)
111
112/* Conversions. Rounding and limit checking is only done on the TO_REG
113   variants. */
114
115/********* VOLTAGE CONVERSIONS (Bob Dougherty) ********/
116// From HWMon.cpp (Copyright 1998-2000 Jonathan Teh Soon Yew):
117// voltagefactor[0]=1.25/2628; (2628/1.25=2102.4)   // Vccp
118// voltagefactor[1]=1.25/2628; (2628/1.25=2102.4)   // +2.5V
119// voltagefactor[2]=1.67/2628; (2628/1.67=1573.7)   // +3.3V
120// voltagefactor[3]=2.6/2628;  (2628/2.60=1010.8)   // +5V
121// voltagefactor[4]=6.3/2628;  (2628/6.30=417.14)   // +12V
122// in[i]=(data[i+2]*25.0+133)*voltagefactor[i];
123// That is:
124// volts = (25*regVal+133)*factor
125// regVal = (volts/factor-133)/25
126// (These conversions were contributed by Jonathan Teh Soon Yew
127// <j.teh@iname.com>)
128static inline u8 IN_TO_REG(long val, int inNum)
129{
130        /* To avoid floating point, we multiply constants by 10 (100 for +12V).
131           Rounding is done (1205000 is actually 1330000 - 125000).
132           Remember that val is expressed in 0.01V/bit, which is why we divide
133           by an additional 1000 (10000 for +12V): 100 for val and 10 (100)
134           for the constants. */
135        if (inNum <= 1)
136                return (u8)
137                    SENSORS_LIMIT((val * 21024 - 1205000) / 250000, 0, 255);
138        else if (inNum == 2)
139                return (u8)
140                    SENSORS_LIMIT((val * 15737 - 1205000) / 250000, 0, 255);
141        else if (inNum == 3)
142                return (u8)
143                    SENSORS_LIMIT((val * 10108 - 1205000) / 250000, 0, 255);
144        else
145                return (u8)
146                    SENSORS_LIMIT((val * 41714 - 12050000) / 2500000, 0, 255);
147}
148
149static inline long IN_FROM_REG(u8 val, int inNum)
150{
151        /* To avoid floating point, we multiply constants by 10 (100 for +12V).
152           We also multiply them by 100 because we want 0.01V/bit for the
153           output value. Rounding is done. */
154        if (inNum <= 1)
155                return (long) ((25000 * val + 133000 + 21024 / 2) / 21024);
156        else if (inNum == 2)
157                return (long) ((25000 * val + 133000 + 15737 / 2) / 15737);
158        else if (inNum == 3)
159                return (long) ((25000 * val + 133000 + 10108 / 2) / 10108);
160        else
161                return (long) ((250000 * val + 1330000 + 41714 / 2) / 41714);
162}
163
164/********* FAN RPM CONVERSIONS ********/
165// Higher register values = slower fans (the fan's strobe gates a counter).
166// But this chip saturates back at 0, not at 255 like all the other chips.
167// So, 0 means 0 RPM
168static inline u8 FAN_TO_REG(long rpm, int div)
169{
170        if (rpm == 0)
171                return 0;
172        rpm = SENSORS_LIMIT(rpm, 1, 1000000);
173        return SENSORS_LIMIT((1350000 + rpm * div / 2) / (rpm * div), 1, 255);
174}
175
176#define FAN_FROM_REG(val,div) ((val)==0?0:(val)==255?0:1350000/((val)*(div)))
177
178/******** TEMP CONVERSIONS (Bob Dougherty) *********/
179// linear fits from HWMon.cpp (Copyright 1998-2000 Jonathan Teh Soon Yew)
180//      if(temp<169)
181//              return double(temp)*0.427-32.08;
182//      else if(temp>=169 && temp<=202)
183//              return double(temp)*0.582-58.16;
184//      else
185//              return double(temp)*0.924-127.33;
186//
187// A fifth-order polynomial fits the unofficial data (provided by Alex van
188// Kaam <darkside@chello.nl>) a bit better.  It also give more reasonable
189// numbers on my machine (ie. they agree with what my BIOS tells me). 
190// Here's the fifth-order fit to the 8-bit data:
191// temp = 1.625093e-10*val^5 - 1.001632e-07*val^4 + 2.457653e-05*val^3 -
192//        2.967619e-03*val^2 + 2.175144e-01*val - 7.090067e+0.
193//
194// (2000-10-25- RFD: thanks to Uwe Andersen <uandersen@mayah.com> for
195// finding my typos in this formula!)
196//
197// Alas, none of the elegant function-fit solutions will work because we
198// aren't allowed to use floating point in the kernel and doing it with
199// integers doesn't rpovide enough precision.  So we'll do boring old
200// look-up table stuff.  The unofficial data (see below) have effectively
201// 7-bit resolution (they are rounded to the nearest degree).  I'm assuming
202// that the transfer function of the device is monotonic and smooth, so a
203// smooth function fit to the data will allow us to get better precision. 
204// I used the 5th-order poly fit described above and solved for
205// VIA register values 0-255.  I *10 before rounding, so we get tenth-degree
206// precision.  (I could have done all 1024 values for our 10-bit readings,
207// but the function is very linear in the useful range (0-80 deg C), so
208// we'll just use linear interpolation for 10-bit readings.)  So, tempLUT
209// is the temp at via register values 0-255:
210static const long tempLUT[] =
211    { -709, -688, -667, -646, -627, -607, -589, -570, -553, -536, -519,
212            -503, -487, -471, -456, -442, -428, -414, -400, -387, -375,
213            -362, -350, -339, -327, -316, -305, -295, -285, -275, -265,
214            -255, -246, -237, -229, -220, -212, -204, -196, -188, -180,
215            -173, -166, -159, -152, -145, -139, -132, -126, -120, -114,
216            -108, -102, -96, -91, -85, -80, -74, -69, -64, -59, -54, -49,
217            -44, -39, -34, -29, -25, -20, -15, -11, -6, -2, 3, 7, 12, 16,
218            20, 25, 29, 33, 37, 42, 46, 50, 54, 59, 63, 67, 71, 75, 79, 84,
219            88, 92, 96, 100, 104, 109, 113, 117, 121, 125, 130, 134, 138,
220            142, 146, 151, 155, 159, 163, 168, 172, 176, 181, 185, 189,
221            193, 198, 202, 206, 211, 215, 219, 224, 228, 232, 237, 241,
222            245, 250, 254, 259, 263, 267, 272, 276, 281, 285, 290, 294,
223            299, 303, 307, 312, 316, 321, 325, 330, 334, 339, 344, 348,
224            353, 357, 362, 366, 371, 376, 380, 385, 390, 395, 399, 404,
225            409, 414, 419, 423, 428, 433, 438, 443, 449, 454, 459, 464,
226            469, 475, 480, 486, 491, 497, 502, 508, 514, 520, 526, 532,
227            538, 544, 551, 557, 564, 571, 578, 584, 592, 599, 606, 614,
228            621, 629, 637, 645, 654, 662, 671, 680, 689, 698, 708, 718,
229            728, 738, 749, 759, 770, 782, 793, 805, 818, 830, 843, 856,
230            870, 883, 898, 912, 927, 943, 958, 975, 991, 1008, 1026, 1044,
231            1062, 1081, 1101, 1121, 1141, 1162, 1184, 1206, 1229, 1252,
232            1276, 1301, 1326, 1352, 1378, 1406, 1434, 1462
233};
234
235/* the original LUT values from Alex van Kaam <darkside@chello.nl>
236   (for via register values 12-240):
237{-50,-49,-47,-45,-43,-41,-39,-38,-37,-35,-34,-33,-32,-31,
238-30,-29,-28,-27,-26,-25,-24,-24,-23,-22,-21,-20,-20,-19,-18,-17,-17,-16,-15,
239-15,-14,-14,-13,-12,-12,-11,-11,-10,-9,-9,-8,-8,-7,-7,-6,-6,-5,-5,-4,-4,-3,
240-3,-2,-2,-1,-1,0,0,1,1,1,3,3,3,4,4,4,5,5,5,6,6,7,7,8,8,9,9,9,10,10,11,11,12,
24112,12,13,13,13,14,14,15,15,16,16,16,17,17,18,18,19,19,20,20,21,21,21,22,22,
24222,23,23,24,24,25,25,26,26,26,27,27,27,28,28,29,29,30,30,30,31,31,32,32,33,
24333,34,34,35,35,35,36,36,37,37,38,38,39,39,40,40,41,41,42,42,43,43,44,44,45,
24445,46,46,47,48,48,49,49,50,51,51,52,52,53,53,54,55,55,56,57,57,58,59,59,60,
24561,62,62,63,64,65,66,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,83,84,
24685,86,88,89,91,92,94,96,97,99,101,103,105,107,109,110};
247*/
248
249// Here's the reverse LUT.  I got it by doing a 6-th order poly fit (needed
250// an extra term for a good fit to these inverse data!) and then
251// solving for each temp value from -50 to 110 (the useable range for
252// this chip).  Here's the fit:
253// viaRegVal = -1.160370e-10*val^6 +3.193693e-08*val^5 - 1.464447e-06*val^4
254// - 2.525453e-04*val^3 + 1.424593e-02*val^2 + 2.148941e+00*val +7.275808e+01)
255// Note that n=161:
256static const u8 viaLUT[] =
257    { 12, 12, 13, 14, 14, 15, 16, 16, 17, 18, 18, 19, 20, 20, 21, 22, 23,
258            23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 35, 36, 37, 39, 40,
259            41, 43, 45, 46, 48, 49, 51, 53, 55, 57, 59, 60, 62, 64, 66,
260            69, 71, 73, 75, 77, 79, 82, 84, 86, 88, 91, 93, 95, 98, 100,
261            103, 105, 107, 110, 112, 115, 117, 119, 122, 124, 126, 129,
262            131, 134, 136, 138, 140, 143, 145, 147, 150, 152, 154, 156,
263            158, 160, 162, 164, 166, 168, 170, 172, 174, 176, 178, 180,
264            182, 183, 185, 187, 188, 190, 192, 193, 195, 196, 198, 199,
265            200, 202, 203, 205, 206, 207, 208, 209, 210, 211, 212, 213,
266            214, 215, 216, 217, 218, 219, 220, 221, 222, 222, 223, 224,
267            225, 226, 226, 227, 228, 228, 229, 230, 230, 231, 232, 232,
268            233, 233, 234, 235, 235, 236, 236, 237, 237, 238, 238, 239,
269            239, 240
270};
271
272/* Converting temps to (8-bit) hyst and over registers */
273// No interpolation here.  Just check the limits and go.
274// The +5 effectively rounds off properly and the +50 is because
275// the temps start at -50
276static inline u8 TEMP_TO_REG(long val)
277{
278        return (u8)
279            SENSORS_LIMIT(viaLUT[((val <= -500) ? 0 : (val >= 1100) ? 160 : 
280                                  ((val + 5) / 10 + 50))], 0, 255);
281}
282
283/* for 8-bit temperature hyst and over registers */
284// The temp values are already *10, so we don't need to do that.
285// But we _will_ round these off to the nearest degree with (...*10+5)/10
286#define TEMP_FROM_REG(val) ((tempLUT[(val)]*10+5)/10)
287
288/* for 10-bit temperature readings */
289// You might _think_ this is too long to inline, but's it's really only
290// called once...
291static inline long TEMP_FROM_REG10(u16 val)
292{
293        // the temp values are already *10, so we don't need to do that.
294        long temp;
295        u16 eightBits = val >> 2;
296        u16 twoBits = val & 3;
297
298        // handle the extremes first (they won't interpolate well! ;-)
299        if (val == 0)
300                return (long) tempLUT[0];
301        if (val == 1023)
302                return (long) tempLUT[255];
303
304        if (twoBits == 0)
305                return (long) tempLUT[eightBits];
306        else {
307                // do some interpolation by multipying the lower and upper
308                // bounds by 25, 50 or 75, then /100.
309                temp = ((25 * (4 - twoBits)) * tempLUT[eightBits]
310                        + (25 * twoBits) * tempLUT[eightBits + 1]);
311                // increase the magnitude by 50 to achieve rounding.
312                if (temp > 0)
313                        temp += 50;
314                else
315                        temp -= 50;
316                return (temp / 100);
317        }
318}
319
320#define ALARMS_FROM_REG(val) (val)
321
322#define DIV_FROM_REG(val) (1 << (val))
323#define DIV_TO_REG(val) ((val)==8?3:(val)==4?2:(val)==1?0:1)
324
325/* For the VIA686A, we need to keep some data in memory.
326   The structure is dynamically allocated, at the same time when a new
327   via686a client is allocated. */
328struct via686a_data {
329        struct i2c_client client;
330        struct semaphore lock;
331        int sysctl_id;
332
333        struct semaphore update_lock;
334        char valid;             /* !=0 if following fields are valid */
335        unsigned long last_updated;     /* In jiffies */
336
337        u8 in[5];               /* Register value */
338        u8 in_max[5];           /* Register value */
339        u8 in_min[5];           /* Register value */
340        u8 fan[2];              /* Register value */
341        u8 fan_min[2];          /* Register value */
342        u16 temp[3];            /* Register value 10 bit */
343        u8 temp_over[3];        /* Register value */
344        u8 temp_hyst[3];        /* Register value */
345        u8 fan_div[2];          /* Register encoding, shifted right */
346        u16 alarms;             /* Register encoding, combined */
347};
348
349static struct pci_dev *s_bridge;        /* pointer to the (only) via686a */
350
351static int via686a_attach_adapter(struct i2c_adapter *adapter);
352static int via686a_detect(struct i2c_adapter *adapter, int address,
353                          unsigned short flags, int kind);
354static int via686a_detach_client(struct i2c_client *client);
355
356static int via686a_read_value(struct i2c_client *client, u8 register);
357static void via686a_write_value(struct i2c_client *client, u8 register,
358                                u8 value);
359static void via686a_update_client(struct i2c_client *client);
360static void via686a_init_client(struct i2c_client *client);
361
362
363static void via686a_in(struct i2c_client *client, int operation,
364                       int ctl_name, int *nrels_mag, long *results);
365static void via686a_fan(struct i2c_client *client, int operation,
366                        int ctl_name, int *nrels_mag, long *results);
367static void via686a_temp(struct i2c_client *client, int operation,
368                         int ctl_name, int *nrels_mag, long *results);
369static void via686a_alarms(struct i2c_client *client, int operation,
370                           int ctl_name, int *nrels_mag, long *results);
371static void via686a_fan_div(struct i2c_client *client, int operation,
372                            int ctl_name, int *nrels_mag, long *results);
373
374static int via686a_id = 0;
375
376/* The driver. I choose to use type i2c_driver, as at is identical to both
377   smbus_driver and isa_driver, and clients could be of either kind */
378static struct i2c_driver via686a_driver = {
379        .owner          = THIS_MODULE,
380        .name           = "VIA 686A",
381        .id             = I2C_DRIVERID_VIA686A,
382        .flags          = I2C_DF_NOTIFY,
383        .attach_adapter = via686a_attach_adapter,
384        .detach_client  = via686a_detach_client,
385};
386
387
388
389/* The /proc/sys entries */
390
391/* -- SENSORS SYSCTL START -- */
392#define VIA686A_SYSCTL_IN0 1000
393#define VIA686A_SYSCTL_IN1 1001
394#define VIA686A_SYSCTL_IN2 1002
395#define VIA686A_SYSCTL_IN3 1003
396#define VIA686A_SYSCTL_IN4 1004
397#define VIA686A_SYSCTL_FAN1 1101
398#define VIA686A_SYSCTL_FAN2 1102
399#define VIA686A_SYSCTL_TEMP 1200
400#define VIA686A_SYSCTL_TEMP2 1201
401#define VIA686A_SYSCTL_TEMP3 1202
402#define VIA686A_SYSCTL_FAN_DIV 2000
403#define VIA686A_SYSCTL_ALARMS 2001
404
405#define VIA686A_ALARM_IN0 0x01
406#define VIA686A_ALARM_IN1 0x02
407#define VIA686A_ALARM_IN2 0x04
408#define VIA686A_ALARM_IN3 0x08
409#define VIA686A_ALARM_TEMP 0x10
410#define VIA686A_ALARM_FAN1 0x40
411#define VIA686A_ALARM_FAN2 0x80
412#define VIA686A_ALARM_IN4 0x100
413#define VIA686A_ALARM_TEMP2 0x800
414#define VIA686A_ALARM_CHAS 0x1000
415#define VIA686A_ALARM_TEMP3 0x8000
416
417/* -- SENSORS SYSCTL END -- */
418
419/* These files are created for each detected VIA686A. This is just a template;
420   though at first sight, you might think we could use a statically
421   allocated list, we need some way to get back to the parent - which
422   is done through one of the 'extra' fields which are initialized
423   when a new copy is allocated. */
424static ctl_table via686a_dir_table_template[] = {
425        {VIA686A_SYSCTL_IN0, "in0", NULL, 0, 0644, NULL, &i2c_proc_real,
426         &i2c_sysctl_real, NULL, &via686a_in},
427        {VIA686A_SYSCTL_IN1, "in1", NULL, 0, 0644, NULL, &i2c_proc_real,
428         &i2c_sysctl_real, NULL, &via686a_in},
429        {VIA686A_SYSCTL_IN2, "in2", NULL, 0, 0644, NULL, &i2c_proc_real,
430         &i2c_sysctl_real, NULL, &via686a_in},
431        {VIA686A_SYSCTL_IN3, "in3", NULL, 0, 0644, NULL, &i2c_proc_real,
432         &i2c_sysctl_real, NULL, &via686a_in},
433        {VIA686A_SYSCTL_IN4, "in4", NULL, 0, 0644, NULL, &i2c_proc_real,
434         &i2c_sysctl_real, NULL, &via686a_in},
435        {VIA686A_SYSCTL_FAN1, "fan1", NULL, 0, 0644, NULL, &i2c_proc_real,
436         &i2c_sysctl_real, NULL, &via686a_fan},
437        {VIA686A_SYSCTL_FAN2, "fan2", NULL, 0, 0644, NULL, &i2c_proc_real,
438         &i2c_sysctl_real, NULL, &via686a_fan},
439        {VIA686A_SYSCTL_TEMP, "temp1", NULL, 0, 0644, NULL, &i2c_proc_real,
440         &i2c_sysctl_real, NULL, &via686a_temp},
441        {VIA686A_SYSCTL_TEMP2, "temp2", NULL, 0, 0644, NULL,
442         &i2c_proc_real, &i2c_sysctl_real, NULL, &via686a_temp},
443        {VIA686A_SYSCTL_TEMP3, "temp3", NULL, 0, 0644, NULL,
444         &i2c_proc_real, &i2c_sysctl_real, NULL, &via686a_temp},
445        {VIA686A_SYSCTL_FAN_DIV, "fan_div", NULL, 0, 0644, NULL,
446         &i2c_proc_real, &i2c_sysctl_real, NULL, &via686a_fan_div},
447        {VIA686A_SYSCTL_ALARMS, "alarms", NULL, 0, 0444, NULL,
448         &i2c_proc_real, &i2c_sysctl_real, NULL, &via686a_alarms},
449        {0}
450};
451
452static inline int via686a_read_value(struct i2c_client *client, u8 reg)
453{
454        return (inb_p(client->addr + reg));
455}
456
457static inline void via686a_write_value(struct i2c_client *client, u8 reg,
458                                       u8 value)
459{
460        outb_p(value, client->addr + reg);
461}
462
463/* This is called when the module is loaded */
464static int via686a_attach_adapter(struct i2c_adapter *adapter)
465{
466        return i2c_detect(adapter, &addr_data, via686a_detect);
467}
468
469int via686a_detect(struct i2c_adapter *adapter, int address,
470                   unsigned short flags, int kind)
471{
472        int i;
473        struct i2c_client *new_client;
474        struct via686a_data *data;
475        int err = 0;
476        const char *type_name = "via686a";
477        u16 val;
478
479        /* Make sure we are probing the ISA bus!!  */
480        if (!i2c_is_isa_adapter(adapter)) {
481                printk
482                ("via686a.o: via686a_detect called for an I2C bus adapter?!?\n");
483                return 0;
484        }
485
486        /* 8231 requires multiple of 256, we enforce that on 686 as well */
487        if(force_addr)
488                address = force_addr & 0xFF00;
489        if (check_region(address, VIA686A_EXTENT)) {
490                printk("via686a.o: region 0x%x already in use!\n",
491                       address);
492                return -ENODEV;
493        }
494
495        if(force_addr) {
496                printk("via686a.o: forcing ISA address 0x%04X\n", address);
497                if (PCIBIOS_SUCCESSFUL !=
498                    pci_write_config_word(s_bridge, VIA686A_BASE_REG, address))
499                        return -ENODEV;
500        }
501        if (PCIBIOS_SUCCESSFUL !=
502            pci_read_config_word(s_bridge, VIA686A_ENABLE_REG, &val))
503                return -ENODEV;
504        if (!(val & 0x0001)) {
505                printk("via686a.o: enabling sensors\n");
506                if (PCIBIOS_SUCCESSFUL !=
507                    pci_write_config_word(s_bridge, VIA686A_ENABLE_REG,
508                                      val | 0x0001))
509                        return -ENODEV;
510        }
511
512        if (!(data = kmalloc(sizeof(struct via686a_data), GFP_KERNEL))) {
513                err = -ENOMEM;
514                goto ERROR0;
515        }
516
517        new_client = &data->client;
518        new_client->addr = address;
519        init_MUTEX(&data->lock);
520        new_client->data = data;
521        new_client->adapter = adapter;
522        new_client->driver = &via686a_driver;
523        new_client->flags = 0;
524
525        /* Reserve the ISA region */
526        request_region(address, VIA686A_EXTENT, "via686a-sensors");
527
528        /* Fill in the remaining client fields and put into the global list */
529        strcpy(new_client->name, "Via 686A Integrated Sensors");
530
531        new_client->id = via686a_id++;
532        data->valid = 0;
533        init_MUTEX(&data->update_lock);
534
535        /* Tell the I2C layer a new client has arrived */
536        if ((err = i2c_attach_client(new_client)))
537                goto ERROR3;
538
539        /* Register a new directory entry with module sensors */
540        if ((i = i2c_register_entry((struct i2c_client *) new_client,
541                                        type_name,
542                                        via686a_dir_table_template)) < 0) {
543                err = i;
544                goto ERROR4;
545        }
546        data->sysctl_id = i;
547
548        /* Initialize the VIA686A chip */
549        via686a_init_client(new_client);
550        return 0;
551
552      ERROR4:
553        i2c_detach_client(new_client);
554      ERROR3:
555        release_region(address, VIA686A_EXTENT);
556        kfree(data);
557      ERROR0:
558        return err;
559}
560
561static int via686a_detach_client(struct i2c_client *client)
562{
563        int err;
564
565        i2c_deregister_entry(((struct via686a_data *) 
566                                  (client->data))->sysctl_id);
567
568        if ((err = i2c_detach_client(client))) {
569                printk
570                ("via686a.o: Client deregistration failed, client not detached.\n");
571                return err;
572        }
573
574        release_region(client->addr, VIA686A_EXTENT);
575        kfree(client->data);
576
577        return 0;
578}
579
580/* Called when we have found a new VIA686A. */
581static void via686a_init_client(struct i2c_client *client)
582{
583        u8 reg;
584
585        /* Start monitoring */
586        reg = via686a_read_value(client, VIA686A_REG_CONFIG);
587        via686a_write_value(client, VIA686A_REG_CONFIG, (reg|0x01)&0x7F);
588
589        /* Configure temp interrupt mode for continuous-interrupt operation */
590        via686a_write_value(client, VIA686A_REG_TEMP_MODE, 
591                            via686a_read_value(client, VIA686A_REG_TEMP_MODE) &
592                            !(VIA686A_TEMP_MODE_MASK | VIA686A_TEMP_MODE_CONTINUOUS));
593}
594
595static void via686a_update_client(struct i2c_client *client)
596{
597        struct via686a_data *data = client->data;
598        int i;
599
600        down(&data->update_lock);
601
602       if (time_after(jiffies - data->last_updated, HZ + HZ / 2) ||
603           time_before(jiffies, data->last_updated) || !data->valid) {
604
605                for (i = 0; i <= 4; i++) {
606                        data->in[i] =
607                            via686a_read_value(client, VIA686A_REG_IN(i));
608                        data->in_min[i] = via686a_read_value(client,
609                                                             VIA686A_REG_IN_MIN
610                                                             (i));
611                        data->in_max[i] =
612                            via686a_read_value(client, VIA686A_REG_IN_MAX(i));
613                }
614                for (i = 1; i <= 2; i++) {
615                        data->fan[i - 1] =
616                            via686a_read_value(client, VIA686A_REG_FAN(i));
617                        data->fan_min[i - 1] = via686a_read_value(client,
618                                                     VIA686A_REG_FAN_MIN(i));
619                }
620                for (i = 1; i <= 3; i++) {
621                        data->temp[i - 1] = via686a_read_value(client,
622                                                 VIA686A_REG_TEMP(i)) << 2;
623                        data->temp_over[i - 1] =
624                            via686a_read_value(client,
625                                               VIA686A_REG_TEMP_OVER(i));
626                        data->temp_hyst[i - 1] =
627                            via686a_read_value(client,
628                                               VIA686A_REG_TEMP_HYST(i));
629                }
630                /* add in lower 2 bits
631                   temp1 uses bits 7-6 of VIA686A_REG_TEMP_LOW1
632                   temp2 uses bits 5-4 of VIA686A_REG_TEMP_LOW23
633                   temp3 uses bits 7-6 of VIA686A_REG_TEMP_LOW23
634                 */
635                data->temp[0] |= (via686a_read_value(client,
636                                                     VIA686A_REG_TEMP_LOW1)
637                                  & 0xc0) >> 6;
638                data->temp[1] |=
639                    (via686a_read_value(client, VIA686A_REG_TEMP_LOW23) &
640                     0x30) >> 4;
641                data->temp[2] |=
642                    (via686a_read_value(client, VIA686A_REG_TEMP_LOW23) &
643                     0xc0) >> 6;
644
645                i = via686a_read_value(client, VIA686A_REG_FANDIV);
646                data->fan_div[0] = (i >> 4) & 0x03;
647                data->fan_div[1] = i >> 6;
648                data->alarms =
649                    via686a_read_value(client,
650                                       VIA686A_REG_ALARM1) |
651                    (via686a_read_value(client, VIA686A_REG_ALARM2) << 8);
652                data->last_updated = jiffies;
653                data->valid = 1;
654        }
655
656        up(&data->update_lock);
657}
658
659
660/* The next few functions are the call-back functions of the /proc/sys and
661   sysctl files. Which function is used is defined in the ctl_table in
662   the extra1 field.
663   Each function must return the magnitude (power of 10 to divide the date
664   with) if it is called with operation==SENSORS_PROC_REAL_INFO. It must
665   put a maximum of *nrels elements in results reflecting the data of this
666   file, and set *nrels to the number it actually put in it, if operation==
667   SENSORS_PROC_REAL_READ. Finally, it must get upto *nrels elements from
668   results and write them to the chip, if operations==SENSORS_PROC_REAL_WRITE.
669   Note that on SENSORS_PROC_REAL_READ, I do not check whether results is
670   large enough (by checking the incoming value of *nrels). This is not very
671   good practice, but as long as you put less than about 5 values in results,
672   you can assume it is large enough. */
673static void via686a_in(struct i2c_client *client, int operation, int ctl_name,
674               int *nrels_mag, long *results)
675{
676        struct via686a_data *data = client->data;
677        int nr = ctl_name - VIA686A_SYSCTL_IN0;
678
679        if (operation == SENSORS_PROC_REAL_INFO)
680                *nrels_mag = 2;
681        else if (operation == SENSORS_PROC_REAL_READ) {
682                via686a_update_client(client);
683                results[0] = IN_FROM_REG(data->in_min[nr], nr);
684                results[1] = IN_FROM_REG(data->in_max[nr], nr);
685                results[2] = IN_FROM_REG(data->in[nr], nr);
686                *nrels_mag = 3;
687        } else if (operation == SENSORS_PROC_REAL_WRITE) {
688                if (*nrels_mag >= 1) {
689                        data->in_min[nr] = IN_TO_REG(results[0], nr);
690                        via686a_write_value(client, VIA686A_REG_IN_MIN(nr),
691                                            data->in_min[nr]);
692                }
693                if (*nrels_mag >= 2) {
694                        data->in_max[nr] = IN_TO_REG(results[1], nr);
695                        via686a_write_value(client, VIA686A_REG_IN_MAX(nr),
696                                            data->in_max[nr]);
697                }
698        }
699}
700
701void via686a_fan(struct i2c_client *client, int operation, int ctl_name,
702                 int *nrels_mag, long *results)
703{
704        struct via686a_data *data = client->data;
705        int nr = ctl_name - VIA686A_SYSCTL_FAN1 + 1;
706
707        if (operation == SENSORS_PROC_REAL_INFO)
708                *nrels_mag = 0;
709        else if (operation == SENSORS_PROC_REAL_READ) {
710                via686a_update_client(client);
711                results[0] = FAN_FROM_REG(data->fan_min[nr - 1],
712                                          DIV_FROM_REG(data->fan_div
713                                                       [nr - 1]));
714                results[1] = FAN_FROM_REG(data->fan[nr - 1],
715                                 DIV_FROM_REG(data->fan_div[nr - 1]));
716                *nrels_mag = 2;
717        } else if (operation == SENSORS_PROC_REAL_WRITE) {
718                if (*nrels_mag >= 1) {
719                        data->fan_min[nr - 1] = FAN_TO_REG(results[0], 
720                                                           DIV_FROM_REG(data->
721                                                              fan_div[nr -1]));
722                        via686a_write_value(client,
723                                            VIA686A_REG_FAN_MIN(nr),
724                                            data->fan_min[nr - 1]);
725                }
726        }
727}
728
729void via686a_temp(struct i2c_client *client, int operation, int ctl_name,
730                  int *nrels_mag, long *results)
731{
732        struct via686a_data *data = client->data;
733        int nr = ctl_name - VIA686A_SYSCTL_TEMP;
734
735        if (operation == SENSORS_PROC_REAL_INFO)
736                *nrels_mag = 1;
737        else if (operation == SENSORS_PROC_REAL_READ) {
738                via686a_update_client(client);
739                results[0] = TEMP_FROM_REG(data->temp_over[nr]);
740                results[1] = TEMP_FROM_REG(data->temp_hyst[nr]);
741                results[2] = TEMP_FROM_REG10(data->temp[nr]);
742                *nrels_mag = 3;
743        } else if (operation == SENSORS_PROC_REAL_WRITE) {
744                if (*nrels_mag >= 1) {
745                        data->temp_over[nr] = TEMP_TO_REG(results[0]);
746                        via686a_write_value(client,
747                                            VIA686A_REG_TEMP_OVER(nr + 1),
748                                            data->temp_over[nr]);
749                }
750                if (*nrels_mag >= 2) {
751                        data->temp_hyst[nr] = TEMP_TO_REG(results[1]);
752                        via686a_write_value(client,
753                                            VIA686A_REG_TEMP_HYST(nr + 1),
754                                            data->temp_hyst[nr]);
755                }
756        }
757}
758
759void via686a_alarms(struct i2c_client *client, int operation, int ctl_name,
760                    int *nrels_mag, long *results)
761{
762        struct via686a_data *data = client->data;
763        if (operation == SENSORS_PROC_REAL_INFO)
764                *nrels_mag = 0;
765        else if (operation == SENSORS_PROC_REAL_READ) {
766                via686a_update_client(client);
767                results[0] = ALARMS_FROM_REG(data->alarms);
768                *nrels_mag = 1;
769        }
770}
771
772void via686a_fan_div(struct i2c_client *client, int operation,
773                     int ctl_name, int *nrels_mag, long *results)
774{
775        struct via686a_data *data = client->data;
776        int old;
777
778        if (operation == SENSORS_PROC_REAL_INFO)
779                *nrels_mag = 0;
780        else if (operation == SENSORS_PROC_REAL_READ) {
781                via686a_update_client(client);
782                results[0] = DIV_FROM_REG(data->fan_div[0]);
783                results[1] = DIV_FROM_REG(data->fan_div[1]);
784                *nrels_mag = 2;
785        } else if (operation == SENSORS_PROC_REAL_WRITE) {
786                old = via686a_read_value(client, VIA686A_REG_FANDIV);
787                if (*nrels_mag >= 2) {
788                        data->fan_div[1] = DIV_TO_REG(results[1]);
789                        old = (old & 0x3f) | (data->fan_div[1] << 6);
790                }
791                if (*nrels_mag >= 1) {
792                        data->fan_div[0] = DIV_TO_REG(results[0]);
793                        old = (old & 0xcf) | (data->fan_div[0] << 4);
794                        via686a_write_value(client, VIA686A_REG_FANDIV,
795                                            old);
796                }
797        }
798}
799
800
801static struct pci_device_id via686a_pci_ids[] __devinitdata = {
802       {PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C686_4, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
803       { 0, }
804};
805
806static int __devinit via686a_pci_probe(struct pci_dev *dev,
807                                      const struct pci_device_id *id)
808{
809       u16 val;
810       int addr = 0;
811
812       if (PCIBIOS_SUCCESSFUL !=
813           pci_read_config_word(dev, VIA686A_BASE_REG, &val))
814               return -ENODEV;
815
816       addr = val & ~(VIA686A_EXTENT - 1);
817       if (addr == 0 && force_addr == 0) {
818               printk("via686a.o: base address not set - upgrade BIOS or use force_addr=0xaddr\n");
819               return -ENODEV;
820       }
821       if (force_addr)
822               addr = force_addr;      /* so detect will get called */
823
824       if (!addr) {
825               printk("via686a.o: No Via 686A sensors found.\n");
826               return -ENODEV;
827       }
828       normal_isa[0] = addr;
829       s_bridge = dev;
830       return i2c_add_driver(&via686a_driver);
831}
832
833static void __devexit via686a_pci_remove(struct pci_dev *dev)
834{
835       i2c_del_driver(&via686a_driver);
836}
837
838static struct pci_driver via686a_pci_driver = {
839       .name            = "via686a",
840       .id_table        = via686a_pci_ids,
841       .probe           = via686a_pci_probe,
842       .remove          = __devexit_p(via686a_pci_remove),
843};
844
845static int __init sm_via686a_init(void)
846{
847        printk("via686a.o version %s (%s)\n", LM_VERSION, LM_DATE);
848        return pci_module_init(&via686a_pci_driver);
849}
850
851static void __exit sm_via686a_exit(void)
852{
853       pci_unregister_driver(&via686a_pci_driver);
854}
855
856MODULE_AUTHOR("Kyösti Mälkki <kmalkki@cc.hut.fi>, "
857              "Mark Studebaker <mdsxyz123@yahoo.com> "
858             "and Bob Dougherty <bobd@stanford.edu>");
859MODULE_DESCRIPTION("VIA 686A Sensor device");
860MODULE_LICENSE("GPL");
861
862module_init(sm_via686a_init);
863module_exit(sm_via686a_exit);
Note: See TracBrowser for help on using the browser.