blob: aa8cf5d5c22e5377562e27b8304cef17677018e5 [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 Goedeed4f7c22009-01-07 16:37:30 +010057#define SIO_F8000_ID 0x0581 /* Chipset ID */
Jean Delvare383586b2011-03-26 10:45:02 +010058#define SIO_F81865_ID 0x0704 /* Chipset ID */
Hans de Goede45fb3662007-07-13 14:34:19 +020059
60#define REGION_LENGTH 8
61#define ADDR_REG_OFFSET 5
62#define DATA_REG_OFFSET 6
63
Hans de Goede3cad4022011-03-09 20:57:14 +010064#define F71882FG_REG_IN_STATUS 0x12 /* f7188x only */
65#define F71882FG_REG_IN_BEEP 0x13 /* f7188x only */
Hans de Goede45fb3662007-07-13 14:34:19 +020066#define F71882FG_REG_IN(nr) (0x20 + (nr))
Hans de Goede3cad4022011-03-09 20:57:14 +010067#define F71882FG_REG_IN1_HIGH 0x32 /* f7188x only */
Hans de Goede45fb3662007-07-13 14:34:19 +020068
69#define F71882FG_REG_FAN(nr) (0xA0 + (16 * (nr)))
Mark van Doesburg9ab796e2009-01-07 16:37:27 +010070#define F71882FG_REG_FAN_TARGET(nr) (0xA2 + (16 * (nr)))
71#define F71882FG_REG_FAN_FULL_SPEED(nr) (0xA4 + (16 * (nr)))
Hans de Goede45fb3662007-07-13 14:34:19 +020072#define F71882FG_REG_FAN_STATUS 0x92
73#define F71882FG_REG_FAN_BEEP 0x93
74
Hans de Goede7567a042009-01-07 16:37:28 +010075#define F71882FG_REG_TEMP(nr) (0x70 + 2 * (nr))
76#define F71882FG_REG_TEMP_OVT(nr) (0x80 + 2 * (nr))
77#define F71882FG_REG_TEMP_HIGH(nr) (0x81 + 2 * (nr))
Hans de Goede45fb3662007-07-13 14:34:19 +020078#define F71882FG_REG_TEMP_STATUS 0x62
79#define F71882FG_REG_TEMP_BEEP 0x63
Hans de Goede09475d32009-06-15 18:39:52 +020080#define F71882FG_REG_TEMP_CONFIG 0x69
Hans de Goedebc274902009-01-07 16:37:29 +010081#define F71882FG_REG_TEMP_HYST(nr) (0x6C + (nr))
Hans de Goede45fb3662007-07-13 14:34:19 +020082#define F71882FG_REG_TEMP_TYPE 0x6B
83#define F71882FG_REG_TEMP_DIODE_OPEN 0x6F
84
Mark van Doesburg9ab796e2009-01-07 16:37:27 +010085#define F71882FG_REG_PWM(nr) (0xA3 + (16 * (nr)))
86#define F71882FG_REG_PWM_TYPE 0x94
87#define F71882FG_REG_PWM_ENABLE 0x96
88
Hans de Goedebc274902009-01-07 16:37:29 +010089#define F71882FG_REG_FAN_HYST(nr) (0x98 + (nr))
Mark van Doesburg9ab796e2009-01-07 16:37:27 +010090
Hans de Goede98f7ba12011-03-09 20:57:09 +010091#define F71882FG_REG_FAN_FAULT_T 0x9F
92#define F71882FG_FAN_NEG_TEMP_EN 0x20
Hans de Goede3cad4022011-03-09 20:57:14 +010093#define F71882FG_FAN_PROG_SEL 0x80
Hans de Goede98f7ba12011-03-09 20:57:09 +010094
Mark van Doesburg9ab796e2009-01-07 16:37:27 +010095#define F71882FG_REG_POINT_PWM(pwm, point) (0xAA + (point) + (16 * (pwm)))
96#define F71882FG_REG_POINT_TEMP(pwm, point) (0xA6 + (point) + (16 * (pwm)))
97#define F71882FG_REG_POINT_MAPPING(nr) (0xAF + 16 * (nr))
98
Hans de Goede45fb3662007-07-13 14:34:19 +020099#define F71882FG_REG_START 0x01
100
Hans de Goede0bae6402011-03-09 20:57:10 +0100101#define F71882FG_MAX_INS 9
102
Hans de Goede45fb3662007-07-13 14:34:19 +0200103#define FAN_MIN_DETECT 366 /* Lowest detectable fanspeed */
104
Jean Delvare67b671b2007-12-06 23:13:42 +0100105static unsigned short force_id;
106module_param(force_id, ushort, 0);
107MODULE_PARM_DESC(force_id, "Override the detected device ID");
108
Hans de Goedee5e713c2011-03-10 08:54:02 +0100109enum chips { f71808e, f71858fg, f71862fg, f71869, f71882fg, f71889fg,
Jean Delvare383586b2011-03-26 10:45:02 +0100110 f71889ed, f8000, f81865f };
Hans de Goede498be962009-01-07 16:37:28 +0100111
112static const char *f71882fg_names[] = {
Hans de Goedee5e713c2011-03-10 08:54:02 +0100113 "f71808e",
Hans de Goede09475d32009-06-15 18:39:52 +0200114 "f71858fg",
Hans de Goede498be962009-01-07 16:37:28 +0100115 "f71862fg",
Hans de Goedec11bb992011-03-09 20:57:15 +0100116 "f71869", /* Both f71869f and f71869e, reg. compatible and same id */
Hans de Goede498be962009-01-07 16:37:28 +0100117 "f71882fg",
Jean Delvare5d7f77b2011-03-26 10:45:02 +0100118 "f71889fg", /* f81801u too, same id */
Hans de Goede3cad4022011-03-09 20:57:14 +0100119 "f71889ed",
Hans de Goedeed4f7c22009-01-07 16:37:30 +0100120 "f8000",
Jean Delvare383586b2011-03-26 10:45:02 +0100121 "f81865f",
Hans de Goede498be962009-01-07 16:37:28 +0100122};
123
Jean Delvare2740c602011-03-26 10:45:01 +0100124static const char f71882fg_has_in[][F71882FG_MAX_INS] = {
125 [f71808e] = { 1, 1, 1, 1, 1, 1, 0, 1, 1 },
126 [f71858fg] = { 1, 1, 1, 0, 0, 0, 0, 0, 0 },
127 [f71862fg] = { 1, 1, 1, 1, 1, 1, 1, 1, 1 },
128 [f71869] = { 1, 1, 1, 1, 1, 1, 1, 1, 1 },
129 [f71882fg] = { 1, 1, 1, 1, 1, 1, 1, 1, 1 },
130 [f71889fg] = { 1, 1, 1, 1, 1, 1, 1, 1, 1 },
131 [f71889ed] = { 1, 1, 1, 1, 1, 1, 1, 1, 1 },
132 [f8000] = { 1, 1, 1, 0, 0, 0, 0, 0, 0 },
Jean Delvare383586b2011-03-26 10:45:02 +0100133 [f81865f] = { 1, 1, 1, 1, 1, 1, 1, 0, 0 },
Hans de Goede0bae6402011-03-09 20:57:10 +0100134};
135
Jean Delvare2740c602011-03-26 10:45:01 +0100136static const char f71882fg_has_in1_alarm[] = {
137 [f71808e] = 0,
138 [f71858fg] = 0,
139 [f71862fg] = 0,
140 [f71869] = 0,
141 [f71882fg] = 1,
142 [f71889fg] = 1,
143 [f71889ed] = 1,
144 [f8000] = 0,
Jean Delvare383586b2011-03-26 10:45:02 +0100145 [f81865f] = 1,
Hans de Goede0bae6402011-03-09 20:57:10 +0100146};
147
Jean Delvare2740c602011-03-26 10:45:01 +0100148static const char f71882fg_has_beep[] = {
149 [f71808e] = 0,
150 [f71858fg] = 0,
151 [f71862fg] = 1,
152 [f71869] = 1,
153 [f71882fg] = 1,
154 [f71889fg] = 1,
155 [f71889ed] = 1,
156 [f8000] = 0,
Jean Delvare383586b2011-03-26 10:45:02 +0100157 [f81865f] = 1,
Hans de Goede78aa4f72011-03-09 20:57:12 +0100158};
159
Jean Delvaref27def02011-03-26 10:45:01 +0100160static const char f71882fg_nr_fans[] = {
161 [f71808e] = 3,
162 [f71858fg] = 3,
163 [f71862fg] = 3,
164 [f71869] = 3,
165 [f71882fg] = 4,
166 [f71889fg] = 3,
167 [f71889ed] = 3,
168 [f8000] = 3,
Jean Delvare383586b2011-03-26 10:45:02 +0100169 [f81865f] = 2,
Jean Delvaref27def02011-03-26 10:45:01 +0100170};
171
172static const char f71882fg_nr_temps[] = {
173 [f71808e] = 2,
174 [f71858fg] = 3,
175 [f71862fg] = 3,
176 [f71869] = 3,
177 [f71882fg] = 3,
178 [f71889fg] = 3,
179 [f71889ed] = 3,
180 [f8000] = 3,
Jean Delvare383586b2011-03-26 10:45:02 +0100181 [f81865f] = 2,
Jean Delvaref27def02011-03-26 10:45:01 +0100182};
183
Mark van Doesburg77a4a3e2009-01-07 16:37:27 +0100184static struct platform_device *f71882fg_pdev;
Hans de Goede45fb3662007-07-13 14:34:19 +0200185
186/* Super-I/O Function prototypes */
187static inline int superio_inb(int base, int reg);
188static inline int superio_inw(int base, int reg);
Giel van Schijndelcadb8652010-10-03 08:09:49 -0400189static inline int superio_enter(int base);
Hans de Goede45fb3662007-07-13 14:34:19 +0200190static inline void superio_select(int base, int ld);
191static inline void superio_exit(int base);
192
Hans de Goede498be962009-01-07 16:37:28 +0100193struct f71882fg_sio_data {
194 enum chips type;
195};
196
Hans de Goede45fb3662007-07-13 14:34:19 +0200197struct f71882fg_data {
198 unsigned short addr;
Hans de Goede498be962009-01-07 16:37:28 +0100199 enum chips type;
Tony Jones1beeffe2007-08-20 13:46:20 -0700200 struct device *hwmon_dev;
Hans de Goede45fb3662007-07-13 14:34:19 +0200201
202 struct mutex update_lock;
Hans de Goede09475d32009-06-15 18:39:52 +0200203 int temp_start; /* temp numbering start (0 or 1) */
Hans de Goede45fb3662007-07-13 14:34:19 +0200204 char valid; /* !=0 if following fields are valid */
Hans de Goede98f7ba12011-03-09 20:57:09 +0100205 char auto_point_temp_signed;
Hans de Goede45fb3662007-07-13 14:34:19 +0200206 unsigned long last_updated; /* In jiffies */
207 unsigned long last_limits; /* In jiffies */
208
209 /* Register Values */
Hans de Goede0bae6402011-03-09 20:57:10 +0100210 u8 in[F71882FG_MAX_INS];
Hans de Goede45fb3662007-07-13 14:34:19 +0200211 u8 in1_max;
212 u8 in_status;
213 u8 in_beep;
214 u16 fan[4];
Mark van Doesburg9ab796e2009-01-07 16:37:27 +0100215 u16 fan_target[4];
216 u16 fan_full_speed[4];
Hans de Goede45fb3662007-07-13 14:34:19 +0200217 u8 fan_status;
218 u8 fan_beep;
Hans de Goedee5e713c2011-03-10 08:54:02 +0100219 /* Note: all models have max 3 temperature channels, but on some
Hans de Goede7567a042009-01-07 16:37:28 +0100220 they are addressed as 0-2 and on others as 1-3, so for coding
221 convenience we reserve space for 4 channels */
Hans de Goede09475d32009-06-15 18:39:52 +0200222 u16 temp[4];
Hans de Goede7567a042009-01-07 16:37:28 +0100223 u8 temp_ovt[4];
224 u8 temp_high[4];
Hans de Goedebc274902009-01-07 16:37:29 +0100225 u8 temp_hyst[2]; /* 2 hysts stored per reg */
Hans de Goede7567a042009-01-07 16:37:28 +0100226 u8 temp_type[4];
Hans de Goede45fb3662007-07-13 14:34:19 +0200227 u8 temp_status;
228 u8 temp_beep;
229 u8 temp_diode_open;
Hans de Goede09475d32009-06-15 18:39:52 +0200230 u8 temp_config;
Mark van Doesburg9ab796e2009-01-07 16:37:27 +0100231 u8 pwm[4];
232 u8 pwm_enable;
233 u8 pwm_auto_point_hyst[2];
234 u8 pwm_auto_point_mapping[4];
235 u8 pwm_auto_point_pwm[4][5];
Hans de Goede76698962009-12-09 20:36:01 +0100236 s8 pwm_auto_point_temp[4][4];
Hans de Goede45fb3662007-07-13 14:34:19 +0200237};
238
Mark van Doesburg77a4a3e2009-01-07 16:37:27 +0100239/* Sysfs in */
Hans de Goede45fb3662007-07-13 14:34:19 +0200240static ssize_t show_in(struct device *dev, struct device_attribute *devattr,
241 char *buf);
242static ssize_t show_in_max(struct device *dev, struct device_attribute
243 *devattr, char *buf);
244static ssize_t store_in_max(struct device *dev, struct device_attribute
245 *devattr, const char *buf, size_t count);
246static ssize_t show_in_beep(struct device *dev, struct device_attribute
247 *devattr, char *buf);
248static ssize_t store_in_beep(struct device *dev, struct device_attribute
249 *devattr, const char *buf, size_t count);
250static ssize_t show_in_alarm(struct device *dev, struct device_attribute
251 *devattr, char *buf);
252/* Sysfs Fan */
253static ssize_t show_fan(struct device *dev, struct device_attribute *devattr,
254 char *buf);
Mark van Doesburg9ab796e2009-01-07 16:37:27 +0100255static ssize_t show_fan_full_speed(struct device *dev,
256 struct device_attribute *devattr, char *buf);
257static ssize_t store_fan_full_speed(struct device *dev,
258 struct device_attribute *devattr, const char *buf, size_t count);
Hans de Goede45fb3662007-07-13 14:34:19 +0200259static ssize_t show_fan_beep(struct device *dev, struct device_attribute
260 *devattr, char *buf);
261static ssize_t store_fan_beep(struct device *dev, struct device_attribute
262 *devattr, const char *buf, size_t count);
263static ssize_t show_fan_alarm(struct device *dev, struct device_attribute
264 *devattr, char *buf);
265/* Sysfs Temp */
266static ssize_t show_temp(struct device *dev, struct device_attribute
267 *devattr, char *buf);
268static ssize_t show_temp_max(struct device *dev, struct device_attribute
269 *devattr, char *buf);
270static ssize_t store_temp_max(struct device *dev, struct device_attribute
271 *devattr, const char *buf, size_t count);
272static ssize_t show_temp_max_hyst(struct device *dev, struct device_attribute
273 *devattr, char *buf);
274static ssize_t store_temp_max_hyst(struct device *dev, struct device_attribute
275 *devattr, const char *buf, size_t count);
276static ssize_t show_temp_crit(struct device *dev, struct device_attribute
277 *devattr, char *buf);
278static ssize_t store_temp_crit(struct device *dev, struct device_attribute
279 *devattr, const char *buf, size_t count);
280static ssize_t show_temp_crit_hyst(struct device *dev, struct device_attribute
281 *devattr, char *buf);
282static ssize_t show_temp_type(struct device *dev, struct device_attribute
283 *devattr, char *buf);
284static ssize_t show_temp_beep(struct device *dev, struct device_attribute
285 *devattr, char *buf);
286static ssize_t store_temp_beep(struct device *dev, struct device_attribute
287 *devattr, const char *buf, size_t count);
288static ssize_t show_temp_alarm(struct device *dev, struct device_attribute
289 *devattr, char *buf);
290static ssize_t show_temp_fault(struct device *dev, struct device_attribute
291 *devattr, char *buf);
Mark van Doesburg9ab796e2009-01-07 16:37:27 +0100292/* PWM and Auto point control */
293static ssize_t show_pwm(struct device *dev, struct device_attribute *devattr,
294 char *buf);
295static ssize_t store_pwm(struct device *dev, struct device_attribute *devattr,
296 const char *buf, size_t count);
297static ssize_t show_pwm_enable(struct device *dev,
298 struct device_attribute *devattr, char *buf);
299static ssize_t store_pwm_enable(struct device *dev,
300 struct device_attribute *devattr, const char *buf, size_t count);
301static ssize_t show_pwm_interpolate(struct device *dev,
302 struct device_attribute *devattr, char *buf);
303static ssize_t store_pwm_interpolate(struct device *dev,
304 struct device_attribute *devattr, const char *buf, size_t count);
305static ssize_t show_pwm_auto_point_channel(struct device *dev,
306 struct device_attribute *devattr, char *buf);
307static ssize_t store_pwm_auto_point_channel(struct device *dev,
308 struct device_attribute *devattr, const char *buf, size_t count);
309static ssize_t show_pwm_auto_point_temp_hyst(struct device *dev,
310 struct device_attribute *devattr, char *buf);
311static ssize_t store_pwm_auto_point_temp_hyst(struct device *dev,
312 struct device_attribute *devattr, const char *buf, size_t count);
313static ssize_t show_pwm_auto_point_pwm(struct device *dev,
314 struct device_attribute *devattr, char *buf);
315static ssize_t store_pwm_auto_point_pwm(struct device *dev,
316 struct device_attribute *devattr, const char *buf, size_t count);
317static ssize_t show_pwm_auto_point_temp(struct device *dev,
318 struct device_attribute *devattr, char *buf);
319static ssize_t store_pwm_auto_point_temp(struct device *dev,
320 struct device_attribute *devattr, const char *buf, size_t count);
Hans de Goede45fb3662007-07-13 14:34:19 +0200321/* Sysfs misc */
322static ssize_t show_name(struct device *dev, struct device_attribute *devattr,
323 char *buf);
324
325static int __devinit f71882fg_probe(struct platform_device * pdev);
Hans de Goedec13548c2009-01-07 16:37:27 +0100326static int f71882fg_remove(struct platform_device *pdev);
Hans de Goede45fb3662007-07-13 14:34:19 +0200327
328static struct platform_driver f71882fg_driver = {
329 .driver = {
330 .owner = THIS_MODULE,
331 .name = DRVNAME,
332 },
333 .probe = f71882fg_probe,
Jean Delvarecd659fd2009-06-15 18:39:45 +0200334 .remove = f71882fg_remove,
Hans de Goede45fb3662007-07-13 14:34:19 +0200335};
336
Hans de Goedec13548c2009-01-07 16:37:27 +0100337static DEVICE_ATTR(name, S_IRUGO, show_name, NULL);
Hans de Goede45fb3662007-07-13 14:34:19 +0200338
Hans de Goede0bae6402011-03-09 20:57:10 +0100339/* Temp attr for the f71858fg, the f71858fg is special as it has its
340 temperature indexes start at 0 (the others start at 1) */
341static struct sensor_device_attribute_2 f71858fg_temp_attr[] = {
Hans de Goede09475d32009-06-15 18:39:52 +0200342 SENSOR_ATTR_2(temp1_input, S_IRUGO, show_temp, NULL, 0, 0),
343 SENSOR_ATTR_2(temp1_max, S_IRUGO|S_IWUSR, show_temp_max,
344 store_temp_max, 0, 0),
345 SENSOR_ATTR_2(temp1_max_hyst, S_IRUGO|S_IWUSR, show_temp_max_hyst,
346 store_temp_max_hyst, 0, 0),
347 SENSOR_ATTR_2(temp1_max_alarm, S_IRUGO, show_temp_alarm, NULL, 0, 0),
348 SENSOR_ATTR_2(temp1_crit, S_IRUGO|S_IWUSR, show_temp_crit,
349 store_temp_crit, 0, 0),
350 SENSOR_ATTR_2(temp1_crit_hyst, S_IRUGO, show_temp_crit_hyst, NULL,
351 0, 0),
352 SENSOR_ATTR_2(temp1_crit_alarm, S_IRUGO, show_temp_alarm, NULL, 0, 4),
353 SENSOR_ATTR_2(temp1_fault, S_IRUGO, show_temp_fault, NULL, 0, 0),
354 SENSOR_ATTR_2(temp2_input, S_IRUGO, show_temp, NULL, 0, 1),
355 SENSOR_ATTR_2(temp2_max, S_IRUGO|S_IWUSR, show_temp_max,
356 store_temp_max, 0, 1),
357 SENSOR_ATTR_2(temp2_max_hyst, S_IRUGO|S_IWUSR, show_temp_max_hyst,
358 store_temp_max_hyst, 0, 1),
359 SENSOR_ATTR_2(temp2_max_alarm, S_IRUGO, show_temp_alarm, NULL, 0, 1),
360 SENSOR_ATTR_2(temp2_crit, S_IRUGO|S_IWUSR, show_temp_crit,
361 store_temp_crit, 0, 1),
362 SENSOR_ATTR_2(temp2_crit_hyst, S_IRUGO, show_temp_crit_hyst, NULL,
363 0, 1),
364 SENSOR_ATTR_2(temp2_crit_alarm, S_IRUGO, show_temp_alarm, NULL, 0, 5),
Hans de Goede09475d32009-06-15 18:39:52 +0200365 SENSOR_ATTR_2(temp2_fault, S_IRUGO, show_temp_fault, NULL, 0, 1),
366 SENSOR_ATTR_2(temp3_input, S_IRUGO, show_temp, NULL, 0, 2),
367 SENSOR_ATTR_2(temp3_max, S_IRUGO|S_IWUSR, show_temp_max,
368 store_temp_max, 0, 2),
369 SENSOR_ATTR_2(temp3_max_hyst, S_IRUGO|S_IWUSR, show_temp_max_hyst,
370 store_temp_max_hyst, 0, 2),
371 SENSOR_ATTR_2(temp3_max_alarm, S_IRUGO, show_temp_alarm, NULL, 0, 2),
372 SENSOR_ATTR_2(temp3_crit, S_IRUGO|S_IWUSR, show_temp_crit,
373 store_temp_crit, 0, 2),
374 SENSOR_ATTR_2(temp3_crit_hyst, S_IRUGO, show_temp_crit_hyst, NULL,
375 0, 2),
376 SENSOR_ATTR_2(temp3_crit_alarm, S_IRUGO, show_temp_alarm, NULL, 0, 6),
377 SENSOR_ATTR_2(temp3_fault, S_IRUGO, show_temp_fault, NULL, 0, 2),
378};
379
Hans de Goede0bae6402011-03-09 20:57:10 +0100380/* Temp attr for the standard models */
Hans de Goede78aa4f72011-03-09 20:57:12 +0100381static struct sensor_device_attribute_2 fxxxx_temp_attr[3][9] = { {
Hans de Goede7567a042009-01-07 16:37:28 +0100382 SENSOR_ATTR_2(temp1_input, S_IRUGO, show_temp, NULL, 0, 1),
Mark van Doesburgbc37ae72009-01-07 16:37:27 +0100383 SENSOR_ATTR_2(temp1_max, S_IRUGO|S_IWUSR, show_temp_max,
Mark van Doesburgbc37ae72009-01-07 16:37:27 +0100384 store_temp_max, 0, 1),
Hans de Goede7567a042009-01-07 16:37:28 +0100385 SENSOR_ATTR_2(temp1_max_hyst, S_IRUGO|S_IWUSR, show_temp_max_hyst,
Mark van Doesburgbc37ae72009-01-07 16:37:27 +0100386 store_temp_max_hyst, 0, 1),
Hans de Goede754a5907b2009-01-07 16:37:29 +0100387 /* Should really be temp1_max_alarm, but older versions did not handle
388 the max and crit alarms separately and lm_sensors v2 depends on the
389 presence of temp#_alarm files. The same goes for temp2/3 _alarm. */
390 SENSOR_ATTR_2(temp1_alarm, S_IRUGO, show_temp_alarm, NULL, 0, 1),
Hans de Goede7567a042009-01-07 16:37:28 +0100391 SENSOR_ATTR_2(temp1_crit, S_IRUGO|S_IWUSR, show_temp_crit,
Mark van Doesburgbc37ae72009-01-07 16:37:27 +0100392 store_temp_crit, 0, 1),
Hans de Goede7567a042009-01-07 16:37:28 +0100393 SENSOR_ATTR_2(temp1_crit_hyst, S_IRUGO, show_temp_crit_hyst, NULL,
Mark van Doesburgbc37ae72009-01-07 16:37:27 +0100394 0, 1),
Hans de Goede754a5907b2009-01-07 16:37:29 +0100395 SENSOR_ATTR_2(temp1_crit_alarm, S_IRUGO, show_temp_alarm, NULL, 0, 5),
Hans de Goede7567a042009-01-07 16:37:28 +0100396 SENSOR_ATTR_2(temp1_type, S_IRUGO, show_temp_type, NULL, 0, 1),
Hans de Goede7567a042009-01-07 16:37:28 +0100397 SENSOR_ATTR_2(temp1_fault, S_IRUGO, show_temp_fault, NULL, 0, 1),
Hans de Goede60d2b372011-03-09 20:57:11 +0100398}, {
Hans de Goede7567a042009-01-07 16:37:28 +0100399 SENSOR_ATTR_2(temp2_input, S_IRUGO, show_temp, NULL, 0, 2),
400 SENSOR_ATTR_2(temp2_max, S_IRUGO|S_IWUSR, show_temp_max,
Mark van Doesburgbc37ae72009-01-07 16:37:27 +0100401 store_temp_max, 0, 2),
Hans de Goede7567a042009-01-07 16:37:28 +0100402 SENSOR_ATTR_2(temp2_max_hyst, S_IRUGO|S_IWUSR, show_temp_max_hyst,
Mark van Doesburgbc37ae72009-01-07 16:37:27 +0100403 store_temp_max_hyst, 0, 2),
Hans de Goede754a5907b2009-01-07 16:37:29 +0100404 /* Should be temp2_max_alarm, see temp1_alarm note */
405 SENSOR_ATTR_2(temp2_alarm, S_IRUGO, show_temp_alarm, NULL, 0, 2),
Hans de Goede7567a042009-01-07 16:37:28 +0100406 SENSOR_ATTR_2(temp2_crit, S_IRUGO|S_IWUSR, show_temp_crit,
Mark van Doesburgbc37ae72009-01-07 16:37:27 +0100407 store_temp_crit, 0, 2),
Hans de Goede7567a042009-01-07 16:37:28 +0100408 SENSOR_ATTR_2(temp2_crit_hyst, S_IRUGO, show_temp_crit_hyst, NULL,
Mark van Doesburgbc37ae72009-01-07 16:37:27 +0100409 0, 2),
Hans de Goede754a5907b2009-01-07 16:37:29 +0100410 SENSOR_ATTR_2(temp2_crit_alarm, S_IRUGO, show_temp_alarm, NULL, 0, 6),
Hans de Goede7567a042009-01-07 16:37:28 +0100411 SENSOR_ATTR_2(temp2_type, S_IRUGO, show_temp_type, NULL, 0, 2),
Hans de Goede7567a042009-01-07 16:37:28 +0100412 SENSOR_ATTR_2(temp2_fault, S_IRUGO, show_temp_fault, NULL, 0, 2),
Hans de Goede60d2b372011-03-09 20:57:11 +0100413}, {
Hans de Goede7567a042009-01-07 16:37:28 +0100414 SENSOR_ATTR_2(temp3_input, S_IRUGO, show_temp, NULL, 0, 3),
415 SENSOR_ATTR_2(temp3_max, S_IRUGO|S_IWUSR, show_temp_max,
416 store_temp_max, 0, 3),
417 SENSOR_ATTR_2(temp3_max_hyst, S_IRUGO|S_IWUSR, show_temp_max_hyst,
418 store_temp_max_hyst, 0, 3),
Hans de Goede754a5907b2009-01-07 16:37:29 +0100419 /* Should be temp3_max_alarm, see temp1_alarm note */
420 SENSOR_ATTR_2(temp3_alarm, S_IRUGO, show_temp_alarm, NULL, 0, 3),
Hans de Goede7567a042009-01-07 16:37:28 +0100421 SENSOR_ATTR_2(temp3_crit, S_IRUGO|S_IWUSR, show_temp_crit,
422 store_temp_crit, 0, 3),
423 SENSOR_ATTR_2(temp3_crit_hyst, S_IRUGO, show_temp_crit_hyst, NULL,
424 0, 3),
Hans de Goede754a5907b2009-01-07 16:37:29 +0100425 SENSOR_ATTR_2(temp3_crit_alarm, S_IRUGO, show_temp_alarm, NULL, 0, 7),
Hans de Goede7567a042009-01-07 16:37:28 +0100426 SENSOR_ATTR_2(temp3_type, S_IRUGO, show_temp_type, NULL, 0, 3),
Hans de Goede7567a042009-01-07 16:37:28 +0100427 SENSOR_ATTR_2(temp3_fault, S_IRUGO, show_temp_fault, NULL, 0, 3),
Hans de Goede60d2b372011-03-09 20:57:11 +0100428} };
Hans de Goede45fb3662007-07-13 14:34:19 +0200429
Hans de Goede78aa4f72011-03-09 20:57:12 +0100430/* Temp attr for models which can beep on temp alarm */
431static struct sensor_device_attribute_2 fxxxx_temp_beep_attr[3][2] = { {
432 SENSOR_ATTR_2(temp1_max_beep, S_IRUGO|S_IWUSR, show_temp_beep,
433 store_temp_beep, 0, 1),
434 SENSOR_ATTR_2(temp1_crit_beep, S_IRUGO|S_IWUSR, show_temp_beep,
435 store_temp_beep, 0, 5),
436}, {
437 SENSOR_ATTR_2(temp2_max_beep, S_IRUGO|S_IWUSR, show_temp_beep,
438 store_temp_beep, 0, 2),
439 SENSOR_ATTR_2(temp2_crit_beep, S_IRUGO|S_IWUSR, show_temp_beep,
440 store_temp_beep, 0, 6),
441}, {
442 SENSOR_ATTR_2(temp3_max_beep, S_IRUGO|S_IWUSR, show_temp_beep,
443 store_temp_beep, 0, 3),
444 SENSOR_ATTR_2(temp3_crit_beep, S_IRUGO|S_IWUSR, show_temp_beep,
445 store_temp_beep, 0, 7),
446} };
447
Hans de Goede0bae6402011-03-09 20:57:10 +0100448/* Temp attr for the f8000
Hans de Goedeed4f7c22009-01-07 16:37:30 +0100449 Note on the f8000 temp_ovt (crit) is used as max, and temp_high (max)
450 is used as hysteresis value to clear alarms
Hans de Goede66344aa2009-12-09 20:35:59 +0100451 Also like the f71858fg its temperature indexes start at 0
Hans de Goedeed4f7c22009-01-07 16:37:30 +0100452 */
Hans de Goede0bae6402011-03-09 20:57:10 +0100453static struct sensor_device_attribute_2 f8000_temp_attr[] = {
Hans de Goedeed4f7c22009-01-07 16:37:30 +0100454 SENSOR_ATTR_2(temp1_input, S_IRUGO, show_temp, NULL, 0, 0),
455 SENSOR_ATTR_2(temp1_max, S_IRUGO|S_IWUSR, show_temp_crit,
456 store_temp_crit, 0, 0),
457 SENSOR_ATTR_2(temp1_max_hyst, S_IRUGO|S_IWUSR, show_temp_max,
458 store_temp_max, 0, 0),
459 SENSOR_ATTR_2(temp1_alarm, S_IRUGO, show_temp_alarm, NULL, 0, 4),
Hans de Goedeb6858bc2009-06-15 18:39:51 +0200460 SENSOR_ATTR_2(temp1_fault, S_IRUGO, show_temp_fault, NULL, 0, 0),
Hans de Goedeed4f7c22009-01-07 16:37:30 +0100461 SENSOR_ATTR_2(temp2_input, S_IRUGO, show_temp, NULL, 0, 1),
462 SENSOR_ATTR_2(temp2_max, S_IRUGO|S_IWUSR, show_temp_crit,
463 store_temp_crit, 0, 1),
464 SENSOR_ATTR_2(temp2_max_hyst, S_IRUGO|S_IWUSR, show_temp_max,
465 store_temp_max, 0, 1),
466 SENSOR_ATTR_2(temp2_alarm, S_IRUGO, show_temp_alarm, NULL, 0, 5),
Hans de Goedeb6858bc2009-06-15 18:39:51 +0200467 SENSOR_ATTR_2(temp2_fault, S_IRUGO, show_temp_fault, NULL, 0, 1),
Hans de Goedeed4f7c22009-01-07 16:37:30 +0100468 SENSOR_ATTR_2(temp3_input, S_IRUGO, show_temp, NULL, 0, 2),
469 SENSOR_ATTR_2(temp3_max, S_IRUGO|S_IWUSR, show_temp_crit,
470 store_temp_crit, 0, 2),
471 SENSOR_ATTR_2(temp3_max_hyst, S_IRUGO|S_IWUSR, show_temp_max,
472 store_temp_max, 0, 2),
473 SENSOR_ATTR_2(temp3_alarm, S_IRUGO, show_temp_alarm, NULL, 0, 6),
Hans de Goedeb6858bc2009-06-15 18:39:51 +0200474 SENSOR_ATTR_2(temp3_fault, S_IRUGO, show_temp_fault, NULL, 0, 2),
Hans de Goedeed4f7c22009-01-07 16:37:30 +0100475};
476
Hans de Goede0bae6402011-03-09 20:57:10 +0100477/* in attr for all models */
478static struct sensor_device_attribute_2 fxxxx_in_attr[] = {
479 SENSOR_ATTR_2(in0_input, S_IRUGO, show_in, NULL, 0, 0),
480 SENSOR_ATTR_2(in1_input, S_IRUGO, show_in, NULL, 0, 1),
481 SENSOR_ATTR_2(in2_input, S_IRUGO, show_in, NULL, 0, 2),
482 SENSOR_ATTR_2(in3_input, S_IRUGO, show_in, NULL, 0, 3),
483 SENSOR_ATTR_2(in4_input, S_IRUGO, show_in, NULL, 0, 4),
484 SENSOR_ATTR_2(in5_input, S_IRUGO, show_in, NULL, 0, 5),
485 SENSOR_ATTR_2(in6_input, S_IRUGO, show_in, NULL, 0, 6),
486 SENSOR_ATTR_2(in7_input, S_IRUGO, show_in, NULL, 0, 7),
487 SENSOR_ATTR_2(in8_input, S_IRUGO, show_in, NULL, 0, 8),
488};
489
490/* For models with in1 alarm capability */
491static struct sensor_device_attribute_2 fxxxx_in1_alarm_attr[] = {
492 SENSOR_ATTR_2(in1_max, S_IRUGO|S_IWUSR, show_in_max, store_in_max,
493 0, 1),
494 SENSOR_ATTR_2(in1_beep, S_IRUGO|S_IWUSR, show_in_beep, store_in_beep,
495 0, 1),
496 SENSOR_ATTR_2(in1_alarm, S_IRUGO, show_in_alarm, NULL, 0, 1),
497};
498
Hans de Goedeed4f7c22009-01-07 16:37:30 +0100499/* Fan / PWM attr common to all models */
Hans de Goedeb69b0392009-12-09 20:36:00 +0100500static struct sensor_device_attribute_2 fxxxx_fan_attr[4][6] = { {
Mark van Doesburgbc37ae72009-01-07 16:37:27 +0100501 SENSOR_ATTR_2(fan1_input, S_IRUGO, show_fan, NULL, 0, 0),
Mark van Doesburg9ab796e2009-01-07 16:37:27 +0100502 SENSOR_ATTR_2(fan1_full_speed, S_IRUGO|S_IWUSR,
503 show_fan_full_speed,
504 store_fan_full_speed, 0, 0),
Mark van Doesburgbc37ae72009-01-07 16:37:27 +0100505 SENSOR_ATTR_2(fan1_alarm, S_IRUGO, show_fan_alarm, NULL, 0, 0),
Mark van Doesburg9ab796e2009-01-07 16:37:27 +0100506 SENSOR_ATTR_2(pwm1, S_IRUGO|S_IWUSR, show_pwm, store_pwm, 0, 0),
507 SENSOR_ATTR_2(pwm1_enable, S_IRUGO|S_IWUSR, show_pwm_enable,
508 store_pwm_enable, 0, 0),
509 SENSOR_ATTR_2(pwm1_interpolate, S_IRUGO|S_IWUSR,
510 show_pwm_interpolate, store_pwm_interpolate, 0, 0),
Hans de Goedeb69b0392009-12-09 20:36:00 +0100511}, {
512 SENSOR_ATTR_2(fan2_input, S_IRUGO, show_fan, NULL, 0, 1),
513 SENSOR_ATTR_2(fan2_full_speed, S_IRUGO|S_IWUSR,
514 show_fan_full_speed,
515 store_fan_full_speed, 0, 1),
516 SENSOR_ATTR_2(fan2_alarm, S_IRUGO, show_fan_alarm, NULL, 0, 1),
Hans de Goede498be962009-01-07 16:37:28 +0100517 SENSOR_ATTR_2(pwm2, S_IRUGO|S_IWUSR, show_pwm, store_pwm, 0, 1),
518 SENSOR_ATTR_2(pwm2_enable, S_IRUGO|S_IWUSR, show_pwm_enable,
519 store_pwm_enable, 0, 1),
520 SENSOR_ATTR_2(pwm2_interpolate, S_IRUGO|S_IWUSR,
521 show_pwm_interpolate, store_pwm_interpolate, 0, 1),
Hans de Goedeb69b0392009-12-09 20:36:00 +0100522}, {
523 SENSOR_ATTR_2(fan3_input, S_IRUGO, show_fan, NULL, 0, 2),
524 SENSOR_ATTR_2(fan3_full_speed, S_IRUGO|S_IWUSR,
525 show_fan_full_speed,
526 store_fan_full_speed, 0, 2),
527 SENSOR_ATTR_2(fan3_alarm, S_IRUGO, show_fan_alarm, NULL, 0, 2),
Hans de Goede3fc78382009-06-15 18:39:50 +0200528 SENSOR_ATTR_2(pwm3, S_IRUGO|S_IWUSR, show_pwm, store_pwm, 0, 2),
529 SENSOR_ATTR_2(pwm3_enable, S_IRUGO|S_IWUSR, show_pwm_enable,
530 store_pwm_enable, 0, 2),
Hans de Goede498be962009-01-07 16:37:28 +0100531 SENSOR_ATTR_2(pwm3_interpolate, S_IRUGO|S_IWUSR,
532 show_pwm_interpolate, store_pwm_interpolate, 0, 2),
Hans de Goedeb69b0392009-12-09 20:36:00 +0100533}, {
534 SENSOR_ATTR_2(fan4_input, S_IRUGO, show_fan, NULL, 0, 3),
535 SENSOR_ATTR_2(fan4_full_speed, S_IRUGO|S_IWUSR,
536 show_fan_full_speed,
537 store_fan_full_speed, 0, 3),
538 SENSOR_ATTR_2(fan4_alarm, S_IRUGO, show_fan_alarm, NULL, 0, 3),
539 SENSOR_ATTR_2(pwm4, S_IRUGO|S_IWUSR, show_pwm, store_pwm, 0, 3),
540 SENSOR_ATTR_2(pwm4_enable, S_IRUGO|S_IWUSR, show_pwm_enable,
541 store_pwm_enable, 0, 3),
542 SENSOR_ATTR_2(pwm4_interpolate, S_IRUGO|S_IWUSR,
543 show_pwm_interpolate, store_pwm_interpolate, 0, 3),
544} };
Hans de Goede498be962009-01-07 16:37:28 +0100545
Hans de Goede66344aa2009-12-09 20:35:59 +0100546/* Attr for models which can beep on Fan alarm */
547static struct sensor_device_attribute_2 fxxxx_fan_beep_attr[] = {
Hans de Goedeed4f7c22009-01-07 16:37:30 +0100548 SENSOR_ATTR_2(fan1_beep, S_IRUGO|S_IWUSR, show_fan_beep,
549 store_fan_beep, 0, 0),
550 SENSOR_ATTR_2(fan2_beep, S_IRUGO|S_IWUSR, show_fan_beep,
551 store_fan_beep, 0, 1),
552 SENSOR_ATTR_2(fan3_beep, S_IRUGO|S_IWUSR, show_fan_beep,
553 store_fan_beep, 0, 2),
Hans de Goedeb69b0392009-12-09 20:36:00 +0100554 SENSOR_ATTR_2(fan4_beep, S_IRUGO|S_IWUSR, show_fan_beep,
555 store_fan_beep, 0, 3),
Hans de Goede66344aa2009-12-09 20:35:59 +0100556};
Hans de Goedeed4f7c22009-01-07 16:37:30 +0100557
Hans de Goede66344aa2009-12-09 20:35:59 +0100558/* PWM attr for the f71862fg, fewer pwms and fewer zones per pwm than the
Hans de Goede3cad4022011-03-09 20:57:14 +0100559 standard models */
Hans de Goede66344aa2009-12-09 20:35:59 +0100560static struct sensor_device_attribute_2 f71862fg_auto_pwm_attr[] = {
561 SENSOR_ATTR_2(pwm1_auto_channels_temp, S_IRUGO|S_IWUSR,
562 show_pwm_auto_point_channel,
563 store_pwm_auto_point_channel, 0, 0),
Hans de Goede498be962009-01-07 16:37:28 +0100564 SENSOR_ATTR_2(pwm1_auto_point1_pwm, S_IRUGO|S_IWUSR,
565 show_pwm_auto_point_pwm, store_pwm_auto_point_pwm,
566 1, 0),
567 SENSOR_ATTR_2(pwm1_auto_point2_pwm, S_IRUGO|S_IWUSR,
568 show_pwm_auto_point_pwm, store_pwm_auto_point_pwm,
569 4, 0),
570 SENSOR_ATTR_2(pwm1_auto_point1_temp, S_IRUGO|S_IWUSR,
571 show_pwm_auto_point_temp, store_pwm_auto_point_temp,
572 0, 0),
573 SENSOR_ATTR_2(pwm1_auto_point2_temp, S_IRUGO|S_IWUSR,
574 show_pwm_auto_point_temp, store_pwm_auto_point_temp,
575 3, 0),
576 SENSOR_ATTR_2(pwm1_auto_point1_temp_hyst, S_IRUGO|S_IWUSR,
577 show_pwm_auto_point_temp_hyst,
578 store_pwm_auto_point_temp_hyst,
579 0, 0),
580 SENSOR_ATTR_2(pwm1_auto_point2_temp_hyst, S_IRUGO,
581 show_pwm_auto_point_temp_hyst, NULL, 3, 0),
582
Hans de Goede66344aa2009-12-09 20:35:59 +0100583 SENSOR_ATTR_2(pwm2_auto_channels_temp, S_IRUGO|S_IWUSR,
584 show_pwm_auto_point_channel,
585 store_pwm_auto_point_channel, 0, 1),
Hans de Goede498be962009-01-07 16:37:28 +0100586 SENSOR_ATTR_2(pwm2_auto_point1_pwm, S_IRUGO|S_IWUSR,
587 show_pwm_auto_point_pwm, store_pwm_auto_point_pwm,
588 1, 1),
589 SENSOR_ATTR_2(pwm2_auto_point2_pwm, S_IRUGO|S_IWUSR,
590 show_pwm_auto_point_pwm, store_pwm_auto_point_pwm,
591 4, 1),
592 SENSOR_ATTR_2(pwm2_auto_point1_temp, S_IRUGO|S_IWUSR,
593 show_pwm_auto_point_temp, store_pwm_auto_point_temp,
594 0, 1),
595 SENSOR_ATTR_2(pwm2_auto_point2_temp, S_IRUGO|S_IWUSR,
596 show_pwm_auto_point_temp, store_pwm_auto_point_temp,
597 3, 1),
598 SENSOR_ATTR_2(pwm2_auto_point1_temp_hyst, S_IRUGO|S_IWUSR,
599 show_pwm_auto_point_temp_hyst,
600 store_pwm_auto_point_temp_hyst,
601 0, 1),
602 SENSOR_ATTR_2(pwm2_auto_point2_temp_hyst, S_IRUGO,
603 show_pwm_auto_point_temp_hyst, NULL, 3, 1),
Hans de Goede49010622009-01-07 16:37:30 +0100604
Hans de Goede66344aa2009-12-09 20:35:59 +0100605 SENSOR_ATTR_2(pwm3_auto_channels_temp, S_IRUGO|S_IWUSR,
606 show_pwm_auto_point_channel,
607 store_pwm_auto_point_channel, 0, 2),
Hans de Goede49010622009-01-07 16:37:30 +0100608 SENSOR_ATTR_2(pwm3_auto_point1_pwm, S_IRUGO|S_IWUSR,
609 show_pwm_auto_point_pwm, store_pwm_auto_point_pwm,
610 1, 2),
611 SENSOR_ATTR_2(pwm3_auto_point2_pwm, S_IRUGO|S_IWUSR,
612 show_pwm_auto_point_pwm, store_pwm_auto_point_pwm,
613 4, 2),
614 SENSOR_ATTR_2(pwm3_auto_point1_temp, S_IRUGO|S_IWUSR,
615 show_pwm_auto_point_temp, store_pwm_auto_point_temp,
616 0, 2),
617 SENSOR_ATTR_2(pwm3_auto_point2_temp, S_IRUGO|S_IWUSR,
618 show_pwm_auto_point_temp, store_pwm_auto_point_temp,
619 3, 2),
620 SENSOR_ATTR_2(pwm3_auto_point1_temp_hyst, S_IRUGO|S_IWUSR,
621 show_pwm_auto_point_temp_hyst,
622 store_pwm_auto_point_temp_hyst,
623 0, 2),
624 SENSOR_ATTR_2(pwm3_auto_point2_temp_hyst, S_IRUGO,
625 show_pwm_auto_point_temp_hyst, NULL, 3, 2),
Hans de Goede498be962009-01-07 16:37:28 +0100626};
627
Hans de Goedee5e713c2011-03-10 08:54:02 +0100628/* PWM attr for the f71808e/f71869, almost identical to the f71862fg, but the
Hans de Goedec11bb992011-03-09 20:57:15 +0100629 pwm setting when the temperature is above the pwmX_auto_point1_temp can be
630 programmed instead of being hardcoded to 0xff */
631static struct sensor_device_attribute_2 f71869_auto_pwm_attr[] = {
632 SENSOR_ATTR_2(pwm1_auto_channels_temp, S_IRUGO|S_IWUSR,
633 show_pwm_auto_point_channel,
634 store_pwm_auto_point_channel, 0, 0),
635 SENSOR_ATTR_2(pwm1_auto_point1_pwm, S_IRUGO|S_IWUSR,
636 show_pwm_auto_point_pwm, store_pwm_auto_point_pwm,
637 0, 0),
638 SENSOR_ATTR_2(pwm1_auto_point2_pwm, S_IRUGO|S_IWUSR,
639 show_pwm_auto_point_pwm, store_pwm_auto_point_pwm,
640 1, 0),
641 SENSOR_ATTR_2(pwm1_auto_point3_pwm, S_IRUGO|S_IWUSR,
642 show_pwm_auto_point_pwm, store_pwm_auto_point_pwm,
643 4, 0),
644 SENSOR_ATTR_2(pwm1_auto_point1_temp, S_IRUGO|S_IWUSR,
645 show_pwm_auto_point_temp, store_pwm_auto_point_temp,
646 0, 0),
647 SENSOR_ATTR_2(pwm1_auto_point2_temp, S_IRUGO|S_IWUSR,
648 show_pwm_auto_point_temp, store_pwm_auto_point_temp,
649 3, 0),
650 SENSOR_ATTR_2(pwm1_auto_point1_temp_hyst, S_IRUGO|S_IWUSR,
651 show_pwm_auto_point_temp_hyst,
652 store_pwm_auto_point_temp_hyst,
653 0, 0),
654 SENSOR_ATTR_2(pwm1_auto_point2_temp_hyst, S_IRUGO,
655 show_pwm_auto_point_temp_hyst, NULL, 3, 0),
656
657 SENSOR_ATTR_2(pwm2_auto_channels_temp, S_IRUGO|S_IWUSR,
658 show_pwm_auto_point_channel,
659 store_pwm_auto_point_channel, 0, 1),
660 SENSOR_ATTR_2(pwm2_auto_point1_pwm, S_IRUGO|S_IWUSR,
661 show_pwm_auto_point_pwm, store_pwm_auto_point_pwm,
662 0, 1),
663 SENSOR_ATTR_2(pwm2_auto_point2_pwm, S_IRUGO|S_IWUSR,
664 show_pwm_auto_point_pwm, store_pwm_auto_point_pwm,
665 1, 1),
666 SENSOR_ATTR_2(pwm2_auto_point3_pwm, S_IRUGO|S_IWUSR,
667 show_pwm_auto_point_pwm, store_pwm_auto_point_pwm,
668 4, 1),
669 SENSOR_ATTR_2(pwm2_auto_point1_temp, S_IRUGO|S_IWUSR,
670 show_pwm_auto_point_temp, store_pwm_auto_point_temp,
671 0, 1),
672 SENSOR_ATTR_2(pwm2_auto_point2_temp, S_IRUGO|S_IWUSR,
673 show_pwm_auto_point_temp, store_pwm_auto_point_temp,
674 3, 1),
675 SENSOR_ATTR_2(pwm2_auto_point1_temp_hyst, S_IRUGO|S_IWUSR,
676 show_pwm_auto_point_temp_hyst,
677 store_pwm_auto_point_temp_hyst,
678 0, 1),
679 SENSOR_ATTR_2(pwm2_auto_point2_temp_hyst, S_IRUGO,
680 show_pwm_auto_point_temp_hyst, NULL, 3, 1),
681
682 SENSOR_ATTR_2(pwm3_auto_channels_temp, S_IRUGO|S_IWUSR,
683 show_pwm_auto_point_channel,
684 store_pwm_auto_point_channel, 0, 2),
685 SENSOR_ATTR_2(pwm3_auto_point1_pwm, S_IRUGO|S_IWUSR,
686 show_pwm_auto_point_pwm, store_pwm_auto_point_pwm,
687 0, 2),
688 SENSOR_ATTR_2(pwm3_auto_point2_pwm, S_IRUGO|S_IWUSR,
689 show_pwm_auto_point_pwm, store_pwm_auto_point_pwm,
690 1, 2),
691 SENSOR_ATTR_2(pwm3_auto_point3_pwm, S_IRUGO|S_IWUSR,
692 show_pwm_auto_point_pwm, store_pwm_auto_point_pwm,
693 4, 2),
694 SENSOR_ATTR_2(pwm3_auto_point1_temp, S_IRUGO|S_IWUSR,
695 show_pwm_auto_point_temp, store_pwm_auto_point_temp,
696 0, 2),
697 SENSOR_ATTR_2(pwm3_auto_point2_temp, S_IRUGO|S_IWUSR,
698 show_pwm_auto_point_temp, store_pwm_auto_point_temp,
699 3, 2),
700 SENSOR_ATTR_2(pwm3_auto_point1_temp_hyst, S_IRUGO|S_IWUSR,
701 show_pwm_auto_point_temp_hyst,
702 store_pwm_auto_point_temp_hyst,
703 0, 2),
704 SENSOR_ATTR_2(pwm3_auto_point2_temp_hyst, S_IRUGO,
705 show_pwm_auto_point_temp_hyst, NULL, 3, 2),
706};
707
Hans de Goede3cad4022011-03-09 20:57:14 +0100708/* PWM attr for the standard models */
Hans de Goedeb69b0392009-12-09 20:36:00 +0100709static struct sensor_device_attribute_2 fxxxx_auto_pwm_attr[4][14] = { {
Hans de Goede66344aa2009-12-09 20:35:59 +0100710 SENSOR_ATTR_2(pwm1_auto_channels_temp, S_IRUGO|S_IWUSR,
711 show_pwm_auto_point_channel,
712 store_pwm_auto_point_channel, 0, 0),
Mark van Doesburg9ab796e2009-01-07 16:37:27 +0100713 SENSOR_ATTR_2(pwm1_auto_point1_pwm, S_IRUGO|S_IWUSR,
714 show_pwm_auto_point_pwm, store_pwm_auto_point_pwm,
715 0, 0),
716 SENSOR_ATTR_2(pwm1_auto_point2_pwm, S_IRUGO|S_IWUSR,
717 show_pwm_auto_point_pwm, store_pwm_auto_point_pwm,
718 1, 0),
719 SENSOR_ATTR_2(pwm1_auto_point3_pwm, S_IRUGO|S_IWUSR,
720 show_pwm_auto_point_pwm, store_pwm_auto_point_pwm,
721 2, 0),
722 SENSOR_ATTR_2(pwm1_auto_point4_pwm, S_IRUGO|S_IWUSR,
723 show_pwm_auto_point_pwm, store_pwm_auto_point_pwm,
724 3, 0),
725 SENSOR_ATTR_2(pwm1_auto_point5_pwm, S_IRUGO|S_IWUSR,
726 show_pwm_auto_point_pwm, store_pwm_auto_point_pwm,
727 4, 0),
728 SENSOR_ATTR_2(pwm1_auto_point1_temp, S_IRUGO|S_IWUSR,
729 show_pwm_auto_point_temp, store_pwm_auto_point_temp,
730 0, 0),
731 SENSOR_ATTR_2(pwm1_auto_point2_temp, S_IRUGO|S_IWUSR,
732 show_pwm_auto_point_temp, store_pwm_auto_point_temp,
733 1, 0),
734 SENSOR_ATTR_2(pwm1_auto_point3_temp, S_IRUGO|S_IWUSR,
735 show_pwm_auto_point_temp, store_pwm_auto_point_temp,
736 2, 0),
737 SENSOR_ATTR_2(pwm1_auto_point4_temp, S_IRUGO|S_IWUSR,
738 show_pwm_auto_point_temp, store_pwm_auto_point_temp,
739 3, 0),
740 SENSOR_ATTR_2(pwm1_auto_point1_temp_hyst, S_IRUGO|S_IWUSR,
741 show_pwm_auto_point_temp_hyst,
742 store_pwm_auto_point_temp_hyst,
743 0, 0),
744 SENSOR_ATTR_2(pwm1_auto_point2_temp_hyst, S_IRUGO,
745 show_pwm_auto_point_temp_hyst, NULL, 1, 0),
746 SENSOR_ATTR_2(pwm1_auto_point3_temp_hyst, S_IRUGO,
747 show_pwm_auto_point_temp_hyst, NULL, 2, 0),
748 SENSOR_ATTR_2(pwm1_auto_point4_temp_hyst, S_IRUGO,
749 show_pwm_auto_point_temp_hyst, NULL, 3, 0),
Hans de Goedeb69b0392009-12-09 20:36:00 +0100750}, {
Hans de Goede66344aa2009-12-09 20:35:59 +0100751 SENSOR_ATTR_2(pwm2_auto_channels_temp, S_IRUGO|S_IWUSR,
752 show_pwm_auto_point_channel,
753 store_pwm_auto_point_channel, 0, 1),
Mark van Doesburg9ab796e2009-01-07 16:37:27 +0100754 SENSOR_ATTR_2(pwm2_auto_point1_pwm, S_IRUGO|S_IWUSR,
755 show_pwm_auto_point_pwm, store_pwm_auto_point_pwm,
756 0, 1),
757 SENSOR_ATTR_2(pwm2_auto_point2_pwm, S_IRUGO|S_IWUSR,
758 show_pwm_auto_point_pwm, store_pwm_auto_point_pwm,
759 1, 1),
760 SENSOR_ATTR_2(pwm2_auto_point3_pwm, S_IRUGO|S_IWUSR,
761 show_pwm_auto_point_pwm, store_pwm_auto_point_pwm,
762 2, 1),
763 SENSOR_ATTR_2(pwm2_auto_point4_pwm, S_IRUGO|S_IWUSR,
764 show_pwm_auto_point_pwm, store_pwm_auto_point_pwm,
765 3, 1),
766 SENSOR_ATTR_2(pwm2_auto_point5_pwm, S_IRUGO|S_IWUSR,
767 show_pwm_auto_point_pwm, store_pwm_auto_point_pwm,
768 4, 1),
769 SENSOR_ATTR_2(pwm2_auto_point1_temp, S_IRUGO|S_IWUSR,
770 show_pwm_auto_point_temp, store_pwm_auto_point_temp,
771 0, 1),
772 SENSOR_ATTR_2(pwm2_auto_point2_temp, S_IRUGO|S_IWUSR,
773 show_pwm_auto_point_temp, store_pwm_auto_point_temp,
774 1, 1),
775 SENSOR_ATTR_2(pwm2_auto_point3_temp, S_IRUGO|S_IWUSR,
776 show_pwm_auto_point_temp, store_pwm_auto_point_temp,
777 2, 1),
778 SENSOR_ATTR_2(pwm2_auto_point4_temp, S_IRUGO|S_IWUSR,
779 show_pwm_auto_point_temp, store_pwm_auto_point_temp,
780 3, 1),
781 SENSOR_ATTR_2(pwm2_auto_point1_temp_hyst, S_IRUGO|S_IWUSR,
782 show_pwm_auto_point_temp_hyst,
783 store_pwm_auto_point_temp_hyst,
784 0, 1),
785 SENSOR_ATTR_2(pwm2_auto_point2_temp_hyst, S_IRUGO,
786 show_pwm_auto_point_temp_hyst, NULL, 1, 1),
787 SENSOR_ATTR_2(pwm2_auto_point3_temp_hyst, S_IRUGO,
788 show_pwm_auto_point_temp_hyst, NULL, 2, 1),
789 SENSOR_ATTR_2(pwm2_auto_point4_temp_hyst, S_IRUGO,
790 show_pwm_auto_point_temp_hyst, NULL, 3, 1),
Hans de Goedeb69b0392009-12-09 20:36:00 +0100791}, {
Hans de Goede66344aa2009-12-09 20:35:59 +0100792 SENSOR_ATTR_2(pwm3_auto_channels_temp, S_IRUGO|S_IWUSR,
793 show_pwm_auto_point_channel,
794 store_pwm_auto_point_channel, 0, 2),
Mark van Doesburg9ab796e2009-01-07 16:37:27 +0100795 SENSOR_ATTR_2(pwm3_auto_point1_pwm, S_IRUGO|S_IWUSR,
796 show_pwm_auto_point_pwm, store_pwm_auto_point_pwm,
797 0, 2),
798 SENSOR_ATTR_2(pwm3_auto_point2_pwm, S_IRUGO|S_IWUSR,
799 show_pwm_auto_point_pwm, store_pwm_auto_point_pwm,
800 1, 2),
801 SENSOR_ATTR_2(pwm3_auto_point3_pwm, S_IRUGO|S_IWUSR,
802 show_pwm_auto_point_pwm, store_pwm_auto_point_pwm,
803 2, 2),
804 SENSOR_ATTR_2(pwm3_auto_point4_pwm, S_IRUGO|S_IWUSR,
805 show_pwm_auto_point_pwm, store_pwm_auto_point_pwm,
806 3, 2),
807 SENSOR_ATTR_2(pwm3_auto_point5_pwm, S_IRUGO|S_IWUSR,
808 show_pwm_auto_point_pwm, store_pwm_auto_point_pwm,
809 4, 2),
810 SENSOR_ATTR_2(pwm3_auto_point1_temp, S_IRUGO|S_IWUSR,
811 show_pwm_auto_point_temp, store_pwm_auto_point_temp,
812 0, 2),
813 SENSOR_ATTR_2(pwm3_auto_point2_temp, S_IRUGO|S_IWUSR,
814 show_pwm_auto_point_temp, store_pwm_auto_point_temp,
815 1, 2),
816 SENSOR_ATTR_2(pwm3_auto_point3_temp, S_IRUGO|S_IWUSR,
817 show_pwm_auto_point_temp, store_pwm_auto_point_temp,
818 2, 2),
819 SENSOR_ATTR_2(pwm3_auto_point4_temp, S_IRUGO|S_IWUSR,
820 show_pwm_auto_point_temp, store_pwm_auto_point_temp,
821 3, 2),
822 SENSOR_ATTR_2(pwm3_auto_point1_temp_hyst, S_IRUGO|S_IWUSR,
823 show_pwm_auto_point_temp_hyst,
824 store_pwm_auto_point_temp_hyst,
825 0, 2),
826 SENSOR_ATTR_2(pwm3_auto_point2_temp_hyst, S_IRUGO,
827 show_pwm_auto_point_temp_hyst, NULL, 1, 2),
828 SENSOR_ATTR_2(pwm3_auto_point3_temp_hyst, S_IRUGO,
829 show_pwm_auto_point_temp_hyst, NULL, 2, 2),
830 SENSOR_ATTR_2(pwm3_auto_point4_temp_hyst, S_IRUGO,
831 show_pwm_auto_point_temp_hyst, NULL, 3, 2),
Hans de Goedeb69b0392009-12-09 20:36:00 +0100832}, {
Mark van Doesburg9ab796e2009-01-07 16:37:27 +0100833 SENSOR_ATTR_2(pwm4_auto_channels_temp, S_IRUGO|S_IWUSR,
834 show_pwm_auto_point_channel,
835 store_pwm_auto_point_channel, 0, 3),
836 SENSOR_ATTR_2(pwm4_auto_point1_pwm, S_IRUGO|S_IWUSR,
837 show_pwm_auto_point_pwm, store_pwm_auto_point_pwm,
838 0, 3),
839 SENSOR_ATTR_2(pwm4_auto_point2_pwm, S_IRUGO|S_IWUSR,
840 show_pwm_auto_point_pwm, store_pwm_auto_point_pwm,
841 1, 3),
842 SENSOR_ATTR_2(pwm4_auto_point3_pwm, S_IRUGO|S_IWUSR,
843 show_pwm_auto_point_pwm, store_pwm_auto_point_pwm,
844 2, 3),
845 SENSOR_ATTR_2(pwm4_auto_point4_pwm, S_IRUGO|S_IWUSR,
846 show_pwm_auto_point_pwm, store_pwm_auto_point_pwm,
847 3, 3),
848 SENSOR_ATTR_2(pwm4_auto_point5_pwm, S_IRUGO|S_IWUSR,
849 show_pwm_auto_point_pwm, store_pwm_auto_point_pwm,
850 4, 3),
851 SENSOR_ATTR_2(pwm4_auto_point1_temp, S_IRUGO|S_IWUSR,
852 show_pwm_auto_point_temp, store_pwm_auto_point_temp,
853 0, 3),
854 SENSOR_ATTR_2(pwm4_auto_point2_temp, S_IRUGO|S_IWUSR,
855 show_pwm_auto_point_temp, store_pwm_auto_point_temp,
856 1, 3),
857 SENSOR_ATTR_2(pwm4_auto_point3_temp, S_IRUGO|S_IWUSR,
858 show_pwm_auto_point_temp, store_pwm_auto_point_temp,
859 2, 3),
860 SENSOR_ATTR_2(pwm4_auto_point4_temp, S_IRUGO|S_IWUSR,
861 show_pwm_auto_point_temp, store_pwm_auto_point_temp,
862 3, 3),
863 SENSOR_ATTR_2(pwm4_auto_point1_temp_hyst, S_IRUGO|S_IWUSR,
864 show_pwm_auto_point_temp_hyst,
865 store_pwm_auto_point_temp_hyst,
866 0, 3),
867 SENSOR_ATTR_2(pwm4_auto_point2_temp_hyst, S_IRUGO,
868 show_pwm_auto_point_temp_hyst, NULL, 1, 3),
869 SENSOR_ATTR_2(pwm4_auto_point3_temp_hyst, S_IRUGO,
870 show_pwm_auto_point_temp_hyst, NULL, 2, 3),
871 SENSOR_ATTR_2(pwm4_auto_point4_temp_hyst, S_IRUGO,
872 show_pwm_auto_point_temp_hyst, NULL, 3, 3),
Hans de Goedeb69b0392009-12-09 20:36:00 +0100873} };
Hans de Goede45fb3662007-07-13 14:34:19 +0200874
Hans de Goede66344aa2009-12-09 20:35:59 +0100875/* Fan attr specific to the f8000 (4th fan input can only measure speed) */
Hans de Goedeed4f7c22009-01-07 16:37:30 +0100876static struct sensor_device_attribute_2 f8000_fan_attr[] = {
877 SENSOR_ATTR_2(fan4_input, S_IRUGO, show_fan, NULL, 0, 3),
Hans de Goede66344aa2009-12-09 20:35:59 +0100878};
Hans de Goedeed4f7c22009-01-07 16:37:30 +0100879
Hans de Goede66344aa2009-12-09 20:35:59 +0100880/* PWM attr for the f8000, zones mapped to temp instead of to pwm!
881 Also the register block at offset A0 maps to TEMP1 (so our temp2, as the
882 F8000 starts counting temps at 0), B0 maps the TEMP2 and C0 maps to TEMP0 */
883static struct sensor_device_attribute_2 f8000_auto_pwm_attr[] = {
884 SENSOR_ATTR_2(pwm1_auto_channels_temp, S_IRUGO|S_IWUSR,
885 show_pwm_auto_point_channel,
886 store_pwm_auto_point_channel, 0, 0),
Hans de Goedeed4f7c22009-01-07 16:37:30 +0100887 SENSOR_ATTR_2(temp1_auto_point1_pwm, S_IRUGO|S_IWUSR,
888 show_pwm_auto_point_pwm, store_pwm_auto_point_pwm,
889 0, 2),
890 SENSOR_ATTR_2(temp1_auto_point2_pwm, S_IRUGO|S_IWUSR,
891 show_pwm_auto_point_pwm, store_pwm_auto_point_pwm,
892 1, 2),
893 SENSOR_ATTR_2(temp1_auto_point3_pwm, S_IRUGO|S_IWUSR,
894 show_pwm_auto_point_pwm, store_pwm_auto_point_pwm,
895 2, 2),
896 SENSOR_ATTR_2(temp1_auto_point4_pwm, S_IRUGO|S_IWUSR,
897 show_pwm_auto_point_pwm, store_pwm_auto_point_pwm,
898 3, 2),
899 SENSOR_ATTR_2(temp1_auto_point5_pwm, S_IRUGO|S_IWUSR,
900 show_pwm_auto_point_pwm, store_pwm_auto_point_pwm,
901 4, 2),
902 SENSOR_ATTR_2(temp1_auto_point1_temp, S_IRUGO|S_IWUSR,
903 show_pwm_auto_point_temp, store_pwm_auto_point_temp,
904 0, 2),
905 SENSOR_ATTR_2(temp1_auto_point2_temp, S_IRUGO|S_IWUSR,
906 show_pwm_auto_point_temp, store_pwm_auto_point_temp,
907 1, 2),
908 SENSOR_ATTR_2(temp1_auto_point3_temp, S_IRUGO|S_IWUSR,
909 show_pwm_auto_point_temp, store_pwm_auto_point_temp,
910 2, 2),
911 SENSOR_ATTR_2(temp1_auto_point4_temp, S_IRUGO|S_IWUSR,
912 show_pwm_auto_point_temp, store_pwm_auto_point_temp,
913 3, 2),
914 SENSOR_ATTR_2(temp1_auto_point1_temp_hyst, S_IRUGO|S_IWUSR,
915 show_pwm_auto_point_temp_hyst,
916 store_pwm_auto_point_temp_hyst,
917 0, 2),
918 SENSOR_ATTR_2(temp1_auto_point2_temp_hyst, S_IRUGO,
919 show_pwm_auto_point_temp_hyst, NULL, 1, 2),
920 SENSOR_ATTR_2(temp1_auto_point3_temp_hyst, S_IRUGO,
921 show_pwm_auto_point_temp_hyst, NULL, 2, 2),
922 SENSOR_ATTR_2(temp1_auto_point4_temp_hyst, S_IRUGO,
923 show_pwm_auto_point_temp_hyst, NULL, 3, 2),
924
Hans de Goede66344aa2009-12-09 20:35:59 +0100925 SENSOR_ATTR_2(pwm2_auto_channels_temp, S_IRUGO|S_IWUSR,
926 show_pwm_auto_point_channel,
927 store_pwm_auto_point_channel, 0, 1),
Hans de Goedeed4f7c22009-01-07 16:37:30 +0100928 SENSOR_ATTR_2(temp2_auto_point1_pwm, S_IRUGO|S_IWUSR,
929 show_pwm_auto_point_pwm, store_pwm_auto_point_pwm,
930 0, 0),
931 SENSOR_ATTR_2(temp2_auto_point2_pwm, S_IRUGO|S_IWUSR,
932 show_pwm_auto_point_pwm, store_pwm_auto_point_pwm,
933 1, 0),
934 SENSOR_ATTR_2(temp2_auto_point3_pwm, S_IRUGO|S_IWUSR,
935 show_pwm_auto_point_pwm, store_pwm_auto_point_pwm,
936 2, 0),
937 SENSOR_ATTR_2(temp2_auto_point4_pwm, S_IRUGO|S_IWUSR,
938 show_pwm_auto_point_pwm, store_pwm_auto_point_pwm,
939 3, 0),
940 SENSOR_ATTR_2(temp2_auto_point5_pwm, S_IRUGO|S_IWUSR,
941 show_pwm_auto_point_pwm, store_pwm_auto_point_pwm,
942 4, 0),
943 SENSOR_ATTR_2(temp2_auto_point1_temp, S_IRUGO|S_IWUSR,
944 show_pwm_auto_point_temp, store_pwm_auto_point_temp,
945 0, 0),
946 SENSOR_ATTR_2(temp2_auto_point2_temp, S_IRUGO|S_IWUSR,
947 show_pwm_auto_point_temp, store_pwm_auto_point_temp,
948 1, 0),
949 SENSOR_ATTR_2(temp2_auto_point3_temp, S_IRUGO|S_IWUSR,
950 show_pwm_auto_point_temp, store_pwm_auto_point_temp,
951 2, 0),
952 SENSOR_ATTR_2(temp2_auto_point4_temp, S_IRUGO|S_IWUSR,
953 show_pwm_auto_point_temp, store_pwm_auto_point_temp,
954 3, 0),
955 SENSOR_ATTR_2(temp2_auto_point1_temp_hyst, S_IRUGO|S_IWUSR,
956 show_pwm_auto_point_temp_hyst,
957 store_pwm_auto_point_temp_hyst,
958 0, 0),
959 SENSOR_ATTR_2(temp2_auto_point2_temp_hyst, S_IRUGO,
960 show_pwm_auto_point_temp_hyst, NULL, 1, 0),
961 SENSOR_ATTR_2(temp2_auto_point3_temp_hyst, S_IRUGO,
962 show_pwm_auto_point_temp_hyst, NULL, 2, 0),
963 SENSOR_ATTR_2(temp2_auto_point4_temp_hyst, S_IRUGO,
964 show_pwm_auto_point_temp_hyst, NULL, 3, 0),
965
Hans de Goede66344aa2009-12-09 20:35:59 +0100966 SENSOR_ATTR_2(pwm3_auto_channels_temp, S_IRUGO|S_IWUSR,
967 show_pwm_auto_point_channel,
968 store_pwm_auto_point_channel, 0, 2),
Hans de Goedeed4f7c22009-01-07 16:37:30 +0100969 SENSOR_ATTR_2(temp3_auto_point1_pwm, S_IRUGO|S_IWUSR,
970 show_pwm_auto_point_pwm, store_pwm_auto_point_pwm,
971 0, 1),
972 SENSOR_ATTR_2(temp3_auto_point2_pwm, S_IRUGO|S_IWUSR,
973 show_pwm_auto_point_pwm, store_pwm_auto_point_pwm,
974 1, 1),
975 SENSOR_ATTR_2(temp3_auto_point3_pwm, S_IRUGO|S_IWUSR,
976 show_pwm_auto_point_pwm, store_pwm_auto_point_pwm,
977 2, 1),
978 SENSOR_ATTR_2(temp3_auto_point4_pwm, S_IRUGO|S_IWUSR,
979 show_pwm_auto_point_pwm, store_pwm_auto_point_pwm,
980 3, 1),
981 SENSOR_ATTR_2(temp3_auto_point5_pwm, S_IRUGO|S_IWUSR,
982 show_pwm_auto_point_pwm, store_pwm_auto_point_pwm,
983 4, 1),
984 SENSOR_ATTR_2(temp3_auto_point1_temp, S_IRUGO|S_IWUSR,
985 show_pwm_auto_point_temp, store_pwm_auto_point_temp,
986 0, 1),
987 SENSOR_ATTR_2(temp3_auto_point2_temp, S_IRUGO|S_IWUSR,
988 show_pwm_auto_point_temp, store_pwm_auto_point_temp,
989 1, 1),
990 SENSOR_ATTR_2(temp3_auto_point3_temp, S_IRUGO|S_IWUSR,
991 show_pwm_auto_point_temp, store_pwm_auto_point_temp,
992 2, 1),
993 SENSOR_ATTR_2(temp3_auto_point4_temp, S_IRUGO|S_IWUSR,
994 show_pwm_auto_point_temp, store_pwm_auto_point_temp,
995 3, 1),
996 SENSOR_ATTR_2(temp3_auto_point1_temp_hyst, S_IRUGO|S_IWUSR,
997 show_pwm_auto_point_temp_hyst,
998 store_pwm_auto_point_temp_hyst,
999 0, 1),
1000 SENSOR_ATTR_2(temp3_auto_point2_temp_hyst, S_IRUGO,
1001 show_pwm_auto_point_temp_hyst, NULL, 1, 1),
1002 SENSOR_ATTR_2(temp3_auto_point3_temp_hyst, S_IRUGO,
1003 show_pwm_auto_point_temp_hyst, NULL, 2, 1),
1004 SENSOR_ATTR_2(temp3_auto_point4_temp_hyst, S_IRUGO,
1005 show_pwm_auto_point_temp_hyst, NULL, 3, 1),
1006};
Hans de Goede45fb3662007-07-13 14:34:19 +02001007
1008/* Super I/O functions */
1009static inline int superio_inb(int base, int reg)
1010{
1011 outb(reg, base);
1012 return inb(base + 1);
1013}
1014
1015static int superio_inw(int base, int reg)
1016{
1017 int val;
Giel van Schijndelbd328ac2010-05-27 19:58:42 +02001018 val = superio_inb(base, reg) << 8;
1019 val |= superio_inb(base, reg + 1);
Hans de Goede45fb3662007-07-13 14:34:19 +02001020 return val;
1021}
1022
Giel van Schijndelcadb8652010-10-03 08:09:49 -04001023static inline int superio_enter(int base)
Hans de Goede45fb3662007-07-13 14:34:19 +02001024{
Giel van Schijndelcadb8652010-10-03 08:09:49 -04001025 /* Don't step on other drivers' I/O space by accident */
1026 if (!request_muxed_region(base, 2, DRVNAME)) {
Joe Perches22d3b412010-10-20 06:51:34 +00001027 pr_err("I/O address 0x%04x already in use\n", base);
Giel van Schijndelcadb8652010-10-03 08:09:49 -04001028 return -EBUSY;
1029 }
1030
Hans de Goede45fb3662007-07-13 14:34:19 +02001031 /* according to the datasheet the key must be send twice! */
Giel van Schijndel162bb592010-05-27 19:58:40 +02001032 outb(SIO_UNLOCK_KEY, base);
1033 outb(SIO_UNLOCK_KEY, base);
Giel van Schijndelcadb8652010-10-03 08:09:49 -04001034
1035 return 0;
Hans de Goede45fb3662007-07-13 14:34:19 +02001036}
1037
Giel van Schijndel162bb592010-05-27 19:58:40 +02001038static inline void superio_select(int base, int ld)
Hans de Goede45fb3662007-07-13 14:34:19 +02001039{
1040 outb(SIO_REG_LDSEL, base);
1041 outb(ld, base + 1);
1042}
1043
1044static inline void superio_exit(int base)
1045{
1046 outb(SIO_LOCK_KEY, base);
Giel van Schijndelcadb8652010-10-03 08:09:49 -04001047 release_region(base, 2);
Hans de Goede45fb3662007-07-13 14:34:19 +02001048}
1049
Hans de Goede2f650632009-01-07 16:37:31 +01001050static inline int fan_from_reg(u16 reg)
Hans de Goede45fb3662007-07-13 14:34:19 +02001051{
1052 return reg ? (1500000 / reg) : 0;
1053}
1054
Hans de Goede2f650632009-01-07 16:37:31 +01001055static inline u16 fan_to_reg(int fan)
Mark van Doesburg9ab796e2009-01-07 16:37:27 +01001056{
1057 return fan ? (1500000 / fan) : 0;
1058}
1059
Hans de Goede45fb3662007-07-13 14:34:19 +02001060static u8 f71882fg_read8(struct f71882fg_data *data, u8 reg)
1061{
1062 u8 val;
1063
1064 outb(reg, data->addr + ADDR_REG_OFFSET);
1065 val = inb(data->addr + DATA_REG_OFFSET);
1066
1067 return val;
1068}
1069
1070static u16 f71882fg_read16(struct f71882fg_data *data, u8 reg)
1071{
1072 u16 val;
1073
Giel van Schijndelbd328ac2010-05-27 19:58:42 +02001074 val = f71882fg_read8(data, reg) << 8;
1075 val |= f71882fg_read8(data, reg + 1);
Hans de Goede45fb3662007-07-13 14:34:19 +02001076
1077 return val;
1078}
1079
1080static void f71882fg_write8(struct f71882fg_data *data, u8 reg, u8 val)
1081{
1082 outb(reg, data->addr + ADDR_REG_OFFSET);
1083 outb(val, data->addr + DATA_REG_OFFSET);
1084}
1085
Mark van Doesburg9ab796e2009-01-07 16:37:27 +01001086static void f71882fg_write16(struct f71882fg_data *data, u8 reg, u16 val)
1087{
Giel van Schijndelbd328ac2010-05-27 19:58:42 +02001088 f71882fg_write8(data, reg, val >> 8);
1089 f71882fg_write8(data, reg + 1, val & 0xff);
Mark van Doesburg9ab796e2009-01-07 16:37:27 +01001090}
1091
Hans de Goede09475d32009-06-15 18:39:52 +02001092static u16 f71882fg_read_temp(struct f71882fg_data *data, int nr)
1093{
1094 if (data->type == f71858fg)
1095 return f71882fg_read16(data, F71882FG_REG_TEMP(nr));
1096 else
1097 return f71882fg_read8(data, F71882FG_REG_TEMP(nr));
1098}
1099
Mark van Doesburg77a4a3e2009-01-07 16:37:27 +01001100static struct f71882fg_data *f71882fg_update_device(struct device *dev)
Hans de Goede45fb3662007-07-13 14:34:19 +02001101{
1102 struct f71882fg_data *data = dev_get_drvdata(dev);
Jean Delvaref27def02011-03-26 10:45:01 +01001103 int nr_fans = f71882fg_nr_fans[data->type];
1104 int nr_temps = f71882fg_nr_temps[data->type];
Hans de Goedee5e713c2011-03-10 08:54:02 +01001105 int nr, reg, point;
Hans de Goede45fb3662007-07-13 14:34:19 +02001106
1107 mutex_lock(&data->update_lock);
1108
1109 /* Update once every 60 seconds */
Giel van Schijndel162bb592010-05-27 19:58:40 +02001110 if (time_after(jiffies, data->last_limits + 60 * HZ) ||
Hans de Goede45fb3662007-07-13 14:34:19 +02001111 !data->valid) {
Hans de Goede0bae6402011-03-09 20:57:10 +01001112 if (f71882fg_has_in1_alarm[data->type]) {
Hans de Goede498be962009-01-07 16:37:28 +01001113 data->in1_max =
1114 f71882fg_read8(data, F71882FG_REG_IN1_HIGH);
1115 data->in_beep =
1116 f71882fg_read8(data, F71882FG_REG_IN_BEEP);
1117 }
Hans de Goede45fb3662007-07-13 14:34:19 +02001118
1119 /* Get High & boundary temps*/
Hans de Goedee5e713c2011-03-10 08:54:02 +01001120 for (nr = data->temp_start; nr < nr_temps + data->temp_start;
1121 nr++) {
Hans de Goede45fb3662007-07-13 14:34:19 +02001122 data->temp_ovt[nr] = f71882fg_read8(data,
1123 F71882FG_REG_TEMP_OVT(nr));
1124 data->temp_high[nr] = f71882fg_read8(data,
1125 F71882FG_REG_TEMP_HIGH(nr));
1126 }
1127
Hans de Goedeed4f7c22009-01-07 16:37:30 +01001128 if (data->type != f8000) {
Hans de Goedeed4f7c22009-01-07 16:37:30 +01001129 data->temp_hyst[0] = f71882fg_read8(data,
1130 F71882FG_REG_TEMP_HYST(0));
1131 data->temp_hyst[1] = f71882fg_read8(data,
1132 F71882FG_REG_TEMP_HYST(1));
Hans de Goede09475d32009-06-15 18:39:52 +02001133 }
Hans de Goede78aa4f72011-03-09 20:57:12 +01001134 /* All but the f71858fg / f8000 have this register */
1135 if ((data->type != f71858fg) && (data->type != f8000)) {
Hans de Goedeed4f7c22009-01-07 16:37:30 +01001136 reg = f71882fg_read8(data, F71882FG_REG_TEMP_TYPE);
Hans de Goede44c4dc52011-03-09 20:57:07 +01001137 data->temp_type[1] = (reg & 0x02) ? 2 : 4;
Hans de Goedeed4f7c22009-01-07 16:37:30 +01001138 data->temp_type[2] = (reg & 0x04) ? 2 : 4;
1139 data->temp_type[3] = (reg & 0x08) ? 2 : 4;
1140 }
Hans de Goede45fb3662007-07-13 14:34:19 +02001141
Hans de Goede78aa4f72011-03-09 20:57:12 +01001142 if (f71882fg_has_beep[data->type]) {
1143 data->fan_beep = f71882fg_read8(data,
1144 F71882FG_REG_FAN_BEEP);
1145 data->temp_beep = f71882fg_read8(data,
1146 F71882FG_REG_TEMP_BEEP);
1147 }
1148
Mark van Doesburg9ab796e2009-01-07 16:37:27 +01001149 data->pwm_enable = f71882fg_read8(data,
1150 F71882FG_REG_PWM_ENABLE);
Hans de Goedebc274902009-01-07 16:37:29 +01001151 data->pwm_auto_point_hyst[0] =
1152 f71882fg_read8(data, F71882FG_REG_FAN_HYST(0));
1153 data->pwm_auto_point_hyst[1] =
1154 f71882fg_read8(data, F71882FG_REG_FAN_HYST(1));
1155
Hans de Goede498be962009-01-07 16:37:28 +01001156 for (nr = 0; nr < nr_fans; nr++) {
Mark van Doesburg9ab796e2009-01-07 16:37:27 +01001157 data->pwm_auto_point_mapping[nr] =
1158 f71882fg_read8(data,
1159 F71882FG_REG_POINT_MAPPING(nr));
1160
Hans de Goedee5e713c2011-03-10 08:54:02 +01001161 switch (data->type) {
1162 default:
Hans de Goede498be962009-01-07 16:37:28 +01001163 for (point = 0; point < 5; point++) {
1164 data->pwm_auto_point_pwm[nr][point] =
1165 f71882fg_read8(data,
1166 F71882FG_REG_POINT_PWM
1167 (nr, point));
1168 }
1169 for (point = 0; point < 4; point++) {
1170 data->pwm_auto_point_temp[nr][point] =
1171 f71882fg_read8(data,
1172 F71882FG_REG_POINT_TEMP
1173 (nr, point));
1174 }
Hans de Goedee5e713c2011-03-10 08:54:02 +01001175 break;
1176 case f71808e:
1177 case f71869:
1178 data->pwm_auto_point_pwm[nr][0] =
1179 f71882fg_read8(data,
1180 F71882FG_REG_POINT_PWM(nr, 0));
1181 /* Fall through */
1182 case f71862fg:
Hans de Goede498be962009-01-07 16:37:28 +01001183 data->pwm_auto_point_pwm[nr][1] =
1184 f71882fg_read8(data,
1185 F71882FG_REG_POINT_PWM
1186 (nr, 1));
1187 data->pwm_auto_point_pwm[nr][4] =
1188 f71882fg_read8(data,
1189 F71882FG_REG_POINT_PWM
1190 (nr, 4));
1191 data->pwm_auto_point_temp[nr][0] =
1192 f71882fg_read8(data,
1193 F71882FG_REG_POINT_TEMP
1194 (nr, 0));
1195 data->pwm_auto_point_temp[nr][3] =
1196 f71882fg_read8(data,
1197 F71882FG_REG_POINT_TEMP
1198 (nr, 3));
Hans de Goedee5e713c2011-03-10 08:54:02 +01001199 break;
Mark van Doesburg9ab796e2009-01-07 16:37:27 +01001200 }
1201 }
Hans de Goede45fb3662007-07-13 14:34:19 +02001202 data->last_limits = jiffies;
1203 }
1204
1205 /* Update every second */
Mark M. Hoffman8afb1042007-08-21 23:10:46 -04001206 if (time_after(jiffies, data->last_updated + HZ) || !data->valid) {
Hans de Goede45fb3662007-07-13 14:34:19 +02001207 data->temp_status = f71882fg_read8(data,
1208 F71882FG_REG_TEMP_STATUS);
1209 data->temp_diode_open = f71882fg_read8(data,
1210 F71882FG_REG_TEMP_DIODE_OPEN);
Hans de Goedee5e713c2011-03-10 08:54:02 +01001211 for (nr = data->temp_start; nr < nr_temps + data->temp_start;
1212 nr++)
Hans de Goede09475d32009-06-15 18:39:52 +02001213 data->temp[nr] = f71882fg_read_temp(data, nr);
Hans de Goede45fb3662007-07-13 14:34:19 +02001214
1215 data->fan_status = f71882fg_read8(data,
1216 F71882FG_REG_FAN_STATUS);
Hans de Goede498be962009-01-07 16:37:28 +01001217 for (nr = 0; nr < nr_fans; nr++) {
Hans de Goede45fb3662007-07-13 14:34:19 +02001218 data->fan[nr] = f71882fg_read16(data,
1219 F71882FG_REG_FAN(nr));
Mark van Doesburg9ab796e2009-01-07 16:37:27 +01001220 data->fan_target[nr] =
1221 f71882fg_read16(data, F71882FG_REG_FAN_TARGET(nr));
1222 data->fan_full_speed[nr] =
1223 f71882fg_read16(data,
1224 F71882FG_REG_FAN_FULL_SPEED(nr));
1225 data->pwm[nr] =
1226 f71882fg_read8(data, F71882FG_REG_PWM(nr));
1227 }
Hans de Goedeed4f7c22009-01-07 16:37:30 +01001228 /* The f8000 can monitor 1 more fan, but has no pwm for it */
1229 if (data->type == f8000)
1230 data->fan[3] = f71882fg_read16(data,
1231 F71882FG_REG_FAN(3));
Hans de Goede0bae6402011-03-09 20:57:10 +01001232
1233 if (f71882fg_has_in1_alarm[data->type])
Hans de Goede498be962009-01-07 16:37:28 +01001234 data->in_status = f71882fg_read8(data,
Hans de Goede45fb3662007-07-13 14:34:19 +02001235 F71882FG_REG_IN_STATUS);
Hans de Goede0bae6402011-03-09 20:57:10 +01001236 for (nr = 0; nr < F71882FG_MAX_INS; nr++)
1237 if (f71882fg_has_in[data->type][nr])
1238 data->in[nr] = f71882fg_read8(data,
1239 F71882FG_REG_IN(nr));
Hans de Goede45fb3662007-07-13 14:34:19 +02001240
1241 data->last_updated = jiffies;
1242 data->valid = 1;
1243 }
1244
1245 mutex_unlock(&data->update_lock);
1246
1247 return data;
1248}
1249
1250/* Sysfs Interface */
1251static ssize_t show_fan(struct device *dev, struct device_attribute *devattr,
1252 char *buf)
1253{
1254 struct f71882fg_data *data = f71882fg_update_device(dev);
Mark van Doesburgbc37ae72009-01-07 16:37:27 +01001255 int nr = to_sensor_dev_attr_2(devattr)->index;
Hans de Goede45fb3662007-07-13 14:34:19 +02001256 int speed = fan_from_reg(data->fan[nr]);
1257
1258 if (speed == FAN_MIN_DETECT)
1259 speed = 0;
1260
1261 return sprintf(buf, "%d\n", speed);
1262}
1263
Mark van Doesburg9ab796e2009-01-07 16:37:27 +01001264static ssize_t show_fan_full_speed(struct device *dev,
1265 struct device_attribute *devattr, char *buf)
1266{
1267 struct f71882fg_data *data = f71882fg_update_device(dev);
1268 int nr = to_sensor_dev_attr_2(devattr)->index;
1269 int speed = fan_from_reg(data->fan_full_speed[nr]);
1270 return sprintf(buf, "%d\n", speed);
1271}
1272
1273static ssize_t store_fan_full_speed(struct device *dev,
1274 struct device_attribute *devattr,
1275 const char *buf, size_t count)
1276{
1277 struct f71882fg_data *data = dev_get_drvdata(dev);
Giel van Schijndele8a4eac2010-05-27 19:58:41 +02001278 int err, nr = to_sensor_dev_attr_2(devattr)->index;
1279 long val;
1280
1281 err = strict_strtol(buf, 10, &val);
1282 if (err)
1283 return err;
Mark van Doesburg9ab796e2009-01-07 16:37:27 +01001284
1285 val = SENSORS_LIMIT(val, 23, 1500000);
1286 val = fan_to_reg(val);
1287
1288 mutex_lock(&data->update_lock);
Hans de Goede4c82c382009-01-07 16:37:30 +01001289 f71882fg_write16(data, F71882FG_REG_FAN_FULL_SPEED(nr), val);
1290 data->fan_full_speed[nr] = val;
Mark van Doesburg9ab796e2009-01-07 16:37:27 +01001291 mutex_unlock(&data->update_lock);
1292
1293 return count;
1294}
1295
Hans de Goede45fb3662007-07-13 14:34:19 +02001296static ssize_t show_fan_beep(struct device *dev, struct device_attribute
1297 *devattr, char *buf)
1298{
1299 struct f71882fg_data *data = f71882fg_update_device(dev);
Mark van Doesburgbc37ae72009-01-07 16:37:27 +01001300 int nr = to_sensor_dev_attr_2(devattr)->index;
Hans de Goede45fb3662007-07-13 14:34:19 +02001301
1302 if (data->fan_beep & (1 << nr))
1303 return sprintf(buf, "1\n");
1304 else
1305 return sprintf(buf, "0\n");
1306}
1307
1308static ssize_t store_fan_beep(struct device *dev, struct device_attribute
1309 *devattr, const char *buf, size_t count)
1310{
1311 struct f71882fg_data *data = dev_get_drvdata(dev);
Giel van Schijndele8a4eac2010-05-27 19:58:41 +02001312 int err, nr = to_sensor_dev_attr_2(devattr)->index;
1313 unsigned long val;
1314
1315 err = strict_strtoul(buf, 10, &val);
1316 if (err)
1317 return err;
Hans de Goede45fb3662007-07-13 14:34:19 +02001318
1319 mutex_lock(&data->update_lock);
Hans de Goedece0bfa52009-01-07 16:37:28 +01001320 data->fan_beep = f71882fg_read8(data, F71882FG_REG_FAN_BEEP);
Hans de Goede45fb3662007-07-13 14:34:19 +02001321 if (val)
1322 data->fan_beep |= 1 << nr;
1323 else
1324 data->fan_beep &= ~(1 << nr);
1325
1326 f71882fg_write8(data, F71882FG_REG_FAN_BEEP, data->fan_beep);
1327 mutex_unlock(&data->update_lock);
1328
1329 return count;
1330}
1331
1332static ssize_t show_fan_alarm(struct device *dev, struct device_attribute
1333 *devattr, char *buf)
1334{
1335 struct f71882fg_data *data = f71882fg_update_device(dev);
Mark van Doesburgbc37ae72009-01-07 16:37:27 +01001336 int nr = to_sensor_dev_attr_2(devattr)->index;
Hans de Goede45fb3662007-07-13 14:34:19 +02001337
1338 if (data->fan_status & (1 << nr))
1339 return sprintf(buf, "1\n");
1340 else
1341 return sprintf(buf, "0\n");
1342}
1343
1344static ssize_t show_in(struct device *dev, struct device_attribute *devattr,
1345 char *buf)
1346{
1347 struct f71882fg_data *data = f71882fg_update_device(dev);
Mark van Doesburgbc37ae72009-01-07 16:37:27 +01001348 int nr = to_sensor_dev_attr_2(devattr)->index;
Hans de Goede45fb3662007-07-13 14:34:19 +02001349
1350 return sprintf(buf, "%d\n", data->in[nr] * 8);
1351}
1352
1353static ssize_t show_in_max(struct device *dev, struct device_attribute
1354 *devattr, char *buf)
1355{
1356 struct f71882fg_data *data = f71882fg_update_device(dev);
1357
1358 return sprintf(buf, "%d\n", data->in1_max * 8);
1359}
1360
1361static ssize_t store_in_max(struct device *dev, struct device_attribute
1362 *devattr, const char *buf, size_t count)
1363{
1364 struct f71882fg_data *data = dev_get_drvdata(dev);
Giel van Schijndele8a4eac2010-05-27 19:58:41 +02001365 int err;
1366 long val;
1367
1368 err = strict_strtol(buf, 10, &val);
1369 if (err)
1370 return err;
1371
1372 val /= 8;
Hans de Goedece0bfa52009-01-07 16:37:28 +01001373 val = SENSORS_LIMIT(val, 0, 255);
Hans de Goede45fb3662007-07-13 14:34:19 +02001374
1375 mutex_lock(&data->update_lock);
1376 f71882fg_write8(data, F71882FG_REG_IN1_HIGH, val);
1377 data->in1_max = val;
1378 mutex_unlock(&data->update_lock);
1379
1380 return count;
1381}
1382
1383static ssize_t show_in_beep(struct device *dev, struct device_attribute
1384 *devattr, char *buf)
1385{
1386 struct f71882fg_data *data = f71882fg_update_device(dev);
Mark van Doesburgbc37ae72009-01-07 16:37:27 +01001387 int nr = to_sensor_dev_attr_2(devattr)->index;
Hans de Goede45fb3662007-07-13 14:34:19 +02001388
1389 if (data->in_beep & (1 << nr))
1390 return sprintf(buf, "1\n");
1391 else
1392 return sprintf(buf, "0\n");
1393}
1394
1395static ssize_t store_in_beep(struct device *dev, struct device_attribute
1396 *devattr, const char *buf, size_t count)
1397{
1398 struct f71882fg_data *data = dev_get_drvdata(dev);
Giel van Schijndele8a4eac2010-05-27 19:58:41 +02001399 int err, nr = to_sensor_dev_attr_2(devattr)->index;
1400 unsigned long val;
1401
1402 err = strict_strtoul(buf, 10, &val);
1403 if (err)
1404 return err;
Hans de Goede45fb3662007-07-13 14:34:19 +02001405
1406 mutex_lock(&data->update_lock);
Hans de Goedece0bfa52009-01-07 16:37:28 +01001407 data->in_beep = f71882fg_read8(data, F71882FG_REG_IN_BEEP);
Hans de Goede45fb3662007-07-13 14:34:19 +02001408 if (val)
1409 data->in_beep |= 1 << nr;
1410 else
1411 data->in_beep &= ~(1 << nr);
1412
1413 f71882fg_write8(data, F71882FG_REG_IN_BEEP, data->in_beep);
1414 mutex_unlock(&data->update_lock);
1415
1416 return count;
1417}
1418
1419static ssize_t show_in_alarm(struct device *dev, struct device_attribute
1420 *devattr, char *buf)
1421{
1422 struct f71882fg_data *data = f71882fg_update_device(dev);
Mark van Doesburgbc37ae72009-01-07 16:37:27 +01001423 int nr = to_sensor_dev_attr_2(devattr)->index;
Hans de Goede45fb3662007-07-13 14:34:19 +02001424
1425 if (data->in_status & (1 << nr))
1426 return sprintf(buf, "1\n");
1427 else
1428 return sprintf(buf, "0\n");
1429}
1430
1431static ssize_t show_temp(struct device *dev, struct device_attribute *devattr,
1432 char *buf)
1433{
1434 struct f71882fg_data *data = f71882fg_update_device(dev);
Mark van Doesburgbc37ae72009-01-07 16:37:27 +01001435 int nr = to_sensor_dev_attr_2(devattr)->index;
Hans de Goede09475d32009-06-15 18:39:52 +02001436 int sign, temp;
Hans de Goede45fb3662007-07-13 14:34:19 +02001437
Hans de Goede09475d32009-06-15 18:39:52 +02001438 if (data->type == f71858fg) {
1439 /* TEMP_TABLE_SEL 1 or 3 ? */
1440 if (data->temp_config & 1) {
1441 sign = data->temp[nr] & 0x0001;
1442 temp = (data->temp[nr] >> 5) & 0x7ff;
1443 } else {
1444 sign = data->temp[nr] & 0x8000;
1445 temp = (data->temp[nr] >> 5) & 0x3ff;
1446 }
1447 temp *= 125;
1448 if (sign)
1449 temp -= 128000;
1450 } else
1451 temp = data->temp[nr] * 1000;
1452
1453 return sprintf(buf, "%d\n", temp);
Hans de Goede45fb3662007-07-13 14:34:19 +02001454}
1455
1456static ssize_t show_temp_max(struct device *dev, struct device_attribute
1457 *devattr, char *buf)
1458{
1459 struct f71882fg_data *data = f71882fg_update_device(dev);
Mark van Doesburgbc37ae72009-01-07 16:37:27 +01001460 int nr = to_sensor_dev_attr_2(devattr)->index;
Hans de Goede45fb3662007-07-13 14:34:19 +02001461
1462 return sprintf(buf, "%d\n", data->temp_high[nr] * 1000);
1463}
1464
1465static ssize_t store_temp_max(struct device *dev, struct device_attribute
1466 *devattr, const char *buf, size_t count)
1467{
1468 struct f71882fg_data *data = dev_get_drvdata(dev);
Giel van Schijndele8a4eac2010-05-27 19:58:41 +02001469 int err, nr = to_sensor_dev_attr_2(devattr)->index;
1470 long val;
1471
1472 err = strict_strtol(buf, 10, &val);
1473 if (err)
1474 return err;
1475
1476 val /= 1000;
Hans de Goedece0bfa52009-01-07 16:37:28 +01001477 val = SENSORS_LIMIT(val, 0, 255);
Hans de Goede45fb3662007-07-13 14:34:19 +02001478
1479 mutex_lock(&data->update_lock);
1480 f71882fg_write8(data, F71882FG_REG_TEMP_HIGH(nr), val);
1481 data->temp_high[nr] = val;
1482 mutex_unlock(&data->update_lock);
1483
1484 return count;
1485}
1486
1487static ssize_t show_temp_max_hyst(struct device *dev, struct device_attribute
1488 *devattr, char *buf)
1489{
1490 struct f71882fg_data *data = f71882fg_update_device(dev);
Mark van Doesburgbc37ae72009-01-07 16:37:27 +01001491 int nr = to_sensor_dev_attr_2(devattr)->index;
Hans de Goedece0bfa52009-01-07 16:37:28 +01001492 int temp_max_hyst;
Hans de Goede45fb3662007-07-13 14:34:19 +02001493
Hans de Goedece0bfa52009-01-07 16:37:28 +01001494 mutex_lock(&data->update_lock);
Hans de Goedebc274902009-01-07 16:37:29 +01001495 if (nr & 1)
1496 temp_max_hyst = data->temp_hyst[nr / 2] >> 4;
1497 else
1498 temp_max_hyst = data->temp_hyst[nr / 2] & 0x0f;
1499 temp_max_hyst = (data->temp_high[nr] - temp_max_hyst) * 1000;
Hans de Goedece0bfa52009-01-07 16:37:28 +01001500 mutex_unlock(&data->update_lock);
1501
1502 return sprintf(buf, "%d\n", temp_max_hyst);
Hans de Goede45fb3662007-07-13 14:34:19 +02001503}
1504
1505static ssize_t store_temp_max_hyst(struct device *dev, struct device_attribute
1506 *devattr, const char *buf, size_t count)
1507{
1508 struct f71882fg_data *data = dev_get_drvdata(dev);
Giel van Schijndele8a4eac2010-05-27 19:58:41 +02001509 int err, nr = to_sensor_dev_attr_2(devattr)->index;
Hans de Goede45fb3662007-07-13 14:34:19 +02001510 ssize_t ret = count;
Hans de Goedece0bfa52009-01-07 16:37:28 +01001511 u8 reg;
Giel van Schijndele8a4eac2010-05-27 19:58:41 +02001512 long val;
1513
1514 err = strict_strtol(buf, 10, &val);
1515 if (err)
1516 return err;
1517
1518 val /= 1000;
Hans de Goede45fb3662007-07-13 14:34:19 +02001519
1520 mutex_lock(&data->update_lock);
1521
1522 /* convert abs to relative and check */
Hans de Goedece0bfa52009-01-07 16:37:28 +01001523 data->temp_high[nr] = f71882fg_read8(data, F71882FG_REG_TEMP_HIGH(nr));
1524 val = SENSORS_LIMIT(val, data->temp_high[nr] - 15,
1525 data->temp_high[nr]);
Hans de Goede45fb3662007-07-13 14:34:19 +02001526 val = data->temp_high[nr] - val;
Hans de Goede45fb3662007-07-13 14:34:19 +02001527
1528 /* convert value to register contents */
Hans de Goedebc274902009-01-07 16:37:29 +01001529 reg = f71882fg_read8(data, F71882FG_REG_TEMP_HYST(nr / 2));
1530 if (nr & 1)
1531 reg = (reg & 0x0f) | (val << 4);
1532 else
1533 reg = (reg & 0xf0) | val;
1534 f71882fg_write8(data, F71882FG_REG_TEMP_HYST(nr / 2), reg);
1535 data->temp_hyst[nr / 2] = reg;
Hans de Goede45fb3662007-07-13 14:34:19 +02001536
Hans de Goede45fb3662007-07-13 14:34:19 +02001537 mutex_unlock(&data->update_lock);
1538 return ret;
1539}
1540
1541static ssize_t show_temp_crit(struct device *dev, struct device_attribute
1542 *devattr, char *buf)
1543{
1544 struct f71882fg_data *data = f71882fg_update_device(dev);
Mark van Doesburgbc37ae72009-01-07 16:37:27 +01001545 int nr = to_sensor_dev_attr_2(devattr)->index;
Hans de Goede45fb3662007-07-13 14:34:19 +02001546
1547 return sprintf(buf, "%d\n", data->temp_ovt[nr] * 1000);
1548}
1549
1550static ssize_t store_temp_crit(struct device *dev, struct device_attribute
1551 *devattr, const char *buf, size_t count)
1552{
1553 struct f71882fg_data *data = dev_get_drvdata(dev);
Giel van Schijndele8a4eac2010-05-27 19:58:41 +02001554 int err, nr = to_sensor_dev_attr_2(devattr)->index;
1555 long val;
1556
1557 err = strict_strtol(buf, 10, &val);
1558 if (err)
1559 return err;
1560
1561 val /= 1000;
Hans de Goedece0bfa52009-01-07 16:37:28 +01001562 val = SENSORS_LIMIT(val, 0, 255);
Hans de Goede45fb3662007-07-13 14:34:19 +02001563
1564 mutex_lock(&data->update_lock);
1565 f71882fg_write8(data, F71882FG_REG_TEMP_OVT(nr), val);
1566 data->temp_ovt[nr] = val;
1567 mutex_unlock(&data->update_lock);
1568
1569 return count;
1570}
1571
1572static ssize_t show_temp_crit_hyst(struct device *dev, struct device_attribute
1573 *devattr, char *buf)
1574{
1575 struct f71882fg_data *data = f71882fg_update_device(dev);
Mark van Doesburgbc37ae72009-01-07 16:37:27 +01001576 int nr = to_sensor_dev_attr_2(devattr)->index;
Hans de Goedece0bfa52009-01-07 16:37:28 +01001577 int temp_crit_hyst;
Hans de Goede45fb3662007-07-13 14:34:19 +02001578
Hans de Goedece0bfa52009-01-07 16:37:28 +01001579 mutex_lock(&data->update_lock);
Hans de Goedebc274902009-01-07 16:37:29 +01001580 if (nr & 1)
1581 temp_crit_hyst = data->temp_hyst[nr / 2] >> 4;
1582 else
1583 temp_crit_hyst = data->temp_hyst[nr / 2] & 0x0f;
1584 temp_crit_hyst = (data->temp_ovt[nr] - temp_crit_hyst) * 1000;
Hans de Goedece0bfa52009-01-07 16:37:28 +01001585 mutex_unlock(&data->update_lock);
1586
1587 return sprintf(buf, "%d\n", temp_crit_hyst);
Hans de Goede45fb3662007-07-13 14:34:19 +02001588}
1589
1590static ssize_t show_temp_type(struct device *dev, struct device_attribute
1591 *devattr, char *buf)
1592{
1593 struct f71882fg_data *data = f71882fg_update_device(dev);
Mark van Doesburgbc37ae72009-01-07 16:37:27 +01001594 int nr = to_sensor_dev_attr_2(devattr)->index;
Hans de Goede45fb3662007-07-13 14:34:19 +02001595
1596 return sprintf(buf, "%d\n", data->temp_type[nr]);
1597}
1598
1599static ssize_t show_temp_beep(struct device *dev, struct device_attribute
1600 *devattr, char *buf)
1601{
1602 struct f71882fg_data *data = f71882fg_update_device(dev);
Mark van Doesburgbc37ae72009-01-07 16:37:27 +01001603 int nr = to_sensor_dev_attr_2(devattr)->index;
Hans de Goede45fb3662007-07-13 14:34:19 +02001604
Hans de Goede7567a042009-01-07 16:37:28 +01001605 if (data->temp_beep & (1 << nr))
Hans de Goede45fb3662007-07-13 14:34:19 +02001606 return sprintf(buf, "1\n");
1607 else
1608 return sprintf(buf, "0\n");
1609}
1610
1611static ssize_t store_temp_beep(struct device *dev, struct device_attribute
1612 *devattr, const char *buf, size_t count)
1613{
1614 struct f71882fg_data *data = dev_get_drvdata(dev);
Giel van Schijndele8a4eac2010-05-27 19:58:41 +02001615 int err, nr = to_sensor_dev_attr_2(devattr)->index;
1616 unsigned long val;
1617
1618 err = strict_strtoul(buf, 10, &val);
1619 if (err)
1620 return err;
Hans de Goede45fb3662007-07-13 14:34:19 +02001621
1622 mutex_lock(&data->update_lock);
Hans de Goedece0bfa52009-01-07 16:37:28 +01001623 data->temp_beep = f71882fg_read8(data, F71882FG_REG_TEMP_BEEP);
Hans de Goede45fb3662007-07-13 14:34:19 +02001624 if (val)
Hans de Goede7567a042009-01-07 16:37:28 +01001625 data->temp_beep |= 1 << nr;
Hans de Goede45fb3662007-07-13 14:34:19 +02001626 else
Hans de Goede7567a042009-01-07 16:37:28 +01001627 data->temp_beep &= ~(1 << nr);
Hans de Goede45fb3662007-07-13 14:34:19 +02001628
1629 f71882fg_write8(data, F71882FG_REG_TEMP_BEEP, data->temp_beep);
1630 mutex_unlock(&data->update_lock);
1631
1632 return count;
1633}
1634
1635static ssize_t show_temp_alarm(struct device *dev, struct device_attribute
1636 *devattr, char *buf)
1637{
1638 struct f71882fg_data *data = f71882fg_update_device(dev);
Mark van Doesburgbc37ae72009-01-07 16:37:27 +01001639 int nr = to_sensor_dev_attr_2(devattr)->index;
Hans de Goede45fb3662007-07-13 14:34:19 +02001640
Hans de Goede7567a042009-01-07 16:37:28 +01001641 if (data->temp_status & (1 << nr))
Hans de Goede45fb3662007-07-13 14:34:19 +02001642 return sprintf(buf, "1\n");
1643 else
1644 return sprintf(buf, "0\n");
1645}
1646
1647static ssize_t show_temp_fault(struct device *dev, struct device_attribute
1648 *devattr, char *buf)
1649{
1650 struct f71882fg_data *data = f71882fg_update_device(dev);
Mark van Doesburgbc37ae72009-01-07 16:37:27 +01001651 int nr = to_sensor_dev_attr_2(devattr)->index;
Hans de Goede45fb3662007-07-13 14:34:19 +02001652
Hans de Goede7567a042009-01-07 16:37:28 +01001653 if (data->temp_diode_open & (1 << nr))
Hans de Goede45fb3662007-07-13 14:34:19 +02001654 return sprintf(buf, "1\n");
1655 else
1656 return sprintf(buf, "0\n");
1657}
1658
Mark van Doesburg9ab796e2009-01-07 16:37:27 +01001659static ssize_t show_pwm(struct device *dev,
1660 struct device_attribute *devattr, char *buf)
1661{
1662 struct f71882fg_data *data = f71882fg_update_device(dev);
1663 int val, nr = to_sensor_dev_attr_2(devattr)->index;
Hans de Goedece0bfa52009-01-07 16:37:28 +01001664 mutex_lock(&data->update_lock);
Mark van Doesburg9ab796e2009-01-07 16:37:27 +01001665 if (data->pwm_enable & (1 << (2 * nr)))
1666 /* PWM mode */
1667 val = data->pwm[nr];
1668 else {
1669 /* RPM mode */
Mark van Doesburg9ab796e2009-01-07 16:37:27 +01001670 val = 255 * fan_from_reg(data->fan_target[nr])
1671 / fan_from_reg(data->fan_full_speed[nr]);
Mark van Doesburg9ab796e2009-01-07 16:37:27 +01001672 }
Hans de Goedece0bfa52009-01-07 16:37:28 +01001673 mutex_unlock(&data->update_lock);
Mark van Doesburg9ab796e2009-01-07 16:37:27 +01001674 return sprintf(buf, "%d\n", val);
1675}
1676
1677static ssize_t store_pwm(struct device *dev,
1678 struct device_attribute *devattr, const char *buf,
1679 size_t count)
1680{
Hans de Goedece0bfa52009-01-07 16:37:28 +01001681 struct f71882fg_data *data = dev_get_drvdata(dev);
Giel van Schijndele8a4eac2010-05-27 19:58:41 +02001682 int err, nr = to_sensor_dev_attr_2(devattr)->index;
1683 long val;
1684
1685 err = strict_strtol(buf, 10, &val);
1686 if (err)
1687 return err;
1688
Mark van Doesburg9ab796e2009-01-07 16:37:27 +01001689 val = SENSORS_LIMIT(val, 0, 255);
1690
1691 mutex_lock(&data->update_lock);
Hans de Goedece0bfa52009-01-07 16:37:28 +01001692 data->pwm_enable = f71882fg_read8(data, F71882FG_REG_PWM_ENABLE);
Hans de Goedeed4f7c22009-01-07 16:37:30 +01001693 if ((data->type == f8000 && ((data->pwm_enable >> 2 * nr) & 3) != 2) ||
1694 (data->type != f8000 && !((data->pwm_enable >> 2 * nr) & 2))) {
1695 count = -EROFS;
1696 goto leave;
1697 }
Mark van Doesburg9ab796e2009-01-07 16:37:27 +01001698 if (data->pwm_enable & (1 << (2 * nr))) {
1699 /* PWM mode */
1700 f71882fg_write8(data, F71882FG_REG_PWM(nr), val);
1701 data->pwm[nr] = val;
1702 } else {
1703 /* RPM mode */
Hans de Goedece0bfa52009-01-07 16:37:28 +01001704 int target, full_speed;
1705 full_speed = f71882fg_read16(data,
1706 F71882FG_REG_FAN_FULL_SPEED(nr));
1707 target = fan_to_reg(val * fan_from_reg(full_speed) / 255);
1708 f71882fg_write16(data, F71882FG_REG_FAN_TARGET(nr), target);
1709 data->fan_target[nr] = target;
1710 data->fan_full_speed[nr] = full_speed;
Mark van Doesburg9ab796e2009-01-07 16:37:27 +01001711 }
Hans de Goedeed4f7c22009-01-07 16:37:30 +01001712leave:
Mark van Doesburg9ab796e2009-01-07 16:37:27 +01001713 mutex_unlock(&data->update_lock);
1714
1715 return count;
1716}
1717
1718static ssize_t show_pwm_enable(struct device *dev,
1719 struct device_attribute *devattr, char *buf)
1720{
Hans de Goedeed4f7c22009-01-07 16:37:30 +01001721 int result = 0;
Mark van Doesburg9ab796e2009-01-07 16:37:27 +01001722 struct f71882fg_data *data = f71882fg_update_device(dev);
1723 int nr = to_sensor_dev_attr_2(devattr)->index;
1724
Hans de Goedeed4f7c22009-01-07 16:37:30 +01001725 switch ((data->pwm_enable >> 2 * nr) & 3) {
1726 case 0:
1727 case 1:
1728 result = 2; /* Normal auto mode */
1729 break;
1730 case 2:
1731 result = 1; /* Manual mode */
1732 break;
1733 case 3:
1734 if (data->type == f8000)
1735 result = 3; /* Thermostat mode */
1736 else
1737 result = 1; /* Manual mode */
1738 break;
1739 }
Mark van Doesburg9ab796e2009-01-07 16:37:27 +01001740
1741 return sprintf(buf, "%d\n", result);
1742}
1743
1744static ssize_t store_pwm_enable(struct device *dev, struct device_attribute
1745 *devattr, const char *buf, size_t count)
1746{
1747 struct f71882fg_data *data = dev_get_drvdata(dev);
Giel van Schijndele8a4eac2010-05-27 19:58:41 +02001748 int err, nr = to_sensor_dev_attr_2(devattr)->index;
1749 long val;
1750
1751 err = strict_strtol(buf, 10, &val);
1752 if (err)
1753 return err;
Mark van Doesburg9ab796e2009-01-07 16:37:27 +01001754
Hans de Goede3fc78382009-06-15 18:39:50 +02001755 /* Special case for F8000 pwm channel 3 which only does auto mode */
1756 if (data->type == f8000 && nr == 2 && val != 2)
1757 return -EINVAL;
1758
Mark van Doesburg9ab796e2009-01-07 16:37:27 +01001759 mutex_lock(&data->update_lock);
Hans de Goedece0bfa52009-01-07 16:37:28 +01001760 data->pwm_enable = f71882fg_read8(data, F71882FG_REG_PWM_ENABLE);
Hans de Goedeed4f7c22009-01-07 16:37:30 +01001761 /* Special case for F8000 auto PWM mode / Thermostat mode */
1762 if (data->type == f8000 && ((data->pwm_enable >> 2 * nr) & 1)) {
1763 switch (val) {
1764 case 2:
1765 data->pwm_enable &= ~(2 << (2 * nr));
1766 break; /* Normal auto mode */
1767 case 3:
1768 data->pwm_enable |= 2 << (2 * nr);
1769 break; /* Thermostat mode */
1770 default:
1771 count = -EINVAL;
1772 goto leave;
1773 }
1774 } else {
1775 switch (val) {
1776 case 1:
Hans de Goede09475d32009-06-15 18:39:52 +02001777 /* The f71858fg does not support manual RPM mode */
1778 if (data->type == f71858fg &&
1779 ((data->pwm_enable >> (2 * nr)) & 1)) {
1780 count = -EINVAL;
1781 goto leave;
1782 }
Hans de Goedeed4f7c22009-01-07 16:37:30 +01001783 data->pwm_enable |= 2 << (2 * nr);
1784 break; /* Manual */
1785 case 2:
1786 data->pwm_enable &= ~(2 << (2 * nr));
1787 break; /* Normal auto mode */
1788 default:
1789 count = -EINVAL;
1790 goto leave;
1791 }
Mark van Doesburg9ab796e2009-01-07 16:37:27 +01001792 }
Mark van Doesburg9ab796e2009-01-07 16:37:27 +01001793 f71882fg_write8(data, F71882FG_REG_PWM_ENABLE, data->pwm_enable);
Hans de Goedeed4f7c22009-01-07 16:37:30 +01001794leave:
Mark van Doesburg9ab796e2009-01-07 16:37:27 +01001795 mutex_unlock(&data->update_lock);
1796
1797 return count;
1798}
1799
1800static ssize_t show_pwm_auto_point_pwm(struct device *dev,
1801 struct device_attribute *devattr,
1802 char *buf)
1803{
1804 int result;
1805 struct f71882fg_data *data = f71882fg_update_device(dev);
1806 int pwm = to_sensor_dev_attr_2(devattr)->index;
1807 int point = to_sensor_dev_attr_2(devattr)->nr;
1808
Hans de Goedece0bfa52009-01-07 16:37:28 +01001809 mutex_lock(&data->update_lock);
Mark van Doesburg9ab796e2009-01-07 16:37:27 +01001810 if (data->pwm_enable & (1 << (2 * pwm))) {
1811 /* PWM mode */
1812 result = data->pwm_auto_point_pwm[pwm][point];
1813 } else {
1814 /* RPM mode */
1815 result = 32 * 255 / (32 + data->pwm_auto_point_pwm[pwm][point]);
1816 }
Hans de Goedece0bfa52009-01-07 16:37:28 +01001817 mutex_unlock(&data->update_lock);
Mark van Doesburg9ab796e2009-01-07 16:37:27 +01001818
1819 return sprintf(buf, "%d\n", result);
1820}
1821
1822static ssize_t store_pwm_auto_point_pwm(struct device *dev,
1823 struct device_attribute *devattr,
1824 const char *buf, size_t count)
1825{
Hans de Goedece0bfa52009-01-07 16:37:28 +01001826 struct f71882fg_data *data = dev_get_drvdata(dev);
Giel van Schijndele8a4eac2010-05-27 19:58:41 +02001827 int err, pwm = to_sensor_dev_attr_2(devattr)->index;
Mark van Doesburg9ab796e2009-01-07 16:37:27 +01001828 int point = to_sensor_dev_attr_2(devattr)->nr;
Giel van Schijndele8a4eac2010-05-27 19:58:41 +02001829 long val;
1830
1831 err = strict_strtol(buf, 10, &val);
1832 if (err)
1833 return err;
1834
Mark van Doesburg9ab796e2009-01-07 16:37:27 +01001835 val = SENSORS_LIMIT(val, 0, 255);
1836
1837 mutex_lock(&data->update_lock);
Hans de Goedece0bfa52009-01-07 16:37:28 +01001838 data->pwm_enable = f71882fg_read8(data, F71882FG_REG_PWM_ENABLE);
Mark van Doesburg9ab796e2009-01-07 16:37:27 +01001839 if (data->pwm_enable & (1 << (2 * pwm))) {
1840 /* PWM mode */
1841 } else {
1842 /* RPM mode */
1843 if (val < 29) /* Prevent negative numbers */
1844 val = 255;
1845 else
1846 val = (255 - val) * 32 / val;
1847 }
1848 f71882fg_write8(data, F71882FG_REG_POINT_PWM(pwm, point), val);
1849 data->pwm_auto_point_pwm[pwm][point] = val;
1850 mutex_unlock(&data->update_lock);
1851
1852 return count;
1853}
1854
1855static ssize_t show_pwm_auto_point_temp_hyst(struct device *dev,
1856 struct device_attribute *devattr,
1857 char *buf)
1858{
1859 int result = 0;
1860 struct f71882fg_data *data = f71882fg_update_device(dev);
1861 int nr = to_sensor_dev_attr_2(devattr)->index;
1862 int point = to_sensor_dev_attr_2(devattr)->nr;
1863
1864 mutex_lock(&data->update_lock);
Hans de Goedebc274902009-01-07 16:37:29 +01001865 if (nr & 1)
1866 result = data->pwm_auto_point_hyst[nr / 2] >> 4;
1867 else
1868 result = data->pwm_auto_point_hyst[nr / 2] & 0x0f;
Mark van Doesburg9ab796e2009-01-07 16:37:27 +01001869 result = 1000 * (data->pwm_auto_point_temp[nr][point] - result);
1870 mutex_unlock(&data->update_lock);
1871
1872 return sprintf(buf, "%d\n", result);
1873}
1874
1875static ssize_t store_pwm_auto_point_temp_hyst(struct device *dev,
1876 struct device_attribute *devattr,
1877 const char *buf, size_t count)
1878{
Hans de Goedece0bfa52009-01-07 16:37:28 +01001879 struct f71882fg_data *data = dev_get_drvdata(dev);
Giel van Schijndele8a4eac2010-05-27 19:58:41 +02001880 int err, nr = to_sensor_dev_attr_2(devattr)->index;
Mark van Doesburg9ab796e2009-01-07 16:37:27 +01001881 int point = to_sensor_dev_attr_2(devattr)->nr;
Hans de Goedebc274902009-01-07 16:37:29 +01001882 u8 reg;
Giel van Schijndele8a4eac2010-05-27 19:58:41 +02001883 long val;
1884
1885 err = strict_strtol(buf, 10, &val);
1886 if (err)
1887 return err;
1888
1889 val /= 1000;
Mark van Doesburg9ab796e2009-01-07 16:37:27 +01001890
1891 mutex_lock(&data->update_lock);
Hans de Goedece0bfa52009-01-07 16:37:28 +01001892 data->pwm_auto_point_temp[nr][point] =
1893 f71882fg_read8(data, F71882FG_REG_POINT_TEMP(nr, point));
Mark van Doesburg9ab796e2009-01-07 16:37:27 +01001894 val = SENSORS_LIMIT(val, data->pwm_auto_point_temp[nr][point] - 15,
1895 data->pwm_auto_point_temp[nr][point]);
1896 val = data->pwm_auto_point_temp[nr][point] - val;
1897
Hans de Goedebc274902009-01-07 16:37:29 +01001898 reg = f71882fg_read8(data, F71882FG_REG_FAN_HYST(nr / 2));
1899 if (nr & 1)
1900 reg = (reg & 0x0f) | (val << 4);
1901 else
1902 reg = (reg & 0xf0) | val;
1903
1904 f71882fg_write8(data, F71882FG_REG_FAN_HYST(nr / 2), reg);
1905 data->pwm_auto_point_hyst[nr / 2] = reg;
Mark van Doesburg9ab796e2009-01-07 16:37:27 +01001906 mutex_unlock(&data->update_lock);
1907
1908 return count;
1909}
1910
1911static ssize_t show_pwm_interpolate(struct device *dev,
1912 struct device_attribute *devattr, char *buf)
1913{
1914 int result;
1915 struct f71882fg_data *data = f71882fg_update_device(dev);
1916 int nr = to_sensor_dev_attr_2(devattr)->index;
1917
1918 result = (data->pwm_auto_point_mapping[nr] >> 4) & 1;
1919
1920 return sprintf(buf, "%d\n", result);
1921}
1922
1923static ssize_t store_pwm_interpolate(struct device *dev,
1924 struct device_attribute *devattr,
1925 const char *buf, size_t count)
1926{
Hans de Goedece0bfa52009-01-07 16:37:28 +01001927 struct f71882fg_data *data = dev_get_drvdata(dev);
Giel van Schijndele8a4eac2010-05-27 19:58:41 +02001928 int err, nr = to_sensor_dev_attr_2(devattr)->index;
1929 unsigned long val;
1930
1931 err = strict_strtoul(buf, 10, &val);
1932 if (err)
1933 return err;
Hans de Goedece0bfa52009-01-07 16:37:28 +01001934
Mark van Doesburg9ab796e2009-01-07 16:37:27 +01001935 mutex_lock(&data->update_lock);
Hans de Goedece0bfa52009-01-07 16:37:28 +01001936 data->pwm_auto_point_mapping[nr] =
1937 f71882fg_read8(data, F71882FG_REG_POINT_MAPPING(nr));
Mark van Doesburg9ab796e2009-01-07 16:37:27 +01001938 if (val)
1939 val = data->pwm_auto_point_mapping[nr] | (1 << 4);
1940 else
1941 val = data->pwm_auto_point_mapping[nr] & (~(1 << 4));
1942 f71882fg_write8(data, F71882FG_REG_POINT_MAPPING(nr), val);
1943 data->pwm_auto_point_mapping[nr] = val;
1944 mutex_unlock(&data->update_lock);
1945
1946 return count;
1947}
1948
1949static ssize_t show_pwm_auto_point_channel(struct device *dev,
1950 struct device_attribute *devattr,
1951 char *buf)
1952{
1953 int result;
1954 struct f71882fg_data *data = f71882fg_update_device(dev);
1955 int nr = to_sensor_dev_attr_2(devattr)->index;
1956
Hans de Goede09475d32009-06-15 18:39:52 +02001957 result = 1 << ((data->pwm_auto_point_mapping[nr] & 3) -
1958 data->temp_start);
Mark van Doesburg9ab796e2009-01-07 16:37:27 +01001959
1960 return sprintf(buf, "%d\n", result);
1961}
1962
1963static ssize_t store_pwm_auto_point_channel(struct device *dev,
1964 struct device_attribute *devattr,
1965 const char *buf, size_t count)
1966{
Hans de Goedece0bfa52009-01-07 16:37:28 +01001967 struct f71882fg_data *data = dev_get_drvdata(dev);
Giel van Schijndele8a4eac2010-05-27 19:58:41 +02001968 int err, nr = to_sensor_dev_attr_2(devattr)->index;
1969 long val;
1970
1971 err = strict_strtol(buf, 10, &val);
1972 if (err)
1973 return err;
Hans de Goede30453012009-01-07 16:37:30 +01001974
Mark van Doesburg9ab796e2009-01-07 16:37:27 +01001975 switch (val) {
1976 case 1:
Hans de Goede30453012009-01-07 16:37:30 +01001977 val = 0;
Mark van Doesburg9ab796e2009-01-07 16:37:27 +01001978 break;
1979 case 2:
Hans de Goede30453012009-01-07 16:37:30 +01001980 val = 1;
Mark van Doesburg9ab796e2009-01-07 16:37:27 +01001981 break;
1982 case 4:
Hans de Goede30453012009-01-07 16:37:30 +01001983 val = 2;
Mark van Doesburg9ab796e2009-01-07 16:37:27 +01001984 break;
1985 default:
1986 return -EINVAL;
1987 }
Hans de Goede09475d32009-06-15 18:39:52 +02001988 val += data->temp_start;
Mark van Doesburg9ab796e2009-01-07 16:37:27 +01001989 mutex_lock(&data->update_lock);
Hans de Goedece0bfa52009-01-07 16:37:28 +01001990 data->pwm_auto_point_mapping[nr] =
1991 f71882fg_read8(data, F71882FG_REG_POINT_MAPPING(nr));
Mark van Doesburg9ab796e2009-01-07 16:37:27 +01001992 val = (data->pwm_auto_point_mapping[nr] & 0xfc) | val;
1993 f71882fg_write8(data, F71882FG_REG_POINT_MAPPING(nr), val);
1994 data->pwm_auto_point_mapping[nr] = val;
1995 mutex_unlock(&data->update_lock);
1996
1997 return count;
1998}
1999
2000static ssize_t show_pwm_auto_point_temp(struct device *dev,
2001 struct device_attribute *devattr,
2002 char *buf)
2003{
2004 int result;
2005 struct f71882fg_data *data = f71882fg_update_device(dev);
2006 int pwm = to_sensor_dev_attr_2(devattr)->index;
2007 int point = to_sensor_dev_attr_2(devattr)->nr;
2008
2009 result = data->pwm_auto_point_temp[pwm][point];
2010 return sprintf(buf, "%d\n", 1000 * result);
2011}
2012
2013static ssize_t store_pwm_auto_point_temp(struct device *dev,
2014 struct device_attribute *devattr,
2015 const char *buf, size_t count)
2016{
Hans de Goedece0bfa52009-01-07 16:37:28 +01002017 struct f71882fg_data *data = dev_get_drvdata(dev);
Giel van Schijndele8a4eac2010-05-27 19:58:41 +02002018 int err, pwm = to_sensor_dev_attr_2(devattr)->index;
Mark van Doesburg9ab796e2009-01-07 16:37:27 +01002019 int point = to_sensor_dev_attr_2(devattr)->nr;
Giel van Schijndele8a4eac2010-05-27 19:58:41 +02002020 long val;
2021
2022 err = strict_strtol(buf, 10, &val);
2023 if (err)
2024 return err;
2025
2026 val /= 1000;
Hans de Goede76698962009-12-09 20:36:01 +01002027
Hans de Goede98f7ba12011-03-09 20:57:09 +01002028 if (data->auto_point_temp_signed)
Hans de Goede76698962009-12-09 20:36:01 +01002029 val = SENSORS_LIMIT(val, -128, 127);
2030 else
2031 val = SENSORS_LIMIT(val, 0, 127);
Mark van Doesburg9ab796e2009-01-07 16:37:27 +01002032
2033 mutex_lock(&data->update_lock);
2034 f71882fg_write8(data, F71882FG_REG_POINT_TEMP(pwm, point), val);
2035 data->pwm_auto_point_temp[pwm][point] = val;
2036 mutex_unlock(&data->update_lock);
2037
2038 return count;
2039}
2040
Hans de Goede45fb3662007-07-13 14:34:19 +02002041static ssize_t show_name(struct device *dev, struct device_attribute *devattr,
2042 char *buf)
2043{
Hans de Goede498be962009-01-07 16:37:28 +01002044 struct f71882fg_data *data = dev_get_drvdata(dev);
2045 return sprintf(buf, "%s\n", f71882fg_names[data->type]);
Hans de Goede45fb3662007-07-13 14:34:19 +02002046}
2047
Hans de Goedec13548c2009-01-07 16:37:27 +01002048static int __devinit f71882fg_create_sysfs_files(struct platform_device *pdev,
2049 struct sensor_device_attribute_2 *attr, int count)
2050{
2051 int err, i;
Hans de Goede45fb3662007-07-13 14:34:19 +02002052
Hans de Goedec13548c2009-01-07 16:37:27 +01002053 for (i = 0; i < count; i++) {
2054 err = device_create_file(&pdev->dev, &attr[i].dev_attr);
2055 if (err)
2056 return err;
2057 }
2058 return 0;
2059}
2060
Hans de Goedefc16c562009-12-09 20:36:01 +01002061static void f71882fg_remove_sysfs_files(struct platform_device *pdev,
2062 struct sensor_device_attribute_2 *attr, int count)
2063{
2064 int i;
2065
2066 for (i = 0; i < count; i++)
2067 device_remove_file(&pdev->dev, &attr[i].dev_attr);
2068}
2069
Hans de Goedec13548c2009-01-07 16:37:27 +01002070static int __devinit f71882fg_probe(struct platform_device *pdev)
Hans de Goede45fb3662007-07-13 14:34:19 +02002071{
2072 struct f71882fg_data *data;
Hans de Goede498be962009-01-07 16:37:28 +01002073 struct f71882fg_sio_data *sio_data = pdev->dev.platform_data;
Jean Delvaref27def02011-03-26 10:45:01 +01002074 int nr_fans = f71882fg_nr_fans[sio_data->type];
2075 int nr_temps = f71882fg_nr_temps[sio_data->type];
2076 int err, i;
Hans de Goede98f7ba12011-03-09 20:57:09 +01002077 u8 start_reg, reg;
Hans de Goede45fb3662007-07-13 14:34:19 +02002078
Hans de Goedec13548c2009-01-07 16:37:27 +01002079 data = kzalloc(sizeof(struct f71882fg_data), GFP_KERNEL);
2080 if (!data)
Hans de Goede45fb3662007-07-13 14:34:19 +02002081 return -ENOMEM;
2082
2083 data->addr = platform_get_resource(pdev, IORESOURCE_IO, 0)->start;
Hans de Goede498be962009-01-07 16:37:28 +01002084 data->type = sio_data->type;
Hans de Goede09475d32009-06-15 18:39:52 +02002085 data->temp_start =
2086 (data->type == f71858fg || data->type == f8000) ? 0 : 1;
Hans de Goede45fb3662007-07-13 14:34:19 +02002087 mutex_init(&data->update_lock);
2088 platform_set_drvdata(pdev, data);
2089
Hans de Goede3cc74752009-01-07 16:37:28 +01002090 start_reg = f71882fg_read8(data, F71882FG_REG_START);
Hans de Goede12d66e82009-01-07 16:37:29 +01002091 if (start_reg & 0x04) {
2092 dev_warn(&pdev->dev, "Hardware monitor is powered down\n");
2093 err = -ENODEV;
2094 goto exit_free;
2095 }
Hans de Goede3cc74752009-01-07 16:37:28 +01002096 if (!(start_reg & 0x03)) {
2097 dev_warn(&pdev->dev, "Hardware monitoring not activated\n");
2098 err = -ENODEV;
2099 goto exit_free;
2100 }
2101
Hans de Goede45fb3662007-07-13 14:34:19 +02002102 /* Register sysfs interface files */
Hans de Goedec13548c2009-01-07 16:37:27 +01002103 err = device_create_file(&pdev->dev, &dev_attr_name);
2104 if (err)
2105 goto exit_unregister_sysfs;
2106
Hans de Goedec13548c2009-01-07 16:37:27 +01002107 if (start_reg & 0x01) {
Hans de Goedeed4f7c22009-01-07 16:37:30 +01002108 switch (data->type) {
Hans de Goede09475d32009-06-15 18:39:52 +02002109 case f71858fg:
2110 data->temp_config =
2111 f71882fg_read8(data, F71882FG_REG_TEMP_CONFIG);
2112 if (data->temp_config & 0x10)
2113 /* The f71858fg temperature alarms behave as
2114 the f8000 alarms in this mode */
2115 err = f71882fg_create_sysfs_files(pdev,
Hans de Goede0bae6402011-03-09 20:57:10 +01002116 f8000_temp_attr,
2117 ARRAY_SIZE(f8000_temp_attr));
Hans de Goede09475d32009-06-15 18:39:52 +02002118 else
2119 err = f71882fg_create_sysfs_files(pdev,
Hans de Goede0bae6402011-03-09 20:57:10 +01002120 f71858fg_temp_attr,
2121 ARRAY_SIZE(f71858fg_temp_attr));
Hans de Goede09475d32009-06-15 18:39:52 +02002122 break;
Hans de Goede0bae6402011-03-09 20:57:10 +01002123 case f8000:
2124 err = f71882fg_create_sysfs_files(pdev,
2125 f8000_temp_attr,
2126 ARRAY_SIZE(f8000_temp_attr));
2127 break;
2128 default:
2129 err = f71882fg_create_sysfs_files(pdev,
Hans de Goede60d2b372011-03-09 20:57:11 +01002130 &fxxxx_temp_attr[0][0],
2131 ARRAY_SIZE(fxxxx_temp_attr[0]) * nr_temps);
Hans de Goede0bae6402011-03-09 20:57:10 +01002132 }
2133 if (err)
2134 goto exit_unregister_sysfs;
2135
Hans de Goede78aa4f72011-03-09 20:57:12 +01002136 if (f71882fg_has_beep[data->type]) {
2137 err = f71882fg_create_sysfs_files(pdev,
2138 &fxxxx_temp_beep_attr[0][0],
2139 ARRAY_SIZE(fxxxx_temp_beep_attr[0])
2140 * nr_temps);
2141 if (err)
2142 goto exit_unregister_sysfs;
2143 }
2144
Hans de Goede0bae6402011-03-09 20:57:10 +01002145 for (i = 0; i < F71882FG_MAX_INS; i++) {
2146 if (f71882fg_has_in[data->type][i]) {
2147 err = device_create_file(&pdev->dev,
2148 &fxxxx_in_attr[i].dev_attr);
2149 if (err)
2150 goto exit_unregister_sysfs;
2151 }
2152 }
2153 if (f71882fg_has_in1_alarm[data->type]) {
Hans de Goede498be962009-01-07 16:37:28 +01002154 err = f71882fg_create_sysfs_files(pdev,
Hans de Goede66344aa2009-12-09 20:35:59 +01002155 fxxxx_in1_alarm_attr,
2156 ARRAY_SIZE(fxxxx_in1_alarm_attr));
Hans de Goede498be962009-01-07 16:37:28 +01002157 if (err)
2158 goto exit_unregister_sysfs;
2159 }
Hans de Goede45fb3662007-07-13 14:34:19 +02002160 }
2161
Hans de Goede45fb3662007-07-13 14:34:19 +02002162 if (start_reg & 0x02) {
Hans de Goede98f7ba12011-03-09 20:57:09 +01002163 switch (data->type) {
Hans de Goedee5e713c2011-03-10 08:54:02 +01002164 case f71808e:
Hans de Goedec11bb992011-03-09 20:57:15 +01002165 case f71869:
Hans de Goedee5e713c2011-03-10 08:54:02 +01002166 /* These always have signed auto point temps */
Hans de Goedec11bb992011-03-09 20:57:15 +01002167 data->auto_point_temp_signed = 1;
2168 /* Fall through to select correct fan/pwm reg bank! */
Hans de Goede98f7ba12011-03-09 20:57:09 +01002169 case f71889fg:
Hans de Goede3cad4022011-03-09 20:57:14 +01002170 case f71889ed:
Hans de Goede98f7ba12011-03-09 20:57:09 +01002171 reg = f71882fg_read8(data, F71882FG_REG_FAN_FAULT_T);
2172 if (reg & F71882FG_FAN_NEG_TEMP_EN)
2173 data->auto_point_temp_signed = 1;
Hans de Goede3cad4022011-03-09 20:57:14 +01002174 /* Ensure banked pwm registers point to right bank */
2175 reg &= ~F71882FG_FAN_PROG_SEL;
2176 f71882fg_write8(data, F71882FG_REG_FAN_FAULT_T, reg);
Hans de Goede98f7ba12011-03-09 20:57:09 +01002177 break;
2178 default:
2179 break;
2180 }
2181
Hans de Goede996cadb2009-06-15 18:39:51 +02002182 data->pwm_enable =
2183 f71882fg_read8(data, F71882FG_REG_PWM_ENABLE);
2184
2185 /* Sanity check the pwm settings */
2186 switch (data->type) {
Hans de Goede09475d32009-06-15 18:39:52 +02002187 case f71858fg:
2188 err = 0;
2189 for (i = 0; i < nr_fans; i++)
2190 if (((data->pwm_enable >> (i * 2)) & 3) == 3)
2191 err = 1;
2192 break;
Hans de Goede996cadb2009-06-15 18:39:51 +02002193 case f71862fg:
2194 err = (data->pwm_enable & 0x15) != 0x15;
2195 break;
Hans de Goede996cadb2009-06-15 18:39:51 +02002196 case f8000:
2197 err = data->pwm_enable & 0x20;
2198 break;
Jean Delvare383586b2011-03-26 10:45:02 +01002199 default:
2200 err = 0;
2201 break;
Hans de Goede996cadb2009-06-15 18:39:51 +02002202 }
2203 if (err) {
2204 dev_err(&pdev->dev,
2205 "Invalid (reserved) pwm settings: 0x%02x\n",
2206 (unsigned int)data->pwm_enable);
2207 err = -ENODEV;
2208 goto exit_unregister_sysfs;
2209 }
2210
Hans de Goedeb69b0392009-12-09 20:36:00 +01002211 err = f71882fg_create_sysfs_files(pdev, &fxxxx_fan_attr[0][0],
2212 ARRAY_SIZE(fxxxx_fan_attr[0]) * nr_fans);
Hans de Goede498be962009-01-07 16:37:28 +01002213 if (err)
2214 goto exit_unregister_sysfs;
2215
Hans de Goede78aa4f72011-03-09 20:57:12 +01002216 if (f71882fg_has_beep[data->type]) {
Hans de Goedeb69b0392009-12-09 20:36:00 +01002217 err = f71882fg_create_sysfs_files(pdev,
2218 fxxxx_fan_beep_attr, nr_fans);
2219 if (err)
2220 goto exit_unregister_sysfs;
2221 }
2222
Hans de Goedeed4f7c22009-01-07 16:37:30 +01002223 switch (data->type) {
Hans de Goedee5e713c2011-03-10 08:54:02 +01002224 case f71808e:
Hans de Goedec11bb992011-03-09 20:57:15 +01002225 case f71869:
Hans de Goedee48a7f12011-03-09 20:57:13 +01002226 case f71889fg:
Hans de Goede3cad4022011-03-09 20:57:14 +01002227 case f71889ed:
Hans de Goedee48a7f12011-03-09 20:57:13 +01002228 for (i = 0; i < nr_fans; i++) {
2229 data->pwm_auto_point_mapping[i] =
2230 f71882fg_read8(data,
2231 F71882FG_REG_POINT_MAPPING(i));
Hans de Goede3cad4022011-03-09 20:57:14 +01002232 if ((data->pwm_auto_point_mapping[i] & 0x80) ||
2233 (data->pwm_auto_point_mapping[i] & 3) == 0)
Hans de Goedee48a7f12011-03-09 20:57:13 +01002234 break;
2235 }
2236 if (i != nr_fans) {
2237 dev_warn(&pdev->dev,
2238 "Auto pwm controlled by raw digital "
2239 "data, disabling pwm auto_point "
2240 "sysfs attributes\n");
2241 goto no_pwm_auto_point;
2242 }
2243 break;
2244 default:
2245 break;
2246 }
2247
2248 switch (data->type) {
Hans de Goedeed4f7c22009-01-07 16:37:30 +01002249 case f71862fg:
Hans de Goede498be962009-01-07 16:37:28 +01002250 err = f71882fg_create_sysfs_files(pdev,
Hans de Goede66344aa2009-12-09 20:35:59 +01002251 f71862fg_auto_pwm_attr,
2252 ARRAY_SIZE(f71862fg_auto_pwm_attr));
Hans de Goedeed4f7c22009-01-07 16:37:30 +01002253 break;
Hans de Goedee5e713c2011-03-10 08:54:02 +01002254 case f71808e:
Hans de Goedec11bb992011-03-09 20:57:15 +01002255 case f71869:
2256 err = f71882fg_create_sysfs_files(pdev,
2257 f71869_auto_pwm_attr,
2258 ARRAY_SIZE(f71869_auto_pwm_attr));
2259 break;
Hans de Goedeed4f7c22009-01-07 16:37:30 +01002260 case f8000:
2261 err = f71882fg_create_sysfs_files(pdev,
2262 f8000_fan_attr,
2263 ARRAY_SIZE(f8000_fan_attr));
Hans de Goede66344aa2009-12-09 20:35:59 +01002264 if (err)
2265 goto exit_unregister_sysfs;
2266 err = f71882fg_create_sysfs_files(pdev,
2267 f8000_auto_pwm_attr,
2268 ARRAY_SIZE(f8000_auto_pwm_attr));
Hans de Goedeed4f7c22009-01-07 16:37:30 +01002269 break;
Hans de Goedee48a7f12011-03-09 20:57:13 +01002270 default:
Hans de Goedeb69b0392009-12-09 20:36:00 +01002271 err = f71882fg_create_sysfs_files(pdev,
2272 &fxxxx_auto_pwm_attr[0][0],
2273 ARRAY_SIZE(fxxxx_auto_pwm_attr[0]) * nr_fans);
Hans de Goede498be962009-01-07 16:37:28 +01002274 }
Hans de Goedec13548c2009-01-07 16:37:27 +01002275 if (err)
2276 goto exit_unregister_sysfs;
Hans de Goede28ba8582009-01-07 16:37:31 +01002277
Hans de Goedee48a7f12011-03-09 20:57:13 +01002278no_pwm_auto_point:
Hans de Goede28ba8582009-01-07 16:37:31 +01002279 for (i = 0; i < nr_fans; i++)
2280 dev_info(&pdev->dev, "Fan: %d is in %s mode\n", i + 1,
2281 (data->pwm_enable & (1 << 2 * i)) ?
2282 "duty-cycle" : "RPM");
Hans de Goede45fb3662007-07-13 14:34:19 +02002283 }
2284
Tony Jones1beeffe2007-08-20 13:46:20 -07002285 data->hwmon_dev = hwmon_device_register(&pdev->dev);
2286 if (IS_ERR(data->hwmon_dev)) {
2287 err = PTR_ERR(data->hwmon_dev);
Hans de Goedec13548c2009-01-07 16:37:27 +01002288 data->hwmon_dev = NULL;
Hans de Goede45fb3662007-07-13 14:34:19 +02002289 goto exit_unregister_sysfs;
2290 }
2291
2292 return 0;
2293
2294exit_unregister_sysfs:
Hans de Goedec13548c2009-01-07 16:37:27 +01002295 f71882fg_remove(pdev); /* Will unregister the sysfs files for us */
Hans de Goede3cc74752009-01-07 16:37:28 +01002296 return err; /* f71882fg_remove() also frees our data */
2297exit_free:
2298 kfree(data);
Hans de Goede45fb3662007-07-13 14:34:19 +02002299 return err;
2300}
2301
Hans de Goedec13548c2009-01-07 16:37:27 +01002302static int f71882fg_remove(struct platform_device *pdev)
Hans de Goede45fb3662007-07-13 14:34:19 +02002303{
Hans de Goede45fb3662007-07-13 14:34:19 +02002304 struct f71882fg_data *data = platform_get_drvdata(pdev);
Jean Delvaref27def02011-03-26 10:45:01 +01002305 int nr_fans = f71882fg_nr_fans[data->type];
2306 int nr_temps = f71882fg_nr_temps[data->type];
2307 int i;
Hans de Goedefc16c562009-12-09 20:36:01 +01002308 u8 start_reg = f71882fg_read8(data, F71882FG_REG_START);
Hans de Goede45fb3662007-07-13 14:34:19 +02002309
Hans de Goedec13548c2009-01-07 16:37:27 +01002310 if (data->hwmon_dev)
2311 hwmon_device_unregister(data->hwmon_dev);
Hans de Goede45fb3662007-07-13 14:34:19 +02002312
Hans de Goedec13548c2009-01-07 16:37:27 +01002313 device_remove_file(&pdev->dev, &dev_attr_name);
Hans de Goede45fb3662007-07-13 14:34:19 +02002314
Hans de Goedefc16c562009-12-09 20:36:01 +01002315 if (start_reg & 0x01) {
2316 switch (data->type) {
2317 case f71858fg:
2318 if (data->temp_config & 0x10)
2319 f71882fg_remove_sysfs_files(pdev,
Hans de Goede0bae6402011-03-09 20:57:10 +01002320 f8000_temp_attr,
2321 ARRAY_SIZE(f8000_temp_attr));
Hans de Goedefc16c562009-12-09 20:36:01 +01002322 else
2323 f71882fg_remove_sysfs_files(pdev,
Hans de Goede0bae6402011-03-09 20:57:10 +01002324 f71858fg_temp_attr,
2325 ARRAY_SIZE(f71858fg_temp_attr));
Hans de Goedefc16c562009-12-09 20:36:01 +01002326 break;
2327 case f8000:
2328 f71882fg_remove_sysfs_files(pdev,
Hans de Goede0bae6402011-03-09 20:57:10 +01002329 f8000_temp_attr,
2330 ARRAY_SIZE(f8000_temp_attr));
Hans de Goedefc16c562009-12-09 20:36:01 +01002331 break;
Hans de Goede0bae6402011-03-09 20:57:10 +01002332 default:
2333 f71882fg_remove_sysfs_files(pdev,
Hans de Goede60d2b372011-03-09 20:57:11 +01002334 &fxxxx_temp_attr[0][0],
2335 ARRAY_SIZE(fxxxx_temp_attr[0]) * nr_temps);
Hans de Goede0bae6402011-03-09 20:57:10 +01002336 }
Hans de Goede78aa4f72011-03-09 20:57:12 +01002337 if (f71882fg_has_beep[data->type]) {
2338 f71882fg_remove_sysfs_files(pdev,
2339 &fxxxx_temp_beep_attr[0][0],
2340 ARRAY_SIZE(fxxxx_temp_beep_attr[0]) * nr_temps);
2341 }
2342
Hans de Goede0bae6402011-03-09 20:57:10 +01002343 for (i = 0; i < F71882FG_MAX_INS; i++) {
2344 if (f71882fg_has_in[data->type][i]) {
2345 device_remove_file(&pdev->dev,
2346 &fxxxx_in_attr[i].dev_attr);
2347 }
2348 }
2349 if (f71882fg_has_in1_alarm[data->type]) {
2350 f71882fg_remove_sysfs_files(pdev,
2351 fxxxx_in1_alarm_attr,
2352 ARRAY_SIZE(fxxxx_in1_alarm_attr));
Hans de Goedefc16c562009-12-09 20:36:01 +01002353 }
2354 }
Hans de Goede498be962009-01-07 16:37:28 +01002355
Hans de Goedefc16c562009-12-09 20:36:01 +01002356 if (start_reg & 0x02) {
2357 f71882fg_remove_sysfs_files(pdev, &fxxxx_fan_attr[0][0],
2358 ARRAY_SIZE(fxxxx_fan_attr[0]) * nr_fans);
Hans de Goede45fb3662007-07-13 14:34:19 +02002359
Hans de Goede78aa4f72011-03-09 20:57:12 +01002360 if (f71882fg_has_beep[data->type]) {
Hans de Goedefc16c562009-12-09 20:36:01 +01002361 f71882fg_remove_sysfs_files(pdev,
2362 fxxxx_fan_beep_attr, nr_fans);
Hans de Goede78aa4f72011-03-09 20:57:12 +01002363 }
Hans de Goede498be962009-01-07 16:37:28 +01002364
Hans de Goedefc16c562009-12-09 20:36:01 +01002365 switch (data->type) {
2366 case f71862fg:
2367 f71882fg_remove_sysfs_files(pdev,
2368 f71862fg_auto_pwm_attr,
2369 ARRAY_SIZE(f71862fg_auto_pwm_attr));
2370 break;
Hans de Goedee5e713c2011-03-10 08:54:02 +01002371 case f71808e:
Hans de Goedec11bb992011-03-09 20:57:15 +01002372 case f71869:
2373 f71882fg_remove_sysfs_files(pdev,
2374 f71869_auto_pwm_attr,
2375 ARRAY_SIZE(f71869_auto_pwm_attr));
2376 break;
Hans de Goedefc16c562009-12-09 20:36:01 +01002377 case f8000:
2378 f71882fg_remove_sysfs_files(pdev,
2379 f8000_fan_attr,
2380 ARRAY_SIZE(f8000_fan_attr));
2381 f71882fg_remove_sysfs_files(pdev,
2382 f8000_auto_pwm_attr,
2383 ARRAY_SIZE(f8000_auto_pwm_attr));
2384 break;
Hans de Goede3cad4022011-03-09 20:57:14 +01002385 default:
Hans de Goedefc16c562009-12-09 20:36:01 +01002386 f71882fg_remove_sysfs_files(pdev,
2387 &fxxxx_auto_pwm_attr[0][0],
2388 ARRAY_SIZE(fxxxx_auto_pwm_attr[0]) * nr_fans);
2389 }
2390 }
Hans de Goedeed4f7c22009-01-07 16:37:30 +01002391
Hans de Goeded9ebaa42011-03-13 13:50:33 +01002392 platform_set_drvdata(pdev, NULL);
Hans de Goede45fb3662007-07-13 14:34:19 +02002393 kfree(data);
2394
2395 return 0;
2396}
2397
Hans de Goede498be962009-01-07 16:37:28 +01002398static int __init f71882fg_find(int sioaddr, unsigned short *address,
2399 struct f71882fg_sio_data *sio_data)
Hans de Goede45fb3662007-07-13 14:34:19 +02002400{
Hans de Goede45fb3662007-07-13 14:34:19 +02002401 u16 devid;
Giel van Schijndelcadb8652010-10-03 08:09:49 -04002402 int err = superio_enter(sioaddr);
2403 if (err)
2404 return err;
Hans de Goede45fb3662007-07-13 14:34:19 +02002405
2406 devid = superio_inw(sioaddr, SIO_REG_MANID);
2407 if (devid != SIO_FINTEK_ID) {
Joe Perches22d3b412010-10-20 06:51:34 +00002408 pr_debug("Not a Fintek device\n");
Giel van Schijndelcadb8652010-10-03 08:09:49 -04002409 err = -ENODEV;
Hans de Goede45fb3662007-07-13 14:34:19 +02002410 goto exit;
2411 }
2412
Jean Delvare67b671b2007-12-06 23:13:42 +01002413 devid = force_id ? force_id : superio_inw(sioaddr, SIO_REG_DEVID);
Hans de Goede498be962009-01-07 16:37:28 +01002414 switch (devid) {
Hans de Goedee5e713c2011-03-10 08:54:02 +01002415 case SIO_F71808E_ID:
2416 sio_data->type = f71808e;
2417 break;
Hans de Goede09475d32009-06-15 18:39:52 +02002418 case SIO_F71858_ID:
2419 sio_data->type = f71858fg;
2420 break;
Hans de Goede498be962009-01-07 16:37:28 +01002421 case SIO_F71862_ID:
2422 sio_data->type = f71862fg;
2423 break;
Hans de Goedec11bb992011-03-09 20:57:15 +01002424 case SIO_F71869_ID:
2425 sio_data->type = f71869;
2426 break;
Hans de Goede498be962009-01-07 16:37:28 +01002427 case SIO_F71882_ID:
2428 sio_data->type = f71882fg;
2429 break;
Hans de Goede76698962009-12-09 20:36:01 +01002430 case SIO_F71889_ID:
2431 sio_data->type = f71889fg;
2432 break;
Hans de Goede3cad4022011-03-09 20:57:14 +01002433 case SIO_F71889E_ID:
2434 sio_data->type = f71889ed;
2435 break;
Hans de Goedeed4f7c22009-01-07 16:37:30 +01002436 case SIO_F8000_ID:
2437 sio_data->type = f8000;
2438 break;
Jean Delvare383586b2011-03-26 10:45:02 +01002439 case SIO_F81865_ID:
2440 sio_data->type = f81865f;
2441 break;
Hans de Goede498be962009-01-07 16:37:28 +01002442 default:
Joe Perches22d3b412010-10-20 06:51:34 +00002443 pr_info("Unsupported Fintek device: %04x\n",
2444 (unsigned int)devid);
Giel van Schijndelcadb8652010-10-03 08:09:49 -04002445 err = -ENODEV;
Hans de Goede45fb3662007-07-13 14:34:19 +02002446 goto exit;
2447 }
2448
Hans de Goede09475d32009-06-15 18:39:52 +02002449 if (sio_data->type == f71858fg)
2450 superio_select(sioaddr, SIO_F71858FG_LD_HWM);
2451 else
2452 superio_select(sioaddr, SIO_F71882FG_LD_HWM);
2453
Mark M. Hoffman8afb1042007-08-21 23:10:46 -04002454 if (!(superio_inb(sioaddr, SIO_REG_ENABLE) & 0x01)) {
Joe Perches22d3b412010-10-20 06:51:34 +00002455 pr_warn("Device not activated\n");
Giel van Schijndelcadb8652010-10-03 08:09:49 -04002456 err = -ENODEV;
Hans de Goede45fb3662007-07-13 14:34:19 +02002457 goto exit;
2458 }
2459
2460 *address = superio_inw(sioaddr, SIO_REG_ADDR);
Giel van Schijndel162bb592010-05-27 19:58:40 +02002461 if (*address == 0) {
Joe Perches22d3b412010-10-20 06:51:34 +00002462 pr_warn("Base address not set\n");
Giel van Schijndelcadb8652010-10-03 08:09:49 -04002463 err = -ENODEV;
Hans de Goede45fb3662007-07-13 14:34:19 +02002464 goto exit;
2465 }
2466 *address &= ~(REGION_LENGTH - 1); /* Ignore 3 LSB */
2467
Hans de Goede45fb3662007-07-13 14:34:19 +02002468 err = 0;
Joe Perches22d3b412010-10-20 06:51:34 +00002469 pr_info("Found %s chip at %#x, revision %d\n",
Hans de Goede498be962009-01-07 16:37:28 +01002470 f71882fg_names[sio_data->type], (unsigned int)*address,
Hans de Goede45fb3662007-07-13 14:34:19 +02002471 (int)superio_inb(sioaddr, SIO_REG_DEVREV));
2472exit:
2473 superio_exit(sioaddr);
2474 return err;
2475}
2476
Hans de Goede498be962009-01-07 16:37:28 +01002477static int __init f71882fg_device_add(unsigned short address,
2478 const struct f71882fg_sio_data *sio_data)
Hans de Goede45fb3662007-07-13 14:34:19 +02002479{
2480 struct resource res = {
2481 .start = address,
2482 .end = address + REGION_LENGTH - 1,
2483 .flags = IORESOURCE_IO,
2484 };
2485 int err;
2486
2487 f71882fg_pdev = platform_device_alloc(DRVNAME, address);
Mark M. Hoffman8afb1042007-08-21 23:10:46 -04002488 if (!f71882fg_pdev)
Hans de Goede45fb3662007-07-13 14:34:19 +02002489 return -ENOMEM;
2490
2491 res.name = f71882fg_pdev->name;
Jean Delvareb9acb642009-01-07 16:37:35 +01002492 err = acpi_check_resource_conflict(&res);
2493 if (err)
Hans de Goede18632f82009-02-17 19:59:54 +01002494 goto exit_device_put;
Jean Delvareb9acb642009-01-07 16:37:35 +01002495
Hans de Goede45fb3662007-07-13 14:34:19 +02002496 err = platform_device_add_resources(f71882fg_pdev, &res, 1);
Mark M. Hoffman8afb1042007-08-21 23:10:46 -04002497 if (err) {
Joe Perches22d3b412010-10-20 06:51:34 +00002498 pr_err("Device resource addition failed\n");
Hans de Goede45fb3662007-07-13 14:34:19 +02002499 goto exit_device_put;
2500 }
2501
Hans de Goede498be962009-01-07 16:37:28 +01002502 err = platform_device_add_data(f71882fg_pdev, sio_data,
2503 sizeof(struct f71882fg_sio_data));
2504 if (err) {
Joe Perches22d3b412010-10-20 06:51:34 +00002505 pr_err("Platform data allocation failed\n");
Hans de Goede498be962009-01-07 16:37:28 +01002506 goto exit_device_put;
2507 }
2508
Hans de Goede45fb3662007-07-13 14:34:19 +02002509 err = platform_device_add(f71882fg_pdev);
Mark M. Hoffman8afb1042007-08-21 23:10:46 -04002510 if (err) {
Joe Perches22d3b412010-10-20 06:51:34 +00002511 pr_err("Device addition failed\n");
Hans de Goede45fb3662007-07-13 14:34:19 +02002512 goto exit_device_put;
2513 }
2514
2515 return 0;
2516
2517exit_device_put:
2518 platform_device_put(f71882fg_pdev);
2519
2520 return err;
2521}
2522
2523static int __init f71882fg_init(void)
2524{
2525 int err = -ENODEV;
2526 unsigned short address;
Hans de Goede498be962009-01-07 16:37:28 +01002527 struct f71882fg_sio_data sio_data;
Hans de Goede45fb3662007-07-13 14:34:19 +02002528
Hans de Goede498be962009-01-07 16:37:28 +01002529 memset(&sio_data, 0, sizeof(sio_data));
2530
2531 if (f71882fg_find(0x2e, &address, &sio_data) &&
2532 f71882fg_find(0x4e, &address, &sio_data))
Hans de Goede45fb3662007-07-13 14:34:19 +02002533 goto exit;
2534
Hans de Goedec13548c2009-01-07 16:37:27 +01002535 err = platform_driver_register(&f71882fg_driver);
2536 if (err)
Hans de Goede45fb3662007-07-13 14:34:19 +02002537 goto exit;
2538
Hans de Goede498be962009-01-07 16:37:28 +01002539 err = f71882fg_device_add(address, &sio_data);
Hans de Goedec13548c2009-01-07 16:37:27 +01002540 if (err)
Hans de Goede45fb3662007-07-13 14:34:19 +02002541 goto exit_driver;
2542
2543 return 0;
2544
2545exit_driver:
2546 platform_driver_unregister(&f71882fg_driver);
2547exit:
2548 return err;
2549}
2550
2551static void __exit f71882fg_exit(void)
2552{
2553 platform_device_unregister(f71882fg_pdev);
2554 platform_driver_unregister(&f71882fg_driver);
2555}
2556
2557MODULE_DESCRIPTION("F71882FG Hardware Monitoring Driver");
Hans de Goedec13548c2009-01-07 16:37:27 +01002558MODULE_AUTHOR("Hans Edgington, Hans de Goede (hdegoede@redhat.com)");
Hans de Goede45fb3662007-07-13 14:34:19 +02002559MODULE_LICENSE("GPL");
2560
2561module_init(f71882fg_init);
2562module_exit(f71882fg_exit);