blob: ca07a32447c23406ef8e39523eb1830d42d56286 [file] [log] [blame]
Hans de Goede45fb3662007-07-13 14:34:19 +02001/***************************************************************************
2 * Copyright (C) 2006 by Hans Edgington <hans@edgington.nl> *
Hans de Goede44c4dc52011-03-09 20:57:07 +01003 * Copyright (C) 2007-2011 Hans de Goede <hdegoede@redhat.com> *
Hans de Goede45fb3662007-07-13 14:34:19 +02004 * *
5 * This program is free software; you can redistribute it and/or modify *
6 * it under the terms of the GNU General Public License as published by *
7 * the Free Software Foundation; either version 2 of the License, or *
8 * (at your option) any later version. *
9 * *
10 * This program is distributed in the hope that it will be useful, *
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
13 * GNU General Public License for more details. *
14 * *
15 * You should have received a copy of the GNU General Public License *
16 * along with this program; if not, write to the *
17 * Free Software Foundation, Inc., *
18 * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
19 ***************************************************************************/
20
Joe Perches22d3b412010-10-20 06:51:34 +000021#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
22
Hans de Goede45fb3662007-07-13 14:34:19 +020023#include <linux/module.h>
24#include <linux/init.h>
25#include <linux/slab.h>
26#include <linux/jiffies.h>
27#include <linux/platform_device.h>
28#include <linux/hwmon.h>
29#include <linux/hwmon-sysfs.h>
30#include <linux/err.h>
31#include <linux/mutex.h>
Mark van Doesburg77a4a3e2009-01-07 16:37:27 +010032#include <linux/io.h>
Jean Delvareb9acb642009-01-07 16:37:35 +010033#include <linux/acpi.h>
Hans de Goede45fb3662007-07-13 14:34:19 +020034
35#define DRVNAME "f71882fg"
36
Hans de Goede09475d32009-06-15 18:39:52 +020037#define SIO_F71858FG_LD_HWM 0x02 /* Hardware monitor logical device */
Mark van Doesburg77a4a3e2009-01-07 16:37:27 +010038#define SIO_F71882FG_LD_HWM 0x04 /* Hardware monitor logical device */
Hans de Goede45fb3662007-07-13 14:34:19 +020039#define SIO_UNLOCK_KEY 0x87 /* Key to enable Super-I/O */
Hans de Goede14a40192011-03-13 13:50:32 +010040#define SIO_LOCK_KEY 0xAA /* Key to disable Super-I/O */
Hans de Goede45fb3662007-07-13 14:34:19 +020041
42#define SIO_REG_LDSEL 0x07 /* Logical device select */
43#define SIO_REG_DEVID 0x20 /* Device ID (2 bytes) */
44#define SIO_REG_DEVREV 0x22 /* Device revision */
45#define SIO_REG_MANID 0x23 /* Fintek ID (2 bytes) */
46#define SIO_REG_ENABLE 0x30 /* Logical device enable */
47#define SIO_REG_ADDR 0x60 /* Logical device address (2 bytes) */
48
49#define SIO_FINTEK_ID 0x1934 /* Manufacturers ID */
Hans de Goedee5e713c2011-03-10 08:54:02 +010050#define SIO_F71808E_ID 0x0901 /* Chipset ID */
Hans de Goede09475d32009-06-15 18:39:52 +020051#define SIO_F71858_ID 0x0507 /* Chipset ID */
Hans de Goede498be962009-01-07 16:37:28 +010052#define SIO_F71862_ID 0x0601 /* Chipset ID */
Hans de Goedec11bb992011-03-09 20:57:15 +010053#define SIO_F71869_ID 0x0814 /* Chipset ID */
Hans de Goede45fb3662007-07-13 14:34:19 +020054#define SIO_F71882_ID 0x0541 /* Chipset ID */
Hans de Goede76698962009-12-09 20:36:01 +010055#define SIO_F71889_ID 0x0723 /* Chipset ID */
Hans de Goede3cad4022011-03-09 20:57:14 +010056#define SIO_F71889E_ID 0x0909 /* Chipset ID */
Hans de Goedea66c1082011-03-26 10:45:02 +010057#define SIO_F71889A_ID 0x1005 /* Chipset ID */
Hans de Goedeed4f7c22009-01-07 16:37:30 +010058#define SIO_F8000_ID 0x0581 /* Chipset ID */
Jean Delvare383586b2011-03-26 10:45:02 +010059#define SIO_F81865_ID 0x0704 /* Chipset ID */
Hans de Goede45fb3662007-07-13 14:34:19 +020060
61#define REGION_LENGTH 8
62#define ADDR_REG_OFFSET 5
63#define DATA_REG_OFFSET 6
64
Hans de Goede3cad4022011-03-09 20:57:14 +010065#define F71882FG_REG_IN_STATUS 0x12 /* f7188x only */
66#define F71882FG_REG_IN_BEEP 0x13 /* f7188x only */
Hans de Goede45fb3662007-07-13 14:34:19 +020067#define F71882FG_REG_IN(nr) (0x20 + (nr))
Hans de Goede3cad4022011-03-09 20:57:14 +010068#define F71882FG_REG_IN1_HIGH 0x32 /* f7188x only */
Hans de Goede45fb3662007-07-13 14:34:19 +020069
70#define F71882FG_REG_FAN(nr) (0xA0 + (16 * (nr)))
Mark van Doesburg9ab796e2009-01-07 16:37:27 +010071#define F71882FG_REG_FAN_TARGET(nr) (0xA2 + (16 * (nr)))
72#define F71882FG_REG_FAN_FULL_SPEED(nr) (0xA4 + (16 * (nr)))
Hans de Goede45fb3662007-07-13 14:34:19 +020073#define F71882FG_REG_FAN_STATUS 0x92
74#define F71882FG_REG_FAN_BEEP 0x93
75
Hans de Goede7567a042009-01-07 16:37:28 +010076#define F71882FG_REG_TEMP(nr) (0x70 + 2 * (nr))
77#define F71882FG_REG_TEMP_OVT(nr) (0x80 + 2 * (nr))
78#define F71882FG_REG_TEMP_HIGH(nr) (0x81 + 2 * (nr))
Hans de Goede45fb3662007-07-13 14:34:19 +020079#define F71882FG_REG_TEMP_STATUS 0x62
80#define F71882FG_REG_TEMP_BEEP 0x63
Hans de Goede09475d32009-06-15 18:39:52 +020081#define F71882FG_REG_TEMP_CONFIG 0x69
Hans de Goedebc274902009-01-07 16:37:29 +010082#define F71882FG_REG_TEMP_HYST(nr) (0x6C + (nr))
Hans de Goede45fb3662007-07-13 14:34:19 +020083#define F71882FG_REG_TEMP_TYPE 0x6B
84#define F71882FG_REG_TEMP_DIODE_OPEN 0x6F
85
Mark van Doesburg9ab796e2009-01-07 16:37:27 +010086#define F71882FG_REG_PWM(nr) (0xA3 + (16 * (nr)))
87#define F71882FG_REG_PWM_TYPE 0x94
88#define F71882FG_REG_PWM_ENABLE 0x96
89
Hans de Goedebc274902009-01-07 16:37:29 +010090#define F71882FG_REG_FAN_HYST(nr) (0x98 + (nr))
Mark van Doesburg9ab796e2009-01-07 16:37:27 +010091
Hans de Goede98f7ba12011-03-09 20:57:09 +010092#define F71882FG_REG_FAN_FAULT_T 0x9F
93#define F71882FG_FAN_NEG_TEMP_EN 0x20
Hans de Goede3cad4022011-03-09 20:57:14 +010094#define F71882FG_FAN_PROG_SEL 0x80
Hans de Goede98f7ba12011-03-09 20:57:09 +010095
Mark van Doesburg9ab796e2009-01-07 16:37:27 +010096#define F71882FG_REG_POINT_PWM(pwm, point) (0xAA + (point) + (16 * (pwm)))
97#define F71882FG_REG_POINT_TEMP(pwm, point) (0xA6 + (point) + (16 * (pwm)))
98#define F71882FG_REG_POINT_MAPPING(nr) (0xAF + 16 * (nr))
99
Hans de Goede45fb3662007-07-13 14:34:19 +0200100#define F71882FG_REG_START 0x01
101
Hans de Goede0bae6402011-03-09 20:57:10 +0100102#define F71882FG_MAX_INS 9
103
Hans de Goede45fb3662007-07-13 14:34:19 +0200104#define FAN_MIN_DETECT 366 /* Lowest detectable fanspeed */
105
Jean Delvare67b671b2007-12-06 23:13:42 +0100106static unsigned short force_id;
107module_param(force_id, ushort, 0);
108MODULE_PARM_DESC(force_id, "Override the detected device ID");
109
Hans de Goedee5e713c2011-03-10 08:54:02 +0100110enum chips { f71808e, f71858fg, f71862fg, f71869, f71882fg, f71889fg,
Hans de Goedea66c1082011-03-26 10:45:02 +0100111 f71889ed, f71889a, f8000, f81865f };
Hans de Goede498be962009-01-07 16:37:28 +0100112
113static const char *f71882fg_names[] = {
Hans de Goedee5e713c2011-03-10 08:54:02 +0100114 "f71808e",
Hans de Goede09475d32009-06-15 18:39:52 +0200115 "f71858fg",
Hans de Goede498be962009-01-07 16:37:28 +0100116 "f71862fg",
Hans de Goedec11bb992011-03-09 20:57:15 +0100117 "f71869", /* Both f71869f and f71869e, reg. compatible and same id */
Hans de Goede498be962009-01-07 16:37:28 +0100118 "f71882fg",
Jean Delvare5d7f77b2011-03-26 10:45:02 +0100119 "f71889fg", /* f81801u too, same id */
Hans de Goede3cad4022011-03-09 20:57:14 +0100120 "f71889ed",
Hans de Goedea66c1082011-03-26 10:45:02 +0100121 "f71889a",
Hans de Goedeed4f7c22009-01-07 16:37:30 +0100122 "f8000",
Jean Delvare383586b2011-03-26 10:45:02 +0100123 "f81865f",
Hans de Goede498be962009-01-07 16:37:28 +0100124};
125
Jean Delvare2740c602011-03-26 10:45:01 +0100126static const char f71882fg_has_in[][F71882FG_MAX_INS] = {
127 [f71808e] = { 1, 1, 1, 1, 1, 1, 0, 1, 1 },
128 [f71858fg] = { 1, 1, 1, 0, 0, 0, 0, 0, 0 },
129 [f71862fg] = { 1, 1, 1, 1, 1, 1, 1, 1, 1 },
130 [f71869] = { 1, 1, 1, 1, 1, 1, 1, 1, 1 },
131 [f71882fg] = { 1, 1, 1, 1, 1, 1, 1, 1, 1 },
132 [f71889fg] = { 1, 1, 1, 1, 1, 1, 1, 1, 1 },
133 [f71889ed] = { 1, 1, 1, 1, 1, 1, 1, 1, 1 },
Hans de Goedea66c1082011-03-26 10:45:02 +0100134 [f71889a] = { 1, 1, 1, 1, 1, 1, 1, 1, 1 },
Jean Delvare2740c602011-03-26 10:45:01 +0100135 [f8000] = { 1, 1, 1, 0, 0, 0, 0, 0, 0 },
Jean Delvare383586b2011-03-26 10:45:02 +0100136 [f81865f] = { 1, 1, 1, 1, 1, 1, 1, 0, 0 },
Hans de Goede0bae6402011-03-09 20:57:10 +0100137};
138
Jean Delvare2740c602011-03-26 10:45:01 +0100139static const char f71882fg_has_in1_alarm[] = {
140 [f71808e] = 0,
141 [f71858fg] = 0,
142 [f71862fg] = 0,
143 [f71869] = 0,
144 [f71882fg] = 1,
145 [f71889fg] = 1,
146 [f71889ed] = 1,
Hans de Goedea66c1082011-03-26 10:45:02 +0100147 [f71889a] = 1,
Jean Delvare2740c602011-03-26 10:45:01 +0100148 [f8000] = 0,
Jean Delvare383586b2011-03-26 10:45:02 +0100149 [f81865f] = 1,
Hans de Goede0bae6402011-03-09 20:57:10 +0100150};
151
Jean Delvare2740c602011-03-26 10:45:01 +0100152static const char f71882fg_has_beep[] = {
153 [f71808e] = 0,
154 [f71858fg] = 0,
155 [f71862fg] = 1,
156 [f71869] = 1,
157 [f71882fg] = 1,
158 [f71889fg] = 1,
159 [f71889ed] = 1,
Hans de Goedea66c1082011-03-26 10:45:02 +0100160 [f71889a] = 1,
Jean Delvare2740c602011-03-26 10:45:01 +0100161 [f8000] = 0,
Jean Delvare383586b2011-03-26 10:45:02 +0100162 [f81865f] = 1,
Hans de Goede78aa4f72011-03-09 20:57:12 +0100163};
164
Jean Delvaref27def02011-03-26 10:45:01 +0100165static const char f71882fg_nr_fans[] = {
166 [f71808e] = 3,
167 [f71858fg] = 3,
168 [f71862fg] = 3,
169 [f71869] = 3,
170 [f71882fg] = 4,
171 [f71889fg] = 3,
172 [f71889ed] = 3,
Hans de Goedea66c1082011-03-26 10:45:02 +0100173 [f71889a] = 3,
Jean Delvaref27def02011-03-26 10:45:01 +0100174 [f8000] = 3,
Jean Delvare383586b2011-03-26 10:45:02 +0100175 [f81865f] = 2,
Jean Delvaref27def02011-03-26 10:45:01 +0100176};
177
178static const char f71882fg_nr_temps[] = {
179 [f71808e] = 2,
180 [f71858fg] = 3,
181 [f71862fg] = 3,
182 [f71869] = 3,
183 [f71882fg] = 3,
184 [f71889fg] = 3,
185 [f71889ed] = 3,
Hans de Goedea66c1082011-03-26 10:45:02 +0100186 [f71889a] = 3,
Jean Delvaref27def02011-03-26 10:45:01 +0100187 [f8000] = 3,
Jean Delvare383586b2011-03-26 10:45:02 +0100188 [f81865f] = 2,
Jean Delvaref27def02011-03-26 10:45:01 +0100189};
190
Mark van Doesburg77a4a3e2009-01-07 16:37:27 +0100191static struct platform_device *f71882fg_pdev;
Hans de Goede45fb3662007-07-13 14:34:19 +0200192
193/* Super-I/O Function prototypes */
194static inline int superio_inb(int base, int reg);
195static inline int superio_inw(int base, int reg);
Giel van Schijndelcadb8652010-10-03 08:09:49 -0400196static inline int superio_enter(int base);
Hans de Goede45fb3662007-07-13 14:34:19 +0200197static inline void superio_select(int base, int ld);
198static inline void superio_exit(int base);
199
Hans de Goede498be962009-01-07 16:37:28 +0100200struct f71882fg_sio_data {
201 enum chips type;
202};
203
Hans de Goede45fb3662007-07-13 14:34:19 +0200204struct f71882fg_data {
205 unsigned short addr;
Hans de Goede498be962009-01-07 16:37:28 +0100206 enum chips type;
Tony Jones1beeffe2007-08-20 13:46:20 -0700207 struct device *hwmon_dev;
Hans de Goede45fb3662007-07-13 14:34:19 +0200208
209 struct mutex update_lock;
Hans de Goede09475d32009-06-15 18:39:52 +0200210 int temp_start; /* temp numbering start (0 or 1) */
Hans de Goede45fb3662007-07-13 14:34:19 +0200211 char valid; /* !=0 if following fields are valid */
Hans de Goede98f7ba12011-03-09 20:57:09 +0100212 char auto_point_temp_signed;
Hans de Goede45fb3662007-07-13 14:34:19 +0200213 unsigned long last_updated; /* In jiffies */
214 unsigned long last_limits; /* In jiffies */
215
216 /* Register Values */
Hans de Goede0bae6402011-03-09 20:57:10 +0100217 u8 in[F71882FG_MAX_INS];
Hans de Goede45fb3662007-07-13 14:34:19 +0200218 u8 in1_max;
219 u8 in_status;
220 u8 in_beep;
221 u16 fan[4];
Mark van Doesburg9ab796e2009-01-07 16:37:27 +0100222 u16 fan_target[4];
223 u16 fan_full_speed[4];
Hans de Goede45fb3662007-07-13 14:34:19 +0200224 u8 fan_status;
225 u8 fan_beep;
Hans de Goedee5e713c2011-03-10 08:54:02 +0100226 /* Note: all models have max 3 temperature channels, but on some
Hans de Goede7567a042009-01-07 16:37:28 +0100227 they are addressed as 0-2 and on others as 1-3, so for coding
228 convenience we reserve space for 4 channels */
Hans de Goede09475d32009-06-15 18:39:52 +0200229 u16 temp[4];
Hans de Goede7567a042009-01-07 16:37:28 +0100230 u8 temp_ovt[4];
231 u8 temp_high[4];
Hans de Goedebc274902009-01-07 16:37:29 +0100232 u8 temp_hyst[2]; /* 2 hysts stored per reg */
Hans de Goede7567a042009-01-07 16:37:28 +0100233 u8 temp_type[4];
Hans de Goede45fb3662007-07-13 14:34:19 +0200234 u8 temp_status;
235 u8 temp_beep;
236 u8 temp_diode_open;
Hans de Goede09475d32009-06-15 18:39:52 +0200237 u8 temp_config;
Mark van Doesburg9ab796e2009-01-07 16:37:27 +0100238 u8 pwm[4];
239 u8 pwm_enable;
240 u8 pwm_auto_point_hyst[2];
241 u8 pwm_auto_point_mapping[4];
242 u8 pwm_auto_point_pwm[4][5];
Hans de Goede76698962009-12-09 20:36:01 +0100243 s8 pwm_auto_point_temp[4][4];
Hans de Goede45fb3662007-07-13 14:34:19 +0200244};
245
Mark van Doesburg77a4a3e2009-01-07 16:37:27 +0100246/* Sysfs in */
Hans de Goede45fb3662007-07-13 14:34:19 +0200247static ssize_t show_in(struct device *dev, struct device_attribute *devattr,
248 char *buf);
249static ssize_t show_in_max(struct device *dev, struct device_attribute
250 *devattr, char *buf);
251static ssize_t store_in_max(struct device *dev, struct device_attribute
252 *devattr, const char *buf, size_t count);
253static ssize_t show_in_beep(struct device *dev, struct device_attribute
254 *devattr, char *buf);
255static ssize_t store_in_beep(struct device *dev, struct device_attribute
256 *devattr, const char *buf, size_t count);
257static ssize_t show_in_alarm(struct device *dev, struct device_attribute
258 *devattr, char *buf);
259/* Sysfs Fan */
260static ssize_t show_fan(struct device *dev, struct device_attribute *devattr,
261 char *buf);
Mark van Doesburg9ab796e2009-01-07 16:37:27 +0100262static ssize_t show_fan_full_speed(struct device *dev,
263 struct device_attribute *devattr, char *buf);
264static ssize_t store_fan_full_speed(struct device *dev,
265 struct device_attribute *devattr, const char *buf, size_t count);
Hans de Goede45fb3662007-07-13 14:34:19 +0200266static ssize_t show_fan_beep(struct device *dev, struct device_attribute
267 *devattr, char *buf);
268static ssize_t store_fan_beep(struct device *dev, struct device_attribute
269 *devattr, const char *buf, size_t count);
270static ssize_t show_fan_alarm(struct device *dev, struct device_attribute
271 *devattr, char *buf);
272/* Sysfs Temp */
273static ssize_t show_temp(struct device *dev, struct device_attribute
274 *devattr, char *buf);
275static ssize_t show_temp_max(struct device *dev, struct device_attribute
276 *devattr, char *buf);
277static ssize_t store_temp_max(struct device *dev, struct device_attribute
278 *devattr, const char *buf, size_t count);
279static ssize_t show_temp_max_hyst(struct device *dev, struct device_attribute
280 *devattr, char *buf);
281static ssize_t store_temp_max_hyst(struct device *dev, struct device_attribute
282 *devattr, const char *buf, size_t count);
283static ssize_t show_temp_crit(struct device *dev, struct device_attribute
284 *devattr, char *buf);
285static ssize_t store_temp_crit(struct device *dev, struct device_attribute
286 *devattr, const char *buf, size_t count);
287static ssize_t show_temp_crit_hyst(struct device *dev, struct device_attribute
288 *devattr, char *buf);
289static ssize_t show_temp_type(struct device *dev, struct device_attribute
290 *devattr, char *buf);
291static ssize_t show_temp_beep(struct device *dev, struct device_attribute
292 *devattr, char *buf);
293static ssize_t store_temp_beep(struct device *dev, struct device_attribute
294 *devattr, const char *buf, size_t count);
295static ssize_t show_temp_alarm(struct device *dev, struct device_attribute
296 *devattr, char *buf);
297static ssize_t show_temp_fault(struct device *dev, struct device_attribute
298 *devattr, char *buf);
Mark van Doesburg9ab796e2009-01-07 16:37:27 +0100299/* PWM and Auto point control */
300static ssize_t show_pwm(struct device *dev, struct device_attribute *devattr,
301 char *buf);
302static ssize_t store_pwm(struct device *dev, struct device_attribute *devattr,
303 const char *buf, size_t count);
304static ssize_t show_pwm_enable(struct device *dev,
305 struct device_attribute *devattr, char *buf);
306static ssize_t store_pwm_enable(struct device *dev,
307 struct device_attribute *devattr, const char *buf, size_t count);
308static ssize_t show_pwm_interpolate(struct device *dev,
309 struct device_attribute *devattr, char *buf);
310static ssize_t store_pwm_interpolate(struct device *dev,
311 struct device_attribute *devattr, const char *buf, size_t count);
312static ssize_t show_pwm_auto_point_channel(struct device *dev,
313 struct device_attribute *devattr, char *buf);
314static ssize_t store_pwm_auto_point_channel(struct device *dev,
315 struct device_attribute *devattr, const char *buf, size_t count);
316static ssize_t show_pwm_auto_point_temp_hyst(struct device *dev,
317 struct device_attribute *devattr, char *buf);
318static ssize_t store_pwm_auto_point_temp_hyst(struct device *dev,
319 struct device_attribute *devattr, const char *buf, size_t count);
320static ssize_t show_pwm_auto_point_pwm(struct device *dev,
321 struct device_attribute *devattr, char *buf);
322static ssize_t store_pwm_auto_point_pwm(struct device *dev,
323 struct device_attribute *devattr, const char *buf, size_t count);
324static ssize_t show_pwm_auto_point_temp(struct device *dev,
325 struct device_attribute *devattr, char *buf);
326static ssize_t store_pwm_auto_point_temp(struct device *dev,
327 struct device_attribute *devattr, const char *buf, size_t count);
Hans de Goede45fb3662007-07-13 14:34:19 +0200328/* Sysfs misc */
329static ssize_t show_name(struct device *dev, struct device_attribute *devattr,
330 char *buf);
331
332static int __devinit f71882fg_probe(struct platform_device * pdev);
Hans de Goedec13548c2009-01-07 16:37:27 +0100333static int f71882fg_remove(struct platform_device *pdev);
Hans de Goede45fb3662007-07-13 14:34:19 +0200334
335static struct platform_driver f71882fg_driver = {
336 .driver = {
337 .owner = THIS_MODULE,
338 .name = DRVNAME,
339 },
340 .probe = f71882fg_probe,
Jean Delvarecd659fd2009-06-15 18:39:45 +0200341 .remove = f71882fg_remove,
Hans de Goede45fb3662007-07-13 14:34:19 +0200342};
343
Hans de Goedec13548c2009-01-07 16:37:27 +0100344static DEVICE_ATTR(name, S_IRUGO, show_name, NULL);
Hans de Goede45fb3662007-07-13 14:34:19 +0200345
Hans de Goede0bae6402011-03-09 20:57:10 +0100346/* Temp attr for the f71858fg, the f71858fg is special as it has its
347 temperature indexes start at 0 (the others start at 1) */
348static struct sensor_device_attribute_2 f71858fg_temp_attr[] = {
Hans de Goede09475d32009-06-15 18:39:52 +0200349 SENSOR_ATTR_2(temp1_input, S_IRUGO, show_temp, NULL, 0, 0),
350 SENSOR_ATTR_2(temp1_max, S_IRUGO|S_IWUSR, show_temp_max,
351 store_temp_max, 0, 0),
352 SENSOR_ATTR_2(temp1_max_hyst, S_IRUGO|S_IWUSR, show_temp_max_hyst,
353 store_temp_max_hyst, 0, 0),
354 SENSOR_ATTR_2(temp1_max_alarm, S_IRUGO, show_temp_alarm, NULL, 0, 0),
355 SENSOR_ATTR_2(temp1_crit, S_IRUGO|S_IWUSR, show_temp_crit,
356 store_temp_crit, 0, 0),
357 SENSOR_ATTR_2(temp1_crit_hyst, S_IRUGO, show_temp_crit_hyst, NULL,
358 0, 0),
359 SENSOR_ATTR_2(temp1_crit_alarm, S_IRUGO, show_temp_alarm, NULL, 0, 4),
360 SENSOR_ATTR_2(temp1_fault, S_IRUGO, show_temp_fault, NULL, 0, 0),
361 SENSOR_ATTR_2(temp2_input, S_IRUGO, show_temp, NULL, 0, 1),
362 SENSOR_ATTR_2(temp2_max, S_IRUGO|S_IWUSR, show_temp_max,
363 store_temp_max, 0, 1),
364 SENSOR_ATTR_2(temp2_max_hyst, S_IRUGO|S_IWUSR, show_temp_max_hyst,
365 store_temp_max_hyst, 0, 1),
366 SENSOR_ATTR_2(temp2_max_alarm, S_IRUGO, show_temp_alarm, NULL, 0, 1),
367 SENSOR_ATTR_2(temp2_crit, S_IRUGO|S_IWUSR, show_temp_crit,
368 store_temp_crit, 0, 1),
369 SENSOR_ATTR_2(temp2_crit_hyst, S_IRUGO, show_temp_crit_hyst, NULL,
370 0, 1),
371 SENSOR_ATTR_2(temp2_crit_alarm, S_IRUGO, show_temp_alarm, NULL, 0, 5),
Hans de Goede09475d32009-06-15 18:39:52 +0200372 SENSOR_ATTR_2(temp2_fault, S_IRUGO, show_temp_fault, NULL, 0, 1),
373 SENSOR_ATTR_2(temp3_input, S_IRUGO, show_temp, NULL, 0, 2),
374 SENSOR_ATTR_2(temp3_max, S_IRUGO|S_IWUSR, show_temp_max,
375 store_temp_max, 0, 2),
376 SENSOR_ATTR_2(temp3_max_hyst, S_IRUGO|S_IWUSR, show_temp_max_hyst,
377 store_temp_max_hyst, 0, 2),
378 SENSOR_ATTR_2(temp3_max_alarm, S_IRUGO, show_temp_alarm, NULL, 0, 2),
379 SENSOR_ATTR_2(temp3_crit, S_IRUGO|S_IWUSR, show_temp_crit,
380 store_temp_crit, 0, 2),
381 SENSOR_ATTR_2(temp3_crit_hyst, S_IRUGO, show_temp_crit_hyst, NULL,
382 0, 2),
383 SENSOR_ATTR_2(temp3_crit_alarm, S_IRUGO, show_temp_alarm, NULL, 0, 6),
384 SENSOR_ATTR_2(temp3_fault, S_IRUGO, show_temp_fault, NULL, 0, 2),
385};
386
Hans de Goede0bae6402011-03-09 20:57:10 +0100387/* Temp attr for the standard models */
Hans de Goede78aa4f72011-03-09 20:57:12 +0100388static struct sensor_device_attribute_2 fxxxx_temp_attr[3][9] = { {
Hans de Goede7567a042009-01-07 16:37:28 +0100389 SENSOR_ATTR_2(temp1_input, S_IRUGO, show_temp, NULL, 0, 1),
Mark van Doesburgbc37ae72009-01-07 16:37:27 +0100390 SENSOR_ATTR_2(temp1_max, S_IRUGO|S_IWUSR, show_temp_max,
Mark van Doesburgbc37ae72009-01-07 16:37:27 +0100391 store_temp_max, 0, 1),
Hans de Goede7567a042009-01-07 16:37:28 +0100392 SENSOR_ATTR_2(temp1_max_hyst, S_IRUGO|S_IWUSR, show_temp_max_hyst,
Mark van Doesburgbc37ae72009-01-07 16:37:27 +0100393 store_temp_max_hyst, 0, 1),
Hans de Goede754a5902009-01-07 16:37:29 +0100394 /* Should really be temp1_max_alarm, but older versions did not handle
395 the max and crit alarms separately and lm_sensors v2 depends on the
396 presence of temp#_alarm files. The same goes for temp2/3 _alarm. */
397 SENSOR_ATTR_2(temp1_alarm, S_IRUGO, show_temp_alarm, NULL, 0, 1),
Hans de Goede7567a042009-01-07 16:37:28 +0100398 SENSOR_ATTR_2(temp1_crit, S_IRUGO|S_IWUSR, show_temp_crit,
Mark van Doesburgbc37ae72009-01-07 16:37:27 +0100399 store_temp_crit, 0, 1),
Hans de Goede7567a042009-01-07 16:37:28 +0100400 SENSOR_ATTR_2(temp1_crit_hyst, S_IRUGO, show_temp_crit_hyst, NULL,
Mark van Doesburgbc37ae72009-01-07 16:37:27 +0100401 0, 1),
Hans de Goede754a5902009-01-07 16:37:29 +0100402 SENSOR_ATTR_2(temp1_crit_alarm, S_IRUGO, show_temp_alarm, NULL, 0, 5),
Hans de Goede7567a042009-01-07 16:37:28 +0100403 SENSOR_ATTR_2(temp1_type, S_IRUGO, show_temp_type, NULL, 0, 1),
Hans de Goede7567a042009-01-07 16:37:28 +0100404 SENSOR_ATTR_2(temp1_fault, S_IRUGO, show_temp_fault, NULL, 0, 1),
Hans de Goede60d2b372011-03-09 20:57:11 +0100405}, {
Hans de Goede7567a042009-01-07 16:37:28 +0100406 SENSOR_ATTR_2(temp2_input, S_IRUGO, show_temp, NULL, 0, 2),
407 SENSOR_ATTR_2(temp2_max, S_IRUGO|S_IWUSR, show_temp_max,
Mark van Doesburgbc37ae72009-01-07 16:37:27 +0100408 store_temp_max, 0, 2),
Hans de Goede7567a042009-01-07 16:37:28 +0100409 SENSOR_ATTR_2(temp2_max_hyst, S_IRUGO|S_IWUSR, show_temp_max_hyst,
Mark van Doesburgbc37ae72009-01-07 16:37:27 +0100410 store_temp_max_hyst, 0, 2),
Hans de Goede754a5902009-01-07 16:37:29 +0100411 /* Should be temp2_max_alarm, see temp1_alarm note */
412 SENSOR_ATTR_2(temp2_alarm, S_IRUGO, show_temp_alarm, NULL, 0, 2),
Hans de Goede7567a042009-01-07 16:37:28 +0100413 SENSOR_ATTR_2(temp2_crit, S_IRUGO|S_IWUSR, show_temp_crit,
Mark van Doesburgbc37ae72009-01-07 16:37:27 +0100414 store_temp_crit, 0, 2),
Hans de Goede7567a042009-01-07 16:37:28 +0100415 SENSOR_ATTR_2(temp2_crit_hyst, S_IRUGO, show_temp_crit_hyst, NULL,
Mark van Doesburgbc37ae72009-01-07 16:37:27 +0100416 0, 2),
Hans de Goede754a5902009-01-07 16:37:29 +0100417 SENSOR_ATTR_2(temp2_crit_alarm, S_IRUGO, show_temp_alarm, NULL, 0, 6),
Hans de Goede7567a042009-01-07 16:37:28 +0100418 SENSOR_ATTR_2(temp2_type, S_IRUGO, show_temp_type, NULL, 0, 2),
Hans de Goede7567a042009-01-07 16:37:28 +0100419 SENSOR_ATTR_2(temp2_fault, S_IRUGO, show_temp_fault, NULL, 0, 2),
Hans de Goede60d2b372011-03-09 20:57:11 +0100420}, {
Hans de Goede7567a042009-01-07 16:37:28 +0100421 SENSOR_ATTR_2(temp3_input, S_IRUGO, show_temp, NULL, 0, 3),
422 SENSOR_ATTR_2(temp3_max, S_IRUGO|S_IWUSR, show_temp_max,
423 store_temp_max, 0, 3),
424 SENSOR_ATTR_2(temp3_max_hyst, S_IRUGO|S_IWUSR, show_temp_max_hyst,
425 store_temp_max_hyst, 0, 3),
Hans de Goede754a5902009-01-07 16:37:29 +0100426 /* Should be temp3_max_alarm, see temp1_alarm note */
427 SENSOR_ATTR_2(temp3_alarm, S_IRUGO, show_temp_alarm, NULL, 0, 3),
Hans de Goede7567a042009-01-07 16:37:28 +0100428 SENSOR_ATTR_2(temp3_crit, S_IRUGO|S_IWUSR, show_temp_crit,
429 store_temp_crit, 0, 3),
430 SENSOR_ATTR_2(temp3_crit_hyst, S_IRUGO, show_temp_crit_hyst, NULL,
431 0, 3),
Hans de Goede754a5902009-01-07 16:37:29 +0100432 SENSOR_ATTR_2(temp3_crit_alarm, S_IRUGO, show_temp_alarm, NULL, 0, 7),
Hans de Goede7567a042009-01-07 16:37:28 +0100433 SENSOR_ATTR_2(temp3_type, S_IRUGO, show_temp_type, NULL, 0, 3),
Hans de Goede7567a042009-01-07 16:37:28 +0100434 SENSOR_ATTR_2(temp3_fault, S_IRUGO, show_temp_fault, NULL, 0, 3),
Hans de Goede60d2b372011-03-09 20:57:11 +0100435} };
Hans de Goede45fb3662007-07-13 14:34:19 +0200436
Hans de Goede78aa4f72011-03-09 20:57:12 +0100437/* Temp attr for models which can beep on temp alarm */
438static struct sensor_device_attribute_2 fxxxx_temp_beep_attr[3][2] = { {
439 SENSOR_ATTR_2(temp1_max_beep, S_IRUGO|S_IWUSR, show_temp_beep,
440 store_temp_beep, 0, 1),
441 SENSOR_ATTR_2(temp1_crit_beep, S_IRUGO|S_IWUSR, show_temp_beep,
442 store_temp_beep, 0, 5),
443}, {
444 SENSOR_ATTR_2(temp2_max_beep, S_IRUGO|S_IWUSR, show_temp_beep,
445 store_temp_beep, 0, 2),
446 SENSOR_ATTR_2(temp2_crit_beep, S_IRUGO|S_IWUSR, show_temp_beep,
447 store_temp_beep, 0, 6),
448}, {
449 SENSOR_ATTR_2(temp3_max_beep, S_IRUGO|S_IWUSR, show_temp_beep,
450 store_temp_beep, 0, 3),
451 SENSOR_ATTR_2(temp3_crit_beep, S_IRUGO|S_IWUSR, show_temp_beep,
452 store_temp_beep, 0, 7),
453} };
454
Hans de Goede0bae6402011-03-09 20:57:10 +0100455/* Temp attr for the f8000
Hans de Goedeed4f7c22009-01-07 16:37:30 +0100456 Note on the f8000 temp_ovt (crit) is used as max, and temp_high (max)
457 is used as hysteresis value to clear alarms
Hans de Goede66344aa2009-12-09 20:35:59 +0100458 Also like the f71858fg its temperature indexes start at 0
Hans de Goedeed4f7c22009-01-07 16:37:30 +0100459 */
Hans de Goede0bae6402011-03-09 20:57:10 +0100460static struct sensor_device_attribute_2 f8000_temp_attr[] = {
Hans de Goedeed4f7c22009-01-07 16:37:30 +0100461 SENSOR_ATTR_2(temp1_input, S_IRUGO, show_temp, NULL, 0, 0),
462 SENSOR_ATTR_2(temp1_max, S_IRUGO|S_IWUSR, show_temp_crit,
463 store_temp_crit, 0, 0),
464 SENSOR_ATTR_2(temp1_max_hyst, S_IRUGO|S_IWUSR, show_temp_max,
465 store_temp_max, 0, 0),
466 SENSOR_ATTR_2(temp1_alarm, S_IRUGO, show_temp_alarm, NULL, 0, 4),
Hans de Goedeb6858bc2009-06-15 18:39:51 +0200467 SENSOR_ATTR_2(temp1_fault, S_IRUGO, show_temp_fault, NULL, 0, 0),
Hans de Goedeed4f7c22009-01-07 16:37:30 +0100468 SENSOR_ATTR_2(temp2_input, S_IRUGO, show_temp, NULL, 0, 1),
469 SENSOR_ATTR_2(temp2_max, S_IRUGO|S_IWUSR, show_temp_crit,
470 store_temp_crit, 0, 1),
471 SENSOR_ATTR_2(temp2_max_hyst, S_IRUGO|S_IWUSR, show_temp_max,
472 store_temp_max, 0, 1),
473 SENSOR_ATTR_2(temp2_alarm, S_IRUGO, show_temp_alarm, NULL, 0, 5),
Hans de Goedeb6858bc2009-06-15 18:39:51 +0200474 SENSOR_ATTR_2(temp2_fault, S_IRUGO, show_temp_fault, NULL, 0, 1),
Hans de Goedeed4f7c22009-01-07 16:37:30 +0100475 SENSOR_ATTR_2(temp3_input, S_IRUGO, show_temp, NULL, 0, 2),
476 SENSOR_ATTR_2(temp3_max, S_IRUGO|S_IWUSR, show_temp_crit,
477 store_temp_crit, 0, 2),
478 SENSOR_ATTR_2(temp3_max_hyst, S_IRUGO|S_IWUSR, show_temp_max,
479 store_temp_max, 0, 2),
480 SENSOR_ATTR_2(temp3_alarm, S_IRUGO, show_temp_alarm, NULL, 0, 6),
Hans de Goedeb6858bc2009-06-15 18:39:51 +0200481 SENSOR_ATTR_2(temp3_fault, S_IRUGO, show_temp_fault, NULL, 0, 2),
Hans de Goedeed4f7c22009-01-07 16:37:30 +0100482};
483
Hans de Goede0bae6402011-03-09 20:57:10 +0100484/* in attr for all models */
485static struct sensor_device_attribute_2 fxxxx_in_attr[] = {
486 SENSOR_ATTR_2(in0_input, S_IRUGO, show_in, NULL, 0, 0),
487 SENSOR_ATTR_2(in1_input, S_IRUGO, show_in, NULL, 0, 1),
488 SENSOR_ATTR_2(in2_input, S_IRUGO, show_in, NULL, 0, 2),
489 SENSOR_ATTR_2(in3_input, S_IRUGO, show_in, NULL, 0, 3),
490 SENSOR_ATTR_2(in4_input, S_IRUGO, show_in, NULL, 0, 4),
491 SENSOR_ATTR_2(in5_input, S_IRUGO, show_in, NULL, 0, 5),
492 SENSOR_ATTR_2(in6_input, S_IRUGO, show_in, NULL, 0, 6),
493 SENSOR_ATTR_2(in7_input, S_IRUGO, show_in, NULL, 0, 7),
494 SENSOR_ATTR_2(in8_input, S_IRUGO, show_in, NULL, 0, 8),
495};
496
497/* For models with in1 alarm capability */
498static struct sensor_device_attribute_2 fxxxx_in1_alarm_attr[] = {
499 SENSOR_ATTR_2(in1_max, S_IRUGO|S_IWUSR, show_in_max, store_in_max,
500 0, 1),
501 SENSOR_ATTR_2(in1_beep, S_IRUGO|S_IWUSR, show_in_beep, store_in_beep,
502 0, 1),
503 SENSOR_ATTR_2(in1_alarm, S_IRUGO, show_in_alarm, NULL, 0, 1),
504};
505
Hans de Goedeed4f7c22009-01-07 16:37:30 +0100506/* Fan / PWM attr common to all models */
Hans de Goedeb69b0392009-12-09 20:36:00 +0100507static struct sensor_device_attribute_2 fxxxx_fan_attr[4][6] = { {
Mark van Doesburgbc37ae72009-01-07 16:37:27 +0100508 SENSOR_ATTR_2(fan1_input, S_IRUGO, show_fan, NULL, 0, 0),
Mark van Doesburg9ab796e2009-01-07 16:37:27 +0100509 SENSOR_ATTR_2(fan1_full_speed, S_IRUGO|S_IWUSR,
510 show_fan_full_speed,
511 store_fan_full_speed, 0, 0),
Mark van Doesburgbc37ae72009-01-07 16:37:27 +0100512 SENSOR_ATTR_2(fan1_alarm, S_IRUGO, show_fan_alarm, NULL, 0, 0),
Mark van Doesburg9ab796e2009-01-07 16:37:27 +0100513 SENSOR_ATTR_2(pwm1, S_IRUGO|S_IWUSR, show_pwm, store_pwm, 0, 0),
514 SENSOR_ATTR_2(pwm1_enable, S_IRUGO|S_IWUSR, show_pwm_enable,
515 store_pwm_enable, 0, 0),
516 SENSOR_ATTR_2(pwm1_interpolate, S_IRUGO|S_IWUSR,
517 show_pwm_interpolate, store_pwm_interpolate, 0, 0),
Hans de Goedeb69b0392009-12-09 20:36:00 +0100518}, {
519 SENSOR_ATTR_2(fan2_input, S_IRUGO, show_fan, NULL, 0, 1),
520 SENSOR_ATTR_2(fan2_full_speed, S_IRUGO|S_IWUSR,
521 show_fan_full_speed,
522 store_fan_full_speed, 0, 1),
523 SENSOR_ATTR_2(fan2_alarm, S_IRUGO, show_fan_alarm, NULL, 0, 1),
Hans de Goede498be962009-01-07 16:37:28 +0100524 SENSOR_ATTR_2(pwm2, S_IRUGO|S_IWUSR, show_pwm, store_pwm, 0, 1),
525 SENSOR_ATTR_2(pwm2_enable, S_IRUGO|S_IWUSR, show_pwm_enable,
526 store_pwm_enable, 0, 1),
527 SENSOR_ATTR_2(pwm2_interpolate, S_IRUGO|S_IWUSR,
528 show_pwm_interpolate, store_pwm_interpolate, 0, 1),
Hans de Goedeb69b0392009-12-09 20:36:00 +0100529}, {
530 SENSOR_ATTR_2(fan3_input, S_IRUGO, show_fan, NULL, 0, 2),
531 SENSOR_ATTR_2(fan3_full_speed, S_IRUGO|S_IWUSR,
532 show_fan_full_speed,
533 store_fan_full_speed, 0, 2),
534 SENSOR_ATTR_2(fan3_alarm, S_IRUGO, show_fan_alarm, NULL, 0, 2),
Hans de Goede3fc78382009-06-15 18:39:50 +0200535 SENSOR_ATTR_2(pwm3, S_IRUGO|S_IWUSR, show_pwm, store_pwm, 0, 2),
536 SENSOR_ATTR_2(pwm3_enable, S_IRUGO|S_IWUSR, show_pwm_enable,
537 store_pwm_enable, 0, 2),
Hans de Goede498be962009-01-07 16:37:28 +0100538 SENSOR_ATTR_2(pwm3_interpolate, S_IRUGO|S_IWUSR,
539 show_pwm_interpolate, store_pwm_interpolate, 0, 2),
Hans de Goedeb69b0392009-12-09 20:36:00 +0100540}, {
541 SENSOR_ATTR_2(fan4_input, S_IRUGO, show_fan, NULL, 0, 3),
542 SENSOR_ATTR_2(fan4_full_speed, S_IRUGO|S_IWUSR,
543 show_fan_full_speed,
544 store_fan_full_speed, 0, 3),
545 SENSOR_ATTR_2(fan4_alarm, S_IRUGO, show_fan_alarm, NULL, 0, 3),
546 SENSOR_ATTR_2(pwm4, S_IRUGO|S_IWUSR, show_pwm, store_pwm, 0, 3),
547 SENSOR_ATTR_2(pwm4_enable, S_IRUGO|S_IWUSR, show_pwm_enable,
548 store_pwm_enable, 0, 3),
549 SENSOR_ATTR_2(pwm4_interpolate, S_IRUGO|S_IWUSR,
550 show_pwm_interpolate, store_pwm_interpolate, 0, 3),
551} };
Hans de Goede498be962009-01-07 16:37:28 +0100552
Hans de Goede66344aa2009-12-09 20:35:59 +0100553/* Attr for models which can beep on Fan alarm */
554static struct sensor_device_attribute_2 fxxxx_fan_beep_attr[] = {
Hans de Goedeed4f7c22009-01-07 16:37:30 +0100555 SENSOR_ATTR_2(fan1_beep, S_IRUGO|S_IWUSR, show_fan_beep,
556 store_fan_beep, 0, 0),
557 SENSOR_ATTR_2(fan2_beep, S_IRUGO|S_IWUSR, show_fan_beep,
558 store_fan_beep, 0, 1),
559 SENSOR_ATTR_2(fan3_beep, S_IRUGO|S_IWUSR, show_fan_beep,
560 store_fan_beep, 0, 2),
Hans de Goedeb69b0392009-12-09 20:36:00 +0100561 SENSOR_ATTR_2(fan4_beep, S_IRUGO|S_IWUSR, show_fan_beep,
562 store_fan_beep, 0, 3),
Hans de Goede66344aa2009-12-09 20:35:59 +0100563};
Hans de Goedeed4f7c22009-01-07 16:37:30 +0100564
Hans de Goede66344aa2009-12-09 20:35:59 +0100565/* PWM attr for the f71862fg, fewer pwms and fewer zones per pwm than the
Hans de Goede3cad4022011-03-09 20:57:14 +0100566 standard models */
Hans de Goede66344aa2009-12-09 20:35:59 +0100567static struct sensor_device_attribute_2 f71862fg_auto_pwm_attr[] = {
568 SENSOR_ATTR_2(pwm1_auto_channels_temp, S_IRUGO|S_IWUSR,
569 show_pwm_auto_point_channel,
570 store_pwm_auto_point_channel, 0, 0),
Hans de Goede498be962009-01-07 16:37:28 +0100571 SENSOR_ATTR_2(pwm1_auto_point1_pwm, S_IRUGO|S_IWUSR,
572 show_pwm_auto_point_pwm, store_pwm_auto_point_pwm,
573 1, 0),
574 SENSOR_ATTR_2(pwm1_auto_point2_pwm, S_IRUGO|S_IWUSR,
575 show_pwm_auto_point_pwm, store_pwm_auto_point_pwm,
576 4, 0),
577 SENSOR_ATTR_2(pwm1_auto_point1_temp, S_IRUGO|S_IWUSR,
578 show_pwm_auto_point_temp, store_pwm_auto_point_temp,
579 0, 0),
580 SENSOR_ATTR_2(pwm1_auto_point2_temp, S_IRUGO|S_IWUSR,
581 show_pwm_auto_point_temp, store_pwm_auto_point_temp,
582 3, 0),
583 SENSOR_ATTR_2(pwm1_auto_point1_temp_hyst, S_IRUGO|S_IWUSR,
584 show_pwm_auto_point_temp_hyst,
585 store_pwm_auto_point_temp_hyst,
586 0, 0),
587 SENSOR_ATTR_2(pwm1_auto_point2_temp_hyst, S_IRUGO,
588 show_pwm_auto_point_temp_hyst, NULL, 3, 0),
589
Hans de Goede66344aa2009-12-09 20:35:59 +0100590 SENSOR_ATTR_2(pwm2_auto_channels_temp, S_IRUGO|S_IWUSR,
591 show_pwm_auto_point_channel,
592 store_pwm_auto_point_channel, 0, 1),
Hans de Goede498be962009-01-07 16:37:28 +0100593 SENSOR_ATTR_2(pwm2_auto_point1_pwm, S_IRUGO|S_IWUSR,
594 show_pwm_auto_point_pwm, store_pwm_auto_point_pwm,
595 1, 1),
596 SENSOR_ATTR_2(pwm2_auto_point2_pwm, S_IRUGO|S_IWUSR,
597 show_pwm_auto_point_pwm, store_pwm_auto_point_pwm,
598 4, 1),
599 SENSOR_ATTR_2(pwm2_auto_point1_temp, S_IRUGO|S_IWUSR,
600 show_pwm_auto_point_temp, store_pwm_auto_point_temp,
601 0, 1),
602 SENSOR_ATTR_2(pwm2_auto_point2_temp, S_IRUGO|S_IWUSR,
603 show_pwm_auto_point_temp, store_pwm_auto_point_temp,
604 3, 1),
605 SENSOR_ATTR_2(pwm2_auto_point1_temp_hyst, S_IRUGO|S_IWUSR,
606 show_pwm_auto_point_temp_hyst,
607 store_pwm_auto_point_temp_hyst,
608 0, 1),
609 SENSOR_ATTR_2(pwm2_auto_point2_temp_hyst, S_IRUGO,
610 show_pwm_auto_point_temp_hyst, NULL, 3, 1),
Hans de Goede49010622009-01-07 16:37:30 +0100611
Hans de Goede66344aa2009-12-09 20:35:59 +0100612 SENSOR_ATTR_2(pwm3_auto_channels_temp, S_IRUGO|S_IWUSR,
613 show_pwm_auto_point_channel,
614 store_pwm_auto_point_channel, 0, 2),
Hans de Goede49010622009-01-07 16:37:30 +0100615 SENSOR_ATTR_2(pwm3_auto_point1_pwm, S_IRUGO|S_IWUSR,
616 show_pwm_auto_point_pwm, store_pwm_auto_point_pwm,
617 1, 2),
618 SENSOR_ATTR_2(pwm3_auto_point2_pwm, S_IRUGO|S_IWUSR,
619 show_pwm_auto_point_pwm, store_pwm_auto_point_pwm,
620 4, 2),
621 SENSOR_ATTR_2(pwm3_auto_point1_temp, S_IRUGO|S_IWUSR,
622 show_pwm_auto_point_temp, store_pwm_auto_point_temp,
623 0, 2),
624 SENSOR_ATTR_2(pwm3_auto_point2_temp, S_IRUGO|S_IWUSR,
625 show_pwm_auto_point_temp, store_pwm_auto_point_temp,
626 3, 2),
627 SENSOR_ATTR_2(pwm3_auto_point1_temp_hyst, S_IRUGO|S_IWUSR,
628 show_pwm_auto_point_temp_hyst,
629 store_pwm_auto_point_temp_hyst,
630 0, 2),
631 SENSOR_ATTR_2(pwm3_auto_point2_temp_hyst, S_IRUGO,
632 show_pwm_auto_point_temp_hyst, NULL, 3, 2),
Hans de Goede498be962009-01-07 16:37:28 +0100633};
634
Hans de Goedee5e713c2011-03-10 08:54:02 +0100635/* PWM attr for the f71808e/f71869, almost identical to the f71862fg, but the
Hans de Goedec11bb992011-03-09 20:57:15 +0100636 pwm setting when the temperature is above the pwmX_auto_point1_temp can be
637 programmed instead of being hardcoded to 0xff */
638static struct sensor_device_attribute_2 f71869_auto_pwm_attr[] = {
639 SENSOR_ATTR_2(pwm1_auto_channels_temp, S_IRUGO|S_IWUSR,
640 show_pwm_auto_point_channel,
641 store_pwm_auto_point_channel, 0, 0),
642 SENSOR_ATTR_2(pwm1_auto_point1_pwm, S_IRUGO|S_IWUSR,
643 show_pwm_auto_point_pwm, store_pwm_auto_point_pwm,
644 0, 0),
645 SENSOR_ATTR_2(pwm1_auto_point2_pwm, S_IRUGO|S_IWUSR,
646 show_pwm_auto_point_pwm, store_pwm_auto_point_pwm,
647 1, 0),
648 SENSOR_ATTR_2(pwm1_auto_point3_pwm, S_IRUGO|S_IWUSR,
649 show_pwm_auto_point_pwm, store_pwm_auto_point_pwm,
650 4, 0),
651 SENSOR_ATTR_2(pwm1_auto_point1_temp, S_IRUGO|S_IWUSR,
652 show_pwm_auto_point_temp, store_pwm_auto_point_temp,
653 0, 0),
654 SENSOR_ATTR_2(pwm1_auto_point2_temp, S_IRUGO|S_IWUSR,
655 show_pwm_auto_point_temp, store_pwm_auto_point_temp,
656 3, 0),
657 SENSOR_ATTR_2(pwm1_auto_point1_temp_hyst, S_IRUGO|S_IWUSR,
658 show_pwm_auto_point_temp_hyst,
659 store_pwm_auto_point_temp_hyst,
660 0, 0),
661 SENSOR_ATTR_2(pwm1_auto_point2_temp_hyst, S_IRUGO,
662 show_pwm_auto_point_temp_hyst, NULL, 3, 0),
663
664 SENSOR_ATTR_2(pwm2_auto_channels_temp, S_IRUGO|S_IWUSR,
665 show_pwm_auto_point_channel,
666 store_pwm_auto_point_channel, 0, 1),
667 SENSOR_ATTR_2(pwm2_auto_point1_pwm, S_IRUGO|S_IWUSR,
668 show_pwm_auto_point_pwm, store_pwm_auto_point_pwm,
669 0, 1),
670 SENSOR_ATTR_2(pwm2_auto_point2_pwm, S_IRUGO|S_IWUSR,
671 show_pwm_auto_point_pwm, store_pwm_auto_point_pwm,
672 1, 1),
673 SENSOR_ATTR_2(pwm2_auto_point3_pwm, S_IRUGO|S_IWUSR,
674 show_pwm_auto_point_pwm, store_pwm_auto_point_pwm,
675 4, 1),
676 SENSOR_ATTR_2(pwm2_auto_point1_temp, S_IRUGO|S_IWUSR,
677 show_pwm_auto_point_temp, store_pwm_auto_point_temp,
678 0, 1),
679 SENSOR_ATTR_2(pwm2_auto_point2_temp, S_IRUGO|S_IWUSR,
680 show_pwm_auto_point_temp, store_pwm_auto_point_temp,
681 3, 1),
682 SENSOR_ATTR_2(pwm2_auto_point1_temp_hyst, S_IRUGO|S_IWUSR,
683 show_pwm_auto_point_temp_hyst,
684 store_pwm_auto_point_temp_hyst,
685 0, 1),
686 SENSOR_ATTR_2(pwm2_auto_point2_temp_hyst, S_IRUGO,
687 show_pwm_auto_point_temp_hyst, NULL, 3, 1),
688
689 SENSOR_ATTR_2(pwm3_auto_channels_temp, S_IRUGO|S_IWUSR,
690 show_pwm_auto_point_channel,
691 store_pwm_auto_point_channel, 0, 2),
692 SENSOR_ATTR_2(pwm3_auto_point1_pwm, S_IRUGO|S_IWUSR,
693 show_pwm_auto_point_pwm, store_pwm_auto_point_pwm,
694 0, 2),
695 SENSOR_ATTR_2(pwm3_auto_point2_pwm, S_IRUGO|S_IWUSR,
696 show_pwm_auto_point_pwm, store_pwm_auto_point_pwm,
697 1, 2),
698 SENSOR_ATTR_2(pwm3_auto_point3_pwm, S_IRUGO|S_IWUSR,
699 show_pwm_auto_point_pwm, store_pwm_auto_point_pwm,
700 4, 2),
701 SENSOR_ATTR_2(pwm3_auto_point1_temp, S_IRUGO|S_IWUSR,
702 show_pwm_auto_point_temp, store_pwm_auto_point_temp,
703 0, 2),
704 SENSOR_ATTR_2(pwm3_auto_point2_temp, S_IRUGO|S_IWUSR,
705 show_pwm_auto_point_temp, store_pwm_auto_point_temp,
706 3, 2),
707 SENSOR_ATTR_2(pwm3_auto_point1_temp_hyst, S_IRUGO|S_IWUSR,
708 show_pwm_auto_point_temp_hyst,
709 store_pwm_auto_point_temp_hyst,
710 0, 2),
711 SENSOR_ATTR_2(pwm3_auto_point2_temp_hyst, S_IRUGO,
712 show_pwm_auto_point_temp_hyst, NULL, 3, 2),
713};
714
Hans de Goede3cad4022011-03-09 20:57:14 +0100715/* PWM attr for the standard models */
Hans de Goedeb69b0392009-12-09 20:36:00 +0100716static struct sensor_device_attribute_2 fxxxx_auto_pwm_attr[4][14] = { {
Hans de Goede66344aa2009-12-09 20:35:59 +0100717 SENSOR_ATTR_2(pwm1_auto_channels_temp, S_IRUGO|S_IWUSR,
718 show_pwm_auto_point_channel,
719 store_pwm_auto_point_channel, 0, 0),
Mark van Doesburg9ab796e2009-01-07 16:37:27 +0100720 SENSOR_ATTR_2(pwm1_auto_point1_pwm, S_IRUGO|S_IWUSR,
721 show_pwm_auto_point_pwm, store_pwm_auto_point_pwm,
722 0, 0),
723 SENSOR_ATTR_2(pwm1_auto_point2_pwm, S_IRUGO|S_IWUSR,
724 show_pwm_auto_point_pwm, store_pwm_auto_point_pwm,
725 1, 0),
726 SENSOR_ATTR_2(pwm1_auto_point3_pwm, S_IRUGO|S_IWUSR,
727 show_pwm_auto_point_pwm, store_pwm_auto_point_pwm,
728 2, 0),
729 SENSOR_ATTR_2(pwm1_auto_point4_pwm, S_IRUGO|S_IWUSR,
730 show_pwm_auto_point_pwm, store_pwm_auto_point_pwm,
731 3, 0),
732 SENSOR_ATTR_2(pwm1_auto_point5_pwm, S_IRUGO|S_IWUSR,
733 show_pwm_auto_point_pwm, store_pwm_auto_point_pwm,
734 4, 0),
735 SENSOR_ATTR_2(pwm1_auto_point1_temp, S_IRUGO|S_IWUSR,
736 show_pwm_auto_point_temp, store_pwm_auto_point_temp,
737 0, 0),
738 SENSOR_ATTR_2(pwm1_auto_point2_temp, S_IRUGO|S_IWUSR,
739 show_pwm_auto_point_temp, store_pwm_auto_point_temp,
740 1, 0),
741 SENSOR_ATTR_2(pwm1_auto_point3_temp, S_IRUGO|S_IWUSR,
742 show_pwm_auto_point_temp, store_pwm_auto_point_temp,
743 2, 0),
744 SENSOR_ATTR_2(pwm1_auto_point4_temp, S_IRUGO|S_IWUSR,
745 show_pwm_auto_point_temp, store_pwm_auto_point_temp,
746 3, 0),
747 SENSOR_ATTR_2(pwm1_auto_point1_temp_hyst, S_IRUGO|S_IWUSR,
748 show_pwm_auto_point_temp_hyst,
749 store_pwm_auto_point_temp_hyst,
750 0, 0),
751 SENSOR_ATTR_2(pwm1_auto_point2_temp_hyst, S_IRUGO,
752 show_pwm_auto_point_temp_hyst, NULL, 1, 0),
753 SENSOR_ATTR_2(pwm1_auto_point3_temp_hyst, S_IRUGO,
754 show_pwm_auto_point_temp_hyst, NULL, 2, 0),
755 SENSOR_ATTR_2(pwm1_auto_point4_temp_hyst, S_IRUGO,
756 show_pwm_auto_point_temp_hyst, NULL, 3, 0),
Hans de Goedeb69b0392009-12-09 20:36:00 +0100757}, {
Hans de Goede66344aa2009-12-09 20:35:59 +0100758 SENSOR_ATTR_2(pwm2_auto_channels_temp, S_IRUGO|S_IWUSR,
759 show_pwm_auto_point_channel,
760 store_pwm_auto_point_channel, 0, 1),
Mark van Doesburg9ab796e2009-01-07 16:37:27 +0100761 SENSOR_ATTR_2(pwm2_auto_point1_pwm, S_IRUGO|S_IWUSR,
762 show_pwm_auto_point_pwm, store_pwm_auto_point_pwm,
763 0, 1),
764 SENSOR_ATTR_2(pwm2_auto_point2_pwm, S_IRUGO|S_IWUSR,
765 show_pwm_auto_point_pwm, store_pwm_auto_point_pwm,
766 1, 1),
767 SENSOR_ATTR_2(pwm2_auto_point3_pwm, S_IRUGO|S_IWUSR,
768 show_pwm_auto_point_pwm, store_pwm_auto_point_pwm,
769 2, 1),
770 SENSOR_ATTR_2(pwm2_auto_point4_pwm, S_IRUGO|S_IWUSR,
771 show_pwm_auto_point_pwm, store_pwm_auto_point_pwm,
772 3, 1),
773 SENSOR_ATTR_2(pwm2_auto_point5_pwm, S_IRUGO|S_IWUSR,
774 show_pwm_auto_point_pwm, store_pwm_auto_point_pwm,
775 4, 1),
776 SENSOR_ATTR_2(pwm2_auto_point1_temp, S_IRUGO|S_IWUSR,
777 show_pwm_auto_point_temp, store_pwm_auto_point_temp,
778 0, 1),
779 SENSOR_ATTR_2(pwm2_auto_point2_temp, S_IRUGO|S_IWUSR,
780 show_pwm_auto_point_temp, store_pwm_auto_point_temp,
781 1, 1),
782 SENSOR_ATTR_2(pwm2_auto_point3_temp, S_IRUGO|S_IWUSR,
783 show_pwm_auto_point_temp, store_pwm_auto_point_temp,
784 2, 1),
785 SENSOR_ATTR_2(pwm2_auto_point4_temp, S_IRUGO|S_IWUSR,
786 show_pwm_auto_point_temp, store_pwm_auto_point_temp,
787 3, 1),
788 SENSOR_ATTR_2(pwm2_auto_point1_temp_hyst, S_IRUGO|S_IWUSR,
789 show_pwm_auto_point_temp_hyst,
790 store_pwm_auto_point_temp_hyst,
791 0, 1),
792 SENSOR_ATTR_2(pwm2_auto_point2_temp_hyst, S_IRUGO,
793 show_pwm_auto_point_temp_hyst, NULL, 1, 1),
794 SENSOR_ATTR_2(pwm2_auto_point3_temp_hyst, S_IRUGO,
795 show_pwm_auto_point_temp_hyst, NULL, 2, 1),
796 SENSOR_ATTR_2(pwm2_auto_point4_temp_hyst, S_IRUGO,
797 show_pwm_auto_point_temp_hyst, NULL, 3, 1),
Hans de Goedeb69b0392009-12-09 20:36:00 +0100798}, {
Hans de Goede66344aa2009-12-09 20:35:59 +0100799 SENSOR_ATTR_2(pwm3_auto_channels_temp, S_IRUGO|S_IWUSR,
800 show_pwm_auto_point_channel,
801 store_pwm_auto_point_channel, 0, 2),
Mark van Doesburg9ab796e2009-01-07 16:37:27 +0100802 SENSOR_ATTR_2(pwm3_auto_point1_pwm, S_IRUGO|S_IWUSR,
803 show_pwm_auto_point_pwm, store_pwm_auto_point_pwm,
804 0, 2),
805 SENSOR_ATTR_2(pwm3_auto_point2_pwm, S_IRUGO|S_IWUSR,
806 show_pwm_auto_point_pwm, store_pwm_auto_point_pwm,
807 1, 2),
808 SENSOR_ATTR_2(pwm3_auto_point3_pwm, S_IRUGO|S_IWUSR,
809 show_pwm_auto_point_pwm, store_pwm_auto_point_pwm,
810 2, 2),
811 SENSOR_ATTR_2(pwm3_auto_point4_pwm, S_IRUGO|S_IWUSR,
812 show_pwm_auto_point_pwm, store_pwm_auto_point_pwm,
813 3, 2),
814 SENSOR_ATTR_2(pwm3_auto_point5_pwm, S_IRUGO|S_IWUSR,
815 show_pwm_auto_point_pwm, store_pwm_auto_point_pwm,
816 4, 2),
817 SENSOR_ATTR_2(pwm3_auto_point1_temp, S_IRUGO|S_IWUSR,
818 show_pwm_auto_point_temp, store_pwm_auto_point_temp,
819 0, 2),
820 SENSOR_ATTR_2(pwm3_auto_point2_temp, S_IRUGO|S_IWUSR,
821 show_pwm_auto_point_temp, store_pwm_auto_point_temp,
822 1, 2),
823 SENSOR_ATTR_2(pwm3_auto_point3_temp, S_IRUGO|S_IWUSR,
824 show_pwm_auto_point_temp, store_pwm_auto_point_temp,
825 2, 2),
826 SENSOR_ATTR_2(pwm3_auto_point4_temp, S_IRUGO|S_IWUSR,
827 show_pwm_auto_point_temp, store_pwm_auto_point_temp,
828 3, 2),
829 SENSOR_ATTR_2(pwm3_auto_point1_temp_hyst, S_IRUGO|S_IWUSR,
830 show_pwm_auto_point_temp_hyst,
831 store_pwm_auto_point_temp_hyst,
832 0, 2),
833 SENSOR_ATTR_2(pwm3_auto_point2_temp_hyst, S_IRUGO,
834 show_pwm_auto_point_temp_hyst, NULL, 1, 2),
835 SENSOR_ATTR_2(pwm3_auto_point3_temp_hyst, S_IRUGO,
836 show_pwm_auto_point_temp_hyst, NULL, 2, 2),
837 SENSOR_ATTR_2(pwm3_auto_point4_temp_hyst, S_IRUGO,
838 show_pwm_auto_point_temp_hyst, NULL, 3, 2),
Hans de Goedeb69b0392009-12-09 20:36:00 +0100839}, {
Mark van Doesburg9ab796e2009-01-07 16:37:27 +0100840 SENSOR_ATTR_2(pwm4_auto_channels_temp, S_IRUGO|S_IWUSR,
841 show_pwm_auto_point_channel,
842 store_pwm_auto_point_channel, 0, 3),
843 SENSOR_ATTR_2(pwm4_auto_point1_pwm, S_IRUGO|S_IWUSR,
844 show_pwm_auto_point_pwm, store_pwm_auto_point_pwm,
845 0, 3),
846 SENSOR_ATTR_2(pwm4_auto_point2_pwm, S_IRUGO|S_IWUSR,
847 show_pwm_auto_point_pwm, store_pwm_auto_point_pwm,
848 1, 3),
849 SENSOR_ATTR_2(pwm4_auto_point3_pwm, S_IRUGO|S_IWUSR,
850 show_pwm_auto_point_pwm, store_pwm_auto_point_pwm,
851 2, 3),
852 SENSOR_ATTR_2(pwm4_auto_point4_pwm, S_IRUGO|S_IWUSR,
853 show_pwm_auto_point_pwm, store_pwm_auto_point_pwm,
854 3, 3),
855 SENSOR_ATTR_2(pwm4_auto_point5_pwm, S_IRUGO|S_IWUSR,
856 show_pwm_auto_point_pwm, store_pwm_auto_point_pwm,
857 4, 3),
858 SENSOR_ATTR_2(pwm4_auto_point1_temp, S_IRUGO|S_IWUSR,
859 show_pwm_auto_point_temp, store_pwm_auto_point_temp,
860 0, 3),
861 SENSOR_ATTR_2(pwm4_auto_point2_temp, S_IRUGO|S_IWUSR,
862 show_pwm_auto_point_temp, store_pwm_auto_point_temp,
863 1, 3),
864 SENSOR_ATTR_2(pwm4_auto_point3_temp, S_IRUGO|S_IWUSR,
865 show_pwm_auto_point_temp, store_pwm_auto_point_temp,
866 2, 3),
867 SENSOR_ATTR_2(pwm4_auto_point4_temp, S_IRUGO|S_IWUSR,
868 show_pwm_auto_point_temp, store_pwm_auto_point_temp,
869 3, 3),
870 SENSOR_ATTR_2(pwm4_auto_point1_temp_hyst, S_IRUGO|S_IWUSR,
871 show_pwm_auto_point_temp_hyst,
872 store_pwm_auto_point_temp_hyst,
873 0, 3),
874 SENSOR_ATTR_2(pwm4_auto_point2_temp_hyst, S_IRUGO,
875 show_pwm_auto_point_temp_hyst, NULL, 1, 3),
876 SENSOR_ATTR_2(pwm4_auto_point3_temp_hyst, S_IRUGO,
877 show_pwm_auto_point_temp_hyst, NULL, 2, 3),
878 SENSOR_ATTR_2(pwm4_auto_point4_temp_hyst, S_IRUGO,
879 show_pwm_auto_point_temp_hyst, NULL, 3, 3),
Hans de Goedeb69b0392009-12-09 20:36:00 +0100880} };
Hans de Goede45fb3662007-07-13 14:34:19 +0200881
Hans de Goede66344aa2009-12-09 20:35:59 +0100882/* Fan attr specific to the f8000 (4th fan input can only measure speed) */
Hans de Goedeed4f7c22009-01-07 16:37:30 +0100883static struct sensor_device_attribute_2 f8000_fan_attr[] = {
884 SENSOR_ATTR_2(fan4_input, S_IRUGO, show_fan, NULL, 0, 3),
Hans de Goede66344aa2009-12-09 20:35:59 +0100885};
Hans de Goedeed4f7c22009-01-07 16:37:30 +0100886
Hans de Goede66344aa2009-12-09 20:35:59 +0100887/* PWM attr for the f8000, zones mapped to temp instead of to pwm!
888 Also the register block at offset A0 maps to TEMP1 (so our temp2, as the
889 F8000 starts counting temps at 0), B0 maps the TEMP2 and C0 maps to TEMP0 */
890static struct sensor_device_attribute_2 f8000_auto_pwm_attr[] = {
891 SENSOR_ATTR_2(pwm1_auto_channels_temp, S_IRUGO|S_IWUSR,
892 show_pwm_auto_point_channel,
893 store_pwm_auto_point_channel, 0, 0),
Hans de Goedeed4f7c22009-01-07 16:37:30 +0100894 SENSOR_ATTR_2(temp1_auto_point1_pwm, S_IRUGO|S_IWUSR,
895 show_pwm_auto_point_pwm, store_pwm_auto_point_pwm,
896 0, 2),
897 SENSOR_ATTR_2(temp1_auto_point2_pwm, S_IRUGO|S_IWUSR,
898 show_pwm_auto_point_pwm, store_pwm_auto_point_pwm,
899 1, 2),
900 SENSOR_ATTR_2(temp1_auto_point3_pwm, S_IRUGO|S_IWUSR,
901 show_pwm_auto_point_pwm, store_pwm_auto_point_pwm,
902 2, 2),
903 SENSOR_ATTR_2(temp1_auto_point4_pwm, S_IRUGO|S_IWUSR,
904 show_pwm_auto_point_pwm, store_pwm_auto_point_pwm,
905 3, 2),
906 SENSOR_ATTR_2(temp1_auto_point5_pwm, S_IRUGO|S_IWUSR,
907 show_pwm_auto_point_pwm, store_pwm_auto_point_pwm,
908 4, 2),
909 SENSOR_ATTR_2(temp1_auto_point1_temp, S_IRUGO|S_IWUSR,
910 show_pwm_auto_point_temp, store_pwm_auto_point_temp,
911 0, 2),
912 SENSOR_ATTR_2(temp1_auto_point2_temp, S_IRUGO|S_IWUSR,
913 show_pwm_auto_point_temp, store_pwm_auto_point_temp,
914 1, 2),
915 SENSOR_ATTR_2(temp1_auto_point3_temp, S_IRUGO|S_IWUSR,
916 show_pwm_auto_point_temp, store_pwm_auto_point_temp,
917 2, 2),
918 SENSOR_ATTR_2(temp1_auto_point4_temp, S_IRUGO|S_IWUSR,
919 show_pwm_auto_point_temp, store_pwm_auto_point_temp,
920 3, 2),
921 SENSOR_ATTR_2(temp1_auto_point1_temp_hyst, S_IRUGO|S_IWUSR,
922 show_pwm_auto_point_temp_hyst,
923 store_pwm_auto_point_temp_hyst,
924 0, 2),
925 SENSOR_ATTR_2(temp1_auto_point2_temp_hyst, S_IRUGO,
926 show_pwm_auto_point_temp_hyst, NULL, 1, 2),
927 SENSOR_ATTR_2(temp1_auto_point3_temp_hyst, S_IRUGO,
928 show_pwm_auto_point_temp_hyst, NULL, 2, 2),
929 SENSOR_ATTR_2(temp1_auto_point4_temp_hyst, S_IRUGO,
930 show_pwm_auto_point_temp_hyst, NULL, 3, 2),
931
Hans de Goede66344aa2009-12-09 20:35:59 +0100932 SENSOR_ATTR_2(pwm2_auto_channels_temp, S_IRUGO|S_IWUSR,
933 show_pwm_auto_point_channel,
934 store_pwm_auto_point_channel, 0, 1),
Hans de Goedeed4f7c22009-01-07 16:37:30 +0100935 SENSOR_ATTR_2(temp2_auto_point1_pwm, S_IRUGO|S_IWUSR,
936 show_pwm_auto_point_pwm, store_pwm_auto_point_pwm,
937 0, 0),
938 SENSOR_ATTR_2(temp2_auto_point2_pwm, S_IRUGO|S_IWUSR,
939 show_pwm_auto_point_pwm, store_pwm_auto_point_pwm,
940 1, 0),
941 SENSOR_ATTR_2(temp2_auto_point3_pwm, S_IRUGO|S_IWUSR,
942 show_pwm_auto_point_pwm, store_pwm_auto_point_pwm,
943 2, 0),
944 SENSOR_ATTR_2(temp2_auto_point4_pwm, S_IRUGO|S_IWUSR,
945 show_pwm_auto_point_pwm, store_pwm_auto_point_pwm,
946 3, 0),
947 SENSOR_ATTR_2(temp2_auto_point5_pwm, S_IRUGO|S_IWUSR,
948 show_pwm_auto_point_pwm, store_pwm_auto_point_pwm,
949 4, 0),
950 SENSOR_ATTR_2(temp2_auto_point1_temp, S_IRUGO|S_IWUSR,
951 show_pwm_auto_point_temp, store_pwm_auto_point_temp,
952 0, 0),
953 SENSOR_ATTR_2(temp2_auto_point2_temp, S_IRUGO|S_IWUSR,
954 show_pwm_auto_point_temp, store_pwm_auto_point_temp,
955 1, 0),
956 SENSOR_ATTR_2(temp2_auto_point3_temp, S_IRUGO|S_IWUSR,
957 show_pwm_auto_point_temp, store_pwm_auto_point_temp,
958 2, 0),
959 SENSOR_ATTR_2(temp2_auto_point4_temp, S_IRUGO|S_IWUSR,
960 show_pwm_auto_point_temp, store_pwm_auto_point_temp,
961 3, 0),
962 SENSOR_ATTR_2(temp2_auto_point1_temp_hyst, S_IRUGO|S_IWUSR,
963 show_pwm_auto_point_temp_hyst,
964 store_pwm_auto_point_temp_hyst,
965 0, 0),
966 SENSOR_ATTR_2(temp2_auto_point2_temp_hyst, S_IRUGO,
967 show_pwm_auto_point_temp_hyst, NULL, 1, 0),
968 SENSOR_ATTR_2(temp2_auto_point3_temp_hyst, S_IRUGO,
969 show_pwm_auto_point_temp_hyst, NULL, 2, 0),
970 SENSOR_ATTR_2(temp2_auto_point4_temp_hyst, S_IRUGO,
971 show_pwm_auto_point_temp_hyst, NULL, 3, 0),
972
Hans de Goede66344aa2009-12-09 20:35:59 +0100973 SENSOR_ATTR_2(pwm3_auto_channels_temp, S_IRUGO|S_IWUSR,
974 show_pwm_auto_point_channel,
975 store_pwm_auto_point_channel, 0, 2),
Hans de Goedeed4f7c22009-01-07 16:37:30 +0100976 SENSOR_ATTR_2(temp3_auto_point1_pwm, S_IRUGO|S_IWUSR,
977 show_pwm_auto_point_pwm, store_pwm_auto_point_pwm,
978 0, 1),
979 SENSOR_ATTR_2(temp3_auto_point2_pwm, S_IRUGO|S_IWUSR,
980 show_pwm_auto_point_pwm, store_pwm_auto_point_pwm,
981 1, 1),
982 SENSOR_ATTR_2(temp3_auto_point3_pwm, S_IRUGO|S_IWUSR,
983 show_pwm_auto_point_pwm, store_pwm_auto_point_pwm,
984 2, 1),
985 SENSOR_ATTR_2(temp3_auto_point4_pwm, S_IRUGO|S_IWUSR,
986 show_pwm_auto_point_pwm, store_pwm_auto_point_pwm,
987 3, 1),
988 SENSOR_ATTR_2(temp3_auto_point5_pwm, S_IRUGO|S_IWUSR,
989 show_pwm_auto_point_pwm, store_pwm_auto_point_pwm,
990 4, 1),
991 SENSOR_ATTR_2(temp3_auto_point1_temp, S_IRUGO|S_IWUSR,
992 show_pwm_auto_point_temp, store_pwm_auto_point_temp,
993 0, 1),
994 SENSOR_ATTR_2(temp3_auto_point2_temp, S_IRUGO|S_IWUSR,
995 show_pwm_auto_point_temp, store_pwm_auto_point_temp,
996 1, 1),
997 SENSOR_ATTR_2(temp3_auto_point3_temp, S_IRUGO|S_IWUSR,
998 show_pwm_auto_point_temp, store_pwm_auto_point_temp,
999 2, 1),
1000 SENSOR_ATTR_2(temp3_auto_point4_temp, S_IRUGO|S_IWUSR,
1001 show_pwm_auto_point_temp, store_pwm_auto_point_temp,
1002 3, 1),
1003 SENSOR_ATTR_2(temp3_auto_point1_temp_hyst, S_IRUGO|S_IWUSR,
1004 show_pwm_auto_point_temp_hyst,
1005 store_pwm_auto_point_temp_hyst,
1006 0, 1),
1007 SENSOR_ATTR_2(temp3_auto_point2_temp_hyst, S_IRUGO,
1008 show_pwm_auto_point_temp_hyst, NULL, 1, 1),
1009 SENSOR_ATTR_2(temp3_auto_point3_temp_hyst, S_IRUGO,
1010 show_pwm_auto_point_temp_hyst, NULL, 2, 1),
1011 SENSOR_ATTR_2(temp3_auto_point4_temp_hyst, S_IRUGO,
1012 show_pwm_auto_point_temp_hyst, NULL, 3, 1),
1013};
Hans de Goede45fb3662007-07-13 14:34:19 +02001014
1015/* Super I/O functions */
1016static inline int superio_inb(int base, int reg)
1017{
1018 outb(reg, base);
1019 return inb(base + 1);
1020}
1021
1022static int superio_inw(int base, int reg)
1023{
1024 int val;
Giel van Schijndelbd328ac2010-05-27 19:58:42 +02001025 val = superio_inb(base, reg) << 8;
1026 val |= superio_inb(base, reg + 1);
Hans de Goede45fb3662007-07-13 14:34:19 +02001027 return val;
1028}
1029
Giel van Schijndelcadb8652010-10-03 08:09:49 -04001030static inline int superio_enter(int base)
Hans de Goede45fb3662007-07-13 14:34:19 +02001031{
Giel van Schijndelcadb8652010-10-03 08:09:49 -04001032 /* Don't step on other drivers' I/O space by accident */
1033 if (!request_muxed_region(base, 2, DRVNAME)) {
Joe Perches22d3b412010-10-20 06:51:34 +00001034 pr_err("I/O address 0x%04x already in use\n", base);
Giel van Schijndelcadb8652010-10-03 08:09:49 -04001035 return -EBUSY;
1036 }
1037
Hans de Goede45fb3662007-07-13 14:34:19 +02001038 /* according to the datasheet the key must be send twice! */
Giel van Schijndel162bb592010-05-27 19:58:40 +02001039 outb(SIO_UNLOCK_KEY, base);
1040 outb(SIO_UNLOCK_KEY, base);
Giel van Schijndelcadb8652010-10-03 08:09:49 -04001041
1042 return 0;
Hans de Goede45fb3662007-07-13 14:34:19 +02001043}
1044
Giel van Schijndel162bb592010-05-27 19:58:40 +02001045static inline void superio_select(int base, int ld)
Hans de Goede45fb3662007-07-13 14:34:19 +02001046{
1047 outb(SIO_REG_LDSEL, base);
1048 outb(ld, base + 1);
1049}
1050
1051static inline void superio_exit(int base)
1052{
1053 outb(SIO_LOCK_KEY, base);
Giel van Schijndelcadb8652010-10-03 08:09:49 -04001054 release_region(base, 2);
Hans de Goede45fb3662007-07-13 14:34:19 +02001055}
1056
Hans de Goede2f650632009-01-07 16:37:31 +01001057static inline int fan_from_reg(u16 reg)
Hans de Goede45fb3662007-07-13 14:34:19 +02001058{
1059 return reg ? (1500000 / reg) : 0;
1060}
1061
Hans de Goede2f650632009-01-07 16:37:31 +01001062static inline u16 fan_to_reg(int fan)
Mark van Doesburg9ab796e2009-01-07 16:37:27 +01001063{
1064 return fan ? (1500000 / fan) : 0;
1065}
1066
Hans de Goede45fb3662007-07-13 14:34:19 +02001067static u8 f71882fg_read8(struct f71882fg_data *data, u8 reg)
1068{
1069 u8 val;
1070
1071 outb(reg, data->addr + ADDR_REG_OFFSET);
1072 val = inb(data->addr + DATA_REG_OFFSET);
1073
1074 return val;
1075}
1076
1077static u16 f71882fg_read16(struct f71882fg_data *data, u8 reg)
1078{
1079 u16 val;
1080
Giel van Schijndelbd328ac2010-05-27 19:58:42 +02001081 val = f71882fg_read8(data, reg) << 8;
1082 val |= f71882fg_read8(data, reg + 1);
Hans de Goede45fb3662007-07-13 14:34:19 +02001083
1084 return val;
1085}
1086
1087static void f71882fg_write8(struct f71882fg_data *data, u8 reg, u8 val)
1088{
1089 outb(reg, data->addr + ADDR_REG_OFFSET);
1090 outb(val, data->addr + DATA_REG_OFFSET);
1091}
1092
Mark van Doesburg9ab796e2009-01-07 16:37:27 +01001093static void f71882fg_write16(struct f71882fg_data *data, u8 reg, u16 val)
1094{
Giel van Schijndelbd328ac2010-05-27 19:58:42 +02001095 f71882fg_write8(data, reg, val >> 8);
1096 f71882fg_write8(data, reg + 1, val & 0xff);
Mark van Doesburg9ab796e2009-01-07 16:37:27 +01001097}
1098
Hans de Goede09475d32009-06-15 18:39:52 +02001099static u16 f71882fg_read_temp(struct f71882fg_data *data, int nr)
1100{
1101 if (data->type == f71858fg)
1102 return f71882fg_read16(data, F71882FG_REG_TEMP(nr));
1103 else
1104 return f71882fg_read8(data, F71882FG_REG_TEMP(nr));
1105}
1106
Mark van Doesburg77a4a3e2009-01-07 16:37:27 +01001107static struct f71882fg_data *f71882fg_update_device(struct device *dev)
Hans de Goede45fb3662007-07-13 14:34:19 +02001108{
1109 struct f71882fg_data *data = dev_get_drvdata(dev);
Jean Delvaref27def02011-03-26 10:45:01 +01001110 int nr_fans = f71882fg_nr_fans[data->type];
1111 int nr_temps = f71882fg_nr_temps[data->type];
Hans de Goedee5e713c2011-03-10 08:54:02 +01001112 int nr, reg, point;
Hans de Goede45fb3662007-07-13 14:34:19 +02001113
1114 mutex_lock(&data->update_lock);
1115
1116 /* Update once every 60 seconds */
Giel van Schijndel162bb592010-05-27 19:58:40 +02001117 if (time_after(jiffies, data->last_limits + 60 * HZ) ||
Hans de Goede45fb3662007-07-13 14:34:19 +02001118 !data->valid) {
Hans de Goede0bae6402011-03-09 20:57:10 +01001119 if (f71882fg_has_in1_alarm[data->type]) {
Hans de Goede498be962009-01-07 16:37:28 +01001120 data->in1_max =
1121 f71882fg_read8(data, F71882FG_REG_IN1_HIGH);
1122 data->in_beep =
1123 f71882fg_read8(data, F71882FG_REG_IN_BEEP);
1124 }
Hans de Goede45fb3662007-07-13 14:34:19 +02001125
1126 /* Get High & boundary temps*/
Hans de Goedee5e713c2011-03-10 08:54:02 +01001127 for (nr = data->temp_start; nr < nr_temps + data->temp_start;
1128 nr++) {
Hans de Goede45fb3662007-07-13 14:34:19 +02001129 data->temp_ovt[nr] = f71882fg_read8(data,
1130 F71882FG_REG_TEMP_OVT(nr));
1131 data->temp_high[nr] = f71882fg_read8(data,
1132 F71882FG_REG_TEMP_HIGH(nr));
1133 }
1134
Hans de Goedeed4f7c22009-01-07 16:37:30 +01001135 if (data->type != f8000) {
Hans de Goedeed4f7c22009-01-07 16:37:30 +01001136 data->temp_hyst[0] = f71882fg_read8(data,
1137 F71882FG_REG_TEMP_HYST(0));
1138 data->temp_hyst[1] = f71882fg_read8(data,
1139 F71882FG_REG_TEMP_HYST(1));
Hans de Goede09475d32009-06-15 18:39:52 +02001140 }
Hans de Goede78aa4f72011-03-09 20:57:12 +01001141 /* All but the f71858fg / f8000 have this register */
1142 if ((data->type != f71858fg) && (data->type != f8000)) {
Hans de Goedeed4f7c22009-01-07 16:37:30 +01001143 reg = f71882fg_read8(data, F71882FG_REG_TEMP_TYPE);
Hans de Goede44c4dc52011-03-09 20:57:07 +01001144 data->temp_type[1] = (reg & 0x02) ? 2 : 4;
Hans de Goedeed4f7c22009-01-07 16:37:30 +01001145 data->temp_type[2] = (reg & 0x04) ? 2 : 4;
1146 data->temp_type[3] = (reg & 0x08) ? 2 : 4;
1147 }
Hans de Goede45fb3662007-07-13 14:34:19 +02001148
Hans de Goede78aa4f72011-03-09 20:57:12 +01001149 if (f71882fg_has_beep[data->type]) {
1150 data->fan_beep = f71882fg_read8(data,
1151 F71882FG_REG_FAN_BEEP);
1152 data->temp_beep = f71882fg_read8(data,
1153 F71882FG_REG_TEMP_BEEP);
1154 }
1155
Mark van Doesburg9ab796e2009-01-07 16:37:27 +01001156 data->pwm_enable = f71882fg_read8(data,
1157 F71882FG_REG_PWM_ENABLE);
Hans de Goedebc274902009-01-07 16:37:29 +01001158 data->pwm_auto_point_hyst[0] =
1159 f71882fg_read8(data, F71882FG_REG_FAN_HYST(0));
1160 data->pwm_auto_point_hyst[1] =
1161 f71882fg_read8(data, F71882FG_REG_FAN_HYST(1));
1162
Hans de Goede498be962009-01-07 16:37:28 +01001163 for (nr = 0; nr < nr_fans; nr++) {
Mark van Doesburg9ab796e2009-01-07 16:37:27 +01001164 data->pwm_auto_point_mapping[nr] =
1165 f71882fg_read8(data,
1166 F71882FG_REG_POINT_MAPPING(nr));
1167
Hans de Goedee5e713c2011-03-10 08:54:02 +01001168 switch (data->type) {
1169 default:
Hans de Goede498be962009-01-07 16:37:28 +01001170 for (point = 0; point < 5; point++) {
1171 data->pwm_auto_point_pwm[nr][point] =
1172 f71882fg_read8(data,
1173 F71882FG_REG_POINT_PWM
1174 (nr, point));
1175 }
1176 for (point = 0; point < 4; point++) {
1177 data->pwm_auto_point_temp[nr][point] =
1178 f71882fg_read8(data,
1179 F71882FG_REG_POINT_TEMP
1180 (nr, point));
1181 }
Hans de Goedee5e713c2011-03-10 08:54:02 +01001182 break;
1183 case f71808e:
1184 case f71869:
1185 data->pwm_auto_point_pwm[nr][0] =
1186 f71882fg_read8(data,
1187 F71882FG_REG_POINT_PWM(nr, 0));
1188 /* Fall through */
1189 case f71862fg:
Hans de Goede498be962009-01-07 16:37:28 +01001190 data->pwm_auto_point_pwm[nr][1] =
1191 f71882fg_read8(data,
1192 F71882FG_REG_POINT_PWM
1193 (nr, 1));
1194 data->pwm_auto_point_pwm[nr][4] =
1195 f71882fg_read8(data,
1196 F71882FG_REG_POINT_PWM
1197 (nr, 4));
1198 data->pwm_auto_point_temp[nr][0] =
1199 f71882fg_read8(data,
1200 F71882FG_REG_POINT_TEMP
1201 (nr, 0));
1202 data->pwm_auto_point_temp[nr][3] =
1203 f71882fg_read8(data,
1204 F71882FG_REG_POINT_TEMP
1205 (nr, 3));
Hans de Goedee5e713c2011-03-10 08:54:02 +01001206 break;
Mark van Doesburg9ab796e2009-01-07 16:37:27 +01001207 }
1208 }
Hans de Goede45fb3662007-07-13 14:34:19 +02001209 data->last_limits = jiffies;
1210 }
1211
1212 /* Update every second */
Mark M. Hoffman8afb1042007-08-21 23:10:46 -04001213 if (time_after(jiffies, data->last_updated + HZ) || !data->valid) {
Hans de Goede45fb3662007-07-13 14:34:19 +02001214 data->temp_status = f71882fg_read8(data,
1215 F71882FG_REG_TEMP_STATUS);
1216 data->temp_diode_open = f71882fg_read8(data,
1217 F71882FG_REG_TEMP_DIODE_OPEN);
Hans de Goedee5e713c2011-03-10 08:54:02 +01001218 for (nr = data->temp_start; nr < nr_temps + data->temp_start;
1219 nr++)
Hans de Goede09475d32009-06-15 18:39:52 +02001220 data->temp[nr] = f71882fg_read_temp(data, nr);
Hans de Goede45fb3662007-07-13 14:34:19 +02001221
1222 data->fan_status = f71882fg_read8(data,
1223 F71882FG_REG_FAN_STATUS);
Hans de Goede498be962009-01-07 16:37:28 +01001224 for (nr = 0; nr < nr_fans; nr++) {
Hans de Goede45fb3662007-07-13 14:34:19 +02001225 data->fan[nr] = f71882fg_read16(data,
1226 F71882FG_REG_FAN(nr));
Mark van Doesburg9ab796e2009-01-07 16:37:27 +01001227 data->fan_target[nr] =
1228 f71882fg_read16(data, F71882FG_REG_FAN_TARGET(nr));
1229 data->fan_full_speed[nr] =
1230 f71882fg_read16(data,
1231 F71882FG_REG_FAN_FULL_SPEED(nr));
1232 data->pwm[nr] =
1233 f71882fg_read8(data, F71882FG_REG_PWM(nr));
1234 }
Hans de Goedeed4f7c22009-01-07 16:37:30 +01001235 /* The f8000 can monitor 1 more fan, but has no pwm for it */
1236 if (data->type == f8000)
1237 data->fan[3] = f71882fg_read16(data,
1238 F71882FG_REG_FAN(3));
Hans de Goede0bae6402011-03-09 20:57:10 +01001239
1240 if (f71882fg_has_in1_alarm[data->type])
Hans de Goede498be962009-01-07 16:37:28 +01001241 data->in_status = f71882fg_read8(data,
Hans de Goede45fb3662007-07-13 14:34:19 +02001242 F71882FG_REG_IN_STATUS);
Hans de Goede0bae6402011-03-09 20:57:10 +01001243 for (nr = 0; nr < F71882FG_MAX_INS; nr++)
1244 if (f71882fg_has_in[data->type][nr])
1245 data->in[nr] = f71882fg_read8(data,
1246 F71882FG_REG_IN(nr));
Hans de Goede45fb3662007-07-13 14:34:19 +02001247
1248 data->last_updated = jiffies;
1249 data->valid = 1;
1250 }
1251
1252 mutex_unlock(&data->update_lock);
1253
1254 return data;
1255}
1256
1257/* Sysfs Interface */
1258static ssize_t show_fan(struct device *dev, struct device_attribute *devattr,
1259 char *buf)
1260{
1261 struct f71882fg_data *data = f71882fg_update_device(dev);
Mark van Doesburgbc37ae72009-01-07 16:37:27 +01001262 int nr = to_sensor_dev_attr_2(devattr)->index;
Hans de Goede45fb3662007-07-13 14:34:19 +02001263 int speed = fan_from_reg(data->fan[nr]);
1264
1265 if (speed == FAN_MIN_DETECT)
1266 speed = 0;
1267
1268 return sprintf(buf, "%d\n", speed);
1269}
1270
Mark van Doesburg9ab796e2009-01-07 16:37:27 +01001271static ssize_t show_fan_full_speed(struct device *dev,
1272 struct device_attribute *devattr, char *buf)
1273{
1274 struct f71882fg_data *data = f71882fg_update_device(dev);
1275 int nr = to_sensor_dev_attr_2(devattr)->index;
1276 int speed = fan_from_reg(data->fan_full_speed[nr]);
1277 return sprintf(buf, "%d\n", speed);
1278}
1279
1280static ssize_t store_fan_full_speed(struct device *dev,
1281 struct device_attribute *devattr,
1282 const char *buf, size_t count)
1283{
1284 struct f71882fg_data *data = dev_get_drvdata(dev);
Giel van Schijndele8a4eac2010-05-27 19:58:41 +02001285 int err, nr = to_sensor_dev_attr_2(devattr)->index;
1286 long val;
1287
1288 err = strict_strtol(buf, 10, &val);
1289 if (err)
1290 return err;
Mark van Doesburg9ab796e2009-01-07 16:37:27 +01001291
1292 val = SENSORS_LIMIT(val, 23, 1500000);
1293 val = fan_to_reg(val);
1294
1295 mutex_lock(&data->update_lock);
Hans de Goede4c82c382009-01-07 16:37:30 +01001296 f71882fg_write16(data, F71882FG_REG_FAN_FULL_SPEED(nr), val);
1297 data->fan_full_speed[nr] = val;
Mark van Doesburg9ab796e2009-01-07 16:37:27 +01001298 mutex_unlock(&data->update_lock);
1299
1300 return count;
1301}
1302
Hans de Goede45fb3662007-07-13 14:34:19 +02001303static ssize_t show_fan_beep(struct device *dev, struct device_attribute
1304 *devattr, char *buf)
1305{
1306 struct f71882fg_data *data = f71882fg_update_device(dev);
Mark van Doesburgbc37ae72009-01-07 16:37:27 +01001307 int nr = to_sensor_dev_attr_2(devattr)->index;
Hans de Goede45fb3662007-07-13 14:34:19 +02001308
1309 if (data->fan_beep & (1 << nr))
1310 return sprintf(buf, "1\n");
1311 else
1312 return sprintf(buf, "0\n");
1313}
1314
1315static ssize_t store_fan_beep(struct device *dev, struct device_attribute
1316 *devattr, const char *buf, size_t count)
1317{
1318 struct f71882fg_data *data = dev_get_drvdata(dev);
Giel van Schijndele8a4eac2010-05-27 19:58:41 +02001319 int err, nr = to_sensor_dev_attr_2(devattr)->index;
1320 unsigned long val;
1321
1322 err = strict_strtoul(buf, 10, &val);
1323 if (err)
1324 return err;
Hans de Goede45fb3662007-07-13 14:34:19 +02001325
1326 mutex_lock(&data->update_lock);
Hans de Goedece0bfa52009-01-07 16:37:28 +01001327 data->fan_beep = f71882fg_read8(data, F71882FG_REG_FAN_BEEP);
Hans de Goede45fb3662007-07-13 14:34:19 +02001328 if (val)
1329 data->fan_beep |= 1 << nr;
1330 else
1331 data->fan_beep &= ~(1 << nr);
1332
1333 f71882fg_write8(data, F71882FG_REG_FAN_BEEP, data->fan_beep);
1334 mutex_unlock(&data->update_lock);
1335
1336 return count;
1337}
1338
1339static ssize_t show_fan_alarm(struct device *dev, struct device_attribute
1340 *devattr, char *buf)
1341{
1342 struct f71882fg_data *data = f71882fg_update_device(dev);
Mark van Doesburgbc37ae72009-01-07 16:37:27 +01001343 int nr = to_sensor_dev_attr_2(devattr)->index;
Hans de Goede45fb3662007-07-13 14:34:19 +02001344
1345 if (data->fan_status & (1 << nr))
1346 return sprintf(buf, "1\n");
1347 else
1348 return sprintf(buf, "0\n");
1349}
1350
1351static ssize_t show_in(struct device *dev, struct device_attribute *devattr,
1352 char *buf)
1353{
1354 struct f71882fg_data *data = f71882fg_update_device(dev);
Mark van Doesburgbc37ae72009-01-07 16:37:27 +01001355 int nr = to_sensor_dev_attr_2(devattr)->index;
Hans de Goede45fb3662007-07-13 14:34:19 +02001356
1357 return sprintf(buf, "%d\n", data->in[nr] * 8);
1358}
1359
1360static ssize_t show_in_max(struct device *dev, struct device_attribute
1361 *devattr, char *buf)
1362{
1363 struct f71882fg_data *data = f71882fg_update_device(dev);
1364
1365 return sprintf(buf, "%d\n", data->in1_max * 8);
1366}
1367
1368static ssize_t store_in_max(struct device *dev, struct device_attribute
1369 *devattr, const char *buf, size_t count)
1370{
1371 struct f71882fg_data *data = dev_get_drvdata(dev);
Giel van Schijndele8a4eac2010-05-27 19:58:41 +02001372 int err;
1373 long val;
1374
1375 err = strict_strtol(buf, 10, &val);
1376 if (err)
1377 return err;
1378
1379 val /= 8;
Hans de Goedece0bfa52009-01-07 16:37:28 +01001380 val = SENSORS_LIMIT(val, 0, 255);
Hans de Goede45fb3662007-07-13 14:34:19 +02001381
1382 mutex_lock(&data->update_lock);
1383 f71882fg_write8(data, F71882FG_REG_IN1_HIGH, val);
1384 data->in1_max = val;
1385 mutex_unlock(&data->update_lock);
1386
1387 return count;
1388}
1389
1390static ssize_t show_in_beep(struct device *dev, struct device_attribute
1391 *devattr, char *buf)
1392{
1393 struct f71882fg_data *data = f71882fg_update_device(dev);
Mark van Doesburgbc37ae72009-01-07 16:37:27 +01001394 int nr = to_sensor_dev_attr_2(devattr)->index;
Hans de Goede45fb3662007-07-13 14:34:19 +02001395
1396 if (data->in_beep & (1 << nr))
1397 return sprintf(buf, "1\n");
1398 else
1399 return sprintf(buf, "0\n");
1400}
1401
1402static ssize_t store_in_beep(struct device *dev, struct device_attribute
1403 *devattr, const char *buf, size_t count)
1404{
1405 struct f71882fg_data *data = dev_get_drvdata(dev);
Giel van Schijndele8a4eac2010-05-27 19:58:41 +02001406 int err, nr = to_sensor_dev_attr_2(devattr)->index;
1407 unsigned long val;
1408
1409 err = strict_strtoul(buf, 10, &val);
1410 if (err)
1411 return err;
Hans de Goede45fb3662007-07-13 14:34:19 +02001412
1413 mutex_lock(&data->update_lock);
Hans de Goedece0bfa52009-01-07 16:37:28 +01001414 data->in_beep = f71882fg_read8(data, F71882FG_REG_IN_BEEP);
Hans de Goede45fb3662007-07-13 14:34:19 +02001415 if (val)
1416 data->in_beep |= 1 << nr;
1417 else
1418 data->in_beep &= ~(1 << nr);
1419
1420 f71882fg_write8(data, F71882FG_REG_IN_BEEP, data->in_beep);
1421 mutex_unlock(&data->update_lock);
1422
1423 return count;
1424}
1425
1426static ssize_t show_in_alarm(struct device *dev, struct device_attribute
1427 *devattr, char *buf)
1428{
1429 struct f71882fg_data *data = f71882fg_update_device(dev);
Mark van Doesburgbc37ae72009-01-07 16:37:27 +01001430 int nr = to_sensor_dev_attr_2(devattr)->index;
Hans de Goede45fb3662007-07-13 14:34:19 +02001431
1432 if (data->in_status & (1 << nr))
1433 return sprintf(buf, "1\n");
1434 else
1435 return sprintf(buf, "0\n");
1436}
1437
1438static ssize_t show_temp(struct device *dev, struct device_attribute *devattr,
1439 char *buf)
1440{
1441 struct f71882fg_data *data = f71882fg_update_device(dev);
Mark van Doesburgbc37ae72009-01-07 16:37:27 +01001442 int nr = to_sensor_dev_attr_2(devattr)->index;
Hans de Goede09475d32009-06-15 18:39:52 +02001443 int sign, temp;
Hans de Goede45fb3662007-07-13 14:34:19 +02001444
Hans de Goede09475d32009-06-15 18:39:52 +02001445 if (data->type == f71858fg) {
1446 /* TEMP_TABLE_SEL 1 or 3 ? */
1447 if (data->temp_config & 1) {
1448 sign = data->temp[nr] & 0x0001;
1449 temp = (data->temp[nr] >> 5) & 0x7ff;
1450 } else {
1451 sign = data->temp[nr] & 0x8000;
1452 temp = (data->temp[nr] >> 5) & 0x3ff;
1453 }
1454 temp *= 125;
1455 if (sign)
1456 temp -= 128000;
1457 } else
1458 temp = data->temp[nr] * 1000;
1459
1460 return sprintf(buf, "%d\n", temp);
Hans de Goede45fb3662007-07-13 14:34:19 +02001461}
1462
1463static ssize_t show_temp_max(struct device *dev, struct device_attribute
1464 *devattr, char *buf)
1465{
1466 struct f71882fg_data *data = f71882fg_update_device(dev);
Mark van Doesburgbc37ae72009-01-07 16:37:27 +01001467 int nr = to_sensor_dev_attr_2(devattr)->index;
Hans de Goede45fb3662007-07-13 14:34:19 +02001468
1469 return sprintf(buf, "%d\n", data->temp_high[nr] * 1000);
1470}
1471
1472static ssize_t store_temp_max(struct device *dev, struct device_attribute
1473 *devattr, const char *buf, size_t count)
1474{
1475 struct f71882fg_data *data = dev_get_drvdata(dev);
Giel van Schijndele8a4eac2010-05-27 19:58:41 +02001476 int err, nr = to_sensor_dev_attr_2(devattr)->index;
1477 long val;
1478
1479 err = strict_strtol(buf, 10, &val);
1480 if (err)
1481 return err;
1482
1483 val /= 1000;
Hans de Goedece0bfa52009-01-07 16:37:28 +01001484 val = SENSORS_LIMIT(val, 0, 255);
Hans de Goede45fb3662007-07-13 14:34:19 +02001485
1486 mutex_lock(&data->update_lock);
1487 f71882fg_write8(data, F71882FG_REG_TEMP_HIGH(nr), val);
1488 data->temp_high[nr] = val;
1489 mutex_unlock(&data->update_lock);
1490
1491 return count;
1492}
1493
1494static ssize_t show_temp_max_hyst(struct device *dev, struct device_attribute
1495 *devattr, char *buf)
1496{
1497 struct f71882fg_data *data = f71882fg_update_device(dev);
Mark van Doesburgbc37ae72009-01-07 16:37:27 +01001498 int nr = to_sensor_dev_attr_2(devattr)->index;
Hans de Goedece0bfa52009-01-07 16:37:28 +01001499 int temp_max_hyst;
Hans de Goede45fb3662007-07-13 14:34:19 +02001500
Hans de Goedece0bfa52009-01-07 16:37:28 +01001501 mutex_lock(&data->update_lock);
Hans de Goedebc274902009-01-07 16:37:29 +01001502 if (nr & 1)
1503 temp_max_hyst = data->temp_hyst[nr / 2] >> 4;
1504 else
1505 temp_max_hyst = data->temp_hyst[nr / 2] & 0x0f;
1506 temp_max_hyst = (data->temp_high[nr] - temp_max_hyst) * 1000;
Hans de Goedece0bfa52009-01-07 16:37:28 +01001507 mutex_unlock(&data->update_lock);
1508
1509 return sprintf(buf, "%d\n", temp_max_hyst);
Hans de Goede45fb3662007-07-13 14:34:19 +02001510}
1511
1512static ssize_t store_temp_max_hyst(struct device *dev, struct device_attribute
1513 *devattr, const char *buf, size_t count)
1514{
1515 struct f71882fg_data *data = dev_get_drvdata(dev);
Giel van Schijndele8a4eac2010-05-27 19:58:41 +02001516 int err, nr = to_sensor_dev_attr_2(devattr)->index;
Hans de Goede45fb3662007-07-13 14:34:19 +02001517 ssize_t ret = count;
Hans de Goedece0bfa52009-01-07 16:37:28 +01001518 u8 reg;
Giel van Schijndele8a4eac2010-05-27 19:58:41 +02001519 long val;
1520
1521 err = strict_strtol(buf, 10, &val);
1522 if (err)
1523 return err;
1524
1525 val /= 1000;
Hans de Goede45fb3662007-07-13 14:34:19 +02001526
1527 mutex_lock(&data->update_lock);
1528
1529 /* convert abs to relative and check */
Hans de Goedece0bfa52009-01-07 16:37:28 +01001530 data->temp_high[nr] = f71882fg_read8(data, F71882FG_REG_TEMP_HIGH(nr));
1531 val = SENSORS_LIMIT(val, data->temp_high[nr] - 15,
1532 data->temp_high[nr]);
Hans de Goede45fb3662007-07-13 14:34:19 +02001533 val = data->temp_high[nr] - val;
Hans de Goede45fb3662007-07-13 14:34:19 +02001534
1535 /* convert value to register contents */
Hans de Goedebc274902009-01-07 16:37:29 +01001536 reg = f71882fg_read8(data, F71882FG_REG_TEMP_HYST(nr / 2));
1537 if (nr & 1)
1538 reg = (reg & 0x0f) | (val << 4);
1539 else
1540 reg = (reg & 0xf0) | val;
1541 f71882fg_write8(data, F71882FG_REG_TEMP_HYST(nr / 2), reg);
1542 data->temp_hyst[nr / 2] = reg;
Hans de Goede45fb3662007-07-13 14:34:19 +02001543
Hans de Goede45fb3662007-07-13 14:34:19 +02001544 mutex_unlock(&data->update_lock);
1545 return ret;
1546}
1547
1548static ssize_t show_temp_crit(struct device *dev, struct device_attribute
1549 *devattr, char *buf)
1550{
1551 struct f71882fg_data *data = f71882fg_update_device(dev);
Mark van Doesburgbc37ae72009-01-07 16:37:27 +01001552 int nr = to_sensor_dev_attr_2(devattr)->index;
Hans de Goede45fb3662007-07-13 14:34:19 +02001553
1554 return sprintf(buf, "%d\n", data->temp_ovt[nr] * 1000);
1555}
1556
1557static ssize_t store_temp_crit(struct device *dev, struct device_attribute
1558 *devattr, const char *buf, size_t count)
1559{
1560 struct f71882fg_data *data = dev_get_drvdata(dev);
Giel van Schijndele8a4eac2010-05-27 19:58:41 +02001561 int err, nr = to_sensor_dev_attr_2(devattr)->index;
1562 long val;
1563
1564 err = strict_strtol(buf, 10, &val);
1565 if (err)
1566 return err;
1567
1568 val /= 1000;
Hans de Goedece0bfa52009-01-07 16:37:28 +01001569 val = SENSORS_LIMIT(val, 0, 255);
Hans de Goede45fb3662007-07-13 14:34:19 +02001570
1571 mutex_lock(&data->update_lock);
1572 f71882fg_write8(data, F71882FG_REG_TEMP_OVT(nr), val);
1573 data->temp_ovt[nr] = val;
1574 mutex_unlock(&data->update_lock);
1575
1576 return count;
1577}
1578
1579static ssize_t show_temp_crit_hyst(struct device *dev, struct device_attribute
1580 *devattr, char *buf)
1581{
1582 struct f71882fg_data *data = f71882fg_update_device(dev);
Mark van Doesburgbc37ae72009-01-07 16:37:27 +01001583 int nr = to_sensor_dev_attr_2(devattr)->index;
Hans de Goedece0bfa52009-01-07 16:37:28 +01001584 int temp_crit_hyst;
Hans de Goede45fb3662007-07-13 14:34:19 +02001585
Hans de Goedece0bfa52009-01-07 16:37:28 +01001586 mutex_lock(&data->update_lock);
Hans de Goedebc274902009-01-07 16:37:29 +01001587 if (nr & 1)
1588 temp_crit_hyst = data->temp_hyst[nr / 2] >> 4;
1589 else
1590 temp_crit_hyst = data->temp_hyst[nr / 2] & 0x0f;
1591 temp_crit_hyst = (data->temp_ovt[nr] - temp_crit_hyst) * 1000;
Hans de Goedece0bfa52009-01-07 16:37:28 +01001592 mutex_unlock(&data->update_lock);
1593
1594 return sprintf(buf, "%d\n", temp_crit_hyst);
Hans de Goede45fb3662007-07-13 14:34:19 +02001595}
1596
1597static ssize_t show_temp_type(struct device *dev, struct device_attribute
1598 *devattr, char *buf)
1599{
1600 struct f71882fg_data *data = f71882fg_update_device(dev);
Mark van Doesburgbc37ae72009-01-07 16:37:27 +01001601 int nr = to_sensor_dev_attr_2(devattr)->index;
Hans de Goede45fb3662007-07-13 14:34:19 +02001602
1603 return sprintf(buf, "%d\n", data->temp_type[nr]);
1604}
1605
1606static ssize_t show_temp_beep(struct device *dev, struct device_attribute
1607 *devattr, char *buf)
1608{
1609 struct f71882fg_data *data = f71882fg_update_device(dev);
Mark van Doesburgbc37ae72009-01-07 16:37:27 +01001610 int nr = to_sensor_dev_attr_2(devattr)->index;
Hans de Goede45fb3662007-07-13 14:34:19 +02001611
Hans de Goede7567a042009-01-07 16:37:28 +01001612 if (data->temp_beep & (1 << nr))
Hans de Goede45fb3662007-07-13 14:34:19 +02001613 return sprintf(buf, "1\n");
1614 else
1615 return sprintf(buf, "0\n");
1616}
1617
1618static ssize_t store_temp_beep(struct device *dev, struct device_attribute
1619 *devattr, const char *buf, size_t count)
1620{
1621 struct f71882fg_data *data = dev_get_drvdata(dev);
Giel van Schijndele8a4eac2010-05-27 19:58:41 +02001622 int err, nr = to_sensor_dev_attr_2(devattr)->index;
1623 unsigned long val;
1624
1625 err = strict_strtoul(buf, 10, &val);
1626 if (err)
1627 return err;
Hans de Goede45fb3662007-07-13 14:34:19 +02001628
1629 mutex_lock(&data->update_lock);
Hans de Goedece0bfa52009-01-07 16:37:28 +01001630 data->temp_beep = f71882fg_read8(data, F71882FG_REG_TEMP_BEEP);
Hans de Goede45fb3662007-07-13 14:34:19 +02001631 if (val)
Hans de Goede7567a042009-01-07 16:37:28 +01001632 data->temp_beep |= 1 << nr;
Hans de Goede45fb3662007-07-13 14:34:19 +02001633 else
Hans de Goede7567a042009-01-07 16:37:28 +01001634 data->temp_beep &= ~(1 << nr);
Hans de Goede45fb3662007-07-13 14:34:19 +02001635
1636 f71882fg_write8(data, F71882FG_REG_TEMP_BEEP, data->temp_beep);
1637 mutex_unlock(&data->update_lock);
1638
1639 return count;
1640}
1641
1642static ssize_t show_temp_alarm(struct device *dev, struct device_attribute
1643 *devattr, char *buf)
1644{
1645 struct f71882fg_data *data = f71882fg_update_device(dev);
Mark van Doesburgbc37ae72009-01-07 16:37:27 +01001646 int nr = to_sensor_dev_attr_2(devattr)->index;
Hans de Goede45fb3662007-07-13 14:34:19 +02001647
Hans de Goede7567a042009-01-07 16:37:28 +01001648 if (data->temp_status & (1 << nr))
Hans de Goede45fb3662007-07-13 14:34:19 +02001649 return sprintf(buf, "1\n");
1650 else
1651 return sprintf(buf, "0\n");
1652}
1653
1654static ssize_t show_temp_fault(struct device *dev, struct device_attribute
1655 *devattr, char *buf)
1656{
1657 struct f71882fg_data *data = f71882fg_update_device(dev);
Mark van Doesburgbc37ae72009-01-07 16:37:27 +01001658 int nr = to_sensor_dev_attr_2(devattr)->index;
Hans de Goede45fb3662007-07-13 14:34:19 +02001659
Hans de Goede7567a042009-01-07 16:37:28 +01001660 if (data->temp_diode_open & (1 << nr))
Hans de Goede45fb3662007-07-13 14:34:19 +02001661 return sprintf(buf, "1\n");
1662 else
1663 return sprintf(buf, "0\n");
1664}
1665
Mark van Doesburg9ab796e2009-01-07 16:37:27 +01001666static ssize_t show_pwm(struct device *dev,
1667 struct device_attribute *devattr, char *buf)
1668{
1669 struct f71882fg_data *data = f71882fg_update_device(dev);
1670 int val, nr = to_sensor_dev_attr_2(devattr)->index;
Hans de Goedece0bfa52009-01-07 16:37:28 +01001671 mutex_lock(&data->update_lock);
Mark van Doesburg9ab796e2009-01-07 16:37:27 +01001672 if (data->pwm_enable & (1 << (2 * nr)))
1673 /* PWM mode */
1674 val = data->pwm[nr];
1675 else {
1676 /* RPM mode */
Mark van Doesburg9ab796e2009-01-07 16:37:27 +01001677 val = 255 * fan_from_reg(data->fan_target[nr])
1678 / fan_from_reg(data->fan_full_speed[nr]);
Mark van Doesburg9ab796e2009-01-07 16:37:27 +01001679 }
Hans de Goedece0bfa52009-01-07 16:37:28 +01001680 mutex_unlock(&data->update_lock);
Mark van Doesburg9ab796e2009-01-07 16:37:27 +01001681 return sprintf(buf, "%d\n", val);
1682}
1683
1684static ssize_t store_pwm(struct device *dev,
1685 struct device_attribute *devattr, const char *buf,
1686 size_t count)
1687{
Hans de Goedece0bfa52009-01-07 16:37:28 +01001688 struct f71882fg_data *data = dev_get_drvdata(dev);
Giel van Schijndele8a4eac2010-05-27 19:58:41 +02001689 int err, nr = to_sensor_dev_attr_2(devattr)->index;
1690 long val;
1691
1692 err = strict_strtol(buf, 10, &val);
1693 if (err)
1694 return err;
1695
Mark van Doesburg9ab796e2009-01-07 16:37:27 +01001696 val = SENSORS_LIMIT(val, 0, 255);
1697
1698 mutex_lock(&data->update_lock);
Hans de Goedece0bfa52009-01-07 16:37:28 +01001699 data->pwm_enable = f71882fg_read8(data, F71882FG_REG_PWM_ENABLE);
Hans de Goedeed4f7c22009-01-07 16:37:30 +01001700 if ((data->type == f8000 && ((data->pwm_enable >> 2 * nr) & 3) != 2) ||
1701 (data->type != f8000 && !((data->pwm_enable >> 2 * nr) & 2))) {
1702 count = -EROFS;
1703 goto leave;
1704 }
Mark van Doesburg9ab796e2009-01-07 16:37:27 +01001705 if (data->pwm_enable & (1 << (2 * nr))) {
1706 /* PWM mode */
1707 f71882fg_write8(data, F71882FG_REG_PWM(nr), val);
1708 data->pwm[nr] = val;
1709 } else {
1710 /* RPM mode */
Hans de Goedece0bfa52009-01-07 16:37:28 +01001711 int target, full_speed;
1712 full_speed = f71882fg_read16(data,
1713 F71882FG_REG_FAN_FULL_SPEED(nr));
1714 target = fan_to_reg(val * fan_from_reg(full_speed) / 255);
1715 f71882fg_write16(data, F71882FG_REG_FAN_TARGET(nr), target);
1716 data->fan_target[nr] = target;
1717 data->fan_full_speed[nr] = full_speed;
Mark van Doesburg9ab796e2009-01-07 16:37:27 +01001718 }
Hans de Goedeed4f7c22009-01-07 16:37:30 +01001719leave:
Mark van Doesburg9ab796e2009-01-07 16:37:27 +01001720 mutex_unlock(&data->update_lock);
1721
1722 return count;
1723}
1724
1725static ssize_t show_pwm_enable(struct device *dev,
1726 struct device_attribute *devattr, char *buf)
1727{
Hans de Goedeed4f7c22009-01-07 16:37:30 +01001728 int result = 0;
Mark van Doesburg9ab796e2009-01-07 16:37:27 +01001729 struct f71882fg_data *data = f71882fg_update_device(dev);
1730 int nr = to_sensor_dev_attr_2(devattr)->index;
1731
Hans de Goedeed4f7c22009-01-07 16:37:30 +01001732 switch ((data->pwm_enable >> 2 * nr) & 3) {
1733 case 0:
1734 case 1:
1735 result = 2; /* Normal auto mode */
1736 break;
1737 case 2:
1738 result = 1; /* Manual mode */
1739 break;
1740 case 3:
1741 if (data->type == f8000)
1742 result = 3; /* Thermostat mode */
1743 else
1744 result = 1; /* Manual mode */
1745 break;
1746 }
Mark van Doesburg9ab796e2009-01-07 16:37:27 +01001747
1748 return sprintf(buf, "%d\n", result);
1749}
1750
1751static ssize_t store_pwm_enable(struct device *dev, struct device_attribute
1752 *devattr, const char *buf, size_t count)
1753{
1754 struct f71882fg_data *data = dev_get_drvdata(dev);
Giel van Schijndele8a4eac2010-05-27 19:58:41 +02001755 int err, nr = to_sensor_dev_attr_2(devattr)->index;
1756 long val;
1757
1758 err = strict_strtol(buf, 10, &val);
1759 if (err)
1760 return err;
Mark van Doesburg9ab796e2009-01-07 16:37:27 +01001761
Hans de Goede3fc78382009-06-15 18:39:50 +02001762 /* Special case for F8000 pwm channel 3 which only does auto mode */
1763 if (data->type == f8000 && nr == 2 && val != 2)
1764 return -EINVAL;
1765
Mark van Doesburg9ab796e2009-01-07 16:37:27 +01001766 mutex_lock(&data->update_lock);
Hans de Goedece0bfa52009-01-07 16:37:28 +01001767 data->pwm_enable = f71882fg_read8(data, F71882FG_REG_PWM_ENABLE);
Hans de Goedeed4f7c22009-01-07 16:37:30 +01001768 /* Special case for F8000 auto PWM mode / Thermostat mode */
1769 if (data->type == f8000 && ((data->pwm_enable >> 2 * nr) & 1)) {
1770 switch (val) {
1771 case 2:
1772 data->pwm_enable &= ~(2 << (2 * nr));
1773 break; /* Normal auto mode */
1774 case 3:
1775 data->pwm_enable |= 2 << (2 * nr);
1776 break; /* Thermostat mode */
1777 default:
1778 count = -EINVAL;
1779 goto leave;
1780 }
1781 } else {
1782 switch (val) {
1783 case 1:
Hans de Goede09475d32009-06-15 18:39:52 +02001784 /* The f71858fg does not support manual RPM mode */
1785 if (data->type == f71858fg &&
1786 ((data->pwm_enable >> (2 * nr)) & 1)) {
1787 count = -EINVAL;
1788 goto leave;
1789 }
Hans de Goedeed4f7c22009-01-07 16:37:30 +01001790 data->pwm_enable |= 2 << (2 * nr);
1791 break; /* Manual */
1792 case 2:
1793 data->pwm_enable &= ~(2 << (2 * nr));
1794 break; /* Normal auto mode */
1795 default:
1796 count = -EINVAL;
1797 goto leave;
1798 }
Mark van Doesburg9ab796e2009-01-07 16:37:27 +01001799 }
Mark van Doesburg9ab796e2009-01-07 16:37:27 +01001800 f71882fg_write8(data, F71882FG_REG_PWM_ENABLE, data->pwm_enable);
Hans de Goedeed4f7c22009-01-07 16:37:30 +01001801leave:
Mark van Doesburg9ab796e2009-01-07 16:37:27 +01001802 mutex_unlock(&data->update_lock);
1803
1804 return count;
1805}
1806
1807static ssize_t show_pwm_auto_point_pwm(struct device *dev,
1808 struct device_attribute *devattr,
1809 char *buf)
1810{
1811 int result;
1812 struct f71882fg_data *data = f71882fg_update_device(dev);
1813 int pwm = to_sensor_dev_attr_2(devattr)->index;
1814 int point = to_sensor_dev_attr_2(devattr)->nr;
1815
Hans de Goedece0bfa52009-01-07 16:37:28 +01001816 mutex_lock(&data->update_lock);
Mark van Doesburg9ab796e2009-01-07 16:37:27 +01001817 if (data->pwm_enable & (1 << (2 * pwm))) {
1818 /* PWM mode */
1819 result = data->pwm_auto_point_pwm[pwm][point];
1820 } else {
1821 /* RPM mode */
1822 result = 32 * 255 / (32 + data->pwm_auto_point_pwm[pwm][point]);
1823 }
Hans de Goedece0bfa52009-01-07 16:37:28 +01001824 mutex_unlock(&data->update_lock);
Mark van Doesburg9ab796e2009-01-07 16:37:27 +01001825
1826 return sprintf(buf, "%d\n", result);
1827}
1828
1829static ssize_t store_pwm_auto_point_pwm(struct device *dev,
1830 struct device_attribute *devattr,
1831 const char *buf, size_t count)
1832{
Hans de Goedece0bfa52009-01-07 16:37:28 +01001833 struct f71882fg_data *data = dev_get_drvdata(dev);
Giel van Schijndele8a4eac2010-05-27 19:58:41 +02001834 int err, pwm = to_sensor_dev_attr_2(devattr)->index;
Mark van Doesburg9ab796e2009-01-07 16:37:27 +01001835 int point = to_sensor_dev_attr_2(devattr)->nr;
Giel van Schijndele8a4eac2010-05-27 19:58:41 +02001836 long val;
1837
1838 err = strict_strtol(buf, 10, &val);
1839 if (err)
1840 return err;
1841
Mark van Doesburg9ab796e2009-01-07 16:37:27 +01001842 val = SENSORS_LIMIT(val, 0, 255);
1843
1844 mutex_lock(&data->update_lock);
Hans de Goedece0bfa52009-01-07 16:37:28 +01001845 data->pwm_enable = f71882fg_read8(data, F71882FG_REG_PWM_ENABLE);
Mark van Doesburg9ab796e2009-01-07 16:37:27 +01001846 if (data->pwm_enable & (1 << (2 * pwm))) {
1847 /* PWM mode */
1848 } else {
1849 /* RPM mode */
1850 if (val < 29) /* Prevent negative numbers */
1851 val = 255;
1852 else
1853 val = (255 - val) * 32 / val;
1854 }
1855 f71882fg_write8(data, F71882FG_REG_POINT_PWM(pwm, point), val);
1856 data->pwm_auto_point_pwm[pwm][point] = val;
1857 mutex_unlock(&data->update_lock);
1858
1859 return count;
1860}
1861
1862static ssize_t show_pwm_auto_point_temp_hyst(struct device *dev,
1863 struct device_attribute *devattr,
1864 char *buf)
1865{
1866 int result = 0;
1867 struct f71882fg_data *data = f71882fg_update_device(dev);
1868 int nr = to_sensor_dev_attr_2(devattr)->index;
1869 int point = to_sensor_dev_attr_2(devattr)->nr;
1870
1871 mutex_lock(&data->update_lock);
Hans de Goedebc274902009-01-07 16:37:29 +01001872 if (nr & 1)
1873 result = data->pwm_auto_point_hyst[nr / 2] >> 4;
1874 else
1875 result = data->pwm_auto_point_hyst[nr / 2] & 0x0f;
Mark van Doesburg9ab796e2009-01-07 16:37:27 +01001876 result = 1000 * (data->pwm_auto_point_temp[nr][point] - result);
1877 mutex_unlock(&data->update_lock);
1878
1879 return sprintf(buf, "%d\n", result);
1880}
1881
1882static ssize_t store_pwm_auto_point_temp_hyst(struct device *dev,
1883 struct device_attribute *devattr,
1884 const char *buf, size_t count)
1885{
Hans de Goedece0bfa52009-01-07 16:37:28 +01001886 struct f71882fg_data *data = dev_get_drvdata(dev);
Giel van Schijndele8a4eac2010-05-27 19:58:41 +02001887 int err, nr = to_sensor_dev_attr_2(devattr)->index;
Mark van Doesburg9ab796e2009-01-07 16:37:27 +01001888 int point = to_sensor_dev_attr_2(devattr)->nr;
Hans de Goedebc274902009-01-07 16:37:29 +01001889 u8 reg;
Giel van Schijndele8a4eac2010-05-27 19:58:41 +02001890 long val;
1891
1892 err = strict_strtol(buf, 10, &val);
1893 if (err)
1894 return err;
1895
1896 val /= 1000;
Mark van Doesburg9ab796e2009-01-07 16:37:27 +01001897
1898 mutex_lock(&data->update_lock);
Hans de Goedece0bfa52009-01-07 16:37:28 +01001899 data->pwm_auto_point_temp[nr][point] =
1900 f71882fg_read8(data, F71882FG_REG_POINT_TEMP(nr, point));
Mark van Doesburg9ab796e2009-01-07 16:37:27 +01001901 val = SENSORS_LIMIT(val, data->pwm_auto_point_temp[nr][point] - 15,
1902 data->pwm_auto_point_temp[nr][point]);
1903 val = data->pwm_auto_point_temp[nr][point] - val;
1904
Hans de Goedebc274902009-01-07 16:37:29 +01001905 reg = f71882fg_read8(data, F71882FG_REG_FAN_HYST(nr / 2));
1906 if (nr & 1)
1907 reg = (reg & 0x0f) | (val << 4);
1908 else
1909 reg = (reg & 0xf0) | val;
1910
1911 f71882fg_write8(data, F71882FG_REG_FAN_HYST(nr / 2), reg);
1912 data->pwm_auto_point_hyst[nr / 2] = reg;
Mark van Doesburg9ab796e2009-01-07 16:37:27 +01001913 mutex_unlock(&data->update_lock);
1914
1915 return count;
1916}
1917
1918static ssize_t show_pwm_interpolate(struct device *dev,
1919 struct device_attribute *devattr, char *buf)
1920{
1921 int result;
1922 struct f71882fg_data *data = f71882fg_update_device(dev);
1923 int nr = to_sensor_dev_attr_2(devattr)->index;
1924
1925 result = (data->pwm_auto_point_mapping[nr] >> 4) & 1;
1926
1927 return sprintf(buf, "%d\n", result);
1928}
1929
1930static ssize_t store_pwm_interpolate(struct device *dev,
1931 struct device_attribute *devattr,
1932 const char *buf, size_t count)
1933{
Hans de Goedece0bfa52009-01-07 16:37:28 +01001934 struct f71882fg_data *data = dev_get_drvdata(dev);
Giel van Schijndele8a4eac2010-05-27 19:58:41 +02001935 int err, nr = to_sensor_dev_attr_2(devattr)->index;
1936 unsigned long val;
1937
1938 err = strict_strtoul(buf, 10, &val);
1939 if (err)
1940 return err;
Hans de Goedece0bfa52009-01-07 16:37:28 +01001941
Mark van Doesburg9ab796e2009-01-07 16:37:27 +01001942 mutex_lock(&data->update_lock);
Hans de Goedece0bfa52009-01-07 16:37:28 +01001943 data->pwm_auto_point_mapping[nr] =
1944 f71882fg_read8(data, F71882FG_REG_POINT_MAPPING(nr));
Mark van Doesburg9ab796e2009-01-07 16:37:27 +01001945 if (val)
1946 val = data->pwm_auto_point_mapping[nr] | (1 << 4);
1947 else
1948 val = data->pwm_auto_point_mapping[nr] & (~(1 << 4));
1949 f71882fg_write8(data, F71882FG_REG_POINT_MAPPING(nr), val);
1950 data->pwm_auto_point_mapping[nr] = val;
1951 mutex_unlock(&data->update_lock);
1952
1953 return count;
1954}
1955
1956static ssize_t show_pwm_auto_point_channel(struct device *dev,
1957 struct device_attribute *devattr,
1958 char *buf)
1959{
1960 int result;
1961 struct f71882fg_data *data = f71882fg_update_device(dev);
1962 int nr = to_sensor_dev_attr_2(devattr)->index;
1963
Hans de Goede09475d32009-06-15 18:39:52 +02001964 result = 1 << ((data->pwm_auto_point_mapping[nr] & 3) -
1965 data->temp_start);
Mark van Doesburg9ab796e2009-01-07 16:37:27 +01001966
1967 return sprintf(buf, "%d\n", result);
1968}
1969
1970static ssize_t store_pwm_auto_point_channel(struct device *dev,
1971 struct device_attribute *devattr,
1972 const char *buf, size_t count)
1973{
Hans de Goedece0bfa52009-01-07 16:37:28 +01001974 struct f71882fg_data *data = dev_get_drvdata(dev);
Giel van Schijndele8a4eac2010-05-27 19:58:41 +02001975 int err, nr = to_sensor_dev_attr_2(devattr)->index;
1976 long val;
1977
1978 err = strict_strtol(buf, 10, &val);
1979 if (err)
1980 return err;
Hans de Goede30453012009-01-07 16:37:30 +01001981
Mark van Doesburg9ab796e2009-01-07 16:37:27 +01001982 switch (val) {
1983 case 1:
Hans de Goede30453012009-01-07 16:37:30 +01001984 val = 0;
Mark van Doesburg9ab796e2009-01-07 16:37:27 +01001985 break;
1986 case 2:
Hans de Goede30453012009-01-07 16:37:30 +01001987 val = 1;
Mark van Doesburg9ab796e2009-01-07 16:37:27 +01001988 break;
1989 case 4:
Hans de Goede30453012009-01-07 16:37:30 +01001990 val = 2;
Mark van Doesburg9ab796e2009-01-07 16:37:27 +01001991 break;
1992 default:
1993 return -EINVAL;
1994 }
Hans de Goede09475d32009-06-15 18:39:52 +02001995 val += data->temp_start;
Mark van Doesburg9ab796e2009-01-07 16:37:27 +01001996 mutex_lock(&data->update_lock);
Hans de Goedece0bfa52009-01-07 16:37:28 +01001997 data->pwm_auto_point_mapping[nr] =
1998 f71882fg_read8(data, F71882FG_REG_POINT_MAPPING(nr));
Mark van Doesburg9ab796e2009-01-07 16:37:27 +01001999 val = (data->pwm_auto_point_mapping[nr] & 0xfc) | val;
2000 f71882fg_write8(data, F71882FG_REG_POINT_MAPPING(nr), val);
2001 data->pwm_auto_point_mapping[nr] = val;
2002 mutex_unlock(&data->update_lock);
2003
2004 return count;
2005}
2006
2007static ssize_t show_pwm_auto_point_temp(struct device *dev,
2008 struct device_attribute *devattr,
2009 char *buf)
2010{
2011 int result;
2012 struct f71882fg_data *data = f71882fg_update_device(dev);
2013 int pwm = to_sensor_dev_attr_2(devattr)->index;
2014 int point = to_sensor_dev_attr_2(devattr)->nr;
2015
2016 result = data->pwm_auto_point_temp[pwm][point];
2017 return sprintf(buf, "%d\n", 1000 * result);
2018}
2019
2020static ssize_t store_pwm_auto_point_temp(struct device *dev,
2021 struct device_attribute *devattr,
2022 const char *buf, size_t count)
2023{
Hans de Goedece0bfa52009-01-07 16:37:28 +01002024 struct f71882fg_data *data = dev_get_drvdata(dev);
Giel van Schijndele8a4eac2010-05-27 19:58:41 +02002025 int err, pwm = to_sensor_dev_attr_2(devattr)->index;
Mark van Doesburg9ab796e2009-01-07 16:37:27 +01002026 int point = to_sensor_dev_attr_2(devattr)->nr;
Giel van Schijndele8a4eac2010-05-27 19:58:41 +02002027 long val;
2028
2029 err = strict_strtol(buf, 10, &val);
2030 if (err)
2031 return err;
2032
2033 val /= 1000;
Hans de Goede76698962009-12-09 20:36:01 +01002034
Hans de Goede98f7ba12011-03-09 20:57:09 +01002035 if (data->auto_point_temp_signed)
Hans de Goede76698962009-12-09 20:36:01 +01002036 val = SENSORS_LIMIT(val, -128, 127);
2037 else
2038 val = SENSORS_LIMIT(val, 0, 127);
Mark van Doesburg9ab796e2009-01-07 16:37:27 +01002039
2040 mutex_lock(&data->update_lock);
2041 f71882fg_write8(data, F71882FG_REG_POINT_TEMP(pwm, point), val);
2042 data->pwm_auto_point_temp[pwm][point] = val;
2043 mutex_unlock(&data->update_lock);
2044
2045 return count;
2046}
2047
Hans de Goede45fb3662007-07-13 14:34:19 +02002048static ssize_t show_name(struct device *dev, struct device_attribute *devattr,
2049 char *buf)
2050{
Hans de Goede498be962009-01-07 16:37:28 +01002051 struct f71882fg_data *data = dev_get_drvdata(dev);
2052 return sprintf(buf, "%s\n", f71882fg_names[data->type]);
Hans de Goede45fb3662007-07-13 14:34:19 +02002053}
2054
Hans de Goedec13548c2009-01-07 16:37:27 +01002055static int __devinit f71882fg_create_sysfs_files(struct platform_device *pdev,
2056 struct sensor_device_attribute_2 *attr, int count)
2057{
2058 int err, i;
Hans de Goede45fb3662007-07-13 14:34:19 +02002059
Hans de Goedec13548c2009-01-07 16:37:27 +01002060 for (i = 0; i < count; i++) {
2061 err = device_create_file(&pdev->dev, &attr[i].dev_attr);
2062 if (err)
2063 return err;
2064 }
2065 return 0;
2066}
2067
Hans de Goedefc16c562009-12-09 20:36:01 +01002068static void f71882fg_remove_sysfs_files(struct platform_device *pdev,
2069 struct sensor_device_attribute_2 *attr, int count)
2070{
2071 int i;
2072
2073 for (i = 0; i < count; i++)
2074 device_remove_file(&pdev->dev, &attr[i].dev_attr);
2075}
2076
Hans de Goedec13548c2009-01-07 16:37:27 +01002077static int __devinit f71882fg_probe(struct platform_device *pdev)
Hans de Goede45fb3662007-07-13 14:34:19 +02002078{
2079 struct f71882fg_data *data;
Hans de Goede498be962009-01-07 16:37:28 +01002080 struct f71882fg_sio_data *sio_data = pdev->dev.platform_data;
Jean Delvaref27def02011-03-26 10:45:01 +01002081 int nr_fans = f71882fg_nr_fans[sio_data->type];
2082 int nr_temps = f71882fg_nr_temps[sio_data->type];
2083 int err, i;
Hans de Goede98f7ba12011-03-09 20:57:09 +01002084 u8 start_reg, reg;
Hans de Goede45fb3662007-07-13 14:34:19 +02002085
Hans de Goedec13548c2009-01-07 16:37:27 +01002086 data = kzalloc(sizeof(struct f71882fg_data), GFP_KERNEL);
2087 if (!data)
Hans de Goede45fb3662007-07-13 14:34:19 +02002088 return -ENOMEM;
2089
2090 data->addr = platform_get_resource(pdev, IORESOURCE_IO, 0)->start;
Hans de Goede498be962009-01-07 16:37:28 +01002091 data->type = sio_data->type;
Hans de Goede09475d32009-06-15 18:39:52 +02002092 data->temp_start =
2093 (data->type == f71858fg || data->type == f8000) ? 0 : 1;
Hans de Goede45fb3662007-07-13 14:34:19 +02002094 mutex_init(&data->update_lock);
2095 platform_set_drvdata(pdev, data);
2096
Hans de Goede3cc74752009-01-07 16:37:28 +01002097 start_reg = f71882fg_read8(data, F71882FG_REG_START);
Hans de Goede12d66e82009-01-07 16:37:29 +01002098 if (start_reg & 0x04) {
2099 dev_warn(&pdev->dev, "Hardware monitor is powered down\n");
2100 err = -ENODEV;
2101 goto exit_free;
2102 }
Hans de Goede3cc74752009-01-07 16:37:28 +01002103 if (!(start_reg & 0x03)) {
2104 dev_warn(&pdev->dev, "Hardware monitoring not activated\n");
2105 err = -ENODEV;
2106 goto exit_free;
2107 }
2108
Hans de Goede45fb3662007-07-13 14:34:19 +02002109 /* Register sysfs interface files */
Hans de Goedec13548c2009-01-07 16:37:27 +01002110 err = device_create_file(&pdev->dev, &dev_attr_name);
2111 if (err)
2112 goto exit_unregister_sysfs;
2113
Hans de Goedec13548c2009-01-07 16:37:27 +01002114 if (start_reg & 0x01) {
Hans de Goedeed4f7c22009-01-07 16:37:30 +01002115 switch (data->type) {
Hans de Goede09475d32009-06-15 18:39:52 +02002116 case f71858fg:
2117 data->temp_config =
2118 f71882fg_read8(data, F71882FG_REG_TEMP_CONFIG);
2119 if (data->temp_config & 0x10)
2120 /* The f71858fg temperature alarms behave as
2121 the f8000 alarms in this mode */
2122 err = f71882fg_create_sysfs_files(pdev,
Hans de Goede0bae6402011-03-09 20:57:10 +01002123 f8000_temp_attr,
2124 ARRAY_SIZE(f8000_temp_attr));
Hans de Goede09475d32009-06-15 18:39:52 +02002125 else
2126 err = f71882fg_create_sysfs_files(pdev,
Hans de Goede0bae6402011-03-09 20:57:10 +01002127 f71858fg_temp_attr,
2128 ARRAY_SIZE(f71858fg_temp_attr));
Hans de Goede09475d32009-06-15 18:39:52 +02002129 break;
Hans de Goede0bae6402011-03-09 20:57:10 +01002130 case f8000:
2131 err = f71882fg_create_sysfs_files(pdev,
2132 f8000_temp_attr,
2133 ARRAY_SIZE(f8000_temp_attr));
2134 break;
2135 default:
2136 err = f71882fg_create_sysfs_files(pdev,
Hans de Goede60d2b372011-03-09 20:57:11 +01002137 &fxxxx_temp_attr[0][0],
2138 ARRAY_SIZE(fxxxx_temp_attr[0]) * nr_temps);
Hans de Goede0bae6402011-03-09 20:57:10 +01002139 }
2140 if (err)
2141 goto exit_unregister_sysfs;
2142
Hans de Goede78aa4f72011-03-09 20:57:12 +01002143 if (f71882fg_has_beep[data->type]) {
2144 err = f71882fg_create_sysfs_files(pdev,
2145 &fxxxx_temp_beep_attr[0][0],
2146 ARRAY_SIZE(fxxxx_temp_beep_attr[0])
2147 * nr_temps);
2148 if (err)
2149 goto exit_unregister_sysfs;
2150 }
2151
Hans de Goede0bae6402011-03-09 20:57:10 +01002152 for (i = 0; i < F71882FG_MAX_INS; i++) {
2153 if (f71882fg_has_in[data->type][i]) {
2154 err = device_create_file(&pdev->dev,
2155 &fxxxx_in_attr[i].dev_attr);
2156 if (err)
2157 goto exit_unregister_sysfs;
2158 }
2159 }
2160 if (f71882fg_has_in1_alarm[data->type]) {
Hans de Goede498be962009-01-07 16:37:28 +01002161 err = f71882fg_create_sysfs_files(pdev,
Hans de Goede66344aa2009-12-09 20:35:59 +01002162 fxxxx_in1_alarm_attr,
2163 ARRAY_SIZE(fxxxx_in1_alarm_attr));
Hans de Goede498be962009-01-07 16:37:28 +01002164 if (err)
2165 goto exit_unregister_sysfs;
2166 }
Hans de Goede45fb3662007-07-13 14:34:19 +02002167 }
2168
Hans de Goede45fb3662007-07-13 14:34:19 +02002169 if (start_reg & 0x02) {
Hans de Goede98f7ba12011-03-09 20:57:09 +01002170 switch (data->type) {
Hans de Goedee5e713c2011-03-10 08:54:02 +01002171 case f71808e:
Hans de Goedec11bb992011-03-09 20:57:15 +01002172 case f71869:
Hans de Goedee5e713c2011-03-10 08:54:02 +01002173 /* These always have signed auto point temps */
Hans de Goedec11bb992011-03-09 20:57:15 +01002174 data->auto_point_temp_signed = 1;
2175 /* Fall through to select correct fan/pwm reg bank! */
Hans de Goede98f7ba12011-03-09 20:57:09 +01002176 case f71889fg:
Hans de Goede3cad4022011-03-09 20:57:14 +01002177 case f71889ed:
Hans de Goedea66c1082011-03-26 10:45:02 +01002178 case f71889a:
Hans de Goede98f7ba12011-03-09 20:57:09 +01002179 reg = f71882fg_read8(data, F71882FG_REG_FAN_FAULT_T);
2180 if (reg & F71882FG_FAN_NEG_TEMP_EN)
2181 data->auto_point_temp_signed = 1;
Hans de Goede3cad4022011-03-09 20:57:14 +01002182 /* Ensure banked pwm registers point to right bank */
2183 reg &= ~F71882FG_FAN_PROG_SEL;
2184 f71882fg_write8(data, F71882FG_REG_FAN_FAULT_T, reg);
Hans de Goede98f7ba12011-03-09 20:57:09 +01002185 break;
2186 default:
2187 break;
2188 }
2189
Hans de Goede996cadb2009-06-15 18:39:51 +02002190 data->pwm_enable =
2191 f71882fg_read8(data, F71882FG_REG_PWM_ENABLE);
2192
2193 /* Sanity check the pwm settings */
2194 switch (data->type) {
Hans de Goede09475d32009-06-15 18:39:52 +02002195 case f71858fg:
2196 err = 0;
2197 for (i = 0; i < nr_fans; i++)
2198 if (((data->pwm_enable >> (i * 2)) & 3) == 3)
2199 err = 1;
2200 break;
Hans de Goede996cadb2009-06-15 18:39:51 +02002201 case f71862fg:
2202 err = (data->pwm_enable & 0x15) != 0x15;
2203 break;
Hans de Goede996cadb2009-06-15 18:39:51 +02002204 case f8000:
2205 err = data->pwm_enable & 0x20;
2206 break;
Jean Delvare383586b2011-03-26 10:45:02 +01002207 default:
2208 err = 0;
2209 break;
Hans de Goede996cadb2009-06-15 18:39:51 +02002210 }
2211 if (err) {
2212 dev_err(&pdev->dev,
2213 "Invalid (reserved) pwm settings: 0x%02x\n",
2214 (unsigned int)data->pwm_enable);
2215 err = -ENODEV;
2216 goto exit_unregister_sysfs;
2217 }
2218
Hans de Goedeb69b0392009-12-09 20:36:00 +01002219 err = f71882fg_create_sysfs_files(pdev, &fxxxx_fan_attr[0][0],
2220 ARRAY_SIZE(fxxxx_fan_attr[0]) * nr_fans);
Hans de Goede498be962009-01-07 16:37:28 +01002221 if (err)
2222 goto exit_unregister_sysfs;
2223
Hans de Goede78aa4f72011-03-09 20:57:12 +01002224 if (f71882fg_has_beep[data->type]) {
Hans de Goedeb69b0392009-12-09 20:36:00 +01002225 err = f71882fg_create_sysfs_files(pdev,
2226 fxxxx_fan_beep_attr, nr_fans);
2227 if (err)
2228 goto exit_unregister_sysfs;
2229 }
2230
Hans de Goedeed4f7c22009-01-07 16:37:30 +01002231 switch (data->type) {
Hans de Goedee5e713c2011-03-10 08:54:02 +01002232 case f71808e:
Hans de Goedec11bb992011-03-09 20:57:15 +01002233 case f71869:
Hans de Goedee48a7f12011-03-09 20:57:13 +01002234 case f71889fg:
Hans de Goede3cad4022011-03-09 20:57:14 +01002235 case f71889ed:
Hans de Goedea66c1082011-03-26 10:45:02 +01002236 case f71889a:
Hans de Goedee48a7f12011-03-09 20:57:13 +01002237 for (i = 0; i < nr_fans; i++) {
2238 data->pwm_auto_point_mapping[i] =
2239 f71882fg_read8(data,
2240 F71882FG_REG_POINT_MAPPING(i));
Hans de Goede3cad4022011-03-09 20:57:14 +01002241 if ((data->pwm_auto_point_mapping[i] & 0x80) ||
2242 (data->pwm_auto_point_mapping[i] & 3) == 0)
Hans de Goedee48a7f12011-03-09 20:57:13 +01002243 break;
2244 }
2245 if (i != nr_fans) {
2246 dev_warn(&pdev->dev,
2247 "Auto pwm controlled by raw digital "
2248 "data, disabling pwm auto_point "
2249 "sysfs attributes\n");
2250 goto no_pwm_auto_point;
2251 }
2252 break;
2253 default:
2254 break;
2255 }
2256
2257 switch (data->type) {
Hans de Goedeed4f7c22009-01-07 16:37:30 +01002258 case f71862fg:
Hans de Goede498be962009-01-07 16:37:28 +01002259 err = f71882fg_create_sysfs_files(pdev,
Hans de Goede66344aa2009-12-09 20:35:59 +01002260 f71862fg_auto_pwm_attr,
2261 ARRAY_SIZE(f71862fg_auto_pwm_attr));
Hans de Goedeed4f7c22009-01-07 16:37:30 +01002262 break;
Hans de Goedee5e713c2011-03-10 08:54:02 +01002263 case f71808e:
Hans de Goedec11bb992011-03-09 20:57:15 +01002264 case f71869:
2265 err = f71882fg_create_sysfs_files(pdev,
2266 f71869_auto_pwm_attr,
2267 ARRAY_SIZE(f71869_auto_pwm_attr));
2268 break;
Hans de Goedeed4f7c22009-01-07 16:37:30 +01002269 case f8000:
2270 err = f71882fg_create_sysfs_files(pdev,
2271 f8000_fan_attr,
2272 ARRAY_SIZE(f8000_fan_attr));
Hans de Goede66344aa2009-12-09 20:35:59 +01002273 if (err)
2274 goto exit_unregister_sysfs;
2275 err = f71882fg_create_sysfs_files(pdev,
2276 f8000_auto_pwm_attr,
2277 ARRAY_SIZE(f8000_auto_pwm_attr));
Hans de Goedeed4f7c22009-01-07 16:37:30 +01002278 break;
Hans de Goedee48a7f12011-03-09 20:57:13 +01002279 default:
Hans de Goedeb69b0392009-12-09 20:36:00 +01002280 err = f71882fg_create_sysfs_files(pdev,
2281 &fxxxx_auto_pwm_attr[0][0],
2282 ARRAY_SIZE(fxxxx_auto_pwm_attr[0]) * nr_fans);
Hans de Goede498be962009-01-07 16:37:28 +01002283 }
Hans de Goedec13548c2009-01-07 16:37:27 +01002284 if (err)
2285 goto exit_unregister_sysfs;
Hans de Goede28ba8582009-01-07 16:37:31 +01002286
Hans de Goedee48a7f12011-03-09 20:57:13 +01002287no_pwm_auto_point:
Hans de Goede28ba8582009-01-07 16:37:31 +01002288 for (i = 0; i < nr_fans; i++)
2289 dev_info(&pdev->dev, "Fan: %d is in %s mode\n", i + 1,
2290 (data->pwm_enable & (1 << 2 * i)) ?
2291 "duty-cycle" : "RPM");
Hans de Goede45fb3662007-07-13 14:34:19 +02002292 }
2293
Tony Jones1beeffe2007-08-20 13:46:20 -07002294 data->hwmon_dev = hwmon_device_register(&pdev->dev);
2295 if (IS_ERR(data->hwmon_dev)) {
2296 err = PTR_ERR(data->hwmon_dev);
Hans de Goedec13548c2009-01-07 16:37:27 +01002297 data->hwmon_dev = NULL;
Hans de Goede45fb3662007-07-13 14:34:19 +02002298 goto exit_unregister_sysfs;
2299 }
2300
2301 return 0;
2302
2303exit_unregister_sysfs:
Hans de Goedec13548c2009-01-07 16:37:27 +01002304 f71882fg_remove(pdev); /* Will unregister the sysfs files for us */
Hans de Goede3cc74752009-01-07 16:37:28 +01002305 return err; /* f71882fg_remove() also frees our data */
2306exit_free:
2307 kfree(data);
Hans de Goede45fb3662007-07-13 14:34:19 +02002308 return err;
2309}
2310
Hans de Goedec13548c2009-01-07 16:37:27 +01002311static int f71882fg_remove(struct platform_device *pdev)
Hans de Goede45fb3662007-07-13 14:34:19 +02002312{
Hans de Goede45fb3662007-07-13 14:34:19 +02002313 struct f71882fg_data *data = platform_get_drvdata(pdev);
Jean Delvaref27def02011-03-26 10:45:01 +01002314 int nr_fans = f71882fg_nr_fans[data->type];
2315 int nr_temps = f71882fg_nr_temps[data->type];
2316 int i;
Hans de Goedefc16c562009-12-09 20:36:01 +01002317 u8 start_reg = f71882fg_read8(data, F71882FG_REG_START);
Hans de Goede45fb3662007-07-13 14:34:19 +02002318
Hans de Goedec13548c2009-01-07 16:37:27 +01002319 if (data->hwmon_dev)
2320 hwmon_device_unregister(data->hwmon_dev);
Hans de Goede45fb3662007-07-13 14:34:19 +02002321
Hans de Goedec13548c2009-01-07 16:37:27 +01002322 device_remove_file(&pdev->dev, &dev_attr_name);
Hans de Goede45fb3662007-07-13 14:34:19 +02002323
Hans de Goedefc16c562009-12-09 20:36:01 +01002324 if (start_reg & 0x01) {
2325 switch (data->type) {
2326 case f71858fg:
2327 if (data->temp_config & 0x10)
2328 f71882fg_remove_sysfs_files(pdev,
Hans de Goede0bae6402011-03-09 20:57:10 +01002329 f8000_temp_attr,
2330 ARRAY_SIZE(f8000_temp_attr));
Hans de Goedefc16c562009-12-09 20:36:01 +01002331 else
2332 f71882fg_remove_sysfs_files(pdev,
Hans de Goede0bae6402011-03-09 20:57:10 +01002333 f71858fg_temp_attr,
2334 ARRAY_SIZE(f71858fg_temp_attr));
Hans de Goedefc16c562009-12-09 20:36:01 +01002335 break;
2336 case f8000:
2337 f71882fg_remove_sysfs_files(pdev,
Hans de Goede0bae6402011-03-09 20:57:10 +01002338 f8000_temp_attr,
2339 ARRAY_SIZE(f8000_temp_attr));
Hans de Goedefc16c562009-12-09 20:36:01 +01002340 break;
Hans de Goede0bae6402011-03-09 20:57:10 +01002341 default:
2342 f71882fg_remove_sysfs_files(pdev,
Hans de Goede60d2b372011-03-09 20:57:11 +01002343 &fxxxx_temp_attr[0][0],
2344 ARRAY_SIZE(fxxxx_temp_attr[0]) * nr_temps);
Hans de Goede0bae6402011-03-09 20:57:10 +01002345 }
Hans de Goede78aa4f72011-03-09 20:57:12 +01002346 if (f71882fg_has_beep[data->type]) {
2347 f71882fg_remove_sysfs_files(pdev,
2348 &fxxxx_temp_beep_attr[0][0],
2349 ARRAY_SIZE(fxxxx_temp_beep_attr[0]) * nr_temps);
2350 }
2351
Hans de Goede0bae6402011-03-09 20:57:10 +01002352 for (i = 0; i < F71882FG_MAX_INS; i++) {
2353 if (f71882fg_has_in[data->type][i]) {
2354 device_remove_file(&pdev->dev,
2355 &fxxxx_in_attr[i].dev_attr);
2356 }
2357 }
2358 if (f71882fg_has_in1_alarm[data->type]) {
2359 f71882fg_remove_sysfs_files(pdev,
2360 fxxxx_in1_alarm_attr,
2361 ARRAY_SIZE(fxxxx_in1_alarm_attr));
Hans de Goedefc16c562009-12-09 20:36:01 +01002362 }
2363 }
Hans de Goede498be962009-01-07 16:37:28 +01002364
Hans de Goedefc16c562009-12-09 20:36:01 +01002365 if (start_reg & 0x02) {
2366 f71882fg_remove_sysfs_files(pdev, &fxxxx_fan_attr[0][0],
2367 ARRAY_SIZE(fxxxx_fan_attr[0]) * nr_fans);
Hans de Goede45fb3662007-07-13 14:34:19 +02002368
Hans de Goede78aa4f72011-03-09 20:57:12 +01002369 if (f71882fg_has_beep[data->type]) {
Hans de Goedefc16c562009-12-09 20:36:01 +01002370 f71882fg_remove_sysfs_files(pdev,
2371 fxxxx_fan_beep_attr, nr_fans);
Hans de Goede78aa4f72011-03-09 20:57:12 +01002372 }
Hans de Goede498be962009-01-07 16:37:28 +01002373
Hans de Goedefc16c562009-12-09 20:36:01 +01002374 switch (data->type) {
2375 case f71862fg:
2376 f71882fg_remove_sysfs_files(pdev,
2377 f71862fg_auto_pwm_attr,
2378 ARRAY_SIZE(f71862fg_auto_pwm_attr));
2379 break;
Hans de Goedee5e713c2011-03-10 08:54:02 +01002380 case f71808e:
Hans de Goedec11bb992011-03-09 20:57:15 +01002381 case f71869:
2382 f71882fg_remove_sysfs_files(pdev,
2383 f71869_auto_pwm_attr,
2384 ARRAY_SIZE(f71869_auto_pwm_attr));
2385 break;
Hans de Goedefc16c562009-12-09 20:36:01 +01002386 case f8000:
2387 f71882fg_remove_sysfs_files(pdev,
2388 f8000_fan_attr,
2389 ARRAY_SIZE(f8000_fan_attr));
2390 f71882fg_remove_sysfs_files(pdev,
2391 f8000_auto_pwm_attr,
2392 ARRAY_SIZE(f8000_auto_pwm_attr));
2393 break;
Hans de Goede3cad4022011-03-09 20:57:14 +01002394 default:
Hans de Goedefc16c562009-12-09 20:36:01 +01002395 f71882fg_remove_sysfs_files(pdev,
2396 &fxxxx_auto_pwm_attr[0][0],
2397 ARRAY_SIZE(fxxxx_auto_pwm_attr[0]) * nr_fans);
2398 }
2399 }
Hans de Goedeed4f7c22009-01-07 16:37:30 +01002400
Hans de Goeded9ebaa42011-03-13 13:50:33 +01002401 platform_set_drvdata(pdev, NULL);
Hans de Goede45fb3662007-07-13 14:34:19 +02002402 kfree(data);
2403
2404 return 0;
2405}
2406
Hans de Goede498be962009-01-07 16:37:28 +01002407static int __init f71882fg_find(int sioaddr, unsigned short *address,
2408 struct f71882fg_sio_data *sio_data)
Hans de Goede45fb3662007-07-13 14:34:19 +02002409{
Hans de Goede45fb3662007-07-13 14:34:19 +02002410 u16 devid;
Giel van Schijndelcadb8652010-10-03 08:09:49 -04002411 int err = superio_enter(sioaddr);
2412 if (err)
2413 return err;
Hans de Goede45fb3662007-07-13 14:34:19 +02002414
2415 devid = superio_inw(sioaddr, SIO_REG_MANID);
2416 if (devid != SIO_FINTEK_ID) {
Joe Perches22d3b412010-10-20 06:51:34 +00002417 pr_debug("Not a Fintek device\n");
Giel van Schijndelcadb8652010-10-03 08:09:49 -04002418 err = -ENODEV;
Hans de Goede45fb3662007-07-13 14:34:19 +02002419 goto exit;
2420 }
2421
Jean Delvare67b671b2007-12-06 23:13:42 +01002422 devid = force_id ? force_id : superio_inw(sioaddr, SIO_REG_DEVID);
Hans de Goede498be962009-01-07 16:37:28 +01002423 switch (devid) {
Hans de Goedee5e713c2011-03-10 08:54:02 +01002424 case SIO_F71808E_ID:
2425 sio_data->type = f71808e;
2426 break;
Hans de Goede09475d32009-06-15 18:39:52 +02002427 case SIO_F71858_ID:
2428 sio_data->type = f71858fg;
2429 break;
Hans de Goede498be962009-01-07 16:37:28 +01002430 case SIO_F71862_ID:
2431 sio_data->type = f71862fg;
2432 break;
Hans de Goedec11bb992011-03-09 20:57:15 +01002433 case SIO_F71869_ID:
2434 sio_data->type = f71869;
2435 break;
Hans de Goede498be962009-01-07 16:37:28 +01002436 case SIO_F71882_ID:
2437 sio_data->type = f71882fg;
2438 break;
Hans de Goede76698962009-12-09 20:36:01 +01002439 case SIO_F71889_ID:
2440 sio_data->type = f71889fg;
2441 break;
Hans de Goede3cad4022011-03-09 20:57:14 +01002442 case SIO_F71889E_ID:
2443 sio_data->type = f71889ed;
2444 break;
Hans de Goedea66c1082011-03-26 10:45:02 +01002445 case SIO_F71889A_ID:
2446 sio_data->type = f71889a;
2447 break;
Hans de Goedeed4f7c22009-01-07 16:37:30 +01002448 case SIO_F8000_ID:
2449 sio_data->type = f8000;
2450 break;
Jean Delvare383586b2011-03-26 10:45:02 +01002451 case SIO_F81865_ID:
2452 sio_data->type = f81865f;
2453 break;
Hans de Goede498be962009-01-07 16:37:28 +01002454 default:
Joe Perches22d3b412010-10-20 06:51:34 +00002455 pr_info("Unsupported Fintek device: %04x\n",
2456 (unsigned int)devid);
Giel van Schijndelcadb8652010-10-03 08:09:49 -04002457 err = -ENODEV;
Hans de Goede45fb3662007-07-13 14:34:19 +02002458 goto exit;
2459 }
2460
Hans de Goede09475d32009-06-15 18:39:52 +02002461 if (sio_data->type == f71858fg)
2462 superio_select(sioaddr, SIO_F71858FG_LD_HWM);
2463 else
2464 superio_select(sioaddr, SIO_F71882FG_LD_HWM);
2465
Mark M. Hoffman8afb1042007-08-21 23:10:46 -04002466 if (!(superio_inb(sioaddr, SIO_REG_ENABLE) & 0x01)) {
Joe Perches22d3b412010-10-20 06:51:34 +00002467 pr_warn("Device not activated\n");
Giel van Schijndelcadb8652010-10-03 08:09:49 -04002468 err = -ENODEV;
Hans de Goede45fb3662007-07-13 14:34:19 +02002469 goto exit;
2470 }
2471
2472 *address = superio_inw(sioaddr, SIO_REG_ADDR);
Giel van Schijndel162bb592010-05-27 19:58:40 +02002473 if (*address == 0) {
Joe Perches22d3b412010-10-20 06:51:34 +00002474 pr_warn("Base address not set\n");
Giel van Schijndelcadb8652010-10-03 08:09:49 -04002475 err = -ENODEV;
Hans de Goede45fb3662007-07-13 14:34:19 +02002476 goto exit;
2477 }
2478 *address &= ~(REGION_LENGTH - 1); /* Ignore 3 LSB */
2479
Hans de Goede45fb3662007-07-13 14:34:19 +02002480 err = 0;
Joe Perches22d3b412010-10-20 06:51:34 +00002481 pr_info("Found %s chip at %#x, revision %d\n",
Hans de Goede498be962009-01-07 16:37:28 +01002482 f71882fg_names[sio_data->type], (unsigned int)*address,
Hans de Goede45fb3662007-07-13 14:34:19 +02002483 (int)superio_inb(sioaddr, SIO_REG_DEVREV));
2484exit:
2485 superio_exit(sioaddr);
2486 return err;
2487}
2488
Hans de Goede498be962009-01-07 16:37:28 +01002489static int __init f71882fg_device_add(unsigned short address,
2490 const struct f71882fg_sio_data *sio_data)
Hans de Goede45fb3662007-07-13 14:34:19 +02002491{
2492 struct resource res = {
2493 .start = address,
2494 .end = address + REGION_LENGTH - 1,
2495 .flags = IORESOURCE_IO,
2496 };
2497 int err;
2498
2499 f71882fg_pdev = platform_device_alloc(DRVNAME, address);
Mark M. Hoffman8afb1042007-08-21 23:10:46 -04002500 if (!f71882fg_pdev)
Hans de Goede45fb3662007-07-13 14:34:19 +02002501 return -ENOMEM;
2502
2503 res.name = f71882fg_pdev->name;
Jean Delvareb9acb642009-01-07 16:37:35 +01002504 err = acpi_check_resource_conflict(&res);
2505 if (err)
Hans de Goede18632f82009-02-17 19:59:54 +01002506 goto exit_device_put;
Jean Delvareb9acb642009-01-07 16:37:35 +01002507
Hans de Goede45fb3662007-07-13 14:34:19 +02002508 err = platform_device_add_resources(f71882fg_pdev, &res, 1);
Mark M. Hoffman8afb1042007-08-21 23:10:46 -04002509 if (err) {
Joe Perches22d3b412010-10-20 06:51:34 +00002510 pr_err("Device resource addition failed\n");
Hans de Goede45fb3662007-07-13 14:34:19 +02002511 goto exit_device_put;
2512 }
2513
Hans de Goede498be962009-01-07 16:37:28 +01002514 err = platform_device_add_data(f71882fg_pdev, sio_data,
2515 sizeof(struct f71882fg_sio_data));
2516 if (err) {
Joe Perches22d3b412010-10-20 06:51:34 +00002517 pr_err("Platform data allocation failed\n");
Hans de Goede498be962009-01-07 16:37:28 +01002518 goto exit_device_put;
2519 }
2520
Hans de Goede45fb3662007-07-13 14:34:19 +02002521 err = platform_device_add(f71882fg_pdev);
Mark M. Hoffman8afb1042007-08-21 23:10:46 -04002522 if (err) {
Joe Perches22d3b412010-10-20 06:51:34 +00002523 pr_err("Device addition failed\n");
Hans de Goede45fb3662007-07-13 14:34:19 +02002524 goto exit_device_put;
2525 }
2526
2527 return 0;
2528
2529exit_device_put:
2530 platform_device_put(f71882fg_pdev);
2531
2532 return err;
2533}
2534
2535static int __init f71882fg_init(void)
2536{
2537 int err = -ENODEV;
2538 unsigned short address;
Hans de Goede498be962009-01-07 16:37:28 +01002539 struct f71882fg_sio_data sio_data;
Hans de Goede45fb3662007-07-13 14:34:19 +02002540
Hans de Goede498be962009-01-07 16:37:28 +01002541 memset(&sio_data, 0, sizeof(sio_data));
2542
2543 if (f71882fg_find(0x2e, &address, &sio_data) &&
2544 f71882fg_find(0x4e, &address, &sio_data))
Hans de Goede45fb3662007-07-13 14:34:19 +02002545 goto exit;
2546
Hans de Goedec13548c2009-01-07 16:37:27 +01002547 err = platform_driver_register(&f71882fg_driver);
2548 if (err)
Hans de Goede45fb3662007-07-13 14:34:19 +02002549 goto exit;
2550
Hans de Goede498be962009-01-07 16:37:28 +01002551 err = f71882fg_device_add(address, &sio_data);
Hans de Goedec13548c2009-01-07 16:37:27 +01002552 if (err)
Hans de Goede45fb3662007-07-13 14:34:19 +02002553 goto exit_driver;
2554
2555 return 0;
2556
2557exit_driver:
2558 platform_driver_unregister(&f71882fg_driver);
2559exit:
2560 return err;
2561}
2562
2563static void __exit f71882fg_exit(void)
2564{
2565 platform_device_unregister(f71882fg_pdev);
2566 platform_driver_unregister(&f71882fg_driver);
2567}
2568
2569MODULE_DESCRIPTION("F71882FG Hardware Monitoring Driver");
Hans de Goedec13548c2009-01-07 16:37:27 +01002570MODULE_AUTHOR("Hans Edgington, Hans de Goede (hdegoede@redhat.com)");
Hans de Goede45fb3662007-07-13 14:34:19 +02002571MODULE_LICENSE("GPL");
2572
2573module_init(f71882fg_init);
2574module_exit(f71882fg_exit);