Blame view

drivers/hwmon/vt8231.c 30.8 KB
1de9e371b   Roger Lucas   [PATCH] hwmon: Ne...
1
2
3
  /*
  	vt8231.c - Part of lm_sensors, Linux kernel modules
  				for hardware monitoring
af865765a   Roger Lucas   hwmon: (vt8231) U...
4
  	Copyright (c) 2005 Roger Lucas <vt8231@hiddenengine.co.uk>
1de9e371b   Roger Lucas   [PATCH] hwmon: Ne...
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
  	Copyright (c) 2002 Mark D. Studebaker <mdsxyz123@yahoo.com>
  			   Aaron M. Marsh <amarsh@sdf.lonestar.org>
  
  	This program is free software; you can redistribute it and/or modify
  	it under the terms of the GNU General Public License as published by
  	the Free Software Foundation; either version 2 of the License, or
  	(at your option) any later version.
  
  	This program is distributed in the hope that it will be useful,
  	but WITHOUT ANY WARRANTY; without even the implied warranty of
  	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  	GNU General Public License for more details.
  
  	You should have received a copy of the GNU General Public License
  	along with this program; if not, write to the Free Software
  	Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  */
  
  /* Supports VIA VT8231 South Bridge embedded sensors
  */
9d72be0da   Joe Perches   hwmon: (vt8231) U...
25
  #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
1de9e371b   Roger Lucas   [PATCH] hwmon: Ne...
26
27
28
29
30
  #include <linux/module.h>
  #include <linux/init.h>
  #include <linux/slab.h>
  #include <linux/pci.h>
  #include <linux/jiffies.h>
ec5e1a4b8   Roger Lucas   hwmon: Convert vt...
31
  #include <linux/platform_device.h>
1de9e371b   Roger Lucas   [PATCH] hwmon: Ne...
32
33
34
35
  #include <linux/hwmon.h>
  #include <linux/hwmon-sysfs.h>
  #include <linux/hwmon-vid.h>
  #include <linux/err.h>
9a61bf630   Ingo Molnar   [PATCH] hwmon: Se...
36
  #include <linux/mutex.h>
b9acb64a3   Jean Delvare   hwmon: Check for ...
37
  #include <linux/acpi.h>
6055fae8a   H Hartley Sweeten   hwmon: Include <l...
38
  #include <linux/io.h>
1de9e371b   Roger Lucas   [PATCH] hwmon: Ne...
39
40
41
42
  
  static int force_addr;
  module_param(force_addr, int, 0);
  MODULE_PARM_DESC(force_addr, "Initialize the base address of the sensors");
ec5e1a4b8   Roger Lucas   hwmon: Convert vt...
43
  static struct platform_device *pdev;
1de9e371b   Roger Lucas   [PATCH] hwmon: Ne...
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
  
  #define VT8231_EXTENT 0x80
  #define VT8231_BASE_REG 0x70
  #define VT8231_ENABLE_REG 0x74
  
  /* The VT8231 registers
  
     The reset value for the input channel configuration is used (Reg 0x4A=0x07)
     which sets the selected inputs marked with '*' below if multiple options are
     possible:
  
  	            Voltage Mode	  Temperature Mode
  	Sensor	      Linux Id	      Linux Id        VIA Id
  	--------      --------	      --------        ------
  	CPU Diode	N/A		temp1		0
  	UIC1		in0		temp2 *		1
  	UIC2		in1 *		temp3   	2
  	UIC3		in2 *		temp4		3
  	UIC4		in3 *		temp5		4
  	UIC5		in4 *		temp6		5
  	3.3V		in5		N/A
  
     Note that the BIOS may set the configuration register to a different value
     to match the motherboard configuration.
  */
  
  /* fans numbered 0-1 */
  #define VT8231_REG_FAN_MIN(nr)	(0x3b + (nr))
  #define VT8231_REG_FAN(nr)	(0x29 + (nr))
  
  /* Voltage inputs numbered 0-5 */
  
  static const u8 regvolt[]    = { 0x21, 0x22, 0x23, 0x24, 0x25, 0x26 };
  static const u8 regvoltmax[] = { 0x3d, 0x2b, 0x2d, 0x2f, 0x31, 0x33 };
  static const u8 regvoltmin[] = { 0x3e, 0x2c, 0x2e, 0x30, 0x32, 0x34 };
  
  /* Temperatures are numbered 1-6 according to the Linux kernel specification.
  **
  ** In the VIA datasheet, however, the temperatures are numbered from zero.
  ** Since it is important that this driver can easily be compared to the VIA
  ** datasheet, we will use the VIA numbering within this driver and map the
  ** kernel sysfs device name to the VIA number in the sysfs callback.
  */
  
  #define VT8231_REG_TEMP_LOW01	0x49
  #define VT8231_REG_TEMP_LOW25	0x4d
  
  static const u8 regtemp[]    = { 0x1f, 0x21, 0x22, 0x23, 0x24, 0x25 };
  static const u8 regtempmax[] = { 0x39, 0x3d, 0x2b, 0x2d, 0x2f, 0x31 };
  static const u8 regtempmin[] = { 0x3a, 0x3e, 0x2c, 0x2e, 0x30, 0x32 };
  
  #define TEMP_FROM_REG(reg)		(((253 * 4 - (reg)) * 550 + 105) / 210)
  #define TEMP_MAXMIN_FROM_REG(reg)	(((253 - (reg)) * 2200 + 105) / 210)
  #define TEMP_MAXMIN_TO_REG(val)		(253 - ((val) * 210 + 1100) / 2200)
  
  #define VT8231_REG_CONFIG 0x40
  #define VT8231_REG_ALARM1 0x41
  #define VT8231_REG_ALARM2 0x42
  #define VT8231_REG_FANDIV 0x47
  #define VT8231_REG_UCH_CONFIG 0x4a
  #define VT8231_REG_TEMP1_CONFIG 0x4b
  #define VT8231_REG_TEMP2_CONFIG 0x4c
  
  /* temps 0-5 as numbered in VIA datasheet - see later for mapping to Linux
  ** numbering
  */
  #define ISTEMP(i, ch_config) ((i) == 0 ? 1 : \
  			      ((ch_config) >> ((i)+1)) & 0x01)
  /* voltages 0-5 */
  #define ISVOLT(i, ch_config) ((i) == 5 ? 1 : \
  			      !(((ch_config) >> ((i)+2)) & 0x01))
  
  #define DIV_FROM_REG(val) (1 << (val))
  
  /* NB  The values returned here are NOT temperatures.  The calibration curves
  **     for the thermistor curves are board-specific and must go in the
  **     sensors.conf file.  Temperature sensors are actually ten bits, but the
  **     VIA datasheet only considers the 8 MSBs obtained from the regtemp[]
  **     register.  The temperature value returned should have a magnitude of 3,
  **     so we use the VIA scaling as the "true" scaling and use the remaining 2
  **     LSBs as fractional precision.
  **
  **     All the on-chip hardware temperature comparisons for the alarms are only
  **     8-bits wide, and compare against the 8 MSBs of the temperature.  The bits
  **     in the registers VT8231_REG_TEMP_LOW01 and VT8231_REG_TEMP_LOW25 are
  **     ignored.
  */
  
  /******** FAN RPM CONVERSIONS ********
  ** This chip saturates back at 0, not at 255 like many the other chips.
  ** So, 0 means 0 RPM
  */
  static inline u8 FAN_TO_REG(long rpm, int div)
  {
  	if (rpm == 0)
  		return 0;
  	return SENSORS_LIMIT(1310720 / (rpm * div), 1, 255);
  }
  
  #define FAN_FROM_REG(val, div) ((val) == 0 ? 0 : 1310720 / ((val) * (div)))
  
  struct vt8231_data {
ec5e1a4b8   Roger Lucas   hwmon: Convert vt...
146
147
  	unsigned short addr;
  	const char *name;
9a61bf630   Ingo Molnar   [PATCH] hwmon: Se...
148
  	struct mutex update_lock;
1beeffe43   Tony Jones   hwmon: Convert fr...
149
  	struct device *hwmon_dev;
1de9e371b   Roger Lucas   [PATCH] hwmon: Ne...
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
  	char valid;		/* !=0 if following fields are valid */
  	unsigned long last_updated;	/* In jiffies */
  
  	u8 in[6];		/* Register value */
  	u8 in_max[6];		/* Register value */
  	u8 in_min[6];		/* Register value */
  	u16 temp[6];		/* Register value 10 bit, right aligned */
  	u8 temp_max[6];		/* Register value */
  	u8 temp_min[6];		/* Register value */
  	u8 fan[2];		/* Register value */
  	u8 fan_min[2];		/* Register value */
  	u8 fan_div[2];		/* Register encoding, shifted right */
  	u16 alarms;		/* Register encoding */
  	u8 uch_config;
  };
  
  static struct pci_dev *s_bridge;
ec5e1a4b8   Roger Lucas   hwmon: Convert vt...
167
  static int vt8231_probe(struct platform_device *pdev);
d05461289   Jean Delvare   hwmon: Add missin...
168
  static int __devexit vt8231_remove(struct platform_device *pdev);
1de9e371b   Roger Lucas   [PATCH] hwmon: Ne...
169
  static struct vt8231_data *vt8231_update_device(struct device *dev);
ec5e1a4b8   Roger Lucas   hwmon: Convert vt...
170
  static void vt8231_init_device(struct vt8231_data *data);
1de9e371b   Roger Lucas   [PATCH] hwmon: Ne...
171

ec5e1a4b8   Roger Lucas   hwmon: Convert vt...
172
  static inline int vt8231_read_value(struct vt8231_data *data, u8 reg)
1de9e371b   Roger Lucas   [PATCH] hwmon: Ne...
173
  {
ec5e1a4b8   Roger Lucas   hwmon: Convert vt...
174
  	return inb_p(data->addr + reg);
1de9e371b   Roger Lucas   [PATCH] hwmon: Ne...
175
  }
ec5e1a4b8   Roger Lucas   hwmon: Convert vt...
176
  static inline void vt8231_write_value(struct vt8231_data *data, u8 reg,
1de9e371b   Roger Lucas   [PATCH] hwmon: Ne...
177
178
  					u8 value)
  {
ec5e1a4b8   Roger Lucas   hwmon: Convert vt...
179
  	outb_p(value, data->addr + reg);
1de9e371b   Roger Lucas   [PATCH] hwmon: Ne...
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
  }
  
  /* following are the sysfs callback functions */
  static ssize_t show_in(struct device *dev, struct device_attribute *attr,
  		char *buf)
  {
  	struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr);
  	int nr = sensor_attr->index;
  	struct vt8231_data *data = vt8231_update_device(dev);
  
  	return sprintf(buf, "%d
  ", ((data->in[nr] - 3) * 10000) / 958);
  }
  
  static ssize_t show_in_min(struct device *dev, struct device_attribute *attr,
  		char *buf)
  {
  	struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr);
  	int nr = sensor_attr->index;
  	struct vt8231_data *data = vt8231_update_device(dev);
  
  	return sprintf(buf, "%d
  ", ((data->in_min[nr] - 3) * 10000) / 958);
  }
  
  static ssize_t show_in_max(struct device *dev, struct device_attribute *attr,
  		char *buf)
  {
  	struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr);
  	int nr = sensor_attr->index;
  	struct vt8231_data *data = vt8231_update_device(dev);
  
  	return sprintf(buf, "%d
  ", (((data->in_max[nr] - 3) * 10000) / 958));
  }
  
  static ssize_t set_in_min(struct device *dev, struct device_attribute *attr,
  		const char *buf, size_t count)
  {
  	struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr);
  	int nr = sensor_attr->index;
ec5e1a4b8   Roger Lucas   hwmon: Convert vt...
221
  	struct vt8231_data *data = dev_get_drvdata(dev);
1de9e371b   Roger Lucas   [PATCH] hwmon: Ne...
222
  	unsigned long val = simple_strtoul(buf, NULL, 10);
9a61bf630   Ingo Molnar   [PATCH] hwmon: Se...
223
  	mutex_lock(&data->update_lock);
1de9e371b   Roger Lucas   [PATCH] hwmon: Ne...
224
  	data->in_min[nr] = SENSORS_LIMIT(((val * 958) / 10000) + 3, 0, 255);
ec5e1a4b8   Roger Lucas   hwmon: Convert vt...
225
  	vt8231_write_value(data, regvoltmin[nr], data->in_min[nr]);
9a61bf630   Ingo Molnar   [PATCH] hwmon: Se...
226
  	mutex_unlock(&data->update_lock);
1de9e371b   Roger Lucas   [PATCH] hwmon: Ne...
227
228
229
230
231
232
233
234
  	return count;
  }
  
  static ssize_t set_in_max(struct device *dev, struct device_attribute *attr,
  		const char *buf, size_t count)
  {
  	struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr);
  	int nr = sensor_attr->index;
ec5e1a4b8   Roger Lucas   hwmon: Convert vt...
235
  	struct vt8231_data *data = dev_get_drvdata(dev);
1de9e371b   Roger Lucas   [PATCH] hwmon: Ne...
236
  	unsigned long val = simple_strtoul(buf, NULL, 10);
9a61bf630   Ingo Molnar   [PATCH] hwmon: Se...
237
  	mutex_lock(&data->update_lock);
1de9e371b   Roger Lucas   [PATCH] hwmon: Ne...
238
  	data->in_max[nr] = SENSORS_LIMIT(((val * 958) / 10000) + 3, 0, 255);
ec5e1a4b8   Roger Lucas   hwmon: Convert vt...
239
  	vt8231_write_value(data, regvoltmax[nr], data->in_max[nr]);
9a61bf630   Ingo Molnar   [PATCH] hwmon: Se...
240
  	mutex_unlock(&data->update_lock);
1de9e371b   Roger Lucas   [PATCH] hwmon: Ne...
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
  	return count;
  }
  
  /* Special case for input 5 as this has 3.3V scaling built into the chip */
  static ssize_t show_in5(struct device *dev, struct device_attribute *attr,
  		char *buf)
  {
  	struct vt8231_data *data = vt8231_update_device(dev);
  
  	return sprintf(buf, "%d
  ",
  		(((data->in[5] - 3) * 10000 * 54) / (958 * 34)));
  }
  
  static ssize_t show_in5_min(struct device *dev, struct device_attribute *attr,
  		char *buf)
  {
  	struct vt8231_data *data = vt8231_update_device(dev);
  
  	return sprintf(buf, "%d
  ",
  		(((data->in_min[5] - 3) * 10000 * 54) / (958 * 34)));
  }
  
  static ssize_t show_in5_max(struct device *dev, struct device_attribute *attr,
  		char *buf)
  {
  	struct vt8231_data *data = vt8231_update_device(dev);
  
  	return sprintf(buf, "%d
  ",
  		(((data->in_max[5] - 3) * 10000 * 54) / (958 * 34)));
  }
  
  static ssize_t set_in5_min(struct device *dev, struct device_attribute *attr,
  		const char *buf, size_t count)
  {
ec5e1a4b8   Roger Lucas   hwmon: Convert vt...
278
  	struct vt8231_data *data = dev_get_drvdata(dev);
1de9e371b   Roger Lucas   [PATCH] hwmon: Ne...
279
  	unsigned long val = simple_strtoul(buf, NULL, 10);
9a61bf630   Ingo Molnar   [PATCH] hwmon: Se...
280
  	mutex_lock(&data->update_lock);
1de9e371b   Roger Lucas   [PATCH] hwmon: Ne...
281
282
  	data->in_min[5] = SENSORS_LIMIT(((val * 958 * 34) / (10000 * 54)) + 3,
  					0, 255);
ec5e1a4b8   Roger Lucas   hwmon: Convert vt...
283
  	vt8231_write_value(data, regvoltmin[5], data->in_min[5]);
9a61bf630   Ingo Molnar   [PATCH] hwmon: Se...
284
  	mutex_unlock(&data->update_lock);
1de9e371b   Roger Lucas   [PATCH] hwmon: Ne...
285
286
287
288
289
290
  	return count;
  }
  
  static ssize_t set_in5_max(struct device *dev, struct device_attribute *attr,
  		const char *buf, size_t count)
  {
ec5e1a4b8   Roger Lucas   hwmon: Convert vt...
291
  	struct vt8231_data *data = dev_get_drvdata(dev);
1de9e371b   Roger Lucas   [PATCH] hwmon: Ne...
292
  	unsigned long val = simple_strtoul(buf, NULL, 10);
9a61bf630   Ingo Molnar   [PATCH] hwmon: Se...
293
  	mutex_lock(&data->update_lock);
1de9e371b   Roger Lucas   [PATCH] hwmon: Ne...
294
295
  	data->in_max[5] = SENSORS_LIMIT(((val * 958 * 34) / (10000 * 54)) + 3,
  					0, 255);
ec5e1a4b8   Roger Lucas   hwmon: Convert vt...
296
  	vt8231_write_value(data, regvoltmax[5], data->in_max[5]);
9a61bf630   Ingo Molnar   [PATCH] hwmon: Se...
297
  	mutex_unlock(&data->update_lock);
1de9e371b   Roger Lucas   [PATCH] hwmon: Ne...
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
  	return count;
  }
  
  #define define_voltage_sysfs(offset)				\
  static SENSOR_DEVICE_ATTR(in##offset##_input, S_IRUGO,		\
  		show_in, NULL, offset);				\
  static SENSOR_DEVICE_ATTR(in##offset##_min, S_IRUGO | S_IWUSR,	\
  		show_in_min, set_in_min, offset);		\
  static SENSOR_DEVICE_ATTR(in##offset##_max, S_IRUGO | S_IWUSR,	\
  		show_in_max, set_in_max, offset)
  
  define_voltage_sysfs(0);
  define_voltage_sysfs(1);
  define_voltage_sysfs(2);
  define_voltage_sysfs(3);
  define_voltage_sysfs(4);
  
  static DEVICE_ATTR(in5_input, S_IRUGO, show_in5, NULL);
  static DEVICE_ATTR(in5_min, S_IRUGO | S_IWUSR, show_in5_min, set_in5_min);
  static DEVICE_ATTR(in5_max, S_IRUGO | S_IWUSR, show_in5_max, set_in5_max);
  
  /* Temperatures */
  static ssize_t show_temp0(struct device *dev, struct device_attribute *attr,
  		char *buf)
  {
  	struct vt8231_data *data = vt8231_update_device(dev);
  	return sprintf(buf, "%d
  ", data->temp[0] * 250);
  }
  
  static ssize_t show_temp0_max(struct device *dev, struct device_attribute *attr,
  		char *buf)
  {
  	struct vt8231_data *data = vt8231_update_device(dev);
  	return sprintf(buf, "%d
  ", data->temp_max[0] * 1000);
  }
  
  static ssize_t show_temp0_min(struct device *dev, struct device_attribute *attr,
  		char *buf)
  {
  	struct vt8231_data *data = vt8231_update_device(dev);
  	return sprintf(buf, "%d
  ", data->temp_min[0] * 1000);
  }
  
  static ssize_t set_temp0_max(struct device *dev, struct device_attribute *attr,
  		const char *buf, size_t count)
  {
ec5e1a4b8   Roger Lucas   hwmon: Convert vt...
347
  	struct vt8231_data *data = dev_get_drvdata(dev);
1de9e371b   Roger Lucas   [PATCH] hwmon: Ne...
348
  	int val = simple_strtol(buf, NULL, 10);
9a61bf630   Ingo Molnar   [PATCH] hwmon: Se...
349
  	mutex_lock(&data->update_lock);
1de9e371b   Roger Lucas   [PATCH] hwmon: Ne...
350
  	data->temp_max[0] = SENSORS_LIMIT((val + 500) / 1000, 0, 255);
ec5e1a4b8   Roger Lucas   hwmon: Convert vt...
351
  	vt8231_write_value(data, regtempmax[0], data->temp_max[0]);
9a61bf630   Ingo Molnar   [PATCH] hwmon: Se...
352
  	mutex_unlock(&data->update_lock);
1de9e371b   Roger Lucas   [PATCH] hwmon: Ne...
353
354
355
356
357
  	return count;
  }
  static ssize_t set_temp0_min(struct device *dev, struct device_attribute *attr,
  		const char *buf, size_t count)
  {
ec5e1a4b8   Roger Lucas   hwmon: Convert vt...
358
  	struct vt8231_data *data = dev_get_drvdata(dev);
1de9e371b   Roger Lucas   [PATCH] hwmon: Ne...
359
  	int val = simple_strtol(buf, NULL, 10);
9a61bf630   Ingo Molnar   [PATCH] hwmon: Se...
360
  	mutex_lock(&data->update_lock);
1de9e371b   Roger Lucas   [PATCH] hwmon: Ne...
361
  	data->temp_min[0] = SENSORS_LIMIT((val + 500) / 1000, 0, 255);
ec5e1a4b8   Roger Lucas   hwmon: Convert vt...
362
  	vt8231_write_value(data, regtempmin[0], data->temp_min[0]);
9a61bf630   Ingo Molnar   [PATCH] hwmon: Se...
363
  	mutex_unlock(&data->update_lock);
1de9e371b   Roger Lucas   [PATCH] hwmon: Ne...
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
  	return count;
  }
  
  static ssize_t show_temp(struct device *dev, struct device_attribute *attr,
  		char *buf)
  {
  	struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr);
  	int nr = sensor_attr->index;
  	struct vt8231_data *data = vt8231_update_device(dev);
  	return sprintf(buf, "%d
  ", TEMP_FROM_REG(data->temp[nr]));
  }
  
  static ssize_t show_temp_max(struct device *dev, struct device_attribute *attr,
  		char *buf)
  {
  	struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr);
  	int nr = sensor_attr->index;
  	struct vt8231_data *data = vt8231_update_device(dev);
  	return sprintf(buf, "%d
  ", TEMP_MAXMIN_FROM_REG(data->temp_max[nr]));
  }
  
  static ssize_t show_temp_min(struct device *dev, struct device_attribute *attr,
  		char *buf)
  {
  	struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr);
  	int nr = sensor_attr->index;
  	struct vt8231_data *data = vt8231_update_device(dev);
  	return sprintf(buf, "%d
  ", TEMP_MAXMIN_FROM_REG(data->temp_min[nr]));
  }
  
  static ssize_t set_temp_max(struct device *dev, struct device_attribute *attr,
  		const char *buf, size_t count)
  {
  	struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr);
  	int nr = sensor_attr->index;
ec5e1a4b8   Roger Lucas   hwmon: Convert vt...
402
  	struct vt8231_data *data = dev_get_drvdata(dev);
1de9e371b   Roger Lucas   [PATCH] hwmon: Ne...
403
  	int val = simple_strtol(buf, NULL, 10);
9a61bf630   Ingo Molnar   [PATCH] hwmon: Se...
404
  	mutex_lock(&data->update_lock);
1de9e371b   Roger Lucas   [PATCH] hwmon: Ne...
405
  	data->temp_max[nr] = SENSORS_LIMIT(TEMP_MAXMIN_TO_REG(val), 0, 255);
ec5e1a4b8   Roger Lucas   hwmon: Convert vt...
406
  	vt8231_write_value(data, regtempmax[nr], data->temp_max[nr]);
9a61bf630   Ingo Molnar   [PATCH] hwmon: Se...
407
  	mutex_unlock(&data->update_lock);
1de9e371b   Roger Lucas   [PATCH] hwmon: Ne...
408
409
410
411
412
413
414
  	return count;
  }
  static ssize_t set_temp_min(struct device *dev, struct device_attribute *attr,
  		const char *buf, size_t count)
  {
  	struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr);
  	int nr = sensor_attr->index;
ec5e1a4b8   Roger Lucas   hwmon: Convert vt...
415
  	struct vt8231_data *data = dev_get_drvdata(dev);
1de9e371b   Roger Lucas   [PATCH] hwmon: Ne...
416
  	int val = simple_strtol(buf, NULL, 10);
9a61bf630   Ingo Molnar   [PATCH] hwmon: Se...
417
  	mutex_lock(&data->update_lock);
1de9e371b   Roger Lucas   [PATCH] hwmon: Ne...
418
  	data->temp_min[nr] = SENSORS_LIMIT(TEMP_MAXMIN_TO_REG(val), 0, 255);
ec5e1a4b8   Roger Lucas   hwmon: Convert vt...
419
  	vt8231_write_value(data, regtempmin[nr], data->temp_min[nr]);
9a61bf630   Ingo Molnar   [PATCH] hwmon: Se...
420
  	mutex_unlock(&data->update_lock);
1de9e371b   Roger Lucas   [PATCH] hwmon: Ne...
421
422
423
424
425
426
427
428
429
430
431
  	return count;
  }
  
  /* Note that these map the Linux temperature sensor numbering (1-6) to the VIA
  ** temperature sensor numbering (0-5)
  */
  #define define_temperature_sysfs(offset)				\
  static SENSOR_DEVICE_ATTR(temp##offset##_input, S_IRUGO,		\
  		show_temp, NULL, offset - 1);				\
  static SENSOR_DEVICE_ATTR(temp##offset##_max, S_IRUGO | S_IWUSR,	\
  		show_temp_max, set_temp_max, offset - 1);		\
e3efa5a73   Jean Delvare   [PATCH] vt8231: F...
432
  static SENSOR_DEVICE_ATTR(temp##offset##_max_hyst, S_IRUGO | S_IWUSR,	\
1de9e371b   Roger Lucas   [PATCH] hwmon: Ne...
433
434
435
436
  		show_temp_min, set_temp_min, offset - 1)
  
  static DEVICE_ATTR(temp1_input, S_IRUGO, show_temp0, NULL);
  static DEVICE_ATTR(temp1_max, S_IRUGO | S_IWUSR, show_temp0_max, set_temp0_max);
e3efa5a73   Jean Delvare   [PATCH] vt8231: F...
437
  static DEVICE_ATTR(temp1_max_hyst, S_IRUGO | S_IWUSR, show_temp0_min, set_temp0_min);
1de9e371b   Roger Lucas   [PATCH] hwmon: Ne...
438
439
440
441
442
443
  
  define_temperature_sysfs(2);
  define_temperature_sysfs(3);
  define_temperature_sysfs(4);
  define_temperature_sysfs(5);
  define_temperature_sysfs(6);
1de9e371b   Roger Lucas   [PATCH] hwmon: Ne...
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
  /* Fans */
  static ssize_t show_fan(struct device *dev, struct device_attribute *attr,
  		char *buf)
  {
  	struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr);
  	int nr = sensor_attr->index;
  	struct vt8231_data *data = vt8231_update_device(dev);
  	return sprintf(buf, "%d
  ", FAN_FROM_REG(data->fan[nr],
  				DIV_FROM_REG(data->fan_div[nr])));
  }
  
  static ssize_t show_fan_min(struct device *dev, struct device_attribute *attr,
  		char *buf)
  {
  	struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr);
  	int nr = sensor_attr->index;
  	struct vt8231_data *data = vt8231_update_device(dev);
  	return sprintf(buf, "%d
  ", FAN_FROM_REG(data->fan_min[nr],
  			DIV_FROM_REG(data->fan_div[nr])));
  }
  
  static ssize_t show_fan_div(struct device *dev, struct device_attribute *attr,
  		char *buf)
  {
  	struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr);
  	int nr = sensor_attr->index;
  	struct vt8231_data *data = vt8231_update_device(dev);
  	return sprintf(buf, "%d
  ", DIV_FROM_REG(data->fan_div[nr]));
  }
  
  static ssize_t set_fan_min(struct device *dev, struct device_attribute *attr,
  		const char *buf, size_t count)
  {
  	struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr);
  	int nr = sensor_attr->index;
ec5e1a4b8   Roger Lucas   hwmon: Convert vt...
482
  	struct vt8231_data *data = dev_get_drvdata(dev);
1de9e371b   Roger Lucas   [PATCH] hwmon: Ne...
483
  	int val = simple_strtoul(buf, NULL, 10);
9a61bf630   Ingo Molnar   [PATCH] hwmon: Se...
484
  	mutex_lock(&data->update_lock);
1de9e371b   Roger Lucas   [PATCH] hwmon: Ne...
485
  	data->fan_min[nr] = FAN_TO_REG(val, DIV_FROM_REG(data->fan_div[nr]));
ec5e1a4b8   Roger Lucas   hwmon: Convert vt...
486
  	vt8231_write_value(data, VT8231_REG_FAN_MIN(nr), data->fan_min[nr]);
9a61bf630   Ingo Molnar   [PATCH] hwmon: Se...
487
  	mutex_unlock(&data->update_lock);
1de9e371b   Roger Lucas   [PATCH] hwmon: Ne...
488
489
490
491
492
493
  	return count;
  }
  
  static ssize_t set_fan_div(struct device *dev, struct device_attribute *attr,
  		const char *buf, size_t count)
  {
ec5e1a4b8   Roger Lucas   hwmon: Convert vt...
494
  	struct vt8231_data *data = dev_get_drvdata(dev);
1de9e371b   Roger Lucas   [PATCH] hwmon: Ne...
495
496
497
  	struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr);
  	unsigned long val = simple_strtoul(buf, NULL, 10);
  	int nr = sensor_attr->index;
ec5e1a4b8   Roger Lucas   hwmon: Convert vt...
498
  	int old = vt8231_read_value(data, VT8231_REG_FANDIV);
1de9e371b   Roger Lucas   [PATCH] hwmon: Ne...
499
500
  	long min = FAN_FROM_REG(data->fan_min[nr],
  				 DIV_FROM_REG(data->fan_div[nr]));
9a61bf630   Ingo Molnar   [PATCH] hwmon: Se...
501
  	mutex_lock(&data->update_lock);
1de9e371b   Roger Lucas   [PATCH] hwmon: Ne...
502
503
504
505
506
507
  	switch (val) {
  	case 1: data->fan_div[nr] = 0; break;
  	case 2: data->fan_div[nr] = 1; break;
  	case 4: data->fan_div[nr] = 2; break;
  	case 8: data->fan_div[nr] = 3; break;
  	default:
b20ff13a6   Joe Perches   hwmon: (vt8231) A...
508
  		dev_err(dev, "fan_div value %ld not supported. "
1de9e371b   Roger Lucas   [PATCH] hwmon: Ne...
509
510
  		        "Choose one of 1, 2, 4 or 8!
  ", val);
9a61bf630   Ingo Molnar   [PATCH] hwmon: Se...
511
  		mutex_unlock(&data->update_lock);
1de9e371b   Roger Lucas   [PATCH] hwmon: Ne...
512
513
514
515
516
  		return -EINVAL;
  	}
  
  	/* Correct the fan minimum speed */
  	data->fan_min[nr] = FAN_TO_REG(min, DIV_FROM_REG(data->fan_div[nr]));
ec5e1a4b8   Roger Lucas   hwmon: Convert vt...
517
  	vt8231_write_value(data, VT8231_REG_FAN_MIN(nr), data->fan_min[nr]);
1de9e371b   Roger Lucas   [PATCH] hwmon: Ne...
518
519
  
  	old = (old & 0x0f) | (data->fan_div[1] << 6) | (data->fan_div[0] << 4);
ec5e1a4b8   Roger Lucas   hwmon: Convert vt...
520
  	vt8231_write_value(data, VT8231_REG_FANDIV, old);
9a61bf630   Ingo Molnar   [PATCH] hwmon: Se...
521
  	mutex_unlock(&data->update_lock);
1de9e371b   Roger Lucas   [PATCH] hwmon: Ne...
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
  	return count;
  }
  
  
  #define define_fan_sysfs(offset)					\
  static SENSOR_DEVICE_ATTR(fan##offset##_input, S_IRUGO,			\
  		show_fan, NULL, offset - 1);				\
  static SENSOR_DEVICE_ATTR(fan##offset##_div, S_IRUGO | S_IWUSR,		\
  		show_fan_div, set_fan_div, offset - 1);			\
  static SENSOR_DEVICE_ATTR(fan##offset##_min, S_IRUGO | S_IWUSR,		\
  		show_fan_min, set_fan_min, offset - 1)
  
  define_fan_sysfs(1);
  define_fan_sysfs(2);
  
  /* Alarms */
  static ssize_t show_alarms(struct device *dev, struct device_attribute *attr,
  			   char *buf)
  {
  	struct vt8231_data *data = vt8231_update_device(dev);
  	return sprintf(buf, "%d
  ", data->alarms);
  }
1de9e371b   Roger Lucas   [PATCH] hwmon: Ne...
545
  static DEVICE_ATTR(alarms, S_IRUGO, show_alarms, NULL);
2d1374cad   Jean Delvare   hwmon: (vt8231) A...
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
  static ssize_t show_alarm(struct device *dev, struct device_attribute *attr,
  			  char *buf)
  {
  	int bitnr = to_sensor_dev_attr(attr)->index;
  	struct vt8231_data *data = vt8231_update_device(dev);
  	return sprintf(buf, "%u
  ", (data->alarms >> bitnr) & 1);
  }
  static SENSOR_DEVICE_ATTR(temp1_alarm, S_IRUGO, show_alarm, NULL, 4);
  static SENSOR_DEVICE_ATTR(temp2_alarm, S_IRUGO, show_alarm, NULL, 11);
  static SENSOR_DEVICE_ATTR(temp3_alarm, S_IRUGO, show_alarm, NULL, 0);
  static SENSOR_DEVICE_ATTR(temp4_alarm, S_IRUGO, show_alarm, NULL, 1);
  static SENSOR_DEVICE_ATTR(temp5_alarm, S_IRUGO, show_alarm, NULL, 3);
  static SENSOR_DEVICE_ATTR(temp6_alarm, S_IRUGO, show_alarm, NULL, 8);
  static SENSOR_DEVICE_ATTR(in0_alarm, S_IRUGO, show_alarm, NULL, 11);
  static SENSOR_DEVICE_ATTR(in1_alarm, S_IRUGO, show_alarm, NULL, 0);
  static SENSOR_DEVICE_ATTR(in2_alarm, S_IRUGO, show_alarm, NULL, 1);
  static SENSOR_DEVICE_ATTR(in3_alarm, S_IRUGO, show_alarm, NULL, 3);
  static SENSOR_DEVICE_ATTR(in4_alarm, S_IRUGO, show_alarm, NULL, 8);
  static SENSOR_DEVICE_ATTR(in5_alarm, S_IRUGO, show_alarm, NULL, 2);
  static SENSOR_DEVICE_ATTR(fan1_alarm, S_IRUGO, show_alarm, NULL, 6);
  static SENSOR_DEVICE_ATTR(fan2_alarm, S_IRUGO, show_alarm, NULL, 7);
ec5e1a4b8   Roger Lucas   hwmon: Convert vt...
568
569
570
571
572
573
574
575
  static ssize_t show_name(struct device *dev, struct device_attribute
  			 *devattr, char *buf)
  {
  	struct vt8231_data *data = dev_get_drvdata(dev);
  	return sprintf(buf, "%s
  ", data->name);
  }
  static DEVICE_ATTR(name, S_IRUGO, show_name, NULL);
2d1374cad   Jean Delvare   hwmon: (vt8231) A...
576
  static struct attribute *vt8231_attributes_temps[6][5] = {
cbeeb5b7c   Roger Lucas   vt8231: Fix unche...
577
578
579
580
  	{
  		&dev_attr_temp1_input.attr,
  		&dev_attr_temp1_max_hyst.attr,
  		&dev_attr_temp1_max.attr,
2d1374cad   Jean Delvare   hwmon: (vt8231) A...
581
  		&sensor_dev_attr_temp1_alarm.dev_attr.attr,
cbeeb5b7c   Roger Lucas   vt8231: Fix unche...
582
583
584
585
586
  		NULL
  	}, {
  		&sensor_dev_attr_temp2_input.dev_attr.attr,
  		&sensor_dev_attr_temp2_max_hyst.dev_attr.attr,
  		&sensor_dev_attr_temp2_max.dev_attr.attr,
2d1374cad   Jean Delvare   hwmon: (vt8231) A...
587
  		&sensor_dev_attr_temp2_alarm.dev_attr.attr,
cbeeb5b7c   Roger Lucas   vt8231: Fix unche...
588
589
590
591
592
  		NULL
  	}, {
  		&sensor_dev_attr_temp3_input.dev_attr.attr,
  		&sensor_dev_attr_temp3_max_hyst.dev_attr.attr,
  		&sensor_dev_attr_temp3_max.dev_attr.attr,
2d1374cad   Jean Delvare   hwmon: (vt8231) A...
593
  		&sensor_dev_attr_temp3_alarm.dev_attr.attr,
cbeeb5b7c   Roger Lucas   vt8231: Fix unche...
594
595
596
597
598
  		NULL
  	}, {
  		&sensor_dev_attr_temp4_input.dev_attr.attr,
  		&sensor_dev_attr_temp4_max_hyst.dev_attr.attr,
  		&sensor_dev_attr_temp4_max.dev_attr.attr,
2d1374cad   Jean Delvare   hwmon: (vt8231) A...
599
  		&sensor_dev_attr_temp4_alarm.dev_attr.attr,
cbeeb5b7c   Roger Lucas   vt8231: Fix unche...
600
601
602
603
604
  		NULL
  	}, {
  		&sensor_dev_attr_temp5_input.dev_attr.attr,
  		&sensor_dev_attr_temp5_max_hyst.dev_attr.attr,
  		&sensor_dev_attr_temp5_max.dev_attr.attr,
2d1374cad   Jean Delvare   hwmon: (vt8231) A...
605
  		&sensor_dev_attr_temp5_alarm.dev_attr.attr,
cbeeb5b7c   Roger Lucas   vt8231: Fix unche...
606
607
608
609
610
  		NULL
  	}, {
  		&sensor_dev_attr_temp6_input.dev_attr.attr,
  		&sensor_dev_attr_temp6_max_hyst.dev_attr.attr,
  		&sensor_dev_attr_temp6_max.dev_attr.attr,
2d1374cad   Jean Delvare   hwmon: (vt8231) A...
611
  		&sensor_dev_attr_temp6_alarm.dev_attr.attr,
cbeeb5b7c   Roger Lucas   vt8231: Fix unche...
612
613
614
615
616
617
618
619
620
621
622
623
  		NULL
  	}
  };
  
  static const struct attribute_group vt8231_group_temps[6] = {
  	{ .attrs = vt8231_attributes_temps[0] },
  	{ .attrs = vt8231_attributes_temps[1] },
  	{ .attrs = vt8231_attributes_temps[2] },
  	{ .attrs = vt8231_attributes_temps[3] },
  	{ .attrs = vt8231_attributes_temps[4] },
  	{ .attrs = vt8231_attributes_temps[5] },
  };
2d1374cad   Jean Delvare   hwmon: (vt8231) A...
624
  static struct attribute *vt8231_attributes_volts[6][5] = {
cbeeb5b7c   Roger Lucas   vt8231: Fix unche...
625
626
627
628
  	{
  		&sensor_dev_attr_in0_input.dev_attr.attr,
  		&sensor_dev_attr_in0_min.dev_attr.attr,
  		&sensor_dev_attr_in0_max.dev_attr.attr,
2d1374cad   Jean Delvare   hwmon: (vt8231) A...
629
  		&sensor_dev_attr_in0_alarm.dev_attr.attr,
cbeeb5b7c   Roger Lucas   vt8231: Fix unche...
630
631
632
633
634
  		NULL
  	}, {
  		&sensor_dev_attr_in1_input.dev_attr.attr,
  		&sensor_dev_attr_in1_min.dev_attr.attr,
  		&sensor_dev_attr_in1_max.dev_attr.attr,
2d1374cad   Jean Delvare   hwmon: (vt8231) A...
635
  		&sensor_dev_attr_in1_alarm.dev_attr.attr,
cbeeb5b7c   Roger Lucas   vt8231: Fix unche...
636
637
638
639
640
  		NULL
  	}, {
  		&sensor_dev_attr_in2_input.dev_attr.attr,
  		&sensor_dev_attr_in2_min.dev_attr.attr,
  		&sensor_dev_attr_in2_max.dev_attr.attr,
2d1374cad   Jean Delvare   hwmon: (vt8231) A...
641
  		&sensor_dev_attr_in2_alarm.dev_attr.attr,
cbeeb5b7c   Roger Lucas   vt8231: Fix unche...
642
643
644
645
646
  		NULL
  	}, {
  		&sensor_dev_attr_in3_input.dev_attr.attr,
  		&sensor_dev_attr_in3_min.dev_attr.attr,
  		&sensor_dev_attr_in3_max.dev_attr.attr,
2d1374cad   Jean Delvare   hwmon: (vt8231) A...
647
  		&sensor_dev_attr_in3_alarm.dev_attr.attr,
cbeeb5b7c   Roger Lucas   vt8231: Fix unche...
648
649
650
651
652
  		NULL
  	}, {
  		&sensor_dev_attr_in4_input.dev_attr.attr,
  		&sensor_dev_attr_in4_min.dev_attr.attr,
  		&sensor_dev_attr_in4_max.dev_attr.attr,
2d1374cad   Jean Delvare   hwmon: (vt8231) A...
653
  		&sensor_dev_attr_in4_alarm.dev_attr.attr,
cbeeb5b7c   Roger Lucas   vt8231: Fix unche...
654
655
656
657
658
  		NULL
  	}, {
  		&dev_attr_in5_input.attr,
  		&dev_attr_in5_min.attr,
  		&dev_attr_in5_max.attr,
2d1374cad   Jean Delvare   hwmon: (vt8231) A...
659
  		&sensor_dev_attr_in5_alarm.dev_attr.attr,
cbeeb5b7c   Roger Lucas   vt8231: Fix unche...
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
  		NULL
  	}
  };
  
  static const struct attribute_group vt8231_group_volts[6] = {
  	{ .attrs = vt8231_attributes_volts[0] },
  	{ .attrs = vt8231_attributes_volts[1] },
  	{ .attrs = vt8231_attributes_volts[2] },
  	{ .attrs = vt8231_attributes_volts[3] },
  	{ .attrs = vt8231_attributes_volts[4] },
  	{ .attrs = vt8231_attributes_volts[5] },
  };
  
  static struct attribute *vt8231_attributes[] = {
  	&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,
2d1374cad   Jean Delvare   hwmon: (vt8231) A...
680
681
  	&sensor_dev_attr_fan1_alarm.dev_attr.attr,
  	&sensor_dev_attr_fan2_alarm.dev_attr.attr,
cbeeb5b7c   Roger Lucas   vt8231: Fix unche...
682
  	&dev_attr_alarms.attr,
ec5e1a4b8   Roger Lucas   hwmon: Convert vt...
683
  	&dev_attr_name.attr,
cbeeb5b7c   Roger Lucas   vt8231: Fix unche...
684
685
686
687
688
689
  	NULL
  };
  
  static const struct attribute_group vt8231_group = {
  	.attrs = vt8231_attributes,
  };
ec5e1a4b8   Roger Lucas   hwmon: Convert vt...
690
  static struct platform_driver vt8231_driver = {
cdaf79349   Laurent Riffard   [PATCH] i2c: Drop...
691
  	.driver = {
872188420   Jean Delvare   i2c-isa: Restore ...
692
  		.owner	= THIS_MODULE,
cdaf79349   Laurent Riffard   [PATCH] i2c: Drop...
693
694
  		.name	= "vt8231",
  	},
ec5e1a4b8   Roger Lucas   hwmon: Convert vt...
695
696
  	.probe	= vt8231_probe,
  	.remove	= __devexit_p(vt8231_remove),
1de9e371b   Roger Lucas   [PATCH] hwmon: Ne...
697
  };
3dd3a1563   Márton Németh   hwmon: Make PCI d...
698
  static const struct pci_device_id vt8231_pci_ids[] = {
1de9e371b   Roger Lucas   [PATCH] hwmon: Ne...
699
700
701
702
703
704
705
706
707
708
709
710
711
712
  	{ PCI_DEVICE(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_8231_4) },
  	{ 0, }
  };
  
  MODULE_DEVICE_TABLE(pci, vt8231_pci_ids);
  
  static int __devinit vt8231_pci_probe(struct pci_dev *dev,
  			 	      const struct pci_device_id *id);
  
  static struct pci_driver vt8231_pci_driver = {
  	.name		= "vt8231",
  	.id_table	= vt8231_pci_ids,
  	.probe		= vt8231_pci_probe,
  };
a022fef5a   Mark M. Hoffman   hwmon: (vt8231) f...
713
  static int vt8231_probe(struct platform_device *pdev)
1de9e371b   Roger Lucas   [PATCH] hwmon: Ne...
714
  {
ec5e1a4b8   Roger Lucas   hwmon: Convert vt...
715
  	struct resource *res;
1de9e371b   Roger Lucas   [PATCH] hwmon: Ne...
716
717
  	struct vt8231_data *data;
  	int err = 0, i;
1de9e371b   Roger Lucas   [PATCH] hwmon: Ne...
718
719
  
  	/* Reserve the ISA region */
ec5e1a4b8   Roger Lucas   hwmon: Convert vt...
720
721
722
723
724
725
  	res = platform_get_resource(pdev, IORESOURCE_IO, 0);
  	if (!request_region(res->start, VT8231_EXTENT,
  			    vt8231_driver.driver.name)) {
  		dev_err(&pdev->dev, "Region 0x%lx-0x%lx already in use!
  ",
  			(unsigned long)res->start, (unsigned long)res->end);
1de9e371b   Roger Lucas   [PATCH] hwmon: Ne...
726
727
728
729
730
731
732
  		return -ENODEV;
  	}
  
  	if (!(data = kzalloc(sizeof(struct vt8231_data), GFP_KERNEL))) {
  		err = -ENOMEM;
  		goto exit_release;
  	}
ec5e1a4b8   Roger Lucas   hwmon: Convert vt...
733
734
735
  	platform_set_drvdata(pdev, data);
  	data->addr = res->start;
  	data->name = "vt8231";
1de9e371b   Roger Lucas   [PATCH] hwmon: Ne...
736

9a61bf630   Ingo Molnar   [PATCH] hwmon: Se...
737
  	mutex_init(&data->update_lock);
ec5e1a4b8   Roger Lucas   hwmon: Convert vt...
738
  	vt8231_init_device(data);
1de9e371b   Roger Lucas   [PATCH] hwmon: Ne...
739
740
  
  	/* Register sysfs hooks */
ec5e1a4b8   Roger Lucas   hwmon: Convert vt...
741
742
  	if ((err = sysfs_create_group(&pdev->dev.kobj, &vt8231_group)))
  		goto exit_free;
1de9e371b   Roger Lucas   [PATCH] hwmon: Ne...
743
744
  
  	/* Must update device information to find out the config field */
ec5e1a4b8   Roger Lucas   hwmon: Convert vt...
745
  	data->uch_config = vt8231_read_value(data, VT8231_REG_UCH_CONFIG);
1de9e371b   Roger Lucas   [PATCH] hwmon: Ne...
746

cbeeb5b7c   Roger Lucas   vt8231: Fix unche...
747
  	for (i = 0; i < ARRAY_SIZE(vt8231_group_temps); i++) {
1de9e371b   Roger Lucas   [PATCH] hwmon: Ne...
748
  		if (ISTEMP(i, data->uch_config)) {
ec5e1a4b8   Roger Lucas   hwmon: Convert vt...
749
  			if ((err = sysfs_create_group(&pdev->dev.kobj,
cbeeb5b7c   Roger Lucas   vt8231: Fix unche...
750
751
  					&vt8231_group_temps[i])))
  				goto exit_remove_files;
1de9e371b   Roger Lucas   [PATCH] hwmon: Ne...
752
753
  		}
  	}
cbeeb5b7c   Roger Lucas   vt8231: Fix unche...
754
  	for (i = 0; i < ARRAY_SIZE(vt8231_group_volts); i++) {
1de9e371b   Roger Lucas   [PATCH] hwmon: Ne...
755
  		if (ISVOLT(i, data->uch_config)) {
ec5e1a4b8   Roger Lucas   hwmon: Convert vt...
756
  			if ((err = sysfs_create_group(&pdev->dev.kobj,
cbeeb5b7c   Roger Lucas   vt8231: Fix unche...
757
758
  					&vt8231_group_volts[i])))
  				goto exit_remove_files;
1de9e371b   Roger Lucas   [PATCH] hwmon: Ne...
759
760
  		}
  	}
1beeffe43   Tony Jones   hwmon: Convert fr...
761
762
763
  	data->hwmon_dev = hwmon_device_register(&pdev->dev);
  	if (IS_ERR(data->hwmon_dev)) {
  		err = PTR_ERR(data->hwmon_dev);
cbeeb5b7c   Roger Lucas   vt8231: Fix unche...
764
765
  		goto exit_remove_files;
  	}
1de9e371b   Roger Lucas   [PATCH] hwmon: Ne...
766
  	return 0;
cbeeb5b7c   Roger Lucas   vt8231: Fix unche...
767
768
  exit_remove_files:
  	for (i = 0; i < ARRAY_SIZE(vt8231_group_volts); i++)
ec5e1a4b8   Roger Lucas   hwmon: Convert vt...
769
  		sysfs_remove_group(&pdev->dev.kobj, &vt8231_group_volts[i]);
cbeeb5b7c   Roger Lucas   vt8231: Fix unche...
770
771
  
  	for (i = 0; i < ARRAY_SIZE(vt8231_group_temps); i++)
ec5e1a4b8   Roger Lucas   hwmon: Convert vt...
772
773
774
  		sysfs_remove_group(&pdev->dev.kobj, &vt8231_group_temps[i]);
  
  	sysfs_remove_group(&pdev->dev.kobj, &vt8231_group);
cbeeb5b7c   Roger Lucas   vt8231: Fix unche...
775

1de9e371b   Roger Lucas   [PATCH] hwmon: Ne...
776
  exit_free:
04a6217df   Jean Delvare   hwmon: Fix a pote...
777
  	platform_set_drvdata(pdev, NULL);
1de9e371b   Roger Lucas   [PATCH] hwmon: Ne...
778
  	kfree(data);
ec5e1a4b8   Roger Lucas   hwmon: Convert vt...
779

1de9e371b   Roger Lucas   [PATCH] hwmon: Ne...
780
  exit_release:
ec5e1a4b8   Roger Lucas   hwmon: Convert vt...
781
  	release_region(res->start, VT8231_EXTENT);
1de9e371b   Roger Lucas   [PATCH] hwmon: Ne...
782
783
  	return err;
  }
d05461289   Jean Delvare   hwmon: Add missin...
784
  static int __devexit vt8231_remove(struct platform_device *pdev)
1de9e371b   Roger Lucas   [PATCH] hwmon: Ne...
785
  {
ec5e1a4b8   Roger Lucas   hwmon: Convert vt...
786
787
  	struct vt8231_data *data = platform_get_drvdata(pdev);
  	int i;
1de9e371b   Roger Lucas   [PATCH] hwmon: Ne...
788

1beeffe43   Tony Jones   hwmon: Convert fr...
789
  	hwmon_device_unregister(data->hwmon_dev);
1de9e371b   Roger Lucas   [PATCH] hwmon: Ne...
790

cbeeb5b7c   Roger Lucas   vt8231: Fix unche...
791
  	for (i = 0; i < ARRAY_SIZE(vt8231_group_volts); i++)
ec5e1a4b8   Roger Lucas   hwmon: Convert vt...
792
  		sysfs_remove_group(&pdev->dev.kobj, &vt8231_group_volts[i]);
cbeeb5b7c   Roger Lucas   vt8231: Fix unche...
793
794
  
  	for (i = 0; i < ARRAY_SIZE(vt8231_group_temps); i++)
ec5e1a4b8   Roger Lucas   hwmon: Convert vt...
795
  		sysfs_remove_group(&pdev->dev.kobj, &vt8231_group_temps[i]);
cbeeb5b7c   Roger Lucas   vt8231: Fix unche...
796

ec5e1a4b8   Roger Lucas   hwmon: Convert vt...
797
  	sysfs_remove_group(&pdev->dev.kobj, &vt8231_group);
cbeeb5b7c   Roger Lucas   vt8231: Fix unche...
798

ec5e1a4b8   Roger Lucas   hwmon: Convert vt...
799
800
  	release_region(data->addr, VT8231_EXTENT);
  	platform_set_drvdata(pdev, NULL);
1de9e371b   Roger Lucas   [PATCH] hwmon: Ne...
801
  	kfree(data);
1de9e371b   Roger Lucas   [PATCH] hwmon: Ne...
802
803
  	return 0;
  }
ec5e1a4b8   Roger Lucas   hwmon: Convert vt...
804
  static void vt8231_init_device(struct vt8231_data *data)
1de9e371b   Roger Lucas   [PATCH] hwmon: Ne...
805
  {
ec5e1a4b8   Roger Lucas   hwmon: Convert vt...
806
807
  	vt8231_write_value(data, VT8231_REG_TEMP1_CONFIG, 0);
  	vt8231_write_value(data, VT8231_REG_TEMP2_CONFIG, 0);
1de9e371b   Roger Lucas   [PATCH] hwmon: Ne...
808
809
810
811
  }
  
  static struct vt8231_data *vt8231_update_device(struct device *dev)
  {
ec5e1a4b8   Roger Lucas   hwmon: Convert vt...
812
  	struct vt8231_data *data = dev_get_drvdata(dev);
1de9e371b   Roger Lucas   [PATCH] hwmon: Ne...
813
814
  	int i;
  	u16 low;
9a61bf630   Ingo Molnar   [PATCH] hwmon: Se...
815
  	mutex_lock(&data->update_lock);
1de9e371b   Roger Lucas   [PATCH] hwmon: Ne...
816
817
818
819
820
  
  	if (time_after(jiffies, data->last_updated + HZ + HZ / 2)
  	    || !data->valid) {
  		for (i = 0; i < 6; i++) {
  			if (ISVOLT(i, data->uch_config)) {
ec5e1a4b8   Roger Lucas   hwmon: Convert vt...
821
  				data->in[i] = vt8231_read_value(data,
1de9e371b   Roger Lucas   [PATCH] hwmon: Ne...
822
  						regvolt[i]);
ec5e1a4b8   Roger Lucas   hwmon: Convert vt...
823
  				data->in_min[i] = vt8231_read_value(data,
1de9e371b   Roger Lucas   [PATCH] hwmon: Ne...
824
  						regvoltmin[i]);
ec5e1a4b8   Roger Lucas   hwmon: Convert vt...
825
  				data->in_max[i] = vt8231_read_value(data,
1de9e371b   Roger Lucas   [PATCH] hwmon: Ne...
826
827
828
829
  						regvoltmax[i]);
  			}
  		}
  		for (i = 0; i < 2; i++) {
ec5e1a4b8   Roger Lucas   hwmon: Convert vt...
830
  			data->fan[i] = vt8231_read_value(data,
1de9e371b   Roger Lucas   [PATCH] hwmon: Ne...
831
  						VT8231_REG_FAN(i));
ec5e1a4b8   Roger Lucas   hwmon: Convert vt...
832
  			data->fan_min[i] = vt8231_read_value(data,
1de9e371b   Roger Lucas   [PATCH] hwmon: Ne...
833
834
  						VT8231_REG_FAN_MIN(i));
  		}
ec5e1a4b8   Roger Lucas   hwmon: Convert vt...
835
  		low = vt8231_read_value(data, VT8231_REG_TEMP_LOW01);
1de9e371b   Roger Lucas   [PATCH] hwmon: Ne...
836
  		low = (low >> 6) | ((low & 0x30) >> 2)
ec5e1a4b8   Roger Lucas   hwmon: Convert vt...
837
  		    | (vt8231_read_value(data, VT8231_REG_TEMP_LOW25) << 4);
1de9e371b   Roger Lucas   [PATCH] hwmon: Ne...
838
839
  		for (i = 0; i < 6; i++) {
  			if (ISTEMP(i, data->uch_config)) {
ec5e1a4b8   Roger Lucas   hwmon: Convert vt...
840
  				data->temp[i] = (vt8231_read_value(data,
1de9e371b   Roger Lucas   [PATCH] hwmon: Ne...
841
842
  						       regtemp[i]) << 2)
  						| ((low >> (2 * i)) & 0x03);
ec5e1a4b8   Roger Lucas   hwmon: Convert vt...
843
  				data->temp_max[i] = vt8231_read_value(data,
1de9e371b   Roger Lucas   [PATCH] hwmon: Ne...
844
  						      regtempmax[i]);
ec5e1a4b8   Roger Lucas   hwmon: Convert vt...
845
  				data->temp_min[i] = vt8231_read_value(data,
1de9e371b   Roger Lucas   [PATCH] hwmon: Ne...
846
847
848
  						      regtempmin[i]);
  			}
  		}
ec5e1a4b8   Roger Lucas   hwmon: Convert vt...
849
  		i = vt8231_read_value(data, VT8231_REG_FANDIV);
1de9e371b   Roger Lucas   [PATCH] hwmon: Ne...
850
851
  		data->fan_div[0] = (i >> 4) & 0x03;
  		data->fan_div[1] = i >> 6;
ec5e1a4b8   Roger Lucas   hwmon: Convert vt...
852
853
  		data->alarms = vt8231_read_value(data, VT8231_REG_ALARM1) |
  			(vt8231_read_value(data, VT8231_REG_ALARM2) << 8);
1de9e371b   Roger Lucas   [PATCH] hwmon: Ne...
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
  
  		/* Set alarm flags correctly */
  		if (!data->fan[0] && data->fan_min[0]) {
  			data->alarms |= 0x40;
  		} else if (data->fan[0] && !data->fan_min[0]) {
  			data->alarms &= ~0x40;
  		}
  
  		if (!data->fan[1] && data->fan_min[1]) {
  			data->alarms |= 0x80;
  		} else if (data->fan[1] && !data->fan_min[1]) {
  			data->alarms &= ~0x80;
  		}
  
  		data->last_updated = jiffies;
  		data->valid = 1;
  	}
9a61bf630   Ingo Molnar   [PATCH] hwmon: Se...
871
  	mutex_unlock(&data->update_lock);
1de9e371b   Roger Lucas   [PATCH] hwmon: Ne...
872
873
874
  
  	return data;
  }
ec5e1a4b8   Roger Lucas   hwmon: Convert vt...
875
876
877
878
879
880
881
882
883
  static int __devinit vt8231_device_add(unsigned short address)
  {
  	struct resource res = {
  		.start	= address,
  		.end	= address + VT8231_EXTENT - 1,
  		.name	= "vt8231",
  		.flags	= IORESOURCE_IO,
  	};
  	int err;
b9acb64a3   Jean Delvare   hwmon: Check for ...
884
885
886
  	err = acpi_check_resource_conflict(&res);
  	if (err)
  		goto exit;
ec5e1a4b8   Roger Lucas   hwmon: Convert vt...
887
888
889
  	pdev = platform_device_alloc("vt8231", address);
  	if (!pdev) {
  		err = -ENOMEM;
9d72be0da   Joe Perches   hwmon: (vt8231) U...
890
891
  		pr_err("Device allocation failed
  ");
ec5e1a4b8   Roger Lucas   hwmon: Convert vt...
892
893
894
895
896
  		goto exit;
  	}
  
  	err = platform_device_add_resources(pdev, &res, 1);
  	if (err) {
9d72be0da   Joe Perches   hwmon: (vt8231) U...
897
898
  		pr_err("Device resource addition failed (%d)
  ", err);
ec5e1a4b8   Roger Lucas   hwmon: Convert vt...
899
900
901
902
903
  		goto exit_device_put;
  	}
  
  	err = platform_device_add(pdev);
  	if (err) {
9d72be0da   Joe Perches   hwmon: (vt8231) U...
904
905
  		pr_err("Device addition failed (%d)
  ", err);
ec5e1a4b8   Roger Lucas   hwmon: Convert vt...
906
907
908
909
910
911
912
913
914
915
  		goto exit_device_put;
  	}
  
  	return 0;
  
  exit_device_put:
  	platform_device_put(pdev);
  exit:
  	return err;
  }
1de9e371b   Roger Lucas   [PATCH] hwmon: Ne...
916
917
918
  static int __devinit vt8231_pci_probe(struct pci_dev *dev,
  				const struct pci_device_id *id)
  {
ec5e1a4b8   Roger Lucas   hwmon: Convert vt...
919
920
921
922
923
924
925
926
927
928
929
  	u16 address, val;
  	if (force_addr) {
  		address = force_addr & 0xff00;
  		dev_warn(&dev->dev, "Forcing ISA address 0x%x
  ",
  			 address);
  
  		if (PCIBIOS_SUCCESSFUL !=
  		    pci_write_config_word(dev, VT8231_BASE_REG, address | 1))
  			return -ENODEV;
  	}
1de9e371b   Roger Lucas   [PATCH] hwmon: Ne...
930
931
932
933
  
  	if (PCIBIOS_SUCCESSFUL != pci_read_config_word(dev, VT8231_BASE_REG,
  							&val))
  		return -ENODEV;
ec5e1a4b8   Roger Lucas   hwmon: Convert vt...
934
935
  	address = val & ~(VT8231_EXTENT - 1);
  	if (address == 0) {
4cae78784   Joe Perches   drivers/hwmon/vt8...
936
937
  		dev_err(&dev->dev, "base address not set - upgrade BIOS or use force_addr=0xaddr
  ");
1de9e371b   Roger Lucas   [PATCH] hwmon: Ne...
938
939
  		return -ENODEV;
  	}
ec5e1a4b8   Roger Lucas   hwmon: Convert vt...
940
941
942
  	if (PCIBIOS_SUCCESSFUL != pci_read_config_word(dev, VT8231_ENABLE_REG,
  							&val))
  		return -ENODEV;
1de9e371b   Roger Lucas   [PATCH] hwmon: Ne...
943

ec5e1a4b8   Roger Lucas   hwmon: Convert vt...
944
945
946
947
948
949
950
  	if (!(val & 0x0001)) {
  		dev_warn(&dev->dev, "enabling sensors
  ");
  		if (PCIBIOS_SUCCESSFUL !=
  			pci_write_config_word(dev, VT8231_ENABLE_REG,
  							val | 0x0001))
  			return -ENODEV;
1de9e371b   Roger Lucas   [PATCH] hwmon: Ne...
951
  	}
ec5e1a4b8   Roger Lucas   hwmon: Convert vt...
952
953
954
955
956
957
  	if (platform_driver_register(&vt8231_driver))
  		goto exit;
  
  	/* Sets global pdev as a side effect */
  	if (vt8231_device_add(address))
  		goto exit_unregister;
1de9e371b   Roger Lucas   [PATCH] hwmon: Ne...
958
959
960
961
  	/* Always return failure here.  This is to allow other drivers to bind
  	 * 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.
  	 */
ec5e1a4b8   Roger Lucas   hwmon: Convert vt...
962
963
964
965
966
967
968
969
970
  
  	/* We do, however, mark ourselves as using the PCI device to stop it
  	   getting unloaded. */
  	s_bridge = pci_dev_get(dev);
  	return -ENODEV;
  
  exit_unregister:
  	platform_driver_unregister(&vt8231_driver);
  exit:
1de9e371b   Roger Lucas   [PATCH] hwmon: Ne...
971
972
973
974
975
  	return -ENODEV;
  }
  
  static int __init sm_vt8231_init(void)
  {
93b47684f   Richard Knutsson   [PATCH] drivers/*...
976
  	return pci_register_driver(&vt8231_pci_driver);
1de9e371b   Roger Lucas   [PATCH] hwmon: Ne...
977
978
979
980
981
982
  }
  
  static void __exit sm_vt8231_exit(void)
  {
  	pci_unregister_driver(&vt8231_pci_driver);
  	if (s_bridge != NULL) {
ec5e1a4b8   Roger Lucas   hwmon: Convert vt...
983
984
  		platform_device_unregister(pdev);
  		platform_driver_unregister(&vt8231_driver);
1de9e371b   Roger Lucas   [PATCH] hwmon: Ne...
985
986
987
988
  		pci_dev_put(s_bridge);
  		s_bridge = NULL;
  	}
  }
af865765a   Roger Lucas   hwmon: (vt8231) U...
989
  MODULE_AUTHOR("Roger Lucas <vt8231@hiddenengine.co.uk>");
1de9e371b   Roger Lucas   [PATCH] hwmon: Ne...
990
991
992
993
994
  MODULE_DESCRIPTION("VT8231 sensors");
  MODULE_LICENSE("GPL");
  
  module_init(sm_vt8231_init);
  module_exit(sm_vt8231_exit);