blob: 16330db2bcdc83605ce42ffff29ef96aa631bcc9 [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
Hans de Goede4d538112011-05-25 20:43:32 +0200152static const char f71882fg_fan_has_beep[] = {
Jean Delvare2740c602011-03-26 10:45:01 +0100153 [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
Hans de Goede4d538112011-05-25 20:43:32 +0200178static const char f71882fg_temp_has_beep[] = {
179 [f71808e] = 0,
180 [f71858fg] = 0,
181 [f71862fg] = 1,
182 [f71869] = 1,
183 [f71882fg] = 1,
184 [f71889fg] = 1,
185 [f71889ed] = 1,
186 [f71889a] = 1,
187 [f8000] = 0,
188 [f81865f] = 1,
189};
190
Jean Delvaref27def02011-03-26 10:45:01 +0100191static const char f71882fg_nr_temps[] = {
192 [f71808e] = 2,
193 [f71858fg] = 3,
194 [f71862fg] = 3,
195 [f71869] = 3,
196 [f71882fg] = 3,
197 [f71889fg] = 3,
198 [f71889ed] = 3,
Hans de Goedea66c1082011-03-26 10:45:02 +0100199 [f71889a] = 3,
Jean Delvaref27def02011-03-26 10:45:01 +0100200 [f8000] = 3,
Jean Delvare383586b2011-03-26 10:45:02 +0100201 [f81865f] = 2,
Jean Delvaref27def02011-03-26 10:45:01 +0100202};
203
Mark van Doesburg77a4a3e2009-01-07 16:37:27 +0100204static struct platform_device *f71882fg_pdev;
Hans de Goede45fb3662007-07-13 14:34:19 +0200205
206/* Super-I/O Function prototypes */
207static inline int superio_inb(int base, int reg);
208static inline int superio_inw(int base, int reg);
Giel van Schijndelcadb8652010-10-03 08:09:49 -0400209static inline int superio_enter(int base);
Hans de Goede45fb3662007-07-13 14:34:19 +0200210static inline void superio_select(int base, int ld);
211static inline void superio_exit(int base);
212
Hans de Goede498be962009-01-07 16:37:28 +0100213struct f71882fg_sio_data {
214 enum chips type;
215};
216
Hans de Goede45fb3662007-07-13 14:34:19 +0200217struct f71882fg_data {
218 unsigned short addr;
Hans de Goede498be962009-01-07 16:37:28 +0100219 enum chips type;
Tony Jones1beeffe2007-08-20 13:46:20 -0700220 struct device *hwmon_dev;
Hans de Goede45fb3662007-07-13 14:34:19 +0200221
222 struct mutex update_lock;
Hans de Goede09475d32009-06-15 18:39:52 +0200223 int temp_start; /* temp numbering start (0 or 1) */
Hans de Goede45fb3662007-07-13 14:34:19 +0200224 char valid; /* !=0 if following fields are valid */
Hans de Goede98f7ba12011-03-09 20:57:09 +0100225 char auto_point_temp_signed;
Hans de Goede45fb3662007-07-13 14:34:19 +0200226 unsigned long last_updated; /* In jiffies */
227 unsigned long last_limits; /* In jiffies */
228
229 /* Register Values */
Hans de Goede0bae6402011-03-09 20:57:10 +0100230 u8 in[F71882FG_MAX_INS];
Hans de Goede45fb3662007-07-13 14:34:19 +0200231 u8 in1_max;
232 u8 in_status;
233 u8 in_beep;
234 u16 fan[4];
Mark van Doesburg9ab796e2009-01-07 16:37:27 +0100235 u16 fan_target[4];
236 u16 fan_full_speed[4];
Hans de Goede45fb3662007-07-13 14:34:19 +0200237 u8 fan_status;
238 u8 fan_beep;
Hans de Goedee5e713c2011-03-10 08:54:02 +0100239 /* Note: all models have max 3 temperature channels, but on some
Hans de Goede7567a042009-01-07 16:37:28 +0100240 they are addressed as 0-2 and on others as 1-3, so for coding
241 convenience we reserve space for 4 channels */
Hans de Goede09475d32009-06-15 18:39:52 +0200242 u16 temp[4];
Hans de Goede7567a042009-01-07 16:37:28 +0100243 u8 temp_ovt[4];
244 u8 temp_high[4];
Hans de Goedebc274902009-01-07 16:37:29 +0100245 u8 temp_hyst[2]; /* 2 hysts stored per reg */
Hans de Goede7567a042009-01-07 16:37:28 +0100246 u8 temp_type[4];
Hans de Goede45fb3662007-07-13 14:34:19 +0200247 u8 temp_status;
248 u8 temp_beep;
249 u8 temp_diode_open;
Hans de Goede09475d32009-06-15 18:39:52 +0200250 u8 temp_config;
Mark van Doesburg9ab796e2009-01-07 16:37:27 +0100251 u8 pwm[4];
252 u8 pwm_enable;
253 u8 pwm_auto_point_hyst[2];
254 u8 pwm_auto_point_mapping[4];
255 u8 pwm_auto_point_pwm[4][5];
Hans de Goede76698962009-12-09 20:36:01 +0100256 s8 pwm_auto_point_temp[4][4];
Hans de Goede45fb3662007-07-13 14:34:19 +0200257};
258
Mark van Doesburg77a4a3e2009-01-07 16:37:27 +0100259/* Sysfs in */
Hans de Goede45fb3662007-07-13 14:34:19 +0200260static ssize_t show_in(struct device *dev, struct device_attribute *devattr,
261 char *buf);
262static ssize_t show_in_max(struct device *dev, struct device_attribute
263 *devattr, char *buf);
264static ssize_t store_in_max(struct device *dev, struct device_attribute
265 *devattr, const char *buf, size_t count);
266static ssize_t show_in_beep(struct device *dev, struct device_attribute
267 *devattr, char *buf);
268static ssize_t store_in_beep(struct device *dev, struct device_attribute
269 *devattr, const char *buf, size_t count);
270static ssize_t show_in_alarm(struct device *dev, struct device_attribute
271 *devattr, char *buf);
272/* Sysfs Fan */
273static ssize_t show_fan(struct device *dev, struct device_attribute *devattr,
274 char *buf);
Mark van Doesburg9ab796e2009-01-07 16:37:27 +0100275static ssize_t show_fan_full_speed(struct device *dev,
276 struct device_attribute *devattr, char *buf);
277static ssize_t store_fan_full_speed(struct device *dev,
278 struct device_attribute *devattr, const char *buf, size_t count);
Hans de Goede45fb3662007-07-13 14:34:19 +0200279static ssize_t show_fan_beep(struct device *dev, struct device_attribute
280 *devattr, char *buf);
281static ssize_t store_fan_beep(struct device *dev, struct device_attribute
282 *devattr, const char *buf, size_t count);
283static ssize_t show_fan_alarm(struct device *dev, struct device_attribute
284 *devattr, char *buf);
285/* Sysfs Temp */
286static ssize_t show_temp(struct device *dev, struct device_attribute
287 *devattr, char *buf);
288static ssize_t show_temp_max(struct device *dev, struct device_attribute
289 *devattr, char *buf);
290static ssize_t store_temp_max(struct device *dev, struct device_attribute
291 *devattr, const char *buf, size_t count);
292static ssize_t show_temp_max_hyst(struct device *dev, struct device_attribute
293 *devattr, char *buf);
294static ssize_t store_temp_max_hyst(struct device *dev, struct device_attribute
295 *devattr, const char *buf, size_t count);
296static ssize_t show_temp_crit(struct device *dev, struct device_attribute
297 *devattr, char *buf);
298static ssize_t store_temp_crit(struct device *dev, struct device_attribute
299 *devattr, const char *buf, size_t count);
300static ssize_t show_temp_crit_hyst(struct device *dev, struct device_attribute
301 *devattr, char *buf);
302static ssize_t show_temp_type(struct device *dev, struct device_attribute
303 *devattr, char *buf);
304static ssize_t show_temp_beep(struct device *dev, struct device_attribute
305 *devattr, char *buf);
306static ssize_t store_temp_beep(struct device *dev, struct device_attribute
307 *devattr, const char *buf, size_t count);
308static ssize_t show_temp_alarm(struct device *dev, struct device_attribute
309 *devattr, char *buf);
310static ssize_t show_temp_fault(struct device *dev, struct device_attribute
311 *devattr, char *buf);
Mark van Doesburg9ab796e2009-01-07 16:37:27 +0100312/* PWM and Auto point control */
313static ssize_t show_pwm(struct device *dev, struct device_attribute *devattr,
314 char *buf);
315static ssize_t store_pwm(struct device *dev, struct device_attribute *devattr,
316 const char *buf, size_t count);
317static ssize_t show_pwm_enable(struct device *dev,
318 struct device_attribute *devattr, char *buf);
319static ssize_t store_pwm_enable(struct device *dev,
320 struct device_attribute *devattr, const char *buf, size_t count);
321static ssize_t show_pwm_interpolate(struct device *dev,
322 struct device_attribute *devattr, char *buf);
323static ssize_t store_pwm_interpolate(struct device *dev,
324 struct device_attribute *devattr, const char *buf, size_t count);
325static ssize_t show_pwm_auto_point_channel(struct device *dev,
326 struct device_attribute *devattr, char *buf);
327static ssize_t store_pwm_auto_point_channel(struct device *dev,
328 struct device_attribute *devattr, const char *buf, size_t count);
329static ssize_t show_pwm_auto_point_temp_hyst(struct device *dev,
330 struct device_attribute *devattr, char *buf);
331static ssize_t store_pwm_auto_point_temp_hyst(struct device *dev,
332 struct device_attribute *devattr, const char *buf, size_t count);
333static ssize_t show_pwm_auto_point_pwm(struct device *dev,
334 struct device_attribute *devattr, char *buf);
335static ssize_t store_pwm_auto_point_pwm(struct device *dev,
336 struct device_attribute *devattr, const char *buf, size_t count);
337static ssize_t show_pwm_auto_point_temp(struct device *dev,
338 struct device_attribute *devattr, char *buf);
339static ssize_t store_pwm_auto_point_temp(struct device *dev,
340 struct device_attribute *devattr, const char *buf, size_t count);
Hans de Goede45fb3662007-07-13 14:34:19 +0200341/* Sysfs misc */
342static ssize_t show_name(struct device *dev, struct device_attribute *devattr,
343 char *buf);
344
345static int __devinit f71882fg_probe(struct platform_device * pdev);
Hans de Goedec13548c2009-01-07 16:37:27 +0100346static int f71882fg_remove(struct platform_device *pdev);
Hans de Goede45fb3662007-07-13 14:34:19 +0200347
348static struct platform_driver f71882fg_driver = {
349 .driver = {
350 .owner = THIS_MODULE,
351 .name = DRVNAME,
352 },
353 .probe = f71882fg_probe,
Jean Delvarecd659fd2009-06-15 18:39:45 +0200354 .remove = f71882fg_remove,
Hans de Goede45fb3662007-07-13 14:34:19 +0200355};
356
Hans de Goedec13548c2009-01-07 16:37:27 +0100357static DEVICE_ATTR(name, S_IRUGO, show_name, NULL);
Hans de Goede45fb3662007-07-13 14:34:19 +0200358
Hans de Goede0bae6402011-03-09 20:57:10 +0100359/* Temp attr for the f71858fg, the f71858fg is special as it has its
360 temperature indexes start at 0 (the others start at 1) */
361static struct sensor_device_attribute_2 f71858fg_temp_attr[] = {
Hans de Goede09475d32009-06-15 18:39:52 +0200362 SENSOR_ATTR_2(temp1_input, S_IRUGO, show_temp, NULL, 0, 0),
363 SENSOR_ATTR_2(temp1_max, S_IRUGO|S_IWUSR, show_temp_max,
364 store_temp_max, 0, 0),
365 SENSOR_ATTR_2(temp1_max_hyst, S_IRUGO|S_IWUSR, show_temp_max_hyst,
366 store_temp_max_hyst, 0, 0),
367 SENSOR_ATTR_2(temp1_max_alarm, S_IRUGO, show_temp_alarm, NULL, 0, 0),
368 SENSOR_ATTR_2(temp1_crit, S_IRUGO|S_IWUSR, show_temp_crit,
369 store_temp_crit, 0, 0),
370 SENSOR_ATTR_2(temp1_crit_hyst, S_IRUGO, show_temp_crit_hyst, NULL,
371 0, 0),
372 SENSOR_ATTR_2(temp1_crit_alarm, S_IRUGO, show_temp_alarm, NULL, 0, 4),
373 SENSOR_ATTR_2(temp1_fault, S_IRUGO, show_temp_fault, NULL, 0, 0),
374 SENSOR_ATTR_2(temp2_input, S_IRUGO, show_temp, NULL, 0, 1),
375 SENSOR_ATTR_2(temp2_max, S_IRUGO|S_IWUSR, show_temp_max,
376 store_temp_max, 0, 1),
377 SENSOR_ATTR_2(temp2_max_hyst, S_IRUGO|S_IWUSR, show_temp_max_hyst,
378 store_temp_max_hyst, 0, 1),
379 SENSOR_ATTR_2(temp2_max_alarm, S_IRUGO, show_temp_alarm, NULL, 0, 1),
380 SENSOR_ATTR_2(temp2_crit, S_IRUGO|S_IWUSR, show_temp_crit,
381 store_temp_crit, 0, 1),
382 SENSOR_ATTR_2(temp2_crit_hyst, S_IRUGO, show_temp_crit_hyst, NULL,
383 0, 1),
384 SENSOR_ATTR_2(temp2_crit_alarm, S_IRUGO, show_temp_alarm, NULL, 0, 5),
Hans de Goede09475d32009-06-15 18:39:52 +0200385 SENSOR_ATTR_2(temp2_fault, S_IRUGO, show_temp_fault, NULL, 0, 1),
386 SENSOR_ATTR_2(temp3_input, S_IRUGO, show_temp, NULL, 0, 2),
387 SENSOR_ATTR_2(temp3_max, S_IRUGO|S_IWUSR, show_temp_max,
388 store_temp_max, 0, 2),
389 SENSOR_ATTR_2(temp3_max_hyst, S_IRUGO|S_IWUSR, show_temp_max_hyst,
390 store_temp_max_hyst, 0, 2),
391 SENSOR_ATTR_2(temp3_max_alarm, S_IRUGO, show_temp_alarm, NULL, 0, 2),
392 SENSOR_ATTR_2(temp3_crit, S_IRUGO|S_IWUSR, show_temp_crit,
393 store_temp_crit, 0, 2),
394 SENSOR_ATTR_2(temp3_crit_hyst, S_IRUGO, show_temp_crit_hyst, NULL,
395 0, 2),
396 SENSOR_ATTR_2(temp3_crit_alarm, S_IRUGO, show_temp_alarm, NULL, 0, 6),
397 SENSOR_ATTR_2(temp3_fault, S_IRUGO, show_temp_fault, NULL, 0, 2),
398};
399
Hans de Goede0bae6402011-03-09 20:57:10 +0100400/* Temp attr for the standard models */
Hans de Goede78aa4f72011-03-09 20:57:12 +0100401static struct sensor_device_attribute_2 fxxxx_temp_attr[3][9] = { {
Hans de Goede7567a042009-01-07 16:37:28 +0100402 SENSOR_ATTR_2(temp1_input, S_IRUGO, show_temp, NULL, 0, 1),
Mark van Doesburgbc37ae72009-01-07 16:37:27 +0100403 SENSOR_ATTR_2(temp1_max, S_IRUGO|S_IWUSR, show_temp_max,
Mark van Doesburgbc37ae72009-01-07 16:37:27 +0100404 store_temp_max, 0, 1),
Hans de Goede7567a042009-01-07 16:37:28 +0100405 SENSOR_ATTR_2(temp1_max_hyst, S_IRUGO|S_IWUSR, show_temp_max_hyst,
Mark van Doesburgbc37ae72009-01-07 16:37:27 +0100406 store_temp_max_hyst, 0, 1),
Hans de Goede754a5907b2009-01-07 16:37:29 +0100407 /* Should really be temp1_max_alarm, but older versions did not handle
408 the max and crit alarms separately and lm_sensors v2 depends on the
409 presence of temp#_alarm files. The same goes for temp2/3 _alarm. */
410 SENSOR_ATTR_2(temp1_alarm, S_IRUGO, show_temp_alarm, NULL, 0, 1),
Hans de Goede7567a042009-01-07 16:37:28 +0100411 SENSOR_ATTR_2(temp1_crit, S_IRUGO|S_IWUSR, show_temp_crit,
Mark van Doesburgbc37ae72009-01-07 16:37:27 +0100412 store_temp_crit, 0, 1),
Hans de Goede7567a042009-01-07 16:37:28 +0100413 SENSOR_ATTR_2(temp1_crit_hyst, S_IRUGO, show_temp_crit_hyst, NULL,
Mark van Doesburgbc37ae72009-01-07 16:37:27 +0100414 0, 1),
Hans de Goede754a5907b2009-01-07 16:37:29 +0100415 SENSOR_ATTR_2(temp1_crit_alarm, S_IRUGO, show_temp_alarm, NULL, 0, 5),
Hans de Goede7567a042009-01-07 16:37:28 +0100416 SENSOR_ATTR_2(temp1_type, S_IRUGO, show_temp_type, NULL, 0, 1),
Hans de Goede7567a042009-01-07 16:37:28 +0100417 SENSOR_ATTR_2(temp1_fault, S_IRUGO, show_temp_fault, NULL, 0, 1),
Hans de Goede60d2b372011-03-09 20:57:11 +0100418}, {
Hans de Goede7567a042009-01-07 16:37:28 +0100419 SENSOR_ATTR_2(temp2_input, S_IRUGO, show_temp, NULL, 0, 2),
420 SENSOR_ATTR_2(temp2_max, S_IRUGO|S_IWUSR, show_temp_max,
Mark van Doesburgbc37ae72009-01-07 16:37:27 +0100421 store_temp_max, 0, 2),
Hans de Goede7567a042009-01-07 16:37:28 +0100422 SENSOR_ATTR_2(temp2_max_hyst, S_IRUGO|S_IWUSR, show_temp_max_hyst,
Mark van Doesburgbc37ae72009-01-07 16:37:27 +0100423 store_temp_max_hyst, 0, 2),
Hans de Goede754a5907b2009-01-07 16:37:29 +0100424 /* Should be temp2_max_alarm, see temp1_alarm note */
425 SENSOR_ATTR_2(temp2_alarm, S_IRUGO, show_temp_alarm, NULL, 0, 2),
Hans de Goede7567a042009-01-07 16:37:28 +0100426 SENSOR_ATTR_2(temp2_crit, S_IRUGO|S_IWUSR, show_temp_crit,
Mark van Doesburgbc37ae72009-01-07 16:37:27 +0100427 store_temp_crit, 0, 2),
Hans de Goede7567a042009-01-07 16:37:28 +0100428 SENSOR_ATTR_2(temp2_crit_hyst, S_IRUGO, show_temp_crit_hyst, NULL,
Mark van Doesburgbc37ae72009-01-07 16:37:27 +0100429 0, 2),
Hans de Goede754a5907b2009-01-07 16:37:29 +0100430 SENSOR_ATTR_2(temp2_crit_alarm, S_IRUGO, show_temp_alarm, NULL, 0, 6),
Hans de Goede7567a042009-01-07 16:37:28 +0100431 SENSOR_ATTR_2(temp2_type, S_IRUGO, show_temp_type, NULL, 0, 2),
Hans de Goede7567a042009-01-07 16:37:28 +0100432 SENSOR_ATTR_2(temp2_fault, S_IRUGO, show_temp_fault, NULL, 0, 2),
Hans de Goede60d2b372011-03-09 20:57:11 +0100433}, {
Hans de Goede7567a042009-01-07 16:37:28 +0100434 SENSOR_ATTR_2(temp3_input, S_IRUGO, show_temp, NULL, 0, 3),
435 SENSOR_ATTR_2(temp3_max, S_IRUGO|S_IWUSR, show_temp_max,
436 store_temp_max, 0, 3),
437 SENSOR_ATTR_2(temp3_max_hyst, S_IRUGO|S_IWUSR, show_temp_max_hyst,
438 store_temp_max_hyst, 0, 3),
Hans de Goede754a5907b2009-01-07 16:37:29 +0100439 /* Should be temp3_max_alarm, see temp1_alarm note */
440 SENSOR_ATTR_2(temp3_alarm, S_IRUGO, show_temp_alarm, NULL, 0, 3),
Hans de Goede7567a042009-01-07 16:37:28 +0100441 SENSOR_ATTR_2(temp3_crit, S_IRUGO|S_IWUSR, show_temp_crit,
442 store_temp_crit, 0, 3),
443 SENSOR_ATTR_2(temp3_crit_hyst, S_IRUGO, show_temp_crit_hyst, NULL,
444 0, 3),
Hans de Goede754a5907b2009-01-07 16:37:29 +0100445 SENSOR_ATTR_2(temp3_crit_alarm, S_IRUGO, show_temp_alarm, NULL, 0, 7),
Hans de Goede7567a042009-01-07 16:37:28 +0100446 SENSOR_ATTR_2(temp3_type, S_IRUGO, show_temp_type, NULL, 0, 3),
Hans de Goede7567a042009-01-07 16:37:28 +0100447 SENSOR_ATTR_2(temp3_fault, S_IRUGO, show_temp_fault, NULL, 0, 3),
Hans de Goede60d2b372011-03-09 20:57:11 +0100448} };
Hans de Goede45fb3662007-07-13 14:34:19 +0200449
Hans de Goede78aa4f72011-03-09 20:57:12 +0100450/* Temp attr for models which can beep on temp alarm */
451static struct sensor_device_attribute_2 fxxxx_temp_beep_attr[3][2] = { {
452 SENSOR_ATTR_2(temp1_max_beep, S_IRUGO|S_IWUSR, show_temp_beep,
453 store_temp_beep, 0, 1),
454 SENSOR_ATTR_2(temp1_crit_beep, S_IRUGO|S_IWUSR, show_temp_beep,
455 store_temp_beep, 0, 5),
456}, {
457 SENSOR_ATTR_2(temp2_max_beep, S_IRUGO|S_IWUSR, show_temp_beep,
458 store_temp_beep, 0, 2),
459 SENSOR_ATTR_2(temp2_crit_beep, S_IRUGO|S_IWUSR, show_temp_beep,
460 store_temp_beep, 0, 6),
461}, {
462 SENSOR_ATTR_2(temp3_max_beep, S_IRUGO|S_IWUSR, show_temp_beep,
463 store_temp_beep, 0, 3),
464 SENSOR_ATTR_2(temp3_crit_beep, S_IRUGO|S_IWUSR, show_temp_beep,
465 store_temp_beep, 0, 7),
466} };
467
Hans de Goede0bae6402011-03-09 20:57:10 +0100468/* Temp attr for the f8000
Hans de Goedeed4f7c22009-01-07 16:37:30 +0100469 Note on the f8000 temp_ovt (crit) is used as max, and temp_high (max)
470 is used as hysteresis value to clear alarms
Hans de Goede66344aa2009-12-09 20:35:59 +0100471 Also like the f71858fg its temperature indexes start at 0
Hans de Goedeed4f7c22009-01-07 16:37:30 +0100472 */
Hans de Goede0bae6402011-03-09 20:57:10 +0100473static struct sensor_device_attribute_2 f8000_temp_attr[] = {
Hans de Goedeed4f7c22009-01-07 16:37:30 +0100474 SENSOR_ATTR_2(temp1_input, S_IRUGO, show_temp, NULL, 0, 0),
475 SENSOR_ATTR_2(temp1_max, S_IRUGO|S_IWUSR, show_temp_crit,
476 store_temp_crit, 0, 0),
477 SENSOR_ATTR_2(temp1_max_hyst, S_IRUGO|S_IWUSR, show_temp_max,
478 store_temp_max, 0, 0),
479 SENSOR_ATTR_2(temp1_alarm, S_IRUGO, show_temp_alarm, NULL, 0, 4),
Hans de Goedeb6858bc2009-06-15 18:39:51 +0200480 SENSOR_ATTR_2(temp1_fault, S_IRUGO, show_temp_fault, NULL, 0, 0),
Hans de Goedeed4f7c22009-01-07 16:37:30 +0100481 SENSOR_ATTR_2(temp2_input, S_IRUGO, show_temp, NULL, 0, 1),
482 SENSOR_ATTR_2(temp2_max, S_IRUGO|S_IWUSR, show_temp_crit,
483 store_temp_crit, 0, 1),
484 SENSOR_ATTR_2(temp2_max_hyst, S_IRUGO|S_IWUSR, show_temp_max,
485 store_temp_max, 0, 1),
486 SENSOR_ATTR_2(temp2_alarm, S_IRUGO, show_temp_alarm, NULL, 0, 5),
Hans de Goedeb6858bc2009-06-15 18:39:51 +0200487 SENSOR_ATTR_2(temp2_fault, S_IRUGO, show_temp_fault, NULL, 0, 1),
Hans de Goedeed4f7c22009-01-07 16:37:30 +0100488 SENSOR_ATTR_2(temp3_input, S_IRUGO, show_temp, NULL, 0, 2),
489 SENSOR_ATTR_2(temp3_max, S_IRUGO|S_IWUSR, show_temp_crit,
490 store_temp_crit, 0, 2),
491 SENSOR_ATTR_2(temp3_max_hyst, S_IRUGO|S_IWUSR, show_temp_max,
492 store_temp_max, 0, 2),
493 SENSOR_ATTR_2(temp3_alarm, S_IRUGO, show_temp_alarm, NULL, 0, 6),
Hans de Goedeb6858bc2009-06-15 18:39:51 +0200494 SENSOR_ATTR_2(temp3_fault, S_IRUGO, show_temp_fault, NULL, 0, 2),
Hans de Goedeed4f7c22009-01-07 16:37:30 +0100495};
496
Hans de Goede0bae6402011-03-09 20:57:10 +0100497/* in attr for all models */
498static struct sensor_device_attribute_2 fxxxx_in_attr[] = {
499 SENSOR_ATTR_2(in0_input, S_IRUGO, show_in, NULL, 0, 0),
500 SENSOR_ATTR_2(in1_input, S_IRUGO, show_in, NULL, 0, 1),
501 SENSOR_ATTR_2(in2_input, S_IRUGO, show_in, NULL, 0, 2),
502 SENSOR_ATTR_2(in3_input, S_IRUGO, show_in, NULL, 0, 3),
503 SENSOR_ATTR_2(in4_input, S_IRUGO, show_in, NULL, 0, 4),
504 SENSOR_ATTR_2(in5_input, S_IRUGO, show_in, NULL, 0, 5),
505 SENSOR_ATTR_2(in6_input, S_IRUGO, show_in, NULL, 0, 6),
506 SENSOR_ATTR_2(in7_input, S_IRUGO, show_in, NULL, 0, 7),
507 SENSOR_ATTR_2(in8_input, S_IRUGO, show_in, NULL, 0, 8),
508};
509
510/* For models with in1 alarm capability */
511static struct sensor_device_attribute_2 fxxxx_in1_alarm_attr[] = {
512 SENSOR_ATTR_2(in1_max, S_IRUGO|S_IWUSR, show_in_max, store_in_max,
513 0, 1),
514 SENSOR_ATTR_2(in1_beep, S_IRUGO|S_IWUSR, show_in_beep, store_in_beep,
515 0, 1),
516 SENSOR_ATTR_2(in1_alarm, S_IRUGO, show_in_alarm, NULL, 0, 1),
517};
518
Hans de Goedeed4f7c22009-01-07 16:37:30 +0100519/* Fan / PWM attr common to all models */
Hans de Goedeb69b0392009-12-09 20:36:00 +0100520static struct sensor_device_attribute_2 fxxxx_fan_attr[4][6] = { {
Mark van Doesburgbc37ae72009-01-07 16:37:27 +0100521 SENSOR_ATTR_2(fan1_input, S_IRUGO, show_fan, NULL, 0, 0),
Mark van Doesburg9ab796e2009-01-07 16:37:27 +0100522 SENSOR_ATTR_2(fan1_full_speed, S_IRUGO|S_IWUSR,
523 show_fan_full_speed,
524 store_fan_full_speed, 0, 0),
Mark van Doesburgbc37ae72009-01-07 16:37:27 +0100525 SENSOR_ATTR_2(fan1_alarm, S_IRUGO, show_fan_alarm, NULL, 0, 0),
Mark van Doesburg9ab796e2009-01-07 16:37:27 +0100526 SENSOR_ATTR_2(pwm1, S_IRUGO|S_IWUSR, show_pwm, store_pwm, 0, 0),
527 SENSOR_ATTR_2(pwm1_enable, S_IRUGO|S_IWUSR, show_pwm_enable,
528 store_pwm_enable, 0, 0),
529 SENSOR_ATTR_2(pwm1_interpolate, S_IRUGO|S_IWUSR,
530 show_pwm_interpolate, store_pwm_interpolate, 0, 0),
Hans de Goedeb69b0392009-12-09 20:36:00 +0100531}, {
532 SENSOR_ATTR_2(fan2_input, S_IRUGO, show_fan, NULL, 0, 1),
533 SENSOR_ATTR_2(fan2_full_speed, S_IRUGO|S_IWUSR,
534 show_fan_full_speed,
535 store_fan_full_speed, 0, 1),
536 SENSOR_ATTR_2(fan2_alarm, S_IRUGO, show_fan_alarm, NULL, 0, 1),
Hans de Goede498be962009-01-07 16:37:28 +0100537 SENSOR_ATTR_2(pwm2, S_IRUGO|S_IWUSR, show_pwm, store_pwm, 0, 1),
538 SENSOR_ATTR_2(pwm2_enable, S_IRUGO|S_IWUSR, show_pwm_enable,
539 store_pwm_enable, 0, 1),
540 SENSOR_ATTR_2(pwm2_interpolate, S_IRUGO|S_IWUSR,
541 show_pwm_interpolate, store_pwm_interpolate, 0, 1),
Hans de Goedeb69b0392009-12-09 20:36:00 +0100542}, {
543 SENSOR_ATTR_2(fan3_input, S_IRUGO, show_fan, NULL, 0, 2),
544 SENSOR_ATTR_2(fan3_full_speed, S_IRUGO|S_IWUSR,
545 show_fan_full_speed,
546 store_fan_full_speed, 0, 2),
547 SENSOR_ATTR_2(fan3_alarm, S_IRUGO, show_fan_alarm, NULL, 0, 2),
Hans de Goede3fc78382009-06-15 18:39:50 +0200548 SENSOR_ATTR_2(pwm3, S_IRUGO|S_IWUSR, show_pwm, store_pwm, 0, 2),
549 SENSOR_ATTR_2(pwm3_enable, S_IRUGO|S_IWUSR, show_pwm_enable,
550 store_pwm_enable, 0, 2),
Hans de Goede498be962009-01-07 16:37:28 +0100551 SENSOR_ATTR_2(pwm3_interpolate, S_IRUGO|S_IWUSR,
552 show_pwm_interpolate, store_pwm_interpolate, 0, 2),
Hans de Goedeb69b0392009-12-09 20:36:00 +0100553}, {
554 SENSOR_ATTR_2(fan4_input, S_IRUGO, show_fan, NULL, 0, 3),
555 SENSOR_ATTR_2(fan4_full_speed, S_IRUGO|S_IWUSR,
556 show_fan_full_speed,
557 store_fan_full_speed, 0, 3),
558 SENSOR_ATTR_2(fan4_alarm, S_IRUGO, show_fan_alarm, NULL, 0, 3),
559 SENSOR_ATTR_2(pwm4, S_IRUGO|S_IWUSR, show_pwm, store_pwm, 0, 3),
560 SENSOR_ATTR_2(pwm4_enable, S_IRUGO|S_IWUSR, show_pwm_enable,
561 store_pwm_enable, 0, 3),
562 SENSOR_ATTR_2(pwm4_interpolate, S_IRUGO|S_IWUSR,
563 show_pwm_interpolate, store_pwm_interpolate, 0, 3),
564} };
Hans de Goede498be962009-01-07 16:37:28 +0100565
Hans de Goede66344aa2009-12-09 20:35:59 +0100566/* Attr for models which can beep on Fan alarm */
567static struct sensor_device_attribute_2 fxxxx_fan_beep_attr[] = {
Hans de Goedeed4f7c22009-01-07 16:37:30 +0100568 SENSOR_ATTR_2(fan1_beep, S_IRUGO|S_IWUSR, show_fan_beep,
569 store_fan_beep, 0, 0),
570 SENSOR_ATTR_2(fan2_beep, S_IRUGO|S_IWUSR, show_fan_beep,
571 store_fan_beep, 0, 1),
572 SENSOR_ATTR_2(fan3_beep, S_IRUGO|S_IWUSR, show_fan_beep,
573 store_fan_beep, 0, 2),
Hans de Goedeb69b0392009-12-09 20:36:00 +0100574 SENSOR_ATTR_2(fan4_beep, S_IRUGO|S_IWUSR, show_fan_beep,
575 store_fan_beep, 0, 3),
Hans de Goede66344aa2009-12-09 20:35:59 +0100576};
Hans de Goedeed4f7c22009-01-07 16:37:30 +0100577
Hans de Goede66344aa2009-12-09 20:35:59 +0100578/* PWM attr for the f71862fg, fewer pwms and fewer zones per pwm than the
Hans de Goede3cad4022011-03-09 20:57:14 +0100579 standard models */
Hans de Goede66344aa2009-12-09 20:35:59 +0100580static struct sensor_device_attribute_2 f71862fg_auto_pwm_attr[] = {
581 SENSOR_ATTR_2(pwm1_auto_channels_temp, S_IRUGO|S_IWUSR,
582 show_pwm_auto_point_channel,
583 store_pwm_auto_point_channel, 0, 0),
Hans de Goede498be962009-01-07 16:37:28 +0100584 SENSOR_ATTR_2(pwm1_auto_point1_pwm, S_IRUGO|S_IWUSR,
585 show_pwm_auto_point_pwm, store_pwm_auto_point_pwm,
586 1, 0),
587 SENSOR_ATTR_2(pwm1_auto_point2_pwm, S_IRUGO|S_IWUSR,
588 show_pwm_auto_point_pwm, store_pwm_auto_point_pwm,
589 4, 0),
590 SENSOR_ATTR_2(pwm1_auto_point1_temp, S_IRUGO|S_IWUSR,
591 show_pwm_auto_point_temp, store_pwm_auto_point_temp,
592 0, 0),
593 SENSOR_ATTR_2(pwm1_auto_point2_temp, S_IRUGO|S_IWUSR,
594 show_pwm_auto_point_temp, store_pwm_auto_point_temp,
595 3, 0),
596 SENSOR_ATTR_2(pwm1_auto_point1_temp_hyst, S_IRUGO|S_IWUSR,
597 show_pwm_auto_point_temp_hyst,
598 store_pwm_auto_point_temp_hyst,
599 0, 0),
600 SENSOR_ATTR_2(pwm1_auto_point2_temp_hyst, S_IRUGO,
601 show_pwm_auto_point_temp_hyst, NULL, 3, 0),
602
Hans de Goede66344aa2009-12-09 20:35:59 +0100603 SENSOR_ATTR_2(pwm2_auto_channels_temp, S_IRUGO|S_IWUSR,
604 show_pwm_auto_point_channel,
605 store_pwm_auto_point_channel, 0, 1),
Hans de Goede498be962009-01-07 16:37:28 +0100606 SENSOR_ATTR_2(pwm2_auto_point1_pwm, S_IRUGO|S_IWUSR,
607 show_pwm_auto_point_pwm, store_pwm_auto_point_pwm,
608 1, 1),
609 SENSOR_ATTR_2(pwm2_auto_point2_pwm, S_IRUGO|S_IWUSR,
610 show_pwm_auto_point_pwm, store_pwm_auto_point_pwm,
611 4, 1),
612 SENSOR_ATTR_2(pwm2_auto_point1_temp, S_IRUGO|S_IWUSR,
613 show_pwm_auto_point_temp, store_pwm_auto_point_temp,
614 0, 1),
615 SENSOR_ATTR_2(pwm2_auto_point2_temp, S_IRUGO|S_IWUSR,
616 show_pwm_auto_point_temp, store_pwm_auto_point_temp,
617 3, 1),
618 SENSOR_ATTR_2(pwm2_auto_point1_temp_hyst, S_IRUGO|S_IWUSR,
619 show_pwm_auto_point_temp_hyst,
620 store_pwm_auto_point_temp_hyst,
621 0, 1),
622 SENSOR_ATTR_2(pwm2_auto_point2_temp_hyst, S_IRUGO,
623 show_pwm_auto_point_temp_hyst, NULL, 3, 1),
Hans de Goede49010622009-01-07 16:37:30 +0100624
Hans de Goede66344aa2009-12-09 20:35:59 +0100625 SENSOR_ATTR_2(pwm3_auto_channels_temp, S_IRUGO|S_IWUSR,
626 show_pwm_auto_point_channel,
627 store_pwm_auto_point_channel, 0, 2),
Hans de Goede49010622009-01-07 16:37:30 +0100628 SENSOR_ATTR_2(pwm3_auto_point1_pwm, S_IRUGO|S_IWUSR,
629 show_pwm_auto_point_pwm, store_pwm_auto_point_pwm,
630 1, 2),
631 SENSOR_ATTR_2(pwm3_auto_point2_pwm, S_IRUGO|S_IWUSR,
632 show_pwm_auto_point_pwm, store_pwm_auto_point_pwm,
633 4, 2),
634 SENSOR_ATTR_2(pwm3_auto_point1_temp, S_IRUGO|S_IWUSR,
635 show_pwm_auto_point_temp, store_pwm_auto_point_temp,
636 0, 2),
637 SENSOR_ATTR_2(pwm3_auto_point2_temp, S_IRUGO|S_IWUSR,
638 show_pwm_auto_point_temp, store_pwm_auto_point_temp,
639 3, 2),
640 SENSOR_ATTR_2(pwm3_auto_point1_temp_hyst, S_IRUGO|S_IWUSR,
641 show_pwm_auto_point_temp_hyst,
642 store_pwm_auto_point_temp_hyst,
643 0, 2),
644 SENSOR_ATTR_2(pwm3_auto_point2_temp_hyst, S_IRUGO,
645 show_pwm_auto_point_temp_hyst, NULL, 3, 2),
Hans de Goede498be962009-01-07 16:37:28 +0100646};
647
Hans de Goedee5e713c2011-03-10 08:54:02 +0100648/* PWM attr for the f71808e/f71869, almost identical to the f71862fg, but the
Hans de Goedec11bb992011-03-09 20:57:15 +0100649 pwm setting when the temperature is above the pwmX_auto_point1_temp can be
650 programmed instead of being hardcoded to 0xff */
651static struct sensor_device_attribute_2 f71869_auto_pwm_attr[] = {
652 SENSOR_ATTR_2(pwm1_auto_channels_temp, S_IRUGO|S_IWUSR,
653 show_pwm_auto_point_channel,
654 store_pwm_auto_point_channel, 0, 0),
655 SENSOR_ATTR_2(pwm1_auto_point1_pwm, S_IRUGO|S_IWUSR,
656 show_pwm_auto_point_pwm, store_pwm_auto_point_pwm,
657 0, 0),
658 SENSOR_ATTR_2(pwm1_auto_point2_pwm, S_IRUGO|S_IWUSR,
659 show_pwm_auto_point_pwm, store_pwm_auto_point_pwm,
660 1, 0),
661 SENSOR_ATTR_2(pwm1_auto_point3_pwm, S_IRUGO|S_IWUSR,
662 show_pwm_auto_point_pwm, store_pwm_auto_point_pwm,
663 4, 0),
664 SENSOR_ATTR_2(pwm1_auto_point1_temp, S_IRUGO|S_IWUSR,
665 show_pwm_auto_point_temp, store_pwm_auto_point_temp,
666 0, 0),
667 SENSOR_ATTR_2(pwm1_auto_point2_temp, S_IRUGO|S_IWUSR,
668 show_pwm_auto_point_temp, store_pwm_auto_point_temp,
669 3, 0),
670 SENSOR_ATTR_2(pwm1_auto_point1_temp_hyst, S_IRUGO|S_IWUSR,
671 show_pwm_auto_point_temp_hyst,
672 store_pwm_auto_point_temp_hyst,
673 0, 0),
674 SENSOR_ATTR_2(pwm1_auto_point2_temp_hyst, S_IRUGO,
675 show_pwm_auto_point_temp_hyst, NULL, 3, 0),
676
677 SENSOR_ATTR_2(pwm2_auto_channels_temp, S_IRUGO|S_IWUSR,
678 show_pwm_auto_point_channel,
679 store_pwm_auto_point_channel, 0, 1),
680 SENSOR_ATTR_2(pwm2_auto_point1_pwm, S_IRUGO|S_IWUSR,
681 show_pwm_auto_point_pwm, store_pwm_auto_point_pwm,
682 0, 1),
683 SENSOR_ATTR_2(pwm2_auto_point2_pwm, S_IRUGO|S_IWUSR,
684 show_pwm_auto_point_pwm, store_pwm_auto_point_pwm,
685 1, 1),
686 SENSOR_ATTR_2(pwm2_auto_point3_pwm, S_IRUGO|S_IWUSR,
687 show_pwm_auto_point_pwm, store_pwm_auto_point_pwm,
688 4, 1),
689 SENSOR_ATTR_2(pwm2_auto_point1_temp, S_IRUGO|S_IWUSR,
690 show_pwm_auto_point_temp, store_pwm_auto_point_temp,
691 0, 1),
692 SENSOR_ATTR_2(pwm2_auto_point2_temp, S_IRUGO|S_IWUSR,
693 show_pwm_auto_point_temp, store_pwm_auto_point_temp,
694 3, 1),
695 SENSOR_ATTR_2(pwm2_auto_point1_temp_hyst, S_IRUGO|S_IWUSR,
696 show_pwm_auto_point_temp_hyst,
697 store_pwm_auto_point_temp_hyst,
698 0, 1),
699 SENSOR_ATTR_2(pwm2_auto_point2_temp_hyst, S_IRUGO,
700 show_pwm_auto_point_temp_hyst, NULL, 3, 1),
701
702 SENSOR_ATTR_2(pwm3_auto_channels_temp, S_IRUGO|S_IWUSR,
703 show_pwm_auto_point_channel,
704 store_pwm_auto_point_channel, 0, 2),
705 SENSOR_ATTR_2(pwm3_auto_point1_pwm, S_IRUGO|S_IWUSR,
706 show_pwm_auto_point_pwm, store_pwm_auto_point_pwm,
707 0, 2),
708 SENSOR_ATTR_2(pwm3_auto_point2_pwm, S_IRUGO|S_IWUSR,
709 show_pwm_auto_point_pwm, store_pwm_auto_point_pwm,
710 1, 2),
711 SENSOR_ATTR_2(pwm3_auto_point3_pwm, S_IRUGO|S_IWUSR,
712 show_pwm_auto_point_pwm, store_pwm_auto_point_pwm,
713 4, 2),
714 SENSOR_ATTR_2(pwm3_auto_point1_temp, S_IRUGO|S_IWUSR,
715 show_pwm_auto_point_temp, store_pwm_auto_point_temp,
716 0, 2),
717 SENSOR_ATTR_2(pwm3_auto_point2_temp, S_IRUGO|S_IWUSR,
718 show_pwm_auto_point_temp, store_pwm_auto_point_temp,
719 3, 2),
720 SENSOR_ATTR_2(pwm3_auto_point1_temp_hyst, S_IRUGO|S_IWUSR,
721 show_pwm_auto_point_temp_hyst,
722 store_pwm_auto_point_temp_hyst,
723 0, 2),
724 SENSOR_ATTR_2(pwm3_auto_point2_temp_hyst, S_IRUGO,
725 show_pwm_auto_point_temp_hyst, NULL, 3, 2),
726};
727
Hans de Goede3cad4022011-03-09 20:57:14 +0100728/* PWM attr for the standard models */
Hans de Goedeb69b0392009-12-09 20:36:00 +0100729static struct sensor_device_attribute_2 fxxxx_auto_pwm_attr[4][14] = { {
Hans de Goede66344aa2009-12-09 20:35:59 +0100730 SENSOR_ATTR_2(pwm1_auto_channels_temp, S_IRUGO|S_IWUSR,
731 show_pwm_auto_point_channel,
732 store_pwm_auto_point_channel, 0, 0),
Mark van Doesburg9ab796e2009-01-07 16:37:27 +0100733 SENSOR_ATTR_2(pwm1_auto_point1_pwm, S_IRUGO|S_IWUSR,
734 show_pwm_auto_point_pwm, store_pwm_auto_point_pwm,
735 0, 0),
736 SENSOR_ATTR_2(pwm1_auto_point2_pwm, S_IRUGO|S_IWUSR,
737 show_pwm_auto_point_pwm, store_pwm_auto_point_pwm,
738 1, 0),
739 SENSOR_ATTR_2(pwm1_auto_point3_pwm, S_IRUGO|S_IWUSR,
740 show_pwm_auto_point_pwm, store_pwm_auto_point_pwm,
741 2, 0),
742 SENSOR_ATTR_2(pwm1_auto_point4_pwm, S_IRUGO|S_IWUSR,
743 show_pwm_auto_point_pwm, store_pwm_auto_point_pwm,
744 3, 0),
745 SENSOR_ATTR_2(pwm1_auto_point5_pwm, S_IRUGO|S_IWUSR,
746 show_pwm_auto_point_pwm, store_pwm_auto_point_pwm,
747 4, 0),
748 SENSOR_ATTR_2(pwm1_auto_point1_temp, S_IRUGO|S_IWUSR,
749 show_pwm_auto_point_temp, store_pwm_auto_point_temp,
750 0, 0),
751 SENSOR_ATTR_2(pwm1_auto_point2_temp, S_IRUGO|S_IWUSR,
752 show_pwm_auto_point_temp, store_pwm_auto_point_temp,
753 1, 0),
754 SENSOR_ATTR_2(pwm1_auto_point3_temp, S_IRUGO|S_IWUSR,
755 show_pwm_auto_point_temp, store_pwm_auto_point_temp,
756 2, 0),
757 SENSOR_ATTR_2(pwm1_auto_point4_temp, S_IRUGO|S_IWUSR,
758 show_pwm_auto_point_temp, store_pwm_auto_point_temp,
759 3, 0),
760 SENSOR_ATTR_2(pwm1_auto_point1_temp_hyst, S_IRUGO|S_IWUSR,
761 show_pwm_auto_point_temp_hyst,
762 store_pwm_auto_point_temp_hyst,
763 0, 0),
764 SENSOR_ATTR_2(pwm1_auto_point2_temp_hyst, S_IRUGO,
765 show_pwm_auto_point_temp_hyst, NULL, 1, 0),
766 SENSOR_ATTR_2(pwm1_auto_point3_temp_hyst, S_IRUGO,
767 show_pwm_auto_point_temp_hyst, NULL, 2, 0),
768 SENSOR_ATTR_2(pwm1_auto_point4_temp_hyst, S_IRUGO,
769 show_pwm_auto_point_temp_hyst, NULL, 3, 0),
Hans de Goedeb69b0392009-12-09 20:36:00 +0100770}, {
Hans de Goede66344aa2009-12-09 20:35:59 +0100771 SENSOR_ATTR_2(pwm2_auto_channels_temp, S_IRUGO|S_IWUSR,
772 show_pwm_auto_point_channel,
773 store_pwm_auto_point_channel, 0, 1),
Mark van Doesburg9ab796e2009-01-07 16:37:27 +0100774 SENSOR_ATTR_2(pwm2_auto_point1_pwm, S_IRUGO|S_IWUSR,
775 show_pwm_auto_point_pwm, store_pwm_auto_point_pwm,
776 0, 1),
777 SENSOR_ATTR_2(pwm2_auto_point2_pwm, S_IRUGO|S_IWUSR,
778 show_pwm_auto_point_pwm, store_pwm_auto_point_pwm,
779 1, 1),
780 SENSOR_ATTR_2(pwm2_auto_point3_pwm, S_IRUGO|S_IWUSR,
781 show_pwm_auto_point_pwm, store_pwm_auto_point_pwm,
782 2, 1),
783 SENSOR_ATTR_2(pwm2_auto_point4_pwm, S_IRUGO|S_IWUSR,
784 show_pwm_auto_point_pwm, store_pwm_auto_point_pwm,
785 3, 1),
786 SENSOR_ATTR_2(pwm2_auto_point5_pwm, S_IRUGO|S_IWUSR,
787 show_pwm_auto_point_pwm, store_pwm_auto_point_pwm,
788 4, 1),
789 SENSOR_ATTR_2(pwm2_auto_point1_temp, S_IRUGO|S_IWUSR,
790 show_pwm_auto_point_temp, store_pwm_auto_point_temp,
791 0, 1),
792 SENSOR_ATTR_2(pwm2_auto_point2_temp, S_IRUGO|S_IWUSR,
793 show_pwm_auto_point_temp, store_pwm_auto_point_temp,
794 1, 1),
795 SENSOR_ATTR_2(pwm2_auto_point3_temp, S_IRUGO|S_IWUSR,
796 show_pwm_auto_point_temp, store_pwm_auto_point_temp,
797 2, 1),
798 SENSOR_ATTR_2(pwm2_auto_point4_temp, S_IRUGO|S_IWUSR,
799 show_pwm_auto_point_temp, store_pwm_auto_point_temp,
800 3, 1),
801 SENSOR_ATTR_2(pwm2_auto_point1_temp_hyst, S_IRUGO|S_IWUSR,
802 show_pwm_auto_point_temp_hyst,
803 store_pwm_auto_point_temp_hyst,
804 0, 1),
805 SENSOR_ATTR_2(pwm2_auto_point2_temp_hyst, S_IRUGO,
806 show_pwm_auto_point_temp_hyst, NULL, 1, 1),
807 SENSOR_ATTR_2(pwm2_auto_point3_temp_hyst, S_IRUGO,
808 show_pwm_auto_point_temp_hyst, NULL, 2, 1),
809 SENSOR_ATTR_2(pwm2_auto_point4_temp_hyst, S_IRUGO,
810 show_pwm_auto_point_temp_hyst, NULL, 3, 1),
Hans de Goedeb69b0392009-12-09 20:36:00 +0100811}, {
Hans de Goede66344aa2009-12-09 20:35:59 +0100812 SENSOR_ATTR_2(pwm3_auto_channels_temp, S_IRUGO|S_IWUSR,
813 show_pwm_auto_point_channel,
814 store_pwm_auto_point_channel, 0, 2),
Mark van Doesburg9ab796e2009-01-07 16:37:27 +0100815 SENSOR_ATTR_2(pwm3_auto_point1_pwm, S_IRUGO|S_IWUSR,
816 show_pwm_auto_point_pwm, store_pwm_auto_point_pwm,
817 0, 2),
818 SENSOR_ATTR_2(pwm3_auto_point2_pwm, S_IRUGO|S_IWUSR,
819 show_pwm_auto_point_pwm, store_pwm_auto_point_pwm,
820 1, 2),
821 SENSOR_ATTR_2(pwm3_auto_point3_pwm, S_IRUGO|S_IWUSR,
822 show_pwm_auto_point_pwm, store_pwm_auto_point_pwm,
823 2, 2),
824 SENSOR_ATTR_2(pwm3_auto_point4_pwm, S_IRUGO|S_IWUSR,
825 show_pwm_auto_point_pwm, store_pwm_auto_point_pwm,
826 3, 2),
827 SENSOR_ATTR_2(pwm3_auto_point5_pwm, S_IRUGO|S_IWUSR,
828 show_pwm_auto_point_pwm, store_pwm_auto_point_pwm,
829 4, 2),
830 SENSOR_ATTR_2(pwm3_auto_point1_temp, S_IRUGO|S_IWUSR,
831 show_pwm_auto_point_temp, store_pwm_auto_point_temp,
832 0, 2),
833 SENSOR_ATTR_2(pwm3_auto_point2_temp, S_IRUGO|S_IWUSR,
834 show_pwm_auto_point_temp, store_pwm_auto_point_temp,
835 1, 2),
836 SENSOR_ATTR_2(pwm3_auto_point3_temp, S_IRUGO|S_IWUSR,
837 show_pwm_auto_point_temp, store_pwm_auto_point_temp,
838 2, 2),
839 SENSOR_ATTR_2(pwm3_auto_point4_temp, S_IRUGO|S_IWUSR,
840 show_pwm_auto_point_temp, store_pwm_auto_point_temp,
841 3, 2),
842 SENSOR_ATTR_2(pwm3_auto_point1_temp_hyst, S_IRUGO|S_IWUSR,
843 show_pwm_auto_point_temp_hyst,
844 store_pwm_auto_point_temp_hyst,
845 0, 2),
846 SENSOR_ATTR_2(pwm3_auto_point2_temp_hyst, S_IRUGO,
847 show_pwm_auto_point_temp_hyst, NULL, 1, 2),
848 SENSOR_ATTR_2(pwm3_auto_point3_temp_hyst, S_IRUGO,
849 show_pwm_auto_point_temp_hyst, NULL, 2, 2),
850 SENSOR_ATTR_2(pwm3_auto_point4_temp_hyst, S_IRUGO,
851 show_pwm_auto_point_temp_hyst, NULL, 3, 2),
Hans de Goedeb69b0392009-12-09 20:36:00 +0100852}, {
Mark van Doesburg9ab796e2009-01-07 16:37:27 +0100853 SENSOR_ATTR_2(pwm4_auto_channels_temp, S_IRUGO|S_IWUSR,
854 show_pwm_auto_point_channel,
855 store_pwm_auto_point_channel, 0, 3),
856 SENSOR_ATTR_2(pwm4_auto_point1_pwm, S_IRUGO|S_IWUSR,
857 show_pwm_auto_point_pwm, store_pwm_auto_point_pwm,
858 0, 3),
859 SENSOR_ATTR_2(pwm4_auto_point2_pwm, S_IRUGO|S_IWUSR,
860 show_pwm_auto_point_pwm, store_pwm_auto_point_pwm,
861 1, 3),
862 SENSOR_ATTR_2(pwm4_auto_point3_pwm, S_IRUGO|S_IWUSR,
863 show_pwm_auto_point_pwm, store_pwm_auto_point_pwm,
864 2, 3),
865 SENSOR_ATTR_2(pwm4_auto_point4_pwm, S_IRUGO|S_IWUSR,
866 show_pwm_auto_point_pwm, store_pwm_auto_point_pwm,
867 3, 3),
868 SENSOR_ATTR_2(pwm4_auto_point5_pwm, S_IRUGO|S_IWUSR,
869 show_pwm_auto_point_pwm, store_pwm_auto_point_pwm,
870 4, 3),
871 SENSOR_ATTR_2(pwm4_auto_point1_temp, S_IRUGO|S_IWUSR,
872 show_pwm_auto_point_temp, store_pwm_auto_point_temp,
873 0, 3),
874 SENSOR_ATTR_2(pwm4_auto_point2_temp, S_IRUGO|S_IWUSR,
875 show_pwm_auto_point_temp, store_pwm_auto_point_temp,
876 1, 3),
877 SENSOR_ATTR_2(pwm4_auto_point3_temp, S_IRUGO|S_IWUSR,
878 show_pwm_auto_point_temp, store_pwm_auto_point_temp,
879 2, 3),
880 SENSOR_ATTR_2(pwm4_auto_point4_temp, S_IRUGO|S_IWUSR,
881 show_pwm_auto_point_temp, store_pwm_auto_point_temp,
882 3, 3),
883 SENSOR_ATTR_2(pwm4_auto_point1_temp_hyst, S_IRUGO|S_IWUSR,
884 show_pwm_auto_point_temp_hyst,
885 store_pwm_auto_point_temp_hyst,
886 0, 3),
887 SENSOR_ATTR_2(pwm4_auto_point2_temp_hyst, S_IRUGO,
888 show_pwm_auto_point_temp_hyst, NULL, 1, 3),
889 SENSOR_ATTR_2(pwm4_auto_point3_temp_hyst, S_IRUGO,
890 show_pwm_auto_point_temp_hyst, NULL, 2, 3),
891 SENSOR_ATTR_2(pwm4_auto_point4_temp_hyst, S_IRUGO,
892 show_pwm_auto_point_temp_hyst, NULL, 3, 3),
Hans de Goedeb69b0392009-12-09 20:36:00 +0100893} };
Hans de Goede45fb3662007-07-13 14:34:19 +0200894
Hans de Goede66344aa2009-12-09 20:35:59 +0100895/* Fan attr specific to the f8000 (4th fan input can only measure speed) */
Hans de Goedeed4f7c22009-01-07 16:37:30 +0100896static struct sensor_device_attribute_2 f8000_fan_attr[] = {
897 SENSOR_ATTR_2(fan4_input, S_IRUGO, show_fan, NULL, 0, 3),
Hans de Goede66344aa2009-12-09 20:35:59 +0100898};
Hans de Goedeed4f7c22009-01-07 16:37:30 +0100899
Hans de Goede66344aa2009-12-09 20:35:59 +0100900/* PWM attr for the f8000, zones mapped to temp instead of to pwm!
901 Also the register block at offset A0 maps to TEMP1 (so our temp2, as the
902 F8000 starts counting temps at 0), B0 maps the TEMP2 and C0 maps to TEMP0 */
903static struct sensor_device_attribute_2 f8000_auto_pwm_attr[] = {
904 SENSOR_ATTR_2(pwm1_auto_channels_temp, S_IRUGO|S_IWUSR,
905 show_pwm_auto_point_channel,
906 store_pwm_auto_point_channel, 0, 0),
Hans de Goedeed4f7c22009-01-07 16:37:30 +0100907 SENSOR_ATTR_2(temp1_auto_point1_pwm, S_IRUGO|S_IWUSR,
908 show_pwm_auto_point_pwm, store_pwm_auto_point_pwm,
909 0, 2),
910 SENSOR_ATTR_2(temp1_auto_point2_pwm, S_IRUGO|S_IWUSR,
911 show_pwm_auto_point_pwm, store_pwm_auto_point_pwm,
912 1, 2),
913 SENSOR_ATTR_2(temp1_auto_point3_pwm, S_IRUGO|S_IWUSR,
914 show_pwm_auto_point_pwm, store_pwm_auto_point_pwm,
915 2, 2),
916 SENSOR_ATTR_2(temp1_auto_point4_pwm, S_IRUGO|S_IWUSR,
917 show_pwm_auto_point_pwm, store_pwm_auto_point_pwm,
918 3, 2),
919 SENSOR_ATTR_2(temp1_auto_point5_pwm, S_IRUGO|S_IWUSR,
920 show_pwm_auto_point_pwm, store_pwm_auto_point_pwm,
921 4, 2),
922 SENSOR_ATTR_2(temp1_auto_point1_temp, S_IRUGO|S_IWUSR,
923 show_pwm_auto_point_temp, store_pwm_auto_point_temp,
924 0, 2),
925 SENSOR_ATTR_2(temp1_auto_point2_temp, S_IRUGO|S_IWUSR,
926 show_pwm_auto_point_temp, store_pwm_auto_point_temp,
927 1, 2),
928 SENSOR_ATTR_2(temp1_auto_point3_temp, S_IRUGO|S_IWUSR,
929 show_pwm_auto_point_temp, store_pwm_auto_point_temp,
930 2, 2),
931 SENSOR_ATTR_2(temp1_auto_point4_temp, S_IRUGO|S_IWUSR,
932 show_pwm_auto_point_temp, store_pwm_auto_point_temp,
933 3, 2),
934 SENSOR_ATTR_2(temp1_auto_point1_temp_hyst, S_IRUGO|S_IWUSR,
935 show_pwm_auto_point_temp_hyst,
936 store_pwm_auto_point_temp_hyst,
937 0, 2),
938 SENSOR_ATTR_2(temp1_auto_point2_temp_hyst, S_IRUGO,
939 show_pwm_auto_point_temp_hyst, NULL, 1, 2),
940 SENSOR_ATTR_2(temp1_auto_point3_temp_hyst, S_IRUGO,
941 show_pwm_auto_point_temp_hyst, NULL, 2, 2),
942 SENSOR_ATTR_2(temp1_auto_point4_temp_hyst, S_IRUGO,
943 show_pwm_auto_point_temp_hyst, NULL, 3, 2),
944
Hans de Goede66344aa2009-12-09 20:35:59 +0100945 SENSOR_ATTR_2(pwm2_auto_channels_temp, S_IRUGO|S_IWUSR,
946 show_pwm_auto_point_channel,
947 store_pwm_auto_point_channel, 0, 1),
Hans de Goedeed4f7c22009-01-07 16:37:30 +0100948 SENSOR_ATTR_2(temp2_auto_point1_pwm, S_IRUGO|S_IWUSR,
949 show_pwm_auto_point_pwm, store_pwm_auto_point_pwm,
950 0, 0),
951 SENSOR_ATTR_2(temp2_auto_point2_pwm, S_IRUGO|S_IWUSR,
952 show_pwm_auto_point_pwm, store_pwm_auto_point_pwm,
953 1, 0),
954 SENSOR_ATTR_2(temp2_auto_point3_pwm, S_IRUGO|S_IWUSR,
955 show_pwm_auto_point_pwm, store_pwm_auto_point_pwm,
956 2, 0),
957 SENSOR_ATTR_2(temp2_auto_point4_pwm, S_IRUGO|S_IWUSR,
958 show_pwm_auto_point_pwm, store_pwm_auto_point_pwm,
959 3, 0),
960 SENSOR_ATTR_2(temp2_auto_point5_pwm, S_IRUGO|S_IWUSR,
961 show_pwm_auto_point_pwm, store_pwm_auto_point_pwm,
962 4, 0),
963 SENSOR_ATTR_2(temp2_auto_point1_temp, S_IRUGO|S_IWUSR,
964 show_pwm_auto_point_temp, store_pwm_auto_point_temp,
965 0, 0),
966 SENSOR_ATTR_2(temp2_auto_point2_temp, S_IRUGO|S_IWUSR,
967 show_pwm_auto_point_temp, store_pwm_auto_point_temp,
968 1, 0),
969 SENSOR_ATTR_2(temp2_auto_point3_temp, S_IRUGO|S_IWUSR,
970 show_pwm_auto_point_temp, store_pwm_auto_point_temp,
971 2, 0),
972 SENSOR_ATTR_2(temp2_auto_point4_temp, S_IRUGO|S_IWUSR,
973 show_pwm_auto_point_temp, store_pwm_auto_point_temp,
974 3, 0),
975 SENSOR_ATTR_2(temp2_auto_point1_temp_hyst, S_IRUGO|S_IWUSR,
976 show_pwm_auto_point_temp_hyst,
977 store_pwm_auto_point_temp_hyst,
978 0, 0),
979 SENSOR_ATTR_2(temp2_auto_point2_temp_hyst, S_IRUGO,
980 show_pwm_auto_point_temp_hyst, NULL, 1, 0),
981 SENSOR_ATTR_2(temp2_auto_point3_temp_hyst, S_IRUGO,
982 show_pwm_auto_point_temp_hyst, NULL, 2, 0),
983 SENSOR_ATTR_2(temp2_auto_point4_temp_hyst, S_IRUGO,
984 show_pwm_auto_point_temp_hyst, NULL, 3, 0),
985
Hans de Goede66344aa2009-12-09 20:35:59 +0100986 SENSOR_ATTR_2(pwm3_auto_channels_temp, S_IRUGO|S_IWUSR,
987 show_pwm_auto_point_channel,
988 store_pwm_auto_point_channel, 0, 2),
Hans de Goedeed4f7c22009-01-07 16:37:30 +0100989 SENSOR_ATTR_2(temp3_auto_point1_pwm, S_IRUGO|S_IWUSR,
990 show_pwm_auto_point_pwm, store_pwm_auto_point_pwm,
991 0, 1),
992 SENSOR_ATTR_2(temp3_auto_point2_pwm, S_IRUGO|S_IWUSR,
993 show_pwm_auto_point_pwm, store_pwm_auto_point_pwm,
994 1, 1),
995 SENSOR_ATTR_2(temp3_auto_point3_pwm, S_IRUGO|S_IWUSR,
996 show_pwm_auto_point_pwm, store_pwm_auto_point_pwm,
997 2, 1),
998 SENSOR_ATTR_2(temp3_auto_point4_pwm, S_IRUGO|S_IWUSR,
999 show_pwm_auto_point_pwm, store_pwm_auto_point_pwm,
1000 3, 1),
1001 SENSOR_ATTR_2(temp3_auto_point5_pwm, S_IRUGO|S_IWUSR,
1002 show_pwm_auto_point_pwm, store_pwm_auto_point_pwm,
1003 4, 1),
1004 SENSOR_ATTR_2(temp3_auto_point1_temp, S_IRUGO|S_IWUSR,
1005 show_pwm_auto_point_temp, store_pwm_auto_point_temp,
1006 0, 1),
1007 SENSOR_ATTR_2(temp3_auto_point2_temp, S_IRUGO|S_IWUSR,
1008 show_pwm_auto_point_temp, store_pwm_auto_point_temp,
1009 1, 1),
1010 SENSOR_ATTR_2(temp3_auto_point3_temp, S_IRUGO|S_IWUSR,
1011 show_pwm_auto_point_temp, store_pwm_auto_point_temp,
1012 2, 1),
1013 SENSOR_ATTR_2(temp3_auto_point4_temp, S_IRUGO|S_IWUSR,
1014 show_pwm_auto_point_temp, store_pwm_auto_point_temp,
1015 3, 1),
1016 SENSOR_ATTR_2(temp3_auto_point1_temp_hyst, S_IRUGO|S_IWUSR,
1017 show_pwm_auto_point_temp_hyst,
1018 store_pwm_auto_point_temp_hyst,
1019 0, 1),
1020 SENSOR_ATTR_2(temp3_auto_point2_temp_hyst, S_IRUGO,
1021 show_pwm_auto_point_temp_hyst, NULL, 1, 1),
1022 SENSOR_ATTR_2(temp3_auto_point3_temp_hyst, S_IRUGO,
1023 show_pwm_auto_point_temp_hyst, NULL, 2, 1),
1024 SENSOR_ATTR_2(temp3_auto_point4_temp_hyst, S_IRUGO,
1025 show_pwm_auto_point_temp_hyst, NULL, 3, 1),
1026};
Hans de Goede45fb3662007-07-13 14:34:19 +02001027
1028/* Super I/O functions */
1029static inline int superio_inb(int base, int reg)
1030{
1031 outb(reg, base);
1032 return inb(base + 1);
1033}
1034
1035static int superio_inw(int base, int reg)
1036{
1037 int val;
Giel van Schijndelbd328ac2010-05-27 19:58:42 +02001038 val = superio_inb(base, reg) << 8;
1039 val |= superio_inb(base, reg + 1);
Hans de Goede45fb3662007-07-13 14:34:19 +02001040 return val;
1041}
1042
Giel van Schijndelcadb8652010-10-03 08:09:49 -04001043static inline int superio_enter(int base)
Hans de Goede45fb3662007-07-13 14:34:19 +02001044{
Giel van Schijndelcadb8652010-10-03 08:09:49 -04001045 /* Don't step on other drivers' I/O space by accident */
1046 if (!request_muxed_region(base, 2, DRVNAME)) {
Joe Perches22d3b412010-10-20 06:51:34 +00001047 pr_err("I/O address 0x%04x already in use\n", base);
Giel van Schijndelcadb8652010-10-03 08:09:49 -04001048 return -EBUSY;
1049 }
1050
Hans de Goede45fb3662007-07-13 14:34:19 +02001051 /* according to the datasheet the key must be send twice! */
Giel van Schijndel162bb592010-05-27 19:58:40 +02001052 outb(SIO_UNLOCK_KEY, base);
1053 outb(SIO_UNLOCK_KEY, base);
Giel van Schijndelcadb8652010-10-03 08:09:49 -04001054
1055 return 0;
Hans de Goede45fb3662007-07-13 14:34:19 +02001056}
1057
Giel van Schijndel162bb592010-05-27 19:58:40 +02001058static inline void superio_select(int base, int ld)
Hans de Goede45fb3662007-07-13 14:34:19 +02001059{
1060 outb(SIO_REG_LDSEL, base);
1061 outb(ld, base + 1);
1062}
1063
1064static inline void superio_exit(int base)
1065{
1066 outb(SIO_LOCK_KEY, base);
Giel van Schijndelcadb8652010-10-03 08:09:49 -04001067 release_region(base, 2);
Hans de Goede45fb3662007-07-13 14:34:19 +02001068}
1069
Hans de Goede2f650632009-01-07 16:37:31 +01001070static inline int fan_from_reg(u16 reg)
Hans de Goede45fb3662007-07-13 14:34:19 +02001071{
1072 return reg ? (1500000 / reg) : 0;
1073}
1074
Hans de Goede2f650632009-01-07 16:37:31 +01001075static inline u16 fan_to_reg(int fan)
Mark van Doesburg9ab796e2009-01-07 16:37:27 +01001076{
1077 return fan ? (1500000 / fan) : 0;
1078}
1079
Hans de Goede45fb3662007-07-13 14:34:19 +02001080static u8 f71882fg_read8(struct f71882fg_data *data, u8 reg)
1081{
1082 u8 val;
1083
1084 outb(reg, data->addr + ADDR_REG_OFFSET);
1085 val = inb(data->addr + DATA_REG_OFFSET);
1086
1087 return val;
1088}
1089
1090static u16 f71882fg_read16(struct f71882fg_data *data, u8 reg)
1091{
1092 u16 val;
1093
Giel van Schijndelbd328ac2010-05-27 19:58:42 +02001094 val = f71882fg_read8(data, reg) << 8;
1095 val |= f71882fg_read8(data, reg + 1);
Hans de Goede45fb3662007-07-13 14:34:19 +02001096
1097 return val;
1098}
1099
1100static void f71882fg_write8(struct f71882fg_data *data, u8 reg, u8 val)
1101{
1102 outb(reg, data->addr + ADDR_REG_OFFSET);
1103 outb(val, data->addr + DATA_REG_OFFSET);
1104}
1105
Mark van Doesburg9ab796e2009-01-07 16:37:27 +01001106static void f71882fg_write16(struct f71882fg_data *data, u8 reg, u16 val)
1107{
Giel van Schijndelbd328ac2010-05-27 19:58:42 +02001108 f71882fg_write8(data, reg, val >> 8);
1109 f71882fg_write8(data, reg + 1, val & 0xff);
Mark van Doesburg9ab796e2009-01-07 16:37:27 +01001110}
1111
Hans de Goede09475d32009-06-15 18:39:52 +02001112static u16 f71882fg_read_temp(struct f71882fg_data *data, int nr)
1113{
1114 if (data->type == f71858fg)
1115 return f71882fg_read16(data, F71882FG_REG_TEMP(nr));
1116 else
1117 return f71882fg_read8(data, F71882FG_REG_TEMP(nr));
1118}
1119
Mark van Doesburg77a4a3e2009-01-07 16:37:27 +01001120static struct f71882fg_data *f71882fg_update_device(struct device *dev)
Hans de Goede45fb3662007-07-13 14:34:19 +02001121{
1122 struct f71882fg_data *data = dev_get_drvdata(dev);
Jean Delvaref27def02011-03-26 10:45:01 +01001123 int nr_fans = f71882fg_nr_fans[data->type];
1124 int nr_temps = f71882fg_nr_temps[data->type];
Hans de Goedee5e713c2011-03-10 08:54:02 +01001125 int nr, reg, point;
Hans de Goede45fb3662007-07-13 14:34:19 +02001126
1127 mutex_lock(&data->update_lock);
1128
1129 /* Update once every 60 seconds */
Giel van Schijndel162bb592010-05-27 19:58:40 +02001130 if (time_after(jiffies, data->last_limits + 60 * HZ) ||
Hans de Goede45fb3662007-07-13 14:34:19 +02001131 !data->valid) {
Hans de Goede0bae6402011-03-09 20:57:10 +01001132 if (f71882fg_has_in1_alarm[data->type]) {
Hans de Goede498be962009-01-07 16:37:28 +01001133 data->in1_max =
1134 f71882fg_read8(data, F71882FG_REG_IN1_HIGH);
1135 data->in_beep =
1136 f71882fg_read8(data, F71882FG_REG_IN_BEEP);
1137 }
Hans de Goede45fb3662007-07-13 14:34:19 +02001138
1139 /* Get High & boundary temps*/
Hans de Goedee5e713c2011-03-10 08:54:02 +01001140 for (nr = data->temp_start; nr < nr_temps + data->temp_start;
1141 nr++) {
Hans de Goede45fb3662007-07-13 14:34:19 +02001142 data->temp_ovt[nr] = f71882fg_read8(data,
1143 F71882FG_REG_TEMP_OVT(nr));
1144 data->temp_high[nr] = f71882fg_read8(data,
1145 F71882FG_REG_TEMP_HIGH(nr));
1146 }
1147
Hans de Goedeed4f7c22009-01-07 16:37:30 +01001148 if (data->type != f8000) {
Hans de Goedeed4f7c22009-01-07 16:37:30 +01001149 data->temp_hyst[0] = f71882fg_read8(data,
1150 F71882FG_REG_TEMP_HYST(0));
1151 data->temp_hyst[1] = f71882fg_read8(data,
1152 F71882FG_REG_TEMP_HYST(1));
Hans de Goede09475d32009-06-15 18:39:52 +02001153 }
Hans de Goede78aa4f72011-03-09 20:57:12 +01001154 /* All but the f71858fg / f8000 have this register */
1155 if ((data->type != f71858fg) && (data->type != f8000)) {
Hans de Goedeed4f7c22009-01-07 16:37:30 +01001156 reg = f71882fg_read8(data, F71882FG_REG_TEMP_TYPE);
Hans de Goede44c4dc52011-03-09 20:57:07 +01001157 data->temp_type[1] = (reg & 0x02) ? 2 : 4;
Hans de Goedeed4f7c22009-01-07 16:37:30 +01001158 data->temp_type[2] = (reg & 0x04) ? 2 : 4;
1159 data->temp_type[3] = (reg & 0x08) ? 2 : 4;
1160 }
Hans de Goede45fb3662007-07-13 14:34:19 +02001161
Hans de Goede4d538112011-05-25 20:43:32 +02001162 if (f71882fg_fan_has_beep[data->type])
Hans de Goede78aa4f72011-03-09 20:57:12 +01001163 data->fan_beep = f71882fg_read8(data,
1164 F71882FG_REG_FAN_BEEP);
Hans de Goede4d538112011-05-25 20:43:32 +02001165
1166 if (f71882fg_temp_has_beep[data->type])
Hans de Goede78aa4f72011-03-09 20:57:12 +01001167 data->temp_beep = f71882fg_read8(data,
1168 F71882FG_REG_TEMP_BEEP);
Hans de Goede78aa4f72011-03-09 20:57:12 +01001169
Mark van Doesburg9ab796e2009-01-07 16:37:27 +01001170 data->pwm_enable = f71882fg_read8(data,
1171 F71882FG_REG_PWM_ENABLE);
Hans de Goedebc274902009-01-07 16:37:29 +01001172 data->pwm_auto_point_hyst[0] =
1173 f71882fg_read8(data, F71882FG_REG_FAN_HYST(0));
1174 data->pwm_auto_point_hyst[1] =
1175 f71882fg_read8(data, F71882FG_REG_FAN_HYST(1));
1176
Hans de Goede498be962009-01-07 16:37:28 +01001177 for (nr = 0; nr < nr_fans; nr++) {
Mark van Doesburg9ab796e2009-01-07 16:37:27 +01001178 data->pwm_auto_point_mapping[nr] =
1179 f71882fg_read8(data,
1180 F71882FG_REG_POINT_MAPPING(nr));
1181
Hans de Goedee5e713c2011-03-10 08:54:02 +01001182 switch (data->type) {
1183 default:
Hans de Goede498be962009-01-07 16:37:28 +01001184 for (point = 0; point < 5; point++) {
1185 data->pwm_auto_point_pwm[nr][point] =
1186 f71882fg_read8(data,
1187 F71882FG_REG_POINT_PWM
1188 (nr, point));
1189 }
1190 for (point = 0; point < 4; point++) {
1191 data->pwm_auto_point_temp[nr][point] =
1192 f71882fg_read8(data,
1193 F71882FG_REG_POINT_TEMP
1194 (nr, point));
1195 }
Hans de Goedee5e713c2011-03-10 08:54:02 +01001196 break;
1197 case f71808e:
1198 case f71869:
1199 data->pwm_auto_point_pwm[nr][0] =
1200 f71882fg_read8(data,
1201 F71882FG_REG_POINT_PWM(nr, 0));
1202 /* Fall through */
1203 case f71862fg:
Hans de Goede498be962009-01-07 16:37:28 +01001204 data->pwm_auto_point_pwm[nr][1] =
1205 f71882fg_read8(data,
1206 F71882FG_REG_POINT_PWM
1207 (nr, 1));
1208 data->pwm_auto_point_pwm[nr][4] =
1209 f71882fg_read8(data,
1210 F71882FG_REG_POINT_PWM
1211 (nr, 4));
1212 data->pwm_auto_point_temp[nr][0] =
1213 f71882fg_read8(data,
1214 F71882FG_REG_POINT_TEMP
1215 (nr, 0));
1216 data->pwm_auto_point_temp[nr][3] =
1217 f71882fg_read8(data,
1218 F71882FG_REG_POINT_TEMP
1219 (nr, 3));
Hans de Goedee5e713c2011-03-10 08:54:02 +01001220 break;
Mark van Doesburg9ab796e2009-01-07 16:37:27 +01001221 }
1222 }
Hans de Goede45fb3662007-07-13 14:34:19 +02001223 data->last_limits = jiffies;
1224 }
1225
1226 /* Update every second */
Mark M. Hoffman8afb1042007-08-21 23:10:46 -04001227 if (time_after(jiffies, data->last_updated + HZ) || !data->valid) {
Hans de Goede45fb3662007-07-13 14:34:19 +02001228 data->temp_status = f71882fg_read8(data,
1229 F71882FG_REG_TEMP_STATUS);
1230 data->temp_diode_open = f71882fg_read8(data,
1231 F71882FG_REG_TEMP_DIODE_OPEN);
Hans de Goedee5e713c2011-03-10 08:54:02 +01001232 for (nr = data->temp_start; nr < nr_temps + data->temp_start;
1233 nr++)
Hans de Goede09475d32009-06-15 18:39:52 +02001234 data->temp[nr] = f71882fg_read_temp(data, nr);
Hans de Goede45fb3662007-07-13 14:34:19 +02001235
1236 data->fan_status = f71882fg_read8(data,
1237 F71882FG_REG_FAN_STATUS);
Hans de Goede498be962009-01-07 16:37:28 +01001238 for (nr = 0; nr < nr_fans; nr++) {
Hans de Goede45fb3662007-07-13 14:34:19 +02001239 data->fan[nr] = f71882fg_read16(data,
1240 F71882FG_REG_FAN(nr));
Mark van Doesburg9ab796e2009-01-07 16:37:27 +01001241 data->fan_target[nr] =
1242 f71882fg_read16(data, F71882FG_REG_FAN_TARGET(nr));
1243 data->fan_full_speed[nr] =
1244 f71882fg_read16(data,
1245 F71882FG_REG_FAN_FULL_SPEED(nr));
1246 data->pwm[nr] =
1247 f71882fg_read8(data, F71882FG_REG_PWM(nr));
1248 }
Hans de Goedeed4f7c22009-01-07 16:37:30 +01001249 /* The f8000 can monitor 1 more fan, but has no pwm for it */
1250 if (data->type == f8000)
1251 data->fan[3] = f71882fg_read16(data,
1252 F71882FG_REG_FAN(3));
Hans de Goede0bae6402011-03-09 20:57:10 +01001253
1254 if (f71882fg_has_in1_alarm[data->type])
Hans de Goede498be962009-01-07 16:37:28 +01001255 data->in_status = f71882fg_read8(data,
Hans de Goede45fb3662007-07-13 14:34:19 +02001256 F71882FG_REG_IN_STATUS);
Hans de Goede0bae6402011-03-09 20:57:10 +01001257 for (nr = 0; nr < F71882FG_MAX_INS; nr++)
1258 if (f71882fg_has_in[data->type][nr])
1259 data->in[nr] = f71882fg_read8(data,
1260 F71882FG_REG_IN(nr));
Hans de Goede45fb3662007-07-13 14:34:19 +02001261
1262 data->last_updated = jiffies;
1263 data->valid = 1;
1264 }
1265
1266 mutex_unlock(&data->update_lock);
1267
1268 return data;
1269}
1270
1271/* Sysfs Interface */
1272static ssize_t show_fan(struct device *dev, struct device_attribute *devattr,
1273 char *buf)
1274{
1275 struct f71882fg_data *data = f71882fg_update_device(dev);
Mark van Doesburgbc37ae72009-01-07 16:37:27 +01001276 int nr = to_sensor_dev_attr_2(devattr)->index;
Hans de Goede45fb3662007-07-13 14:34:19 +02001277 int speed = fan_from_reg(data->fan[nr]);
1278
1279 if (speed == FAN_MIN_DETECT)
1280 speed = 0;
1281
1282 return sprintf(buf, "%d\n", speed);
1283}
1284
Mark van Doesburg9ab796e2009-01-07 16:37:27 +01001285static ssize_t show_fan_full_speed(struct device *dev,
1286 struct device_attribute *devattr, char *buf)
1287{
1288 struct f71882fg_data *data = f71882fg_update_device(dev);
1289 int nr = to_sensor_dev_attr_2(devattr)->index;
1290 int speed = fan_from_reg(data->fan_full_speed[nr]);
1291 return sprintf(buf, "%d\n", speed);
1292}
1293
1294static ssize_t store_fan_full_speed(struct device *dev,
1295 struct device_attribute *devattr,
1296 const char *buf, size_t count)
1297{
1298 struct f71882fg_data *data = dev_get_drvdata(dev);
Giel van Schijndele8a4eac2010-05-27 19:58:41 +02001299 int err, nr = to_sensor_dev_attr_2(devattr)->index;
1300 long val;
1301
1302 err = strict_strtol(buf, 10, &val);
1303 if (err)
1304 return err;
Mark van Doesburg9ab796e2009-01-07 16:37:27 +01001305
1306 val = SENSORS_LIMIT(val, 23, 1500000);
1307 val = fan_to_reg(val);
1308
1309 mutex_lock(&data->update_lock);
Hans de Goede4c82c382009-01-07 16:37:30 +01001310 f71882fg_write16(data, F71882FG_REG_FAN_FULL_SPEED(nr), val);
1311 data->fan_full_speed[nr] = val;
Mark van Doesburg9ab796e2009-01-07 16:37:27 +01001312 mutex_unlock(&data->update_lock);
1313
1314 return count;
1315}
1316
Hans de Goede45fb3662007-07-13 14:34:19 +02001317static ssize_t show_fan_beep(struct device *dev, struct device_attribute
1318 *devattr, char *buf)
1319{
1320 struct f71882fg_data *data = f71882fg_update_device(dev);
Mark van Doesburgbc37ae72009-01-07 16:37:27 +01001321 int nr = to_sensor_dev_attr_2(devattr)->index;
Hans de Goede45fb3662007-07-13 14:34:19 +02001322
1323 if (data->fan_beep & (1 << nr))
1324 return sprintf(buf, "1\n");
1325 else
1326 return sprintf(buf, "0\n");
1327}
1328
1329static ssize_t store_fan_beep(struct device *dev, struct device_attribute
1330 *devattr, const char *buf, size_t count)
1331{
1332 struct f71882fg_data *data = dev_get_drvdata(dev);
Giel van Schijndele8a4eac2010-05-27 19:58:41 +02001333 int err, nr = to_sensor_dev_attr_2(devattr)->index;
1334 unsigned long val;
1335
1336 err = strict_strtoul(buf, 10, &val);
1337 if (err)
1338 return err;
Hans de Goede45fb3662007-07-13 14:34:19 +02001339
1340 mutex_lock(&data->update_lock);
Hans de Goedece0bfa52009-01-07 16:37:28 +01001341 data->fan_beep = f71882fg_read8(data, F71882FG_REG_FAN_BEEP);
Hans de Goede45fb3662007-07-13 14:34:19 +02001342 if (val)
1343 data->fan_beep |= 1 << nr;
1344 else
1345 data->fan_beep &= ~(1 << nr);
1346
1347 f71882fg_write8(data, F71882FG_REG_FAN_BEEP, data->fan_beep);
1348 mutex_unlock(&data->update_lock);
1349
1350 return count;
1351}
1352
1353static ssize_t show_fan_alarm(struct device *dev, struct device_attribute
1354 *devattr, char *buf)
1355{
1356 struct f71882fg_data *data = f71882fg_update_device(dev);
Mark van Doesburgbc37ae72009-01-07 16:37:27 +01001357 int nr = to_sensor_dev_attr_2(devattr)->index;
Hans de Goede45fb3662007-07-13 14:34:19 +02001358
1359 if (data->fan_status & (1 << nr))
1360 return sprintf(buf, "1\n");
1361 else
1362 return sprintf(buf, "0\n");
1363}
1364
1365static ssize_t show_in(struct device *dev, struct device_attribute *devattr,
1366 char *buf)
1367{
1368 struct f71882fg_data *data = f71882fg_update_device(dev);
Mark van Doesburgbc37ae72009-01-07 16:37:27 +01001369 int nr = to_sensor_dev_attr_2(devattr)->index;
Hans de Goede45fb3662007-07-13 14:34:19 +02001370
1371 return sprintf(buf, "%d\n", data->in[nr] * 8);
1372}
1373
1374static ssize_t show_in_max(struct device *dev, struct device_attribute
1375 *devattr, char *buf)
1376{
1377 struct f71882fg_data *data = f71882fg_update_device(dev);
1378
1379 return sprintf(buf, "%d\n", data->in1_max * 8);
1380}
1381
1382static ssize_t store_in_max(struct device *dev, struct device_attribute
1383 *devattr, const char *buf, size_t count)
1384{
1385 struct f71882fg_data *data = dev_get_drvdata(dev);
Giel van Schijndele8a4eac2010-05-27 19:58:41 +02001386 int err;
1387 long val;
1388
1389 err = strict_strtol(buf, 10, &val);
1390 if (err)
1391 return err;
1392
1393 val /= 8;
Hans de Goedece0bfa52009-01-07 16:37:28 +01001394 val = SENSORS_LIMIT(val, 0, 255);
Hans de Goede45fb3662007-07-13 14:34:19 +02001395
1396 mutex_lock(&data->update_lock);
1397 f71882fg_write8(data, F71882FG_REG_IN1_HIGH, val);
1398 data->in1_max = val;
1399 mutex_unlock(&data->update_lock);
1400
1401 return count;
1402}
1403
1404static ssize_t show_in_beep(struct device *dev, struct device_attribute
1405 *devattr, char *buf)
1406{
1407 struct f71882fg_data *data = f71882fg_update_device(dev);
Mark van Doesburgbc37ae72009-01-07 16:37:27 +01001408 int nr = to_sensor_dev_attr_2(devattr)->index;
Hans de Goede45fb3662007-07-13 14:34:19 +02001409
1410 if (data->in_beep & (1 << nr))
1411 return sprintf(buf, "1\n");
1412 else
1413 return sprintf(buf, "0\n");
1414}
1415
1416static ssize_t store_in_beep(struct device *dev, struct device_attribute
1417 *devattr, const char *buf, size_t count)
1418{
1419 struct f71882fg_data *data = dev_get_drvdata(dev);
Giel van Schijndele8a4eac2010-05-27 19:58:41 +02001420 int err, nr = to_sensor_dev_attr_2(devattr)->index;
1421 unsigned long val;
1422
1423 err = strict_strtoul(buf, 10, &val);
1424 if (err)
1425 return err;
Hans de Goede45fb3662007-07-13 14:34:19 +02001426
1427 mutex_lock(&data->update_lock);
Hans de Goedece0bfa52009-01-07 16:37:28 +01001428 data->in_beep = f71882fg_read8(data, F71882FG_REG_IN_BEEP);
Hans de Goede45fb3662007-07-13 14:34:19 +02001429 if (val)
1430 data->in_beep |= 1 << nr;
1431 else
1432 data->in_beep &= ~(1 << nr);
1433
1434 f71882fg_write8(data, F71882FG_REG_IN_BEEP, data->in_beep);
1435 mutex_unlock(&data->update_lock);
1436
1437 return count;
1438}
1439
1440static ssize_t show_in_alarm(struct device *dev, struct device_attribute
1441 *devattr, char *buf)
1442{
1443 struct f71882fg_data *data = f71882fg_update_device(dev);
Mark van Doesburgbc37ae72009-01-07 16:37:27 +01001444 int nr = to_sensor_dev_attr_2(devattr)->index;
Hans de Goede45fb3662007-07-13 14:34:19 +02001445
1446 if (data->in_status & (1 << nr))
1447 return sprintf(buf, "1\n");
1448 else
1449 return sprintf(buf, "0\n");
1450}
1451
1452static ssize_t show_temp(struct device *dev, struct device_attribute *devattr,
1453 char *buf)
1454{
1455 struct f71882fg_data *data = f71882fg_update_device(dev);
Mark van Doesburgbc37ae72009-01-07 16:37:27 +01001456 int nr = to_sensor_dev_attr_2(devattr)->index;
Hans de Goede09475d32009-06-15 18:39:52 +02001457 int sign, temp;
Hans de Goede45fb3662007-07-13 14:34:19 +02001458
Hans de Goede09475d32009-06-15 18:39:52 +02001459 if (data->type == f71858fg) {
1460 /* TEMP_TABLE_SEL 1 or 3 ? */
1461 if (data->temp_config & 1) {
1462 sign = data->temp[nr] & 0x0001;
1463 temp = (data->temp[nr] >> 5) & 0x7ff;
1464 } else {
1465 sign = data->temp[nr] & 0x8000;
1466 temp = (data->temp[nr] >> 5) & 0x3ff;
1467 }
1468 temp *= 125;
1469 if (sign)
1470 temp -= 128000;
1471 } else
1472 temp = data->temp[nr] * 1000;
1473
1474 return sprintf(buf, "%d\n", temp);
Hans de Goede45fb3662007-07-13 14:34:19 +02001475}
1476
1477static ssize_t show_temp_max(struct device *dev, struct device_attribute
1478 *devattr, char *buf)
1479{
1480 struct f71882fg_data *data = f71882fg_update_device(dev);
Mark van Doesburgbc37ae72009-01-07 16:37:27 +01001481 int nr = to_sensor_dev_attr_2(devattr)->index;
Hans de Goede45fb3662007-07-13 14:34:19 +02001482
1483 return sprintf(buf, "%d\n", data->temp_high[nr] * 1000);
1484}
1485
1486static ssize_t store_temp_max(struct device *dev, struct device_attribute
1487 *devattr, const char *buf, size_t count)
1488{
1489 struct f71882fg_data *data = dev_get_drvdata(dev);
Giel van Schijndele8a4eac2010-05-27 19:58:41 +02001490 int err, nr = to_sensor_dev_attr_2(devattr)->index;
1491 long val;
1492
1493 err = strict_strtol(buf, 10, &val);
1494 if (err)
1495 return err;
1496
1497 val /= 1000;
Hans de Goedece0bfa52009-01-07 16:37:28 +01001498 val = SENSORS_LIMIT(val, 0, 255);
Hans de Goede45fb3662007-07-13 14:34:19 +02001499
1500 mutex_lock(&data->update_lock);
1501 f71882fg_write8(data, F71882FG_REG_TEMP_HIGH(nr), val);
1502 data->temp_high[nr] = val;
1503 mutex_unlock(&data->update_lock);
1504
1505 return count;
1506}
1507
1508static ssize_t show_temp_max_hyst(struct device *dev, struct device_attribute
1509 *devattr, char *buf)
1510{
1511 struct f71882fg_data *data = f71882fg_update_device(dev);
Mark van Doesburgbc37ae72009-01-07 16:37:27 +01001512 int nr = to_sensor_dev_attr_2(devattr)->index;
Hans de Goedece0bfa52009-01-07 16:37:28 +01001513 int temp_max_hyst;
Hans de Goede45fb3662007-07-13 14:34:19 +02001514
Hans de Goedece0bfa52009-01-07 16:37:28 +01001515 mutex_lock(&data->update_lock);
Hans de Goedebc274902009-01-07 16:37:29 +01001516 if (nr & 1)
1517 temp_max_hyst = data->temp_hyst[nr / 2] >> 4;
1518 else
1519 temp_max_hyst = data->temp_hyst[nr / 2] & 0x0f;
1520 temp_max_hyst = (data->temp_high[nr] - temp_max_hyst) * 1000;
Hans de Goedece0bfa52009-01-07 16:37:28 +01001521 mutex_unlock(&data->update_lock);
1522
1523 return sprintf(buf, "%d\n", temp_max_hyst);
Hans de Goede45fb3662007-07-13 14:34:19 +02001524}
1525
1526static ssize_t store_temp_max_hyst(struct device *dev, struct device_attribute
1527 *devattr, const char *buf, size_t count)
1528{
1529 struct f71882fg_data *data = dev_get_drvdata(dev);
Giel van Schijndele8a4eac2010-05-27 19:58:41 +02001530 int err, nr = to_sensor_dev_attr_2(devattr)->index;
Hans de Goede45fb3662007-07-13 14:34:19 +02001531 ssize_t ret = count;
Hans de Goedece0bfa52009-01-07 16:37:28 +01001532 u8 reg;
Giel van Schijndele8a4eac2010-05-27 19:58:41 +02001533 long val;
1534
1535 err = strict_strtol(buf, 10, &val);
1536 if (err)
1537 return err;
1538
1539 val /= 1000;
Hans de Goede45fb3662007-07-13 14:34:19 +02001540
1541 mutex_lock(&data->update_lock);
1542
1543 /* convert abs to relative and check */
Hans de Goedece0bfa52009-01-07 16:37:28 +01001544 data->temp_high[nr] = f71882fg_read8(data, F71882FG_REG_TEMP_HIGH(nr));
1545 val = SENSORS_LIMIT(val, data->temp_high[nr] - 15,
1546 data->temp_high[nr]);
Hans de Goede45fb3662007-07-13 14:34:19 +02001547 val = data->temp_high[nr] - val;
Hans de Goede45fb3662007-07-13 14:34:19 +02001548
1549 /* convert value to register contents */
Hans de Goedebc274902009-01-07 16:37:29 +01001550 reg = f71882fg_read8(data, F71882FG_REG_TEMP_HYST(nr / 2));
1551 if (nr & 1)
1552 reg = (reg & 0x0f) | (val << 4);
1553 else
1554 reg = (reg & 0xf0) | val;
1555 f71882fg_write8(data, F71882FG_REG_TEMP_HYST(nr / 2), reg);
1556 data->temp_hyst[nr / 2] = reg;
Hans de Goede45fb3662007-07-13 14:34:19 +02001557
Hans de Goede45fb3662007-07-13 14:34:19 +02001558 mutex_unlock(&data->update_lock);
1559 return ret;
1560}
1561
1562static ssize_t show_temp_crit(struct device *dev, struct device_attribute
1563 *devattr, char *buf)
1564{
1565 struct f71882fg_data *data = f71882fg_update_device(dev);
Mark van Doesburgbc37ae72009-01-07 16:37:27 +01001566 int nr = to_sensor_dev_attr_2(devattr)->index;
Hans de Goede45fb3662007-07-13 14:34:19 +02001567
1568 return sprintf(buf, "%d\n", data->temp_ovt[nr] * 1000);
1569}
1570
1571static ssize_t store_temp_crit(struct device *dev, struct device_attribute
1572 *devattr, const char *buf, size_t count)
1573{
1574 struct f71882fg_data *data = dev_get_drvdata(dev);
Giel van Schijndele8a4eac2010-05-27 19:58:41 +02001575 int err, nr = to_sensor_dev_attr_2(devattr)->index;
1576 long val;
1577
1578 err = strict_strtol(buf, 10, &val);
1579 if (err)
1580 return err;
1581
1582 val /= 1000;
Hans de Goedece0bfa52009-01-07 16:37:28 +01001583 val = SENSORS_LIMIT(val, 0, 255);
Hans de Goede45fb3662007-07-13 14:34:19 +02001584
1585 mutex_lock(&data->update_lock);
1586 f71882fg_write8(data, F71882FG_REG_TEMP_OVT(nr), val);
1587 data->temp_ovt[nr] = val;
1588 mutex_unlock(&data->update_lock);
1589
1590 return count;
1591}
1592
1593static ssize_t show_temp_crit_hyst(struct device *dev, struct device_attribute
1594 *devattr, char *buf)
1595{
1596 struct f71882fg_data *data = f71882fg_update_device(dev);
Mark van Doesburgbc37ae72009-01-07 16:37:27 +01001597 int nr = to_sensor_dev_attr_2(devattr)->index;
Hans de Goedece0bfa52009-01-07 16:37:28 +01001598 int temp_crit_hyst;
Hans de Goede45fb3662007-07-13 14:34:19 +02001599
Hans de Goedece0bfa52009-01-07 16:37:28 +01001600 mutex_lock(&data->update_lock);
Hans de Goedebc274902009-01-07 16:37:29 +01001601 if (nr & 1)
1602 temp_crit_hyst = data->temp_hyst[nr / 2] >> 4;
1603 else
1604 temp_crit_hyst = data->temp_hyst[nr / 2] & 0x0f;
1605 temp_crit_hyst = (data->temp_ovt[nr] - temp_crit_hyst) * 1000;
Hans de Goedece0bfa52009-01-07 16:37:28 +01001606 mutex_unlock(&data->update_lock);
1607
1608 return sprintf(buf, "%d\n", temp_crit_hyst);
Hans de Goede45fb3662007-07-13 14:34:19 +02001609}
1610
1611static ssize_t show_temp_type(struct device *dev, struct device_attribute
1612 *devattr, char *buf)
1613{
1614 struct f71882fg_data *data = f71882fg_update_device(dev);
Mark van Doesburgbc37ae72009-01-07 16:37:27 +01001615 int nr = to_sensor_dev_attr_2(devattr)->index;
Hans de Goede45fb3662007-07-13 14:34:19 +02001616
1617 return sprintf(buf, "%d\n", data->temp_type[nr]);
1618}
1619
1620static ssize_t show_temp_beep(struct device *dev, struct device_attribute
1621 *devattr, char *buf)
1622{
1623 struct f71882fg_data *data = f71882fg_update_device(dev);
Mark van Doesburgbc37ae72009-01-07 16:37:27 +01001624 int nr = to_sensor_dev_attr_2(devattr)->index;
Hans de Goede45fb3662007-07-13 14:34:19 +02001625
Hans de Goede7567a042009-01-07 16:37:28 +01001626 if (data->temp_beep & (1 << nr))
Hans de Goede45fb3662007-07-13 14:34:19 +02001627 return sprintf(buf, "1\n");
1628 else
1629 return sprintf(buf, "0\n");
1630}
1631
1632static ssize_t store_temp_beep(struct device *dev, struct device_attribute
1633 *devattr, const char *buf, size_t count)
1634{
1635 struct f71882fg_data *data = dev_get_drvdata(dev);
Giel van Schijndele8a4eac2010-05-27 19:58:41 +02001636 int err, nr = to_sensor_dev_attr_2(devattr)->index;
1637 unsigned long val;
1638
1639 err = strict_strtoul(buf, 10, &val);
1640 if (err)
1641 return err;
Hans de Goede45fb3662007-07-13 14:34:19 +02001642
1643 mutex_lock(&data->update_lock);
Hans de Goedece0bfa52009-01-07 16:37:28 +01001644 data->temp_beep = f71882fg_read8(data, F71882FG_REG_TEMP_BEEP);
Hans de Goede45fb3662007-07-13 14:34:19 +02001645 if (val)
Hans de Goede7567a042009-01-07 16:37:28 +01001646 data->temp_beep |= 1 << nr;
Hans de Goede45fb3662007-07-13 14:34:19 +02001647 else
Hans de Goede7567a042009-01-07 16:37:28 +01001648 data->temp_beep &= ~(1 << nr);
Hans de Goede45fb3662007-07-13 14:34:19 +02001649
1650 f71882fg_write8(data, F71882FG_REG_TEMP_BEEP, data->temp_beep);
1651 mutex_unlock(&data->update_lock);
1652
1653 return count;
1654}
1655
1656static ssize_t show_temp_alarm(struct device *dev, struct device_attribute
1657 *devattr, char *buf)
1658{
1659 struct f71882fg_data *data = f71882fg_update_device(dev);
Mark van Doesburgbc37ae72009-01-07 16:37:27 +01001660 int nr = to_sensor_dev_attr_2(devattr)->index;
Hans de Goede45fb3662007-07-13 14:34:19 +02001661
Hans de Goede7567a042009-01-07 16:37:28 +01001662 if (data->temp_status & (1 << nr))
Hans de Goede45fb3662007-07-13 14:34:19 +02001663 return sprintf(buf, "1\n");
1664 else
1665 return sprintf(buf, "0\n");
1666}
1667
1668static ssize_t show_temp_fault(struct device *dev, struct device_attribute
1669 *devattr, char *buf)
1670{
1671 struct f71882fg_data *data = f71882fg_update_device(dev);
Mark van Doesburgbc37ae72009-01-07 16:37:27 +01001672 int nr = to_sensor_dev_attr_2(devattr)->index;
Hans de Goede45fb3662007-07-13 14:34:19 +02001673
Hans de Goede7567a042009-01-07 16:37:28 +01001674 if (data->temp_diode_open & (1 << nr))
Hans de Goede45fb3662007-07-13 14:34:19 +02001675 return sprintf(buf, "1\n");
1676 else
1677 return sprintf(buf, "0\n");
1678}
1679
Mark van Doesburg9ab796e2009-01-07 16:37:27 +01001680static ssize_t show_pwm(struct device *dev,
1681 struct device_attribute *devattr, char *buf)
1682{
1683 struct f71882fg_data *data = f71882fg_update_device(dev);
1684 int val, nr = to_sensor_dev_attr_2(devattr)->index;
Hans de Goedece0bfa52009-01-07 16:37:28 +01001685 mutex_lock(&data->update_lock);
Mark van Doesburg9ab796e2009-01-07 16:37:27 +01001686 if (data->pwm_enable & (1 << (2 * nr)))
1687 /* PWM mode */
1688 val = data->pwm[nr];
1689 else {
1690 /* RPM mode */
Mark van Doesburg9ab796e2009-01-07 16:37:27 +01001691 val = 255 * fan_from_reg(data->fan_target[nr])
1692 / fan_from_reg(data->fan_full_speed[nr]);
Mark van Doesburg9ab796e2009-01-07 16:37:27 +01001693 }
Hans de Goedece0bfa52009-01-07 16:37:28 +01001694 mutex_unlock(&data->update_lock);
Mark van Doesburg9ab796e2009-01-07 16:37:27 +01001695 return sprintf(buf, "%d\n", val);
1696}
1697
1698static ssize_t store_pwm(struct device *dev,
1699 struct device_attribute *devattr, const char *buf,
1700 size_t count)
1701{
Hans de Goedece0bfa52009-01-07 16:37:28 +01001702 struct f71882fg_data *data = dev_get_drvdata(dev);
Giel van Schijndele8a4eac2010-05-27 19:58:41 +02001703 int err, nr = to_sensor_dev_attr_2(devattr)->index;
1704 long val;
1705
1706 err = strict_strtol(buf, 10, &val);
1707 if (err)
1708 return err;
1709
Mark van Doesburg9ab796e2009-01-07 16:37:27 +01001710 val = SENSORS_LIMIT(val, 0, 255);
1711
1712 mutex_lock(&data->update_lock);
Hans de Goedece0bfa52009-01-07 16:37:28 +01001713 data->pwm_enable = f71882fg_read8(data, F71882FG_REG_PWM_ENABLE);
Hans de Goedeed4f7c22009-01-07 16:37:30 +01001714 if ((data->type == f8000 && ((data->pwm_enable >> 2 * nr) & 3) != 2) ||
1715 (data->type != f8000 && !((data->pwm_enable >> 2 * nr) & 2))) {
1716 count = -EROFS;
1717 goto leave;
1718 }
Mark van Doesburg9ab796e2009-01-07 16:37:27 +01001719 if (data->pwm_enable & (1 << (2 * nr))) {
1720 /* PWM mode */
1721 f71882fg_write8(data, F71882FG_REG_PWM(nr), val);
1722 data->pwm[nr] = val;
1723 } else {
1724 /* RPM mode */
Hans de Goedece0bfa52009-01-07 16:37:28 +01001725 int target, full_speed;
1726 full_speed = f71882fg_read16(data,
1727 F71882FG_REG_FAN_FULL_SPEED(nr));
1728 target = fan_to_reg(val * fan_from_reg(full_speed) / 255);
1729 f71882fg_write16(data, F71882FG_REG_FAN_TARGET(nr), target);
1730 data->fan_target[nr] = target;
1731 data->fan_full_speed[nr] = full_speed;
Mark van Doesburg9ab796e2009-01-07 16:37:27 +01001732 }
Hans de Goedeed4f7c22009-01-07 16:37:30 +01001733leave:
Mark van Doesburg9ab796e2009-01-07 16:37:27 +01001734 mutex_unlock(&data->update_lock);
1735
1736 return count;
1737}
1738
1739static ssize_t show_pwm_enable(struct device *dev,
1740 struct device_attribute *devattr, char *buf)
1741{
Hans de Goedeed4f7c22009-01-07 16:37:30 +01001742 int result = 0;
Mark van Doesburg9ab796e2009-01-07 16:37:27 +01001743 struct f71882fg_data *data = f71882fg_update_device(dev);
1744 int nr = to_sensor_dev_attr_2(devattr)->index;
1745
Hans de Goedeed4f7c22009-01-07 16:37:30 +01001746 switch ((data->pwm_enable >> 2 * nr) & 3) {
1747 case 0:
1748 case 1:
1749 result = 2; /* Normal auto mode */
1750 break;
1751 case 2:
1752 result = 1; /* Manual mode */
1753 break;
1754 case 3:
1755 if (data->type == f8000)
1756 result = 3; /* Thermostat mode */
1757 else
1758 result = 1; /* Manual mode */
1759 break;
1760 }
Mark van Doesburg9ab796e2009-01-07 16:37:27 +01001761
1762 return sprintf(buf, "%d\n", result);
1763}
1764
1765static ssize_t store_pwm_enable(struct device *dev, struct device_attribute
1766 *devattr, const char *buf, size_t count)
1767{
1768 struct f71882fg_data *data = dev_get_drvdata(dev);
Giel van Schijndele8a4eac2010-05-27 19:58:41 +02001769 int err, nr = to_sensor_dev_attr_2(devattr)->index;
1770 long val;
1771
1772 err = strict_strtol(buf, 10, &val);
1773 if (err)
1774 return err;
Mark van Doesburg9ab796e2009-01-07 16:37:27 +01001775
Hans de Goede3fc78382009-06-15 18:39:50 +02001776 /* Special case for F8000 pwm channel 3 which only does auto mode */
1777 if (data->type == f8000 && nr == 2 && val != 2)
1778 return -EINVAL;
1779
Mark van Doesburg9ab796e2009-01-07 16:37:27 +01001780 mutex_lock(&data->update_lock);
Hans de Goedece0bfa52009-01-07 16:37:28 +01001781 data->pwm_enable = f71882fg_read8(data, F71882FG_REG_PWM_ENABLE);
Hans de Goedeed4f7c22009-01-07 16:37:30 +01001782 /* Special case for F8000 auto PWM mode / Thermostat mode */
1783 if (data->type == f8000 && ((data->pwm_enable >> 2 * nr) & 1)) {
1784 switch (val) {
1785 case 2:
1786 data->pwm_enable &= ~(2 << (2 * nr));
1787 break; /* Normal auto mode */
1788 case 3:
1789 data->pwm_enable |= 2 << (2 * nr);
1790 break; /* Thermostat mode */
1791 default:
1792 count = -EINVAL;
1793 goto leave;
1794 }
1795 } else {
1796 switch (val) {
1797 case 1:
Hans de Goede09475d32009-06-15 18:39:52 +02001798 /* The f71858fg does not support manual RPM mode */
1799 if (data->type == f71858fg &&
1800 ((data->pwm_enable >> (2 * nr)) & 1)) {
1801 count = -EINVAL;
1802 goto leave;
1803 }
Hans de Goedeed4f7c22009-01-07 16:37:30 +01001804 data->pwm_enable |= 2 << (2 * nr);
1805 break; /* Manual */
1806 case 2:
1807 data->pwm_enable &= ~(2 << (2 * nr));
1808 break; /* Normal auto mode */
1809 default:
1810 count = -EINVAL;
1811 goto leave;
1812 }
Mark van Doesburg9ab796e2009-01-07 16:37:27 +01001813 }
Mark van Doesburg9ab796e2009-01-07 16:37:27 +01001814 f71882fg_write8(data, F71882FG_REG_PWM_ENABLE, data->pwm_enable);
Hans de Goedeed4f7c22009-01-07 16:37:30 +01001815leave:
Mark van Doesburg9ab796e2009-01-07 16:37:27 +01001816 mutex_unlock(&data->update_lock);
1817
1818 return count;
1819}
1820
1821static ssize_t show_pwm_auto_point_pwm(struct device *dev,
1822 struct device_attribute *devattr,
1823 char *buf)
1824{
1825 int result;
1826 struct f71882fg_data *data = f71882fg_update_device(dev);
1827 int pwm = to_sensor_dev_attr_2(devattr)->index;
1828 int point = to_sensor_dev_attr_2(devattr)->nr;
1829
Hans de Goedece0bfa52009-01-07 16:37:28 +01001830 mutex_lock(&data->update_lock);
Mark van Doesburg9ab796e2009-01-07 16:37:27 +01001831 if (data->pwm_enable & (1 << (2 * pwm))) {
1832 /* PWM mode */
1833 result = data->pwm_auto_point_pwm[pwm][point];
1834 } else {
1835 /* RPM mode */
1836 result = 32 * 255 / (32 + data->pwm_auto_point_pwm[pwm][point]);
1837 }
Hans de Goedece0bfa52009-01-07 16:37:28 +01001838 mutex_unlock(&data->update_lock);
Mark van Doesburg9ab796e2009-01-07 16:37:27 +01001839
1840 return sprintf(buf, "%d\n", result);
1841}
1842
1843static ssize_t store_pwm_auto_point_pwm(struct device *dev,
1844 struct device_attribute *devattr,
1845 const char *buf, size_t count)
1846{
Hans de Goedece0bfa52009-01-07 16:37:28 +01001847 struct f71882fg_data *data = dev_get_drvdata(dev);
Giel van Schijndele8a4eac2010-05-27 19:58:41 +02001848 int err, pwm = to_sensor_dev_attr_2(devattr)->index;
Mark van Doesburg9ab796e2009-01-07 16:37:27 +01001849 int point = to_sensor_dev_attr_2(devattr)->nr;
Giel van Schijndele8a4eac2010-05-27 19:58:41 +02001850 long val;
1851
1852 err = strict_strtol(buf, 10, &val);
1853 if (err)
1854 return err;
1855
Mark van Doesburg9ab796e2009-01-07 16:37:27 +01001856 val = SENSORS_LIMIT(val, 0, 255);
1857
1858 mutex_lock(&data->update_lock);
Hans de Goedece0bfa52009-01-07 16:37:28 +01001859 data->pwm_enable = f71882fg_read8(data, F71882FG_REG_PWM_ENABLE);
Mark van Doesburg9ab796e2009-01-07 16:37:27 +01001860 if (data->pwm_enable & (1 << (2 * pwm))) {
1861 /* PWM mode */
1862 } else {
1863 /* RPM mode */
1864 if (val < 29) /* Prevent negative numbers */
1865 val = 255;
1866 else
1867 val = (255 - val) * 32 / val;
1868 }
1869 f71882fg_write8(data, F71882FG_REG_POINT_PWM(pwm, point), val);
1870 data->pwm_auto_point_pwm[pwm][point] = val;
1871 mutex_unlock(&data->update_lock);
1872
1873 return count;
1874}
1875
1876static ssize_t show_pwm_auto_point_temp_hyst(struct device *dev,
1877 struct device_attribute *devattr,
1878 char *buf)
1879{
1880 int result = 0;
1881 struct f71882fg_data *data = f71882fg_update_device(dev);
1882 int nr = to_sensor_dev_attr_2(devattr)->index;
1883 int point = to_sensor_dev_attr_2(devattr)->nr;
1884
1885 mutex_lock(&data->update_lock);
Hans de Goedebc274902009-01-07 16:37:29 +01001886 if (nr & 1)
1887 result = data->pwm_auto_point_hyst[nr / 2] >> 4;
1888 else
1889 result = data->pwm_auto_point_hyst[nr / 2] & 0x0f;
Mark van Doesburg9ab796e2009-01-07 16:37:27 +01001890 result = 1000 * (data->pwm_auto_point_temp[nr][point] - result);
1891 mutex_unlock(&data->update_lock);
1892
1893 return sprintf(buf, "%d\n", result);
1894}
1895
1896static ssize_t store_pwm_auto_point_temp_hyst(struct device *dev,
1897 struct device_attribute *devattr,
1898 const char *buf, size_t count)
1899{
Hans de Goedece0bfa52009-01-07 16:37:28 +01001900 struct f71882fg_data *data = dev_get_drvdata(dev);
Giel van Schijndele8a4eac2010-05-27 19:58:41 +02001901 int err, nr = to_sensor_dev_attr_2(devattr)->index;
Mark van Doesburg9ab796e2009-01-07 16:37:27 +01001902 int point = to_sensor_dev_attr_2(devattr)->nr;
Hans de Goedebc274902009-01-07 16:37:29 +01001903 u8 reg;
Giel van Schijndele8a4eac2010-05-27 19:58:41 +02001904 long val;
1905
1906 err = strict_strtol(buf, 10, &val);
1907 if (err)
1908 return err;
1909
1910 val /= 1000;
Mark van Doesburg9ab796e2009-01-07 16:37:27 +01001911
1912 mutex_lock(&data->update_lock);
Hans de Goedece0bfa52009-01-07 16:37:28 +01001913 data->pwm_auto_point_temp[nr][point] =
1914 f71882fg_read8(data, F71882FG_REG_POINT_TEMP(nr, point));
Mark van Doesburg9ab796e2009-01-07 16:37:27 +01001915 val = SENSORS_LIMIT(val, data->pwm_auto_point_temp[nr][point] - 15,
1916 data->pwm_auto_point_temp[nr][point]);
1917 val = data->pwm_auto_point_temp[nr][point] - val;
1918
Hans de Goedebc274902009-01-07 16:37:29 +01001919 reg = f71882fg_read8(data, F71882FG_REG_FAN_HYST(nr / 2));
1920 if (nr & 1)
1921 reg = (reg & 0x0f) | (val << 4);
1922 else
1923 reg = (reg & 0xf0) | val;
1924
1925 f71882fg_write8(data, F71882FG_REG_FAN_HYST(nr / 2), reg);
1926 data->pwm_auto_point_hyst[nr / 2] = reg;
Mark van Doesburg9ab796e2009-01-07 16:37:27 +01001927 mutex_unlock(&data->update_lock);
1928
1929 return count;
1930}
1931
1932static ssize_t show_pwm_interpolate(struct device *dev,
1933 struct device_attribute *devattr, char *buf)
1934{
1935 int result;
1936 struct f71882fg_data *data = f71882fg_update_device(dev);
1937 int nr = to_sensor_dev_attr_2(devattr)->index;
1938
1939 result = (data->pwm_auto_point_mapping[nr] >> 4) & 1;
1940
1941 return sprintf(buf, "%d\n", result);
1942}
1943
1944static ssize_t store_pwm_interpolate(struct device *dev,
1945 struct device_attribute *devattr,
1946 const char *buf, size_t count)
1947{
Hans de Goedece0bfa52009-01-07 16:37:28 +01001948 struct f71882fg_data *data = dev_get_drvdata(dev);
Giel van Schijndele8a4eac2010-05-27 19:58:41 +02001949 int err, nr = to_sensor_dev_attr_2(devattr)->index;
1950 unsigned long val;
1951
1952 err = strict_strtoul(buf, 10, &val);
1953 if (err)
1954 return err;
Hans de Goedece0bfa52009-01-07 16:37:28 +01001955
Mark van Doesburg9ab796e2009-01-07 16:37:27 +01001956 mutex_lock(&data->update_lock);
Hans de Goedece0bfa52009-01-07 16:37:28 +01001957 data->pwm_auto_point_mapping[nr] =
1958 f71882fg_read8(data, F71882FG_REG_POINT_MAPPING(nr));
Mark van Doesburg9ab796e2009-01-07 16:37:27 +01001959 if (val)
1960 val = data->pwm_auto_point_mapping[nr] | (1 << 4);
1961 else
1962 val = data->pwm_auto_point_mapping[nr] & (~(1 << 4));
1963 f71882fg_write8(data, F71882FG_REG_POINT_MAPPING(nr), val);
1964 data->pwm_auto_point_mapping[nr] = val;
1965 mutex_unlock(&data->update_lock);
1966
1967 return count;
1968}
1969
1970static ssize_t show_pwm_auto_point_channel(struct device *dev,
1971 struct device_attribute *devattr,
1972 char *buf)
1973{
1974 int result;
1975 struct f71882fg_data *data = f71882fg_update_device(dev);
1976 int nr = to_sensor_dev_attr_2(devattr)->index;
1977
Hans de Goede09475d32009-06-15 18:39:52 +02001978 result = 1 << ((data->pwm_auto_point_mapping[nr] & 3) -
1979 data->temp_start);
Mark van Doesburg9ab796e2009-01-07 16:37:27 +01001980
1981 return sprintf(buf, "%d\n", result);
1982}
1983
1984static ssize_t store_pwm_auto_point_channel(struct device *dev,
1985 struct device_attribute *devattr,
1986 const char *buf, size_t count)
1987{
Hans de Goedece0bfa52009-01-07 16:37:28 +01001988 struct f71882fg_data *data = dev_get_drvdata(dev);
Giel van Schijndele8a4eac2010-05-27 19:58:41 +02001989 int err, nr = to_sensor_dev_attr_2(devattr)->index;
1990 long val;
1991
1992 err = strict_strtol(buf, 10, &val);
1993 if (err)
1994 return err;
Hans de Goede30453012009-01-07 16:37:30 +01001995
Mark van Doesburg9ab796e2009-01-07 16:37:27 +01001996 switch (val) {
1997 case 1:
Hans de Goede30453012009-01-07 16:37:30 +01001998 val = 0;
Mark van Doesburg9ab796e2009-01-07 16:37:27 +01001999 break;
2000 case 2:
Hans de Goede30453012009-01-07 16:37:30 +01002001 val = 1;
Mark van Doesburg9ab796e2009-01-07 16:37:27 +01002002 break;
2003 case 4:
Hans de Goede30453012009-01-07 16:37:30 +01002004 val = 2;
Mark van Doesburg9ab796e2009-01-07 16:37:27 +01002005 break;
2006 default:
2007 return -EINVAL;
2008 }
Hans de Goede09475d32009-06-15 18:39:52 +02002009 val += data->temp_start;
Mark van Doesburg9ab796e2009-01-07 16:37:27 +01002010 mutex_lock(&data->update_lock);
Hans de Goedece0bfa52009-01-07 16:37:28 +01002011 data->pwm_auto_point_mapping[nr] =
2012 f71882fg_read8(data, F71882FG_REG_POINT_MAPPING(nr));
Mark van Doesburg9ab796e2009-01-07 16:37:27 +01002013 val = (data->pwm_auto_point_mapping[nr] & 0xfc) | val;
2014 f71882fg_write8(data, F71882FG_REG_POINT_MAPPING(nr), val);
2015 data->pwm_auto_point_mapping[nr] = val;
2016 mutex_unlock(&data->update_lock);
2017
2018 return count;
2019}
2020
2021static ssize_t show_pwm_auto_point_temp(struct device *dev,
2022 struct device_attribute *devattr,
2023 char *buf)
2024{
2025 int result;
2026 struct f71882fg_data *data = f71882fg_update_device(dev);
2027 int pwm = to_sensor_dev_attr_2(devattr)->index;
2028 int point = to_sensor_dev_attr_2(devattr)->nr;
2029
2030 result = data->pwm_auto_point_temp[pwm][point];
2031 return sprintf(buf, "%d\n", 1000 * result);
2032}
2033
2034static ssize_t store_pwm_auto_point_temp(struct device *dev,
2035 struct device_attribute *devattr,
2036 const char *buf, size_t count)
2037{
Hans de Goedece0bfa52009-01-07 16:37:28 +01002038 struct f71882fg_data *data = dev_get_drvdata(dev);
Giel van Schijndele8a4eac2010-05-27 19:58:41 +02002039 int err, pwm = to_sensor_dev_attr_2(devattr)->index;
Mark van Doesburg9ab796e2009-01-07 16:37:27 +01002040 int point = to_sensor_dev_attr_2(devattr)->nr;
Giel van Schijndele8a4eac2010-05-27 19:58:41 +02002041 long val;
2042
2043 err = strict_strtol(buf, 10, &val);
2044 if (err)
2045 return err;
2046
2047 val /= 1000;
Hans de Goede76698962009-12-09 20:36:01 +01002048
Hans de Goede98f7ba12011-03-09 20:57:09 +01002049 if (data->auto_point_temp_signed)
Hans de Goede76698962009-12-09 20:36:01 +01002050 val = SENSORS_LIMIT(val, -128, 127);
2051 else
2052 val = SENSORS_LIMIT(val, 0, 127);
Mark van Doesburg9ab796e2009-01-07 16:37:27 +01002053
2054 mutex_lock(&data->update_lock);
2055 f71882fg_write8(data, F71882FG_REG_POINT_TEMP(pwm, point), val);
2056 data->pwm_auto_point_temp[pwm][point] = val;
2057 mutex_unlock(&data->update_lock);
2058
2059 return count;
2060}
2061
Hans de Goede45fb3662007-07-13 14:34:19 +02002062static ssize_t show_name(struct device *dev, struct device_attribute *devattr,
2063 char *buf)
2064{
Hans de Goede498be962009-01-07 16:37:28 +01002065 struct f71882fg_data *data = dev_get_drvdata(dev);
2066 return sprintf(buf, "%s\n", f71882fg_names[data->type]);
Hans de Goede45fb3662007-07-13 14:34:19 +02002067}
2068
Hans de Goedec13548c2009-01-07 16:37:27 +01002069static int __devinit f71882fg_create_sysfs_files(struct platform_device *pdev,
2070 struct sensor_device_attribute_2 *attr, int count)
2071{
2072 int err, i;
Hans de Goede45fb3662007-07-13 14:34:19 +02002073
Hans de Goedec13548c2009-01-07 16:37:27 +01002074 for (i = 0; i < count; i++) {
2075 err = device_create_file(&pdev->dev, &attr[i].dev_attr);
2076 if (err)
2077 return err;
2078 }
2079 return 0;
2080}
2081
Hans de Goedefc16c562009-12-09 20:36:01 +01002082static void f71882fg_remove_sysfs_files(struct platform_device *pdev,
2083 struct sensor_device_attribute_2 *attr, int count)
2084{
2085 int i;
2086
2087 for (i = 0; i < count; i++)
2088 device_remove_file(&pdev->dev, &attr[i].dev_attr);
2089}
2090
Hans de Goedec13548c2009-01-07 16:37:27 +01002091static int __devinit f71882fg_probe(struct platform_device *pdev)
Hans de Goede45fb3662007-07-13 14:34:19 +02002092{
2093 struct f71882fg_data *data;
Hans de Goede498be962009-01-07 16:37:28 +01002094 struct f71882fg_sio_data *sio_data = pdev->dev.platform_data;
Jean Delvaref27def02011-03-26 10:45:01 +01002095 int nr_fans = f71882fg_nr_fans[sio_data->type];
2096 int nr_temps = f71882fg_nr_temps[sio_data->type];
2097 int err, i;
Hans de Goede98f7ba12011-03-09 20:57:09 +01002098 u8 start_reg, reg;
Hans de Goede45fb3662007-07-13 14:34:19 +02002099
Hans de Goedec13548c2009-01-07 16:37:27 +01002100 data = kzalloc(sizeof(struct f71882fg_data), GFP_KERNEL);
2101 if (!data)
Hans de Goede45fb3662007-07-13 14:34:19 +02002102 return -ENOMEM;
2103
2104 data->addr = platform_get_resource(pdev, IORESOURCE_IO, 0)->start;
Hans de Goede498be962009-01-07 16:37:28 +01002105 data->type = sio_data->type;
Hans de Goede09475d32009-06-15 18:39:52 +02002106 data->temp_start =
2107 (data->type == f71858fg || data->type == f8000) ? 0 : 1;
Hans de Goede45fb3662007-07-13 14:34:19 +02002108 mutex_init(&data->update_lock);
2109 platform_set_drvdata(pdev, data);
2110
Hans de Goede3cc74752009-01-07 16:37:28 +01002111 start_reg = f71882fg_read8(data, F71882FG_REG_START);
Hans de Goede12d66e82009-01-07 16:37:29 +01002112 if (start_reg & 0x04) {
2113 dev_warn(&pdev->dev, "Hardware monitor is powered down\n");
2114 err = -ENODEV;
2115 goto exit_free;
2116 }
Hans de Goede3cc74752009-01-07 16:37:28 +01002117 if (!(start_reg & 0x03)) {
2118 dev_warn(&pdev->dev, "Hardware monitoring not activated\n");
2119 err = -ENODEV;
2120 goto exit_free;
2121 }
2122
Hans de Goede45fb3662007-07-13 14:34:19 +02002123 /* Register sysfs interface files */
Hans de Goedec13548c2009-01-07 16:37:27 +01002124 err = device_create_file(&pdev->dev, &dev_attr_name);
2125 if (err)
2126 goto exit_unregister_sysfs;
2127
Hans de Goedec13548c2009-01-07 16:37:27 +01002128 if (start_reg & 0x01) {
Hans de Goedeed4f7c22009-01-07 16:37:30 +01002129 switch (data->type) {
Hans de Goede09475d32009-06-15 18:39:52 +02002130 case f71858fg:
2131 data->temp_config =
2132 f71882fg_read8(data, F71882FG_REG_TEMP_CONFIG);
2133 if (data->temp_config & 0x10)
2134 /* The f71858fg temperature alarms behave as
2135 the f8000 alarms in this mode */
2136 err = f71882fg_create_sysfs_files(pdev,
Hans de Goede0bae6402011-03-09 20:57:10 +01002137 f8000_temp_attr,
2138 ARRAY_SIZE(f8000_temp_attr));
Hans de Goede09475d32009-06-15 18:39:52 +02002139 else
2140 err = f71882fg_create_sysfs_files(pdev,
Hans de Goede0bae6402011-03-09 20:57:10 +01002141 f71858fg_temp_attr,
2142 ARRAY_SIZE(f71858fg_temp_attr));
Hans de Goede09475d32009-06-15 18:39:52 +02002143 break;
Hans de Goede0bae6402011-03-09 20:57:10 +01002144 case f8000:
2145 err = f71882fg_create_sysfs_files(pdev,
2146 f8000_temp_attr,
2147 ARRAY_SIZE(f8000_temp_attr));
2148 break;
2149 default:
2150 err = f71882fg_create_sysfs_files(pdev,
Hans de Goede60d2b372011-03-09 20:57:11 +01002151 &fxxxx_temp_attr[0][0],
2152 ARRAY_SIZE(fxxxx_temp_attr[0]) * nr_temps);
Hans de Goede0bae6402011-03-09 20:57:10 +01002153 }
2154 if (err)
2155 goto exit_unregister_sysfs;
2156
Hans de Goede4d538112011-05-25 20:43:32 +02002157 if (f71882fg_temp_has_beep[data->type]) {
Hans de Goede78aa4f72011-03-09 20:57:12 +01002158 err = f71882fg_create_sysfs_files(pdev,
2159 &fxxxx_temp_beep_attr[0][0],
2160 ARRAY_SIZE(fxxxx_temp_beep_attr[0])
2161 * nr_temps);
2162 if (err)
2163 goto exit_unregister_sysfs;
2164 }
2165
Hans de Goede0bae6402011-03-09 20:57:10 +01002166 for (i = 0; i < F71882FG_MAX_INS; i++) {
2167 if (f71882fg_has_in[data->type][i]) {
2168 err = device_create_file(&pdev->dev,
2169 &fxxxx_in_attr[i].dev_attr);
2170 if (err)
2171 goto exit_unregister_sysfs;
2172 }
2173 }
2174 if (f71882fg_has_in1_alarm[data->type]) {
Hans de Goede498be962009-01-07 16:37:28 +01002175 err = f71882fg_create_sysfs_files(pdev,
Hans de Goede66344aa2009-12-09 20:35:59 +01002176 fxxxx_in1_alarm_attr,
2177 ARRAY_SIZE(fxxxx_in1_alarm_attr));
Hans de Goede498be962009-01-07 16:37:28 +01002178 if (err)
2179 goto exit_unregister_sysfs;
2180 }
Hans de Goede45fb3662007-07-13 14:34:19 +02002181 }
2182
Hans de Goede45fb3662007-07-13 14:34:19 +02002183 if (start_reg & 0x02) {
Hans de Goede98f7ba12011-03-09 20:57:09 +01002184 switch (data->type) {
Hans de Goedee5e713c2011-03-10 08:54:02 +01002185 case f71808e:
Hans de Goedec11bb992011-03-09 20:57:15 +01002186 case f71869:
Hans de Goedee5e713c2011-03-10 08:54:02 +01002187 /* These always have signed auto point temps */
Hans de Goedec11bb992011-03-09 20:57:15 +01002188 data->auto_point_temp_signed = 1;
2189 /* Fall through to select correct fan/pwm reg bank! */
Hans de Goede98f7ba12011-03-09 20:57:09 +01002190 case f71889fg:
Hans de Goede3cad4022011-03-09 20:57:14 +01002191 case f71889ed:
Hans de Goedea66c1082011-03-26 10:45:02 +01002192 case f71889a:
Hans de Goede98f7ba12011-03-09 20:57:09 +01002193 reg = f71882fg_read8(data, F71882FG_REG_FAN_FAULT_T);
2194 if (reg & F71882FG_FAN_NEG_TEMP_EN)
2195 data->auto_point_temp_signed = 1;
Hans de Goede3cad4022011-03-09 20:57:14 +01002196 /* Ensure banked pwm registers point to right bank */
2197 reg &= ~F71882FG_FAN_PROG_SEL;
2198 f71882fg_write8(data, F71882FG_REG_FAN_FAULT_T, reg);
Hans de Goede98f7ba12011-03-09 20:57:09 +01002199 break;
2200 default:
2201 break;
2202 }
2203
Hans de Goede996cadb2009-06-15 18:39:51 +02002204 data->pwm_enable =
2205 f71882fg_read8(data, F71882FG_REG_PWM_ENABLE);
2206
2207 /* Sanity check the pwm settings */
2208 switch (data->type) {
Hans de Goede09475d32009-06-15 18:39:52 +02002209 case f71858fg:
2210 err = 0;
2211 for (i = 0; i < nr_fans; i++)
2212 if (((data->pwm_enable >> (i * 2)) & 3) == 3)
2213 err = 1;
2214 break;
Hans de Goede996cadb2009-06-15 18:39:51 +02002215 case f71862fg:
2216 err = (data->pwm_enable & 0x15) != 0x15;
2217 break;
Hans de Goede996cadb2009-06-15 18:39:51 +02002218 case f8000:
2219 err = data->pwm_enable & 0x20;
2220 break;
Jean Delvare383586b2011-03-26 10:45:02 +01002221 default:
2222 err = 0;
2223 break;
Hans de Goede996cadb2009-06-15 18:39:51 +02002224 }
2225 if (err) {
2226 dev_err(&pdev->dev,
2227 "Invalid (reserved) pwm settings: 0x%02x\n",
2228 (unsigned int)data->pwm_enable);
2229 err = -ENODEV;
2230 goto exit_unregister_sysfs;
2231 }
2232
Hans de Goedeb69b0392009-12-09 20:36:00 +01002233 err = f71882fg_create_sysfs_files(pdev, &fxxxx_fan_attr[0][0],
2234 ARRAY_SIZE(fxxxx_fan_attr[0]) * nr_fans);
Hans de Goede498be962009-01-07 16:37:28 +01002235 if (err)
2236 goto exit_unregister_sysfs;
2237
Hans de Goede4d538112011-05-25 20:43:32 +02002238 if (f71882fg_fan_has_beep[data->type]) {
Hans de Goedeb69b0392009-12-09 20:36:00 +01002239 err = f71882fg_create_sysfs_files(pdev,
2240 fxxxx_fan_beep_attr, nr_fans);
2241 if (err)
2242 goto exit_unregister_sysfs;
2243 }
2244
Hans de Goedeed4f7c22009-01-07 16:37:30 +01002245 switch (data->type) {
Hans de Goedee5e713c2011-03-10 08:54:02 +01002246 case f71808e:
Hans de Goedec11bb992011-03-09 20:57:15 +01002247 case f71869:
Hans de Goedee48a7f12011-03-09 20:57:13 +01002248 case f71889fg:
Hans de Goede3cad4022011-03-09 20:57:14 +01002249 case f71889ed:
Hans de Goedea66c1082011-03-26 10:45:02 +01002250 case f71889a:
Hans de Goedee48a7f12011-03-09 20:57:13 +01002251 for (i = 0; i < nr_fans; i++) {
2252 data->pwm_auto_point_mapping[i] =
2253 f71882fg_read8(data,
2254 F71882FG_REG_POINT_MAPPING(i));
Hans de Goede3cad4022011-03-09 20:57:14 +01002255 if ((data->pwm_auto_point_mapping[i] & 0x80) ||
2256 (data->pwm_auto_point_mapping[i] & 3) == 0)
Hans de Goedee48a7f12011-03-09 20:57:13 +01002257 break;
2258 }
2259 if (i != nr_fans) {
2260 dev_warn(&pdev->dev,
2261 "Auto pwm controlled by raw digital "
2262 "data, disabling pwm auto_point "
2263 "sysfs attributes\n");
2264 goto no_pwm_auto_point;
2265 }
2266 break;
2267 default:
2268 break;
2269 }
2270
2271 switch (data->type) {
Hans de Goedeed4f7c22009-01-07 16:37:30 +01002272 case f71862fg:
Hans de Goede498be962009-01-07 16:37:28 +01002273 err = f71882fg_create_sysfs_files(pdev,
Hans de Goede66344aa2009-12-09 20:35:59 +01002274 f71862fg_auto_pwm_attr,
2275 ARRAY_SIZE(f71862fg_auto_pwm_attr));
Hans de Goedeed4f7c22009-01-07 16:37:30 +01002276 break;
Hans de Goedee5e713c2011-03-10 08:54:02 +01002277 case f71808e:
Hans de Goedec11bb992011-03-09 20:57:15 +01002278 case f71869:
2279 err = f71882fg_create_sysfs_files(pdev,
2280 f71869_auto_pwm_attr,
2281 ARRAY_SIZE(f71869_auto_pwm_attr));
2282 break;
Hans de Goedeed4f7c22009-01-07 16:37:30 +01002283 case f8000:
2284 err = f71882fg_create_sysfs_files(pdev,
2285 f8000_fan_attr,
2286 ARRAY_SIZE(f8000_fan_attr));
Hans de Goede66344aa2009-12-09 20:35:59 +01002287 if (err)
2288 goto exit_unregister_sysfs;
2289 err = f71882fg_create_sysfs_files(pdev,
2290 f8000_auto_pwm_attr,
2291 ARRAY_SIZE(f8000_auto_pwm_attr));
Hans de Goedeed4f7c22009-01-07 16:37:30 +01002292 break;
Hans de Goedee48a7f12011-03-09 20:57:13 +01002293 default:
Hans de Goedeb69b0392009-12-09 20:36:00 +01002294 err = f71882fg_create_sysfs_files(pdev,
2295 &fxxxx_auto_pwm_attr[0][0],
2296 ARRAY_SIZE(fxxxx_auto_pwm_attr[0]) * nr_fans);
Hans de Goede498be962009-01-07 16:37:28 +01002297 }
Hans de Goedec13548c2009-01-07 16:37:27 +01002298 if (err)
2299 goto exit_unregister_sysfs;
Hans de Goede28ba8582009-01-07 16:37:31 +01002300
Hans de Goedee48a7f12011-03-09 20:57:13 +01002301no_pwm_auto_point:
Hans de Goede28ba8582009-01-07 16:37:31 +01002302 for (i = 0; i < nr_fans; i++)
2303 dev_info(&pdev->dev, "Fan: %d is in %s mode\n", i + 1,
2304 (data->pwm_enable & (1 << 2 * i)) ?
2305 "duty-cycle" : "RPM");
Hans de Goede45fb3662007-07-13 14:34:19 +02002306 }
2307
Tony Jones1beeffe2007-08-20 13:46:20 -07002308 data->hwmon_dev = hwmon_device_register(&pdev->dev);
2309 if (IS_ERR(data->hwmon_dev)) {
2310 err = PTR_ERR(data->hwmon_dev);
Hans de Goedec13548c2009-01-07 16:37:27 +01002311 data->hwmon_dev = NULL;
Hans de Goede45fb3662007-07-13 14:34:19 +02002312 goto exit_unregister_sysfs;
2313 }
2314
2315 return 0;
2316
2317exit_unregister_sysfs:
Hans de Goedec13548c2009-01-07 16:37:27 +01002318 f71882fg_remove(pdev); /* Will unregister the sysfs files for us */
Hans de Goede3cc74752009-01-07 16:37:28 +01002319 return err; /* f71882fg_remove() also frees our data */
2320exit_free:
2321 kfree(data);
Hans de Goede45fb3662007-07-13 14:34:19 +02002322 return err;
2323}
2324
Hans de Goedec13548c2009-01-07 16:37:27 +01002325static int f71882fg_remove(struct platform_device *pdev)
Hans de Goede45fb3662007-07-13 14:34:19 +02002326{
Hans de Goede45fb3662007-07-13 14:34:19 +02002327 struct f71882fg_data *data = platform_get_drvdata(pdev);
Jean Delvaref27def02011-03-26 10:45:01 +01002328 int nr_fans = f71882fg_nr_fans[data->type];
2329 int nr_temps = f71882fg_nr_temps[data->type];
2330 int i;
Hans de Goedefc16c562009-12-09 20:36:01 +01002331 u8 start_reg = f71882fg_read8(data, F71882FG_REG_START);
Hans de Goede45fb3662007-07-13 14:34:19 +02002332
Hans de Goedec13548c2009-01-07 16:37:27 +01002333 if (data->hwmon_dev)
2334 hwmon_device_unregister(data->hwmon_dev);
Hans de Goede45fb3662007-07-13 14:34:19 +02002335
Hans de Goedec13548c2009-01-07 16:37:27 +01002336 device_remove_file(&pdev->dev, &dev_attr_name);
Hans de Goede45fb3662007-07-13 14:34:19 +02002337
Hans de Goedefc16c562009-12-09 20:36:01 +01002338 if (start_reg & 0x01) {
2339 switch (data->type) {
2340 case f71858fg:
2341 if (data->temp_config & 0x10)
2342 f71882fg_remove_sysfs_files(pdev,
Hans de Goede0bae6402011-03-09 20:57:10 +01002343 f8000_temp_attr,
2344 ARRAY_SIZE(f8000_temp_attr));
Hans de Goedefc16c562009-12-09 20:36:01 +01002345 else
2346 f71882fg_remove_sysfs_files(pdev,
Hans de Goede0bae6402011-03-09 20:57:10 +01002347 f71858fg_temp_attr,
2348 ARRAY_SIZE(f71858fg_temp_attr));
Hans de Goedefc16c562009-12-09 20:36:01 +01002349 break;
2350 case f8000:
2351 f71882fg_remove_sysfs_files(pdev,
Hans de Goede0bae6402011-03-09 20:57:10 +01002352 f8000_temp_attr,
2353 ARRAY_SIZE(f8000_temp_attr));
Hans de Goedefc16c562009-12-09 20:36:01 +01002354 break;
Hans de Goede0bae6402011-03-09 20:57:10 +01002355 default:
2356 f71882fg_remove_sysfs_files(pdev,
Hans de Goede60d2b372011-03-09 20:57:11 +01002357 &fxxxx_temp_attr[0][0],
2358 ARRAY_SIZE(fxxxx_temp_attr[0]) * nr_temps);
Hans de Goede0bae6402011-03-09 20:57:10 +01002359 }
Hans de Goede4d538112011-05-25 20:43:32 +02002360 if (f71882fg_temp_has_beep[data->type]) {
Hans de Goede78aa4f72011-03-09 20:57:12 +01002361 f71882fg_remove_sysfs_files(pdev,
2362 &fxxxx_temp_beep_attr[0][0],
2363 ARRAY_SIZE(fxxxx_temp_beep_attr[0]) * nr_temps);
2364 }
2365
Hans de Goede0bae6402011-03-09 20:57:10 +01002366 for (i = 0; i < F71882FG_MAX_INS; i++) {
2367 if (f71882fg_has_in[data->type][i]) {
2368 device_remove_file(&pdev->dev,
2369 &fxxxx_in_attr[i].dev_attr);
2370 }
2371 }
2372 if (f71882fg_has_in1_alarm[data->type]) {
2373 f71882fg_remove_sysfs_files(pdev,
2374 fxxxx_in1_alarm_attr,
2375 ARRAY_SIZE(fxxxx_in1_alarm_attr));
Hans de Goedefc16c562009-12-09 20:36:01 +01002376 }
2377 }
Hans de Goede498be962009-01-07 16:37:28 +01002378
Hans de Goedefc16c562009-12-09 20:36:01 +01002379 if (start_reg & 0x02) {
2380 f71882fg_remove_sysfs_files(pdev, &fxxxx_fan_attr[0][0],
2381 ARRAY_SIZE(fxxxx_fan_attr[0]) * nr_fans);
Hans de Goede45fb3662007-07-13 14:34:19 +02002382
Hans de Goede4d538112011-05-25 20:43:32 +02002383 if (f71882fg_fan_has_beep[data->type]) {
Hans de Goedefc16c562009-12-09 20:36:01 +01002384 f71882fg_remove_sysfs_files(pdev,
2385 fxxxx_fan_beep_attr, nr_fans);
Hans de Goede78aa4f72011-03-09 20:57:12 +01002386 }
Hans de Goede498be962009-01-07 16:37:28 +01002387
Hans de Goedefc16c562009-12-09 20:36:01 +01002388 switch (data->type) {
2389 case f71862fg:
2390 f71882fg_remove_sysfs_files(pdev,
2391 f71862fg_auto_pwm_attr,
2392 ARRAY_SIZE(f71862fg_auto_pwm_attr));
2393 break;
Hans de Goedee5e713c2011-03-10 08:54:02 +01002394 case f71808e:
Hans de Goedec11bb992011-03-09 20:57:15 +01002395 case f71869:
2396 f71882fg_remove_sysfs_files(pdev,
2397 f71869_auto_pwm_attr,
2398 ARRAY_SIZE(f71869_auto_pwm_attr));
2399 break;
Hans de Goedefc16c562009-12-09 20:36:01 +01002400 case f8000:
2401 f71882fg_remove_sysfs_files(pdev,
2402 f8000_fan_attr,
2403 ARRAY_SIZE(f8000_fan_attr));
2404 f71882fg_remove_sysfs_files(pdev,
2405 f8000_auto_pwm_attr,
2406 ARRAY_SIZE(f8000_auto_pwm_attr));
2407 break;
Hans de Goede3cad4022011-03-09 20:57:14 +01002408 default:
Hans de Goedefc16c562009-12-09 20:36:01 +01002409 f71882fg_remove_sysfs_files(pdev,
2410 &fxxxx_auto_pwm_attr[0][0],
2411 ARRAY_SIZE(fxxxx_auto_pwm_attr[0]) * nr_fans);
2412 }
2413 }
Hans de Goedeed4f7c22009-01-07 16:37:30 +01002414
Hans de Goeded9ebaa42011-03-13 13:50:33 +01002415 platform_set_drvdata(pdev, NULL);
Hans de Goede45fb3662007-07-13 14:34:19 +02002416 kfree(data);
2417
2418 return 0;
2419}
2420
Hans de Goede498be962009-01-07 16:37:28 +01002421static int __init f71882fg_find(int sioaddr, unsigned short *address,
2422 struct f71882fg_sio_data *sio_data)
Hans de Goede45fb3662007-07-13 14:34:19 +02002423{
Hans de Goede45fb3662007-07-13 14:34:19 +02002424 u16 devid;
Giel van Schijndelcadb8652010-10-03 08:09:49 -04002425 int err = superio_enter(sioaddr);
2426 if (err)
2427 return err;
Hans de Goede45fb3662007-07-13 14:34:19 +02002428
2429 devid = superio_inw(sioaddr, SIO_REG_MANID);
2430 if (devid != SIO_FINTEK_ID) {
Joe Perches22d3b412010-10-20 06:51:34 +00002431 pr_debug("Not a Fintek device\n");
Giel van Schijndelcadb8652010-10-03 08:09:49 -04002432 err = -ENODEV;
Hans de Goede45fb3662007-07-13 14:34:19 +02002433 goto exit;
2434 }
2435
Jean Delvare67b671b2007-12-06 23:13:42 +01002436 devid = force_id ? force_id : superio_inw(sioaddr, SIO_REG_DEVID);
Hans de Goede498be962009-01-07 16:37:28 +01002437 switch (devid) {
Hans de Goedee5e713c2011-03-10 08:54:02 +01002438 case SIO_F71808E_ID:
2439 sio_data->type = f71808e;
2440 break;
Hans de Goede09475d32009-06-15 18:39:52 +02002441 case SIO_F71858_ID:
2442 sio_data->type = f71858fg;
2443 break;
Hans de Goede498be962009-01-07 16:37:28 +01002444 case SIO_F71862_ID:
2445 sio_data->type = f71862fg;
2446 break;
Hans de Goedec11bb992011-03-09 20:57:15 +01002447 case SIO_F71869_ID:
2448 sio_data->type = f71869;
2449 break;
Hans de Goede498be962009-01-07 16:37:28 +01002450 case SIO_F71882_ID:
2451 sio_data->type = f71882fg;
2452 break;
Hans de Goede76698962009-12-09 20:36:01 +01002453 case SIO_F71889_ID:
2454 sio_data->type = f71889fg;
2455 break;
Hans de Goede3cad4022011-03-09 20:57:14 +01002456 case SIO_F71889E_ID:
2457 sio_data->type = f71889ed;
2458 break;
Hans de Goedea66c1082011-03-26 10:45:02 +01002459 case SIO_F71889A_ID:
2460 sio_data->type = f71889a;
2461 break;
Hans de Goedeed4f7c22009-01-07 16:37:30 +01002462 case SIO_F8000_ID:
2463 sio_data->type = f8000;
2464 break;
Jean Delvare383586b2011-03-26 10:45:02 +01002465 case SIO_F81865_ID:
2466 sio_data->type = f81865f;
2467 break;
Hans de Goede498be962009-01-07 16:37:28 +01002468 default:
Joe Perches22d3b412010-10-20 06:51:34 +00002469 pr_info("Unsupported Fintek device: %04x\n",
2470 (unsigned int)devid);
Giel van Schijndelcadb8652010-10-03 08:09:49 -04002471 err = -ENODEV;
Hans de Goede45fb3662007-07-13 14:34:19 +02002472 goto exit;
2473 }
2474
Hans de Goede09475d32009-06-15 18:39:52 +02002475 if (sio_data->type == f71858fg)
2476 superio_select(sioaddr, SIO_F71858FG_LD_HWM);
2477 else
2478 superio_select(sioaddr, SIO_F71882FG_LD_HWM);
2479
Mark M. Hoffman8afb1042007-08-21 23:10:46 -04002480 if (!(superio_inb(sioaddr, SIO_REG_ENABLE) & 0x01)) {
Joe Perches22d3b412010-10-20 06:51:34 +00002481 pr_warn("Device not activated\n");
Giel van Schijndelcadb8652010-10-03 08:09:49 -04002482 err = -ENODEV;
Hans de Goede45fb3662007-07-13 14:34:19 +02002483 goto exit;
2484 }
2485
2486 *address = superio_inw(sioaddr, SIO_REG_ADDR);
Giel van Schijndel162bb592010-05-27 19:58:40 +02002487 if (*address == 0) {
Joe Perches22d3b412010-10-20 06:51:34 +00002488 pr_warn("Base address not set\n");
Giel van Schijndelcadb8652010-10-03 08:09:49 -04002489 err = -ENODEV;
Hans de Goede45fb3662007-07-13 14:34:19 +02002490 goto exit;
2491 }
2492 *address &= ~(REGION_LENGTH - 1); /* Ignore 3 LSB */
2493
Hans de Goede45fb3662007-07-13 14:34:19 +02002494 err = 0;
Joe Perches22d3b412010-10-20 06:51:34 +00002495 pr_info("Found %s chip at %#x, revision %d\n",
Hans de Goede498be962009-01-07 16:37:28 +01002496 f71882fg_names[sio_data->type], (unsigned int)*address,
Hans de Goede45fb3662007-07-13 14:34:19 +02002497 (int)superio_inb(sioaddr, SIO_REG_DEVREV));
2498exit:
2499 superio_exit(sioaddr);
2500 return err;
2501}
2502
Hans de Goede498be962009-01-07 16:37:28 +01002503static int __init f71882fg_device_add(unsigned short address,
2504 const struct f71882fg_sio_data *sio_data)
Hans de Goede45fb3662007-07-13 14:34:19 +02002505{
2506 struct resource res = {
2507 .start = address,
2508 .end = address + REGION_LENGTH - 1,
2509 .flags = IORESOURCE_IO,
2510 };
2511 int err;
2512
2513 f71882fg_pdev = platform_device_alloc(DRVNAME, address);
Mark M. Hoffman8afb1042007-08-21 23:10:46 -04002514 if (!f71882fg_pdev)
Hans de Goede45fb3662007-07-13 14:34:19 +02002515 return -ENOMEM;
2516
2517 res.name = f71882fg_pdev->name;
Jean Delvareb9acb642009-01-07 16:37:35 +01002518 err = acpi_check_resource_conflict(&res);
2519 if (err)
Hans de Goede18632f82009-02-17 19:59:54 +01002520 goto exit_device_put;
Jean Delvareb9acb642009-01-07 16:37:35 +01002521
Hans de Goede45fb3662007-07-13 14:34:19 +02002522 err = platform_device_add_resources(f71882fg_pdev, &res, 1);
Mark M. Hoffman8afb1042007-08-21 23:10:46 -04002523 if (err) {
Joe Perches22d3b412010-10-20 06:51:34 +00002524 pr_err("Device resource addition failed\n");
Hans de Goede45fb3662007-07-13 14:34:19 +02002525 goto exit_device_put;
2526 }
2527
Hans de Goede498be962009-01-07 16:37:28 +01002528 err = platform_device_add_data(f71882fg_pdev, sio_data,
2529 sizeof(struct f71882fg_sio_data));
2530 if (err) {
Joe Perches22d3b412010-10-20 06:51:34 +00002531 pr_err("Platform data allocation failed\n");
Hans de Goede498be962009-01-07 16:37:28 +01002532 goto exit_device_put;
2533 }
2534
Hans de Goede45fb3662007-07-13 14:34:19 +02002535 err = platform_device_add(f71882fg_pdev);
Mark M. Hoffman8afb1042007-08-21 23:10:46 -04002536 if (err) {
Joe Perches22d3b412010-10-20 06:51:34 +00002537 pr_err("Device addition failed\n");
Hans de Goede45fb3662007-07-13 14:34:19 +02002538 goto exit_device_put;
2539 }
2540
2541 return 0;
2542
2543exit_device_put:
2544 platform_device_put(f71882fg_pdev);
2545
2546 return err;
2547}
2548
2549static int __init f71882fg_init(void)
2550{
2551 int err = -ENODEV;
2552 unsigned short address;
Hans de Goede498be962009-01-07 16:37:28 +01002553 struct f71882fg_sio_data sio_data;
Hans de Goede45fb3662007-07-13 14:34:19 +02002554
Hans de Goede498be962009-01-07 16:37:28 +01002555 memset(&sio_data, 0, sizeof(sio_data));
2556
2557 if (f71882fg_find(0x2e, &address, &sio_data) &&
2558 f71882fg_find(0x4e, &address, &sio_data))
Hans de Goede45fb3662007-07-13 14:34:19 +02002559 goto exit;
2560
Hans de Goedec13548c2009-01-07 16:37:27 +01002561 err = platform_driver_register(&f71882fg_driver);
2562 if (err)
Hans de Goede45fb3662007-07-13 14:34:19 +02002563 goto exit;
2564
Hans de Goede498be962009-01-07 16:37:28 +01002565 err = f71882fg_device_add(address, &sio_data);
Hans de Goedec13548c2009-01-07 16:37:27 +01002566 if (err)
Hans de Goede45fb3662007-07-13 14:34:19 +02002567 goto exit_driver;
2568
2569 return 0;
2570
2571exit_driver:
2572 platform_driver_unregister(&f71882fg_driver);
2573exit:
2574 return err;
2575}
2576
2577static void __exit f71882fg_exit(void)
2578{
2579 platform_device_unregister(f71882fg_pdev);
2580 platform_driver_unregister(&f71882fg_driver);
2581}
2582
2583MODULE_DESCRIPTION("F71882FG Hardware Monitoring Driver");
Hans de Goedec13548c2009-01-07 16:37:27 +01002584MODULE_AUTHOR("Hans Edgington, Hans de Goede (hdegoede@redhat.com)");
Hans de Goede45fb3662007-07-13 14:34:19 +02002585MODULE_LICENSE("GPL");
2586
2587module_init(f71882fg_init);
2588module_exit(f71882fg_exit);