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