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

Revision 999, 33.6 KB (checked in by mds, 12 years ago)

Allow force and force_via686a parameters. Driver will take the

address and program the base address in the 686a.
This is NOT a PCI force; the 3057 device must
be present in lspci.
Should work for Asus A7V/K7V boards which don't set the
base address (because they also have a as99127f on them!??).
Some rough edges remain, because
via686a_find() does not know there is a force; that only
is apparent to via686a_detect().
Notably, the driver will stay loaded even if the address is
uninitialized and there is no force; also, the driver complains
that a force is needed even when you give it one.

  • 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, 1999,2000  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    Warning - only supports a single via686a device.
29*/
30#include <linux/version.h>
31#include <linux/module.h>
32#include <linux/malloc.h>
33#include <linux/proc_fs.h>
34#include <linux/ioport.h>
35#include <linux/sysctl.h>
36#include <linux/pci.h>
37#include <asm/errno.h>
38#include <asm/io.h>
39#include <linux/types.h>
40#include <linux/i2c.h>
41#include "version.h"
42#include "i2c-isa.h"
43#include "sensors.h"
44#include <linux/init.h>
45
46#ifndef PCI_DEVICE_ID_VIA_82C686_4
47#define PCI_DEVICE_ID_VIA_82C686_4 0x3057
48#endif
49
50#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,2,18)) || \
51    (LINUX_VERSION_CODE == KERNEL_VERSION(2,3,0))
52#define init_MUTEX(s) do { *(s) = MUTEX; } while(0)
53#endif
54
55#if LINUX_VERSION_CODE < KERNEL_VERSION(2,3,13)
56#define THIS_MODULE NULL
57#endif
58
59/* Addresses to scan.
60   Note that we can't determine the ISA address until we have initialized
61   our module */
62static unsigned short normal_i2c[] = { SENSORS_I2C_END };
63static unsigned short normal_i2c_range[] = { SENSORS_I2C_END };
64static unsigned int normal_isa[] = { 0x0000, SENSORS_ISA_END };
65static unsigned int normal_isa_range[] = { SENSORS_ISA_END };
66
67/* Insmod parameters */
68SENSORS_INSMOD_1(via686a);
69
70/*
71   The Via 686a southbridge has a LM78-like chip integrated on the same IC.
72   This driver is a customized copy of lm78.c
73*/
74
75/* Many VIA686A constants specified below */
76
77/* Length of ISA address segment */
78#define VIA686A_EXTENT 0x80
79#define VIA686A_BASE_REG 0x70
80#define VIA686A_ENABLE_REG 0x74
81
82/* The VIA686A registers */
83/* ins numbered 0-4 */
84#define VIA686A_REG_IN_MAX(nr) (0x2b + ((nr) * 2))
85#define VIA686A_REG_IN_MIN(nr) (0x2c + ((nr) * 2))
86#define VIA686A_REG_IN(nr)     (0x22 + (nr))
87
88/* fans numbered 1-2 */
89#define VIA686A_REG_FAN_MIN(nr) (0x3a + (nr))
90#define VIA686A_REG_FAN(nr)     (0x28 + (nr))
91
92// the following values are as speced by VIA:
93static const u8 regtemp[] = { 0x20, 0x21, 0x1f };
94static const u8 regover[] = { 0x39, 0x3d, 0x1d };
95static const u8 reghyst[] = { 0x3a, 0x3e, 0x1e };
96
97/* temps numbered 1-3 */
98#define VIA686A_REG_TEMP(nr)            (regtemp[(nr) - 1])
99#define VIA686A_REG_TEMP_OVER(nr)       (regover[(nr) - 1])
100#define VIA686A_REG_TEMP_HYST(nr)       (reghyst[(nr) - 1])
101#define VIA686A_REG_TEMP_LOW1   0x4b    // bits 7-6
102#define VIA686A_REG_TEMP_LOW23  0x49    // 2 = bits 5-4, 3 = bits 7-6
103
104#define VIA686A_REG_ALARM1 0x41
105#define VIA686A_REG_ALARM2 0x42
106#define VIA686A_REG_FANDIV 0x47
107#define VIA686A_REG_CONFIG 0x40
108// The following register sets temp interrupt mode (bits 1-0 for temp1,
109// 3-2 for temp2, 5-4 for temp3).  Modes are:
110//    00 interrupt stays as long as value is out-of-range
111//    01 interrupt is cleared once register is read (default)
112//    10 comparator mode- like 00, but ignores hysteresis
113//    11 same as 00
114#define VIA686A_REG_TEMP_MODE 0x4b
115// We'll just assume that you want to set all 3 simulataneously:
116#define VIA686A_TEMP_MODE_MASK 0x3F
117#define VIA686A_TEMP_MODE_CONTINUOUS (0x00)
118
119/* Conversions. Rounding and limit checking is only done on the TO_REG
120   variants. */
121
122/********* VOLTAGE CONVERSIONS (Bob Dougherty) ********/
123// From HWMon.cpp (Copyright 1998-2000 Jonathan Teh Soon Yew):
124// voltagefactor[0]=1.25/2628; (2628/1.25=2102.4)   // Vccp
125// voltagefactor[1]=1.25/2628; (2628/1.25=2102.4)   // +2.5V
126// voltagefactor[2]=1.67/2628; (2628/1.67=1573.7)   // +3.3V
127// voltagefactor[3]=2.6/2628;  (2628/2.60=1010.8)   // +5V
128// voltagefactor[4]=6.3/2628;  (2628/6.30=417.14)   // +12V
129// in[i]=(data[i+2]*25.0+133)*voltagefactor[i];
130// That is:
131// volts = (25*regVal+133)*factor
132// regVal = (volts/factor-133)/25
133// (These conversions were contributed by Jonathan Teh Soon Yew
134// <j.teh@iname.com>)
135//
136// These get us close, but they don't completely agree with what my BIOS
137// says- they are all a bit low.  But, it all we have to go on...
138extern inline u8 IN_TO_REG(long val, int inNum)
139{
140        // to avoid floating point, we multiply everything by 100.
141        // val is guaranteed to be positive, so we can achieve the effect of
142        // rounding by (...*10+5)/10.  Note that the *10 is hidden in the
143        // /250 (which should really be /2500).
144        // At the end, we need to /100 because we *100 everything and we need
145        // to /10 because of the rounding thing, so we /1000. 
146        if (inNum <= 1)
147                return (u8)
148                    SENSORS_LIMIT(((val * 210240 - 13300) / 250 + 5) / 1000, 
149                                  0, 255);
150        else if (inNum == 2)
151                return (u8)
152                    SENSORS_LIMIT(((val * 157370 - 13300) / 250 + 5) / 1000, 
153                                  0, 255);
154        else if (inNum == 3)
155                return (u8)
156                    SENSORS_LIMIT(((val * 101080 - 13300) / 250 + 5) / 1000, 
157                                  0, 255);
158        else
159                return (u8) SENSORS_LIMIT(((val * 41714 - 13300) / 250 + 5)
160                                          / 1000, 0, 255);
161}
162
163extern inline long IN_FROM_REG(u8 val, int inNum)
164{
165        // to avoid floating point, we multiply everything by 100.
166        // val is guaranteed to be positive, so we can achieve the effect of
167        // rounding by adding 0.5.  Or, to avoid fp math, we do (...*10+5)/10.
168        // We need to scale with *100 anyway, so no need to /100 at the end.
169        if (inNum <= 1)
170                return (long) (((250000 * val + 13300) / 210240 * 10 + 5) /10);
171        else if (inNum == 2)
172                return (long) (((250000 * val + 13300) / 157370 * 10 + 5) /10);
173        else if (inNum == 3)
174                return (long) (((250000 * val + 13300) / 101080 * 10 + 5) /10);
175        else
176                return (long) (((250000 * val + 13300) / 41714 * 10 + 5) /10);
177}
178
179/********* FAN RPM CONVERSIONS ********/
180// Higher register values = slower fans (the fan's strobe gates a counter).
181// But this chip saturates back at 0, not at 255 like all the other chips.
182// So, 0 means 0 RPM
183extern inline u8 FAN_TO_REG(long rpm, int div)
184{
185        if (rpm == 0)
186                return 0;
187        rpm = SENSORS_LIMIT(rpm, 1, 1000000);
188        return SENSORS_LIMIT((1350000 + rpm * div / 2) / (rpm * div), 1, 255);
189}
190
191#define FAN_FROM_REG(val,div) ((val)==0?0:(val)==255?0:1350000/((val)*(div)))
192
193/******** TEMP CONVERSIONS (Bob Dougherty) *********/
194// linear fits from HWMon.cpp (Copyright 1998-2000 Jonathan Teh Soon Yew)
195//      if(temp<169)
196//              return double(temp)*0.427-32.08;
197//      else if(temp>=169 && temp<=202)
198//              return double(temp)*0.582-58.16;
199//      else
200//              return double(temp)*0.924-127.33;
201//
202// A fifth-order polynomial fits the unofficial data (provided by Alex van
203// Kaam <darkside@chello.nl>) a bit better.  It also give more reasonable
204// numbers on my machine (ie. they agree with what my BIOS tells me). 
205// Here's the fifth-order fit to the 8-bit data:
206// temp = 1.625093e-10*val^5 - 1.001632e-07*val^4 + 2.457653e-05*val^3 -
207//        2.967619e-03*val^2 + 2.175144e-01*val - 7.090067e+0.
208//
209// (2000-10-25- RFD: thanks to Uwe Andersen <uandersen@mayah.com> for
210// finding my typos in this formula!)
211//
212// Alas, none of the elegant function-fit solutions will work because we
213// aren't allowed to use floating point in the kernel and doing it with
214// integers doesn't rpovide enough precision.  So we'll do boring old
215// look-up table stuff.  The unofficial data (see below) have effectively
216// 7-bit resolution (they are rounded to the nearest degree).  I'm assuming
217// that the transfer function of the device is monotonic and smooth, so a
218// smooth function fit to the data will allow us to get better precision. 
219// I used the 5th-order poly fit described above and solved for
220// VIA register values 0-255.  I *10 before rounding, so we get tenth-degree
221// precision.  (I could have done all 1024 values for our 10-bit readings,
222// but the function is very linear in the useful range (0-80 deg C), so
223// we'll just use linear interpolation for 10-bit readings.)  So, tempLUT
224// is the temp at via register values 0-255:
225static const long tempLUT[] =
226    { -709, -688, -667, -646, -627, -607, -589, -570, -553, -536, -519,
227            -503, -487, -471, -456, -442, -428, -414, -400, -387, -375,
228            -362, -350, -339, -327, -316, -305, -295, -285, -275, -265,
229            -255, -246, -237, -229, -220, -212, -204, -196, -188, -180,
230            -173, -166, -159, -152, -145, -139, -132, -126, -120, -114,
231            -108, -102, -96, -91, -85, -80, -74, -69, -64, -59, -54, -49,
232            -44, -39, -34, -29, -25, -20, -15, -11, -6, -2, 3, 7, 12, 16,
233            20, 25, 29, 33, 37, 42, 46, 50, 54, 59, 63, 67, 71, 75, 79, 84,
234            88, 92, 96, 100, 104, 109, 113, 117, 121, 125, 130, 134, 138,
235            142, 146, 151, 155, 159, 163, 168, 172, 176, 181, 185, 189,
236            193, 198, 202, 206, 211, 215, 219, 224, 228, 232, 237, 241,
237            245, 250, 254, 259, 263, 267, 272, 276, 281, 285, 290, 294,
238            299, 303, 307, 312, 316, 321, 325, 330, 334, 339, 344, 348,
239            353, 357, 362, 366, 371, 376, 380, 385, 390, 395, 399, 404,
240            409, 414, 419, 423, 428, 433, 438, 443, 449, 454, 459, 464,
241            469, 475, 480, 486, 491, 497, 502, 508, 514, 520, 526, 532,
242            538, 544, 551, 557, 564, 571, 578, 584, 592, 599, 606, 614,
243            621, 629, 637, 645, 654, 662, 671, 680, 689, 698, 708, 718,
244            728, 738, 749, 759, 770, 782, 793, 805, 818, 830, 843, 856,
245            870, 883, 898, 912, 927, 943, 958, 975, 991, 1008, 1026, 1044,
246            1062, 1081, 1101, 1121, 1141, 1162, 1184, 1206, 1229, 1252,
247            1276, 1301, 1326, 1352, 1378, 1406, 1434, 1462
248};
249
250/* the original LUT values from Alex van Kaam <darkside@chello.nl>
251   (for via register values 12-240):
252{-50,-49,-47,-45,-43,-41,-39,-38,-37,-35,-34,-33,-32,-31,
253-30,-29,-28,-27,-26,-25,-24,-24,-23,-22,-21,-20,-20,-19,-18,-17,-17,-16,-15,
254-15,-14,-14,-13,-12,-12,-11,-11,-10,-9,-9,-8,-8,-7,-7,-6,-6,-5,-5,-4,-4,-3,
255-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,
25612,12,13,13,13,14,14,15,15,16,16,16,17,17,18,18,19,19,20,20,21,21,21,22,22,
25722,23,23,24,24,25,25,26,26,26,27,27,27,28,28,29,29,30,30,30,31,31,32,32,33,
25833,34,34,35,35,35,36,36,37,37,38,38,39,39,40,40,41,41,42,42,43,43,44,44,45,
25945,46,46,47,48,48,49,49,50,51,51,52,52,53,53,54,55,55,56,57,57,58,59,59,60,
26061,62,62,63,64,65,66,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,83,84,
26185,86,88,89,91,92,94,96,97,99,101,103,105,107,109,110};
262*/
263
264// Here's the reverse LUT.  I got it by doing a 6-th order poly fit (needed
265// an extra term for a good fit to these inverse data!) and then
266// solving for each temp value from -50 to 110 (the useable range for
267// this chip).  Here's the fit:
268// viaRegVal = -1.160370e-10*val^6 +3.193693e-08*val^5 - 1.464447e-06*val^4
269// - 2.525453e-04*val^3 + 1.424593e-02*val^2 + 2.148941e+00*val +7.275808e+01)
270// Note that n=161:
271static const u8 viaLUT[] =
272    { 12, 12, 13, 14, 14, 15, 16, 16, 17, 18, 18, 19, 20, 20, 21, 22, 23,
273            23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 35, 36, 37, 39, 40,
274            41, 43, 45, 46, 48, 49, 51, 53, 55, 57, 59, 60, 62, 64, 66,
275            69, 71, 73, 75, 77, 79, 82, 84, 86, 88, 91, 93, 95, 98, 100,
276            103, 105, 107, 110, 112, 115, 117, 119, 122, 124, 126, 129,
277            131, 134, 136, 138, 140, 143, 145, 147, 150, 152, 154, 156,
278            158, 160, 162, 164, 166, 168, 170, 172, 174, 176, 178, 180,
279            182, 183, 185, 187, 188, 190, 192, 193, 195, 196, 198, 199,
280            200, 202, 203, 205, 206, 207, 208, 209, 210, 211, 212, 213,
281            214, 215, 216, 217, 218, 219, 220, 221, 222, 222, 223, 224,
282            225, 226, 226, 227, 228, 228, 229, 230, 230, 231, 232, 232,
283            233, 233, 234, 235, 235, 236, 236, 237, 237, 238, 238, 239,
284            239, 240
285};
286
287/* Converting temps to (8-bit) hyst and over registers */
288// No interpolation here.  Just check the limits and go.
289// The +5 effectively rounds off properly and the +50 is because
290// the temps start at -50
291extern inline u8 TEMP_TO_REG(long val)
292{
293        return (u8)
294            SENSORS_LIMIT(viaLUT[((val <= -500) ? 0 : (val >= 1100) ? 160 : 
295                                  ((val + 5) / 10 + 50))], 0, 255);
296}
297
298/* for 8-bit temperature hyst and over registers */
299// The temp values are already *10, so we don't need to do that.
300// But we _will_ round these off to the nearest degree with (...*10+5)/10
301#define TEMP_FROM_REG(val) ((tempLUT[(val)]*10+5)/10)
302
303/* for 10-bit temperature readings */
304// You might _think_ this is too long to inline, but's it's really only
305// called once...
306extern inline long TEMP_FROM_REG10(u16 val)
307{
308        // the temp values are already *10, so we don't need to do that.
309        long temp;
310        u16 eightBits = val >> 2;
311        u16 twoBits = val & 3;
312
313        // handle the extremes first (they won't interpolate well! ;-)
314        if (val == 0)
315                return (long) tempLUT[0];
316        if (val == 1023)
317                return (long) tempLUT[255];
318
319        if (twoBits == 0)
320                return (long) tempLUT[eightBits];
321        else {
322                // do some interpolation by multipying the lower and upper
323                // bounds by 25, 50 or 75, then /100.
324                temp = ((25 * (4 - twoBits)) * tempLUT[eightBits]
325                        + (25 * twoBits) * tempLUT[eightBits + 1]);
326                // increase the magnitude by 50 to achieve rounding.
327                if (temp > 0)
328                        temp += 50;
329                else
330                        temp -= 50;
331                return (temp / 100);
332        }
333}
334
335#define ALARMS_FROM_REG(val) (val)
336
337#define DIV_FROM_REG(val) (1 << (val))
338#define DIV_TO_REG(val) ((val)==8?3:(val)==4?2:(val)==1?0:1)
339
340/* Initial limits */
341#define VIA686A_INIT_IN_0 200
342#define VIA686A_INIT_IN_1 250
343#define VIA686A_INIT_IN_2 330
344#define VIA686A_INIT_IN_3 500
345#define VIA686A_INIT_IN_4 1200
346
347#define VIA686A_INIT_IN_PERCENTAGE 10
348
349#define VIA686A_INIT_IN_MIN_0 (VIA686A_INIT_IN_0 - VIA686A_INIT_IN_0 \
350        * VIA686A_INIT_IN_PERCENTAGE / 100)
351#define VIA686A_INIT_IN_MAX_0 (VIA686A_INIT_IN_0 + VIA686A_INIT_IN_0 \
352        * VIA686A_INIT_IN_PERCENTAGE / 100)
353#define VIA686A_INIT_IN_MIN_1 (VIA686A_INIT_IN_1 - VIA686A_INIT_IN_1 \
354        * VIA686A_INIT_IN_PERCENTAGE / 100)
355#define VIA686A_INIT_IN_MAX_1 (VIA686A_INIT_IN_1 + VIA686A_INIT_IN_1 \
356        * VIA686A_INIT_IN_PERCENTAGE / 100)
357#define VIA686A_INIT_IN_MIN_2 (VIA686A_INIT_IN_2 - VIA686A_INIT_IN_2 \
358        * VIA686A_INIT_IN_PERCENTAGE / 100)
359#define VIA686A_INIT_IN_MAX_2 (VIA686A_INIT_IN_2 + VIA686A_INIT_IN_2 \
360        * VIA686A_INIT_IN_PERCENTAGE / 100)
361#define VIA686A_INIT_IN_MIN_3 (VIA686A_INIT_IN_3 - VIA686A_INIT_IN_3 \
362        * VIA686A_INIT_IN_PERCENTAGE / 100)
363#define VIA686A_INIT_IN_MAX_3 (VIA686A_INIT_IN_3 + VIA686A_INIT_IN_3 \
364        * VIA686A_INIT_IN_PERCENTAGE / 100)
365#define VIA686A_INIT_IN_MIN_4 (VIA686A_INIT_IN_4 - VIA686A_INIT_IN_4 \
366        * VIA686A_INIT_IN_PERCENTAGE / 100)
367#define VIA686A_INIT_IN_MAX_4 (VIA686A_INIT_IN_4 + VIA686A_INIT_IN_4 \
368        * VIA686A_INIT_IN_PERCENTAGE / 100)
369
370#define VIA686A_INIT_FAN_MIN    3000
371
372#define VIA686A_INIT_TEMP_OVER 600
373#define VIA686A_INIT_TEMP_HYST 500
374
375#ifdef MODULE
376extern int init_module(void);
377extern int cleanup_module(void);
378#endif                          /* MODULE */
379
380/* For the VIA686A, we need to keep some data in memory. That
381   data is pointed to by via686a_list[NR]->data. The structure itself is
382   dynamically allocated, at the same time when a new via686a client is
383   allocated. */
384struct via686a_data {
385        struct semaphore lock;
386        int sysctl_id;
387
388        struct semaphore update_lock;
389        char valid;             /* !=0 if following fields are valid */
390        unsigned long last_updated;     /* In jiffies */
391
392        u8 in[5];               /* Register value */
393        u8 in_max[5];           /* Register value */
394        u8 in_min[5];           /* Register value */
395        u8 fan[2];              /* Register value */
396        u8 fan_min[2];          /* Register value */
397        u16 temp[3];            /* Register value 10 bit */
398        u8 temp_over[3];        /* Register value */
399        u8 temp_hyst[3];        /* Register value */
400        u8 fan_div[2];          /* Register encoding, shifted right */
401        u16 alarms;             /* Register encoding, combined */
402};
403
404static struct pci_dev *s_bridge;        /* pointer to the (only) via686a */
405
406#ifdef MODULE
407static
408#else
409extern
410#endif
411int __init sensors_via686a_init(void);
412static int __init via686a_cleanup(void);
413
414static int via686a_attach_adapter(struct i2c_adapter *adapter);
415static int via686a_detect(struct i2c_adapter *adapter, int address,
416                          unsigned short flags, int kind);
417static int via686a_detach_client(struct i2c_client *client);
418static int via686a_command(struct i2c_client *client, unsigned int cmd,
419                           void *arg);
420static void via686a_inc_use(struct i2c_client *client);
421static void via686a_dec_use(struct i2c_client *client);
422
423static int via686a_read_value(struct i2c_client *client, u8 register);
424static void via686a_write_value(struct i2c_client *client, u8 register,
425                                u8 value);
426static void via686a_update_client(struct i2c_client *client);
427static void via686a_init_client(struct i2c_client *client);
428static int via686a_find(int *address);
429
430
431static void via686a_in(struct i2c_client *client, int operation,
432                       int ctl_name, int *nrels_mag, long *results);
433static void via686a_fan(struct i2c_client *client, int operation,
434                        int ctl_name, int *nrels_mag, long *results);
435static void via686a_temp(struct i2c_client *client, int operation,
436                         int ctl_name, int *nrels_mag, long *results);
437static void via686a_alarms(struct i2c_client *client, int operation,
438                           int ctl_name, int *nrels_mag, long *results);
439static void via686a_fan_div(struct i2c_client *client, int operation,
440                            int ctl_name, int *nrels_mag, long *results);
441
442static int via686a_id = 0;
443
444/* The driver. I choose to use type i2c_driver, as at is identical to both
445   smbus_driver and isa_driver, and clients could be of either kind */
446static struct i2c_driver via686a_driver = {
447        /* name */ "VIA 686A",
448        /* id */ I2C_DRIVERID_VIA686A,
449        /* flags */ I2C_DF_NOTIFY,
450        /* attach_adapter */ &via686a_attach_adapter,
451        /* detach_client */ &via686a_detach_client,
452        /* command */ &via686a_command,
453        /* inc_use */ &via686a_inc_use,
454        /* dec_use */ &via686a_dec_use
455};
456
457/* Used by via686a_init/cleanup */
458static int __initdata via686a_initialized = 0;
459
460/* The /proc/sys entries */
461/* These files are created for each detected VIA686A. This is just a template;
462   though at first sight, you might think we could use a statically
463   allocated list, we need some way to get back to the parent - which
464   is done through one of the 'extra' fields which are initialized
465   when a new copy is allocated. */
466static ctl_table via686a_dir_table_template[] = {
467        {VIA686A_SYSCTL_IN0, "in0", NULL, 0, 0644, NULL, &sensors_proc_real,
468         &sensors_sysctl_real, NULL, &via686a_in},
469        {VIA686A_SYSCTL_IN1, "in1", NULL, 0, 0644, NULL, &sensors_proc_real,
470         &sensors_sysctl_real, NULL, &via686a_in},
471        {VIA686A_SYSCTL_IN2, "in2", NULL, 0, 0644, NULL, &sensors_proc_real,
472         &sensors_sysctl_real, NULL, &via686a_in},
473        {VIA686A_SYSCTL_IN3, "in3", NULL, 0, 0644, NULL, &sensors_proc_real,
474         &sensors_sysctl_real, NULL, &via686a_in},
475        {VIA686A_SYSCTL_IN4, "in4", NULL, 0, 0644, NULL, &sensors_proc_real,
476         &sensors_sysctl_real, NULL, &via686a_in},
477        {VIA686A_SYSCTL_FAN1, "fan1", NULL, 0, 0644, NULL, &sensors_proc_real,
478         &sensors_sysctl_real, NULL, &via686a_fan},
479        {VIA686A_SYSCTL_FAN2, "fan2", NULL, 0, 0644, NULL, &sensors_proc_real,
480         &sensors_sysctl_real, NULL, &via686a_fan},
481        {VIA686A_SYSCTL_TEMP, "temp1", NULL, 0, 0644, NULL, &sensors_proc_real,
482         &sensors_sysctl_real, NULL, &via686a_temp},
483        {VIA686A_SYSCTL_TEMP2, "temp2", NULL, 0, 0644, NULL,
484         &sensors_proc_real, &sensors_sysctl_real, NULL, &via686a_temp},
485        {VIA686A_SYSCTL_TEMP3, "temp3", NULL, 0, 0644, NULL,
486         &sensors_proc_real, &sensors_sysctl_real, NULL, &via686a_temp},
487        {VIA686A_SYSCTL_FAN_DIV, "fan_div", NULL, 0, 0644, NULL,
488         &sensors_proc_real, &sensors_sysctl_real, NULL, &via686a_fan_div},
489        {VIA686A_SYSCTL_ALARMS, "alarms", NULL, 0, 0444, NULL,
490         &sensors_proc_real, &sensors_sysctl_real, NULL, &via686a_alarms},
491        {0}
492};
493
494static inline int via686a_read_value(struct i2c_client *client, u8 reg)
495{
496        return (inb_p(client->addr + reg));
497}
498
499static inline void via686a_write_value(struct i2c_client *client, u8 reg,
500                                       u8 value)
501{
502        outb_p(value, client->addr + reg);
503}
504
505/* This is called when the module is loaded */
506int via686a_attach_adapter(struct i2c_adapter *adapter)
507{
508        return sensors_detect(adapter, &addr_data, via686a_detect);
509}
510
511/* Locate chip and get correct base address */
512int via686a_find(int *address)
513{
514        u16 val;
515
516        if (!pci_present())
517                return -ENODEV;
518
519        if (!(s_bridge = pci_find_device(PCI_VENDOR_ID_VIA,
520                                         PCI_DEVICE_ID_VIA_82C686_4,
521                                         NULL))) return -ENODEV;
522
523        if (PCIBIOS_SUCCESSFUL !=
524            pci_read_config_word(s_bridge, VIA686A_BASE_REG, &val))
525                return -ENODEV;
526        *address = val & ~(VIA686A_EXTENT - 1);
527        if (*address == 0) {
528                printk("via686a.o: base address not set - upgrade BIOS or use force=9191,addr\n");
529/*
530   If we do this then the module won't load and force won't work.
531   But unfortunately the above printk is printed even if we are doing a force.
532                return -ENODEV;
533*/
534        }
535/*
536   Moved below.
537        if (PCIBIOS_SUCCESSFUL !=
538            pci_read_config_word(s_bridge, VIA686A_ENABLE_REG, &val))
539                return -ENODEV;
540        if (!(val & 0x01)) {
541                printk("via686a.o: enabling sensors\n");
542                pci_write_config_word(s_bridge, VIA686A_ENABLE_REG,
543                                      val | 0x01);
544        }
545*/
546        return 0;
547}
548
549int via686a_detect(struct i2c_adapter *adapter, int address,
550                   unsigned short flags, int kind)
551{
552        int i;
553        struct i2c_client *new_client;
554        struct via686a_data *data;
555        int err = 0;
556        const char *type_name = "via686a";
557        u16 val;
558
559        /* Make sure we are probing the ISA bus!!  */
560        if (!i2c_is_isa_adapter(adapter)) {
561                printk
562                ("via686a.o: via686a_detect called for an I2C bus adapter?!?\n");
563                return 0;
564        }
565
566        if(kind >= 0)           /* force or force_via686a */
567                address &= ~(VIA686A_EXTENT - 1);
568        if (check_region(address, VIA686A_EXTENT)) {
569                printk("via686a.o: region 0x%x already in use!\n",
570                       address);
571                return -ENODEV;
572        }
573
574        if(kind >= 0) {         /* treat force and force_via686a equally */
575                printk("via686a.o: forcing ISA address 0x%04X\n", address);
576                if (PCIBIOS_SUCCESSFUL !=
577                    pci_write_config_word(s_bridge, VIA686A_BASE_REG, address))
578                        return -ENODEV;
579        }
580        if (PCIBIOS_SUCCESSFUL !=
581            pci_read_config_word(s_bridge, VIA686A_ENABLE_REG, &val))
582                return -ENODEV;
583        if (!(val & 0x0001)) {
584                printk("via686a.o: enabling sensors\n");
585                if (PCIBIOS_SUCCESSFUL !=
586                    pci_write_config_word(s_bridge, VIA686A_ENABLE_REG,
587                                      val | 0x0001))
588                        return -ENODEV;
589        }
590
591        if (!(new_client = kmalloc(sizeof(struct i2c_client) +
592                                   sizeof(struct via686a_data),
593                                   GFP_KERNEL))) {
594                err = -ENOMEM;
595                goto ERROR0;
596        }
597
598        data = (struct via686a_data *) (new_client + 1);
599        new_client->addr = address;
600        init_MUTEX(&data->lock);
601        new_client->data = data;
602        new_client->adapter = adapter;
603        new_client->driver = &via686a_driver;
604        new_client->flags = 0;
605
606        /* Reserve the ISA region */
607        request_region(address, VIA686A_EXTENT, "via686a-sensors");
608
609        /* Fill in the remaining client fields and put into the global list */
610        strcpy(new_client->name, "Via 686A Integrated Sensors");
611
612        new_client->id = via686a_id++;
613        data->valid = 0;
614        init_MUTEX(&data->update_lock);
615
616        /* Tell the I2C layer a new client has arrived */
617        if ((err = i2c_attach_client(new_client)))
618                goto ERROR3;
619
620        /* Register a new directory entry with module sensors */
621        if ((i = sensors_register_entry((struct i2c_client *) new_client,
622                                        type_name,
623                                        via686a_dir_table_template,
624                                        THIS_MODULE)) < 0) {
625                err = i;
626                goto ERROR4;
627        }
628        data->sysctl_id = i;
629
630        /* Initialize the VIA686A chip */
631        via686a_init_client(new_client);
632        return 0;
633
634      ERROR4:
635        i2c_detach_client(new_client);
636      ERROR3:
637        release_region(address, VIA686A_EXTENT);
638        kfree(new_client);
639      ERROR0:
640        return err;
641}
642
643int via686a_detach_client(struct i2c_client *client)
644{
645        int err;
646
647        sensors_deregister_entry(((struct via686a_data *) 
648                                  (client->data))->sysctl_id);
649
650        if ((err = i2c_detach_client(client))) {
651                printk
652                ("via686a.o: Client deregistration failed, client not detached.\n");
653                return err;
654        }
655
656        release_region(client->addr, VIA686A_EXTENT);
657        kfree(client);
658
659        return 0;
660}
661
662/* No commands defined yet */
663int via686a_command(struct i2c_client *client, unsigned int cmd, void *arg)
664{
665        return 0;
666}
667
668void via686a_inc_use(struct i2c_client *client)
669{
670        MOD_INC_USE_COUNT;
671}
672
673void via686a_dec_use(struct i2c_client *client)
674{
675        MOD_DEC_USE_COUNT;
676}
677
678/* Called when we have found a new VIA686A. Set limits, etc. */
679void via686a_init_client(struct i2c_client *client)
680{
681        int i;
682
683        /* Reset the device */
684        via686a_write_value(client, VIA686A_REG_CONFIG, 0x80);
685
686        via686a_write_value(client, VIA686A_REG_IN_MIN(0),
687                            IN_TO_REG(VIA686A_INIT_IN_MIN_0, 0));
688        via686a_write_value(client, VIA686A_REG_IN_MAX(0),
689                            IN_TO_REG(VIA686A_INIT_IN_MAX_0, 0));
690        via686a_write_value(client, VIA686A_REG_IN_MIN(1),
691                            IN_TO_REG(VIA686A_INIT_IN_MIN_1, 1));
692        via686a_write_value(client, VIA686A_REG_IN_MAX(1),
693                            IN_TO_REG(VIA686A_INIT_IN_MAX_1, 1));
694        via686a_write_value(client, VIA686A_REG_IN_MIN(2),
695                            IN_TO_REG(VIA686A_INIT_IN_MIN_2, 2));
696        via686a_write_value(client, VIA686A_REG_IN_MAX(2),
697                            IN_TO_REG(VIA686A_INIT_IN_MAX_2, 2));
698        via686a_write_value(client, VIA686A_REG_IN_MIN(3),
699                            IN_TO_REG(VIA686A_INIT_IN_MIN_3, 3));
700        via686a_write_value(client, VIA686A_REG_IN_MAX(3),
701                            IN_TO_REG(VIA686A_INIT_IN_MAX_3, 3));
702        via686a_write_value(client, VIA686A_REG_IN_MIN(4),
703                            IN_TO_REG(VIA686A_INIT_IN_MIN_4, 4));
704        via686a_write_value(client, VIA686A_REG_IN_MAX(4),
705                            IN_TO_REG(VIA686A_INIT_IN_MAX_4, 4));
706        via686a_write_value(client, VIA686A_REG_FAN_MIN(1),
707                            FAN_TO_REG(VIA686A_INIT_FAN_MIN, 2));
708        via686a_write_value(client, VIA686A_REG_FAN_MIN(2),
709                            FAN_TO_REG(VIA686A_INIT_FAN_MIN, 2));
710        for (i = 1; i <= 3; i++) {
711                via686a_write_value(client, VIA686A_REG_TEMP_OVER(i),
712                                    TEMP_TO_REG(VIA686A_INIT_TEMP_OVER));
713                via686a_write_value(client, VIA686A_REG_TEMP_HYST(i),
714                                    TEMP_TO_REG(VIA686A_INIT_TEMP_HYST));
715        }
716
717        /* Start monitoring */
718        via686a_write_value(client, VIA686A_REG_CONFIG, 0x01);
719
720        /* Cofigure temp interrupt mode for continuous-interrupt operation */
721        via686a_write_value(client, VIA686A_REG_TEMP_MODE, 
722                            via686a_read_value(client, VIA686A_REG_TEMP_MODE) &
723                            !(VIA686A_TEMP_MODE_MASK | VIA686A_TEMP_MODE_CONTINUOUS));
724}
725
726void via686a_update_client(struct i2c_client *client)
727{
728        struct via686a_data *data = client->data;
729        int i;
730
731        down(&data->update_lock);
732
733        if ((jiffies - data->last_updated > HZ + HZ / 2) ||
734            (jiffies < data->last_updated) || !data->valid) {
735
736                for (i = 0; i <= 4; i++) {
737                        data->in[i] =
738                            via686a_read_value(client, VIA686A_REG_IN(i));
739                        data->in_min[i] = via686a_read_value(client,
740                                                             VIA686A_REG_IN_MIN
741                                                             (i));
742                        data->in_max[i] =
743                            via686a_read_value(client, VIA686A_REG_IN_MAX(i));
744                }
745                for (i = 1; i <= 2; i++) {
746                        data->fan[i - 1] =
747                            via686a_read_value(client, VIA686A_REG_FAN(i));
748                        data->fan_min[i - 1] = via686a_read_value(client,
749                                                     VIA686A_REG_FAN_MIN(i));
750                }
751                for (i = 1; i <= 3; i++) {
752                        data->temp[i - 1] = via686a_read_value(client,
753                                                 VIA686A_REG_TEMP(i)) << 2;
754                        data->temp_over[i - 1] =
755                            via686a_read_value(client,
756                                               VIA686A_REG_TEMP_OVER(i));
757                        data->temp_hyst[i - 1] =
758                            via686a_read_value(client,
759                                               VIA686A_REG_TEMP_HYST(i));
760                }
761                /* add in lower 2 bits
762                   temp1 uses bits 7-6 of VIA686A_REG_TEMP_LOW1
763                   temp2 uses bits 5-4 of VIA686A_REG_TEMP_LOW23
764                   temp3 uses bits 7-6 of VIA686A_REG_TEMP_LOW23
765                 */
766                data->temp[0] |= (via686a_read_value(client,
767                                                     VIA686A_REG_TEMP_LOW1)
768                                  & 0xc0) >> 6;
769                data->temp[1] |=
770                    (via686a_read_value(client, VIA686A_REG_TEMP_LOW23) &
771                     0x30) >> 4;
772                data->temp[2] |=
773                    (via686a_read_value(client, VIA686A_REG_TEMP_LOW23) &
774                     0xc0) >> 6;
775
776                i = via686a_read_value(client, VIA686A_REG_FANDIV);
777                data->fan_div[0] = (i >> 4) & 0x03;
778                data->fan_div[1] = i >> 6;
779                data->alarms =
780                    via686a_read_value(client,
781                                       VIA686A_REG_ALARM1) |
782                    (via686a_read_value(client, VIA686A_REG_ALARM2) << 8);
783                data->last_updated = jiffies;
784                data->valid = 1;
785        }
786
787        up(&data->update_lock);
788}
789
790
791/* The next few functions are the call-back functions of the /proc/sys and
792   sysctl files. Which function is used is defined in the ctl_table in
793   the extra1 field.
794   Each function must return the magnitude (power of 10 to divide the date
795   with) if it is called with operation==SENSORS_PROC_REAL_INFO. It must
796   put a maximum of *nrels elements in results reflecting the data of this
797   file, and set *nrels to the number it actually put in it, if operation==
798   SENSORS_PROC_REAL_READ. Finally, it must get upto *nrels elements from
799   results and write them to the chip, if operations==SENSORS_PROC_REAL_WRITE.
800   Note that on SENSORS_PROC_REAL_READ, I do not check whether results is
801   large enough (by checking the incoming value of *nrels). This is not very
802   good practice, but as long as you put less than about 5 values in results,
803   you can assume it is large enough. */
804void via686a_in(struct i2c_client *client, int operation, int ctl_name,
805                int *nrels_mag, long *results)
806{
807        struct via686a_data *data = client->data;
808        int nr = ctl_name - VIA686A_SYSCTL_IN0;
809
810        if (operation == SENSORS_PROC_REAL_INFO)
811                *nrels_mag = 2;
812        else if (operation == SENSORS_PROC_REAL_READ) {
813                via686a_update_client(client);
814                results[0] = IN_FROM_REG(data->in_min[nr], nr);
815                results[1] = IN_FROM_REG(data->in_max[nr], nr);
816                results[2] = IN_FROM_REG(data->in[nr], nr);
817                *nrels_mag = 3;
818        } else if (operation == SENSORS_PROC_REAL_WRITE) {
819                if (*nrels_mag >= 1) {
820                        data->in_min[nr] = IN_TO_REG(results[0], nr);
821                        via686a_write_value(client, VIA686A_REG_IN_MIN(nr),
822                                            data->in_min[nr]);
823                }
824                if (*nrels_mag >= 2) {
825                        data->in_max[nr] = IN_TO_REG(results[1], nr);
826                        via686a_write_value(client, VIA686A_REG_IN_MAX(nr),
827                                            data->in_max[nr]);
828                }
829        }
830}
831
832void via686a_fan(struct i2c_client *client, int operation, int ctl_name,
833                 int *nrels_mag, long *results)
834{
835        struct via686a_data *data = client->data;
836        int nr = ctl_name - VIA686A_SYSCTL_FAN1 + 1;
837
838        if (operation == SENSORS_PROC_REAL_INFO)
839                *nrels_mag = 0;
840        else if (operation == SENSORS_PROC_REAL_READ) {
841                via686a_update_client(client);
842                results[0] = FAN_FROM_REG(data->fan_min[nr - 1],
843                                          DIV_FROM_REG(data->fan_div
844                                                       [nr - 1]));
845                results[1] =
846                    FAN_FROM_REG(data->fan[nr - 1],
847                                 DIV_FROM_REG(data->fan_div[nr - 1]));
848                *nrels_mag = 2;
849        } else if (operation == SENSORS_PROC_REAL_WRITE) {
850                if (*nrels_mag >= 1) {
851                        data->fan_min[nr - 1] = FAN_TO_REG(results[0], 
852                                                           DIV_FROM_REG(data->
853                                                              fan_div[nr -1]));
854                        via686a_write_value(client,
855                                            VIA686A_REG_FAN_MIN(nr),
856                                            data->fan_min[nr - 1]);
857                }
858        }
859}
860
861void via686a_temp(struct i2c_client *client, int operation, int ctl_name,
862                  int *nrels_mag, long *results)
863{
864        struct via686a_data *data = client->data;
865        int nr = ctl_name - VIA686A_SYSCTL_TEMP;
866
867        if (operation == SENSORS_PROC_REAL_INFO)
868                *nrels_mag = 1;
869        else if (operation == SENSORS_PROC_REAL_READ) {
870                via686a_update_client(client);
871                results[0] = TEMP_FROM_REG(data->temp_over[nr]);
872                results[1] = TEMP_FROM_REG(data->temp_hyst[nr]);
873                results[2] = TEMP_FROM_REG10(data->temp[nr]);
874                *nrels_mag = 3;
875        } else if (operation == SENSORS_PROC_REAL_WRITE) {
876                if (*nrels_mag >= 1) {
877                        data->temp_over[nr] = TEMP_TO_REG(results[0]);
878                        via686a_write_value(client,
879                                            VIA686A_REG_TEMP_OVER(nr + 1),
880                                            data->temp_over[nr]);
881                }
882                if (*nrels_mag >= 2) {
883                        data->temp_hyst[nr] = TEMP_TO_REG(results[1]);
884                        via686a_write_value(client,
885                                            VIA686A_REG_TEMP_HYST(nr + 1),
886                                            data->temp_hyst[nr]);
887                }
888        }
889}
890
891void via686a_alarms(struct i2c_client *client, int operation, int ctl_name,
892                    int *nrels_mag, long *results)
893{
894        struct via686a_data *data = client->data;
895        if (operation == SENSORS_PROC_REAL_INFO)
896                *nrels_mag = 0;
897        else if (operation == SENSORS_PROC_REAL_READ) {
898                via686a_update_client(client);
899                results[0] = ALARMS_FROM_REG(data->alarms);
900                *nrels_mag = 1;
901        }
902}
903
904void via686a_fan_div(struct i2c_client *client, int operation,
905                     int ctl_name, int *nrels_mag, long *results)
906{
907        struct via686a_data *data = client->data;
908        int old;
909
910        if (operation == SENSORS_PROC_REAL_INFO)
911                *nrels_mag = 0;
912        else if (operation == SENSORS_PROC_REAL_READ) {
913                via686a_update_client(client);
914                results[0] = DIV_FROM_REG(data->fan_div[0]);
915                results[1] = DIV_FROM_REG(data->fan_div[1]);
916                *nrels_mag = 2;
917        } else if (operation == SENSORS_PROC_REAL_WRITE) {
918                old = via686a_read_value(client, VIA686A_REG_FANDIV);
919                if (*nrels_mag >= 2) {
920                        data->fan_div[1] = DIV_TO_REG(results[1]);
921                        old = (old & 0x3f) | (data->fan_div[1] << 6);
922                }
923                if (*nrels_mag >= 1) {
924                        data->fan_div[0] = DIV_TO_REG(results[0]);
925                        old = (old & 0xcf) | (data->fan_div[0] << 4);
926                        via686a_write_value(client, VIA686A_REG_FANDIV,
927                                            old);
928                }
929        }
930}
931
932int __init sensors_via686a_init(void)
933{
934        int res, addr;
935
936        printk("via686a.o version %s (%s)\n", LM_VERSION, LM_DATE);
937        via686a_initialized = 0;
938
939        if (via686a_find(&addr)) {
940                printk("via686a.o: No Via 686A sensors found.\n");
941                return -ENODEV;
942        }
943        normal_isa[0] = addr;
944
945        if ((res = i2c_add_driver(&via686a_driver))) {
946                printk("via686a.o: Driver registration failed.\n");
947                via686a_cleanup();
948                return res;
949        }
950        via686a_initialized++;
951        return 0;
952}
953
954int __init via686a_cleanup(void)
955{
956        int res;
957
958        if (via686a_initialized >= 1) {
959                if ((res = i2c_del_driver(&via686a_driver))) {
960                        printk
961                            ("via686a.o: Driver deregistration failed.\n");
962                        return res;
963                }
964                via686a_initialized--;
965        }
966        return 0;
967}
968
969EXPORT_NO_SYMBOLS;
970
971#ifdef MODULE
972
973MODULE_AUTHOR
974    ("Kyösti Mälkki <kmalkki@cc.hut.fi>, Mark Studebaker <mdsxyz123@yahoo.com>, Bob Dougherty <bobd@stanford.edu>");
975MODULE_DESCRIPTION("VIA 686A Sensor device");
976
977int init_module(void)
978{
979        return sensors_via686a_init();
980}
981
982int cleanup_module(void)
983{
984        return via686a_cleanup();
985}
986
987#endif                          /* MODULE */
Note: See TracBrowser for help on using the browser.