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