blob: 7c2973487122cd139b22081225cbcbefefa28bae [file] [log] [blame]
Jean Delvaree53004e2006-01-09 23:26:14 +01001/*
Jean Delvare51c997d2006-12-12 18:18:29 +01002 * f71805f.c - driver for the Fintek F71805F/FG and F71872F/FG Super-I/O
3 * chips integrated hardware monitoring features
Jean Delvare2d457712006-09-24 20:52:15 +02004 * Copyright (C) 2005-2006 Jean Delvare <khali@linux-fr.org>
Jean Delvaree53004e2006-01-09 23:26:14 +01005 *
6 * The F71805F/FG is a LPC Super-I/O chip made by Fintek. It integrates
7 * complete hardware monitoring features: voltage, fan and temperature
8 * sensors, and manual and automatic fan speed control.
9 *
Jean Delvare51c997d2006-12-12 18:18:29 +010010 * The F71872F/FG is almost the same, with two more voltages monitored,
11 * and 6 VID inputs.
12 *
Jean Delvaree53004e2006-01-09 23:26:14 +010013 * This program is free software; you can redistribute it and/or modify
14 * it under the terms of the GNU General Public License as published by
15 * the Free Software Foundation; either version 2 of the License, or
16 * (at your option) any later version.
17 *
18 * This program is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU General Public License for more details.
22 *
23 * You should have received a copy of the GNU General Public License
24 * along with this program; if not, write to the Free Software
25 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
26 */
27
28#include <linux/module.h>
29#include <linux/init.h>
30#include <linux/slab.h>
31#include <linux/jiffies.h>
32#include <linux/platform_device.h>
33#include <linux/hwmon.h>
34#include <linux/hwmon-sysfs.h>
35#include <linux/err.h>
Jean Delvaref0819182006-01-18 23:20:53 +010036#include <linux/mutex.h>
Jean Delvare0e39e012006-09-24 21:16:40 +020037#include <linux/sysfs.h>
Jean Delvaree53004e2006-01-09 23:26:14 +010038#include <asm/io.h>
39
40static struct platform_device *pdev;
41
42#define DRVNAME "f71805f"
Jean Delvare51c997d2006-12-12 18:18:29 +010043enum kinds { f71805f, f71872f };
Jean Delvaree53004e2006-01-09 23:26:14 +010044
45/*
46 * Super-I/O constants and functions
47 */
48
49#define F71805F_LD_HWM 0x04
50
51#define SIO_REG_LDSEL 0x07 /* Logical device select */
52#define SIO_REG_DEVID 0x20 /* Device ID (2 bytes) */
53#define SIO_REG_DEVREV 0x22 /* Device revision */
54#define SIO_REG_MANID 0x23 /* Fintek ID (2 bytes) */
Jean Delvare51c997d2006-12-12 18:18:29 +010055#define SIO_REG_FNSEL1 0x29 /* Multi Function Select 1 (F71872F) */
Jean Delvaree53004e2006-01-09 23:26:14 +010056#define SIO_REG_ENABLE 0x30 /* Logical device enable */
57#define SIO_REG_ADDR 0x60 /* Logical device address (2 bytes) */
58
59#define SIO_FINTEK_ID 0x1934
60#define SIO_F71805F_ID 0x0406
Jean Delvare51c997d2006-12-12 18:18:29 +010061#define SIO_F71872F_ID 0x0341
Jean Delvaree53004e2006-01-09 23:26:14 +010062
63static inline int
64superio_inb(int base, int reg)
65{
66 outb(reg, base);
67 return inb(base + 1);
68}
69
70static int
71superio_inw(int base, int reg)
72{
73 int val;
74 outb(reg++, base);
75 val = inb(base + 1) << 8;
76 outb(reg, base);
77 val |= inb(base + 1);
78 return val;
79}
80
81static inline void
82superio_select(int base, int ld)
83{
84 outb(SIO_REG_LDSEL, base);
85 outb(ld, base + 1);
86}
87
88static inline void
89superio_enter(int base)
90{
91 outb(0x87, base);
92 outb(0x87, base);
93}
94
95static inline void
96superio_exit(int base)
97{
98 outb(0xaa, base);
99}
100
101/*
102 * ISA constants
103 */
104
Jean Delvare75c99022006-12-12 18:18:29 +0100105#define REGION_LENGTH 8
106#define ADDR_REG_OFFSET 5
107#define DATA_REG_OFFSET 6
Jean Delvaree53004e2006-01-09 23:26:14 +0100108
Jean Delvaree53004e2006-01-09 23:26:14 +0100109/*
110 * Registers
111 */
112
Jean Delvare51c997d2006-12-12 18:18:29 +0100113/* in nr from 0 to 10 (8-bit values) */
Jean Delvaree53004e2006-01-09 23:26:14 +0100114#define F71805F_REG_IN(nr) (0x10 + (nr))
Jean Delvare51c997d2006-12-12 18:18:29 +0100115#define F71805F_REG_IN_HIGH(nr) ((nr) < 10 ? 0x40 + 2 * (nr) : 0x2E)
116#define F71805F_REG_IN_LOW(nr) ((nr) < 10 ? 0x41 + 2 * (nr) : 0x2F)
Jean Delvaree53004e2006-01-09 23:26:14 +0100117/* fan nr from 0 to 2 (12-bit values, two registers) */
118#define F71805F_REG_FAN(nr) (0x20 + 2 * (nr))
119#define F71805F_REG_FAN_LOW(nr) (0x28 + 2 * (nr))
Jean Delvare315c7112006-12-12 18:18:27 +0100120#define F71805F_REG_FAN_TARGET(nr) (0x69 + 16 * (nr))
Jean Delvaree53004e2006-01-09 23:26:14 +0100121#define F71805F_REG_FAN_CTRL(nr) (0x60 + 16 * (nr))
Jean Delvare6e2bc172006-12-12 18:18:27 +0100122#define F71805F_REG_PWM_FREQ(nr) (0x63 + 16 * (nr))
Jean Delvare95e35312006-12-12 18:18:26 +0100123#define F71805F_REG_PWM_DUTY(nr) (0x6B + 16 * (nr))
Jean Delvaree53004e2006-01-09 23:26:14 +0100124/* temp nr from 0 to 2 (8-bit values) */
125#define F71805F_REG_TEMP(nr) (0x1B + (nr))
126#define F71805F_REG_TEMP_HIGH(nr) (0x54 + 2 * (nr))
127#define F71805F_REG_TEMP_HYST(nr) (0x55 + 2 * (nr))
128#define F71805F_REG_TEMP_MODE 0x01
129
130#define F71805F_REG_START 0x00
131/* status nr from 0 to 2 */
132#define F71805F_REG_STATUS(nr) (0x36 + (nr))
133
Jean Delvare6b14a542006-12-12 18:18:26 +0100134/* individual register bits */
Jean Delvaree1967832006-12-12 18:18:27 +0100135#define FAN_CTRL_DC_MODE 0x10
Jean Delvare315c7112006-12-12 18:18:27 +0100136#define FAN_CTRL_LATCH_FULL 0x08
Jean Delvare95e35312006-12-12 18:18:26 +0100137#define FAN_CTRL_MODE_MASK 0x03
138#define FAN_CTRL_MODE_SPEED 0x00
139#define FAN_CTRL_MODE_TEMPERATURE 0x01
140#define FAN_CTRL_MODE_MANUAL 0x02
Jean Delvare6b14a542006-12-12 18:18:26 +0100141
Jean Delvaree53004e2006-01-09 23:26:14 +0100142/*
143 * Data structures and manipulation thereof
144 */
145
146struct f71805f_data {
147 unsigned short addr;
148 const char *name;
Jean Delvaree53004e2006-01-09 23:26:14 +0100149 struct class_device *class_dev;
150
Jean Delvaref0819182006-01-18 23:20:53 +0100151 struct mutex update_lock;
Jean Delvaree53004e2006-01-09 23:26:14 +0100152 char valid; /* !=0 if following fields are valid */
153 unsigned long last_updated; /* In jiffies */
154 unsigned long last_limits; /* In jiffies */
155
156 /* Register values */
Jean Delvare51c997d2006-12-12 18:18:29 +0100157 u8 in[11];
158 u8 in_high[11];
159 u8 in_low[11];
160 u16 has_in;
Jean Delvaree53004e2006-01-09 23:26:14 +0100161 u16 fan[3];
162 u16 fan_low[3];
Jean Delvare315c7112006-12-12 18:18:27 +0100163 u16 fan_target[3];
Jean Delvare6b14a542006-12-12 18:18:26 +0100164 u8 fan_ctrl[3];
Jean Delvare95e35312006-12-12 18:18:26 +0100165 u8 pwm[3];
Jean Delvare6e2bc172006-12-12 18:18:27 +0100166 u8 pwm_freq[3];
Jean Delvaree53004e2006-01-09 23:26:14 +0100167 u8 temp[3];
168 u8 temp_high[3];
169 u8 temp_hyst[3];
170 u8 temp_mode;
Jean Delvare2d457712006-09-24 20:52:15 +0200171 unsigned long alarms;
Jean Delvaree53004e2006-01-09 23:26:14 +0100172};
173
Jean Delvare51c997d2006-12-12 18:18:29 +0100174struct f71805f_sio_data {
175 enum kinds kind;
176 u8 fnsel1;
177};
178
Jean Delvaree53004e2006-01-09 23:26:14 +0100179static inline long in_from_reg(u8 reg)
180{
181 return (reg * 8);
182}
183
184/* The 2 least significant bits are not used */
185static inline u8 in_to_reg(long val)
186{
187 if (val <= 0)
188 return 0;
189 if (val >= 2016)
190 return 0xfc;
191 return (((val + 16) / 32) << 2);
192}
193
194/* in0 is downscaled by a factor 2 internally */
195static inline long in0_from_reg(u8 reg)
196{
197 return (reg * 16);
198}
199
200static inline u8 in0_to_reg(long val)
201{
202 if (val <= 0)
203 return 0;
204 if (val >= 4032)
205 return 0xfc;
206 return (((val + 32) / 64) << 2);
207}
208
209/* The 4 most significant bits are not used */
210static inline long fan_from_reg(u16 reg)
211{
212 reg &= 0xfff;
213 if (!reg || reg == 0xfff)
214 return 0;
215 return (1500000 / reg);
216}
217
218static inline u16 fan_to_reg(long rpm)
219{
220 /* If the low limit is set below what the chip can measure,
221 store the largest possible 12-bit value in the registers,
222 so that no alarm will ever trigger. */
223 if (rpm < 367)
224 return 0xfff;
225 return (1500000 / rpm);
226}
227
Jean Delvare6e2bc172006-12-12 18:18:27 +0100228static inline unsigned long pwm_freq_from_reg(u8 reg)
229{
230 unsigned long clock = (reg & 0x80) ? 48000000UL : 1000000UL;
231
232 reg &= 0x7f;
233 if (reg == 0)
234 reg++;
235 return clock / (reg << 8);
236}
237
238static inline u8 pwm_freq_to_reg(unsigned long val)
239{
240 if (val >= 187500) /* The highest we can do */
241 return 0x80;
242 if (val >= 1475) /* Use 48 MHz clock */
243 return 0x80 | (48000000UL / (val << 8));
244 if (val < 31) /* The lowest we can do */
245 return 0x7f;
246 else /* Use 1 MHz clock */
247 return 1000000UL / (val << 8);
248}
249
Jean Delvaree1967832006-12-12 18:18:27 +0100250static inline int pwm_mode_from_reg(u8 reg)
251{
252 return !(reg & FAN_CTRL_DC_MODE);
253}
254
Jean Delvaree53004e2006-01-09 23:26:14 +0100255static inline long temp_from_reg(u8 reg)
256{
257 return (reg * 1000);
258}
259
260static inline u8 temp_to_reg(long val)
261{
262 if (val < 0)
263 val = 0;
264 else if (val > 1000 * 0xff)
265 val = 0xff;
266 return ((val + 500) / 1000);
267}
268
269/*
270 * Device I/O access
271 */
272
Jean Delvare7f999aa2007-02-14 21:15:03 +0100273/* Must be called with data->update_lock held, except during initialization */
Jean Delvaree53004e2006-01-09 23:26:14 +0100274static u8 f71805f_read8(struct f71805f_data *data, u8 reg)
275{
Jean Delvaree53004e2006-01-09 23:26:14 +0100276 outb(reg, data->addr + ADDR_REG_OFFSET);
Jean Delvare7f999aa2007-02-14 21:15:03 +0100277 return inb(data->addr + DATA_REG_OFFSET);
Jean Delvaree53004e2006-01-09 23:26:14 +0100278}
279
Jean Delvare7f999aa2007-02-14 21:15:03 +0100280/* Must be called with data->update_lock held, except during initialization */
Jean Delvaree53004e2006-01-09 23:26:14 +0100281static void f71805f_write8(struct f71805f_data *data, u8 reg, u8 val)
282{
Jean Delvaree53004e2006-01-09 23:26:14 +0100283 outb(reg, data->addr + ADDR_REG_OFFSET);
284 outb(val, data->addr + DATA_REG_OFFSET);
Jean Delvaree53004e2006-01-09 23:26:14 +0100285}
286
287/* It is important to read the MSB first, because doing so latches the
Jean Delvare7f999aa2007-02-14 21:15:03 +0100288 value of the LSB, so we are sure both bytes belong to the same value.
289 Must be called with data->update_lock held, except during initialization */
Jean Delvaree53004e2006-01-09 23:26:14 +0100290static u16 f71805f_read16(struct f71805f_data *data, u8 reg)
291{
292 u16 val;
293
Jean Delvaree53004e2006-01-09 23:26:14 +0100294 outb(reg, data->addr + ADDR_REG_OFFSET);
295 val = inb(data->addr + DATA_REG_OFFSET) << 8;
296 outb(++reg, data->addr + ADDR_REG_OFFSET);
297 val |= inb(data->addr + DATA_REG_OFFSET);
Jean Delvaree53004e2006-01-09 23:26:14 +0100298
299 return val;
300}
301
Jean Delvare7f999aa2007-02-14 21:15:03 +0100302/* Must be called with data->update_lock held, except during initialization */
Jean Delvaree53004e2006-01-09 23:26:14 +0100303static void f71805f_write16(struct f71805f_data *data, u8 reg, u16 val)
304{
Jean Delvaree53004e2006-01-09 23:26:14 +0100305 outb(reg, data->addr + ADDR_REG_OFFSET);
306 outb(val >> 8, data->addr + DATA_REG_OFFSET);
307 outb(++reg, data->addr + ADDR_REG_OFFSET);
308 outb(val & 0xff, data->addr + DATA_REG_OFFSET);
Jean Delvaree53004e2006-01-09 23:26:14 +0100309}
310
311static struct f71805f_data *f71805f_update_device(struct device *dev)
312{
313 struct f71805f_data *data = dev_get_drvdata(dev);
314 int nr;
315
Jean Delvaref0819182006-01-18 23:20:53 +0100316 mutex_lock(&data->update_lock);
Jean Delvaree53004e2006-01-09 23:26:14 +0100317
318 /* Limit registers cache is refreshed after 60 seconds */
319 if (time_after(jiffies, data->last_updated + 60 * HZ)
320 || !data->valid) {
Jean Delvare51c997d2006-12-12 18:18:29 +0100321 for (nr = 0; nr < 11; nr++) {
322 if (!(data->has_in & (1 << nr)))
323 continue;
Jean Delvaree53004e2006-01-09 23:26:14 +0100324 data->in_high[nr] = f71805f_read8(data,
325 F71805F_REG_IN_HIGH(nr));
326 data->in_low[nr] = f71805f_read8(data,
327 F71805F_REG_IN_LOW(nr));
328 }
329 for (nr = 0; nr < 3; nr++) {
Jean Delvare6b14a542006-12-12 18:18:26 +0100330 data->fan_low[nr] = f71805f_read16(data,
331 F71805F_REG_FAN_LOW(nr));
Jean Delvare315c7112006-12-12 18:18:27 +0100332 data->fan_target[nr] = f71805f_read16(data,
333 F71805F_REG_FAN_TARGET(nr));
Jean Delvare6e2bc172006-12-12 18:18:27 +0100334 data->pwm_freq[nr] = f71805f_read8(data,
335 F71805F_REG_PWM_FREQ(nr));
Jean Delvaree53004e2006-01-09 23:26:14 +0100336 }
337 for (nr = 0; nr < 3; nr++) {
338 data->temp_high[nr] = f71805f_read8(data,
339 F71805F_REG_TEMP_HIGH(nr));
340 data->temp_hyst[nr] = f71805f_read8(data,
341 F71805F_REG_TEMP_HYST(nr));
342 }
343 data->temp_mode = f71805f_read8(data, F71805F_REG_TEMP_MODE);
344
345 data->last_limits = jiffies;
346 }
347
348 /* Measurement registers cache is refreshed after 1 second */
349 if (time_after(jiffies, data->last_updated + HZ)
350 || !data->valid) {
Jean Delvare51c997d2006-12-12 18:18:29 +0100351 for (nr = 0; nr < 11; nr++) {
352 if (!(data->has_in & (1 << nr)))
353 continue;
Jean Delvaree53004e2006-01-09 23:26:14 +0100354 data->in[nr] = f71805f_read8(data,
355 F71805F_REG_IN(nr));
356 }
357 for (nr = 0; nr < 3; nr++) {
Jean Delvare6b14a542006-12-12 18:18:26 +0100358 data->fan[nr] = f71805f_read16(data,
359 F71805F_REG_FAN(nr));
Jean Delvare95e35312006-12-12 18:18:26 +0100360 data->fan_ctrl[nr] = f71805f_read8(data,
361 F71805F_REG_FAN_CTRL(nr));
362 data->pwm[nr] = f71805f_read8(data,
363 F71805F_REG_PWM_DUTY(nr));
Jean Delvaree53004e2006-01-09 23:26:14 +0100364 }
365 for (nr = 0; nr < 3; nr++) {
366 data->temp[nr] = f71805f_read8(data,
367 F71805F_REG_TEMP(nr));
368 }
Jean Delvare2d457712006-09-24 20:52:15 +0200369 data->alarms = f71805f_read8(data, F71805F_REG_STATUS(0))
370 + (f71805f_read8(data, F71805F_REG_STATUS(1)) << 8)
371 + (f71805f_read8(data, F71805F_REG_STATUS(2)) << 16);
Jean Delvaree53004e2006-01-09 23:26:14 +0100372
373 data->last_updated = jiffies;
374 data->valid = 1;
375 }
376
Jean Delvaref0819182006-01-18 23:20:53 +0100377 mutex_unlock(&data->update_lock);
Jean Delvaree53004e2006-01-09 23:26:14 +0100378
379 return data;
380}
381
382/*
383 * Sysfs interface
384 */
385
386static ssize_t show_in0(struct device *dev, struct device_attribute *devattr,
387 char *buf)
388{
389 struct f71805f_data *data = f71805f_update_device(dev);
Jean Delvare51c997d2006-12-12 18:18:29 +0100390 struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
391 int nr = attr->index;
Jean Delvaree53004e2006-01-09 23:26:14 +0100392
Jean Delvare51c997d2006-12-12 18:18:29 +0100393 return sprintf(buf, "%ld\n", in0_from_reg(data->in[nr]));
Jean Delvaree53004e2006-01-09 23:26:14 +0100394}
395
396static ssize_t show_in0_max(struct device *dev, struct device_attribute
397 *devattr, char *buf)
398{
399 struct f71805f_data *data = f71805f_update_device(dev);
Jean Delvare51c997d2006-12-12 18:18:29 +0100400 struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
401 int nr = attr->index;
Jean Delvaree53004e2006-01-09 23:26:14 +0100402
Jean Delvare51c997d2006-12-12 18:18:29 +0100403 return sprintf(buf, "%ld\n", in0_from_reg(data->in_high[nr]));
Jean Delvaree53004e2006-01-09 23:26:14 +0100404}
405
406static ssize_t show_in0_min(struct device *dev, struct device_attribute
407 *devattr, char *buf)
408{
409 struct f71805f_data *data = f71805f_update_device(dev);
Jean Delvare51c997d2006-12-12 18:18:29 +0100410 struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
411 int nr = attr->index;
Jean Delvaree53004e2006-01-09 23:26:14 +0100412
Jean Delvare51c997d2006-12-12 18:18:29 +0100413 return sprintf(buf, "%ld\n", in0_from_reg(data->in_low[nr]));
Jean Delvaree53004e2006-01-09 23:26:14 +0100414}
415
416static ssize_t set_in0_max(struct device *dev, struct device_attribute
417 *devattr, const char *buf, size_t count)
418{
419 struct f71805f_data *data = dev_get_drvdata(dev);
Jean Delvare51c997d2006-12-12 18:18:29 +0100420 struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
421 int nr = attr->index;
Jean Delvaree53004e2006-01-09 23:26:14 +0100422 long val = simple_strtol(buf, NULL, 10);
423
Jean Delvaref0819182006-01-18 23:20:53 +0100424 mutex_lock(&data->update_lock);
Jean Delvare51c997d2006-12-12 18:18:29 +0100425 data->in_high[nr] = in0_to_reg(val);
426 f71805f_write8(data, F71805F_REG_IN_HIGH(nr), data->in_high[nr]);
Jean Delvaref0819182006-01-18 23:20:53 +0100427 mutex_unlock(&data->update_lock);
Jean Delvaree53004e2006-01-09 23:26:14 +0100428
429 return count;
430}
431
432static ssize_t set_in0_min(struct device *dev, struct device_attribute
433 *devattr, const char *buf, size_t count)
434{
435 struct f71805f_data *data = dev_get_drvdata(dev);
Jean Delvare51c997d2006-12-12 18:18:29 +0100436 struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
437 int nr = attr->index;
Jean Delvaree53004e2006-01-09 23:26:14 +0100438 long val = simple_strtol(buf, NULL, 10);
439
Jean Delvaref0819182006-01-18 23:20:53 +0100440 mutex_lock(&data->update_lock);
Jean Delvare51c997d2006-12-12 18:18:29 +0100441 data->in_low[nr] = in0_to_reg(val);
442 f71805f_write8(data, F71805F_REG_IN_LOW(nr), data->in_low[nr]);
Jean Delvaref0819182006-01-18 23:20:53 +0100443 mutex_unlock(&data->update_lock);
Jean Delvaree53004e2006-01-09 23:26:14 +0100444
445 return count;
446}
447
Jean Delvaree53004e2006-01-09 23:26:14 +0100448static ssize_t show_in(struct device *dev, struct device_attribute *devattr,
449 char *buf)
450{
451 struct f71805f_data *data = f71805f_update_device(dev);
452 struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
453 int nr = attr->index;
454
455 return sprintf(buf, "%ld\n", in_from_reg(data->in[nr]));
456}
457
458static ssize_t show_in_max(struct device *dev, struct device_attribute
459 *devattr, char *buf)
460{
461 struct f71805f_data *data = f71805f_update_device(dev);
462 struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
463 int nr = attr->index;
464
465 return sprintf(buf, "%ld\n", in_from_reg(data->in_high[nr]));
466}
467
468static ssize_t show_in_min(struct device *dev, struct device_attribute
469 *devattr, char *buf)
470{
471 struct f71805f_data *data = f71805f_update_device(dev);
472 struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
473 int nr = attr->index;
474
475 return sprintf(buf, "%ld\n", in_from_reg(data->in_low[nr]));
476}
477
478static ssize_t set_in_max(struct device *dev, struct device_attribute
479 *devattr, const char *buf, size_t count)
480{
481 struct f71805f_data *data = dev_get_drvdata(dev);
482 struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
483 int nr = attr->index;
484 long val = simple_strtol(buf, NULL, 10);
485
Jean Delvaref0819182006-01-18 23:20:53 +0100486 mutex_lock(&data->update_lock);
Jean Delvaree53004e2006-01-09 23:26:14 +0100487 data->in_high[nr] = in_to_reg(val);
488 f71805f_write8(data, F71805F_REG_IN_HIGH(nr), data->in_high[nr]);
Jean Delvaref0819182006-01-18 23:20:53 +0100489 mutex_unlock(&data->update_lock);
Jean Delvaree53004e2006-01-09 23:26:14 +0100490
491 return count;
492}
493
494static ssize_t set_in_min(struct device *dev, struct device_attribute
495 *devattr, const char *buf, size_t count)
496{
497 struct f71805f_data *data = dev_get_drvdata(dev);
498 struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
499 int nr = attr->index;
500 long val = simple_strtol(buf, NULL, 10);
501
Jean Delvaref0819182006-01-18 23:20:53 +0100502 mutex_lock(&data->update_lock);
Jean Delvaree53004e2006-01-09 23:26:14 +0100503 data->in_low[nr] = in_to_reg(val);
504 f71805f_write8(data, F71805F_REG_IN_LOW(nr), data->in_low[nr]);
Jean Delvaref0819182006-01-18 23:20:53 +0100505 mutex_unlock(&data->update_lock);
Jean Delvaree53004e2006-01-09 23:26:14 +0100506
507 return count;
508}
509
Jean Delvaree53004e2006-01-09 23:26:14 +0100510static ssize_t show_fan(struct device *dev, struct device_attribute *devattr,
511 char *buf)
512{
513 struct f71805f_data *data = f71805f_update_device(dev);
514 struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
515 int nr = attr->index;
516
517 return sprintf(buf, "%ld\n", fan_from_reg(data->fan[nr]));
518}
519
520static ssize_t show_fan_min(struct device *dev, struct device_attribute
521 *devattr, char *buf)
522{
523 struct f71805f_data *data = f71805f_update_device(dev);
524 struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
525 int nr = attr->index;
526
527 return sprintf(buf, "%ld\n", fan_from_reg(data->fan_low[nr]));
528}
529
Jean Delvare315c7112006-12-12 18:18:27 +0100530static ssize_t show_fan_target(struct device *dev, struct device_attribute
531 *devattr, char *buf)
532{
533 struct f71805f_data *data = f71805f_update_device(dev);
534 struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
535 int nr = attr->index;
536
537 return sprintf(buf, "%ld\n", fan_from_reg(data->fan_target[nr]));
538}
539
Jean Delvaree53004e2006-01-09 23:26:14 +0100540static ssize_t set_fan_min(struct device *dev, struct device_attribute
541 *devattr, const char *buf, size_t count)
542{
543 struct f71805f_data *data = dev_get_drvdata(dev);
544 struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
545 int nr = attr->index;
546 long val = simple_strtol(buf, NULL, 10);
547
Jean Delvaref0819182006-01-18 23:20:53 +0100548 mutex_lock(&data->update_lock);
Jean Delvaree53004e2006-01-09 23:26:14 +0100549 data->fan_low[nr] = fan_to_reg(val);
550 f71805f_write16(data, F71805F_REG_FAN_LOW(nr), data->fan_low[nr]);
Jean Delvaref0819182006-01-18 23:20:53 +0100551 mutex_unlock(&data->update_lock);
Jean Delvaree53004e2006-01-09 23:26:14 +0100552
553 return count;
554}
555
Jean Delvare315c7112006-12-12 18:18:27 +0100556static ssize_t set_fan_target(struct device *dev, struct device_attribute
557 *devattr, const char *buf, size_t count)
558{
559 struct f71805f_data *data = dev_get_drvdata(dev);
560 struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
561 int nr = attr->index;
562 long val = simple_strtol(buf, NULL, 10);
563
564 mutex_lock(&data->update_lock);
565 data->fan_target[nr] = fan_to_reg(val);
566 f71805f_write16(data, F71805F_REG_FAN_TARGET(nr),
567 data->fan_target[nr]);
568 mutex_unlock(&data->update_lock);
569
570 return count;
571}
572
Jean Delvare95e35312006-12-12 18:18:26 +0100573static ssize_t show_pwm(struct device *dev, struct device_attribute *devattr,
574 char *buf)
575{
576 struct f71805f_data *data = f71805f_update_device(dev);
577 struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
578 int nr = attr->index;
579
580 return sprintf(buf, "%d\n", (int)data->pwm[nr]);
581}
582
583static ssize_t show_pwm_enable(struct device *dev, struct device_attribute
584 *devattr, char *buf)
585{
586 struct f71805f_data *data = f71805f_update_device(dev);
587 struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
588 int nr = attr->index;
589 int mode;
590
591 switch (data->fan_ctrl[nr] & FAN_CTRL_MODE_MASK) {
592 case FAN_CTRL_MODE_SPEED:
593 mode = 3;
594 break;
595 case FAN_CTRL_MODE_TEMPERATURE:
596 mode = 2;
597 break;
598 default: /* MANUAL */
599 mode = 1;
600 }
601
602 return sprintf(buf, "%d\n", mode);
603}
604
Jean Delvare6e2bc172006-12-12 18:18:27 +0100605static ssize_t show_pwm_freq(struct device *dev, struct device_attribute
606 *devattr, char *buf)
607{
608 struct f71805f_data *data = f71805f_update_device(dev);
609 struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
610 int nr = attr->index;
611
612 return sprintf(buf, "%lu\n", pwm_freq_from_reg(data->pwm_freq[nr]));
613}
614
Jean Delvaree1967832006-12-12 18:18:27 +0100615static ssize_t show_pwm_mode(struct device *dev, struct device_attribute
616 *devattr, char *buf)
617{
618 struct f71805f_data *data = f71805f_update_device(dev);
619 struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
620 int nr = attr->index;
621
622 return sprintf(buf, "%d\n", pwm_mode_from_reg(data->fan_ctrl[nr]));
623}
624
Jean Delvare95e35312006-12-12 18:18:26 +0100625static ssize_t set_pwm(struct device *dev, struct device_attribute *devattr,
626 const char *buf, size_t count)
627{
628 struct f71805f_data *data = dev_get_drvdata(dev);
629 struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
630 int nr = attr->index;
631 unsigned long val = simple_strtoul(buf, NULL, 10);
632
633 if (val > 255)
634 return -EINVAL;
635
636 mutex_lock(&data->update_lock);
637 data->pwm[nr] = val;
638 f71805f_write8(data, F71805F_REG_PWM_DUTY(nr), data->pwm[nr]);
639 mutex_unlock(&data->update_lock);
640
641 return count;
642}
643
644static struct attribute *f71805f_attr_pwm[];
645
646static ssize_t set_pwm_enable(struct device *dev, struct device_attribute
647 *devattr, const char *buf, size_t count)
648{
649 struct f71805f_data *data = dev_get_drvdata(dev);
650 struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
651 int nr = attr->index;
652 unsigned long val = simple_strtoul(buf, NULL, 10);
653 u8 reg;
654
655 if (val < 1 || val > 3)
656 return -EINVAL;
657
658 if (val > 1) { /* Automatic mode, user can't set PWM value */
659 if (sysfs_chmod_file(&dev->kobj, f71805f_attr_pwm[nr],
660 S_IRUGO))
661 dev_dbg(dev, "chmod -w pwm%d failed\n", nr + 1);
662 }
663
664 mutex_lock(&data->update_lock);
665 reg = f71805f_read8(data, F71805F_REG_FAN_CTRL(nr))
666 & ~FAN_CTRL_MODE_MASK;
667 switch (val) {
668 case 1:
669 reg |= FAN_CTRL_MODE_MANUAL;
670 break;
671 case 2:
672 reg |= FAN_CTRL_MODE_TEMPERATURE;
673 break;
674 case 3:
675 reg |= FAN_CTRL_MODE_SPEED;
676 break;
677 }
678 data->fan_ctrl[nr] = reg;
679 f71805f_write8(data, F71805F_REG_FAN_CTRL(nr), reg);
680 mutex_unlock(&data->update_lock);
681
682 if (val == 1) { /* Manual mode, user can set PWM value */
683 if (sysfs_chmod_file(&dev->kobj, f71805f_attr_pwm[nr],
684 S_IRUGO | S_IWUSR))
685 dev_dbg(dev, "chmod +w pwm%d failed\n", nr + 1);
686 }
687
688 return count;
689}
690
Jean Delvare6e2bc172006-12-12 18:18:27 +0100691static ssize_t set_pwm_freq(struct device *dev, struct device_attribute
692 *devattr, const char *buf, size_t count)
693{
694 struct f71805f_data *data = dev_get_drvdata(dev);
695 struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
696 int nr = attr->index;
697 unsigned long val = simple_strtoul(buf, NULL, 10);
698
699 mutex_lock(&data->update_lock);
700 data->pwm_freq[nr] = pwm_freq_to_reg(val);
701 f71805f_write8(data, F71805F_REG_PWM_FREQ(nr), data->pwm_freq[nr]);
702 mutex_unlock(&data->update_lock);
703
704 return count;
705}
706
Jean Delvaree53004e2006-01-09 23:26:14 +0100707static ssize_t show_temp(struct device *dev, struct device_attribute *devattr,
708 char *buf)
709{
710 struct f71805f_data *data = f71805f_update_device(dev);
711 struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
712 int nr = attr->index;
713
714 return sprintf(buf, "%ld\n", temp_from_reg(data->temp[nr]));
715}
716
717static ssize_t show_temp_max(struct device *dev, struct device_attribute
718 *devattr, char *buf)
719{
720 struct f71805f_data *data = f71805f_update_device(dev);
721 struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
722 int nr = attr->index;
723
724 return sprintf(buf, "%ld\n", temp_from_reg(data->temp_high[nr]));
725}
726
727static ssize_t show_temp_hyst(struct device *dev, struct device_attribute
728 *devattr, char *buf)
729{
730 struct f71805f_data *data = f71805f_update_device(dev);
731 struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
732 int nr = attr->index;
733
734 return sprintf(buf, "%ld\n", temp_from_reg(data->temp_hyst[nr]));
735}
736
737static ssize_t show_temp_type(struct device *dev, struct device_attribute
738 *devattr, char *buf)
739{
740 struct f71805f_data *data = f71805f_update_device(dev);
741 struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
742 int nr = attr->index;
743
744 /* 3 is diode, 4 is thermistor */
745 return sprintf(buf, "%u\n", (data->temp_mode & (1 << nr)) ? 3 : 4);
746}
747
748static ssize_t set_temp_max(struct device *dev, struct device_attribute
749 *devattr, const char *buf, size_t count)
750{
751 struct f71805f_data *data = dev_get_drvdata(dev);
752 struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
753 int nr = attr->index;
754 long val = simple_strtol(buf, NULL, 10);
755
Jean Delvaref0819182006-01-18 23:20:53 +0100756 mutex_lock(&data->update_lock);
Jean Delvaree53004e2006-01-09 23:26:14 +0100757 data->temp_high[nr] = temp_to_reg(val);
758 f71805f_write8(data, F71805F_REG_TEMP_HIGH(nr), data->temp_high[nr]);
Jean Delvaref0819182006-01-18 23:20:53 +0100759 mutex_unlock(&data->update_lock);
Jean Delvaree53004e2006-01-09 23:26:14 +0100760
761 return count;
762}
763
764static ssize_t set_temp_hyst(struct device *dev, struct device_attribute
765 *devattr, const char *buf, size_t count)
766{
767 struct f71805f_data *data = dev_get_drvdata(dev);
768 struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
769 int nr = attr->index;
770 long val = simple_strtol(buf, NULL, 10);
771
Jean Delvaref0819182006-01-18 23:20:53 +0100772 mutex_lock(&data->update_lock);
Jean Delvaree53004e2006-01-09 23:26:14 +0100773 data->temp_hyst[nr] = temp_to_reg(val);
774 f71805f_write8(data, F71805F_REG_TEMP_HYST(nr), data->temp_hyst[nr]);
Jean Delvaref0819182006-01-18 23:20:53 +0100775 mutex_unlock(&data->update_lock);
Jean Delvaree53004e2006-01-09 23:26:14 +0100776
777 return count;
778}
779
Jean Delvaree53004e2006-01-09 23:26:14 +0100780static ssize_t show_alarms_in(struct device *dev, struct device_attribute
781 *devattr, char *buf)
782{
783 struct f71805f_data *data = f71805f_update_device(dev);
784
Jean Delvare51c997d2006-12-12 18:18:29 +0100785 return sprintf(buf, "%lu\n", data->alarms & 0x7ff);
Jean Delvaree53004e2006-01-09 23:26:14 +0100786}
787
788static ssize_t show_alarms_fan(struct device *dev, struct device_attribute
789 *devattr, char *buf)
790{
791 struct f71805f_data *data = f71805f_update_device(dev);
792
Jean Delvare2d457712006-09-24 20:52:15 +0200793 return sprintf(buf, "%lu\n", (data->alarms >> 16) & 0x07);
Jean Delvaree53004e2006-01-09 23:26:14 +0100794}
795
796static ssize_t show_alarms_temp(struct device *dev, struct device_attribute
797 *devattr, char *buf)
798{
799 struct f71805f_data *data = f71805f_update_device(dev);
800
Jean Delvare2d457712006-09-24 20:52:15 +0200801 return sprintf(buf, "%lu\n", (data->alarms >> 11) & 0x07);
802}
803
804static ssize_t show_alarm(struct device *dev, struct device_attribute
805 *devattr, char *buf)
806{
807 struct f71805f_data *data = f71805f_update_device(dev);
808 struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
809 int bitnr = attr->index;
810
811 return sprintf(buf, "%lu\n", (data->alarms >> bitnr) & 1);
Jean Delvaree53004e2006-01-09 23:26:14 +0100812}
813
Jean Delvaree53004e2006-01-09 23:26:14 +0100814static ssize_t show_name(struct device *dev, struct device_attribute
815 *devattr, char *buf)
816{
817 struct f71805f_data *data = dev_get_drvdata(dev);
818
819 return sprintf(buf, "%s\n", data->name);
820}
821
Jean Delvare51c997d2006-12-12 18:18:29 +0100822static SENSOR_DEVICE_ATTR(in0_input, S_IRUGO, show_in0, NULL, 0);
823static SENSOR_DEVICE_ATTR(in0_max, S_IRUGO| S_IWUSR,
824 show_in0_max, set_in0_max, 0);
825static SENSOR_DEVICE_ATTR(in0_min, S_IRUGO| S_IWUSR,
826 show_in0_min, set_in0_min, 0);
Jean Delvare0e39e012006-09-24 21:16:40 +0200827static SENSOR_DEVICE_ATTR(in1_input, S_IRUGO, show_in, NULL, 1);
828static SENSOR_DEVICE_ATTR(in1_max, S_IRUGO | S_IWUSR,
829 show_in_max, set_in_max, 1);
830static SENSOR_DEVICE_ATTR(in1_min, S_IRUGO | S_IWUSR,
831 show_in_min, set_in_min, 1);
832static SENSOR_DEVICE_ATTR(in2_input, S_IRUGO, show_in, NULL, 2);
833static SENSOR_DEVICE_ATTR(in2_max, S_IRUGO | S_IWUSR,
834 show_in_max, set_in_max, 2);
835static SENSOR_DEVICE_ATTR(in2_min, S_IRUGO | S_IWUSR,
836 show_in_min, set_in_min, 2);
837static SENSOR_DEVICE_ATTR(in3_input, S_IRUGO, show_in, NULL, 3);
838static SENSOR_DEVICE_ATTR(in3_max, S_IRUGO | S_IWUSR,
839 show_in_max, set_in_max, 3);
840static SENSOR_DEVICE_ATTR(in3_min, S_IRUGO | S_IWUSR,
841 show_in_min, set_in_min, 3);
842static SENSOR_DEVICE_ATTR(in4_input, S_IRUGO, show_in, NULL, 4);
843static SENSOR_DEVICE_ATTR(in4_max, S_IRUGO | S_IWUSR,
844 show_in_max, set_in_max, 4);
845static SENSOR_DEVICE_ATTR(in4_min, S_IRUGO | S_IWUSR,
846 show_in_min, set_in_min, 4);
847static SENSOR_DEVICE_ATTR(in5_input, S_IRUGO, show_in, NULL, 5);
848static SENSOR_DEVICE_ATTR(in5_max, S_IRUGO | S_IWUSR,
849 show_in_max, set_in_max, 5);
850static SENSOR_DEVICE_ATTR(in5_min, S_IRUGO | S_IWUSR,
851 show_in_min, set_in_min, 5);
852static SENSOR_DEVICE_ATTR(in6_input, S_IRUGO, show_in, NULL, 6);
853static SENSOR_DEVICE_ATTR(in6_max, S_IRUGO | S_IWUSR,
854 show_in_max, set_in_max, 6);
855static SENSOR_DEVICE_ATTR(in6_min, S_IRUGO | S_IWUSR,
856 show_in_min, set_in_min, 6);
857static SENSOR_DEVICE_ATTR(in7_input, S_IRUGO, show_in, NULL, 7);
858static SENSOR_DEVICE_ATTR(in7_max, S_IRUGO | S_IWUSR,
859 show_in_max, set_in_max, 7);
860static SENSOR_DEVICE_ATTR(in7_min, S_IRUGO | S_IWUSR,
861 show_in_min, set_in_min, 7);
862static SENSOR_DEVICE_ATTR(in8_input, S_IRUGO, show_in, NULL, 8);
863static SENSOR_DEVICE_ATTR(in8_max, S_IRUGO | S_IWUSR,
864 show_in_max, set_in_max, 8);
865static SENSOR_DEVICE_ATTR(in8_min, S_IRUGO | S_IWUSR,
866 show_in_min, set_in_min, 8);
Jean Delvare51c997d2006-12-12 18:18:29 +0100867static SENSOR_DEVICE_ATTR(in9_input, S_IRUGO, show_in0, NULL, 9);
868static SENSOR_DEVICE_ATTR(in9_max, S_IRUGO | S_IWUSR,
869 show_in0_max, set_in0_max, 9);
870static SENSOR_DEVICE_ATTR(in9_min, S_IRUGO | S_IWUSR,
871 show_in0_min, set_in0_min, 9);
872static SENSOR_DEVICE_ATTR(in10_input, S_IRUGO, show_in0, NULL, 10);
873static SENSOR_DEVICE_ATTR(in10_max, S_IRUGO | S_IWUSR,
874 show_in0_max, set_in0_max, 10);
875static SENSOR_DEVICE_ATTR(in10_min, S_IRUGO | S_IWUSR,
876 show_in0_min, set_in0_min, 10);
Jean Delvare0e39e012006-09-24 21:16:40 +0200877
878static SENSOR_DEVICE_ATTR(fan1_input, S_IRUGO, show_fan, NULL, 0);
879static SENSOR_DEVICE_ATTR(fan1_min, S_IRUGO | S_IWUSR,
880 show_fan_min, set_fan_min, 0);
Jean Delvare315c7112006-12-12 18:18:27 +0100881static SENSOR_DEVICE_ATTR(fan1_target, S_IRUGO | S_IWUSR,
882 show_fan_target, set_fan_target, 0);
Jean Delvare0e39e012006-09-24 21:16:40 +0200883static SENSOR_DEVICE_ATTR(fan2_input, S_IRUGO, show_fan, NULL, 1);
884static SENSOR_DEVICE_ATTR(fan2_min, S_IRUGO | S_IWUSR,
885 show_fan_min, set_fan_min, 1);
Jean Delvare315c7112006-12-12 18:18:27 +0100886static SENSOR_DEVICE_ATTR(fan2_target, S_IRUGO | S_IWUSR,
887 show_fan_target, set_fan_target, 1);
Jean Delvare0e39e012006-09-24 21:16:40 +0200888static SENSOR_DEVICE_ATTR(fan3_input, S_IRUGO, show_fan, NULL, 2);
889static SENSOR_DEVICE_ATTR(fan3_min, S_IRUGO | S_IWUSR,
890 show_fan_min, set_fan_min, 2);
Jean Delvare315c7112006-12-12 18:18:27 +0100891static SENSOR_DEVICE_ATTR(fan3_target, S_IRUGO | S_IWUSR,
892 show_fan_target, set_fan_target, 2);
Jean Delvare0e39e012006-09-24 21:16:40 +0200893
894static SENSOR_DEVICE_ATTR(temp1_input, S_IRUGO, show_temp, NULL, 0);
895static SENSOR_DEVICE_ATTR(temp1_max, S_IRUGO | S_IWUSR,
896 show_temp_max, set_temp_max, 0);
897static SENSOR_DEVICE_ATTR(temp1_max_hyst, S_IRUGO | S_IWUSR,
898 show_temp_hyst, set_temp_hyst, 0);
899static SENSOR_DEVICE_ATTR(temp1_type, S_IRUGO, show_temp_type, NULL, 0);
900static SENSOR_DEVICE_ATTR(temp2_input, S_IRUGO, show_temp, NULL, 1);
901static SENSOR_DEVICE_ATTR(temp2_max, S_IRUGO | S_IWUSR,
902 show_temp_max, set_temp_max, 1);
903static SENSOR_DEVICE_ATTR(temp2_max_hyst, S_IRUGO | S_IWUSR,
904 show_temp_hyst, set_temp_hyst, 1);
905static SENSOR_DEVICE_ATTR(temp2_type, S_IRUGO, show_temp_type, NULL, 1);
906static SENSOR_DEVICE_ATTR(temp3_input, S_IRUGO, show_temp, NULL, 2);
907static SENSOR_DEVICE_ATTR(temp3_max, S_IRUGO | S_IWUSR,
908 show_temp_max, set_temp_max, 2);
909static SENSOR_DEVICE_ATTR(temp3_max_hyst, S_IRUGO | S_IWUSR,
910 show_temp_hyst, set_temp_hyst, 2);
911static SENSOR_DEVICE_ATTR(temp3_type, S_IRUGO, show_temp_type, NULL, 2);
912
Jean Delvare95e35312006-12-12 18:18:26 +0100913/* pwm (value) files are created read-only, write permission is
914 then added or removed dynamically as needed */
915static SENSOR_DEVICE_ATTR(pwm1, S_IRUGO, show_pwm, set_pwm, 0);
916static SENSOR_DEVICE_ATTR(pwm1_enable, S_IRUGO | S_IWUSR,
917 show_pwm_enable, set_pwm_enable, 0);
Jean Delvare6e2bc172006-12-12 18:18:27 +0100918static SENSOR_DEVICE_ATTR(pwm1_freq, S_IRUGO | S_IWUSR,
919 show_pwm_freq, set_pwm_freq, 0);
Jean Delvaree1967832006-12-12 18:18:27 +0100920static SENSOR_DEVICE_ATTR(pwm1_mode, S_IRUGO, show_pwm_mode, NULL, 0);
Jean Delvare95e35312006-12-12 18:18:26 +0100921static SENSOR_DEVICE_ATTR(pwm2, S_IRUGO, show_pwm, set_pwm, 1);
922static SENSOR_DEVICE_ATTR(pwm2_enable, S_IRUGO | S_IWUSR,
923 show_pwm_enable, set_pwm_enable, 1);
Jean Delvare6e2bc172006-12-12 18:18:27 +0100924static SENSOR_DEVICE_ATTR(pwm2_freq, S_IRUGO | S_IWUSR,
925 show_pwm_freq, set_pwm_freq, 1);
Jean Delvaree1967832006-12-12 18:18:27 +0100926static SENSOR_DEVICE_ATTR(pwm2_mode, S_IRUGO, show_pwm_mode, NULL, 1);
Jean Delvare95e35312006-12-12 18:18:26 +0100927static SENSOR_DEVICE_ATTR(pwm3, S_IRUGO, show_pwm, set_pwm, 2);
928static SENSOR_DEVICE_ATTR(pwm3_enable, S_IRUGO | S_IWUSR,
929 show_pwm_enable, set_pwm_enable, 2);
Jean Delvare6e2bc172006-12-12 18:18:27 +0100930static SENSOR_DEVICE_ATTR(pwm3_freq, S_IRUGO | S_IWUSR,
931 show_pwm_freq, set_pwm_freq, 2);
Jean Delvaree1967832006-12-12 18:18:27 +0100932static SENSOR_DEVICE_ATTR(pwm3_mode, S_IRUGO, show_pwm_mode, NULL, 2);
Jean Delvare95e35312006-12-12 18:18:26 +0100933
Jean Delvare0e39e012006-09-24 21:16:40 +0200934static SENSOR_DEVICE_ATTR(in0_alarm, S_IRUGO, show_alarm, NULL, 0);
935static SENSOR_DEVICE_ATTR(in1_alarm, S_IRUGO, show_alarm, NULL, 1);
936static SENSOR_DEVICE_ATTR(in2_alarm, S_IRUGO, show_alarm, NULL, 2);
937static SENSOR_DEVICE_ATTR(in3_alarm, S_IRUGO, show_alarm, NULL, 3);
938static SENSOR_DEVICE_ATTR(in4_alarm, S_IRUGO, show_alarm, NULL, 4);
939static SENSOR_DEVICE_ATTR(in5_alarm, S_IRUGO, show_alarm, NULL, 5);
940static SENSOR_DEVICE_ATTR(in6_alarm, S_IRUGO, show_alarm, NULL, 6);
941static SENSOR_DEVICE_ATTR(in7_alarm, S_IRUGO, show_alarm, NULL, 7);
942static SENSOR_DEVICE_ATTR(in8_alarm, S_IRUGO, show_alarm, NULL, 8);
Jean Delvare51c997d2006-12-12 18:18:29 +0100943static SENSOR_DEVICE_ATTR(in9_alarm, S_IRUGO, show_alarm, NULL, 9);
944static SENSOR_DEVICE_ATTR(in10_alarm, S_IRUGO, show_alarm, NULL, 10);
Jean Delvare0e39e012006-09-24 21:16:40 +0200945static SENSOR_DEVICE_ATTR(temp1_alarm, S_IRUGO, show_alarm, NULL, 11);
946static SENSOR_DEVICE_ATTR(temp2_alarm, S_IRUGO, show_alarm, NULL, 12);
947static SENSOR_DEVICE_ATTR(temp3_alarm, S_IRUGO, show_alarm, NULL, 13);
948static SENSOR_DEVICE_ATTR(fan1_alarm, S_IRUGO, show_alarm, NULL, 16);
949static SENSOR_DEVICE_ATTR(fan2_alarm, S_IRUGO, show_alarm, NULL, 17);
950static SENSOR_DEVICE_ATTR(fan3_alarm, S_IRUGO, show_alarm, NULL, 18);
951static DEVICE_ATTR(alarms_in, S_IRUGO, show_alarms_in, NULL);
952static DEVICE_ATTR(alarms_fan, S_IRUGO, show_alarms_fan, NULL);
953static DEVICE_ATTR(alarms_temp, S_IRUGO, show_alarms_temp, NULL);
954
955static DEVICE_ATTR(name, S_IRUGO, show_name, NULL);
956
957static struct attribute *f71805f_attributes[] = {
Jean Delvare51c997d2006-12-12 18:18:29 +0100958 &sensor_dev_attr_in0_input.dev_attr.attr,
959 &sensor_dev_attr_in0_max.dev_attr.attr,
960 &sensor_dev_attr_in0_min.dev_attr.attr,
Jean Delvare0e39e012006-09-24 21:16:40 +0200961 &sensor_dev_attr_in1_input.dev_attr.attr,
962 &sensor_dev_attr_in1_max.dev_attr.attr,
963 &sensor_dev_attr_in1_min.dev_attr.attr,
964 &sensor_dev_attr_in2_input.dev_attr.attr,
965 &sensor_dev_attr_in2_max.dev_attr.attr,
966 &sensor_dev_attr_in2_min.dev_attr.attr,
967 &sensor_dev_attr_in3_input.dev_attr.attr,
968 &sensor_dev_attr_in3_max.dev_attr.attr,
969 &sensor_dev_attr_in3_min.dev_attr.attr,
Jean Delvare0e39e012006-09-24 21:16:40 +0200970 &sensor_dev_attr_in5_input.dev_attr.attr,
971 &sensor_dev_attr_in5_max.dev_attr.attr,
972 &sensor_dev_attr_in5_min.dev_attr.attr,
973 &sensor_dev_attr_in6_input.dev_attr.attr,
974 &sensor_dev_attr_in6_max.dev_attr.attr,
975 &sensor_dev_attr_in6_min.dev_attr.attr,
976 &sensor_dev_attr_in7_input.dev_attr.attr,
977 &sensor_dev_attr_in7_max.dev_attr.attr,
978 &sensor_dev_attr_in7_min.dev_attr.attr,
Jean Delvare0e39e012006-09-24 21:16:40 +0200979
Jean Delvarec7176cb2006-12-12 18:18:29 +0100980 &sensor_dev_attr_fan1_input.dev_attr.attr,
981 &sensor_dev_attr_fan1_min.dev_attr.attr,
982 &sensor_dev_attr_fan1_alarm.dev_attr.attr,
983 &sensor_dev_attr_fan1_target.dev_attr.attr,
984 &sensor_dev_attr_fan2_input.dev_attr.attr,
985 &sensor_dev_attr_fan2_min.dev_attr.attr,
986 &sensor_dev_attr_fan2_alarm.dev_attr.attr,
987 &sensor_dev_attr_fan2_target.dev_attr.attr,
988 &sensor_dev_attr_fan3_input.dev_attr.attr,
989 &sensor_dev_attr_fan3_min.dev_attr.attr,
990 &sensor_dev_attr_fan3_alarm.dev_attr.attr,
991 &sensor_dev_attr_fan3_target.dev_attr.attr,
992
993 &sensor_dev_attr_pwm1.dev_attr.attr,
994 &sensor_dev_attr_pwm1_enable.dev_attr.attr,
995 &sensor_dev_attr_pwm1_mode.dev_attr.attr,
996 &sensor_dev_attr_pwm2.dev_attr.attr,
997 &sensor_dev_attr_pwm2_enable.dev_attr.attr,
998 &sensor_dev_attr_pwm2_mode.dev_attr.attr,
999 &sensor_dev_attr_pwm3.dev_attr.attr,
1000 &sensor_dev_attr_pwm3_enable.dev_attr.attr,
1001 &sensor_dev_attr_pwm3_mode.dev_attr.attr,
1002
Jean Delvare0e39e012006-09-24 21:16:40 +02001003 &sensor_dev_attr_temp1_input.dev_attr.attr,
1004 &sensor_dev_attr_temp1_max.dev_attr.attr,
1005 &sensor_dev_attr_temp1_max_hyst.dev_attr.attr,
1006 &sensor_dev_attr_temp1_type.dev_attr.attr,
1007 &sensor_dev_attr_temp2_input.dev_attr.attr,
1008 &sensor_dev_attr_temp2_max.dev_attr.attr,
1009 &sensor_dev_attr_temp2_max_hyst.dev_attr.attr,
1010 &sensor_dev_attr_temp2_type.dev_attr.attr,
1011 &sensor_dev_attr_temp3_input.dev_attr.attr,
1012 &sensor_dev_attr_temp3_max.dev_attr.attr,
1013 &sensor_dev_attr_temp3_max_hyst.dev_attr.attr,
1014 &sensor_dev_attr_temp3_type.dev_attr.attr,
1015
1016 &sensor_dev_attr_in0_alarm.dev_attr.attr,
1017 &sensor_dev_attr_in1_alarm.dev_attr.attr,
1018 &sensor_dev_attr_in2_alarm.dev_attr.attr,
1019 &sensor_dev_attr_in3_alarm.dev_attr.attr,
Jean Delvare0e39e012006-09-24 21:16:40 +02001020 &sensor_dev_attr_in5_alarm.dev_attr.attr,
1021 &sensor_dev_attr_in6_alarm.dev_attr.attr,
1022 &sensor_dev_attr_in7_alarm.dev_attr.attr,
Jean Delvare0e39e012006-09-24 21:16:40 +02001023 &dev_attr_alarms_in.attr,
1024 &sensor_dev_attr_temp1_alarm.dev_attr.attr,
1025 &sensor_dev_attr_temp2_alarm.dev_attr.attr,
1026 &sensor_dev_attr_temp3_alarm.dev_attr.attr,
1027 &dev_attr_alarms_temp.attr,
1028 &dev_attr_alarms_fan.attr,
1029
1030 &dev_attr_name.attr,
1031 NULL
Jean Delvare2488a392006-01-09 23:29:11 +01001032};
1033
Jean Delvare0e39e012006-09-24 21:16:40 +02001034static const struct attribute_group f71805f_group = {
1035 .attrs = f71805f_attributes,
Jean Delvare2488a392006-01-09 23:29:11 +01001036};
1037
Jean Delvare51c997d2006-12-12 18:18:29 +01001038static struct attribute *f71805f_attributes_optin[4][5] = {
1039 {
1040 &sensor_dev_attr_in4_input.dev_attr.attr,
1041 &sensor_dev_attr_in4_max.dev_attr.attr,
1042 &sensor_dev_attr_in4_min.dev_attr.attr,
1043 &sensor_dev_attr_in4_alarm.dev_attr.attr,
1044 NULL
1045 }, {
1046 &sensor_dev_attr_in8_input.dev_attr.attr,
1047 &sensor_dev_attr_in8_max.dev_attr.attr,
1048 &sensor_dev_attr_in8_min.dev_attr.attr,
1049 &sensor_dev_attr_in8_alarm.dev_attr.attr,
1050 NULL
1051 }, {
1052 &sensor_dev_attr_in9_input.dev_attr.attr,
1053 &sensor_dev_attr_in9_max.dev_attr.attr,
1054 &sensor_dev_attr_in9_min.dev_attr.attr,
1055 &sensor_dev_attr_in9_alarm.dev_attr.attr,
1056 NULL
1057 }, {
1058 &sensor_dev_attr_in10_input.dev_attr.attr,
1059 &sensor_dev_attr_in10_max.dev_attr.attr,
1060 &sensor_dev_attr_in10_min.dev_attr.attr,
1061 &sensor_dev_attr_in10_alarm.dev_attr.attr,
1062 NULL
1063 }
1064};
1065
1066static const struct attribute_group f71805f_group_optin[4] = {
1067 { .attrs = f71805f_attributes_optin[0] },
1068 { .attrs = f71805f_attributes_optin[1] },
1069 { .attrs = f71805f_attributes_optin[2] },
1070 { .attrs = f71805f_attributes_optin[3] },
1071};
1072
Jean Delvaree1967832006-12-12 18:18:27 +01001073/* We don't include pwm_freq files in the arrays above, because they must be
1074 created conditionally (only if pwm_mode is 1 == PWM) */
1075static struct attribute *f71805f_attributes_pwm_freq[] = {
1076 &sensor_dev_attr_pwm1_freq.dev_attr.attr,
1077 &sensor_dev_attr_pwm2_freq.dev_attr.attr,
1078 &sensor_dev_attr_pwm3_freq.dev_attr.attr,
1079 NULL
1080};
1081
1082static const struct attribute_group f71805f_group_pwm_freq = {
1083 .attrs = f71805f_attributes_pwm_freq,
1084};
1085
Jean Delvare95e35312006-12-12 18:18:26 +01001086/* We also need an indexed access to pwmN files to toggle writability */
1087static struct attribute *f71805f_attr_pwm[] = {
1088 &sensor_dev_attr_pwm1.dev_attr.attr,
1089 &sensor_dev_attr_pwm2.dev_attr.attr,
1090 &sensor_dev_attr_pwm3.dev_attr.attr,
1091};
1092
Jean Delvaree53004e2006-01-09 23:26:14 +01001093/*
1094 * Device registration and initialization
1095 */
1096
1097static void __devinit f71805f_init_device(struct f71805f_data *data)
1098{
1099 u8 reg;
1100 int i;
1101
1102 reg = f71805f_read8(data, F71805F_REG_START);
1103 if ((reg & 0x41) != 0x01) {
1104 printk(KERN_DEBUG DRVNAME ": Starting monitoring "
1105 "operations\n");
1106 f71805f_write8(data, F71805F_REG_START, (reg | 0x01) & ~0x40);
1107 }
1108
1109 /* Fan monitoring can be disabled. If it is, we won't be polling
1110 the register values, and won't create the related sysfs files. */
1111 for (i = 0; i < 3; i++) {
Jean Delvare6b14a542006-12-12 18:18:26 +01001112 data->fan_ctrl[i] = f71805f_read8(data,
1113 F71805F_REG_FAN_CTRL(i));
Jean Delvare315c7112006-12-12 18:18:27 +01001114 /* Clear latch full bit, else "speed mode" fan speed control
1115 doesn't work */
1116 if (data->fan_ctrl[i] & FAN_CTRL_LATCH_FULL) {
1117 data->fan_ctrl[i] &= ~FAN_CTRL_LATCH_FULL;
1118 f71805f_write8(data, F71805F_REG_FAN_CTRL(i),
1119 data->fan_ctrl[i]);
1120 }
Jean Delvaree53004e2006-01-09 23:26:14 +01001121 }
1122}
1123
1124static int __devinit f71805f_probe(struct platform_device *pdev)
1125{
Jean Delvare51c997d2006-12-12 18:18:29 +01001126 struct f71805f_sio_data *sio_data = pdev->dev.platform_data;
Jean Delvaree53004e2006-01-09 23:26:14 +01001127 struct f71805f_data *data;
1128 struct resource *res;
Jean Delvare2488a392006-01-09 23:29:11 +01001129 int i, err;
Jean Delvaree53004e2006-01-09 23:26:14 +01001130
Jean Delvare51c997d2006-12-12 18:18:29 +01001131 static const char *names[] = {
1132 "f71805f",
1133 "f71872f",
1134 };
1135
Jean Delvaree53004e2006-01-09 23:26:14 +01001136 if (!(data = kzalloc(sizeof(struct f71805f_data), GFP_KERNEL))) {
1137 err = -ENOMEM;
1138 printk(KERN_ERR DRVNAME ": Out of memory\n");
1139 goto exit;
1140 }
1141
1142 res = platform_get_resource(pdev, IORESOURCE_IO, 0);
1143 data->addr = res->start;
Jean Delvare51c997d2006-12-12 18:18:29 +01001144 data->name = names[sio_data->kind];
Jean Delvaref0819182006-01-18 23:20:53 +01001145 mutex_init(&data->update_lock);
Jean Delvaree53004e2006-01-09 23:26:14 +01001146
1147 platform_set_drvdata(pdev, data);
1148
Jean Delvare51c997d2006-12-12 18:18:29 +01001149 /* Some voltage inputs depend on chip model and configuration */
1150 switch (sio_data->kind) {
1151 case f71805f:
1152 data->has_in = 0x1ff;
1153 break;
1154 case f71872f:
1155 data->has_in = 0x6ef;
1156 if (sio_data->fnsel1 & 0x01)
1157 data->has_in |= (1 << 4); /* in4 */
1158 if (sio_data->fnsel1 & 0x02)
1159 data->has_in |= (1 << 8); /* in8 */
1160 break;
1161 }
1162
Jean Delvaree53004e2006-01-09 23:26:14 +01001163 /* Initialize the F71805F chip */
1164 f71805f_init_device(data);
1165
1166 /* Register sysfs interface files */
Jean Delvare0e39e012006-09-24 21:16:40 +02001167 if ((err = sysfs_create_group(&pdev->dev.kobj, &f71805f_group)))
1168 goto exit_free;
Jean Delvare51c997d2006-12-12 18:18:29 +01001169 if (data->has_in & (1 << 4)) { /* in4 */
1170 if ((err = sysfs_create_group(&pdev->dev.kobj,
1171 &f71805f_group_optin[0])))
1172 goto exit_remove_files;
1173 }
1174 if (data->has_in & (1 << 8)) { /* in8 */
1175 if ((err = sysfs_create_group(&pdev->dev.kobj,
1176 &f71805f_group_optin[1])))
1177 goto exit_remove_files;
1178 }
1179 if (data->has_in & (1 << 9)) { /* in9 (F71872F/FG only) */
1180 if ((err = sysfs_create_group(&pdev->dev.kobj,
1181 &f71805f_group_optin[2])))
1182 goto exit_remove_files;
1183 }
1184 if (data->has_in & (1 << 10)) { /* in9 (F71872F/FG only) */
1185 if ((err = sysfs_create_group(&pdev->dev.kobj,
1186 &f71805f_group_optin[3])))
1187 goto exit_remove_files;
1188 }
Jean Delvare0e39e012006-09-24 21:16:40 +02001189 for (i = 0; i < 3; i++) {
Jean Delvaree1967832006-12-12 18:18:27 +01001190 /* If control mode is PWM, create pwm_freq file */
1191 if (!(data->fan_ctrl[i] & FAN_CTRL_DC_MODE)) {
1192 if ((err = sysfs_create_file(&pdev->dev.kobj,
1193 f71805f_attributes_pwm_freq[i])))
1194 goto exit_remove_files;
1195 }
Jean Delvare95e35312006-12-12 18:18:26 +01001196 /* If PWM is in manual mode, add write permission */
1197 if (data->fan_ctrl[i] & FAN_CTRL_MODE_MANUAL) {
1198 if ((err = sysfs_chmod_file(&pdev->dev.kobj,
1199 f71805f_attr_pwm[i],
1200 S_IRUGO | S_IWUSR))) {
1201 dev_err(&pdev->dev, "chmod +w pwm%d failed\n",
1202 i + 1);
1203 goto exit_remove_files;
1204 }
1205 }
Jean Delvare0e39e012006-09-24 21:16:40 +02001206 }
1207
1208 data->class_dev = hwmon_device_register(&pdev->dev);
1209 if (IS_ERR(data->class_dev)) {
1210 err = PTR_ERR(data->class_dev);
1211 dev_err(&pdev->dev, "Class registration failed (%d)\n", err);
1212 goto exit_remove_files;
Jean Delvaree53004e2006-01-09 23:26:14 +01001213 }
Jean Delvaree53004e2006-01-09 23:26:14 +01001214
1215 return 0;
1216
Jean Delvare0e39e012006-09-24 21:16:40 +02001217exit_remove_files:
1218 sysfs_remove_group(&pdev->dev.kobj, &f71805f_group);
Jean Delvare51c997d2006-12-12 18:18:29 +01001219 for (i = 0; i < 4; i++)
1220 sysfs_remove_group(&pdev->dev.kobj, &f71805f_group_optin[i]);
Jean Delvaree1967832006-12-12 18:18:27 +01001221 sysfs_remove_group(&pdev->dev.kobj, &f71805f_group_pwm_freq);
Jean Delvaree53004e2006-01-09 23:26:14 +01001222exit_free:
Jean Delvare0e39e012006-09-24 21:16:40 +02001223 platform_set_drvdata(pdev, NULL);
Jean Delvaree53004e2006-01-09 23:26:14 +01001224 kfree(data);
1225exit:
1226 return err;
1227}
1228
1229static int __devexit f71805f_remove(struct platform_device *pdev)
1230{
1231 struct f71805f_data *data = platform_get_drvdata(pdev);
Jean Delvare0e39e012006-09-24 21:16:40 +02001232 int i;
Jean Delvaree53004e2006-01-09 23:26:14 +01001233
1234 platform_set_drvdata(pdev, NULL);
1235 hwmon_device_unregister(data->class_dev);
Jean Delvare0e39e012006-09-24 21:16:40 +02001236 sysfs_remove_group(&pdev->dev.kobj, &f71805f_group);
Jean Delvare51c997d2006-12-12 18:18:29 +01001237 for (i = 0; i < 4; i++)
1238 sysfs_remove_group(&pdev->dev.kobj, &f71805f_group_optin[i]);
Jean Delvaree1967832006-12-12 18:18:27 +01001239 sysfs_remove_group(&pdev->dev.kobj, &f71805f_group_pwm_freq);
Jean Delvaree53004e2006-01-09 23:26:14 +01001240 kfree(data);
1241
1242 return 0;
1243}
1244
1245static struct platform_driver f71805f_driver = {
1246 .driver = {
1247 .owner = THIS_MODULE,
1248 .name = DRVNAME,
1249 },
1250 .probe = f71805f_probe,
1251 .remove = __devexit_p(f71805f_remove),
1252};
1253
Jean Delvare51c997d2006-12-12 18:18:29 +01001254static int __init f71805f_device_add(unsigned short address,
1255 const struct f71805f_sio_data *sio_data)
Jean Delvaree53004e2006-01-09 23:26:14 +01001256{
Jean Delvare568825c2006-03-23 16:40:23 +01001257 struct resource res = {
1258 .start = address,
1259 .end = address + REGION_LENGTH - 1,
1260 .flags = IORESOURCE_IO,
1261 };
Jean Delvaree53004e2006-01-09 23:26:14 +01001262 int err;
1263
1264 pdev = platform_device_alloc(DRVNAME, address);
1265 if (!pdev) {
1266 err = -ENOMEM;
1267 printk(KERN_ERR DRVNAME ": Device allocation failed\n");
1268 goto exit;
1269 }
1270
Jean Delvare568825c2006-03-23 16:40:23 +01001271 res.name = pdev->name;
1272 err = platform_device_add_resources(pdev, &res, 1);
Jean Delvaree53004e2006-01-09 23:26:14 +01001273 if (err) {
1274 printk(KERN_ERR DRVNAME ": Device resource addition failed "
1275 "(%d)\n", err);
1276 goto exit_device_put;
1277 }
1278
Jean Delvare51c997d2006-12-12 18:18:29 +01001279 pdev->dev.platform_data = kmalloc(sizeof(struct f71805f_sio_data),
1280 GFP_KERNEL);
1281 if (!pdev->dev.platform_data) {
1282 err = -ENOMEM;
1283 printk(KERN_ERR DRVNAME ": Platform data allocation failed\n");
1284 goto exit_device_put;
1285 }
1286 memcpy(pdev->dev.platform_data, sio_data,
1287 sizeof(struct f71805f_sio_data));
1288
Jean Delvaree53004e2006-01-09 23:26:14 +01001289 err = platform_device_add(pdev);
1290 if (err) {
1291 printk(KERN_ERR DRVNAME ": Device addition failed (%d)\n",
1292 err);
Jean Delvarea117ddd2007-02-14 21:15:05 +01001293 goto exit_device_put;
Jean Delvaree53004e2006-01-09 23:26:14 +01001294 }
1295
1296 return 0;
1297
1298exit_device_put:
1299 platform_device_put(pdev);
1300exit:
1301 return err;
1302}
1303
Jean Delvare51c997d2006-12-12 18:18:29 +01001304static int __init f71805f_find(int sioaddr, unsigned short *address,
1305 struct f71805f_sio_data *sio_data)
Jean Delvaree53004e2006-01-09 23:26:14 +01001306{
1307 int err = -ENODEV;
1308 u16 devid;
1309
Jean Delvare51c997d2006-12-12 18:18:29 +01001310 static const char *names[] = {
1311 "F71805F/FG",
1312 "F71872F/FG",
1313 };
1314
Jean Delvaree53004e2006-01-09 23:26:14 +01001315 superio_enter(sioaddr);
1316
1317 devid = superio_inw(sioaddr, SIO_REG_MANID);
1318 if (devid != SIO_FINTEK_ID)
1319 goto exit;
1320
1321 devid = superio_inw(sioaddr, SIO_REG_DEVID);
Jean Delvare51c997d2006-12-12 18:18:29 +01001322 switch (devid) {
1323 case SIO_F71805F_ID:
1324 sio_data->kind = f71805f;
1325 break;
1326 case SIO_F71872F_ID:
1327 sio_data->kind = f71872f;
1328 sio_data->fnsel1 = superio_inb(sioaddr, SIO_REG_FNSEL1);
1329 break;
1330 default:
Jean Delvaree53004e2006-01-09 23:26:14 +01001331 printk(KERN_INFO DRVNAME ": Unsupported Fintek device, "
1332 "skipping\n");
1333 goto exit;
1334 }
1335
1336 superio_select(sioaddr, F71805F_LD_HWM);
1337 if (!(superio_inb(sioaddr, SIO_REG_ENABLE) & 0x01)) {
1338 printk(KERN_WARNING DRVNAME ": Device not activated, "
1339 "skipping\n");
1340 goto exit;
1341 }
1342
1343 *address = superio_inw(sioaddr, SIO_REG_ADDR);
1344 if (*address == 0) {
1345 printk(KERN_WARNING DRVNAME ": Base address not set, "
1346 "skipping\n");
1347 goto exit;
1348 }
Jean Delvare75c99022006-12-12 18:18:29 +01001349 *address &= ~(REGION_LENGTH - 1); /* Ignore 3 LSB */
Jean Delvaree53004e2006-01-09 23:26:14 +01001350
1351 err = 0;
Jean Delvare51c997d2006-12-12 18:18:29 +01001352 printk(KERN_INFO DRVNAME ": Found %s chip at %#x, revision %u\n",
1353 names[sio_data->kind], *address,
1354 superio_inb(sioaddr, SIO_REG_DEVREV));
Jean Delvaree53004e2006-01-09 23:26:14 +01001355
1356exit:
1357 superio_exit(sioaddr);
1358 return err;
1359}
1360
1361static int __init f71805f_init(void)
1362{
1363 int err;
1364 unsigned short address;
Jean Delvare51c997d2006-12-12 18:18:29 +01001365 struct f71805f_sio_data sio_data;
Jean Delvaree53004e2006-01-09 23:26:14 +01001366
Jean Delvare51c997d2006-12-12 18:18:29 +01001367 if (f71805f_find(0x2e, &address, &sio_data)
1368 && f71805f_find(0x4e, &address, &sio_data))
Jean Delvaree53004e2006-01-09 23:26:14 +01001369 return -ENODEV;
1370
1371 err = platform_driver_register(&f71805f_driver);
1372 if (err)
1373 goto exit;
1374
1375 /* Sets global pdev as a side effect */
Jean Delvare51c997d2006-12-12 18:18:29 +01001376 err = f71805f_device_add(address, &sio_data);
Jean Delvaree53004e2006-01-09 23:26:14 +01001377 if (err)
1378 goto exit_driver;
1379
1380 return 0;
1381
1382exit_driver:
1383 platform_driver_unregister(&f71805f_driver);
1384exit:
1385 return err;
1386}
1387
1388static void __exit f71805f_exit(void)
1389{
1390 platform_device_unregister(pdev);
1391 platform_driver_unregister(&f71805f_driver);
1392}
1393
1394MODULE_AUTHOR("Jean Delvare <khali@linux-fr>");
1395MODULE_LICENSE("GPL");
Jean Delvare51c997d2006-12-12 18:18:29 +01001396MODULE_DESCRIPTION("F71805F/F71872F hardware monitoring driver");
Jean Delvaree53004e2006-01-09 23:26:14 +01001397
1398module_init(f71805f_init);
1399module_exit(f71805f_exit);