Blame view

drivers/hwmon/via686a.c 30.5 KB
74ba9207e   Thomas Gleixner   treewide: Replace...
1
  // SPDX-License-Identifier: GPL-2.0-or-later
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2
  /*
9004ac813   Guenter Roeck   hwmon: (via686a) ...
3
4
5
6
7
8
9
10
11
12
   * via686a.c - Part of lm_sensors, Linux kernel modules
   *	       for hardware monitoring
   *
   * Copyright (c) 1998 - 2002  Frodo Looijaard <frodol@dds.nl>,
   *			      Kyösti Mälkki <kmalkki@cc.hut.fi>,
   *			      Mark Studebaker <mdsxyz123@yahoo.com>,
   *			      and Bob Dougherty <bobd@stanford.edu>
   *
   * (Some conversion-factor data were contributed by Jonathan Teh Soon Yew
   * <j.teh@iname.com> and Alex van Kaam <darkside@chello.nl>.)
9004ac813   Guenter Roeck   hwmon: (via686a) ...
13
   */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
14
15
  
  /*
9004ac813   Guenter Roeck   hwmon: (via686a) ...
16
17
18
19
   * Supports the Via VT82C686A, VT82C686B south bridges.
   * Reports all as a 686A.
   * Warning - only supports a single device.
   */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
20

774f7827e   Joe Perches   hwmon: (via686a) ...
21
  #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
22
23
24
  #include <linux/module.h>
  #include <linux/slab.h>
  #include <linux/pci.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
25
  #include <linux/jiffies.h>
2ec342e68   Jean Delvare   hwmon/via686a: Co...
26
  #include <linux/platform_device.h>
943b0830c   Mark M. Hoffman   [PATCH] I2C hwmon...
27
  #include <linux/hwmon.h>
1e71a5a2c   Jean Delvare   hwmon/via686a: Us...
28
  #include <linux/hwmon-sysfs.h>
943b0830c   Mark M. Hoffman   [PATCH] I2C hwmon...
29
  #include <linux/err.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
30
  #include <linux/init.h>
9a61bf630   Ingo Molnar   [PATCH] hwmon: Se...
31
  #include <linux/mutex.h>
a5ebe668a   Jean Delvare   hwmon: Fix unchec...
32
  #include <linux/sysfs.h>
b9acb64a3   Jean Delvare   hwmon: Check for ...
33
  #include <linux/acpi.h>
6055fae8a   H Hartley Sweeten   hwmon: Include <l...
34
  #include <linux/io.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
35

9004ac813   Guenter Roeck   hwmon: (via686a) ...
36
37
38
39
  /*
   * If force_addr is set to anything different from 0, we forcibly enable
   * the device at the given address.
   */
020029631   Jean Delvare   [PATCH] hwmon: Di...
40
  static unsigned short force_addr;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
41
42
43
  module_param(force_addr, ushort, 0);
  MODULE_PARM_DESC(force_addr,
  		 "Initialize the base address of the sensors");
2ec342e68   Jean Delvare   hwmon/via686a: Co...
44
  static struct platform_device *pdev;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
45
46
  
  /*
9004ac813   Guenter Roeck   hwmon: (via686a) ...
47
48
49
   * The Via 686a southbridge has a LM78-like chip integrated on the same IC.
   * This driver is a customized copy of lm78.c
   */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
50
51
52
53
  
  /* Many VIA686A constants specified below */
  
  /* Length of ISA address segment */
be8992c24   Jean Delvare   [PATCH] I2C: Codi...
54
55
56
  #define VIA686A_EXTENT		0x80
  #define VIA686A_BASE_REG	0x70
  #define VIA686A_ENABLE_REG	0x74
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
57
58
59
  
  /* The VIA686A registers */
  /* ins numbered 0-4 */
be8992c24   Jean Delvare   [PATCH] I2C: Codi...
60
61
62
  #define VIA686A_REG_IN_MAX(nr)	(0x2b + ((nr) * 2))
  #define VIA686A_REG_IN_MIN(nr)	(0x2c + ((nr) * 2))
  #define VIA686A_REG_IN(nr)	(0x22 + (nr))
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
63
64
  
  /* fans numbered 1-2 */
be8992c24   Jean Delvare   [PATCH] I2C: Codi...
65
66
  #define VIA686A_REG_FAN_MIN(nr)	(0x3a + (nr))
  #define VIA686A_REG_FAN(nr)	(0x28 + (nr))
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
67

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
68
  /* temps numbered 1-3 */
563db2fe9   Jean Delvare   [PATCH] I2C: Kill...
69
70
71
  static const u8 VIA686A_REG_TEMP[]	= { 0x20, 0x21, 0x1f };
  static const u8 VIA686A_REG_TEMP_OVER[]	= { 0x39, 0x3d, 0x1d };
  static const u8 VIA686A_REG_TEMP_HYST[]	= { 0x3a, 0x3e, 0x1e };
be8992c24   Jean Delvare   [PATCH] I2C: Codi...
72
73
74
75
76
77
78
79
80
  /* bits 7-6 */
  #define VIA686A_REG_TEMP_LOW1	0x4b
  /* 2 = bits 5-4, 3 = bits 7-6 */
  #define VIA686A_REG_TEMP_LOW23	0x49
  
  #define VIA686A_REG_ALARM1	0x41
  #define VIA686A_REG_ALARM2	0x42
  #define VIA686A_REG_FANDIV	0x47
  #define VIA686A_REG_CONFIG	0x40
9004ac813   Guenter Roeck   hwmon: (via686a) ...
81
82
83
84
85
86
87
88
  /*
   * The following register sets temp interrupt mode (bits 1-0 for temp1,
   * 3-2 for temp2, 5-4 for temp3).  Modes are:
   * 00 interrupt stays as long as value is out-of-range
   * 01 interrupt is cleared once register is read (default)
   * 10 comparator mode- like 00, but ignores hysteresis
   * 11 same as 00
   */
be8992c24   Jean Delvare   [PATCH] I2C: Codi...
89
  #define VIA686A_REG_TEMP_MODE		0x4b
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
90
  /* We'll just assume that you want to set all 3 simultaneously: */
be8992c24   Jean Delvare   [PATCH] I2C: Codi...
91
92
  #define VIA686A_TEMP_MODE_MASK		0x3F
  #define VIA686A_TEMP_MODE_CONTINUOUS	0x00
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
93

9004ac813   Guenter Roeck   hwmon: (via686a) ...
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
  /*
   * Conversions. Limit checking is only done on the TO_REG
   * variants.
   *
   ******** VOLTAGE CONVERSIONS (Bob Dougherty) ********
   * From HWMon.cpp (Copyright 1998-2000 Jonathan Teh Soon Yew):
   * voltagefactor[0]=1.25/2628; (2628/1.25=2102.4)   // Vccp
   * voltagefactor[1]=1.25/2628; (2628/1.25=2102.4)   // +2.5V
   * voltagefactor[2]=1.67/2628; (2628/1.67=1573.7)   // +3.3V
   * voltagefactor[3]=2.6/2628;  (2628/2.60=1010.8)   // +5V
   * voltagefactor[4]=6.3/2628;  (2628/6.30=417.14)   // +12V
   * in[i]=(data[i+2]*25.0+133)*voltagefactor[i];
   * That is:
   * volts = (25*regVal+133)*factor
   * regVal = (volts/factor-133)/25
   * (These conversions were contributed by Jonathan Teh Soon Yew
   * <j.teh@iname.com>)
   */
088ce2ac9   Guenter Roeck   hwmon: Fix CamelC...
112
  static inline u8 IN_TO_REG(long val, int in_num)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
113
  {
9004ac813   Guenter Roeck   hwmon: (via686a) ...
114
115
116
117
118
119
120
  	/*
  	 * To avoid floating point, we multiply constants by 10 (100 for +12V).
  	 * Rounding is done (120500 is actually 133000 - 12500).
  	 * Remember that val is expressed in 0.001V/bit, which is why we divide
  	 * by an additional 10000 (100000 for +12V): 1000 for val and 10 (100)
  	 * for the constants.
  	 */
088ce2ac9   Guenter Roeck   hwmon: Fix CamelC...
121
  	if (in_num <= 1)
2a844c148   Guenter Roeck   hwmon: Replace SE...
122
  		return (u8) clamp_val((val * 21024 - 1205000) / 250000, 0, 255);
088ce2ac9   Guenter Roeck   hwmon: Fix CamelC...
123
  	else if (in_num == 2)
2a844c148   Guenter Roeck   hwmon: Replace SE...
124
  		return (u8) clamp_val((val * 15737 - 1205000) / 250000, 0, 255);
088ce2ac9   Guenter Roeck   hwmon: Fix CamelC...
125
  	else if (in_num == 3)
2a844c148   Guenter Roeck   hwmon: Replace SE...
126
  		return (u8) clamp_val((val * 10108 - 1205000) / 250000, 0, 255);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
127
  	else
2a844c148   Guenter Roeck   hwmon: Replace SE...
128
129
  		return (u8) clamp_val((val * 41714 - 12050000) / 2500000, 0,
  				      255);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
130
  }
088ce2ac9   Guenter Roeck   hwmon: Fix CamelC...
131
  static inline long IN_FROM_REG(u8 val, int in_num)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
132
  {
9004ac813   Guenter Roeck   hwmon: (via686a) ...
133
134
135
136
137
  	/*
  	 * To avoid floating point, we multiply constants by 10 (100 for +12V).
  	 * We also multiply them by 1000 because we want 0.001V/bit for the
  	 * output value. Rounding is done.
  	 */
088ce2ac9   Guenter Roeck   hwmon: Fix CamelC...
138
  	if (in_num <= 1)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
139
  		return (long) ((250000 * val + 1330000 + 21024 / 2) / 21024);
088ce2ac9   Guenter Roeck   hwmon: Fix CamelC...
140
  	else if (in_num == 2)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
141
  		return (long) ((250000 * val + 1330000 + 15737 / 2) / 15737);
088ce2ac9   Guenter Roeck   hwmon: Fix CamelC...
142
  	else if (in_num == 3)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
143
144
145
146
147
148
  		return (long) ((250000 * val + 1330000 + 10108 / 2) / 10108);
  	else
  		return (long) ((2500000 * val + 13300000 + 41714 / 2) / 41714);
  }
  
  /********* FAN RPM CONVERSIONS ********/
9004ac813   Guenter Roeck   hwmon: (via686a) ...
149
150
151
152
153
  /*
   * Higher register values = slower fans (the fan's strobe gates a counter).
   * But this chip saturates back at 0, not at 255 like all the other chips.
   * So, 0 means 0 RPM
   */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
154
155
156
157
  static inline u8 FAN_TO_REG(long rpm, int div)
  {
  	if (rpm == 0)
  		return 0;
2a844c148   Guenter Roeck   hwmon: Replace SE...
158
159
  	rpm = clamp_val(rpm, 1, 1000000);
  	return clamp_val((1350000 + rpm * div / 2) / (rpm * div), 1, 255);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
160
  }
9004ac813   Guenter Roeck   hwmon: (via686a) ...
161
162
  #define FAN_FROM_REG(val, div) ((val) == 0 ? 0 : (val) == 255 ? 0 : 1350000 / \
  				((val) * (div)))
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
163
164
  
  /******** TEMP CONVERSIONS (Bob Dougherty) *********/
9004ac813   Guenter Roeck   hwmon: (via686a) ...
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
  /*
   * linear fits from HWMon.cpp (Copyright 1998-2000 Jonathan Teh Soon Yew)
   *	if(temp<169)
   *		return double(temp)*0.427-32.08;
   *	else if(temp>=169 && temp<=202)
   *		return double(temp)*0.582-58.16;
   *	else
   *		return double(temp)*0.924-127.33;
   *
   * A fifth-order polynomial fits the unofficial data (provided by Alex van
   * Kaam <darkside@chello.nl>) a bit better.  It also give more reasonable
   * numbers on my machine (ie. they agree with what my BIOS tells me).
   * Here's the fifth-order fit to the 8-bit data:
   * temp = 1.625093e-10*val^5 - 1.001632e-07*val^4 + 2.457653e-05*val^3 -
   *	2.967619e-03*val^2 + 2.175144e-01*val - 7.090067e+0.
   *
   * (2000-10-25- RFD: thanks to Uwe Andersen <uandersen@mayah.com> for
   * finding my typos in this formula!)
   *
   * Alas, none of the elegant function-fit solutions will work because we
   * aren't allowed to use floating point in the kernel and doing it with
   * integers doesn't provide enough precision.  So we'll do boring old
   * look-up table stuff.  The unofficial data (see below) have effectively
   * 7-bit resolution (they are rounded to the nearest degree).  I'm assuming
   * that the transfer function of the device is monotonic and smooth, so a
   * smooth function fit to the data will allow us to get better precision.
   * I used the 5th-order poly fit described above and solved for
   * VIA register values 0-255.  I *10 before rounding, so we get tenth-degree
   * precision.  (I could have done all 1024 values for our 10-bit readings,
   * but the function is very linear in the useful range (0-80 deg C), so
088ce2ac9   Guenter Roeck   hwmon: Fix CamelC...
195
   * we'll just use linear interpolation for 10-bit readings.)  So, temp_lut
9004ac813   Guenter Roeck   hwmon: (via686a) ...
196
197
   * is the temp at via register values 0-255:
   */
088ce2ac9   Guenter Roeck   hwmon: Fix CamelC...
198
  static const s16 temp_lut[] = {
9004ac813   Guenter Roeck   hwmon: (via686a) ...
199
  	-709, -688, -667, -646, -627, -607, -589, -570, -553, -536, -519,
be8992c24   Jean Delvare   [PATCH] I2C: Codi...
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
  	-503, -487, -471, -456, -442, -428, -414, -400, -387, -375,
  	-362, -350, -339, -327, -316, -305, -295, -285, -275, -265,
  	-255, -246, -237, -229, -220, -212, -204, -196, -188, -180,
  	-173, -166, -159, -152, -145, -139, -132, -126, -120, -114,
  	-108, -102, -96, -91, -85, -80, -74, -69, -64, -59, -54, -49,
  	-44, -39, -34, -29, -25, -20, -15, -11, -6, -2, 3, 7, 12, 16,
  	20, 25, 29, 33, 37, 42, 46, 50, 54, 59, 63, 67, 71, 75, 79, 84,
  	88, 92, 96, 100, 104, 109, 113, 117, 121, 125, 130, 134, 138,
  	142, 146, 151, 155, 159, 163, 168, 172, 176, 181, 185, 189,
  	193, 198, 202, 206, 211, 215, 219, 224, 228, 232, 237, 241,
  	245, 250, 254, 259, 263, 267, 272, 276, 281, 285, 290, 294,
  	299, 303, 307, 312, 316, 321, 325, 330, 334, 339, 344, 348,
  	353, 357, 362, 366, 371, 376, 380, 385, 390, 395, 399, 404,
  	409, 414, 419, 423, 428, 433, 438, 443, 449, 454, 459, 464,
  	469, 475, 480, 486, 491, 497, 502, 508, 514, 520, 526, 532,
  	538, 544, 551, 557, 564, 571, 578, 584, 592, 599, 606, 614,
  	621, 629, 637, 645, 654, 662, 671, 680, 689, 698, 708, 718,
  	728, 738, 749, 759, 770, 782, 793, 805, 818, 830, 843, 856,
  	870, 883, 898, 912, 927, 943, 958, 975, 991, 1008, 1026, 1044,
  	1062, 1081, 1101, 1121, 1141, 1162, 1184, 1206, 1229, 1252,
  	1276, 1301, 1326, 1352, 1378, 1406, 1434, 1462
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
221
  };
9004ac813   Guenter Roeck   hwmon: (via686a) ...
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
  /*
   * the original LUT values from Alex van Kaam <darkside@chello.nl>
   * (for via register values 12-240):
   * {-50,-49,-47,-45,-43,-41,-39,-38,-37,-35,-34,-33,-32,-31,
   * -30,-29,-28,-27,-26,-25,-24,-24,-23,-22,-21,-20,-20,-19,-18,-17,-17,-16,-15,
   * -15,-14,-14,-13,-12,-12,-11,-11,-10,-9,-9,-8,-8,-7,-7,-6,-6,-5,-5,-4,-4,-3,
   * -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,
   * 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,
   * 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,
   * 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,
   * 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,
   * 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,
   * 85,86,88,89,91,92,94,96,97,99,101,103,105,107,109,110};
   *
   *
   * Here's the reverse LUT.  I got it by doing a 6-th order poly fit (needed
   * an extra term for a good fit to these inverse data!) and then
   * solving for each temp value from -50 to 110 (the useable range for
   * this chip).  Here's the fit:
   * viaRegVal = -1.160370e-10*val^6 +3.193693e-08*val^5 - 1.464447e-06*val^4
   * - 2.525453e-04*val^3 + 1.424593e-02*val^2 + 2.148941e+00*val +7.275808e+01)
   * Note that n=161:
   */
088ce2ac9   Guenter Roeck   hwmon: Fix CamelC...
245
  static const u8 via_lut[] = {
9004ac813   Guenter Roeck   hwmon: (via686a) ...
246
  	12, 12, 13, 14, 14, 15, 16, 16, 17, 18, 18, 19, 20, 20, 21, 22, 23,
be8992c24   Jean Delvare   [PATCH] I2C: Codi...
247
248
249
250
251
252
253
254
255
256
257
258
  	23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 35, 36, 37, 39, 40,
  	41, 43, 45, 46, 48, 49, 51, 53, 55, 57, 59, 60, 62, 64, 66,
  	69, 71, 73, 75, 77, 79, 82, 84, 86, 88, 91, 93, 95, 98, 100,
  	103, 105, 107, 110, 112, 115, 117, 119, 122, 124, 126, 129,
  	131, 134, 136, 138, 140, 143, 145, 147, 150, 152, 154, 156,
  	158, 160, 162, 164, 166, 168, 170, 172, 174, 176, 178, 180,
  	182, 183, 185, 187, 188, 190, 192, 193, 195, 196, 198, 199,
  	200, 202, 203, 205, 206, 207, 208, 209, 210, 211, 212, 213,
  	214, 215, 216, 217, 218, 219, 220, 221, 222, 222, 223, 224,
  	225, 226, 226, 227, 228, 228, 229, 230, 230, 231, 232, 232,
  	233, 233, 234, 235, 235, 236, 236, 237, 237, 238, 238, 239,
  	239, 240
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
259
  };
9004ac813   Guenter Roeck   hwmon: (via686a) ...
260
261
262
263
264
  /*
   * Converting temps to (8-bit) hyst and over registers
   * No interpolation here.
   * The +50 is because the temps start at -50
   */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
265
266
  static inline u8 TEMP_TO_REG(long val)
  {
088ce2ac9   Guenter Roeck   hwmon: Fix CamelC...
267
  	return via_lut[val <= -50000 ? 0 : val >= 110000 ? 160 :
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
268
269
270
271
  		      (val < 0 ? val - 500 : val + 500) / 1000 + 50];
  }
  
  /* for 8-bit temperature hyst and over registers */
088ce2ac9   Guenter Roeck   hwmon: Fix CamelC...
272
  #define TEMP_FROM_REG(val)	((long)temp_lut[val] * 100)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
273
274
275
276
  
  /* for 10-bit temperature readings */
  static inline long TEMP_FROM_REG10(u16 val)
  {
088ce2ac9   Guenter Roeck   hwmon: Fix CamelC...
277
278
  	u16 eight_bits = val >> 2;
  	u16 two_bits = val & 3;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
279
280
  
  	/* no interpolation for these */
088ce2ac9   Guenter Roeck   hwmon: Fix CamelC...
281
282
  	if (two_bits == 0 || eight_bits == 255)
  		return TEMP_FROM_REG(eight_bits);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
283
284
  
  	/* do some linear interpolation */
088ce2ac9   Guenter Roeck   hwmon: Fix CamelC...
285
286
  	return (temp_lut[eight_bits] * (4 - two_bits) +
  		temp_lut[eight_bits + 1] * two_bits) * 25;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
287
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
288
  #define DIV_FROM_REG(val) (1 << (val))
9004ac813   Guenter Roeck   hwmon: (via686a) ...
289
  #define DIV_TO_REG(val) ((val) == 8 ? 3 : (val) == 4 ? 2 : (val) == 1 ? 0 : 1)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
290

9004ac813   Guenter Roeck   hwmon: (via686a) ...
291
292
293
294
  /*
   * For each registered chip, we need to keep some data in memory.
   * The structure is dynamically allocated.
   */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
295
  struct via686a_data {
2ec342e68   Jean Delvare   hwmon/via686a: Co...
296
297
  	unsigned short addr;
  	const char *name;
1beeffe43   Tony Jones   hwmon: Convert fr...
298
  	struct device *hwmon_dev;
9a61bf630   Ingo Molnar   [PATCH] hwmon: Se...
299
  	struct mutex update_lock;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
  	char valid;		/* !=0 if following fields are valid */
  	unsigned long last_updated;	/* In jiffies */
  
  	u8 in[5];		/* Register value */
  	u8 in_max[5];		/* Register value */
  	u8 in_min[5];		/* Register value */
  	u8 fan[2];		/* Register value */
  	u8 fan_min[2];		/* Register value */
  	u16 temp[3];		/* Register value 10 bit */
  	u8 temp_over[3];	/* Register value */
  	u8 temp_hyst[3];	/* Register value */
  	u8 fan_div[2];		/* Register encoding, shifted right */
  	u16 alarms;		/* Register encoding, combined */
  };
  
  static struct pci_dev *s_bridge;	/* pointer to the (only) via686a */
2ec342e68   Jean Delvare   hwmon/via686a: Co...
316
  static int via686a_probe(struct platform_device *pdev);
281dfd0b6   Bill Pemberton   hwmon: remove use...
317
  static int via686a_remove(struct platform_device *pdev);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
318

2ec342e68   Jean Delvare   hwmon/via686a: Co...
319
  static inline int via686a_read_value(struct via686a_data *data, u8 reg)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
320
  {
2ec342e68   Jean Delvare   hwmon/via686a: Co...
321
  	return inb_p(data->addr + reg);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
322
  }
2ec342e68   Jean Delvare   hwmon/via686a: Co...
323
  static inline void via686a_write_value(struct via686a_data *data, u8 reg,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
324
325
  				       u8 value)
  {
2ec342e68   Jean Delvare   hwmon/via686a: Co...
326
  	outb_p(value, data->addr + reg);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
327
328
329
  }
  
  static struct via686a_data *via686a_update_device(struct device *dev);
2ec342e68   Jean Delvare   hwmon/via686a: Co...
330
  static void via686a_init_device(struct via686a_data *data);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
331
332
333
334
  
  /* following are the sysfs callback functions */
  
  /* 7 voltage sensors */
9d5bc0906   Guenter Roeck   hwmon: (via686a) ...
335
336
  static ssize_t in_show(struct device *dev, struct device_attribute *da,
  		       char *buf) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
337
  	struct via686a_data *data = via686a_update_device(dev);
1e71a5a2c   Jean Delvare   hwmon/via686a: Us...
338
339
  	struct sensor_device_attribute *attr = to_sensor_dev_attr(da);
  	int nr = attr->index;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
340
341
342
  	return sprintf(buf, "%ld
  ", IN_FROM_REG(data->in[nr], nr));
  }
9d5bc0906   Guenter Roeck   hwmon: (via686a) ...
343
344
  static ssize_t in_min_show(struct device *dev, struct device_attribute *da,
  			   char *buf) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
345
  	struct via686a_data *data = via686a_update_device(dev);
1e71a5a2c   Jean Delvare   hwmon/via686a: Us...
346
347
  	struct sensor_device_attribute *attr = to_sensor_dev_attr(da);
  	int nr = attr->index;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
348
349
350
  	return sprintf(buf, "%ld
  ", IN_FROM_REG(data->in_min[nr], nr));
  }
9d5bc0906   Guenter Roeck   hwmon: (via686a) ...
351
352
  static ssize_t in_max_show(struct device *dev, struct device_attribute *da,
  			   char *buf) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
353
  	struct via686a_data *data = via686a_update_device(dev);
1e71a5a2c   Jean Delvare   hwmon/via686a: Us...
354
355
  	struct sensor_device_attribute *attr = to_sensor_dev_attr(da);
  	int nr = attr->index;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
356
357
358
  	return sprintf(buf, "%ld
  ", IN_FROM_REG(data->in_max[nr], nr));
  }
9d5bc0906   Guenter Roeck   hwmon: (via686a) ...
359
360
  static ssize_t in_min_store(struct device *dev, struct device_attribute *da,
  			    const char *buf, size_t count) {
2ec342e68   Jean Delvare   hwmon/via686a: Co...
361
  	struct via686a_data *data = dev_get_drvdata(dev);
1e71a5a2c   Jean Delvare   hwmon/via686a: Us...
362
363
  	struct sensor_device_attribute *attr = to_sensor_dev_attr(da);
  	int nr = attr->index;
9004ac813   Guenter Roeck   hwmon: (via686a) ...
364
365
366
367
368
369
  	unsigned long val;
  	int err;
  
  	err = kstrtoul(buf, 10, &val);
  	if (err)
  		return err;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
370

9a61bf630   Ingo Molnar   [PATCH] hwmon: Se...
371
  	mutex_lock(&data->update_lock);
be8992c24   Jean Delvare   [PATCH] I2C: Codi...
372
  	data->in_min[nr] = IN_TO_REG(val, nr);
2ec342e68   Jean Delvare   hwmon/via686a: Co...
373
  	via686a_write_value(data, VIA686A_REG_IN_MIN(nr),
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
374
  			data->in_min[nr]);
9a61bf630   Ingo Molnar   [PATCH] hwmon: Se...
375
  	mutex_unlock(&data->update_lock);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
376
377
  	return count;
  }
9d5bc0906   Guenter Roeck   hwmon: (via686a) ...
378
379
  static ssize_t in_max_store(struct device *dev, struct device_attribute *da,
  			    const char *buf, size_t count) {
2ec342e68   Jean Delvare   hwmon/via686a: Co...
380
  	struct via686a_data *data = dev_get_drvdata(dev);
1e71a5a2c   Jean Delvare   hwmon/via686a: Us...
381
382
  	struct sensor_device_attribute *attr = to_sensor_dev_attr(da);
  	int nr = attr->index;
9004ac813   Guenter Roeck   hwmon: (via686a) ...
383
384
385
386
387
388
  	unsigned long val;
  	int err;
  
  	err = kstrtoul(buf, 10, &val);
  	if (err)
  		return err;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
389

9a61bf630   Ingo Molnar   [PATCH] hwmon: Se...
390
  	mutex_lock(&data->update_lock);
be8992c24   Jean Delvare   [PATCH] I2C: Codi...
391
  	data->in_max[nr] = IN_TO_REG(val, nr);
2ec342e68   Jean Delvare   hwmon/via686a: Co...
392
  	via686a_write_value(data, VIA686A_REG_IN_MAX(nr),
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
393
  			data->in_max[nr]);
9a61bf630   Ingo Molnar   [PATCH] hwmon: Se...
394
  	mutex_unlock(&data->update_lock);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
395
396
  	return count;
  }
9d5bc0906   Guenter Roeck   hwmon: (via686a) ...
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
  
  static SENSOR_DEVICE_ATTR_RO(in0_input, in, 0);
  static SENSOR_DEVICE_ATTR_RW(in0_min, in_min, 0);
  static SENSOR_DEVICE_ATTR_RW(in0_max, in_max, 0);
  static SENSOR_DEVICE_ATTR_RO(in1_input, in, 1);
  static SENSOR_DEVICE_ATTR_RW(in1_min, in_min, 1);
  static SENSOR_DEVICE_ATTR_RW(in1_max, in_max, 1);
  static SENSOR_DEVICE_ATTR_RO(in2_input, in, 2);
  static SENSOR_DEVICE_ATTR_RW(in2_min, in_min, 2);
  static SENSOR_DEVICE_ATTR_RW(in2_max, in_max, 2);
  static SENSOR_DEVICE_ATTR_RO(in3_input, in, 3);
  static SENSOR_DEVICE_ATTR_RW(in3_min, in_min, 3);
  static SENSOR_DEVICE_ATTR_RW(in3_max, in_max, 3);
  static SENSOR_DEVICE_ATTR_RO(in4_input, in, 4);
  static SENSOR_DEVICE_ATTR_RW(in4_min, in_min, 4);
  static SENSOR_DEVICE_ATTR_RW(in4_max, in_max, 4);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
413
414
  
  /* 3 temperatures */
9d5bc0906   Guenter Roeck   hwmon: (via686a) ...
415
416
  static ssize_t temp_show(struct device *dev, struct device_attribute *da,
  			 char *buf) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
417
  	struct via686a_data *data = via686a_update_device(dev);
1e71a5a2c   Jean Delvare   hwmon/via686a: Us...
418
419
  	struct sensor_device_attribute *attr = to_sensor_dev_attr(da);
  	int nr = attr->index;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
420
421
422
  	return sprintf(buf, "%ld
  ", TEMP_FROM_REG10(data->temp[nr]));
  }
9d5bc0906   Guenter Roeck   hwmon: (via686a) ...
423
424
  static ssize_t temp_over_show(struct device *dev, struct device_attribute *da,
  			      char *buf) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
425
  	struct via686a_data *data = via686a_update_device(dev);
1e71a5a2c   Jean Delvare   hwmon/via686a: Us...
426
427
  	struct sensor_device_attribute *attr = to_sensor_dev_attr(da);
  	int nr = attr->index;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
428
429
430
  	return sprintf(buf, "%ld
  ", TEMP_FROM_REG(data->temp_over[nr]));
  }
9d5bc0906   Guenter Roeck   hwmon: (via686a) ...
431
432
  static ssize_t temp_hyst_show(struct device *dev, struct device_attribute *da,
  			      char *buf) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
433
  	struct via686a_data *data = via686a_update_device(dev);
1e71a5a2c   Jean Delvare   hwmon/via686a: Us...
434
435
  	struct sensor_device_attribute *attr = to_sensor_dev_attr(da);
  	int nr = attr->index;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
436
437
438
  	return sprintf(buf, "%ld
  ", TEMP_FROM_REG(data->temp_hyst[nr]));
  }
9d5bc0906   Guenter Roeck   hwmon: (via686a) ...
439
440
441
  static ssize_t temp_over_store(struct device *dev,
  			       struct device_attribute *da, const char *buf,
  			       size_t count) {
2ec342e68   Jean Delvare   hwmon/via686a: Co...
442
  	struct via686a_data *data = dev_get_drvdata(dev);
1e71a5a2c   Jean Delvare   hwmon/via686a: Us...
443
444
  	struct sensor_device_attribute *attr = to_sensor_dev_attr(da);
  	int nr = attr->index;
9004ac813   Guenter Roeck   hwmon: (via686a) ...
445
446
447
448
449
450
  	long val;
  	int err;
  
  	err = kstrtol(buf, 10, &val);
  	if (err)
  		return err;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
451

9a61bf630   Ingo Molnar   [PATCH] hwmon: Se...
452
  	mutex_lock(&data->update_lock);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
453
  	data->temp_over[nr] = TEMP_TO_REG(val);
2ec342e68   Jean Delvare   hwmon/via686a: Co...
454
  	via686a_write_value(data, VIA686A_REG_TEMP_OVER[nr],
563db2fe9   Jean Delvare   [PATCH] I2C: Kill...
455
  			    data->temp_over[nr]);
9a61bf630   Ingo Molnar   [PATCH] hwmon: Se...
456
  	mutex_unlock(&data->update_lock);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
457
458
  	return count;
  }
9d5bc0906   Guenter Roeck   hwmon: (via686a) ...
459
460
461
  static ssize_t temp_hyst_store(struct device *dev,
  			       struct device_attribute *da, const char *buf,
  			       size_t count) {
2ec342e68   Jean Delvare   hwmon/via686a: Co...
462
  	struct via686a_data *data = dev_get_drvdata(dev);
1e71a5a2c   Jean Delvare   hwmon/via686a: Us...
463
464
  	struct sensor_device_attribute *attr = to_sensor_dev_attr(da);
  	int nr = attr->index;
9004ac813   Guenter Roeck   hwmon: (via686a) ...
465
466
467
468
469
470
  	long val;
  	int err;
  
  	err = kstrtol(buf, 10, &val);
  	if (err)
  		return err;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
471

9a61bf630   Ingo Molnar   [PATCH] hwmon: Se...
472
  	mutex_lock(&data->update_lock);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
473
  	data->temp_hyst[nr] = TEMP_TO_REG(val);
2ec342e68   Jean Delvare   hwmon/via686a: Co...
474
  	via686a_write_value(data, VIA686A_REG_TEMP_HYST[nr],
563db2fe9   Jean Delvare   [PATCH] I2C: Kill...
475
  			    data->temp_hyst[nr]);
9a61bf630   Ingo Molnar   [PATCH] hwmon: Se...
476
  	mutex_unlock(&data->update_lock);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
477
478
  	return count;
  }
9d5bc0906   Guenter Roeck   hwmon: (via686a) ...
479
480
481
482
483
484
485
486
487
488
  
  static SENSOR_DEVICE_ATTR_RO(temp1_input, temp, 0);
  static SENSOR_DEVICE_ATTR_RW(temp1_max, temp_over, 0);
  static SENSOR_DEVICE_ATTR_RW(temp1_max_hyst, temp_hyst, 0);
  static SENSOR_DEVICE_ATTR_RO(temp2_input, temp, 1);
  static SENSOR_DEVICE_ATTR_RW(temp2_max, temp_over, 1);
  static SENSOR_DEVICE_ATTR_RW(temp2_max_hyst, temp_hyst, 1);
  static SENSOR_DEVICE_ATTR_RO(temp3_input, temp, 2);
  static SENSOR_DEVICE_ATTR_RW(temp3_max, temp_over, 2);
  static SENSOR_DEVICE_ATTR_RW(temp3_max_hyst, temp_hyst, 2);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
489
490
  
  /* 2 Fans */
9d5bc0906   Guenter Roeck   hwmon: (via686a) ...
491
492
  static ssize_t fan_show(struct device *dev, struct device_attribute *da,
  			char *buf) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
493
  	struct via686a_data *data = via686a_update_device(dev);
1e71a5a2c   Jean Delvare   hwmon/via686a: Us...
494
495
  	struct sensor_device_attribute *attr = to_sensor_dev_attr(da);
  	int nr = attr->index;
be8992c24   Jean Delvare   [PATCH] I2C: Codi...
496
497
  	return sprintf(buf, "%d
  ", FAN_FROM_REG(data->fan[nr],
9004ac813   Guenter Roeck   hwmon: (via686a) ...
498
  				DIV_FROM_REG(data->fan_div[nr])));
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
499
  }
9d5bc0906   Guenter Roeck   hwmon: (via686a) ...
500
501
  static ssize_t fan_min_show(struct device *dev, struct device_attribute *da,
  			    char *buf) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
502
  	struct via686a_data *data = via686a_update_device(dev);
1e71a5a2c   Jean Delvare   hwmon/via686a: Us...
503
504
  	struct sensor_device_attribute *attr = to_sensor_dev_attr(da);
  	int nr = attr->index;
be8992c24   Jean Delvare   [PATCH] I2C: Codi...
505
506
  	return sprintf(buf, "%d
  ",
9004ac813   Guenter Roeck   hwmon: (via686a) ...
507
508
  		FAN_FROM_REG(data->fan_min[nr],
  			     DIV_FROM_REG(data->fan_div[nr])));
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
509
  }
9d5bc0906   Guenter Roeck   hwmon: (via686a) ...
510
511
  static ssize_t fan_div_show(struct device *dev, struct device_attribute *da,
  			    char *buf) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
512
  	struct via686a_data *data = via686a_update_device(dev);
1e71a5a2c   Jean Delvare   hwmon/via686a: Us...
513
514
  	struct sensor_device_attribute *attr = to_sensor_dev_attr(da);
  	int nr = attr->index;
9004ac813   Guenter Roeck   hwmon: (via686a) ...
515
516
  	return sprintf(buf, "%d
  ", DIV_FROM_REG(data->fan_div[nr]));
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
517
  }
9d5bc0906   Guenter Roeck   hwmon: (via686a) ...
518
519
  static ssize_t fan_min_store(struct device *dev, struct device_attribute *da,
  			     const char *buf, size_t count) {
2ec342e68   Jean Delvare   hwmon/via686a: Co...
520
  	struct via686a_data *data = dev_get_drvdata(dev);
1e71a5a2c   Jean Delvare   hwmon/via686a: Us...
521
522
  	struct sensor_device_attribute *attr = to_sensor_dev_attr(da);
  	int nr = attr->index;
9004ac813   Guenter Roeck   hwmon: (via686a) ...
523
524
525
526
527
528
  	unsigned long val;
  	int err;
  
  	err = kstrtoul(buf, 10, &val);
  	if (err)
  		return err;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
529

9a61bf630   Ingo Molnar   [PATCH] hwmon: Se...
530
  	mutex_lock(&data->update_lock);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
531
  	data->fan_min[nr] = FAN_TO_REG(val, DIV_FROM_REG(data->fan_div[nr]));
2ec342e68   Jean Delvare   hwmon/via686a: Co...
532
  	via686a_write_value(data, VIA686A_REG_FAN_MIN(nr+1), data->fan_min[nr]);
9a61bf630   Ingo Molnar   [PATCH] hwmon: Se...
533
  	mutex_unlock(&data->update_lock);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
534
535
  	return count;
  }
9d5bc0906   Guenter Roeck   hwmon: (via686a) ...
536
537
  static ssize_t fan_div_store(struct device *dev, struct device_attribute *da,
  			     const char *buf, size_t count) {
2ec342e68   Jean Delvare   hwmon/via686a: Co...
538
  	struct via686a_data *data = dev_get_drvdata(dev);
1e71a5a2c   Jean Delvare   hwmon/via686a: Us...
539
540
  	struct sensor_device_attribute *attr = to_sensor_dev_attr(da);
  	int nr = attr->index;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
541
  	int old;
9004ac813   Guenter Roeck   hwmon: (via686a) ...
542
543
544
545
546
547
  	unsigned long val;
  	int err;
  
  	err = kstrtoul(buf, 10, &val);
  	if (err)
  		return err;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
548

9a61bf630   Ingo Molnar   [PATCH] hwmon: Se...
549
  	mutex_lock(&data->update_lock);
2ec342e68   Jean Delvare   hwmon/via686a: Co...
550
  	old = via686a_read_value(data, VIA686A_REG_FANDIV);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
551
552
  	data->fan_div[nr] = DIV_TO_REG(val);
  	old = (old & 0x0f) | (data->fan_div[1] << 6) | (data->fan_div[0] << 4);
2ec342e68   Jean Delvare   hwmon/via686a: Co...
553
  	via686a_write_value(data, VIA686A_REG_FANDIV, old);
9a61bf630   Ingo Molnar   [PATCH] hwmon: Se...
554
  	mutex_unlock(&data->update_lock);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
555
556
  	return count;
  }
9d5bc0906   Guenter Roeck   hwmon: (via686a) ...
557
558
559
560
561
562
  static SENSOR_DEVICE_ATTR_RO(fan1_input, fan, 0);
  static SENSOR_DEVICE_ATTR_RW(fan1_min, fan_min, 0);
  static SENSOR_DEVICE_ATTR_RW(fan1_div, fan_div, 0);
  static SENSOR_DEVICE_ATTR_RO(fan2_input, fan, 1);
  static SENSOR_DEVICE_ATTR_RW(fan2_min, fan_min, 1);
  static SENSOR_DEVICE_ATTR_RW(fan2_div, fan_div, 1);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
563
564
  
  /* Alarms */
8b2bd7aef   Julia Lawall   hwmon: (via686a) ...
565
  static ssize_t alarms_show(struct device *dev, struct device_attribute *attr,
9004ac813   Guenter Roeck   hwmon: (via686a) ...
566
567
  			   char *buf)
  {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
568
  	struct via686a_data *data = via686a_update_device(dev);
68188ba7d   Jean Delvare   [PATCH] I2C: Kill...
569
570
  	return sprintf(buf, "%u
  ", data->alarms);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
571
  }
9004ac813   Guenter Roeck   hwmon: (via686a) ...
572

8b2bd7aef   Julia Lawall   hwmon: (via686a) ...
573
  static DEVICE_ATTR_RO(alarms);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
574

9d5bc0906   Guenter Roeck   hwmon: (via686a) ...
575
  static ssize_t alarm_show(struct device *dev, struct device_attribute *attr,
13ff05e9f   Jean Delvare   hwmon: (via686a) ...
576
577
578
579
580
581
582
  			  char *buf)
  {
  	int bitnr = to_sensor_dev_attr(attr)->index;
  	struct via686a_data *data = via686a_update_device(dev);
  	return sprintf(buf, "%u
  ", (data->alarms >> bitnr) & 1);
  }
9d5bc0906   Guenter Roeck   hwmon: (via686a) ...
583
584
585
586
587
588
589
590
591
592
  static SENSOR_DEVICE_ATTR_RO(in0_alarm, alarm, 0);
  static SENSOR_DEVICE_ATTR_RO(in1_alarm, alarm, 1);
  static SENSOR_DEVICE_ATTR_RO(in2_alarm, alarm, 2);
  static SENSOR_DEVICE_ATTR_RO(in3_alarm, alarm, 3);
  static SENSOR_DEVICE_ATTR_RO(in4_alarm, alarm, 8);
  static SENSOR_DEVICE_ATTR_RO(temp1_alarm, alarm, 4);
  static SENSOR_DEVICE_ATTR_RO(temp2_alarm, alarm, 11);
  static SENSOR_DEVICE_ATTR_RO(temp3_alarm, alarm, 15);
  static SENSOR_DEVICE_ATTR_RO(fan1_alarm, alarm, 6);
  static SENSOR_DEVICE_ATTR_RO(fan2_alarm, alarm, 7);
13ff05e9f   Jean Delvare   hwmon: (via686a) ...
593

8b2bd7aef   Julia Lawall   hwmon: (via686a) ...
594
  static ssize_t name_show(struct device *dev, struct device_attribute
2ec342e68   Jean Delvare   hwmon/via686a: Co...
595
596
597
598
599
600
  			 *devattr, char *buf)
  {
  	struct via686a_data *data = dev_get_drvdata(dev);
  	return sprintf(buf, "%s
  ", data->name);
  }
8b2bd7aef   Julia Lawall   hwmon: (via686a) ...
601
  static DEVICE_ATTR_RO(name);
2ec342e68   Jean Delvare   hwmon/via686a: Co...
602

a5ebe668a   Jean Delvare   hwmon: Fix unchec...
603
  static struct attribute *via686a_attributes[] = {
1e71a5a2c   Jean Delvare   hwmon/via686a: Us...
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
  	&sensor_dev_attr_in0_input.dev_attr.attr,
  	&sensor_dev_attr_in1_input.dev_attr.attr,
  	&sensor_dev_attr_in2_input.dev_attr.attr,
  	&sensor_dev_attr_in3_input.dev_attr.attr,
  	&sensor_dev_attr_in4_input.dev_attr.attr,
  	&sensor_dev_attr_in0_min.dev_attr.attr,
  	&sensor_dev_attr_in1_min.dev_attr.attr,
  	&sensor_dev_attr_in2_min.dev_attr.attr,
  	&sensor_dev_attr_in3_min.dev_attr.attr,
  	&sensor_dev_attr_in4_min.dev_attr.attr,
  	&sensor_dev_attr_in0_max.dev_attr.attr,
  	&sensor_dev_attr_in1_max.dev_attr.attr,
  	&sensor_dev_attr_in2_max.dev_attr.attr,
  	&sensor_dev_attr_in3_max.dev_attr.attr,
  	&sensor_dev_attr_in4_max.dev_attr.attr,
13ff05e9f   Jean Delvare   hwmon: (via686a) ...
619
620
621
622
623
  	&sensor_dev_attr_in0_alarm.dev_attr.attr,
  	&sensor_dev_attr_in1_alarm.dev_attr.attr,
  	&sensor_dev_attr_in2_alarm.dev_attr.attr,
  	&sensor_dev_attr_in3_alarm.dev_attr.attr,
  	&sensor_dev_attr_in4_alarm.dev_attr.attr,
1e71a5a2c   Jean Delvare   hwmon/via686a: Us...
624
625
626
627
628
629
630
631
632
633
  
  	&sensor_dev_attr_temp1_input.dev_attr.attr,
  	&sensor_dev_attr_temp2_input.dev_attr.attr,
  	&sensor_dev_attr_temp3_input.dev_attr.attr,
  	&sensor_dev_attr_temp1_max.dev_attr.attr,
  	&sensor_dev_attr_temp2_max.dev_attr.attr,
  	&sensor_dev_attr_temp3_max.dev_attr.attr,
  	&sensor_dev_attr_temp1_max_hyst.dev_attr.attr,
  	&sensor_dev_attr_temp2_max_hyst.dev_attr.attr,
  	&sensor_dev_attr_temp3_max_hyst.dev_attr.attr,
13ff05e9f   Jean Delvare   hwmon: (via686a) ...
634
635
636
  	&sensor_dev_attr_temp1_alarm.dev_attr.attr,
  	&sensor_dev_attr_temp2_alarm.dev_attr.attr,
  	&sensor_dev_attr_temp3_alarm.dev_attr.attr,
1e71a5a2c   Jean Delvare   hwmon/via686a: Us...
637
638
639
640
641
642
643
  
  	&sensor_dev_attr_fan1_input.dev_attr.attr,
  	&sensor_dev_attr_fan2_input.dev_attr.attr,
  	&sensor_dev_attr_fan1_min.dev_attr.attr,
  	&sensor_dev_attr_fan2_min.dev_attr.attr,
  	&sensor_dev_attr_fan1_div.dev_attr.attr,
  	&sensor_dev_attr_fan2_div.dev_attr.attr,
13ff05e9f   Jean Delvare   hwmon: (via686a) ...
644
645
  	&sensor_dev_attr_fan1_alarm.dev_attr.attr,
  	&sensor_dev_attr_fan2_alarm.dev_attr.attr,
a5ebe668a   Jean Delvare   hwmon: Fix unchec...
646
647
  
  	&dev_attr_alarms.attr,
2ec342e68   Jean Delvare   hwmon/via686a: Co...
648
  	&dev_attr_name.attr,
a5ebe668a   Jean Delvare   hwmon: Fix unchec...
649
650
651
652
653
654
  	NULL
  };
  
  static const struct attribute_group via686a_group = {
  	.attrs = via686a_attributes,
  };
2ec342e68   Jean Delvare   hwmon/via686a: Co...
655
  static struct platform_driver via686a_driver = {
cdaf79349   Laurent Riffard   [PATCH] i2c: Drop...
656
  	.driver = {
cdaf79349   Laurent Riffard   [PATCH] i2c: Drop...
657
658
  		.name	= "via686a",
  	},
2ec342e68   Jean Delvare   hwmon/via686a: Co...
659
  	.probe		= via686a_probe,
9e5e9b7a9   Bill Pemberton   hwmon: remove use...
660
  	.remove		= via686a_remove,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
661
  };
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
662
  /* This is called when the module is loaded */
6c931ae1c   Bill Pemberton   hwmon: remove use...
663
  static int via686a_probe(struct platform_device *pdev)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
664
  {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
665
  	struct via686a_data *data;
2ec342e68   Jean Delvare   hwmon/via686a: Co...
666
667
  	struct resource *res;
  	int err;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
668
669
  
  	/* Reserve the ISA region */
2ec342e68   Jean Delvare   hwmon/via686a: Co...
670
  	res = platform_get_resource(pdev, IORESOURCE_IO, 0);
fd55bc009   Guenter Roeck   hwmon: (via686a) ...
671
672
  	if (!devm_request_region(&pdev->dev, res->start, VIA686A_EXTENT,
  				 via686a_driver.driver.name)) {
2ec342e68   Jean Delvare   hwmon/via686a: Co...
673
674
675
  		dev_err(&pdev->dev, "Region 0x%lx-0x%lx already in use!
  ",
  			(unsigned long)res->start, (unsigned long)res->end);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
676
677
  		return -ENODEV;
  	}
fd55bc009   Guenter Roeck   hwmon: (via686a) ...
678
679
680
681
  	data = devm_kzalloc(&pdev->dev, sizeof(struct via686a_data),
  			    GFP_KERNEL);
  	if (!data)
  		return -ENOMEM;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
682

2ec342e68   Jean Delvare   hwmon/via686a: Co...
683
684
685
  	platform_set_drvdata(pdev, data);
  	data->addr = res->start;
  	data->name = "via686a";
9a61bf630   Ingo Molnar   [PATCH] hwmon: Se...
686
  	mutex_init(&data->update_lock);
be8992c24   Jean Delvare   [PATCH] I2C: Codi...
687

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
688
  	/* Initialize the VIA686A chip */
2ec342e68   Jean Delvare   hwmon/via686a: Co...
689
  	via686a_init_device(data);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
690
691
  
  	/* Register sysfs hooks */
9004ac813   Guenter Roeck   hwmon: (via686a) ...
692
693
  	err = sysfs_create_group(&pdev->dev.kobj, &via686a_group);
  	if (err)
fd55bc009   Guenter Roeck   hwmon: (via686a) ...
694
  		return err;
a5ebe668a   Jean Delvare   hwmon: Fix unchec...
695

1beeffe43   Tony Jones   hwmon: Convert fr...
696
697
698
  	data->hwmon_dev = hwmon_device_register(&pdev->dev);
  	if (IS_ERR(data->hwmon_dev)) {
  		err = PTR_ERR(data->hwmon_dev);
a5ebe668a   Jean Delvare   hwmon: Fix unchec...
699
  		goto exit_remove_files;
943b0830c   Mark M. Hoffman   [PATCH] I2C hwmon...
700
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
701
  	return 0;
a5ebe668a   Jean Delvare   hwmon: Fix unchec...
702
  exit_remove_files:
2ec342e68   Jean Delvare   hwmon/via686a: Co...
703
  	sysfs_remove_group(&pdev->dev.kobj, &via686a_group);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
704
705
  	return err;
  }
281dfd0b6   Bill Pemberton   hwmon: remove use...
706
  static int via686a_remove(struct platform_device *pdev)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
707
  {
2ec342e68   Jean Delvare   hwmon/via686a: Co...
708
  	struct via686a_data *data = platform_get_drvdata(pdev);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
709

1beeffe43   Tony Jones   hwmon: Convert fr...
710
  	hwmon_device_unregister(data->hwmon_dev);
2ec342e68   Jean Delvare   hwmon/via686a: Co...
711
  	sysfs_remove_group(&pdev->dev.kobj, &via686a_group);
943b0830c   Mark M. Hoffman   [PATCH] I2C hwmon...
712

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
713
714
  	return 0;
  }
f790674d3   Jean Delvare   hwmon: (via686a) ...
715
716
717
718
719
720
  static void via686a_update_fan_div(struct via686a_data *data)
  {
  	int reg = via686a_read_value(data, VIA686A_REG_FANDIV);
  	data->fan_div[0] = (reg >> 4) & 0x03;
  	data->fan_div[1] = reg >> 6;
  }
6c931ae1c   Bill Pemberton   hwmon: remove use...
721
  static void via686a_init_device(struct via686a_data *data)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
722
723
724
725
  {
  	u8 reg;
  
  	/* Start monitoring */
2ec342e68   Jean Delvare   hwmon/via686a: Co...
726
727
  	reg = via686a_read_value(data, VIA686A_REG_CONFIG);
  	via686a_write_value(data, VIA686A_REG_CONFIG, (reg | 0x01) & 0x7F);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
728
729
  
  	/* Configure temp interrupt mode for continuous-interrupt operation */
2ec342e68   Jean Delvare   hwmon/via686a: Co...
730
731
  	reg = via686a_read_value(data, VIA686A_REG_TEMP_MODE);
  	via686a_write_value(data, VIA686A_REG_TEMP_MODE,
58fe0809c   Jean Delvare   hwmon/via686a: Te...
732
733
  			    (reg & ~VIA686A_TEMP_MODE_MASK)
  			    | VIA686A_TEMP_MODE_CONTINUOUS);
f790674d3   Jean Delvare   hwmon: (via686a) ...
734
735
736
  
  	/* Pre-read fan clock divisor values */
  	via686a_update_fan_div(data);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
737
738
739
740
  }
  
  static struct via686a_data *via686a_update_device(struct device *dev)
  {
2ec342e68   Jean Delvare   hwmon/via686a: Co...
741
  	struct via686a_data *data = dev_get_drvdata(dev);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
742
  	int i;
9a61bf630   Ingo Molnar   [PATCH] hwmon: Se...
743
  	mutex_lock(&data->update_lock);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
744
745
746
747
748
  
  	if (time_after(jiffies, data->last_updated + HZ + HZ / 2)
  	    || !data->valid) {
  		for (i = 0; i <= 4; i++) {
  			data->in[i] =
2ec342e68   Jean Delvare   hwmon/via686a: Co...
749
750
  			    via686a_read_value(data, VIA686A_REG_IN(i));
  			data->in_min[i] = via686a_read_value(data,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
751
752
753
  							     VIA686A_REG_IN_MIN
  							     (i));
  			data->in_max[i] =
2ec342e68   Jean Delvare   hwmon/via686a: Co...
754
  			    via686a_read_value(data, VIA686A_REG_IN_MAX(i));
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
755
756
757
  		}
  		for (i = 1; i <= 2; i++) {
  			data->fan[i - 1] =
2ec342e68   Jean Delvare   hwmon/via686a: Co...
758
759
  			    via686a_read_value(data, VIA686A_REG_FAN(i));
  			data->fan_min[i - 1] = via686a_read_value(data,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
760
761
762
  						     VIA686A_REG_FAN_MIN(i));
  		}
  		for (i = 0; i <= 2; i++) {
2ec342e68   Jean Delvare   hwmon/via686a: Co...
763
  			data->temp[i] = via686a_read_value(data,
563db2fe9   Jean Delvare   [PATCH] I2C: Kill...
764
  						 VIA686A_REG_TEMP[i]) << 2;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
765
  			data->temp_over[i] =
2ec342e68   Jean Delvare   hwmon/via686a: Co...
766
  			    via686a_read_value(data,
563db2fe9   Jean Delvare   [PATCH] I2C: Kill...
767
  					       VIA686A_REG_TEMP_OVER[i]);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
768
  			data->temp_hyst[i] =
2ec342e68   Jean Delvare   hwmon/via686a: Co...
769
  			    via686a_read_value(data,
563db2fe9   Jean Delvare   [PATCH] I2C: Kill...
770
  					       VIA686A_REG_TEMP_HYST[i]);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
771
  		}
9004ac813   Guenter Roeck   hwmon: (via686a) ...
772
773
774
775
776
  		/*
  		 * add in lower 2 bits
  		 * temp1 uses bits 7-6 of VIA686A_REG_TEMP_LOW1
  		 * temp2 uses bits 5-4 of VIA686A_REG_TEMP_LOW23
  		 * temp3 uses bits 7-6 of VIA686A_REG_TEMP_LOW23
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
777
  		 */
2ec342e68   Jean Delvare   hwmon/via686a: Co...
778
  		data->temp[0] |= (via686a_read_value(data,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
779
780
781
  						     VIA686A_REG_TEMP_LOW1)
  				  & 0xc0) >> 6;
  		data->temp[1] |=
2ec342e68   Jean Delvare   hwmon/via686a: Co...
782
  		    (via686a_read_value(data, VIA686A_REG_TEMP_LOW23) &
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
783
784
  		     0x30) >> 4;
  		data->temp[2] |=
2ec342e68   Jean Delvare   hwmon/via686a: Co...
785
  		    (via686a_read_value(data, VIA686A_REG_TEMP_LOW23) &
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
786
  		     0xc0) >> 6;
f790674d3   Jean Delvare   hwmon: (via686a) ...
787
  		via686a_update_fan_div(data);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
788
  		data->alarms =
2ec342e68   Jean Delvare   hwmon/via686a: Co...
789
  		    via686a_read_value(data,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
790
  				       VIA686A_REG_ALARM1) |
2ec342e68   Jean Delvare   hwmon/via686a: Co...
791
  		    (via686a_read_value(data, VIA686A_REG_ALARM2) << 8);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
792
793
794
  		data->last_updated = jiffies;
  		data->valid = 1;
  	}
9a61bf630   Ingo Molnar   [PATCH] hwmon: Se...
795
  	mutex_unlock(&data->update_lock);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
796
797
798
  
  	return data;
  }
cd9bb0564   Jingoo Han   hwmon: remove DEF...
799
  static const struct pci_device_id via686a_pci_ids[] = {
be8992c24   Jean Delvare   [PATCH] I2C: Codi...
800
  	{ PCI_DEVICE(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C686_4) },
9004ac813   Guenter Roeck   hwmon: (via686a) ...
801
  	{ }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
802
  };
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
803
  MODULE_DEVICE_TABLE(pci, via686a_pci_ids);
6c931ae1c   Bill Pemberton   hwmon: remove use...
804
  static int via686a_device_add(unsigned short address)
2ec342e68   Jean Delvare   hwmon/via686a: Co...
805
806
807
808
809
810
811
812
  {
  	struct resource res = {
  		.start	= address,
  		.end	= address + VIA686A_EXTENT - 1,
  		.name	= "via686a",
  		.flags	= IORESOURCE_IO,
  	};
  	int err;
b9acb64a3   Jean Delvare   hwmon: Check for ...
813
814
815
  	err = acpi_check_resource_conflict(&res);
  	if (err)
  		goto exit;
2ec342e68   Jean Delvare   hwmon/via686a: Co...
816
817
818
  	pdev = platform_device_alloc("via686a", address);
  	if (!pdev) {
  		err = -ENOMEM;
774f7827e   Joe Perches   hwmon: (via686a) ...
819
820
  		pr_err("Device allocation failed
  ");
2ec342e68   Jean Delvare   hwmon/via686a: Co...
821
822
823
824
825
  		goto exit;
  	}
  
  	err = platform_device_add_resources(pdev, &res, 1);
  	if (err) {
774f7827e   Joe Perches   hwmon: (via686a) ...
826
827
  		pr_err("Device resource addition failed (%d)
  ", err);
2ec342e68   Jean Delvare   hwmon/via686a: Co...
828
829
830
831
832
  		goto exit_device_put;
  	}
  
  	err = platform_device_add(pdev);
  	if (err) {
774f7827e   Joe Perches   hwmon: (via686a) ...
833
834
  		pr_err("Device addition failed (%d)
  ", err);
2ec342e68   Jean Delvare   hwmon/via686a: Co...
835
836
837
838
839
840
841
842
843
844
  		goto exit_device_put;
  	}
  
  	return 0;
  
  exit_device_put:
  	platform_device_put(pdev);
  exit:
  	return err;
  }
6c931ae1c   Bill Pemberton   hwmon: remove use...
845
  static int via686a_pci_probe(struct pci_dev *dev,
be8992c24   Jean Delvare   [PATCH] I2C: Codi...
846
  				       const struct pci_device_id *id)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
847
  {
2ec342e68   Jean Delvare   hwmon/via686a: Co...
848
  	u16 address, val;
be8992c24   Jean Delvare   [PATCH] I2C: Codi...
849

2ec342e68   Jean Delvare   hwmon/via686a: Co...
850
851
852
853
854
855
856
857
  	if (force_addr) {
  		address = force_addr & ~(VIA686A_EXTENT - 1);
  		dev_warn(&dev->dev, "Forcing ISA address 0x%x
  ", address);
  		if (PCIBIOS_SUCCESSFUL !=
  		    pci_write_config_word(dev, VIA686A_BASE_REG, address | 1))
  			return -ENODEV;
  	}
be8992c24   Jean Delvare   [PATCH] I2C: Codi...
858
859
860
  	if (PCIBIOS_SUCCESSFUL !=
  	    pci_read_config_word(dev, VIA686A_BASE_REG, &val))
  		return -ENODEV;
2d8672c5a   Jean Delvare   [PATCH] I2C: Sepa...
861
  	address = val & ~(VIA686A_EXTENT - 1);
2ec342e68   Jean Delvare   hwmon/via686a: Co...
862
  	if (address == 0) {
b55f37572   Guenter Roeck   hwmon: Fix checkp...
863
864
865
  		dev_err(&dev->dev,
  			"base address not set - upgrade BIOS or use force_addr=0xaddr
  ");
be8992c24   Jean Delvare   [PATCH] I2C: Codi...
866
867
  		return -ENODEV;
  	}
be8992c24   Jean Delvare   [PATCH] I2C: Codi...
868

2ec342e68   Jean Delvare   hwmon/via686a: Co...
869
870
871
872
873
  	if (PCIBIOS_SUCCESSFUL !=
  	    pci_read_config_word(dev, VIA686A_ENABLE_REG, &val))
  		return -ENODEV;
  	if (!(val & 0x0001)) {
  		if (!force_addr) {
b55f37572   Guenter Roeck   hwmon: Fix checkp...
874
875
876
877
  			dev_warn(&dev->dev,
  				 "Sensors disabled, enable with force_addr=0x%x
  ",
  				 address);
2ec342e68   Jean Delvare   hwmon/via686a: Co...
878
879
880
881
882
883
884
885
886
  			return -ENODEV;
  		}
  
  		dev_warn(&dev->dev, "Enabling sensors
  ");
  		if (PCIBIOS_SUCCESSFUL !=
  		    pci_write_config_word(dev, VIA686A_ENABLE_REG,
  					  val | 0x0001))
  			return -ENODEV;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
887
  	}
2ec342e68   Jean Delvare   hwmon/via686a: Co...
888
889
890
891
892
893
  	if (platform_driver_register(&via686a_driver))
  		goto exit;
  
  	/* Sets global pdev as a side effect */
  	if (via686a_device_add(address))
  		goto exit_unregister;
9004ac813   Guenter Roeck   hwmon: (via686a) ...
894
895
  	/*
  	 * Always return failure here.  This is to allow other drivers to bind
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
896
897
898
  	 * to this pci device.  We don't really want to have control over the
  	 * pci device, we only wanted to read as few register values from it.
  	 */
2ec342e68   Jean Delvare   hwmon/via686a: Co...
899
900
901
902
903
904
  	s_bridge = pci_dev_get(dev);
  	return -ENODEV;
  
  exit_unregister:
  	platform_driver_unregister(&via686a_driver);
  exit:
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
905
906
907
908
  	return -ENODEV;
  }
  
  static struct pci_driver via686a_pci_driver = {
be8992c24   Jean Delvare   [PATCH] I2C: Codi...
909
910
911
  	.name		= "via686a",
  	.id_table	= via686a_pci_ids,
  	.probe		= via686a_pci_probe,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
912
913
914
915
  };
  
  static int __init sm_via686a_init(void)
  {
be8992c24   Jean Delvare   [PATCH] I2C: Codi...
916
  	return pci_register_driver(&via686a_pci_driver);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
917
918
919
920
921
922
  }
  
  static void __exit sm_via686a_exit(void)
  {
  	pci_unregister_driver(&via686a_pci_driver);
  	if (s_bridge != NULL) {
2ec342e68   Jean Delvare   hwmon/via686a: Co...
923
924
  		platform_device_unregister(pdev);
  		platform_driver_unregister(&via686a_driver);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
925
926
927
928
  		pci_dev_put(s_bridge);
  		s_bridge = NULL;
  	}
  }
96de0e252   Jan Engelhardt   Convert files to ...
929
  MODULE_AUTHOR("Kyösti Mälkki <kmalkki@cc.hut.fi>, "
be8992c24   Jean Delvare   [PATCH] I2C: Codi...
930
931
  	      "Mark Studebaker <mdsxyz123@yahoo.com> "
  	      "and Bob Dougherty <bobd@stanford.edu>");
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
932
933
934
935
936
  MODULE_DESCRIPTION("VIA 686A Sensor device");
  MODULE_LICENSE("GPL");
  
  module_init(sm_via686a_init);
  module_exit(sm_via686a_exit);