blob: 975c1cc2acf1217b5ed005f7b5ad464be9bfb541 [file] [log] [blame]
Jean Delvaree53004e2006-01-09 23:26:14 +01001/*
2 * f71805f.c - driver for the Fintek F71805F/FG Super-I/O chip integrated
3 * 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 *
10 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License as published by
12 * the Free Software Foundation; either version 2 of the License, or
13 * (at your option) any later version.
14 *
15 * This program is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU General Public License for more details.
19 *
20 * You should have received a copy of the GNU General Public License
21 * along with this program; if not, write to the Free Software
22 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
23 */
24
25#include <linux/module.h>
26#include <linux/init.h>
27#include <linux/slab.h>
28#include <linux/jiffies.h>
29#include <linux/platform_device.h>
30#include <linux/hwmon.h>
31#include <linux/hwmon-sysfs.h>
32#include <linux/err.h>
Jean Delvaref0819182006-01-18 23:20:53 +010033#include <linux/mutex.h>
Jean Delvare0e39e012006-09-24 21:16:40 +020034#include <linux/sysfs.h>
Jean Delvaree53004e2006-01-09 23:26:14 +010035#include <asm/io.h>
36
37static struct platform_device *pdev;
38
39#define DRVNAME "f71805f"
40
41/*
42 * Super-I/O constants and functions
43 */
44
45#define F71805F_LD_HWM 0x04
46
47#define SIO_REG_LDSEL 0x07 /* Logical device select */
48#define SIO_REG_DEVID 0x20 /* Device ID (2 bytes) */
49#define SIO_REG_DEVREV 0x22 /* Device revision */
50#define SIO_REG_MANID 0x23 /* Fintek ID (2 bytes) */
51#define SIO_REG_ENABLE 0x30 /* Logical device enable */
52#define SIO_REG_ADDR 0x60 /* Logical device address (2 bytes) */
53
54#define SIO_FINTEK_ID 0x1934
55#define SIO_F71805F_ID 0x0406
56
57static inline int
58superio_inb(int base, int reg)
59{
60 outb(reg, base);
61 return inb(base + 1);
62}
63
64static int
65superio_inw(int base, int reg)
66{
67 int val;
68 outb(reg++, base);
69 val = inb(base + 1) << 8;
70 outb(reg, base);
71 val |= inb(base + 1);
72 return val;
73}
74
75static inline void
76superio_select(int base, int ld)
77{
78 outb(SIO_REG_LDSEL, base);
79 outb(ld, base + 1);
80}
81
82static inline void
83superio_enter(int base)
84{
85 outb(0x87, base);
86 outb(0x87, base);
87}
88
89static inline void
90superio_exit(int base)
91{
92 outb(0xaa, base);
93}
94
95/*
96 * ISA constants
97 */
98
99#define REGION_LENGTH 2
100#define ADDR_REG_OFFSET 0
101#define DATA_REG_OFFSET 1
102
Jean Delvaree53004e2006-01-09 23:26:14 +0100103/*
104 * Registers
105 */
106
107/* in nr from 0 to 8 (8-bit values) */
108#define F71805F_REG_IN(nr) (0x10 + (nr))
109#define F71805F_REG_IN_HIGH(nr) (0x40 + 2 * (nr))
110#define F71805F_REG_IN_LOW(nr) (0x41 + 2 * (nr))
111/* fan nr from 0 to 2 (12-bit values, two registers) */
112#define F71805F_REG_FAN(nr) (0x20 + 2 * (nr))
113#define F71805F_REG_FAN_LOW(nr) (0x28 + 2 * (nr))
Jean Delvare315c7112006-12-12 18:18:27 +0100114#define F71805F_REG_FAN_TARGET(nr) (0x69 + 16 * (nr))
Jean Delvaree53004e2006-01-09 23:26:14 +0100115#define F71805F_REG_FAN_CTRL(nr) (0x60 + 16 * (nr))
Jean Delvare6e2bc172006-12-12 18:18:27 +0100116#define F71805F_REG_PWM_FREQ(nr) (0x63 + 16 * (nr))
Jean Delvare95e35312006-12-12 18:18:26 +0100117#define F71805F_REG_PWM_DUTY(nr) (0x6B + 16 * (nr))
Jean Delvaree53004e2006-01-09 23:26:14 +0100118/* temp nr from 0 to 2 (8-bit values) */
119#define F71805F_REG_TEMP(nr) (0x1B + (nr))
120#define F71805F_REG_TEMP_HIGH(nr) (0x54 + 2 * (nr))
121#define F71805F_REG_TEMP_HYST(nr) (0x55 + 2 * (nr))
122#define F71805F_REG_TEMP_MODE 0x01
123
124#define F71805F_REG_START 0x00
125/* status nr from 0 to 2 */
126#define F71805F_REG_STATUS(nr) (0x36 + (nr))
127
Jean Delvare6b14a542006-12-12 18:18:26 +0100128/* individual register bits */
129#define FAN_CTRL_SKIP 0x80
Jean Delvaree1967832006-12-12 18:18:27 +0100130#define FAN_CTRL_DC_MODE 0x10
Jean Delvare315c7112006-12-12 18:18:27 +0100131#define FAN_CTRL_LATCH_FULL 0x08
Jean Delvare95e35312006-12-12 18:18:26 +0100132#define FAN_CTRL_MODE_MASK 0x03
133#define FAN_CTRL_MODE_SPEED 0x00
134#define FAN_CTRL_MODE_TEMPERATURE 0x01
135#define FAN_CTRL_MODE_MANUAL 0x02
Jean Delvare6b14a542006-12-12 18:18:26 +0100136
Jean Delvaree53004e2006-01-09 23:26:14 +0100137/*
138 * Data structures and manipulation thereof
139 */
140
141struct f71805f_data {
142 unsigned short addr;
143 const char *name;
Jean Delvaref0819182006-01-18 23:20:53 +0100144 struct mutex lock;
Jean Delvaree53004e2006-01-09 23:26:14 +0100145 struct class_device *class_dev;
146
Jean Delvaref0819182006-01-18 23:20:53 +0100147 struct mutex update_lock;
Jean Delvaree53004e2006-01-09 23:26:14 +0100148 char valid; /* !=0 if following fields are valid */
149 unsigned long last_updated; /* In jiffies */
150 unsigned long last_limits; /* In jiffies */
151
152 /* Register values */
153 u8 in[9];
154 u8 in_high[9];
155 u8 in_low[9];
156 u16 fan[3];
157 u16 fan_low[3];
Jean Delvare315c7112006-12-12 18:18:27 +0100158 u16 fan_target[3];
Jean Delvare6b14a542006-12-12 18:18:26 +0100159 u8 fan_ctrl[3];
Jean Delvare95e35312006-12-12 18:18:26 +0100160 u8 pwm[3];
Jean Delvare6e2bc172006-12-12 18:18:27 +0100161 u8 pwm_freq[3];
Jean Delvaree53004e2006-01-09 23:26:14 +0100162 u8 temp[3];
163 u8 temp_high[3];
164 u8 temp_hyst[3];
165 u8 temp_mode;
Jean Delvare2d457712006-09-24 20:52:15 +0200166 unsigned long alarms;
Jean Delvaree53004e2006-01-09 23:26:14 +0100167};
168
169static inline long in_from_reg(u8 reg)
170{
171 return (reg * 8);
172}
173
174/* The 2 least significant bits are not used */
175static inline u8 in_to_reg(long val)
176{
177 if (val <= 0)
178 return 0;
179 if (val >= 2016)
180 return 0xfc;
181 return (((val + 16) / 32) << 2);
182}
183
184/* in0 is downscaled by a factor 2 internally */
185static inline long in0_from_reg(u8 reg)
186{
187 return (reg * 16);
188}
189
190static inline u8 in0_to_reg(long val)
191{
192 if (val <= 0)
193 return 0;
194 if (val >= 4032)
195 return 0xfc;
196 return (((val + 32) / 64) << 2);
197}
198
199/* The 4 most significant bits are not used */
200static inline long fan_from_reg(u16 reg)
201{
202 reg &= 0xfff;
203 if (!reg || reg == 0xfff)
204 return 0;
205 return (1500000 / reg);
206}
207
208static inline u16 fan_to_reg(long rpm)
209{
210 /* If the low limit is set below what the chip can measure,
211 store the largest possible 12-bit value in the registers,
212 so that no alarm will ever trigger. */
213 if (rpm < 367)
214 return 0xfff;
215 return (1500000 / rpm);
216}
217
Jean Delvare6e2bc172006-12-12 18:18:27 +0100218static inline unsigned long pwm_freq_from_reg(u8 reg)
219{
220 unsigned long clock = (reg & 0x80) ? 48000000UL : 1000000UL;
221
222 reg &= 0x7f;
223 if (reg == 0)
224 reg++;
225 return clock / (reg << 8);
226}
227
228static inline u8 pwm_freq_to_reg(unsigned long val)
229{
230 if (val >= 187500) /* The highest we can do */
231 return 0x80;
232 if (val >= 1475) /* Use 48 MHz clock */
233 return 0x80 | (48000000UL / (val << 8));
234 if (val < 31) /* The lowest we can do */
235 return 0x7f;
236 else /* Use 1 MHz clock */
237 return 1000000UL / (val << 8);
238}
239
Jean Delvaree1967832006-12-12 18:18:27 +0100240static inline int pwm_mode_from_reg(u8 reg)
241{
242 return !(reg & FAN_CTRL_DC_MODE);
243}
244
Jean Delvaree53004e2006-01-09 23:26:14 +0100245static inline long temp_from_reg(u8 reg)
246{
247 return (reg * 1000);
248}
249
250static inline u8 temp_to_reg(long val)
251{
252 if (val < 0)
253 val = 0;
254 else if (val > 1000 * 0xff)
255 val = 0xff;
256 return ((val + 500) / 1000);
257}
258
259/*
260 * Device I/O access
261 */
262
263static u8 f71805f_read8(struct f71805f_data *data, u8 reg)
264{
265 u8 val;
266
Jean Delvaref0819182006-01-18 23:20:53 +0100267 mutex_lock(&data->lock);
Jean Delvaree53004e2006-01-09 23:26:14 +0100268 outb(reg, data->addr + ADDR_REG_OFFSET);
269 val = inb(data->addr + DATA_REG_OFFSET);
Jean Delvaref0819182006-01-18 23:20:53 +0100270 mutex_unlock(&data->lock);
Jean Delvaree53004e2006-01-09 23:26:14 +0100271
272 return val;
273}
274
275static void f71805f_write8(struct f71805f_data *data, u8 reg, u8 val)
276{
Jean Delvaref0819182006-01-18 23:20:53 +0100277 mutex_lock(&data->lock);
Jean Delvaree53004e2006-01-09 23:26:14 +0100278 outb(reg, data->addr + ADDR_REG_OFFSET);
279 outb(val, data->addr + DATA_REG_OFFSET);
Jean Delvaref0819182006-01-18 23:20:53 +0100280 mutex_unlock(&data->lock);
Jean Delvaree53004e2006-01-09 23:26:14 +0100281}
282
283/* It is important to read the MSB first, because doing so latches the
284 value of the LSB, so we are sure both bytes belong to the same value. */
285static u16 f71805f_read16(struct f71805f_data *data, u8 reg)
286{
287 u16 val;
288
Jean Delvaref0819182006-01-18 23:20:53 +0100289 mutex_lock(&data->lock);
Jean Delvaree53004e2006-01-09 23:26:14 +0100290 outb(reg, data->addr + ADDR_REG_OFFSET);
291 val = inb(data->addr + DATA_REG_OFFSET) << 8;
292 outb(++reg, data->addr + ADDR_REG_OFFSET);
293 val |= inb(data->addr + DATA_REG_OFFSET);
Jean Delvaref0819182006-01-18 23:20:53 +0100294 mutex_unlock(&data->lock);
Jean Delvaree53004e2006-01-09 23:26:14 +0100295
296 return val;
297}
298
299static void f71805f_write16(struct f71805f_data *data, u8 reg, u16 val)
300{
Jean Delvaref0819182006-01-18 23:20:53 +0100301 mutex_lock(&data->lock);
Jean Delvaree53004e2006-01-09 23:26:14 +0100302 outb(reg, data->addr + ADDR_REG_OFFSET);
303 outb(val >> 8, data->addr + DATA_REG_OFFSET);
304 outb(++reg, data->addr + ADDR_REG_OFFSET);
305 outb(val & 0xff, data->addr + DATA_REG_OFFSET);
Jean Delvaref0819182006-01-18 23:20:53 +0100306 mutex_unlock(&data->lock);
Jean Delvaree53004e2006-01-09 23:26:14 +0100307}
308
309static struct f71805f_data *f71805f_update_device(struct device *dev)
310{
311 struct f71805f_data *data = dev_get_drvdata(dev);
312 int nr;
313
Jean Delvaref0819182006-01-18 23:20:53 +0100314 mutex_lock(&data->update_lock);
Jean Delvaree53004e2006-01-09 23:26:14 +0100315
316 /* Limit registers cache is refreshed after 60 seconds */
317 if (time_after(jiffies, data->last_updated + 60 * HZ)
318 || !data->valid) {
319 for (nr = 0; nr < 9; nr++) {
320 data->in_high[nr] = f71805f_read8(data,
321 F71805F_REG_IN_HIGH(nr));
322 data->in_low[nr] = f71805f_read8(data,
323 F71805F_REG_IN_LOW(nr));
324 }
325 for (nr = 0; nr < 3; nr++) {
Jean Delvare6b14a542006-12-12 18:18:26 +0100326 if (data->fan_ctrl[nr] & FAN_CTRL_SKIP)
327 continue;
328 data->fan_low[nr] = f71805f_read16(data,
329 F71805F_REG_FAN_LOW(nr));
Jean Delvare315c7112006-12-12 18:18:27 +0100330 data->fan_target[nr] = f71805f_read16(data,
331 F71805F_REG_FAN_TARGET(nr));
Jean Delvare6e2bc172006-12-12 18:18:27 +0100332 data->pwm_freq[nr] = f71805f_read8(data,
333 F71805F_REG_PWM_FREQ(nr));
Jean Delvaree53004e2006-01-09 23:26:14 +0100334 }
335 for (nr = 0; nr < 3; nr++) {
336 data->temp_high[nr] = f71805f_read8(data,
337 F71805F_REG_TEMP_HIGH(nr));
338 data->temp_hyst[nr] = f71805f_read8(data,
339 F71805F_REG_TEMP_HYST(nr));
340 }
341 data->temp_mode = f71805f_read8(data, F71805F_REG_TEMP_MODE);
342
343 data->last_limits = jiffies;
344 }
345
346 /* Measurement registers cache is refreshed after 1 second */
347 if (time_after(jiffies, data->last_updated + HZ)
348 || !data->valid) {
349 for (nr = 0; nr < 9; nr++) {
350 data->in[nr] = f71805f_read8(data,
351 F71805F_REG_IN(nr));
352 }
353 for (nr = 0; nr < 3; nr++) {
Jean Delvare6b14a542006-12-12 18:18:26 +0100354 if (data->fan_ctrl[nr] & FAN_CTRL_SKIP)
355 continue;
356 data->fan[nr] = f71805f_read16(data,
357 F71805F_REG_FAN(nr));
Jean Delvare95e35312006-12-12 18:18:26 +0100358 data->fan_ctrl[nr] = f71805f_read8(data,
359 F71805F_REG_FAN_CTRL(nr));
360 data->pwm[nr] = f71805f_read8(data,
361 F71805F_REG_PWM_DUTY(nr));
Jean Delvaree53004e2006-01-09 23:26:14 +0100362 }
363 for (nr = 0; nr < 3; nr++) {
364 data->temp[nr] = f71805f_read8(data,
365 F71805F_REG_TEMP(nr));
366 }
Jean Delvare2d457712006-09-24 20:52:15 +0200367 data->alarms = f71805f_read8(data, F71805F_REG_STATUS(0))
368 + (f71805f_read8(data, F71805F_REG_STATUS(1)) << 8)
369 + (f71805f_read8(data, F71805F_REG_STATUS(2)) << 16);
Jean Delvaree53004e2006-01-09 23:26:14 +0100370
371 data->last_updated = jiffies;
372 data->valid = 1;
373 }
374
Jean Delvaref0819182006-01-18 23:20:53 +0100375 mutex_unlock(&data->update_lock);
Jean Delvaree53004e2006-01-09 23:26:14 +0100376
377 return data;
378}
379
380/*
381 * Sysfs interface
382 */
383
384static ssize_t show_in0(struct device *dev, struct device_attribute *devattr,
385 char *buf)
386{
387 struct f71805f_data *data = f71805f_update_device(dev);
388
389 return sprintf(buf, "%ld\n", in0_from_reg(data->in[0]));
390}
391
392static ssize_t show_in0_max(struct device *dev, struct device_attribute
393 *devattr, char *buf)
394{
395 struct f71805f_data *data = f71805f_update_device(dev);
396
397 return sprintf(buf, "%ld\n", in0_from_reg(data->in_high[0]));
398}
399
400static ssize_t show_in0_min(struct device *dev, struct device_attribute
401 *devattr, char *buf)
402{
403 struct f71805f_data *data = f71805f_update_device(dev);
404
405 return sprintf(buf, "%ld\n", in0_from_reg(data->in_low[0]));
406}
407
408static ssize_t set_in0_max(struct device *dev, struct device_attribute
409 *devattr, const char *buf, size_t count)
410{
411 struct f71805f_data *data = dev_get_drvdata(dev);
412 long val = simple_strtol(buf, NULL, 10);
413
Jean Delvaref0819182006-01-18 23:20:53 +0100414 mutex_lock(&data->update_lock);
Jean Delvaree53004e2006-01-09 23:26:14 +0100415 data->in_high[0] = in0_to_reg(val);
416 f71805f_write8(data, F71805F_REG_IN_HIGH(0), data->in_high[0]);
Jean Delvaref0819182006-01-18 23:20:53 +0100417 mutex_unlock(&data->update_lock);
Jean Delvaree53004e2006-01-09 23:26:14 +0100418
419 return count;
420}
421
422static ssize_t set_in0_min(struct device *dev, struct device_attribute
423 *devattr, const char *buf, size_t count)
424{
425 struct f71805f_data *data = dev_get_drvdata(dev);
426 long val = simple_strtol(buf, NULL, 10);
427
Jean Delvaref0819182006-01-18 23:20:53 +0100428 mutex_lock(&data->update_lock);
Jean Delvaree53004e2006-01-09 23:26:14 +0100429 data->in_low[0] = in0_to_reg(val);
430 f71805f_write8(data, F71805F_REG_IN_LOW(0), data->in_low[0]);
Jean Delvaref0819182006-01-18 23:20:53 +0100431 mutex_unlock(&data->update_lock);
Jean Delvaree53004e2006-01-09 23:26:14 +0100432
433 return count;
434}
435
Jean Delvaree53004e2006-01-09 23:26:14 +0100436static ssize_t show_in(struct device *dev, struct device_attribute *devattr,
437 char *buf)
438{
439 struct f71805f_data *data = f71805f_update_device(dev);
440 struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
441 int nr = attr->index;
442
443 return sprintf(buf, "%ld\n", in_from_reg(data->in[nr]));
444}
445
446static ssize_t show_in_max(struct device *dev, struct device_attribute
447 *devattr, char *buf)
448{
449 struct f71805f_data *data = f71805f_update_device(dev);
450 struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
451 int nr = attr->index;
452
453 return sprintf(buf, "%ld\n", in_from_reg(data->in_high[nr]));
454}
455
456static ssize_t show_in_min(struct device *dev, struct device_attribute
457 *devattr, char *buf)
458{
459 struct f71805f_data *data = f71805f_update_device(dev);
460 struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
461 int nr = attr->index;
462
463 return sprintf(buf, "%ld\n", in_from_reg(data->in_low[nr]));
464}
465
466static ssize_t set_in_max(struct device *dev, struct device_attribute
467 *devattr, const char *buf, size_t count)
468{
469 struct f71805f_data *data = dev_get_drvdata(dev);
470 struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
471 int nr = attr->index;
472 long val = simple_strtol(buf, NULL, 10);
473
Jean Delvaref0819182006-01-18 23:20:53 +0100474 mutex_lock(&data->update_lock);
Jean Delvaree53004e2006-01-09 23:26:14 +0100475 data->in_high[nr] = in_to_reg(val);
476 f71805f_write8(data, F71805F_REG_IN_HIGH(nr), data->in_high[nr]);
Jean Delvaref0819182006-01-18 23:20:53 +0100477 mutex_unlock(&data->update_lock);
Jean Delvaree53004e2006-01-09 23:26:14 +0100478
479 return count;
480}
481
482static ssize_t set_in_min(struct device *dev, struct device_attribute
483 *devattr, const char *buf, size_t count)
484{
485 struct f71805f_data *data = dev_get_drvdata(dev);
486 struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
487 int nr = attr->index;
488 long val = simple_strtol(buf, NULL, 10);
489
Jean Delvaref0819182006-01-18 23:20:53 +0100490 mutex_lock(&data->update_lock);
Jean Delvaree53004e2006-01-09 23:26:14 +0100491 data->in_low[nr] = in_to_reg(val);
492 f71805f_write8(data, F71805F_REG_IN_LOW(nr), data->in_low[nr]);
Jean Delvaref0819182006-01-18 23:20:53 +0100493 mutex_unlock(&data->update_lock);
Jean Delvaree53004e2006-01-09 23:26:14 +0100494
495 return count;
496}
497
Jean Delvaree53004e2006-01-09 23:26:14 +0100498static ssize_t show_fan(struct device *dev, struct device_attribute *devattr,
499 char *buf)
500{
501 struct f71805f_data *data = f71805f_update_device(dev);
502 struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
503 int nr = attr->index;
504
505 return sprintf(buf, "%ld\n", fan_from_reg(data->fan[nr]));
506}
507
508static ssize_t show_fan_min(struct device *dev, struct device_attribute
509 *devattr, char *buf)
510{
511 struct f71805f_data *data = f71805f_update_device(dev);
512 struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
513 int nr = attr->index;
514
515 return sprintf(buf, "%ld\n", fan_from_reg(data->fan_low[nr]));
516}
517
Jean Delvare315c7112006-12-12 18:18:27 +0100518static ssize_t show_fan_target(struct device *dev, struct device_attribute
519 *devattr, char *buf)
520{
521 struct f71805f_data *data = f71805f_update_device(dev);
522 struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
523 int nr = attr->index;
524
525 return sprintf(buf, "%ld\n", fan_from_reg(data->fan_target[nr]));
526}
527
Jean Delvaree53004e2006-01-09 23:26:14 +0100528static ssize_t set_fan_min(struct device *dev, struct device_attribute
529 *devattr, const char *buf, size_t count)
530{
531 struct f71805f_data *data = dev_get_drvdata(dev);
532 struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
533 int nr = attr->index;
534 long val = simple_strtol(buf, NULL, 10);
535
Jean Delvaref0819182006-01-18 23:20:53 +0100536 mutex_lock(&data->update_lock);
Jean Delvaree53004e2006-01-09 23:26:14 +0100537 data->fan_low[nr] = fan_to_reg(val);
538 f71805f_write16(data, F71805F_REG_FAN_LOW(nr), data->fan_low[nr]);
Jean Delvaref0819182006-01-18 23:20:53 +0100539 mutex_unlock(&data->update_lock);
Jean Delvaree53004e2006-01-09 23:26:14 +0100540
541 return count;
542}
543
Jean Delvare315c7112006-12-12 18:18:27 +0100544static ssize_t set_fan_target(struct device *dev, struct device_attribute
545 *devattr, const char *buf, size_t count)
546{
547 struct f71805f_data *data = dev_get_drvdata(dev);
548 struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
549 int nr = attr->index;
550 long val = simple_strtol(buf, NULL, 10);
551
552 mutex_lock(&data->update_lock);
553 data->fan_target[nr] = fan_to_reg(val);
554 f71805f_write16(data, F71805F_REG_FAN_TARGET(nr),
555 data->fan_target[nr]);
556 mutex_unlock(&data->update_lock);
557
558 return count;
559}
560
Jean Delvare95e35312006-12-12 18:18:26 +0100561static ssize_t show_pwm(struct device *dev, struct device_attribute *devattr,
562 char *buf)
563{
564 struct f71805f_data *data = f71805f_update_device(dev);
565 struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
566 int nr = attr->index;
567
568 return sprintf(buf, "%d\n", (int)data->pwm[nr]);
569}
570
571static ssize_t show_pwm_enable(struct device *dev, struct device_attribute
572 *devattr, char *buf)
573{
574 struct f71805f_data *data = f71805f_update_device(dev);
575 struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
576 int nr = attr->index;
577 int mode;
578
579 switch (data->fan_ctrl[nr] & FAN_CTRL_MODE_MASK) {
580 case FAN_CTRL_MODE_SPEED:
581 mode = 3;
582 break;
583 case FAN_CTRL_MODE_TEMPERATURE:
584 mode = 2;
585 break;
586 default: /* MANUAL */
587 mode = 1;
588 }
589
590 return sprintf(buf, "%d\n", mode);
591}
592
Jean Delvare6e2bc172006-12-12 18:18:27 +0100593static ssize_t show_pwm_freq(struct device *dev, struct device_attribute
594 *devattr, char *buf)
595{
596 struct f71805f_data *data = f71805f_update_device(dev);
597 struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
598 int nr = attr->index;
599
600 return sprintf(buf, "%lu\n", pwm_freq_from_reg(data->pwm_freq[nr]));
601}
602
Jean Delvaree1967832006-12-12 18:18:27 +0100603static ssize_t show_pwm_mode(struct device *dev, struct device_attribute
604 *devattr, char *buf)
605{
606 struct f71805f_data *data = f71805f_update_device(dev);
607 struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
608 int nr = attr->index;
609
610 return sprintf(buf, "%d\n", pwm_mode_from_reg(data->fan_ctrl[nr]));
611}
612
Jean Delvare95e35312006-12-12 18:18:26 +0100613static ssize_t set_pwm(struct device *dev, struct device_attribute *devattr,
614 const char *buf, size_t count)
615{
616 struct f71805f_data *data = dev_get_drvdata(dev);
617 struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
618 int nr = attr->index;
619 unsigned long val = simple_strtoul(buf, NULL, 10);
620
621 if (val > 255)
622 return -EINVAL;
623
624 mutex_lock(&data->update_lock);
625 data->pwm[nr] = val;
626 f71805f_write8(data, F71805F_REG_PWM_DUTY(nr), data->pwm[nr]);
627 mutex_unlock(&data->update_lock);
628
629 return count;
630}
631
632static struct attribute *f71805f_attr_pwm[];
633
634static ssize_t set_pwm_enable(struct device *dev, struct device_attribute
635 *devattr, const char *buf, size_t count)
636{
637 struct f71805f_data *data = dev_get_drvdata(dev);
638 struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
639 int nr = attr->index;
640 unsigned long val = simple_strtoul(buf, NULL, 10);
641 u8 reg;
642
643 if (val < 1 || val > 3)
644 return -EINVAL;
645
646 if (val > 1) { /* Automatic mode, user can't set PWM value */
647 if (sysfs_chmod_file(&dev->kobj, f71805f_attr_pwm[nr],
648 S_IRUGO))
649 dev_dbg(dev, "chmod -w pwm%d failed\n", nr + 1);
650 }
651
652 mutex_lock(&data->update_lock);
653 reg = f71805f_read8(data, F71805F_REG_FAN_CTRL(nr))
654 & ~FAN_CTRL_MODE_MASK;
655 switch (val) {
656 case 1:
657 reg |= FAN_CTRL_MODE_MANUAL;
658 break;
659 case 2:
660 reg |= FAN_CTRL_MODE_TEMPERATURE;
661 break;
662 case 3:
663 reg |= FAN_CTRL_MODE_SPEED;
664 break;
665 }
666 data->fan_ctrl[nr] = reg;
667 f71805f_write8(data, F71805F_REG_FAN_CTRL(nr), reg);
668 mutex_unlock(&data->update_lock);
669
670 if (val == 1) { /* Manual mode, user can set PWM value */
671 if (sysfs_chmod_file(&dev->kobj, f71805f_attr_pwm[nr],
672 S_IRUGO | S_IWUSR))
673 dev_dbg(dev, "chmod +w pwm%d failed\n", nr + 1);
674 }
675
676 return count;
677}
678
Jean Delvare6e2bc172006-12-12 18:18:27 +0100679static ssize_t set_pwm_freq(struct device *dev, struct device_attribute
680 *devattr, const char *buf, size_t count)
681{
682 struct f71805f_data *data = dev_get_drvdata(dev);
683 struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
684 int nr = attr->index;
685 unsigned long val = simple_strtoul(buf, NULL, 10);
686
687 mutex_lock(&data->update_lock);
688 data->pwm_freq[nr] = pwm_freq_to_reg(val);
689 f71805f_write8(data, F71805F_REG_PWM_FREQ(nr), data->pwm_freq[nr]);
690 mutex_unlock(&data->update_lock);
691
692 return count;
693}
694
Jean Delvaree53004e2006-01-09 23:26:14 +0100695static ssize_t show_temp(struct device *dev, struct device_attribute *devattr,
696 char *buf)
697{
698 struct f71805f_data *data = f71805f_update_device(dev);
699 struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
700 int nr = attr->index;
701
702 return sprintf(buf, "%ld\n", temp_from_reg(data->temp[nr]));
703}
704
705static ssize_t show_temp_max(struct device *dev, struct device_attribute
706 *devattr, char *buf)
707{
708 struct f71805f_data *data = f71805f_update_device(dev);
709 struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
710 int nr = attr->index;
711
712 return sprintf(buf, "%ld\n", temp_from_reg(data->temp_high[nr]));
713}
714
715static ssize_t show_temp_hyst(struct device *dev, struct device_attribute
716 *devattr, char *buf)
717{
718 struct f71805f_data *data = f71805f_update_device(dev);
719 struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
720 int nr = attr->index;
721
722 return sprintf(buf, "%ld\n", temp_from_reg(data->temp_hyst[nr]));
723}
724
725static ssize_t show_temp_type(struct device *dev, struct device_attribute
726 *devattr, char *buf)
727{
728 struct f71805f_data *data = f71805f_update_device(dev);
729 struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
730 int nr = attr->index;
731
732 /* 3 is diode, 4 is thermistor */
733 return sprintf(buf, "%u\n", (data->temp_mode & (1 << nr)) ? 3 : 4);
734}
735
736static ssize_t set_temp_max(struct device *dev, struct device_attribute
737 *devattr, const char *buf, size_t count)
738{
739 struct f71805f_data *data = dev_get_drvdata(dev);
740 struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
741 int nr = attr->index;
742 long val = simple_strtol(buf, NULL, 10);
743
Jean Delvaref0819182006-01-18 23:20:53 +0100744 mutex_lock(&data->update_lock);
Jean Delvaree53004e2006-01-09 23:26:14 +0100745 data->temp_high[nr] = temp_to_reg(val);
746 f71805f_write8(data, F71805F_REG_TEMP_HIGH(nr), data->temp_high[nr]);
Jean Delvaref0819182006-01-18 23:20:53 +0100747 mutex_unlock(&data->update_lock);
Jean Delvaree53004e2006-01-09 23:26:14 +0100748
749 return count;
750}
751
752static ssize_t set_temp_hyst(struct device *dev, struct device_attribute
753 *devattr, const char *buf, size_t count)
754{
755 struct f71805f_data *data = dev_get_drvdata(dev);
756 struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
757 int nr = attr->index;
758 long val = simple_strtol(buf, NULL, 10);
759
Jean Delvaref0819182006-01-18 23:20:53 +0100760 mutex_lock(&data->update_lock);
Jean Delvaree53004e2006-01-09 23:26:14 +0100761 data->temp_hyst[nr] = temp_to_reg(val);
762 f71805f_write8(data, F71805F_REG_TEMP_HYST(nr), data->temp_hyst[nr]);
Jean Delvaref0819182006-01-18 23:20:53 +0100763 mutex_unlock(&data->update_lock);
Jean Delvaree53004e2006-01-09 23:26:14 +0100764
765 return count;
766}
767
Jean Delvaree53004e2006-01-09 23:26:14 +0100768static ssize_t show_alarms_in(struct device *dev, struct device_attribute
769 *devattr, char *buf)
770{
771 struct f71805f_data *data = f71805f_update_device(dev);
772
Jean Delvare2d457712006-09-24 20:52:15 +0200773 return sprintf(buf, "%lu\n", data->alarms & 0x1ff);
Jean Delvaree53004e2006-01-09 23:26:14 +0100774}
775
776static ssize_t show_alarms_fan(struct device *dev, struct device_attribute
777 *devattr, char *buf)
778{
779 struct f71805f_data *data = f71805f_update_device(dev);
780
Jean Delvare2d457712006-09-24 20:52:15 +0200781 return sprintf(buf, "%lu\n", (data->alarms >> 16) & 0x07);
Jean Delvaree53004e2006-01-09 23:26:14 +0100782}
783
784static ssize_t show_alarms_temp(struct device *dev, struct device_attribute
785 *devattr, char *buf)
786{
787 struct f71805f_data *data = f71805f_update_device(dev);
788
Jean Delvare2d457712006-09-24 20:52:15 +0200789 return sprintf(buf, "%lu\n", (data->alarms >> 11) & 0x07);
790}
791
792static ssize_t show_alarm(struct device *dev, struct device_attribute
793 *devattr, char *buf)
794{
795 struct f71805f_data *data = f71805f_update_device(dev);
796 struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
797 int bitnr = attr->index;
798
799 return sprintf(buf, "%lu\n", (data->alarms >> bitnr) & 1);
Jean Delvaree53004e2006-01-09 23:26:14 +0100800}
801
Jean Delvaree53004e2006-01-09 23:26:14 +0100802static ssize_t show_name(struct device *dev, struct device_attribute
803 *devattr, char *buf)
804{
805 struct f71805f_data *data = dev_get_drvdata(dev);
806
807 return sprintf(buf, "%s\n", data->name);
808}
809
Jean Delvare0e39e012006-09-24 21:16:40 +0200810static DEVICE_ATTR(in0_input, S_IRUGO, show_in0, NULL);
811static DEVICE_ATTR(in0_max, S_IRUGO| S_IWUSR, show_in0_max, set_in0_max);
812static DEVICE_ATTR(in0_min, S_IRUGO| S_IWUSR, show_in0_min, set_in0_min);
813static SENSOR_DEVICE_ATTR(in1_input, S_IRUGO, show_in, NULL, 1);
814static SENSOR_DEVICE_ATTR(in1_max, S_IRUGO | S_IWUSR,
815 show_in_max, set_in_max, 1);
816static SENSOR_DEVICE_ATTR(in1_min, S_IRUGO | S_IWUSR,
817 show_in_min, set_in_min, 1);
818static SENSOR_DEVICE_ATTR(in2_input, S_IRUGO, show_in, NULL, 2);
819static SENSOR_DEVICE_ATTR(in2_max, S_IRUGO | S_IWUSR,
820 show_in_max, set_in_max, 2);
821static SENSOR_DEVICE_ATTR(in2_min, S_IRUGO | S_IWUSR,
822 show_in_min, set_in_min, 2);
823static SENSOR_DEVICE_ATTR(in3_input, S_IRUGO, show_in, NULL, 3);
824static SENSOR_DEVICE_ATTR(in3_max, S_IRUGO | S_IWUSR,
825 show_in_max, set_in_max, 3);
826static SENSOR_DEVICE_ATTR(in3_min, S_IRUGO | S_IWUSR,
827 show_in_min, set_in_min, 3);
828static SENSOR_DEVICE_ATTR(in4_input, S_IRUGO, show_in, NULL, 4);
829static SENSOR_DEVICE_ATTR(in4_max, S_IRUGO | S_IWUSR,
830 show_in_max, set_in_max, 4);
831static SENSOR_DEVICE_ATTR(in4_min, S_IRUGO | S_IWUSR,
832 show_in_min, set_in_min, 4);
833static SENSOR_DEVICE_ATTR(in5_input, S_IRUGO, show_in, NULL, 5);
834static SENSOR_DEVICE_ATTR(in5_max, S_IRUGO | S_IWUSR,
835 show_in_max, set_in_max, 5);
836static SENSOR_DEVICE_ATTR(in5_min, S_IRUGO | S_IWUSR,
837 show_in_min, set_in_min, 5);
838static SENSOR_DEVICE_ATTR(in6_input, S_IRUGO, show_in, NULL, 6);
839static SENSOR_DEVICE_ATTR(in6_max, S_IRUGO | S_IWUSR,
840 show_in_max, set_in_max, 6);
841static SENSOR_DEVICE_ATTR(in6_min, S_IRUGO | S_IWUSR,
842 show_in_min, set_in_min, 6);
843static SENSOR_DEVICE_ATTR(in7_input, S_IRUGO, show_in, NULL, 7);
844static SENSOR_DEVICE_ATTR(in7_max, S_IRUGO | S_IWUSR,
845 show_in_max, set_in_max, 7);
846static SENSOR_DEVICE_ATTR(in7_min, S_IRUGO | S_IWUSR,
847 show_in_min, set_in_min, 7);
848static SENSOR_DEVICE_ATTR(in8_input, S_IRUGO, show_in, NULL, 8);
849static SENSOR_DEVICE_ATTR(in8_max, S_IRUGO | S_IWUSR,
850 show_in_max, set_in_max, 8);
851static SENSOR_DEVICE_ATTR(in8_min, S_IRUGO | S_IWUSR,
852 show_in_min, set_in_min, 8);
853
854static SENSOR_DEVICE_ATTR(fan1_input, S_IRUGO, show_fan, NULL, 0);
855static SENSOR_DEVICE_ATTR(fan1_min, S_IRUGO | S_IWUSR,
856 show_fan_min, set_fan_min, 0);
Jean Delvare315c7112006-12-12 18:18:27 +0100857static SENSOR_DEVICE_ATTR(fan1_target, S_IRUGO | S_IWUSR,
858 show_fan_target, set_fan_target, 0);
Jean Delvare0e39e012006-09-24 21:16:40 +0200859static SENSOR_DEVICE_ATTR(fan2_input, S_IRUGO, show_fan, NULL, 1);
860static SENSOR_DEVICE_ATTR(fan2_min, S_IRUGO | S_IWUSR,
861 show_fan_min, set_fan_min, 1);
Jean Delvare315c7112006-12-12 18:18:27 +0100862static SENSOR_DEVICE_ATTR(fan2_target, S_IRUGO | S_IWUSR,
863 show_fan_target, set_fan_target, 1);
Jean Delvare0e39e012006-09-24 21:16:40 +0200864static SENSOR_DEVICE_ATTR(fan3_input, S_IRUGO, show_fan, NULL, 2);
865static SENSOR_DEVICE_ATTR(fan3_min, S_IRUGO | S_IWUSR,
866 show_fan_min, set_fan_min, 2);
Jean Delvare315c7112006-12-12 18:18:27 +0100867static SENSOR_DEVICE_ATTR(fan3_target, S_IRUGO | S_IWUSR,
868 show_fan_target, set_fan_target, 2);
Jean Delvare0e39e012006-09-24 21:16:40 +0200869
870static SENSOR_DEVICE_ATTR(temp1_input, S_IRUGO, show_temp, NULL, 0);
871static SENSOR_DEVICE_ATTR(temp1_max, S_IRUGO | S_IWUSR,
872 show_temp_max, set_temp_max, 0);
873static SENSOR_DEVICE_ATTR(temp1_max_hyst, S_IRUGO | S_IWUSR,
874 show_temp_hyst, set_temp_hyst, 0);
875static SENSOR_DEVICE_ATTR(temp1_type, S_IRUGO, show_temp_type, NULL, 0);
876static SENSOR_DEVICE_ATTR(temp2_input, S_IRUGO, show_temp, NULL, 1);
877static SENSOR_DEVICE_ATTR(temp2_max, S_IRUGO | S_IWUSR,
878 show_temp_max, set_temp_max, 1);
879static SENSOR_DEVICE_ATTR(temp2_max_hyst, S_IRUGO | S_IWUSR,
880 show_temp_hyst, set_temp_hyst, 1);
881static SENSOR_DEVICE_ATTR(temp2_type, S_IRUGO, show_temp_type, NULL, 1);
882static SENSOR_DEVICE_ATTR(temp3_input, S_IRUGO, show_temp, NULL, 2);
883static SENSOR_DEVICE_ATTR(temp3_max, S_IRUGO | S_IWUSR,
884 show_temp_max, set_temp_max, 2);
885static SENSOR_DEVICE_ATTR(temp3_max_hyst, S_IRUGO | S_IWUSR,
886 show_temp_hyst, set_temp_hyst, 2);
887static SENSOR_DEVICE_ATTR(temp3_type, S_IRUGO, show_temp_type, NULL, 2);
888
Jean Delvare95e35312006-12-12 18:18:26 +0100889/* pwm (value) files are created read-only, write permission is
890 then added or removed dynamically as needed */
891static SENSOR_DEVICE_ATTR(pwm1, S_IRUGO, show_pwm, set_pwm, 0);
892static SENSOR_DEVICE_ATTR(pwm1_enable, S_IRUGO | S_IWUSR,
893 show_pwm_enable, set_pwm_enable, 0);
Jean Delvare6e2bc172006-12-12 18:18:27 +0100894static SENSOR_DEVICE_ATTR(pwm1_freq, S_IRUGO | S_IWUSR,
895 show_pwm_freq, set_pwm_freq, 0);
Jean Delvaree1967832006-12-12 18:18:27 +0100896static SENSOR_DEVICE_ATTR(pwm1_mode, S_IRUGO, show_pwm_mode, NULL, 0);
Jean Delvare95e35312006-12-12 18:18:26 +0100897static SENSOR_DEVICE_ATTR(pwm2, S_IRUGO, show_pwm, set_pwm, 1);
898static SENSOR_DEVICE_ATTR(pwm2_enable, S_IRUGO | S_IWUSR,
899 show_pwm_enable, set_pwm_enable, 1);
Jean Delvare6e2bc172006-12-12 18:18:27 +0100900static SENSOR_DEVICE_ATTR(pwm2_freq, S_IRUGO | S_IWUSR,
901 show_pwm_freq, set_pwm_freq, 1);
Jean Delvaree1967832006-12-12 18:18:27 +0100902static SENSOR_DEVICE_ATTR(pwm2_mode, S_IRUGO, show_pwm_mode, NULL, 1);
Jean Delvare95e35312006-12-12 18:18:26 +0100903static SENSOR_DEVICE_ATTR(pwm3, S_IRUGO, show_pwm, set_pwm, 2);
904static SENSOR_DEVICE_ATTR(pwm3_enable, S_IRUGO | S_IWUSR,
905 show_pwm_enable, set_pwm_enable, 2);
Jean Delvare6e2bc172006-12-12 18:18:27 +0100906static SENSOR_DEVICE_ATTR(pwm3_freq, S_IRUGO | S_IWUSR,
907 show_pwm_freq, set_pwm_freq, 2);
Jean Delvaree1967832006-12-12 18:18:27 +0100908static SENSOR_DEVICE_ATTR(pwm3_mode, S_IRUGO, show_pwm_mode, NULL, 2);
Jean Delvare95e35312006-12-12 18:18:26 +0100909
Jean Delvare0e39e012006-09-24 21:16:40 +0200910static SENSOR_DEVICE_ATTR(in0_alarm, S_IRUGO, show_alarm, NULL, 0);
911static SENSOR_DEVICE_ATTR(in1_alarm, S_IRUGO, show_alarm, NULL, 1);
912static SENSOR_DEVICE_ATTR(in2_alarm, S_IRUGO, show_alarm, NULL, 2);
913static SENSOR_DEVICE_ATTR(in3_alarm, S_IRUGO, show_alarm, NULL, 3);
914static SENSOR_DEVICE_ATTR(in4_alarm, S_IRUGO, show_alarm, NULL, 4);
915static SENSOR_DEVICE_ATTR(in5_alarm, S_IRUGO, show_alarm, NULL, 5);
916static SENSOR_DEVICE_ATTR(in6_alarm, S_IRUGO, show_alarm, NULL, 6);
917static SENSOR_DEVICE_ATTR(in7_alarm, S_IRUGO, show_alarm, NULL, 7);
918static SENSOR_DEVICE_ATTR(in8_alarm, S_IRUGO, show_alarm, NULL, 8);
919static SENSOR_DEVICE_ATTR(temp1_alarm, S_IRUGO, show_alarm, NULL, 11);
920static SENSOR_DEVICE_ATTR(temp2_alarm, S_IRUGO, show_alarm, NULL, 12);
921static SENSOR_DEVICE_ATTR(temp3_alarm, S_IRUGO, show_alarm, NULL, 13);
922static SENSOR_DEVICE_ATTR(fan1_alarm, S_IRUGO, show_alarm, NULL, 16);
923static SENSOR_DEVICE_ATTR(fan2_alarm, S_IRUGO, show_alarm, NULL, 17);
924static SENSOR_DEVICE_ATTR(fan3_alarm, S_IRUGO, show_alarm, NULL, 18);
925static DEVICE_ATTR(alarms_in, S_IRUGO, show_alarms_in, NULL);
926static DEVICE_ATTR(alarms_fan, S_IRUGO, show_alarms_fan, NULL);
927static DEVICE_ATTR(alarms_temp, S_IRUGO, show_alarms_temp, NULL);
928
929static DEVICE_ATTR(name, S_IRUGO, show_name, NULL);
930
931static struct attribute *f71805f_attributes[] = {
932 &dev_attr_in0_input.attr,
933 &dev_attr_in0_max.attr,
934 &dev_attr_in0_min.attr,
935 &sensor_dev_attr_in1_input.dev_attr.attr,
936 &sensor_dev_attr_in1_max.dev_attr.attr,
937 &sensor_dev_attr_in1_min.dev_attr.attr,
938 &sensor_dev_attr_in2_input.dev_attr.attr,
939 &sensor_dev_attr_in2_max.dev_attr.attr,
940 &sensor_dev_attr_in2_min.dev_attr.attr,
941 &sensor_dev_attr_in3_input.dev_attr.attr,
942 &sensor_dev_attr_in3_max.dev_attr.attr,
943 &sensor_dev_attr_in3_min.dev_attr.attr,
944 &sensor_dev_attr_in4_input.dev_attr.attr,
945 &sensor_dev_attr_in4_max.dev_attr.attr,
946 &sensor_dev_attr_in4_min.dev_attr.attr,
947 &sensor_dev_attr_in5_input.dev_attr.attr,
948 &sensor_dev_attr_in5_max.dev_attr.attr,
949 &sensor_dev_attr_in5_min.dev_attr.attr,
950 &sensor_dev_attr_in6_input.dev_attr.attr,
951 &sensor_dev_attr_in6_max.dev_attr.attr,
952 &sensor_dev_attr_in6_min.dev_attr.attr,
953 &sensor_dev_attr_in7_input.dev_attr.attr,
954 &sensor_dev_attr_in7_max.dev_attr.attr,
955 &sensor_dev_attr_in7_min.dev_attr.attr,
956 &sensor_dev_attr_in8_input.dev_attr.attr,
957 &sensor_dev_attr_in8_max.dev_attr.attr,
958 &sensor_dev_attr_in8_min.dev_attr.attr,
959
960 &sensor_dev_attr_temp1_input.dev_attr.attr,
961 &sensor_dev_attr_temp1_max.dev_attr.attr,
962 &sensor_dev_attr_temp1_max_hyst.dev_attr.attr,
963 &sensor_dev_attr_temp1_type.dev_attr.attr,
964 &sensor_dev_attr_temp2_input.dev_attr.attr,
965 &sensor_dev_attr_temp2_max.dev_attr.attr,
966 &sensor_dev_attr_temp2_max_hyst.dev_attr.attr,
967 &sensor_dev_attr_temp2_type.dev_attr.attr,
968 &sensor_dev_attr_temp3_input.dev_attr.attr,
969 &sensor_dev_attr_temp3_max.dev_attr.attr,
970 &sensor_dev_attr_temp3_max_hyst.dev_attr.attr,
971 &sensor_dev_attr_temp3_type.dev_attr.attr,
972
973 &sensor_dev_attr_in0_alarm.dev_attr.attr,
974 &sensor_dev_attr_in1_alarm.dev_attr.attr,
975 &sensor_dev_attr_in2_alarm.dev_attr.attr,
976 &sensor_dev_attr_in3_alarm.dev_attr.attr,
977 &sensor_dev_attr_in4_alarm.dev_attr.attr,
978 &sensor_dev_attr_in5_alarm.dev_attr.attr,
979 &sensor_dev_attr_in6_alarm.dev_attr.attr,
980 &sensor_dev_attr_in7_alarm.dev_attr.attr,
981 &sensor_dev_attr_in8_alarm.dev_attr.attr,
982 &dev_attr_alarms_in.attr,
983 &sensor_dev_attr_temp1_alarm.dev_attr.attr,
984 &sensor_dev_attr_temp2_alarm.dev_attr.attr,
985 &sensor_dev_attr_temp3_alarm.dev_attr.attr,
986 &dev_attr_alarms_temp.attr,
987 &dev_attr_alarms_fan.attr,
988
989 &dev_attr_name.attr,
990 NULL
Jean Delvare2488a392006-01-09 23:29:11 +0100991};
992
Jean Delvare0e39e012006-09-24 21:16:40 +0200993static const struct attribute_group f71805f_group = {
994 .attrs = f71805f_attributes,
Jean Delvare2488a392006-01-09 23:29:11 +0100995};
996
Jean Delvare315c7112006-12-12 18:18:27 +0100997static struct attribute *f71805f_attributes_fan[3][8] = {
Jean Delvare0e39e012006-09-24 21:16:40 +0200998 {
999 &sensor_dev_attr_fan1_input.dev_attr.attr,
1000 &sensor_dev_attr_fan1_min.dev_attr.attr,
1001 &sensor_dev_attr_fan1_alarm.dev_attr.attr,
Jean Delvare315c7112006-12-12 18:18:27 +01001002 &sensor_dev_attr_fan1_target.dev_attr.attr,
Jean Delvare95e35312006-12-12 18:18:26 +01001003 &sensor_dev_attr_pwm1.dev_attr.attr,
1004 &sensor_dev_attr_pwm1_enable.dev_attr.attr,
Jean Delvaree1967832006-12-12 18:18:27 +01001005 &sensor_dev_attr_pwm1_mode.dev_attr.attr,
Jean Delvare0e39e012006-09-24 21:16:40 +02001006 NULL
1007 }, {
1008 &sensor_dev_attr_fan2_input.dev_attr.attr,
1009 &sensor_dev_attr_fan2_min.dev_attr.attr,
1010 &sensor_dev_attr_fan2_alarm.dev_attr.attr,
Jean Delvare315c7112006-12-12 18:18:27 +01001011 &sensor_dev_attr_fan2_target.dev_attr.attr,
Jean Delvare95e35312006-12-12 18:18:26 +01001012 &sensor_dev_attr_pwm2.dev_attr.attr,
1013 &sensor_dev_attr_pwm2_enable.dev_attr.attr,
Jean Delvaree1967832006-12-12 18:18:27 +01001014 &sensor_dev_attr_pwm2_mode.dev_attr.attr,
Jean Delvare0e39e012006-09-24 21:16:40 +02001015 NULL
1016 }, {
1017 &sensor_dev_attr_fan3_input.dev_attr.attr,
1018 &sensor_dev_attr_fan3_min.dev_attr.attr,
1019 &sensor_dev_attr_fan3_alarm.dev_attr.attr,
Jean Delvare315c7112006-12-12 18:18:27 +01001020 &sensor_dev_attr_fan3_target.dev_attr.attr,
Jean Delvare95e35312006-12-12 18:18:26 +01001021 &sensor_dev_attr_pwm3.dev_attr.attr,
1022 &sensor_dev_attr_pwm3_enable.dev_attr.attr,
Jean Delvaree1967832006-12-12 18:18:27 +01001023 &sensor_dev_attr_pwm3_mode.dev_attr.attr,
Jean Delvare0e39e012006-09-24 21:16:40 +02001024 NULL
1025 }
1026};
1027
1028static const struct attribute_group f71805f_group_fan[3] = {
1029 { .attrs = f71805f_attributes_fan[0] },
1030 { .attrs = f71805f_attributes_fan[1] },
1031 { .attrs = f71805f_attributes_fan[2] },
Jean Delvare2488a392006-01-09 23:29:11 +01001032};
Jean Delvaree53004e2006-01-09 23:26:14 +01001033
Jean Delvaree1967832006-12-12 18:18:27 +01001034/* We don't include pwm_freq files in the arrays above, because they must be
1035 created conditionally (only if pwm_mode is 1 == PWM) */
1036static struct attribute *f71805f_attributes_pwm_freq[] = {
1037 &sensor_dev_attr_pwm1_freq.dev_attr.attr,
1038 &sensor_dev_attr_pwm2_freq.dev_attr.attr,
1039 &sensor_dev_attr_pwm3_freq.dev_attr.attr,
1040 NULL
1041};
1042
1043static const struct attribute_group f71805f_group_pwm_freq = {
1044 .attrs = f71805f_attributes_pwm_freq,
1045};
1046
Jean Delvare95e35312006-12-12 18:18:26 +01001047/* We also need an indexed access to pwmN files to toggle writability */
1048static struct attribute *f71805f_attr_pwm[] = {
1049 &sensor_dev_attr_pwm1.dev_attr.attr,
1050 &sensor_dev_attr_pwm2.dev_attr.attr,
1051 &sensor_dev_attr_pwm3.dev_attr.attr,
1052};
1053
Jean Delvaree53004e2006-01-09 23:26:14 +01001054/*
1055 * Device registration and initialization
1056 */
1057
1058static void __devinit f71805f_init_device(struct f71805f_data *data)
1059{
1060 u8 reg;
1061 int i;
1062
1063 reg = f71805f_read8(data, F71805F_REG_START);
1064 if ((reg & 0x41) != 0x01) {
1065 printk(KERN_DEBUG DRVNAME ": Starting monitoring "
1066 "operations\n");
1067 f71805f_write8(data, F71805F_REG_START, (reg | 0x01) & ~0x40);
1068 }
1069
1070 /* Fan monitoring can be disabled. If it is, we won't be polling
1071 the register values, and won't create the related sysfs files. */
1072 for (i = 0; i < 3; i++) {
Jean Delvare6b14a542006-12-12 18:18:26 +01001073 data->fan_ctrl[i] = f71805f_read8(data,
1074 F71805F_REG_FAN_CTRL(i));
Jean Delvare315c7112006-12-12 18:18:27 +01001075 /* Clear latch full bit, else "speed mode" fan speed control
1076 doesn't work */
1077 if (data->fan_ctrl[i] & FAN_CTRL_LATCH_FULL) {
1078 data->fan_ctrl[i] &= ~FAN_CTRL_LATCH_FULL;
1079 f71805f_write8(data, F71805F_REG_FAN_CTRL(i),
1080 data->fan_ctrl[i]);
1081 }
Jean Delvaree53004e2006-01-09 23:26:14 +01001082 }
1083}
1084
1085static int __devinit f71805f_probe(struct platform_device *pdev)
1086{
1087 struct f71805f_data *data;
1088 struct resource *res;
Jean Delvare2488a392006-01-09 23:29:11 +01001089 int i, err;
Jean Delvaree53004e2006-01-09 23:26:14 +01001090
1091 if (!(data = kzalloc(sizeof(struct f71805f_data), GFP_KERNEL))) {
1092 err = -ENOMEM;
1093 printk(KERN_ERR DRVNAME ": Out of memory\n");
1094 goto exit;
1095 }
1096
1097 res = platform_get_resource(pdev, IORESOURCE_IO, 0);
1098 data->addr = res->start;
Jean Delvaref0819182006-01-18 23:20:53 +01001099 mutex_init(&data->lock);
Jean Delvaree53004e2006-01-09 23:26:14 +01001100 data->name = "f71805f";
Jean Delvaref0819182006-01-18 23:20:53 +01001101 mutex_init(&data->update_lock);
Jean Delvaree53004e2006-01-09 23:26:14 +01001102
1103 platform_set_drvdata(pdev, data);
1104
Jean Delvaree53004e2006-01-09 23:26:14 +01001105 /* Initialize the F71805F chip */
1106 f71805f_init_device(data);
1107
1108 /* Register sysfs interface files */
Jean Delvare0e39e012006-09-24 21:16:40 +02001109 if ((err = sysfs_create_group(&pdev->dev.kobj, &f71805f_group)))
1110 goto exit_free;
1111 for (i = 0; i < 3; i++) {
Jean Delvare6b14a542006-12-12 18:18:26 +01001112 if (data->fan_ctrl[i] & FAN_CTRL_SKIP)
Jean Delvare2488a392006-01-09 23:29:11 +01001113 continue;
Jean Delvare0e39e012006-09-24 21:16:40 +02001114 if ((err = sysfs_create_group(&pdev->dev.kobj,
1115 &f71805f_group_fan[i])))
1116 goto exit_remove_files;
Jean Delvaree1967832006-12-12 18:18:27 +01001117 /* If control mode is PWM, create pwm_freq file */
1118 if (!(data->fan_ctrl[i] & FAN_CTRL_DC_MODE)) {
1119 if ((err = sysfs_create_file(&pdev->dev.kobj,
1120 f71805f_attributes_pwm_freq[i])))
1121 goto exit_remove_files;
1122 }
Jean Delvare95e35312006-12-12 18:18:26 +01001123 /* If PWM is in manual mode, add write permission */
1124 if (data->fan_ctrl[i] & FAN_CTRL_MODE_MANUAL) {
1125 if ((err = sysfs_chmod_file(&pdev->dev.kobj,
1126 f71805f_attr_pwm[i],
1127 S_IRUGO | S_IWUSR))) {
1128 dev_err(&pdev->dev, "chmod +w pwm%d failed\n",
1129 i + 1);
1130 goto exit_remove_files;
1131 }
1132 }
Jean Delvare0e39e012006-09-24 21:16:40 +02001133 }
1134
1135 data->class_dev = hwmon_device_register(&pdev->dev);
1136 if (IS_ERR(data->class_dev)) {
1137 err = PTR_ERR(data->class_dev);
1138 dev_err(&pdev->dev, "Class registration failed (%d)\n", err);
1139 goto exit_remove_files;
Jean Delvaree53004e2006-01-09 23:26:14 +01001140 }
Jean Delvaree53004e2006-01-09 23:26:14 +01001141
1142 return 0;
1143
Jean Delvare0e39e012006-09-24 21:16:40 +02001144exit_remove_files:
1145 sysfs_remove_group(&pdev->dev.kobj, &f71805f_group);
1146 for (i = 0; i < 3; i++)
1147 sysfs_remove_group(&pdev->dev.kobj, &f71805f_group_fan[i]);
Jean Delvaree1967832006-12-12 18:18:27 +01001148 sysfs_remove_group(&pdev->dev.kobj, &f71805f_group_pwm_freq);
Jean Delvaree53004e2006-01-09 23:26:14 +01001149exit_free:
Jean Delvare0e39e012006-09-24 21:16:40 +02001150 platform_set_drvdata(pdev, NULL);
Jean Delvaree53004e2006-01-09 23:26:14 +01001151 kfree(data);
1152exit:
1153 return err;
1154}
1155
1156static int __devexit f71805f_remove(struct platform_device *pdev)
1157{
1158 struct f71805f_data *data = platform_get_drvdata(pdev);
Jean Delvare0e39e012006-09-24 21:16:40 +02001159 int i;
Jean Delvaree53004e2006-01-09 23:26:14 +01001160
1161 platform_set_drvdata(pdev, NULL);
1162 hwmon_device_unregister(data->class_dev);
Jean Delvare0e39e012006-09-24 21:16:40 +02001163 sysfs_remove_group(&pdev->dev.kobj, &f71805f_group);
1164 for (i = 0; i < 3; i++)
1165 sysfs_remove_group(&pdev->dev.kobj, &f71805f_group_fan[i]);
Jean Delvaree1967832006-12-12 18:18:27 +01001166 sysfs_remove_group(&pdev->dev.kobj, &f71805f_group_pwm_freq);
Jean Delvaree53004e2006-01-09 23:26:14 +01001167 kfree(data);
1168
1169 return 0;
1170}
1171
1172static struct platform_driver f71805f_driver = {
1173 .driver = {
1174 .owner = THIS_MODULE,
1175 .name = DRVNAME,
1176 },
1177 .probe = f71805f_probe,
1178 .remove = __devexit_p(f71805f_remove),
1179};
1180
1181static int __init f71805f_device_add(unsigned short address)
1182{
Jean Delvare568825c2006-03-23 16:40:23 +01001183 struct resource res = {
1184 .start = address,
1185 .end = address + REGION_LENGTH - 1,
1186 .flags = IORESOURCE_IO,
1187 };
Jean Delvaree53004e2006-01-09 23:26:14 +01001188 int err;
1189
1190 pdev = platform_device_alloc(DRVNAME, address);
1191 if (!pdev) {
1192 err = -ENOMEM;
1193 printk(KERN_ERR DRVNAME ": Device allocation failed\n");
1194 goto exit;
1195 }
1196
Jean Delvare568825c2006-03-23 16:40:23 +01001197 res.name = pdev->name;
1198 err = platform_device_add_resources(pdev, &res, 1);
Jean Delvaree53004e2006-01-09 23:26:14 +01001199 if (err) {
1200 printk(KERN_ERR DRVNAME ": Device resource addition failed "
1201 "(%d)\n", err);
1202 goto exit_device_put;
1203 }
1204
1205 err = platform_device_add(pdev);
1206 if (err) {
1207 printk(KERN_ERR DRVNAME ": Device addition failed (%d)\n",
1208 err);
1209 goto exit_device_put;
1210 }
1211
1212 return 0;
1213
1214exit_device_put:
1215 platform_device_put(pdev);
1216exit:
1217 return err;
1218}
1219
1220static int __init f71805f_find(int sioaddr, unsigned short *address)
1221{
1222 int err = -ENODEV;
1223 u16 devid;
1224
1225 superio_enter(sioaddr);
1226
1227 devid = superio_inw(sioaddr, SIO_REG_MANID);
1228 if (devid != SIO_FINTEK_ID)
1229 goto exit;
1230
1231 devid = superio_inw(sioaddr, SIO_REG_DEVID);
1232 if (devid != SIO_F71805F_ID) {
1233 printk(KERN_INFO DRVNAME ": Unsupported Fintek device, "
1234 "skipping\n");
1235 goto exit;
1236 }
1237
1238 superio_select(sioaddr, F71805F_LD_HWM);
1239 if (!(superio_inb(sioaddr, SIO_REG_ENABLE) & 0x01)) {
1240 printk(KERN_WARNING DRVNAME ": Device not activated, "
1241 "skipping\n");
1242 goto exit;
1243 }
1244
1245 *address = superio_inw(sioaddr, SIO_REG_ADDR);
1246 if (*address == 0) {
1247 printk(KERN_WARNING DRVNAME ": Base address not set, "
1248 "skipping\n");
1249 goto exit;
1250 }
1251
1252 err = 0;
1253 printk(KERN_INFO DRVNAME ": Found F71805F chip at %#x, revision %u\n",
1254 *address, superio_inb(sioaddr, SIO_REG_DEVREV));
1255
1256exit:
1257 superio_exit(sioaddr);
1258 return err;
1259}
1260
1261static int __init f71805f_init(void)
1262{
1263 int err;
1264 unsigned short address;
1265
1266 if (f71805f_find(0x2e, &address)
1267 && f71805f_find(0x4e, &address))
1268 return -ENODEV;
1269
1270 err = platform_driver_register(&f71805f_driver);
1271 if (err)
1272 goto exit;
1273
1274 /* Sets global pdev as a side effect */
1275 err = f71805f_device_add(address);
1276 if (err)
1277 goto exit_driver;
1278
1279 return 0;
1280
1281exit_driver:
1282 platform_driver_unregister(&f71805f_driver);
1283exit:
1284 return err;
1285}
1286
1287static void __exit f71805f_exit(void)
1288{
1289 platform_device_unregister(pdev);
1290 platform_driver_unregister(&f71805f_driver);
1291}
1292
1293MODULE_AUTHOR("Jean Delvare <khali@linux-fr>");
1294MODULE_LICENSE("GPL");
1295MODULE_DESCRIPTION("F71805F hardware monitoring driver");
1296
1297module_init(f71805f_init);
1298module_exit(f71805f_exit);