]> bbs.cooldavid.org Git - net-next-2.6.git/blame - drivers/hwmon/via686a.c
hwmon: (lm70) Add TI TMP121 support
[net-next-2.6.git] / drivers / hwmon / via686a.c
CommitLineData
1da177e4
LT
1/*
2 via686a.c - Part of lm_sensors, Linux kernel modules
6328c0e1 3 for hardware monitoring
be8992c2 4
1da177e4 5 Copyright (c) 1998 - 2002 Frodo Looijaard <frodol@dds.nl>,
96de0e25 6 Kyösti Mälkki <kmalkki@cc.hut.fi>,
1da177e4
LT
7 Mark Studebaker <mdsxyz123@yahoo.com>,
8 and Bob Dougherty <bobd@stanford.edu>
be8992c2 9 (Some conversion-factor data were contributed by Jonathan Teh Soon Yew
1da177e4
LT
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 Warning - only supports a single device.
31*/
32
1da177e4
LT
33#include <linux/module.h>
34#include <linux/slab.h>
35#include <linux/pci.h>
1da177e4 36#include <linux/jiffies.h>
2ec342e6 37#include <linux/platform_device.h>
943b0830 38#include <linux/hwmon.h>
1e71a5a2 39#include <linux/hwmon-sysfs.h>
943b0830 40#include <linux/err.h>
1da177e4 41#include <linux/init.h>
9a61bf63 42#include <linux/mutex.h>
a5ebe668 43#include <linux/sysfs.h>
1da177e4
LT
44#include <asm/io.h>
45
46
47/* If force_addr is set to anything different from 0, we forcibly enable
48 the device at the given address. */
02002963 49static unsigned short force_addr;
1da177e4
LT
50module_param(force_addr, ushort, 0);
51MODULE_PARM_DESC(force_addr,
52 "Initialize the base address of the sensors");
53
2ec342e6 54static struct platform_device *pdev;
1da177e4
LT
55
56/*
57 The Via 686a southbridge has a LM78-like chip integrated on the same IC.
58 This driver is a customized copy of lm78.c
59*/
60
61/* Many VIA686A constants specified below */
62
63/* Length of ISA address segment */
be8992c2
JD
64#define VIA686A_EXTENT 0x80
65#define VIA686A_BASE_REG 0x70
66#define VIA686A_ENABLE_REG 0x74
1da177e4
LT
67
68/* The VIA686A registers */
69/* ins numbered 0-4 */
be8992c2
JD
70#define VIA686A_REG_IN_MAX(nr) (0x2b + ((nr) * 2))
71#define VIA686A_REG_IN_MIN(nr) (0x2c + ((nr) * 2))
72#define VIA686A_REG_IN(nr) (0x22 + (nr))
1da177e4
LT
73
74/* fans numbered 1-2 */
be8992c2
JD
75#define VIA686A_REG_FAN_MIN(nr) (0x3a + (nr))
76#define VIA686A_REG_FAN(nr) (0x28 + (nr))
1da177e4 77
1da177e4 78/* temps numbered 1-3 */
563db2fe
JD
79static const u8 VIA686A_REG_TEMP[] = { 0x20, 0x21, 0x1f };
80static const u8 VIA686A_REG_TEMP_OVER[] = { 0x39, 0x3d, 0x1d };
81static const u8 VIA686A_REG_TEMP_HYST[] = { 0x3a, 0x3e, 0x1e };
be8992c2
JD
82/* bits 7-6 */
83#define VIA686A_REG_TEMP_LOW1 0x4b
84/* 2 = bits 5-4, 3 = bits 7-6 */
85#define VIA686A_REG_TEMP_LOW23 0x49
86
87#define VIA686A_REG_ALARM1 0x41
88#define VIA686A_REG_ALARM2 0x42
89#define VIA686A_REG_FANDIV 0x47
90#define VIA686A_REG_CONFIG 0x40
91/* The following register sets temp interrupt mode (bits 1-0 for temp1,
1da177e4
LT
92 3-2 for temp2, 5-4 for temp3). Modes are:
93 00 interrupt stays as long as value is out-of-range
94 01 interrupt is cleared once register is read (default)
95 10 comparator mode- like 00, but ignores hysteresis
96 11 same as 00 */
be8992c2 97#define VIA686A_REG_TEMP_MODE 0x4b
1da177e4 98/* We'll just assume that you want to set all 3 simultaneously: */
be8992c2
JD
99#define VIA686A_TEMP_MODE_MASK 0x3F
100#define VIA686A_TEMP_MODE_CONTINUOUS 0x00
1da177e4
LT
101
102/* Conversions. Limit checking is only done on the TO_REG
be8992c2 103 variants.
1da177e4
LT
104
105********* VOLTAGE CONVERSIONS (Bob Dougherty) ********
106 From HWMon.cpp (Copyright 1998-2000 Jonathan Teh Soon Yew):
107 voltagefactor[0]=1.25/2628; (2628/1.25=2102.4) // Vccp
108 voltagefactor[1]=1.25/2628; (2628/1.25=2102.4) // +2.5V
109 voltagefactor[2]=1.67/2628; (2628/1.67=1573.7) // +3.3V
110 voltagefactor[3]=2.6/2628; (2628/2.60=1010.8) // +5V
111 voltagefactor[4]=6.3/2628; (2628/6.30=417.14) // +12V
112 in[i]=(data[i+2]*25.0+133)*voltagefactor[i];
113 That is:
114 volts = (25*regVal+133)*factor
115 regVal = (volts/factor-133)/25
be8992c2 116 (These conversions were contributed by Jonathan Teh Soon Yew
1da177e4
LT
117 <j.teh@iname.com>) */
118static inline u8 IN_TO_REG(long val, int inNum)
119{
120 /* To avoid floating point, we multiply constants by 10 (100 for +12V).
121 Rounding is done (120500 is actually 133000 - 12500).
122 Remember that val is expressed in 0.001V/bit, which is why we divide
123 by an additional 10000 (100000 for +12V): 1000 for val and 10 (100)
124 for the constants. */
125 if (inNum <= 1)
126 return (u8)
127 SENSORS_LIMIT((val * 21024 - 1205000) / 250000, 0, 255);
128 else if (inNum == 2)
129 return (u8)
130 SENSORS_LIMIT((val * 15737 - 1205000) / 250000, 0, 255);
131 else if (inNum == 3)
132 return (u8)
133 SENSORS_LIMIT((val * 10108 - 1205000) / 250000, 0, 255);
134 else
135 return (u8)
136 SENSORS_LIMIT((val * 41714 - 12050000) / 2500000, 0, 255);
137}
138
139static inline long IN_FROM_REG(u8 val, int inNum)
140{
141 /* To avoid floating point, we multiply constants by 10 (100 for +12V).
142 We also multiply them by 1000 because we want 0.001V/bit for the
143 output value. Rounding is done. */
144 if (inNum <= 1)
145 return (long) ((250000 * val + 1330000 + 21024 / 2) / 21024);
146 else if (inNum == 2)
147 return (long) ((250000 * val + 1330000 + 15737 / 2) / 15737);
148 else if (inNum == 3)
149 return (long) ((250000 * val + 1330000 + 10108 / 2) / 10108);
150 else
151 return (long) ((2500000 * val + 13300000 + 41714 / 2) / 41714);
152}
153
154/********* FAN RPM CONVERSIONS ********/
155/* Higher register values = slower fans (the fan's strobe gates a counter).
156 But this chip saturates back at 0, not at 255 like all the other chips.
157 So, 0 means 0 RPM */
158static inline u8 FAN_TO_REG(long rpm, int div)
159{
160 if (rpm == 0)
161 return 0;
162 rpm = SENSORS_LIMIT(rpm, 1, 1000000);
163 return SENSORS_LIMIT((1350000 + rpm * div / 2) / (rpm * div), 1, 255);
164}
165
166#define FAN_FROM_REG(val,div) ((val)==0?0:(val)==255?0:1350000/((val)*(div)))
167
168/******** TEMP CONVERSIONS (Bob Dougherty) *********/
169/* linear fits from HWMon.cpp (Copyright 1998-2000 Jonathan Teh Soon Yew)
170 if(temp<169)
6328c0e1 171 return double(temp)*0.427-32.08;
1da177e4 172 else if(temp>=169 && temp<=202)
6328c0e1 173 return double(temp)*0.582-58.16;
1da177e4 174 else
6328c0e1 175 return double(temp)*0.924-127.33;
1da177e4 176
be8992c2
JD
177 A fifth-order polynomial fits the unofficial data (provided by Alex van
178 Kaam <darkside@chello.nl>) a bit better. It also give more reasonable
179 numbers on my machine (ie. they agree with what my BIOS tells me).
1da177e4 180 Here's the fifth-order fit to the 8-bit data:
be8992c2 181 temp = 1.625093e-10*val^5 - 1.001632e-07*val^4 + 2.457653e-05*val^3 -
6328c0e1 182 2.967619e-03*val^2 + 2.175144e-01*val - 7.090067e+0.
1da177e4 183
be8992c2 184 (2000-10-25- RFD: thanks to Uwe Andersen <uandersen@mayah.com> for
1da177e4
LT
185 finding my typos in this formula!)
186
be8992c2
JD
187 Alas, none of the elegant function-fit solutions will work because we
188 aren't allowed to use floating point in the kernel and doing it with
189 integers doesn't provide enough precision. So we'll do boring old
190 look-up table stuff. The unofficial data (see below) have effectively
191 7-bit resolution (they are rounded to the nearest degree). I'm assuming
192 that the transfer function of the device is monotonic and smooth, so a
193 smooth function fit to the data will allow us to get better precision.
1da177e4 194 I used the 5th-order poly fit described above and solved for
be8992c2
JD
195 VIA register values 0-255. I *10 before rounding, so we get tenth-degree
196 precision. (I could have done all 1024 values for our 10-bit readings,
197 but the function is very linear in the useful range (0-80 deg C), so
198 we'll just use linear interpolation for 10-bit readings.) So, tempLUT
1da177e4 199 is the temp at via register values 0-255: */
088341bd 200static const s16 tempLUT[] =
be8992c2
JD
201{ -709, -688, -667, -646, -627, -607, -589, -570, -553, -536, -519,
202 -503, -487, -471, -456, -442, -428, -414, -400, -387, -375,
203 -362, -350, -339, -327, -316, -305, -295, -285, -275, -265,
204 -255, -246, -237, -229, -220, -212, -204, -196, -188, -180,
205 -173, -166, -159, -152, -145, -139, -132, -126, -120, -114,
206 -108, -102, -96, -91, -85, -80, -74, -69, -64, -59, -54, -49,
207 -44, -39, -34, -29, -25, -20, -15, -11, -6, -2, 3, 7, 12, 16,
208 20, 25, 29, 33, 37, 42, 46, 50, 54, 59, 63, 67, 71, 75, 79, 84,
209 88, 92, 96, 100, 104, 109, 113, 117, 121, 125, 130, 134, 138,
210 142, 146, 151, 155, 159, 163, 168, 172, 176, 181, 185, 189,
211 193, 198, 202, 206, 211, 215, 219, 224, 228, 232, 237, 241,
212 245, 250, 254, 259, 263, 267, 272, 276, 281, 285, 290, 294,
213 299, 303, 307, 312, 316, 321, 325, 330, 334, 339, 344, 348,
214 353, 357, 362, 366, 371, 376, 380, 385, 390, 395, 399, 404,
215 409, 414, 419, 423, 428, 433, 438, 443, 449, 454, 459, 464,
216 469, 475, 480, 486, 491, 497, 502, 508, 514, 520, 526, 532,
217 538, 544, 551, 557, 564, 571, 578, 584, 592, 599, 606, 614,
218 621, 629, 637, 645, 654, 662, 671, 680, 689, 698, 708, 718,
219 728, 738, 749, 759, 770, 782, 793, 805, 818, 830, 843, 856,
220 870, 883, 898, 912, 927, 943, 958, 975, 991, 1008, 1026, 1044,
221 1062, 1081, 1101, 1121, 1141, 1162, 1184, 1206, 1229, 1252,
222 1276, 1301, 1326, 1352, 1378, 1406, 1434, 1462
1da177e4
LT
223};
224
be8992c2 225/* the original LUT values from Alex van Kaam <darkside@chello.nl>
1da177e4
LT
226 (for via register values 12-240):
227{-50,-49,-47,-45,-43,-41,-39,-38,-37,-35,-34,-33,-32,-31,
228-30,-29,-28,-27,-26,-25,-24,-24,-23,-22,-21,-20,-20,-19,-18,-17,-17,-16,-15,
229-15,-14,-14,-13,-12,-12,-11,-11,-10,-9,-9,-8,-8,-7,-7,-6,-6,-5,-5,-4,-4,-3,
230-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,
23112,12,13,13,13,14,14,15,15,16,16,16,17,17,18,18,19,19,20,20,21,21,21,22,22,
23222,23,23,24,24,25,25,26,26,26,27,27,27,28,28,29,29,30,30,30,31,31,32,32,33,
23333,34,34,35,35,35,36,36,37,37,38,38,39,39,40,40,41,41,42,42,43,43,44,44,45,
23445,46,46,47,48,48,49,49,50,51,51,52,52,53,53,54,55,55,56,57,57,58,59,59,60,
23561,62,62,63,64,65,66,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,83,84,
23685,86,88,89,91,92,94,96,97,99,101,103,105,107,109,110};
237
238
239 Here's the reverse LUT. I got it by doing a 6-th order poly fit (needed
be8992c2
JD
240 an extra term for a good fit to these inverse data!) and then
241 solving for each temp value from -50 to 110 (the useable range for
242 this chip). Here's the fit:
243 viaRegVal = -1.160370e-10*val^6 +3.193693e-08*val^5 - 1.464447e-06*val^4
1da177e4
LT
244 - 2.525453e-04*val^3 + 1.424593e-02*val^2 + 2.148941e+00*val +7.275808e+01)
245 Note that n=161: */
246static const u8 viaLUT[] =
be8992c2
JD
247{ 12, 12, 13, 14, 14, 15, 16, 16, 17, 18, 18, 19, 20, 20, 21, 22, 23,
248 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 35, 36, 37, 39, 40,
249 41, 43, 45, 46, 48, 49, 51, 53, 55, 57, 59, 60, 62, 64, 66,
250 69, 71, 73, 75, 77, 79, 82, 84, 86, 88, 91, 93, 95, 98, 100,
251 103, 105, 107, 110, 112, 115, 117, 119, 122, 124, 126, 129,
252 131, 134, 136, 138, 140, 143, 145, 147, 150, 152, 154, 156,
253 158, 160, 162, 164, 166, 168, 170, 172, 174, 176, 178, 180,
254 182, 183, 185, 187, 188, 190, 192, 193, 195, 196, 198, 199,
255 200, 202, 203, 205, 206, 207, 208, 209, 210, 211, 212, 213,
256 214, 215, 216, 217, 218, 219, 220, 221, 222, 222, 223, 224,
257 225, 226, 226, 227, 228, 228, 229, 230, 230, 231, 232, 232,
258 233, 233, 234, 235, 235, 236, 236, 237, 237, 238, 238, 239,
259 239, 240
1da177e4
LT
260};
261
262/* Converting temps to (8-bit) hyst and over registers
263 No interpolation here.
264 The +50 is because the temps start at -50 */
265static inline u8 TEMP_TO_REG(long val)
266{
be8992c2 267 return viaLUT[val <= -50000 ? 0 : val >= 110000 ? 160 :
1da177e4
LT
268 (val < 0 ? val - 500 : val + 500) / 1000 + 50];
269}
270
271/* for 8-bit temperature hyst and over registers */
088341bd 272#define TEMP_FROM_REG(val) ((long)tempLUT[val] * 100)
1da177e4
LT
273
274/* for 10-bit temperature readings */
275static inline long TEMP_FROM_REG10(u16 val)
276{
277 u16 eightBits = val >> 2;
278 u16 twoBits = val & 3;
279
280 /* no interpolation for these */
281 if (twoBits == 0 || eightBits == 255)
282 return TEMP_FROM_REG(eightBits);
283
284 /* do some linear interpolation */
285 return (tempLUT[eightBits] * (4 - twoBits) +
be8992c2 286 tempLUT[eightBits + 1] * twoBits) * 25;
1da177e4
LT
287}
288
1da177e4
LT
289#define DIV_FROM_REG(val) (1 << (val))
290#define DIV_TO_REG(val) ((val)==8?3:(val)==4?2:(val)==1?0:1)
291
ed6bafbf
JD
292/* For each registered chip, we need to keep some data in memory.
293 The structure is dynamically allocated. */
1da177e4 294struct via686a_data {
2ec342e6
JD
295 unsigned short addr;
296 const char *name;
1beeffe4 297 struct device *hwmon_dev;
9a61bf63 298 struct mutex update_lock;
1da177e4
LT
299 char valid; /* !=0 if following fields are valid */
300 unsigned long last_updated; /* In jiffies */
301
302 u8 in[5]; /* Register value */
303 u8 in_max[5]; /* Register value */
304 u8 in_min[5]; /* Register value */
305 u8 fan[2]; /* Register value */
306 u8 fan_min[2]; /* Register value */
307 u16 temp[3]; /* Register value 10 bit */
308 u8 temp_over[3]; /* Register value */
309 u8 temp_hyst[3]; /* Register value */
310 u8 fan_div[2]; /* Register encoding, shifted right */
311 u16 alarms; /* Register encoding, combined */
312};
313
314static struct pci_dev *s_bridge; /* pointer to the (only) via686a */
315
2ec342e6 316static int via686a_probe(struct platform_device *pdev);
d0546128 317static int __devexit via686a_remove(struct platform_device *pdev);
1da177e4 318
2ec342e6 319static inline int via686a_read_value(struct via686a_data *data, u8 reg)
1da177e4 320{
2ec342e6 321 return inb_p(data->addr + reg);
1da177e4
LT
322}
323
2ec342e6 324static inline void via686a_write_value(struct via686a_data *data, u8 reg,
1da177e4
LT
325 u8 value)
326{
2ec342e6 327 outb_p(value, data->addr + reg);
1da177e4
LT
328}
329
330static struct via686a_data *via686a_update_device(struct device *dev);
2ec342e6 331static void via686a_init_device(struct via686a_data *data);
1da177e4
LT
332
333/* following are the sysfs callback functions */
334
335/* 7 voltage sensors */
1e71a5a2
JD
336static ssize_t show_in(struct device *dev, struct device_attribute *da,
337 char *buf) {
1da177e4 338 struct via686a_data *data = via686a_update_device(dev);
1e71a5a2
JD
339 struct sensor_device_attribute *attr = to_sensor_dev_attr(da);
340 int nr = attr->index;
1da177e4
LT
341 return sprintf(buf, "%ld\n", IN_FROM_REG(data->in[nr], nr));
342}
343
1e71a5a2
JD
344static ssize_t show_in_min(struct device *dev, struct device_attribute *da,
345 char *buf) {
1da177e4 346 struct via686a_data *data = via686a_update_device(dev);
1e71a5a2
JD
347 struct sensor_device_attribute *attr = to_sensor_dev_attr(da);
348 int nr = attr->index;
1da177e4
LT
349 return sprintf(buf, "%ld\n", IN_FROM_REG(data->in_min[nr], nr));
350}
351
1e71a5a2
JD
352static ssize_t show_in_max(struct device *dev, struct device_attribute *da,
353 char *buf) {
1da177e4 354 struct via686a_data *data = via686a_update_device(dev);
1e71a5a2
JD
355 struct sensor_device_attribute *attr = to_sensor_dev_attr(da);
356 int nr = attr->index;
1da177e4
LT
357 return sprintf(buf, "%ld\n", IN_FROM_REG(data->in_max[nr], nr));
358}
359
1e71a5a2
JD
360static ssize_t set_in_min(struct device *dev, struct device_attribute *da,
361 const char *buf, size_t count) {
2ec342e6 362 struct via686a_data *data = dev_get_drvdata(dev);
1e71a5a2
JD
363 struct sensor_device_attribute *attr = to_sensor_dev_attr(da);
364 int nr = attr->index;
1da177e4
LT
365 unsigned long val = simple_strtoul(buf, NULL, 10);
366
9a61bf63 367 mutex_lock(&data->update_lock);
be8992c2 368 data->in_min[nr] = IN_TO_REG(val, nr);
2ec342e6 369 via686a_write_value(data, VIA686A_REG_IN_MIN(nr),
1da177e4 370 data->in_min[nr]);
9a61bf63 371 mutex_unlock(&data->update_lock);
1da177e4
LT
372 return count;
373}
1e71a5a2
JD
374static ssize_t set_in_max(struct device *dev, struct device_attribute *da,
375 const char *buf, size_t count) {
2ec342e6 376 struct via686a_data *data = dev_get_drvdata(dev);
1e71a5a2
JD
377 struct sensor_device_attribute *attr = to_sensor_dev_attr(da);
378 int nr = attr->index;
1da177e4
LT
379 unsigned long val = simple_strtoul(buf, NULL, 10);
380
9a61bf63 381 mutex_lock(&data->update_lock);
be8992c2 382 data->in_max[nr] = IN_TO_REG(val, nr);
2ec342e6 383 via686a_write_value(data, VIA686A_REG_IN_MAX(nr),
1da177e4 384 data->in_max[nr]);
9a61bf63 385 mutex_unlock(&data->update_lock);
1da177e4
LT
386 return count;
387}
388#define show_in_offset(offset) \
1e71a5a2
JD
389static SENSOR_DEVICE_ATTR(in##offset##_input, S_IRUGO, \
390 show_in, NULL, offset); \
391static SENSOR_DEVICE_ATTR(in##offset##_min, S_IRUGO | S_IWUSR, \
392 show_in_min, set_in_min, offset); \
393static SENSOR_DEVICE_ATTR(in##offset##_max, S_IRUGO | S_IWUSR, \
394 show_in_max, set_in_max, offset);
1da177e4
LT
395
396show_in_offset(0);
397show_in_offset(1);
398show_in_offset(2);
399show_in_offset(3);
400show_in_offset(4);
401
402/* 3 temperatures */
1e71a5a2
JD
403static ssize_t show_temp(struct device *dev, struct device_attribute *da,
404 char *buf) {
1da177e4 405 struct via686a_data *data = via686a_update_device(dev);
1e71a5a2
JD
406 struct sensor_device_attribute *attr = to_sensor_dev_attr(da);
407 int nr = attr->index;
1da177e4
LT
408 return sprintf(buf, "%ld\n", TEMP_FROM_REG10(data->temp[nr]));
409}
1e71a5a2
JD
410static ssize_t show_temp_over(struct device *dev, struct device_attribute *da,
411 char *buf) {
1da177e4 412 struct via686a_data *data = via686a_update_device(dev);
1e71a5a2
JD
413 struct sensor_device_attribute *attr = to_sensor_dev_attr(da);
414 int nr = attr->index;
1da177e4
LT
415 return sprintf(buf, "%ld\n", TEMP_FROM_REG(data->temp_over[nr]));
416}
1e71a5a2
JD
417static ssize_t show_temp_hyst(struct device *dev, struct device_attribute *da,
418 char *buf) {
1da177e4 419 struct via686a_data *data = via686a_update_device(dev);
1e71a5a2
JD
420 struct sensor_device_attribute *attr = to_sensor_dev_attr(da);
421 int nr = attr->index;
1da177e4
LT
422 return sprintf(buf, "%ld\n", TEMP_FROM_REG(data->temp_hyst[nr]));
423}
1e71a5a2
JD
424static ssize_t set_temp_over(struct device *dev, struct device_attribute *da,
425 const char *buf, size_t count) {
2ec342e6 426 struct via686a_data *data = dev_get_drvdata(dev);
1e71a5a2
JD
427 struct sensor_device_attribute *attr = to_sensor_dev_attr(da);
428 int nr = attr->index;
1da177e4
LT
429 int val = simple_strtol(buf, NULL, 10);
430
9a61bf63 431 mutex_lock(&data->update_lock);
1da177e4 432 data->temp_over[nr] = TEMP_TO_REG(val);
2ec342e6 433 via686a_write_value(data, VIA686A_REG_TEMP_OVER[nr],
563db2fe 434 data->temp_over[nr]);
9a61bf63 435 mutex_unlock(&data->update_lock);
1da177e4
LT
436 return count;
437}
1e71a5a2
JD
438static ssize_t set_temp_hyst(struct device *dev, struct device_attribute *da,
439 const char *buf, size_t count) {
2ec342e6 440 struct via686a_data *data = dev_get_drvdata(dev);
1e71a5a2
JD
441 struct sensor_device_attribute *attr = to_sensor_dev_attr(da);
442 int nr = attr->index;
1da177e4
LT
443 int val = simple_strtol(buf, NULL, 10);
444
9a61bf63 445 mutex_lock(&data->update_lock);
1da177e4 446 data->temp_hyst[nr] = TEMP_TO_REG(val);
2ec342e6 447 via686a_write_value(data, VIA686A_REG_TEMP_HYST[nr],
563db2fe 448 data->temp_hyst[nr]);
9a61bf63 449 mutex_unlock(&data->update_lock);
1da177e4
LT
450 return count;
451}
452#define show_temp_offset(offset) \
1e71a5a2
JD
453static SENSOR_DEVICE_ATTR(temp##offset##_input, S_IRUGO, \
454 show_temp, NULL, offset - 1); \
455static SENSOR_DEVICE_ATTR(temp##offset##_max, S_IRUGO | S_IWUSR, \
456 show_temp_over, set_temp_over, offset - 1); \
457static SENSOR_DEVICE_ATTR(temp##offset##_max_hyst, S_IRUGO | S_IWUSR, \
458 show_temp_hyst, set_temp_hyst, offset - 1);
1da177e4
LT
459
460show_temp_offset(1);
461show_temp_offset(2);
462show_temp_offset(3);
463
464/* 2 Fans */
1e71a5a2
JD
465static ssize_t show_fan(struct device *dev, struct device_attribute *da,
466 char *buf) {
1da177e4 467 struct via686a_data *data = via686a_update_device(dev);
1e71a5a2
JD
468 struct sensor_device_attribute *attr = to_sensor_dev_attr(da);
469 int nr = attr->index;
be8992c2 470 return sprintf(buf, "%d\n", FAN_FROM_REG(data->fan[nr],
1da177e4
LT
471 DIV_FROM_REG(data->fan_div[nr])) );
472}
1e71a5a2
JD
473static ssize_t show_fan_min(struct device *dev, struct device_attribute *da,
474 char *buf) {
1da177e4 475 struct via686a_data *data = via686a_update_device(dev);
1e71a5a2
JD
476 struct sensor_device_attribute *attr = to_sensor_dev_attr(da);
477 int nr = attr->index;
be8992c2 478 return sprintf(buf, "%d\n",
1da177e4
LT
479 FAN_FROM_REG(data->fan_min[nr], DIV_FROM_REG(data->fan_div[nr])) );
480}
1e71a5a2
JD
481static ssize_t show_fan_div(struct device *dev, struct device_attribute *da,
482 char *buf) {
1da177e4 483 struct via686a_data *data = via686a_update_device(dev);
1e71a5a2
JD
484 struct sensor_device_attribute *attr = to_sensor_dev_attr(da);
485 int nr = attr->index;
be8992c2 486 return sprintf(buf, "%d\n", DIV_FROM_REG(data->fan_div[nr]) );
1da177e4 487}
1e71a5a2
JD
488static ssize_t set_fan_min(struct device *dev, struct device_attribute *da,
489 const char *buf, size_t count) {
2ec342e6 490 struct via686a_data *data = dev_get_drvdata(dev);
1e71a5a2
JD
491 struct sensor_device_attribute *attr = to_sensor_dev_attr(da);
492 int nr = attr->index;
1da177e4
LT
493 int val = simple_strtol(buf, NULL, 10);
494
9a61bf63 495 mutex_lock(&data->update_lock);
1da177e4 496 data->fan_min[nr] = FAN_TO_REG(val, DIV_FROM_REG(data->fan_div[nr]));
2ec342e6 497 via686a_write_value(data, VIA686A_REG_FAN_MIN(nr+1), data->fan_min[nr]);
9a61bf63 498 mutex_unlock(&data->update_lock);
1da177e4
LT
499 return count;
500}
1e71a5a2
JD
501static ssize_t set_fan_div(struct device *dev, struct device_attribute *da,
502 const char *buf, size_t count) {
2ec342e6 503 struct via686a_data *data = dev_get_drvdata(dev);
1e71a5a2
JD
504 struct sensor_device_attribute *attr = to_sensor_dev_attr(da);
505 int nr = attr->index;
1da177e4
LT
506 int val = simple_strtol(buf, NULL, 10);
507 int old;
508
9a61bf63 509 mutex_lock(&data->update_lock);
2ec342e6 510 old = via686a_read_value(data, VIA686A_REG_FANDIV);
1da177e4
LT
511 data->fan_div[nr] = DIV_TO_REG(val);
512 old = (old & 0x0f) | (data->fan_div[1] << 6) | (data->fan_div[0] << 4);
2ec342e6 513 via686a_write_value(data, VIA686A_REG_FANDIV, old);
9a61bf63 514 mutex_unlock(&data->update_lock);
1da177e4
LT
515 return count;
516}
517
518#define show_fan_offset(offset) \
1e71a5a2
JD
519static SENSOR_DEVICE_ATTR(fan##offset##_input, S_IRUGO, \
520 show_fan, NULL, offset - 1); \
521static SENSOR_DEVICE_ATTR(fan##offset##_min, S_IRUGO | S_IWUSR, \
522 show_fan_min, set_fan_min, offset - 1); \
523static SENSOR_DEVICE_ATTR(fan##offset##_div, S_IRUGO | S_IWUSR, \
524 show_fan_div, set_fan_div, offset - 1);
1da177e4
LT
525
526show_fan_offset(1);
527show_fan_offset(2);
528
529/* Alarms */
a5099cfc 530static ssize_t show_alarms(struct device *dev, struct device_attribute *attr, char *buf) {
1da177e4 531 struct via686a_data *data = via686a_update_device(dev);
68188ba7 532 return sprintf(buf, "%u\n", data->alarms);
1da177e4 533}
1d66c64c 534static DEVICE_ATTR(alarms, S_IRUGO, show_alarms, NULL);
1da177e4 535
13ff05e9
JD
536static ssize_t show_alarm(struct device *dev, struct device_attribute *attr,
537 char *buf)
538{
539 int bitnr = to_sensor_dev_attr(attr)->index;
540 struct via686a_data *data = via686a_update_device(dev);
541 return sprintf(buf, "%u\n", (data->alarms >> bitnr) & 1);
542}
543static SENSOR_DEVICE_ATTR(in0_alarm, S_IRUGO, show_alarm, NULL, 0);
544static SENSOR_DEVICE_ATTR(in1_alarm, S_IRUGO, show_alarm, NULL, 1);
545static SENSOR_DEVICE_ATTR(in2_alarm, S_IRUGO, show_alarm, NULL, 2);
546static SENSOR_DEVICE_ATTR(in3_alarm, S_IRUGO, show_alarm, NULL, 3);
547static SENSOR_DEVICE_ATTR(in4_alarm, S_IRUGO, show_alarm, NULL, 8);
548static SENSOR_DEVICE_ATTR(temp1_alarm, S_IRUGO, show_alarm, NULL, 4);
549static SENSOR_DEVICE_ATTR(temp2_alarm, S_IRUGO, show_alarm, NULL, 11);
550static SENSOR_DEVICE_ATTR(temp3_alarm, S_IRUGO, show_alarm, NULL, 15);
551static SENSOR_DEVICE_ATTR(fan1_alarm, S_IRUGO, show_alarm, NULL, 6);
552static SENSOR_DEVICE_ATTR(fan2_alarm, S_IRUGO, show_alarm, NULL, 7);
553
2ec342e6
JD
554static ssize_t show_name(struct device *dev, struct device_attribute
555 *devattr, char *buf)
556{
557 struct via686a_data *data = dev_get_drvdata(dev);
558 return sprintf(buf, "%s\n", data->name);
559}
560static DEVICE_ATTR(name, S_IRUGO, show_name, NULL);
561
a5ebe668 562static struct attribute *via686a_attributes[] = {
1e71a5a2
JD
563 &sensor_dev_attr_in0_input.dev_attr.attr,
564 &sensor_dev_attr_in1_input.dev_attr.attr,
565 &sensor_dev_attr_in2_input.dev_attr.attr,
566 &sensor_dev_attr_in3_input.dev_attr.attr,
567 &sensor_dev_attr_in4_input.dev_attr.attr,
568 &sensor_dev_attr_in0_min.dev_attr.attr,
569 &sensor_dev_attr_in1_min.dev_attr.attr,
570 &sensor_dev_attr_in2_min.dev_attr.attr,
571 &sensor_dev_attr_in3_min.dev_attr.attr,
572 &sensor_dev_attr_in4_min.dev_attr.attr,
573 &sensor_dev_attr_in0_max.dev_attr.attr,
574 &sensor_dev_attr_in1_max.dev_attr.attr,
575 &sensor_dev_attr_in2_max.dev_attr.attr,
576 &sensor_dev_attr_in3_max.dev_attr.attr,
577 &sensor_dev_attr_in4_max.dev_attr.attr,
13ff05e9
JD
578 &sensor_dev_attr_in0_alarm.dev_attr.attr,
579 &sensor_dev_attr_in1_alarm.dev_attr.attr,
580 &sensor_dev_attr_in2_alarm.dev_attr.attr,
581 &sensor_dev_attr_in3_alarm.dev_attr.attr,
582 &sensor_dev_attr_in4_alarm.dev_attr.attr,
1e71a5a2
JD
583
584 &sensor_dev_attr_temp1_input.dev_attr.attr,
585 &sensor_dev_attr_temp2_input.dev_attr.attr,
586 &sensor_dev_attr_temp3_input.dev_attr.attr,
587 &sensor_dev_attr_temp1_max.dev_attr.attr,
588 &sensor_dev_attr_temp2_max.dev_attr.attr,
589 &sensor_dev_attr_temp3_max.dev_attr.attr,
590 &sensor_dev_attr_temp1_max_hyst.dev_attr.attr,
591 &sensor_dev_attr_temp2_max_hyst.dev_attr.attr,
592 &sensor_dev_attr_temp3_max_hyst.dev_attr.attr,
13ff05e9
JD
593 &sensor_dev_attr_temp1_alarm.dev_attr.attr,
594 &sensor_dev_attr_temp2_alarm.dev_attr.attr,
595 &sensor_dev_attr_temp3_alarm.dev_attr.attr,
1e71a5a2
JD
596
597 &sensor_dev_attr_fan1_input.dev_attr.attr,
598 &sensor_dev_attr_fan2_input.dev_attr.attr,
599 &sensor_dev_attr_fan1_min.dev_attr.attr,
600 &sensor_dev_attr_fan2_min.dev_attr.attr,
601 &sensor_dev_attr_fan1_div.dev_attr.attr,
602 &sensor_dev_attr_fan2_div.dev_attr.attr,
13ff05e9
JD
603 &sensor_dev_attr_fan1_alarm.dev_attr.attr,
604 &sensor_dev_attr_fan2_alarm.dev_attr.attr,
a5ebe668
JD
605
606 &dev_attr_alarms.attr,
2ec342e6 607 &dev_attr_name.attr,
a5ebe668
JD
608 NULL
609};
610
611static const struct attribute_group via686a_group = {
612 .attrs = via686a_attributes,
613};
614
2ec342e6 615static struct platform_driver via686a_driver = {
cdaf7934 616 .driver = {
87218842 617 .owner = THIS_MODULE,
cdaf7934
LR
618 .name = "via686a",
619 },
2ec342e6
JD
620 .probe = via686a_probe,
621 .remove = __devexit_p(via686a_remove),
1da177e4
LT
622};
623
624
625/* This is called when the module is loaded */
2ec342e6 626static int __devinit via686a_probe(struct platform_device *pdev)
1da177e4 627{
1da177e4 628 struct via686a_data *data;
2ec342e6
JD
629 struct resource *res;
630 int err;
1da177e4
LT
631
632 /* Reserve the ISA region */
2ec342e6
JD
633 res = platform_get_resource(pdev, IORESOURCE_IO, 0);
634 if (!request_region(res->start, VIA686A_EXTENT,
cdaf7934 635 via686a_driver.driver.name)) {
2ec342e6
JD
636 dev_err(&pdev->dev, "Region 0x%lx-0x%lx already in use!\n",
637 (unsigned long)res->start, (unsigned long)res->end);
1da177e4
LT
638 return -ENODEV;
639 }
640
ba9c2e8d 641 if (!(data = kzalloc(sizeof(struct via686a_data), GFP_KERNEL))) {
1da177e4 642 err = -ENOMEM;
943b0830 643 goto exit_release;
1da177e4 644 }
1da177e4 645
2ec342e6
JD
646 platform_set_drvdata(pdev, data);
647 data->addr = res->start;
648 data->name = "via686a";
9a61bf63 649 mutex_init(&data->update_lock);
be8992c2 650
1da177e4 651 /* Initialize the VIA686A chip */
2ec342e6 652 via686a_init_device(data);
1da177e4
LT
653
654 /* Register sysfs hooks */
2ec342e6
JD
655 if ((err = sysfs_create_group(&pdev->dev.kobj, &via686a_group)))
656 goto exit_free;
a5ebe668 657
1beeffe4
TJ
658 data->hwmon_dev = hwmon_device_register(&pdev->dev);
659 if (IS_ERR(data->hwmon_dev)) {
660 err = PTR_ERR(data->hwmon_dev);
a5ebe668 661 goto exit_remove_files;
943b0830
MH
662 }
663
1da177e4
LT
664 return 0;
665
a5ebe668 666exit_remove_files:
2ec342e6 667 sysfs_remove_group(&pdev->dev.kobj, &via686a_group);
943b0830 668exit_free:
1da177e4 669 kfree(data);
943b0830 670exit_release:
2ec342e6 671 release_region(res->start, VIA686A_EXTENT);
1da177e4
LT
672 return err;
673}
674
2ec342e6 675static int __devexit via686a_remove(struct platform_device *pdev)
1da177e4 676{
2ec342e6 677 struct via686a_data *data = platform_get_drvdata(pdev);
1da177e4 678
1beeffe4 679 hwmon_device_unregister(data->hwmon_dev);
2ec342e6 680 sysfs_remove_group(&pdev->dev.kobj, &via686a_group);
943b0830 681
2ec342e6
JD
682 release_region(data->addr, VIA686A_EXTENT);
683 platform_set_drvdata(pdev, NULL);
943b0830 684 kfree(data);
1da177e4
LT
685
686 return 0;
687}
688
2ec342e6 689static void __devinit via686a_init_device(struct via686a_data *data)
1da177e4
LT
690{
691 u8 reg;
692
693 /* Start monitoring */
2ec342e6
JD
694 reg = via686a_read_value(data, VIA686A_REG_CONFIG);
695 via686a_write_value(data, VIA686A_REG_CONFIG, (reg | 0x01) & 0x7F);
1da177e4
LT
696
697 /* Configure temp interrupt mode for continuous-interrupt operation */
2ec342e6
JD
698 reg = via686a_read_value(data, VIA686A_REG_TEMP_MODE);
699 via686a_write_value(data, VIA686A_REG_TEMP_MODE,
58fe0809
JD
700 (reg & ~VIA686A_TEMP_MODE_MASK)
701 | VIA686A_TEMP_MODE_CONTINUOUS);
1da177e4
LT
702}
703
704static struct via686a_data *via686a_update_device(struct device *dev)
705{
2ec342e6 706 struct via686a_data *data = dev_get_drvdata(dev);
1da177e4
LT
707 int i;
708
9a61bf63 709 mutex_lock(&data->update_lock);
1da177e4
LT
710
711 if (time_after(jiffies, data->last_updated + HZ + HZ / 2)
712 || !data->valid) {
713 for (i = 0; i <= 4; i++) {
714 data->in[i] =
2ec342e6
JD
715 via686a_read_value(data, VIA686A_REG_IN(i));
716 data->in_min[i] = via686a_read_value(data,
1da177e4
LT
717 VIA686A_REG_IN_MIN
718 (i));
719 data->in_max[i] =
2ec342e6 720 via686a_read_value(data, VIA686A_REG_IN_MAX(i));
1da177e4
LT
721 }
722 for (i = 1; i <= 2; i++) {
723 data->fan[i - 1] =
2ec342e6
JD
724 via686a_read_value(data, VIA686A_REG_FAN(i));
725 data->fan_min[i - 1] = via686a_read_value(data,
1da177e4
LT
726 VIA686A_REG_FAN_MIN(i));
727 }
728 for (i = 0; i <= 2; i++) {
2ec342e6 729 data->temp[i] = via686a_read_value(data,
563db2fe 730 VIA686A_REG_TEMP[i]) << 2;
1da177e4 731 data->temp_over[i] =
2ec342e6 732 via686a_read_value(data,
563db2fe 733 VIA686A_REG_TEMP_OVER[i]);
1da177e4 734 data->temp_hyst[i] =
2ec342e6 735 via686a_read_value(data,
563db2fe 736 VIA686A_REG_TEMP_HYST[i]);
1da177e4 737 }
be8992c2 738 /* add in lower 2 bits
1da177e4
LT
739 temp1 uses bits 7-6 of VIA686A_REG_TEMP_LOW1
740 temp2 uses bits 5-4 of VIA686A_REG_TEMP_LOW23
741 temp3 uses bits 7-6 of VIA686A_REG_TEMP_LOW23
742 */
2ec342e6 743 data->temp[0] |= (via686a_read_value(data,
1da177e4
LT
744 VIA686A_REG_TEMP_LOW1)
745 & 0xc0) >> 6;
746 data->temp[1] |=
2ec342e6 747 (via686a_read_value(data, VIA686A_REG_TEMP_LOW23) &
1da177e4
LT
748 0x30) >> 4;
749 data->temp[2] |=
2ec342e6 750 (via686a_read_value(data, VIA686A_REG_TEMP_LOW23) &
1da177e4
LT
751 0xc0) >> 6;
752
2ec342e6 753 i = via686a_read_value(data, VIA686A_REG_FANDIV);
1da177e4
LT
754 data->fan_div[0] = (i >> 4) & 0x03;
755 data->fan_div[1] = i >> 6;
756 data->alarms =
2ec342e6 757 via686a_read_value(data,
1da177e4 758 VIA686A_REG_ALARM1) |
2ec342e6 759 (via686a_read_value(data, VIA686A_REG_ALARM2) << 8);
1da177e4
LT
760 data->last_updated = jiffies;
761 data->valid = 1;
762 }
763
9a61bf63 764 mutex_unlock(&data->update_lock);
1da177e4
LT
765
766 return data;
767}
768
769static struct pci_device_id via686a_pci_ids[] = {
be8992c2
JD
770 { PCI_DEVICE(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C686_4) },
771 { 0, }
1da177e4
LT
772};
773
774MODULE_DEVICE_TABLE(pci, via686a_pci_ids);
775
2ec342e6
JD
776static int __devinit via686a_device_add(unsigned short address)
777{
778 struct resource res = {
779 .start = address,
780 .end = address + VIA686A_EXTENT - 1,
781 .name = "via686a",
782 .flags = IORESOURCE_IO,
783 };
784 int err;
785
786 pdev = platform_device_alloc("via686a", address);
787 if (!pdev) {
788 err = -ENOMEM;
789 printk(KERN_ERR "via686a: Device allocation failed\n");
790 goto exit;
791 }
792
793 err = platform_device_add_resources(pdev, &res, 1);
794 if (err) {
795 printk(KERN_ERR "via686a: Device resource addition failed "
796 "(%d)\n", err);
797 goto exit_device_put;
798 }
799
800 err = platform_device_add(pdev);
801 if (err) {
802 printk(KERN_ERR "via686a: Device addition failed (%d)\n",
803 err);
804 goto exit_device_put;
805 }
806
807 return 0;
808
809exit_device_put:
810 platform_device_put(pdev);
811exit:
812 return err;
813}
814
1da177e4 815static int __devinit via686a_pci_probe(struct pci_dev *dev,
be8992c2 816 const struct pci_device_id *id)
1da177e4 817{
2ec342e6 818 u16 address, val;
be8992c2 819
2ec342e6
JD
820 if (force_addr) {
821 address = force_addr & ~(VIA686A_EXTENT - 1);
822 dev_warn(&dev->dev, "Forcing ISA address 0x%x\n", address);
823 if (PCIBIOS_SUCCESSFUL !=
824 pci_write_config_word(dev, VIA686A_BASE_REG, address | 1))
825 return -ENODEV;
826 }
be8992c2
JD
827 if (PCIBIOS_SUCCESSFUL !=
828 pci_read_config_word(dev, VIA686A_BASE_REG, &val))
829 return -ENODEV;
830
2d8672c5 831 address = val & ~(VIA686A_EXTENT - 1);
2ec342e6 832 if (address == 0) {
be8992c2
JD
833 dev_err(&dev->dev, "base address not set - upgrade BIOS "
834 "or use force_addr=0xaddr\n");
835 return -ENODEV;
836 }
be8992c2 837
2ec342e6
JD
838 if (PCIBIOS_SUCCESSFUL !=
839 pci_read_config_word(dev, VIA686A_ENABLE_REG, &val))
840 return -ENODEV;
841 if (!(val & 0x0001)) {
842 if (!force_addr) {
843 dev_warn(&dev->dev, "Sensors disabled, enable "
844 "with force_addr=0x%x\n", address);
845 return -ENODEV;
846 }
847
848 dev_warn(&dev->dev, "Enabling sensors\n");
849 if (PCIBIOS_SUCCESSFUL !=
850 pci_write_config_word(dev, VIA686A_ENABLE_REG,
851 val | 0x0001))
852 return -ENODEV;
1da177e4
LT
853 }
854
2ec342e6
JD
855 if (platform_driver_register(&via686a_driver))
856 goto exit;
857
858 /* Sets global pdev as a side effect */
859 if (via686a_device_add(address))
860 goto exit_unregister;
861
1da177e4
LT
862 /* Always return failure here. This is to allow other drivers to bind
863 * to this pci device. We don't really want to have control over the
864 * pci device, we only wanted to read as few register values from it.
865 */
2ec342e6
JD
866 s_bridge = pci_dev_get(dev);
867 return -ENODEV;
868
869exit_unregister:
870 platform_driver_unregister(&via686a_driver);
871exit:
1da177e4
LT
872 return -ENODEV;
873}
874
875static struct pci_driver via686a_pci_driver = {
be8992c2
JD
876 .name = "via686a",
877 .id_table = via686a_pci_ids,
878 .probe = via686a_pci_probe,
1da177e4
LT
879};
880
881static int __init sm_via686a_init(void)
882{
be8992c2 883 return pci_register_driver(&via686a_pci_driver);
1da177e4
LT
884}
885
886static void __exit sm_via686a_exit(void)
887{
888 pci_unregister_driver(&via686a_pci_driver);
889 if (s_bridge != NULL) {
2ec342e6
JD
890 platform_device_unregister(pdev);
891 platform_driver_unregister(&via686a_driver);
1da177e4
LT
892 pci_dev_put(s_bridge);
893 s_bridge = NULL;
894 }
895}
896
96de0e25 897MODULE_AUTHOR("Kyösti Mälkki <kmalkki@cc.hut.fi>, "
be8992c2
JD
898 "Mark Studebaker <mdsxyz123@yahoo.com> "
899 "and Bob Dougherty <bobd@stanford.edu>");
1da177e4
LT
900MODULE_DESCRIPTION("VIA 686A Sensor device");
901MODULE_LICENSE("GPL");
902
903module_init(sm_via686a_init);
904module_exit(sm_via686a_exit);