11a59d1b8SThomas Gleixner // SPDX-License-Identifier: GPL-2.0-or-later
245fb3669SHans de Goede /***************************************************************************
345fb3669SHans de Goede * Copyright (C) 2006 by Hans Edgington <hans@edgington.nl> *
444c4dc52SHans de Goede * Copyright (C) 2007-2011 Hans de Goede <hdegoede@redhat.com> *
545fb3669SHans de Goede * *
645fb3669SHans de Goede ***************************************************************************/
745fb3669SHans de Goede
822d3b412SJoe Perches #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
922d3b412SJoe Perches
1045fb3669SHans de Goede #include <linux/module.h>
1145fb3669SHans de Goede #include <linux/init.h>
1245fb3669SHans de Goede #include <linux/slab.h>
1345fb3669SHans de Goede #include <linux/jiffies.h>
1445fb3669SHans de Goede #include <linux/platform_device.h>
1545fb3669SHans de Goede #include <linux/hwmon.h>
1645fb3669SHans de Goede #include <linux/hwmon-sysfs.h>
1745fb3669SHans de Goede #include <linux/err.h>
1845fb3669SHans de Goede #include <linux/mutex.h>
1977a4a3e2SMark van Doesburg #include <linux/io.h>
20b9acb64aSJean Delvare #include <linux/acpi.h>
2145fb3669SHans de Goede
2245fb3669SHans de Goede #define DRVNAME "f71882fg"
2345fb3669SHans de Goede
2409475d32SHans de Goede #define SIO_F71858FG_LD_HWM 0x02 /* Hardware monitor logical device */
2545fb3669SHans de Goede #define SIO_F71882FG_LD_HWM 0x04 /* Hardware monitor logical device */
2645fb3669SHans de Goede #define SIO_UNLOCK_KEY 0x87 /* Key to enable Super-I/O */
2714a4019dSHans de Goede #define SIO_LOCK_KEY 0xAA /* Key to disable Super-I/O */
2845fb3669SHans de Goede
2945fb3669SHans de Goede #define SIO_REG_LDSEL 0x07 /* Logical device select */
3045fb3669SHans de Goede #define SIO_REG_DEVID 0x20 /* Device ID (2 bytes) */
3145fb3669SHans de Goede #define SIO_REG_DEVREV 0x22 /* Device revision */
3245fb3669SHans de Goede #define SIO_REG_MANID 0x23 /* Fintek ID (2 bytes) */
3345fb3669SHans de Goede #define SIO_REG_ENABLE 0x30 /* Logical device enable */
3445fb3669SHans de Goede #define SIO_REG_ADDR 0x60 /* Logical device address (2 bytes) */
3545fb3669SHans de Goede
3645fb3669SHans de Goede #define SIO_FINTEK_ID 0x1934 /* Manufacturers ID */
37e5e713cbSHans de Goede #define SIO_F71808E_ID 0x0901 /* Chipset ID */
38629c58baSHans de Goede #define SIO_F71808A_ID 0x1001 /* Chipset ID */
3909475d32SHans de Goede #define SIO_F71858_ID 0x0507 /* Chipset ID */
40498be968SHans de Goede #define SIO_F71862_ID 0x0601 /* Chipset ID */
412725fe2bSPeter Hung #define SIO_F71868_ID 0x1106 /* Chipset ID */
42c11bb993SHans de Goede #define SIO_F71869_ID 0x0814 /* Chipset ID */
435da556e3SHans de Goede #define SIO_F71869A_ID 0x1007 /* Chipset ID */
4445fb3669SHans de Goede #define SIO_F71882_ID 0x0541 /* Chipset ID */
457669896fSHans de Goede #define SIO_F71889_ID 0x0723 /* Chipset ID */
463cad4022SHans de Goede #define SIO_F71889E_ID 0x0909 /* Chipset ID */
47a66c1088SHans de Goede #define SIO_F71889A_ID 0x1005 /* Chipset ID */
48ed4f7c20SHans de Goede #define SIO_F8000_ID 0x0581 /* Chipset ID */
49d8363bb5SGeorge Joseph #define SIO_F81768D_ID 0x1210 /* Chipset ID */
50383586b1SJean Delvare #define SIO_F81865_ID 0x0704 /* Chipset ID */
512725fe2bSPeter Hung #define SIO_F81866_ID 0x1010 /* Chipset ID */
52739743ecSAleksander Mazur #define SIO_F71858AD_ID 0x0903 /* Chipset ID */
53df293076SMenghui Wu #define SIO_F81966_ID 0x1502 /* Chipset ID */
5445fb3669SHans de Goede
5545fb3669SHans de Goede #define REGION_LENGTH 8
5645fb3669SHans de Goede #define ADDR_REG_OFFSET 5
5745fb3669SHans de Goede #define DATA_REG_OFFSET 6
5845fb3669SHans de Goede
593cad4022SHans de Goede #define F71882FG_REG_IN_STATUS 0x12 /* f7188x only */
603cad4022SHans de Goede #define F71882FG_REG_IN_BEEP 0x13 /* f7188x only */
6145fb3669SHans de Goede #define F71882FG_REG_IN(nr) (0x20 + (nr))
623cad4022SHans de Goede #define F71882FG_REG_IN1_HIGH 0x32 /* f7188x only */
6345fb3669SHans de Goede
643e40b860SPeter Hung #define F81866_REG_IN_STATUS 0x16 /* F81866 only */
653e40b860SPeter Hung #define F81866_REG_IN_BEEP 0x17 /* F81866 only */
663e40b860SPeter Hung #define F81866_REG_IN1_HIGH 0x3a /* F81866 only */
673e40b860SPeter Hung
6845fb3669SHans de Goede #define F71882FG_REG_FAN(nr) (0xA0 + (16 * (nr)))
699ab796ebSMark van Doesburg #define F71882FG_REG_FAN_TARGET(nr) (0xA2 + (16 * (nr)))
709ab796ebSMark van Doesburg #define F71882FG_REG_FAN_FULL_SPEED(nr) (0xA4 + (16 * (nr)))
7145fb3669SHans de Goede #define F71882FG_REG_FAN_STATUS 0x92
7245fb3669SHans de Goede #define F71882FG_REG_FAN_BEEP 0x93
7345fb3669SHans de Goede
747567a043SHans de Goede #define F71882FG_REG_TEMP(nr) (0x70 + 2 * (nr))
757567a043SHans de Goede #define F71882FG_REG_TEMP_OVT(nr) (0x80 + 2 * (nr))
767567a043SHans de Goede #define F71882FG_REG_TEMP_HIGH(nr) (0x81 + 2 * (nr))
7745fb3669SHans de Goede #define F71882FG_REG_TEMP_STATUS 0x62
7845fb3669SHans de Goede #define F71882FG_REG_TEMP_BEEP 0x63
7909475d32SHans de Goede #define F71882FG_REG_TEMP_CONFIG 0x69
80bc27490fSHans de Goede #define F71882FG_REG_TEMP_HYST(nr) (0x6C + (nr))
8145fb3669SHans de Goede #define F71882FG_REG_TEMP_TYPE 0x6B
8245fb3669SHans de Goede #define F71882FG_REG_TEMP_DIODE_OPEN 0x6F
8345fb3669SHans de Goede
849ab796ebSMark van Doesburg #define F71882FG_REG_PWM(nr) (0xA3 + (16 * (nr)))
859ab796ebSMark van Doesburg #define F71882FG_REG_PWM_TYPE 0x94
869ab796ebSMark van Doesburg #define F71882FG_REG_PWM_ENABLE 0x96
879ab796ebSMark van Doesburg
88bc27490fSHans de Goede #define F71882FG_REG_FAN_HYST(nr) (0x98 + (nr))
899ab796ebSMark van Doesburg
9098f7ba19SHans de Goede #define F71882FG_REG_FAN_FAULT_T 0x9F
9198f7ba19SHans de Goede #define F71882FG_FAN_NEG_TEMP_EN 0x20
923cad4022SHans de Goede #define F71882FG_FAN_PROG_SEL 0x80
9398f7ba19SHans de Goede
949ab796ebSMark van Doesburg #define F71882FG_REG_POINT_PWM(pwm, point) (0xAA + (point) + (16 * (pwm)))
959ab796ebSMark van Doesburg #define F71882FG_REG_POINT_TEMP(pwm, point) (0xA6 + (point) + (16 * (pwm)))
969ab796ebSMark van Doesburg #define F71882FG_REG_POINT_MAPPING(nr) (0xAF + 16 * (nr))
979ab796ebSMark van Doesburg
9845fb3669SHans de Goede #define F71882FG_REG_START 0x01
9945fb3669SHans de Goede
100d8363bb5SGeorge Joseph #define F71882FG_MAX_INS 11
1010bae6400SHans de Goede
10245fb3669SHans de Goede #define FAN_MIN_DETECT 366 /* Lowest detectable fanspeed */
10345fb3669SHans de Goede
10467b671bcSJean Delvare static unsigned short force_id;
10567b671bcSJean Delvare module_param(force_id, ushort, 0);
10667b671bcSJean Delvare MODULE_PARM_DESC(force_id, "Override the detected device ID");
10767b671bcSJean Delvare
1082725fe2bSPeter Hung enum chips { f71808e, f71808a, f71858fg, f71862fg, f71868a, f71869, f71869a,
109d8363bb5SGeorge Joseph f71882fg, f71889fg, f71889ed, f71889a, f8000, f81768d, f81865f,
110d8363bb5SGeorge Joseph f81866a};
111498be968SHans de Goede
1121dc37089SFrans Meulenbroeks static const char *const f71882fg_names[] = {
113e5e713cbSHans de Goede "f71808e",
114629c58baSHans de Goede "f71808a",
11509475d32SHans de Goede "f71858fg",
116498be968SHans de Goede "f71862fg",
1172725fe2bSPeter Hung "f71868a",
118c11bb993SHans de Goede "f71869", /* Both f71869f and f71869e, reg. compatible and same id */
1195da556e3SHans de Goede "f71869a",
120498be968SHans de Goede "f71882fg",
1215d7f77bfSJean Delvare "f71889fg", /* f81801u too, same id */
1223cad4022SHans de Goede "f71889ed",
123a66c1088SHans de Goede "f71889a",
124ed4f7c20SHans de Goede "f8000",
125d8363bb5SGeorge Joseph "f81768d",
126383586b1SJean Delvare "f81865f",
1272725fe2bSPeter Hung "f81866a",
128498be968SHans de Goede };
129498be968SHans de Goede
1302740c60cSJean Delvare static const char f71882fg_has_in[][F71882FG_MAX_INS] = {
131d8363bb5SGeorge Joseph [f71808e] = { 1, 1, 1, 1, 1, 1, 0, 1, 1, 0, 0 },
132d8363bb5SGeorge Joseph [f71808a] = { 1, 1, 1, 1, 0, 0, 0, 1, 1, 0, 0 },
133d8363bb5SGeorge Joseph [f71858fg] = { 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0 },
134d8363bb5SGeorge Joseph [f71862fg] = { 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0 },
135d8363bb5SGeorge Joseph [f71868a] = { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0 },
136d8363bb5SGeorge Joseph [f71869] = { 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0 },
137d8363bb5SGeorge Joseph [f71869a] = { 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0 },
138d8363bb5SGeorge Joseph [f71882fg] = { 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0 },
139d8363bb5SGeorge Joseph [f71889fg] = { 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0 },
140d8363bb5SGeorge Joseph [f71889ed] = { 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0 },
141d8363bb5SGeorge Joseph [f71889a] = { 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0 },
142d8363bb5SGeorge Joseph [f8000] = { 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0 },
143d8363bb5SGeorge Joseph [f81768d] = { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 },
144d8363bb5SGeorge Joseph [f81865f] = { 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0 },
145d8363bb5SGeorge Joseph [f81866a] = { 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0 },
1460bae6400SHans de Goede };
1470bae6400SHans de Goede
1482740c60cSJean Delvare static const char f71882fg_has_in1_alarm[] = {
1492740c60cSJean Delvare [f71808e] = 0,
150629c58baSHans de Goede [f71808a] = 0,
1512740c60cSJean Delvare [f71858fg] = 0,
1522740c60cSJean Delvare [f71862fg] = 0,
1532725fe2bSPeter Hung [f71868a] = 0,
1542740c60cSJean Delvare [f71869] = 0,
1555da556e3SHans de Goede [f71869a] = 0,
1562740c60cSJean Delvare [f71882fg] = 1,
1572740c60cSJean Delvare [f71889fg] = 1,
1582740c60cSJean Delvare [f71889ed] = 1,
159a66c1088SHans de Goede [f71889a] = 1,
1602740c60cSJean Delvare [f8000] = 0,
161d8363bb5SGeorge Joseph [f81768d] = 1,
162383586b1SJean Delvare [f81865f] = 1,
1632725fe2bSPeter Hung [f81866a] = 1,
1640bae6400SHans de Goede };
1650bae6400SHans de Goede
1664d53811aSHans de Goede static const char f71882fg_fan_has_beep[] = {
1672740c60cSJean Delvare [f71808e] = 0,
168629c58baSHans de Goede [f71808a] = 0,
1692740c60cSJean Delvare [f71858fg] = 0,
1702740c60cSJean Delvare [f71862fg] = 1,
1712725fe2bSPeter Hung [f71868a] = 1,
1722740c60cSJean Delvare [f71869] = 1,
1735da556e3SHans de Goede [f71869a] = 1,
1742740c60cSJean Delvare [f71882fg] = 1,
1752740c60cSJean Delvare [f71889fg] = 1,
1762740c60cSJean Delvare [f71889ed] = 1,
177a66c1088SHans de Goede [f71889a] = 1,
1782740c60cSJean Delvare [f8000] = 0,
179d8363bb5SGeorge Joseph [f81768d] = 1,
180383586b1SJean Delvare [f81865f] = 1,
1812725fe2bSPeter Hung [f81866a] = 1,
18278aa4f72SHans de Goede };
18378aa4f72SHans de Goede
184f27def07SJean Delvare static const char f71882fg_nr_fans[] = {
185f27def07SJean Delvare [f71808e] = 3,
186629c58baSHans de Goede [f71808a] = 2, /* +1 fan which is monitor + simple pwm only */
187f27def07SJean Delvare [f71858fg] = 3,
188f27def07SJean Delvare [f71862fg] = 3,
1892725fe2bSPeter Hung [f71868a] = 3,
190f27def07SJean Delvare [f71869] = 3,
1915da556e3SHans de Goede [f71869a] = 3,
192f27def07SJean Delvare [f71882fg] = 4,
193f27def07SJean Delvare [f71889fg] = 3,
194f27def07SJean Delvare [f71889ed] = 3,
195a66c1088SHans de Goede [f71889a] = 3,
196629c58baSHans de Goede [f8000] = 3, /* +1 fan which is monitor only */
197d8363bb5SGeorge Joseph [f81768d] = 3,
198383586b1SJean Delvare [f81865f] = 2,
1992725fe2bSPeter Hung [f81866a] = 3,
200f27def07SJean Delvare };
201f27def07SJean Delvare
2024d53811aSHans de Goede static const char f71882fg_temp_has_beep[] = {
2034d53811aSHans de Goede [f71808e] = 0,
204629c58baSHans de Goede [f71808a] = 1,
2054d53811aSHans de Goede [f71858fg] = 0,
2064d53811aSHans de Goede [f71862fg] = 1,
2072725fe2bSPeter Hung [f71868a] = 1,
2084d53811aSHans de Goede [f71869] = 1,
2095da556e3SHans de Goede [f71869a] = 1,
2104d53811aSHans de Goede [f71882fg] = 1,
2114d53811aSHans de Goede [f71889fg] = 1,
2124d53811aSHans de Goede [f71889ed] = 1,
2134d53811aSHans de Goede [f71889a] = 1,
2144d53811aSHans de Goede [f8000] = 0,
215d8363bb5SGeorge Joseph [f81768d] = 1,
2164d53811aSHans de Goede [f81865f] = 1,
2172725fe2bSPeter Hung [f81866a] = 1,
2184d53811aSHans de Goede };
2194d53811aSHans de Goede
220f27def07SJean Delvare static const char f71882fg_nr_temps[] = {
221f27def07SJean Delvare [f71808e] = 2,
222629c58baSHans de Goede [f71808a] = 2,
223f27def07SJean Delvare [f71858fg] = 3,
224f27def07SJean Delvare [f71862fg] = 3,
2252725fe2bSPeter Hung [f71868a] = 3,
226f27def07SJean Delvare [f71869] = 3,
2275da556e3SHans de Goede [f71869a] = 3,
228f27def07SJean Delvare [f71882fg] = 3,
229f27def07SJean Delvare [f71889fg] = 3,
230f27def07SJean Delvare [f71889ed] = 3,
231a66c1088SHans de Goede [f71889a] = 3,
232f27def07SJean Delvare [f8000] = 3,
233d8363bb5SGeorge Joseph [f81768d] = 3,
234383586b1SJean Delvare [f81865f] = 2,
2352725fe2bSPeter Hung [f81866a] = 3,
236f27def07SJean Delvare };
237f27def07SJean Delvare
23877a4a3e2SMark van Doesburg static struct platform_device *f71882fg_pdev;
23945fb3669SHans de Goede
240498be968SHans de Goede struct f71882fg_sio_data {
241498be968SHans de Goede enum chips type;
242498be968SHans de Goede };
243498be968SHans de Goede
24445fb3669SHans de Goede struct f71882fg_data {
24545fb3669SHans de Goede unsigned short addr;
246498be968SHans de Goede enum chips type;
2471beeffe4STony Jones struct device *hwmon_dev;
24845fb3669SHans de Goede
24945fb3669SHans de Goede struct mutex update_lock;
25009475d32SHans de Goede int temp_start; /* temp numbering start (0 or 1) */
251952a11caSPaul Fertser bool valid; /* true if following fields are valid */
25298f7ba19SHans de Goede char auto_point_temp_signed;
25345fb3669SHans de Goede unsigned long last_updated; /* In jiffies */
25445fb3669SHans de Goede unsigned long last_limits; /* In jiffies */
25545fb3669SHans de Goede
25645fb3669SHans de Goede /* Register Values */
2570bae6400SHans de Goede u8 in[F71882FG_MAX_INS];
25845fb3669SHans de Goede u8 in1_max;
25945fb3669SHans de Goede u8 in_status;
26045fb3669SHans de Goede u8 in_beep;
26145fb3669SHans de Goede u16 fan[4];
2629ab796ebSMark van Doesburg u16 fan_target[4];
2639ab796ebSMark van Doesburg u16 fan_full_speed[4];
26445fb3669SHans de Goede u8 fan_status;
26545fb3669SHans de Goede u8 fan_beep;
26620eaf724SGuenter Roeck /*
26720eaf724SGuenter Roeck * Note: all models have max 3 temperature channels, but on some
26820eaf724SGuenter Roeck * they are addressed as 0-2 and on others as 1-3, so for coding
26920eaf724SGuenter Roeck * convenience we reserve space for 4 channels
27020eaf724SGuenter Roeck */
27109475d32SHans de Goede u16 temp[4];
2727567a043SHans de Goede u8 temp_ovt[4];
2737567a043SHans de Goede u8 temp_high[4];
274bc27490fSHans de Goede u8 temp_hyst[2]; /* 2 hysts stored per reg */
2757567a043SHans de Goede u8 temp_type[4];
27645fb3669SHans de Goede u8 temp_status;
27745fb3669SHans de Goede u8 temp_beep;
27845fb3669SHans de Goede u8 temp_diode_open;
27909475d32SHans de Goede u8 temp_config;
2809ab796ebSMark van Doesburg u8 pwm[4];
2819ab796ebSMark van Doesburg u8 pwm_enable;
2829ab796ebSMark van Doesburg u8 pwm_auto_point_hyst[2];
2839ab796ebSMark van Doesburg u8 pwm_auto_point_mapping[4];
2849ab796ebSMark van Doesburg u8 pwm_auto_point_pwm[4][5];
2857669896fSHans de Goede s8 pwm_auto_point_temp[4][4];
28645fb3669SHans de Goede };
28745fb3669SHans de Goede
f71882fg_read8(struct f71882fg_data * data,u8 reg)288df9ec2daSUwe Kleine-König static u8 f71882fg_read8(struct f71882fg_data *data, u8 reg)
289df9ec2daSUwe Kleine-König {
290df9ec2daSUwe Kleine-König u8 val;
291df9ec2daSUwe Kleine-König
292df9ec2daSUwe Kleine-König outb(reg, data->addr + ADDR_REG_OFFSET);
293df9ec2daSUwe Kleine-König val = inb(data->addr + DATA_REG_OFFSET);
294df9ec2daSUwe Kleine-König
295df9ec2daSUwe Kleine-König return val;
296df9ec2daSUwe Kleine-König }
297df9ec2daSUwe Kleine-König
f71882fg_read16(struct f71882fg_data * data,u8 reg)298df9ec2daSUwe Kleine-König static u16 f71882fg_read16(struct f71882fg_data *data, u8 reg)
299df9ec2daSUwe Kleine-König {
300df9ec2daSUwe Kleine-König u16 val;
301df9ec2daSUwe Kleine-König
302df9ec2daSUwe Kleine-König val = f71882fg_read8(data, reg) << 8;
303df9ec2daSUwe Kleine-König val |= f71882fg_read8(data, reg + 1);
304df9ec2daSUwe Kleine-König
305df9ec2daSUwe Kleine-König return val;
306df9ec2daSUwe Kleine-König }
307df9ec2daSUwe Kleine-König
fan_from_reg(u16 reg)308df9ec2daSUwe Kleine-König static inline int fan_from_reg(u16 reg)
309df9ec2daSUwe Kleine-König {
310df9ec2daSUwe Kleine-König return reg ? (1500000 / reg) : 0;
311df9ec2daSUwe Kleine-König }
312df9ec2daSUwe Kleine-König
fan_to_reg(int fan)313df9ec2daSUwe Kleine-König static inline u16 fan_to_reg(int fan)
314df9ec2daSUwe Kleine-König {
315df9ec2daSUwe Kleine-König return fan ? (1500000 / fan) : 0;
316df9ec2daSUwe Kleine-König }
317df9ec2daSUwe Kleine-König
f71882fg_write8(struct f71882fg_data * data,u8 reg,u8 val)318df9ec2daSUwe Kleine-König static void f71882fg_write8(struct f71882fg_data *data, u8 reg, u8 val)
319df9ec2daSUwe Kleine-König {
320df9ec2daSUwe Kleine-König outb(reg, data->addr + ADDR_REG_OFFSET);
321df9ec2daSUwe Kleine-König outb(val, data->addr + DATA_REG_OFFSET);
322df9ec2daSUwe Kleine-König }
323df9ec2daSUwe Kleine-König
f71882fg_write16(struct f71882fg_data * data,u8 reg,u16 val)324df9ec2daSUwe Kleine-König static void f71882fg_write16(struct f71882fg_data *data, u8 reg, u16 val)
325df9ec2daSUwe Kleine-König {
326df9ec2daSUwe Kleine-König f71882fg_write8(data, reg, val >> 8);
327df9ec2daSUwe Kleine-König f71882fg_write8(data, reg + 1, val & 0xff);
328df9ec2daSUwe Kleine-König }
329df9ec2daSUwe Kleine-König
f71882fg_read_temp(struct f71882fg_data * data,int nr)330df9ec2daSUwe Kleine-König static u16 f71882fg_read_temp(struct f71882fg_data *data, int nr)
331df9ec2daSUwe Kleine-König {
332df9ec2daSUwe Kleine-König if (data->type == f71858fg)
333df9ec2daSUwe Kleine-König return f71882fg_read16(data, F71882FG_REG_TEMP(nr));
334df9ec2daSUwe Kleine-König else
335df9ec2daSUwe Kleine-König return f71882fg_read8(data, F71882FG_REG_TEMP(nr));
336df9ec2daSUwe Kleine-König }
337df9ec2daSUwe Kleine-König
f71882fg_update_device(struct device * dev)338df9ec2daSUwe Kleine-König static struct f71882fg_data *f71882fg_update_device(struct device *dev)
339df9ec2daSUwe Kleine-König {
340df9ec2daSUwe Kleine-König struct f71882fg_data *data = dev_get_drvdata(dev);
341df9ec2daSUwe Kleine-König int nr_fans = f71882fg_nr_fans[data->type];
342df9ec2daSUwe Kleine-König int nr_temps = f71882fg_nr_temps[data->type];
343df9ec2daSUwe Kleine-König int nr, reg, point;
344df9ec2daSUwe Kleine-König
345df9ec2daSUwe Kleine-König mutex_lock(&data->update_lock);
346df9ec2daSUwe Kleine-König
347df9ec2daSUwe Kleine-König /* Update once every 60 seconds */
348df9ec2daSUwe Kleine-König if (time_after(jiffies, data->last_limits + 60 * HZ) ||
349df9ec2daSUwe Kleine-König !data->valid) {
350df9ec2daSUwe Kleine-König if (f71882fg_has_in1_alarm[data->type]) {
351df9ec2daSUwe Kleine-König if (data->type == f81866a) {
352df9ec2daSUwe Kleine-König data->in1_max =
353df9ec2daSUwe Kleine-König f71882fg_read8(data,
354df9ec2daSUwe Kleine-König F81866_REG_IN1_HIGH);
355df9ec2daSUwe Kleine-König data->in_beep =
356df9ec2daSUwe Kleine-König f71882fg_read8(data,
357df9ec2daSUwe Kleine-König F81866_REG_IN_BEEP);
358df9ec2daSUwe Kleine-König } else {
359df9ec2daSUwe Kleine-König data->in1_max =
360df9ec2daSUwe Kleine-König f71882fg_read8(data,
361df9ec2daSUwe Kleine-König F71882FG_REG_IN1_HIGH);
362df9ec2daSUwe Kleine-König data->in_beep =
363df9ec2daSUwe Kleine-König f71882fg_read8(data,
364df9ec2daSUwe Kleine-König F71882FG_REG_IN_BEEP);
365df9ec2daSUwe Kleine-König }
366df9ec2daSUwe Kleine-König }
367df9ec2daSUwe Kleine-König
368df9ec2daSUwe Kleine-König /* Get High & boundary temps*/
369df9ec2daSUwe Kleine-König for (nr = data->temp_start; nr < nr_temps + data->temp_start;
370df9ec2daSUwe Kleine-König nr++) {
371df9ec2daSUwe Kleine-König data->temp_ovt[nr] = f71882fg_read8(data,
372df9ec2daSUwe Kleine-König F71882FG_REG_TEMP_OVT(nr));
373df9ec2daSUwe Kleine-König data->temp_high[nr] = f71882fg_read8(data,
374df9ec2daSUwe Kleine-König F71882FG_REG_TEMP_HIGH(nr));
375df9ec2daSUwe Kleine-König }
376df9ec2daSUwe Kleine-König
377df9ec2daSUwe Kleine-König if (data->type != f8000) {
378df9ec2daSUwe Kleine-König data->temp_hyst[0] = f71882fg_read8(data,
379df9ec2daSUwe Kleine-König F71882FG_REG_TEMP_HYST(0));
380df9ec2daSUwe Kleine-König data->temp_hyst[1] = f71882fg_read8(data,
381df9ec2daSUwe Kleine-König F71882FG_REG_TEMP_HYST(1));
382df9ec2daSUwe Kleine-König }
383df9ec2daSUwe Kleine-König /* All but the f71858fg / f8000 have this register */
384df9ec2daSUwe Kleine-König if ((data->type != f71858fg) && (data->type != f8000)) {
385df9ec2daSUwe Kleine-König reg = f71882fg_read8(data, F71882FG_REG_TEMP_TYPE);
386df9ec2daSUwe Kleine-König data->temp_type[1] = (reg & 0x02) ? 2 : 4;
387df9ec2daSUwe Kleine-König data->temp_type[2] = (reg & 0x04) ? 2 : 4;
388df9ec2daSUwe Kleine-König data->temp_type[3] = (reg & 0x08) ? 2 : 4;
389df9ec2daSUwe Kleine-König }
390df9ec2daSUwe Kleine-König
391df9ec2daSUwe Kleine-König if (f71882fg_fan_has_beep[data->type])
392df9ec2daSUwe Kleine-König data->fan_beep = f71882fg_read8(data,
393df9ec2daSUwe Kleine-König F71882FG_REG_FAN_BEEP);
394df9ec2daSUwe Kleine-König
395df9ec2daSUwe Kleine-König if (f71882fg_temp_has_beep[data->type])
396df9ec2daSUwe Kleine-König data->temp_beep = f71882fg_read8(data,
397df9ec2daSUwe Kleine-König F71882FG_REG_TEMP_BEEP);
398df9ec2daSUwe Kleine-König
399df9ec2daSUwe Kleine-König data->pwm_enable = f71882fg_read8(data,
400df9ec2daSUwe Kleine-König F71882FG_REG_PWM_ENABLE);
401df9ec2daSUwe Kleine-König data->pwm_auto_point_hyst[0] =
402df9ec2daSUwe Kleine-König f71882fg_read8(data, F71882FG_REG_FAN_HYST(0));
403df9ec2daSUwe Kleine-König data->pwm_auto_point_hyst[1] =
404df9ec2daSUwe Kleine-König f71882fg_read8(data, F71882FG_REG_FAN_HYST(1));
405df9ec2daSUwe Kleine-König
406df9ec2daSUwe Kleine-König for (nr = 0; nr < nr_fans; nr++) {
407df9ec2daSUwe Kleine-König data->pwm_auto_point_mapping[nr] =
408df9ec2daSUwe Kleine-König f71882fg_read8(data,
409df9ec2daSUwe Kleine-König F71882FG_REG_POINT_MAPPING(nr));
410df9ec2daSUwe Kleine-König
411df9ec2daSUwe Kleine-König switch (data->type) {
412df9ec2daSUwe Kleine-König default:
413df9ec2daSUwe Kleine-König for (point = 0; point < 5; point++) {
414df9ec2daSUwe Kleine-König data->pwm_auto_point_pwm[nr][point] =
415df9ec2daSUwe Kleine-König f71882fg_read8(data,
416df9ec2daSUwe Kleine-König F71882FG_REG_POINT_PWM
417df9ec2daSUwe Kleine-König (nr, point));
418df9ec2daSUwe Kleine-König }
419df9ec2daSUwe Kleine-König for (point = 0; point < 4; point++) {
420df9ec2daSUwe Kleine-König data->pwm_auto_point_temp[nr][point] =
421df9ec2daSUwe Kleine-König f71882fg_read8(data,
422df9ec2daSUwe Kleine-König F71882FG_REG_POINT_TEMP
423df9ec2daSUwe Kleine-König (nr, point));
424df9ec2daSUwe Kleine-König }
425df9ec2daSUwe Kleine-König break;
426df9ec2daSUwe Kleine-König case f71808e:
427df9ec2daSUwe Kleine-König case f71869:
428df9ec2daSUwe Kleine-König data->pwm_auto_point_pwm[nr][0] =
429df9ec2daSUwe Kleine-König f71882fg_read8(data,
430df9ec2daSUwe Kleine-König F71882FG_REG_POINT_PWM(nr, 0));
431df9ec2daSUwe Kleine-König fallthrough;
432df9ec2daSUwe Kleine-König case f71862fg:
433df9ec2daSUwe Kleine-König data->pwm_auto_point_pwm[nr][1] =
434df9ec2daSUwe Kleine-König f71882fg_read8(data,
435df9ec2daSUwe Kleine-König F71882FG_REG_POINT_PWM
436df9ec2daSUwe Kleine-König (nr, 1));
437df9ec2daSUwe Kleine-König data->pwm_auto_point_pwm[nr][4] =
438df9ec2daSUwe Kleine-König f71882fg_read8(data,
439df9ec2daSUwe Kleine-König F71882FG_REG_POINT_PWM
440df9ec2daSUwe Kleine-König (nr, 4));
441df9ec2daSUwe Kleine-König data->pwm_auto_point_temp[nr][0] =
442df9ec2daSUwe Kleine-König f71882fg_read8(data,
443df9ec2daSUwe Kleine-König F71882FG_REG_POINT_TEMP
444df9ec2daSUwe Kleine-König (nr, 0));
445df9ec2daSUwe Kleine-König data->pwm_auto_point_temp[nr][3] =
446df9ec2daSUwe Kleine-König f71882fg_read8(data,
447df9ec2daSUwe Kleine-König F71882FG_REG_POINT_TEMP
448df9ec2daSUwe Kleine-König (nr, 3));
449df9ec2daSUwe Kleine-König break;
450df9ec2daSUwe Kleine-König }
451df9ec2daSUwe Kleine-König }
452df9ec2daSUwe Kleine-König data->last_limits = jiffies;
453df9ec2daSUwe Kleine-König }
454df9ec2daSUwe Kleine-König
455df9ec2daSUwe Kleine-König /* Update every second */
456df9ec2daSUwe Kleine-König if (time_after(jiffies, data->last_updated + HZ) || !data->valid) {
457df9ec2daSUwe Kleine-König data->temp_status = f71882fg_read8(data,
458df9ec2daSUwe Kleine-König F71882FG_REG_TEMP_STATUS);
459df9ec2daSUwe Kleine-König data->temp_diode_open = f71882fg_read8(data,
460df9ec2daSUwe Kleine-König F71882FG_REG_TEMP_DIODE_OPEN);
461df9ec2daSUwe Kleine-König for (nr = data->temp_start; nr < nr_temps + data->temp_start;
462df9ec2daSUwe Kleine-König nr++)
463df9ec2daSUwe Kleine-König data->temp[nr] = f71882fg_read_temp(data, nr);
464df9ec2daSUwe Kleine-König
465df9ec2daSUwe Kleine-König data->fan_status = f71882fg_read8(data,
466df9ec2daSUwe Kleine-König F71882FG_REG_FAN_STATUS);
467df9ec2daSUwe Kleine-König for (nr = 0; nr < nr_fans; nr++) {
468df9ec2daSUwe Kleine-König data->fan[nr] = f71882fg_read16(data,
469df9ec2daSUwe Kleine-König F71882FG_REG_FAN(nr));
470df9ec2daSUwe Kleine-König data->fan_target[nr] =
471df9ec2daSUwe Kleine-König f71882fg_read16(data, F71882FG_REG_FAN_TARGET(nr));
472df9ec2daSUwe Kleine-König data->fan_full_speed[nr] =
473df9ec2daSUwe Kleine-König f71882fg_read16(data,
474df9ec2daSUwe Kleine-König F71882FG_REG_FAN_FULL_SPEED(nr));
475df9ec2daSUwe Kleine-König data->pwm[nr] =
476df9ec2daSUwe Kleine-König f71882fg_read8(data, F71882FG_REG_PWM(nr));
477df9ec2daSUwe Kleine-König }
478df9ec2daSUwe Kleine-König /* Some models have 1 more fan with limited capabilities */
479df9ec2daSUwe Kleine-König if (data->type == f71808a) {
480df9ec2daSUwe Kleine-König data->fan[2] = f71882fg_read16(data,
481df9ec2daSUwe Kleine-König F71882FG_REG_FAN(2));
482df9ec2daSUwe Kleine-König data->pwm[2] = f71882fg_read8(data,
483df9ec2daSUwe Kleine-König F71882FG_REG_PWM(2));
484df9ec2daSUwe Kleine-König }
485df9ec2daSUwe Kleine-König if (data->type == f8000)
486df9ec2daSUwe Kleine-König data->fan[3] = f71882fg_read16(data,
487df9ec2daSUwe Kleine-König F71882FG_REG_FAN(3));
488df9ec2daSUwe Kleine-König
489df9ec2daSUwe Kleine-König if (f71882fg_has_in1_alarm[data->type]) {
490df9ec2daSUwe Kleine-König if (data->type == f81866a)
491df9ec2daSUwe Kleine-König data->in_status = f71882fg_read8(data,
492df9ec2daSUwe Kleine-König F81866_REG_IN_STATUS);
493df9ec2daSUwe Kleine-König
494df9ec2daSUwe Kleine-König else
495df9ec2daSUwe Kleine-König data->in_status = f71882fg_read8(data,
496df9ec2daSUwe Kleine-König F71882FG_REG_IN_STATUS);
497df9ec2daSUwe Kleine-König }
498df9ec2daSUwe Kleine-König
499df9ec2daSUwe Kleine-König for (nr = 0; nr < F71882FG_MAX_INS; nr++)
500df9ec2daSUwe Kleine-König if (f71882fg_has_in[data->type][nr])
501df9ec2daSUwe Kleine-König data->in[nr] = f71882fg_read8(data,
502df9ec2daSUwe Kleine-König F71882FG_REG_IN(nr));
503df9ec2daSUwe Kleine-König
504df9ec2daSUwe Kleine-König data->last_updated = jiffies;
505df9ec2daSUwe Kleine-König data->valid = true;
506df9ec2daSUwe Kleine-König }
507df9ec2daSUwe Kleine-König
508df9ec2daSUwe Kleine-König mutex_unlock(&data->update_lock);
509df9ec2daSUwe Kleine-König
510df9ec2daSUwe Kleine-König return data;
511df9ec2daSUwe Kleine-König }
512df9ec2daSUwe Kleine-König
name_show(struct device * dev,struct device_attribute * devattr,char * buf)513f2620e7fSJulia Lawall static ssize_t name_show(struct device *dev, struct device_attribute *devattr,
514df9ec2daSUwe Kleine-König char *buf)
515df9ec2daSUwe Kleine-König {
516df9ec2daSUwe Kleine-König struct f71882fg_data *data = dev_get_drvdata(dev);
517df9ec2daSUwe Kleine-König return sprintf(buf, "%s\n", f71882fg_names[data->type]);
518df9ec2daSUwe Kleine-König }
51945fb3669SHans de Goede
520f2620e7fSJulia Lawall static DEVICE_ATTR_RO(name);
52145fb3669SHans de Goede
show_temp(struct device * dev,struct device_attribute * devattr,char * buf)522df9ec2daSUwe Kleine-König static ssize_t show_temp(struct device *dev, struct device_attribute *devattr,
523df9ec2daSUwe Kleine-König char *buf)
524df9ec2daSUwe Kleine-König {
525df9ec2daSUwe Kleine-König struct f71882fg_data *data = f71882fg_update_device(dev);
526df9ec2daSUwe Kleine-König int nr = to_sensor_dev_attr_2(devattr)->index;
527df9ec2daSUwe Kleine-König int sign, temp;
528df9ec2daSUwe Kleine-König
529df9ec2daSUwe Kleine-König if (data->type == f71858fg) {
530df9ec2daSUwe Kleine-König /* TEMP_TABLE_SEL 1 or 3 ? */
531df9ec2daSUwe Kleine-König if (data->temp_config & 1) {
532df9ec2daSUwe Kleine-König sign = data->temp[nr] & 0x0001;
533df9ec2daSUwe Kleine-König temp = (data->temp[nr] >> 5) & 0x7ff;
534df9ec2daSUwe Kleine-König } else {
535df9ec2daSUwe Kleine-König sign = data->temp[nr] & 0x8000;
536df9ec2daSUwe Kleine-König temp = (data->temp[nr] >> 5) & 0x3ff;
537df9ec2daSUwe Kleine-König }
538df9ec2daSUwe Kleine-König temp *= 125;
539df9ec2daSUwe Kleine-König if (sign)
540df9ec2daSUwe Kleine-König temp -= 128000;
541df9ec2daSUwe Kleine-König } else {
542df9ec2daSUwe Kleine-König temp = ((s8)data->temp[nr]) * 1000;
543df9ec2daSUwe Kleine-König }
544df9ec2daSUwe Kleine-König
545df9ec2daSUwe Kleine-König return sprintf(buf, "%d\n", temp);
546df9ec2daSUwe Kleine-König }
547df9ec2daSUwe Kleine-König
show_temp_max(struct device * dev,struct device_attribute * devattr,char * buf)548df9ec2daSUwe Kleine-König static ssize_t show_temp_max(struct device *dev, struct device_attribute
549df9ec2daSUwe Kleine-König *devattr, char *buf)
550df9ec2daSUwe Kleine-König {
551df9ec2daSUwe Kleine-König struct f71882fg_data *data = f71882fg_update_device(dev);
552df9ec2daSUwe Kleine-König int nr = to_sensor_dev_attr_2(devattr)->index;
553df9ec2daSUwe Kleine-König
554df9ec2daSUwe Kleine-König return sprintf(buf, "%d\n", data->temp_high[nr] * 1000);
555df9ec2daSUwe Kleine-König }
556df9ec2daSUwe Kleine-König
store_temp_max(struct device * dev,struct device_attribute * devattr,const char * buf,size_t count)557df9ec2daSUwe Kleine-König static ssize_t store_temp_max(struct device *dev, struct device_attribute
558df9ec2daSUwe Kleine-König *devattr, const char *buf, size_t count)
559df9ec2daSUwe Kleine-König {
560df9ec2daSUwe Kleine-König struct f71882fg_data *data = dev_get_drvdata(dev);
561df9ec2daSUwe Kleine-König int err, nr = to_sensor_dev_attr_2(devattr)->index;
562df9ec2daSUwe Kleine-König long val;
563df9ec2daSUwe Kleine-König
564df9ec2daSUwe Kleine-König err = kstrtol(buf, 10, &val);
565df9ec2daSUwe Kleine-König if (err)
566df9ec2daSUwe Kleine-König return err;
567df9ec2daSUwe Kleine-König
568df9ec2daSUwe Kleine-König val /= 1000;
569df9ec2daSUwe Kleine-König val = clamp_val(val, 0, 255);
570df9ec2daSUwe Kleine-König
571df9ec2daSUwe Kleine-König mutex_lock(&data->update_lock);
572df9ec2daSUwe Kleine-König f71882fg_write8(data, F71882FG_REG_TEMP_HIGH(nr), val);
573df9ec2daSUwe Kleine-König data->temp_high[nr] = val;
574df9ec2daSUwe Kleine-König mutex_unlock(&data->update_lock);
575df9ec2daSUwe Kleine-König
576df9ec2daSUwe Kleine-König return count;
577df9ec2daSUwe Kleine-König }
578df9ec2daSUwe Kleine-König
show_temp_max_hyst(struct device * dev,struct device_attribute * devattr,char * buf)579df9ec2daSUwe Kleine-König static ssize_t show_temp_max_hyst(struct device *dev, struct device_attribute
580df9ec2daSUwe Kleine-König *devattr, char *buf)
581df9ec2daSUwe Kleine-König {
582df9ec2daSUwe Kleine-König struct f71882fg_data *data = f71882fg_update_device(dev);
583df9ec2daSUwe Kleine-König int nr = to_sensor_dev_attr_2(devattr)->index;
584df9ec2daSUwe Kleine-König int temp_max_hyst;
585df9ec2daSUwe Kleine-König
586df9ec2daSUwe Kleine-König mutex_lock(&data->update_lock);
587df9ec2daSUwe Kleine-König if (nr & 1)
588df9ec2daSUwe Kleine-König temp_max_hyst = data->temp_hyst[nr / 2] >> 4;
589df9ec2daSUwe Kleine-König else
590df9ec2daSUwe Kleine-König temp_max_hyst = data->temp_hyst[nr / 2] & 0x0f;
591df9ec2daSUwe Kleine-König temp_max_hyst = (data->temp_high[nr] - temp_max_hyst) * 1000;
592df9ec2daSUwe Kleine-König mutex_unlock(&data->update_lock);
593df9ec2daSUwe Kleine-König
594df9ec2daSUwe Kleine-König return sprintf(buf, "%d\n", temp_max_hyst);
595df9ec2daSUwe Kleine-König }
596df9ec2daSUwe Kleine-König
store_temp_max_hyst(struct device * dev,struct device_attribute * devattr,const char * buf,size_t count)597df9ec2daSUwe Kleine-König static ssize_t store_temp_max_hyst(struct device *dev, struct device_attribute
598df9ec2daSUwe Kleine-König *devattr, const char *buf, size_t count)
599df9ec2daSUwe Kleine-König {
600df9ec2daSUwe Kleine-König struct f71882fg_data *data = dev_get_drvdata(dev);
601df9ec2daSUwe Kleine-König int err, nr = to_sensor_dev_attr_2(devattr)->index;
602df9ec2daSUwe Kleine-König ssize_t ret = count;
603df9ec2daSUwe Kleine-König u8 reg;
604df9ec2daSUwe Kleine-König long val;
605df9ec2daSUwe Kleine-König
606df9ec2daSUwe Kleine-König err = kstrtol(buf, 10, &val);
607df9ec2daSUwe Kleine-König if (err)
608df9ec2daSUwe Kleine-König return err;
609df9ec2daSUwe Kleine-König
610df9ec2daSUwe Kleine-König val /= 1000;
611df9ec2daSUwe Kleine-König
612df9ec2daSUwe Kleine-König mutex_lock(&data->update_lock);
613df9ec2daSUwe Kleine-König
614df9ec2daSUwe Kleine-König /* convert abs to relative and check */
615df9ec2daSUwe Kleine-König data->temp_high[nr] = f71882fg_read8(data, F71882FG_REG_TEMP_HIGH(nr));
616df9ec2daSUwe Kleine-König val = clamp_val(val, data->temp_high[nr] - 15, data->temp_high[nr]);
617df9ec2daSUwe Kleine-König val = data->temp_high[nr] - val;
618df9ec2daSUwe Kleine-König
619df9ec2daSUwe Kleine-König /* convert value to register contents */
620df9ec2daSUwe Kleine-König reg = f71882fg_read8(data, F71882FG_REG_TEMP_HYST(nr / 2));
621df9ec2daSUwe Kleine-König if (nr & 1)
622df9ec2daSUwe Kleine-König reg = (reg & 0x0f) | (val << 4);
623df9ec2daSUwe Kleine-König else
624df9ec2daSUwe Kleine-König reg = (reg & 0xf0) | val;
625df9ec2daSUwe Kleine-König f71882fg_write8(data, F71882FG_REG_TEMP_HYST(nr / 2), reg);
626df9ec2daSUwe Kleine-König data->temp_hyst[nr / 2] = reg;
627df9ec2daSUwe Kleine-König
628df9ec2daSUwe Kleine-König mutex_unlock(&data->update_lock);
629df9ec2daSUwe Kleine-König return ret;
630df9ec2daSUwe Kleine-König }
631df9ec2daSUwe Kleine-König
show_temp_alarm(struct device * dev,struct device_attribute * devattr,char * buf)632df9ec2daSUwe Kleine-König static ssize_t show_temp_alarm(struct device *dev, struct device_attribute
633df9ec2daSUwe Kleine-König *devattr, char *buf)
634df9ec2daSUwe Kleine-König {
635df9ec2daSUwe Kleine-König struct f71882fg_data *data = f71882fg_update_device(dev);
636df9ec2daSUwe Kleine-König int nr = to_sensor_dev_attr_2(devattr)->index;
637df9ec2daSUwe Kleine-König
638df9ec2daSUwe Kleine-König if (data->temp_status & (1 << nr))
639df9ec2daSUwe Kleine-König return sprintf(buf, "1\n");
640df9ec2daSUwe Kleine-König else
641df9ec2daSUwe Kleine-König return sprintf(buf, "0\n");
642df9ec2daSUwe Kleine-König }
643df9ec2daSUwe Kleine-König
show_temp_crit(struct device * dev,struct device_attribute * devattr,char * buf)644df9ec2daSUwe Kleine-König static ssize_t show_temp_crit(struct device *dev, struct device_attribute
645df9ec2daSUwe Kleine-König *devattr, char *buf)
646df9ec2daSUwe Kleine-König {
647df9ec2daSUwe Kleine-König struct f71882fg_data *data = f71882fg_update_device(dev);
648df9ec2daSUwe Kleine-König int nr = to_sensor_dev_attr_2(devattr)->index;
649df9ec2daSUwe Kleine-König
650df9ec2daSUwe Kleine-König return sprintf(buf, "%d\n", data->temp_ovt[nr] * 1000);
651df9ec2daSUwe Kleine-König }
652df9ec2daSUwe Kleine-König
store_temp_crit(struct device * dev,struct device_attribute * devattr,const char * buf,size_t count)653df9ec2daSUwe Kleine-König static ssize_t store_temp_crit(struct device *dev, struct device_attribute
654df9ec2daSUwe Kleine-König *devattr, const char *buf, size_t count)
655df9ec2daSUwe Kleine-König {
656df9ec2daSUwe Kleine-König struct f71882fg_data *data = dev_get_drvdata(dev);
657df9ec2daSUwe Kleine-König int err, nr = to_sensor_dev_attr_2(devattr)->index;
658df9ec2daSUwe Kleine-König long val;
659df9ec2daSUwe Kleine-König
660df9ec2daSUwe Kleine-König err = kstrtol(buf, 10, &val);
661df9ec2daSUwe Kleine-König if (err)
662df9ec2daSUwe Kleine-König return err;
663df9ec2daSUwe Kleine-König
664df9ec2daSUwe Kleine-König val /= 1000;
665df9ec2daSUwe Kleine-König val = clamp_val(val, 0, 255);
666df9ec2daSUwe Kleine-König
667df9ec2daSUwe Kleine-König mutex_lock(&data->update_lock);
668df9ec2daSUwe Kleine-König f71882fg_write8(data, F71882FG_REG_TEMP_OVT(nr), val);
669df9ec2daSUwe Kleine-König data->temp_ovt[nr] = val;
670df9ec2daSUwe Kleine-König mutex_unlock(&data->update_lock);
671df9ec2daSUwe Kleine-König
672df9ec2daSUwe Kleine-König return count;
673df9ec2daSUwe Kleine-König }
674df9ec2daSUwe Kleine-König
show_temp_crit_hyst(struct device * dev,struct device_attribute * devattr,char * buf)675df9ec2daSUwe Kleine-König static ssize_t show_temp_crit_hyst(struct device *dev, struct device_attribute
676df9ec2daSUwe Kleine-König *devattr, char *buf)
677df9ec2daSUwe Kleine-König {
678df9ec2daSUwe Kleine-König struct f71882fg_data *data = f71882fg_update_device(dev);
679df9ec2daSUwe Kleine-König int nr = to_sensor_dev_attr_2(devattr)->index;
680df9ec2daSUwe Kleine-König int temp_crit_hyst;
681df9ec2daSUwe Kleine-König
682df9ec2daSUwe Kleine-König mutex_lock(&data->update_lock);
683df9ec2daSUwe Kleine-König if (nr & 1)
684df9ec2daSUwe Kleine-König temp_crit_hyst = data->temp_hyst[nr / 2] >> 4;
685df9ec2daSUwe Kleine-König else
686df9ec2daSUwe Kleine-König temp_crit_hyst = data->temp_hyst[nr / 2] & 0x0f;
687df9ec2daSUwe Kleine-König temp_crit_hyst = (data->temp_ovt[nr] - temp_crit_hyst) * 1000;
688df9ec2daSUwe Kleine-König mutex_unlock(&data->update_lock);
689df9ec2daSUwe Kleine-König
690df9ec2daSUwe Kleine-König return sprintf(buf, "%d\n", temp_crit_hyst);
691df9ec2daSUwe Kleine-König }
692df9ec2daSUwe Kleine-König
show_temp_fault(struct device * dev,struct device_attribute * devattr,char * buf)693df9ec2daSUwe Kleine-König static ssize_t show_temp_fault(struct device *dev, struct device_attribute
694df9ec2daSUwe Kleine-König *devattr, char *buf)
695df9ec2daSUwe Kleine-König {
696df9ec2daSUwe Kleine-König struct f71882fg_data *data = f71882fg_update_device(dev);
697df9ec2daSUwe Kleine-König int nr = to_sensor_dev_attr_2(devattr)->index;
698df9ec2daSUwe Kleine-König
699df9ec2daSUwe Kleine-König if (data->temp_diode_open & (1 << nr))
700df9ec2daSUwe Kleine-König return sprintf(buf, "1\n");
701df9ec2daSUwe Kleine-König else
702df9ec2daSUwe Kleine-König return sprintf(buf, "0\n");
703df9ec2daSUwe Kleine-König }
704df9ec2daSUwe Kleine-König
70520eaf724SGuenter Roeck /*
70620eaf724SGuenter Roeck * Temp attr for the f71858fg, the f71858fg is special as it has its
70720eaf724SGuenter Roeck * temperature indexes start at 0 (the others start at 1)
70820eaf724SGuenter Roeck */
7090bae6400SHans de Goede static struct sensor_device_attribute_2 f71858fg_temp_attr[] = {
71009475d32SHans de Goede SENSOR_ATTR_2(temp1_input, S_IRUGO, show_temp, NULL, 0, 0),
71109475d32SHans de Goede SENSOR_ATTR_2(temp1_max, S_IRUGO|S_IWUSR, show_temp_max,
71209475d32SHans de Goede store_temp_max, 0, 0),
71309475d32SHans de Goede SENSOR_ATTR_2(temp1_max_hyst, S_IRUGO|S_IWUSR, show_temp_max_hyst,
71409475d32SHans de Goede store_temp_max_hyst, 0, 0),
71509475d32SHans de Goede SENSOR_ATTR_2(temp1_max_alarm, S_IRUGO, show_temp_alarm, NULL, 0, 0),
71609475d32SHans de Goede SENSOR_ATTR_2(temp1_crit, S_IRUGO|S_IWUSR, show_temp_crit,
71709475d32SHans de Goede store_temp_crit, 0, 0),
71809475d32SHans de Goede SENSOR_ATTR_2(temp1_crit_hyst, S_IRUGO, show_temp_crit_hyst, NULL,
71909475d32SHans de Goede 0, 0),
72009475d32SHans de Goede SENSOR_ATTR_2(temp1_crit_alarm, S_IRUGO, show_temp_alarm, NULL, 0, 4),
72109475d32SHans de Goede SENSOR_ATTR_2(temp1_fault, S_IRUGO, show_temp_fault, NULL, 0, 0),
72209475d32SHans de Goede SENSOR_ATTR_2(temp2_input, S_IRUGO, show_temp, NULL, 0, 1),
72309475d32SHans de Goede SENSOR_ATTR_2(temp2_max, S_IRUGO|S_IWUSR, show_temp_max,
72409475d32SHans de Goede store_temp_max, 0, 1),
72509475d32SHans de Goede SENSOR_ATTR_2(temp2_max_hyst, S_IRUGO|S_IWUSR, show_temp_max_hyst,
72609475d32SHans de Goede store_temp_max_hyst, 0, 1),
72709475d32SHans de Goede SENSOR_ATTR_2(temp2_max_alarm, S_IRUGO, show_temp_alarm, NULL, 0, 1),
72809475d32SHans de Goede SENSOR_ATTR_2(temp2_crit, S_IRUGO|S_IWUSR, show_temp_crit,
72909475d32SHans de Goede store_temp_crit, 0, 1),
73009475d32SHans de Goede SENSOR_ATTR_2(temp2_crit_hyst, S_IRUGO, show_temp_crit_hyst, NULL,
73109475d32SHans de Goede 0, 1),
73209475d32SHans de Goede SENSOR_ATTR_2(temp2_crit_alarm, S_IRUGO, show_temp_alarm, NULL, 0, 5),
73309475d32SHans de Goede SENSOR_ATTR_2(temp2_fault, S_IRUGO, show_temp_fault, NULL, 0, 1),
73409475d32SHans de Goede SENSOR_ATTR_2(temp3_input, S_IRUGO, show_temp, NULL, 0, 2),
73509475d32SHans de Goede SENSOR_ATTR_2(temp3_max, S_IRUGO|S_IWUSR, show_temp_max,
73609475d32SHans de Goede store_temp_max, 0, 2),
73709475d32SHans de Goede SENSOR_ATTR_2(temp3_max_hyst, S_IRUGO|S_IWUSR, show_temp_max_hyst,
73809475d32SHans de Goede store_temp_max_hyst, 0, 2),
73909475d32SHans de Goede SENSOR_ATTR_2(temp3_max_alarm, S_IRUGO, show_temp_alarm, NULL, 0, 2),
74009475d32SHans de Goede SENSOR_ATTR_2(temp3_crit, S_IRUGO|S_IWUSR, show_temp_crit,
74109475d32SHans de Goede store_temp_crit, 0, 2),
74209475d32SHans de Goede SENSOR_ATTR_2(temp3_crit_hyst, S_IRUGO, show_temp_crit_hyst, NULL,
74309475d32SHans de Goede 0, 2),
74409475d32SHans de Goede SENSOR_ATTR_2(temp3_crit_alarm, S_IRUGO, show_temp_alarm, NULL, 0, 6),
74509475d32SHans de Goede SENSOR_ATTR_2(temp3_fault, S_IRUGO, show_temp_fault, NULL, 0, 2),
74609475d32SHans de Goede };
74709475d32SHans de Goede
show_temp_type(struct device * dev,struct device_attribute * devattr,char * buf)748df9ec2daSUwe Kleine-König static ssize_t show_temp_type(struct device *dev, struct device_attribute
749df9ec2daSUwe Kleine-König *devattr, char *buf)
750df9ec2daSUwe Kleine-König {
751df9ec2daSUwe Kleine-König struct f71882fg_data *data = f71882fg_update_device(dev);
752df9ec2daSUwe Kleine-König int nr = to_sensor_dev_attr_2(devattr)->index;
753df9ec2daSUwe Kleine-König
754df9ec2daSUwe Kleine-König return sprintf(buf, "%d\n", data->temp_type[nr]);
755df9ec2daSUwe Kleine-König }
756df9ec2daSUwe Kleine-König
7570bae6400SHans de Goede /* Temp attr for the standard models */
75878aa4f72SHans de Goede static struct sensor_device_attribute_2 fxxxx_temp_attr[3][9] = { {
7597567a043SHans de Goede SENSOR_ATTR_2(temp1_input, S_IRUGO, show_temp, NULL, 0, 1),
760bc37ae71SMark van Doesburg SENSOR_ATTR_2(temp1_max, S_IRUGO|S_IWUSR, show_temp_max,
761bc37ae71SMark van Doesburg store_temp_max, 0, 1),
7627567a043SHans de Goede SENSOR_ATTR_2(temp1_max_hyst, S_IRUGO|S_IWUSR, show_temp_max_hyst,
763bc37ae71SMark van Doesburg store_temp_max_hyst, 0, 1),
76420eaf724SGuenter Roeck /*
76520eaf724SGuenter Roeck * Should really be temp1_max_alarm, but older versions did not handle
76620eaf724SGuenter Roeck * the max and crit alarms separately and lm_sensors v2 depends on the
76720eaf724SGuenter Roeck * presence of temp#_alarm files. The same goes for temp2/3 _alarm.
76820eaf724SGuenter Roeck */
769754a5907SHans de Goede SENSOR_ATTR_2(temp1_alarm, S_IRUGO, show_temp_alarm, NULL, 0, 1),
7707567a043SHans de Goede SENSOR_ATTR_2(temp1_crit, S_IRUGO|S_IWUSR, show_temp_crit,
771bc37ae71SMark van Doesburg store_temp_crit, 0, 1),
7727567a043SHans de Goede SENSOR_ATTR_2(temp1_crit_hyst, S_IRUGO, show_temp_crit_hyst, NULL,
773bc37ae71SMark van Doesburg 0, 1),
774754a5907SHans de Goede SENSOR_ATTR_2(temp1_crit_alarm, S_IRUGO, show_temp_alarm, NULL, 0, 5),
7757567a043SHans de Goede SENSOR_ATTR_2(temp1_type, S_IRUGO, show_temp_type, NULL, 0, 1),
7767567a043SHans de Goede SENSOR_ATTR_2(temp1_fault, S_IRUGO, show_temp_fault, NULL, 0, 1),
77760d2b378SHans de Goede }, {
7787567a043SHans de Goede SENSOR_ATTR_2(temp2_input, S_IRUGO, show_temp, NULL, 0, 2),
7797567a043SHans de Goede SENSOR_ATTR_2(temp2_max, S_IRUGO|S_IWUSR, show_temp_max,
780bc37ae71SMark van Doesburg store_temp_max, 0, 2),
7817567a043SHans de Goede SENSOR_ATTR_2(temp2_max_hyst, S_IRUGO|S_IWUSR, show_temp_max_hyst,
782bc37ae71SMark van Doesburg store_temp_max_hyst, 0, 2),
783754a5907SHans de Goede /* Should be temp2_max_alarm, see temp1_alarm note */
784754a5907SHans de Goede SENSOR_ATTR_2(temp2_alarm, S_IRUGO, show_temp_alarm, NULL, 0, 2),
7857567a043SHans de Goede SENSOR_ATTR_2(temp2_crit, S_IRUGO|S_IWUSR, show_temp_crit,
786bc37ae71SMark van Doesburg store_temp_crit, 0, 2),
7877567a043SHans de Goede SENSOR_ATTR_2(temp2_crit_hyst, S_IRUGO, show_temp_crit_hyst, NULL,
788bc37ae71SMark van Doesburg 0, 2),
789754a5907SHans de Goede SENSOR_ATTR_2(temp2_crit_alarm, S_IRUGO, show_temp_alarm, NULL, 0, 6),
7907567a043SHans de Goede SENSOR_ATTR_2(temp2_type, S_IRUGO, show_temp_type, NULL, 0, 2),
7917567a043SHans de Goede SENSOR_ATTR_2(temp2_fault, S_IRUGO, show_temp_fault, NULL, 0, 2),
79260d2b378SHans de Goede }, {
7937567a043SHans de Goede SENSOR_ATTR_2(temp3_input, S_IRUGO, show_temp, NULL, 0, 3),
7947567a043SHans de Goede SENSOR_ATTR_2(temp3_max, S_IRUGO|S_IWUSR, show_temp_max,
7957567a043SHans de Goede store_temp_max, 0, 3),
7967567a043SHans de Goede SENSOR_ATTR_2(temp3_max_hyst, S_IRUGO|S_IWUSR, show_temp_max_hyst,
7977567a043SHans de Goede store_temp_max_hyst, 0, 3),
798754a5907SHans de Goede /* Should be temp3_max_alarm, see temp1_alarm note */
799754a5907SHans de Goede SENSOR_ATTR_2(temp3_alarm, S_IRUGO, show_temp_alarm, NULL, 0, 3),
8007567a043SHans de Goede SENSOR_ATTR_2(temp3_crit, S_IRUGO|S_IWUSR, show_temp_crit,
8017567a043SHans de Goede store_temp_crit, 0, 3),
8027567a043SHans de Goede SENSOR_ATTR_2(temp3_crit_hyst, S_IRUGO, show_temp_crit_hyst, NULL,
8037567a043SHans de Goede 0, 3),
804754a5907SHans de Goede SENSOR_ATTR_2(temp3_crit_alarm, S_IRUGO, show_temp_alarm, NULL, 0, 7),
8057567a043SHans de Goede SENSOR_ATTR_2(temp3_type, S_IRUGO, show_temp_type, NULL, 0, 3),
8067567a043SHans de Goede SENSOR_ATTR_2(temp3_fault, S_IRUGO, show_temp_fault, NULL, 0, 3),
80760d2b378SHans de Goede } };
80845fb3669SHans de Goede
show_temp_beep(struct device * dev,struct device_attribute * devattr,char * buf)809df9ec2daSUwe Kleine-König static ssize_t show_temp_beep(struct device *dev, struct device_attribute
810df9ec2daSUwe Kleine-König *devattr, char *buf)
811df9ec2daSUwe Kleine-König {
812df9ec2daSUwe Kleine-König struct f71882fg_data *data = f71882fg_update_device(dev);
813df9ec2daSUwe Kleine-König int nr = to_sensor_dev_attr_2(devattr)->index;
814df9ec2daSUwe Kleine-König
815df9ec2daSUwe Kleine-König if (data->temp_beep & (1 << nr))
816df9ec2daSUwe Kleine-König return sprintf(buf, "1\n");
817df9ec2daSUwe Kleine-König else
818df9ec2daSUwe Kleine-König return sprintf(buf, "0\n");
819df9ec2daSUwe Kleine-König }
820df9ec2daSUwe Kleine-König
store_temp_beep(struct device * dev,struct device_attribute * devattr,const char * buf,size_t count)821df9ec2daSUwe Kleine-König static ssize_t store_temp_beep(struct device *dev, struct device_attribute
822df9ec2daSUwe Kleine-König *devattr, const char *buf, size_t count)
823df9ec2daSUwe Kleine-König {
824df9ec2daSUwe Kleine-König struct f71882fg_data *data = dev_get_drvdata(dev);
825df9ec2daSUwe Kleine-König int err, nr = to_sensor_dev_attr_2(devattr)->index;
826df9ec2daSUwe Kleine-König unsigned long val;
827df9ec2daSUwe Kleine-König
828df9ec2daSUwe Kleine-König err = kstrtoul(buf, 10, &val);
829df9ec2daSUwe Kleine-König if (err)
830df9ec2daSUwe Kleine-König return err;
831df9ec2daSUwe Kleine-König
832df9ec2daSUwe Kleine-König mutex_lock(&data->update_lock);
833df9ec2daSUwe Kleine-König data->temp_beep = f71882fg_read8(data, F71882FG_REG_TEMP_BEEP);
834df9ec2daSUwe Kleine-König if (val)
835df9ec2daSUwe Kleine-König data->temp_beep |= 1 << nr;
836df9ec2daSUwe Kleine-König else
837df9ec2daSUwe Kleine-König data->temp_beep &= ~(1 << nr);
838df9ec2daSUwe Kleine-König
839df9ec2daSUwe Kleine-König f71882fg_write8(data, F71882FG_REG_TEMP_BEEP, data->temp_beep);
840df9ec2daSUwe Kleine-König mutex_unlock(&data->update_lock);
841df9ec2daSUwe Kleine-König
842df9ec2daSUwe Kleine-König return count;
843df9ec2daSUwe Kleine-König }
844df9ec2daSUwe Kleine-König
84578aa4f72SHans de Goede /* Temp attr for models which can beep on temp alarm */
84678aa4f72SHans de Goede static struct sensor_device_attribute_2 fxxxx_temp_beep_attr[3][2] = { {
84778aa4f72SHans de Goede SENSOR_ATTR_2(temp1_max_beep, S_IRUGO|S_IWUSR, show_temp_beep,
84878aa4f72SHans de Goede store_temp_beep, 0, 1),
84978aa4f72SHans de Goede SENSOR_ATTR_2(temp1_crit_beep, S_IRUGO|S_IWUSR, show_temp_beep,
85078aa4f72SHans de Goede store_temp_beep, 0, 5),
85178aa4f72SHans de Goede }, {
85278aa4f72SHans de Goede SENSOR_ATTR_2(temp2_max_beep, S_IRUGO|S_IWUSR, show_temp_beep,
85378aa4f72SHans de Goede store_temp_beep, 0, 2),
85478aa4f72SHans de Goede SENSOR_ATTR_2(temp2_crit_beep, S_IRUGO|S_IWUSR, show_temp_beep,
85578aa4f72SHans de Goede store_temp_beep, 0, 6),
85678aa4f72SHans de Goede }, {
85778aa4f72SHans de Goede SENSOR_ATTR_2(temp3_max_beep, S_IRUGO|S_IWUSR, show_temp_beep,
85878aa4f72SHans de Goede store_temp_beep, 0, 3),
85978aa4f72SHans de Goede SENSOR_ATTR_2(temp3_crit_beep, S_IRUGO|S_IWUSR, show_temp_beep,
86078aa4f72SHans de Goede store_temp_beep, 0, 7),
86178aa4f72SHans de Goede } };
86278aa4f72SHans de Goede
863dcd956fcSPeter Hung static struct sensor_device_attribute_2 f81866_temp_beep_attr[3][2] = { {
864dcd956fcSPeter Hung SENSOR_ATTR_2(temp1_max_beep, S_IRUGO|S_IWUSR, show_temp_beep,
865dcd956fcSPeter Hung store_temp_beep, 0, 0),
866dcd956fcSPeter Hung SENSOR_ATTR_2(temp1_crit_beep, S_IRUGO|S_IWUSR, show_temp_beep,
867dcd956fcSPeter Hung store_temp_beep, 0, 4),
868dcd956fcSPeter Hung }, {
869dcd956fcSPeter Hung SENSOR_ATTR_2(temp2_max_beep, S_IRUGO|S_IWUSR, show_temp_beep,
870dcd956fcSPeter Hung store_temp_beep, 0, 1),
871dcd956fcSPeter Hung SENSOR_ATTR_2(temp2_crit_beep, S_IRUGO|S_IWUSR, show_temp_beep,
872dcd956fcSPeter Hung store_temp_beep, 0, 5),
873dcd956fcSPeter Hung }, {
874dcd956fcSPeter Hung SENSOR_ATTR_2(temp3_max_beep, S_IRUGO|S_IWUSR, show_temp_beep,
875dcd956fcSPeter Hung store_temp_beep, 0, 2),
876dcd956fcSPeter Hung SENSOR_ATTR_2(temp3_crit_beep, S_IRUGO|S_IWUSR, show_temp_beep,
877dcd956fcSPeter Hung store_temp_beep, 0, 6),
878dcd956fcSPeter Hung } };
879dcd956fcSPeter Hung
88020eaf724SGuenter Roeck /*
88120eaf724SGuenter Roeck * Temp attr for the f8000
88220eaf724SGuenter Roeck * Note on the f8000 temp_ovt (crit) is used as max, and temp_high (max)
88320eaf724SGuenter Roeck * is used as hysteresis value to clear alarms
88420eaf724SGuenter Roeck * Also like the f71858fg its temperature indexes start at 0
885ed4f7c20SHans de Goede */
8860bae6400SHans de Goede static struct sensor_device_attribute_2 f8000_temp_attr[] = {
887ed4f7c20SHans de Goede SENSOR_ATTR_2(temp1_input, S_IRUGO, show_temp, NULL, 0, 0),
888ed4f7c20SHans de Goede SENSOR_ATTR_2(temp1_max, S_IRUGO|S_IWUSR, show_temp_crit,
889ed4f7c20SHans de Goede store_temp_crit, 0, 0),
890ed4f7c20SHans de Goede SENSOR_ATTR_2(temp1_max_hyst, S_IRUGO|S_IWUSR, show_temp_max,
891ed4f7c20SHans de Goede store_temp_max, 0, 0),
892ed4f7c20SHans de Goede SENSOR_ATTR_2(temp1_alarm, S_IRUGO, show_temp_alarm, NULL, 0, 4),
893b6858bcaSHans de Goede SENSOR_ATTR_2(temp1_fault, S_IRUGO, show_temp_fault, NULL, 0, 0),
894ed4f7c20SHans de Goede SENSOR_ATTR_2(temp2_input, S_IRUGO, show_temp, NULL, 0, 1),
895ed4f7c20SHans de Goede SENSOR_ATTR_2(temp2_max, S_IRUGO|S_IWUSR, show_temp_crit,
896ed4f7c20SHans de Goede store_temp_crit, 0, 1),
897ed4f7c20SHans de Goede SENSOR_ATTR_2(temp2_max_hyst, S_IRUGO|S_IWUSR, show_temp_max,
898ed4f7c20SHans de Goede store_temp_max, 0, 1),
899ed4f7c20SHans de Goede SENSOR_ATTR_2(temp2_alarm, S_IRUGO, show_temp_alarm, NULL, 0, 5),
900b6858bcaSHans de Goede SENSOR_ATTR_2(temp2_fault, S_IRUGO, show_temp_fault, NULL, 0, 1),
901ed4f7c20SHans de Goede SENSOR_ATTR_2(temp3_input, S_IRUGO, show_temp, NULL, 0, 2),
902ed4f7c20SHans de Goede SENSOR_ATTR_2(temp3_max, S_IRUGO|S_IWUSR, show_temp_crit,
903ed4f7c20SHans de Goede store_temp_crit, 0, 2),
904ed4f7c20SHans de Goede SENSOR_ATTR_2(temp3_max_hyst, S_IRUGO|S_IWUSR, show_temp_max,
905ed4f7c20SHans de Goede store_temp_max, 0, 2),
906ed4f7c20SHans de Goede SENSOR_ATTR_2(temp3_alarm, S_IRUGO, show_temp_alarm, NULL, 0, 6),
907b6858bcaSHans de Goede SENSOR_ATTR_2(temp3_fault, S_IRUGO, show_temp_fault, NULL, 0, 2),
908ed4f7c20SHans de Goede };
909ed4f7c20SHans de Goede
show_in(struct device * dev,struct device_attribute * devattr,char * buf)910df9ec2daSUwe Kleine-König static ssize_t show_in(struct device *dev, struct device_attribute *devattr,
911df9ec2daSUwe Kleine-König char *buf)
912df9ec2daSUwe Kleine-König {
913df9ec2daSUwe Kleine-König struct f71882fg_data *data = f71882fg_update_device(dev);
914df9ec2daSUwe Kleine-König int nr = to_sensor_dev_attr_2(devattr)->index;
915df9ec2daSUwe Kleine-König
916df9ec2daSUwe Kleine-König return sprintf(buf, "%d\n", data->in[nr] * 8);
917df9ec2daSUwe Kleine-König }
918df9ec2daSUwe Kleine-König
9190bae6400SHans de Goede /* in attr for all models */
9200bae6400SHans de Goede static struct sensor_device_attribute_2 fxxxx_in_attr[] = {
9210bae6400SHans de Goede SENSOR_ATTR_2(in0_input, S_IRUGO, show_in, NULL, 0, 0),
9220bae6400SHans de Goede SENSOR_ATTR_2(in1_input, S_IRUGO, show_in, NULL, 0, 1),
9230bae6400SHans de Goede SENSOR_ATTR_2(in2_input, S_IRUGO, show_in, NULL, 0, 2),
9240bae6400SHans de Goede SENSOR_ATTR_2(in3_input, S_IRUGO, show_in, NULL, 0, 3),
9250bae6400SHans de Goede SENSOR_ATTR_2(in4_input, S_IRUGO, show_in, NULL, 0, 4),
9260bae6400SHans de Goede SENSOR_ATTR_2(in5_input, S_IRUGO, show_in, NULL, 0, 5),
9270bae6400SHans de Goede SENSOR_ATTR_2(in6_input, S_IRUGO, show_in, NULL, 0, 6),
9280bae6400SHans de Goede SENSOR_ATTR_2(in7_input, S_IRUGO, show_in, NULL, 0, 7),
9290bae6400SHans de Goede SENSOR_ATTR_2(in8_input, S_IRUGO, show_in, NULL, 0, 8),
9302725fe2bSPeter Hung SENSOR_ATTR_2(in9_input, S_IRUGO, show_in, NULL, 0, 9),
931d8363bb5SGeorge Joseph SENSOR_ATTR_2(in10_input, S_IRUGO, show_in, NULL, 0, 10),
9320bae6400SHans de Goede };
9330bae6400SHans de Goede
show_in_max(struct device * dev,struct device_attribute * devattr,char * buf)934df9ec2daSUwe Kleine-König static ssize_t show_in_max(struct device *dev, struct device_attribute
935df9ec2daSUwe Kleine-König *devattr, char *buf)
936df9ec2daSUwe Kleine-König {
937df9ec2daSUwe Kleine-König struct f71882fg_data *data = f71882fg_update_device(dev);
938df9ec2daSUwe Kleine-König
939df9ec2daSUwe Kleine-König return sprintf(buf, "%d\n", data->in1_max * 8);
940df9ec2daSUwe Kleine-König }
941df9ec2daSUwe Kleine-König
store_in_max(struct device * dev,struct device_attribute * devattr,const char * buf,size_t count)942df9ec2daSUwe Kleine-König static ssize_t store_in_max(struct device *dev, struct device_attribute
943df9ec2daSUwe Kleine-König *devattr, const char *buf, size_t count)
944df9ec2daSUwe Kleine-König {
945df9ec2daSUwe Kleine-König struct f71882fg_data *data = dev_get_drvdata(dev);
946df9ec2daSUwe Kleine-König int err;
947df9ec2daSUwe Kleine-König long val;
948df9ec2daSUwe Kleine-König
949df9ec2daSUwe Kleine-König err = kstrtol(buf, 10, &val);
950df9ec2daSUwe Kleine-König if (err)
951df9ec2daSUwe Kleine-König return err;
952df9ec2daSUwe Kleine-König
953df9ec2daSUwe Kleine-König val /= 8;
954df9ec2daSUwe Kleine-König val = clamp_val(val, 0, 255);
955df9ec2daSUwe Kleine-König
956df9ec2daSUwe Kleine-König mutex_lock(&data->update_lock);
957df9ec2daSUwe Kleine-König if (data->type == f81866a)
958df9ec2daSUwe Kleine-König f71882fg_write8(data, F81866_REG_IN1_HIGH, val);
959df9ec2daSUwe Kleine-König else
960df9ec2daSUwe Kleine-König f71882fg_write8(data, F71882FG_REG_IN1_HIGH, val);
961df9ec2daSUwe Kleine-König data->in1_max = val;
962df9ec2daSUwe Kleine-König mutex_unlock(&data->update_lock);
963df9ec2daSUwe Kleine-König
964df9ec2daSUwe Kleine-König return count;
965df9ec2daSUwe Kleine-König }
966df9ec2daSUwe Kleine-König
show_in_beep(struct device * dev,struct device_attribute * devattr,char * buf)967df9ec2daSUwe Kleine-König static ssize_t show_in_beep(struct device *dev, struct device_attribute
968df9ec2daSUwe Kleine-König *devattr, char *buf)
969df9ec2daSUwe Kleine-König {
970df9ec2daSUwe Kleine-König struct f71882fg_data *data = f71882fg_update_device(dev);
971df9ec2daSUwe Kleine-König int nr = to_sensor_dev_attr_2(devattr)->index;
972df9ec2daSUwe Kleine-König
973df9ec2daSUwe Kleine-König if (data->in_beep & (1 << nr))
974df9ec2daSUwe Kleine-König return sprintf(buf, "1\n");
975df9ec2daSUwe Kleine-König else
976df9ec2daSUwe Kleine-König return sprintf(buf, "0\n");
977df9ec2daSUwe Kleine-König }
978df9ec2daSUwe Kleine-König
store_in_beep(struct device * dev,struct device_attribute * devattr,const char * buf,size_t count)979df9ec2daSUwe Kleine-König static ssize_t store_in_beep(struct device *dev, struct device_attribute
980df9ec2daSUwe Kleine-König *devattr, const char *buf, size_t count)
981df9ec2daSUwe Kleine-König {
982df9ec2daSUwe Kleine-König struct f71882fg_data *data = dev_get_drvdata(dev);
983df9ec2daSUwe Kleine-König int err, nr = to_sensor_dev_attr_2(devattr)->index;
984df9ec2daSUwe Kleine-König unsigned long val;
985df9ec2daSUwe Kleine-König
986df9ec2daSUwe Kleine-König err = kstrtoul(buf, 10, &val);
987df9ec2daSUwe Kleine-König if (err)
988df9ec2daSUwe Kleine-König return err;
989df9ec2daSUwe Kleine-König
990df9ec2daSUwe Kleine-König mutex_lock(&data->update_lock);
991df9ec2daSUwe Kleine-König if (data->type == f81866a)
992df9ec2daSUwe Kleine-König data->in_beep = f71882fg_read8(data, F81866_REG_IN_BEEP);
993df9ec2daSUwe Kleine-König else
994df9ec2daSUwe Kleine-König data->in_beep = f71882fg_read8(data, F71882FG_REG_IN_BEEP);
995df9ec2daSUwe Kleine-König
996df9ec2daSUwe Kleine-König if (val)
997df9ec2daSUwe Kleine-König data->in_beep |= 1 << nr;
998df9ec2daSUwe Kleine-König else
999df9ec2daSUwe Kleine-König data->in_beep &= ~(1 << nr);
1000df9ec2daSUwe Kleine-König
1001df9ec2daSUwe Kleine-König if (data->type == f81866a)
1002df9ec2daSUwe Kleine-König f71882fg_write8(data, F81866_REG_IN_BEEP, data->in_beep);
1003df9ec2daSUwe Kleine-König else
1004df9ec2daSUwe Kleine-König f71882fg_write8(data, F71882FG_REG_IN_BEEP, data->in_beep);
1005df9ec2daSUwe Kleine-König mutex_unlock(&data->update_lock);
1006df9ec2daSUwe Kleine-König
1007df9ec2daSUwe Kleine-König return count;
1008df9ec2daSUwe Kleine-König }
1009df9ec2daSUwe Kleine-König
show_in_alarm(struct device * dev,struct device_attribute * devattr,char * buf)1010df9ec2daSUwe Kleine-König static ssize_t show_in_alarm(struct device *dev, struct device_attribute
1011df9ec2daSUwe Kleine-König *devattr, char *buf)
1012df9ec2daSUwe Kleine-König {
1013df9ec2daSUwe Kleine-König struct f71882fg_data *data = f71882fg_update_device(dev);
1014df9ec2daSUwe Kleine-König int nr = to_sensor_dev_attr_2(devattr)->index;
1015df9ec2daSUwe Kleine-König
1016df9ec2daSUwe Kleine-König if (data->in_status & (1 << nr))
1017df9ec2daSUwe Kleine-König return sprintf(buf, "1\n");
1018df9ec2daSUwe Kleine-König else
1019df9ec2daSUwe Kleine-König return sprintf(buf, "0\n");
1020df9ec2daSUwe Kleine-König }
1021df9ec2daSUwe Kleine-König
10220bae6400SHans de Goede /* For models with in1 alarm capability */
10230bae6400SHans de Goede static struct sensor_device_attribute_2 fxxxx_in1_alarm_attr[] = {
10240bae6400SHans de Goede SENSOR_ATTR_2(in1_max, S_IRUGO|S_IWUSR, show_in_max, store_in_max,
10250bae6400SHans de Goede 0, 1),
10260bae6400SHans de Goede SENSOR_ATTR_2(in1_beep, S_IRUGO|S_IWUSR, show_in_beep, store_in_beep,
10270bae6400SHans de Goede 0, 1),
10280bae6400SHans de Goede SENSOR_ATTR_2(in1_alarm, S_IRUGO, show_in_alarm, NULL, 0, 1),
10290bae6400SHans de Goede };
10300bae6400SHans de Goede
show_fan(struct device * dev,struct device_attribute * devattr,char * buf)1031df9ec2daSUwe Kleine-König static ssize_t show_fan(struct device *dev, struct device_attribute *devattr,
1032df9ec2daSUwe Kleine-König char *buf)
1033df9ec2daSUwe Kleine-König {
1034df9ec2daSUwe Kleine-König struct f71882fg_data *data = f71882fg_update_device(dev);
1035df9ec2daSUwe Kleine-König int nr = to_sensor_dev_attr_2(devattr)->index;
1036df9ec2daSUwe Kleine-König int speed = fan_from_reg(data->fan[nr]);
1037df9ec2daSUwe Kleine-König
1038df9ec2daSUwe Kleine-König if (speed == FAN_MIN_DETECT)
1039df9ec2daSUwe Kleine-König speed = 0;
1040df9ec2daSUwe Kleine-König
1041df9ec2daSUwe Kleine-König return sprintf(buf, "%d\n", speed);
1042df9ec2daSUwe Kleine-König }
1043df9ec2daSUwe Kleine-König
show_fan_full_speed(struct device * dev,struct device_attribute * devattr,char * buf)1044df9ec2daSUwe Kleine-König static ssize_t show_fan_full_speed(struct device *dev,
1045df9ec2daSUwe Kleine-König struct device_attribute *devattr, char *buf)
1046df9ec2daSUwe Kleine-König {
1047df9ec2daSUwe Kleine-König struct f71882fg_data *data = f71882fg_update_device(dev);
1048df9ec2daSUwe Kleine-König int nr = to_sensor_dev_attr_2(devattr)->index;
1049df9ec2daSUwe Kleine-König int speed = fan_from_reg(data->fan_full_speed[nr]);
1050df9ec2daSUwe Kleine-König return sprintf(buf, "%d\n", speed);
1051df9ec2daSUwe Kleine-König }
1052df9ec2daSUwe Kleine-König
store_fan_full_speed(struct device * dev,struct device_attribute * devattr,const char * buf,size_t count)1053df9ec2daSUwe Kleine-König static ssize_t store_fan_full_speed(struct device *dev,
1054df9ec2daSUwe Kleine-König struct device_attribute *devattr,
1055df9ec2daSUwe Kleine-König const char *buf, size_t count)
1056df9ec2daSUwe Kleine-König {
1057df9ec2daSUwe Kleine-König struct f71882fg_data *data = dev_get_drvdata(dev);
1058df9ec2daSUwe Kleine-König int err, nr = to_sensor_dev_attr_2(devattr)->index;
1059df9ec2daSUwe Kleine-König long val;
1060df9ec2daSUwe Kleine-König
1061df9ec2daSUwe Kleine-König err = kstrtol(buf, 10, &val);
1062df9ec2daSUwe Kleine-König if (err)
1063df9ec2daSUwe Kleine-König return err;
1064df9ec2daSUwe Kleine-König
1065df9ec2daSUwe Kleine-König val = clamp_val(val, 23, 1500000);
1066df9ec2daSUwe Kleine-König val = fan_to_reg(val);
1067df9ec2daSUwe Kleine-König
1068df9ec2daSUwe Kleine-König mutex_lock(&data->update_lock);
1069df9ec2daSUwe Kleine-König f71882fg_write16(data, F71882FG_REG_FAN_FULL_SPEED(nr), val);
1070df9ec2daSUwe Kleine-König data->fan_full_speed[nr] = val;
1071df9ec2daSUwe Kleine-König mutex_unlock(&data->update_lock);
1072df9ec2daSUwe Kleine-König
1073df9ec2daSUwe Kleine-König return count;
1074df9ec2daSUwe Kleine-König }
1075df9ec2daSUwe Kleine-König
show_fan_alarm(struct device * dev,struct device_attribute * devattr,char * buf)1076df9ec2daSUwe Kleine-König static ssize_t show_fan_alarm(struct device *dev, struct device_attribute
1077df9ec2daSUwe Kleine-König *devattr, char *buf)
1078df9ec2daSUwe Kleine-König {
1079df9ec2daSUwe Kleine-König struct f71882fg_data *data = f71882fg_update_device(dev);
1080df9ec2daSUwe Kleine-König int nr = to_sensor_dev_attr_2(devattr)->index;
1081df9ec2daSUwe Kleine-König
1082df9ec2daSUwe Kleine-König if (data->fan_status & (1 << nr))
1083df9ec2daSUwe Kleine-König return sprintf(buf, "1\n");
1084df9ec2daSUwe Kleine-König else
1085df9ec2daSUwe Kleine-König return sprintf(buf, "0\n");
1086df9ec2daSUwe Kleine-König }
1087df9ec2daSUwe Kleine-König
show_pwm(struct device * dev,struct device_attribute * devattr,char * buf)1088df9ec2daSUwe Kleine-König static ssize_t show_pwm(struct device *dev,
1089df9ec2daSUwe Kleine-König struct device_attribute *devattr, char *buf)
1090df9ec2daSUwe Kleine-König {
1091df9ec2daSUwe Kleine-König struct f71882fg_data *data = f71882fg_update_device(dev);
1092df9ec2daSUwe Kleine-König int val, nr = to_sensor_dev_attr_2(devattr)->index;
1093df9ec2daSUwe Kleine-König mutex_lock(&data->update_lock);
1094df9ec2daSUwe Kleine-König if (data->pwm_enable & (1 << (2 * nr)))
1095df9ec2daSUwe Kleine-König /* PWM mode */
1096df9ec2daSUwe Kleine-König val = data->pwm[nr];
1097df9ec2daSUwe Kleine-König else {
1098df9ec2daSUwe Kleine-König /* RPM mode */
1099*0babf89cSNikita Zhandarovich if (fan_from_reg(data->fan_full_speed[nr]))
1100df9ec2daSUwe Kleine-König val = 255 * fan_from_reg(data->fan_target[nr])
1101df9ec2daSUwe Kleine-König / fan_from_reg(data->fan_full_speed[nr]);
1102*0babf89cSNikita Zhandarovich else
1103*0babf89cSNikita Zhandarovich val = 0;
1104df9ec2daSUwe Kleine-König }
1105df9ec2daSUwe Kleine-König mutex_unlock(&data->update_lock);
1106df9ec2daSUwe Kleine-König return sprintf(buf, "%d\n", val);
1107df9ec2daSUwe Kleine-König }
1108df9ec2daSUwe Kleine-König
store_pwm(struct device * dev,struct device_attribute * devattr,const char * buf,size_t count)1109df9ec2daSUwe Kleine-König static ssize_t store_pwm(struct device *dev,
1110df9ec2daSUwe Kleine-König struct device_attribute *devattr, const char *buf,
1111df9ec2daSUwe Kleine-König size_t count)
1112df9ec2daSUwe Kleine-König {
1113df9ec2daSUwe Kleine-König struct f71882fg_data *data = dev_get_drvdata(dev);
1114df9ec2daSUwe Kleine-König int err, nr = to_sensor_dev_attr_2(devattr)->index;
1115df9ec2daSUwe Kleine-König long val;
1116df9ec2daSUwe Kleine-König
1117df9ec2daSUwe Kleine-König err = kstrtol(buf, 10, &val);
1118df9ec2daSUwe Kleine-König if (err)
1119df9ec2daSUwe Kleine-König return err;
1120df9ec2daSUwe Kleine-König
1121df9ec2daSUwe Kleine-König val = clamp_val(val, 0, 255);
1122df9ec2daSUwe Kleine-König
1123df9ec2daSUwe Kleine-König mutex_lock(&data->update_lock);
1124df9ec2daSUwe Kleine-König data->pwm_enable = f71882fg_read8(data, F71882FG_REG_PWM_ENABLE);
1125df9ec2daSUwe Kleine-König if ((data->type == f8000 && ((data->pwm_enable >> 2 * nr) & 3) != 2) ||
1126df9ec2daSUwe Kleine-König (data->type != f8000 && !((data->pwm_enable >> 2 * nr) & 2))) {
1127df9ec2daSUwe Kleine-König count = -EROFS;
1128df9ec2daSUwe Kleine-König goto leave;
1129df9ec2daSUwe Kleine-König }
1130df9ec2daSUwe Kleine-König if (data->pwm_enable & (1 << (2 * nr))) {
1131df9ec2daSUwe Kleine-König /* PWM mode */
1132df9ec2daSUwe Kleine-König f71882fg_write8(data, F71882FG_REG_PWM(nr), val);
1133df9ec2daSUwe Kleine-König data->pwm[nr] = val;
1134df9ec2daSUwe Kleine-König } else {
1135df9ec2daSUwe Kleine-König /* RPM mode */
1136df9ec2daSUwe Kleine-König int target, full_speed;
1137df9ec2daSUwe Kleine-König full_speed = f71882fg_read16(data,
1138df9ec2daSUwe Kleine-König F71882FG_REG_FAN_FULL_SPEED(nr));
1139df9ec2daSUwe Kleine-König target = fan_to_reg(val * fan_from_reg(full_speed) / 255);
1140df9ec2daSUwe Kleine-König f71882fg_write16(data, F71882FG_REG_FAN_TARGET(nr), target);
1141df9ec2daSUwe Kleine-König data->fan_target[nr] = target;
1142df9ec2daSUwe Kleine-König data->fan_full_speed[nr] = full_speed;
1143df9ec2daSUwe Kleine-König }
1144df9ec2daSUwe Kleine-König leave:
1145df9ec2daSUwe Kleine-König mutex_unlock(&data->update_lock);
1146df9ec2daSUwe Kleine-König
1147df9ec2daSUwe Kleine-König return count;
1148df9ec2daSUwe Kleine-König }
1149df9ec2daSUwe Kleine-König
show_pwm_enable(struct device * dev,struct device_attribute * devattr,char * buf)1150df9ec2daSUwe Kleine-König static ssize_t show_pwm_enable(struct device *dev,
1151df9ec2daSUwe Kleine-König struct device_attribute *devattr, char *buf)
1152df9ec2daSUwe Kleine-König {
1153df9ec2daSUwe Kleine-König int result = 0;
1154df9ec2daSUwe Kleine-König struct f71882fg_data *data = f71882fg_update_device(dev);
1155df9ec2daSUwe Kleine-König int nr = to_sensor_dev_attr_2(devattr)->index;
1156df9ec2daSUwe Kleine-König
1157df9ec2daSUwe Kleine-König switch ((data->pwm_enable >> 2 * nr) & 3) {
1158df9ec2daSUwe Kleine-König case 0:
1159df9ec2daSUwe Kleine-König case 1:
1160df9ec2daSUwe Kleine-König result = 2; /* Normal auto mode */
1161df9ec2daSUwe Kleine-König break;
1162df9ec2daSUwe Kleine-König case 2:
1163df9ec2daSUwe Kleine-König result = 1; /* Manual mode */
1164df9ec2daSUwe Kleine-König break;
1165df9ec2daSUwe Kleine-König case 3:
1166df9ec2daSUwe Kleine-König if (data->type == f8000)
1167df9ec2daSUwe Kleine-König result = 3; /* Thermostat mode */
1168df9ec2daSUwe Kleine-König else
1169df9ec2daSUwe Kleine-König result = 1; /* Manual mode */
1170df9ec2daSUwe Kleine-König break;
1171df9ec2daSUwe Kleine-König }
1172df9ec2daSUwe Kleine-König
1173df9ec2daSUwe Kleine-König return sprintf(buf, "%d\n", result);
1174df9ec2daSUwe Kleine-König }
1175df9ec2daSUwe Kleine-König
store_pwm_enable(struct device * dev,struct device_attribute * devattr,const char * buf,size_t count)1176df9ec2daSUwe Kleine-König static ssize_t store_pwm_enable(struct device *dev, struct device_attribute
1177df9ec2daSUwe Kleine-König *devattr, const char *buf, size_t count)
1178df9ec2daSUwe Kleine-König {
1179df9ec2daSUwe Kleine-König struct f71882fg_data *data = dev_get_drvdata(dev);
1180df9ec2daSUwe Kleine-König int err, nr = to_sensor_dev_attr_2(devattr)->index;
1181df9ec2daSUwe Kleine-König long val;
1182df9ec2daSUwe Kleine-König
1183df9ec2daSUwe Kleine-König err = kstrtol(buf, 10, &val);
1184df9ec2daSUwe Kleine-König if (err)
1185df9ec2daSUwe Kleine-König return err;
1186df9ec2daSUwe Kleine-König
1187df9ec2daSUwe Kleine-König /* Special case for F8000 pwm channel 3 which only does auto mode */
1188df9ec2daSUwe Kleine-König if (data->type == f8000 && nr == 2 && val != 2)
1189df9ec2daSUwe Kleine-König return -EINVAL;
1190df9ec2daSUwe Kleine-König
1191df9ec2daSUwe Kleine-König mutex_lock(&data->update_lock);
1192df9ec2daSUwe Kleine-König data->pwm_enable = f71882fg_read8(data, F71882FG_REG_PWM_ENABLE);
1193df9ec2daSUwe Kleine-König /* Special case for F8000 auto PWM mode / Thermostat mode */
1194df9ec2daSUwe Kleine-König if (data->type == f8000 && ((data->pwm_enable >> 2 * nr) & 1)) {
1195df9ec2daSUwe Kleine-König switch (val) {
1196df9ec2daSUwe Kleine-König case 2:
1197df9ec2daSUwe Kleine-König data->pwm_enable &= ~(2 << (2 * nr));
1198df9ec2daSUwe Kleine-König break; /* Normal auto mode */
1199df9ec2daSUwe Kleine-König case 3:
1200df9ec2daSUwe Kleine-König data->pwm_enable |= 2 << (2 * nr);
1201df9ec2daSUwe Kleine-König break; /* Thermostat mode */
1202df9ec2daSUwe Kleine-König default:
1203df9ec2daSUwe Kleine-König count = -EINVAL;
1204df9ec2daSUwe Kleine-König goto leave;
1205df9ec2daSUwe Kleine-König }
1206df9ec2daSUwe Kleine-König } else {
1207df9ec2daSUwe Kleine-König switch (val) {
1208df9ec2daSUwe Kleine-König case 1:
1209df9ec2daSUwe Kleine-König /* The f71858fg does not support manual RPM mode */
1210df9ec2daSUwe Kleine-König if (data->type == f71858fg &&
1211df9ec2daSUwe Kleine-König ((data->pwm_enable >> (2 * nr)) & 1)) {
1212df9ec2daSUwe Kleine-König count = -EINVAL;
1213df9ec2daSUwe Kleine-König goto leave;
1214df9ec2daSUwe Kleine-König }
1215df9ec2daSUwe Kleine-König data->pwm_enable |= 2 << (2 * nr);
1216df9ec2daSUwe Kleine-König break; /* Manual */
1217df9ec2daSUwe Kleine-König case 2:
1218df9ec2daSUwe Kleine-König data->pwm_enable &= ~(2 << (2 * nr));
1219df9ec2daSUwe Kleine-König break; /* Normal auto mode */
1220df9ec2daSUwe Kleine-König default:
1221df9ec2daSUwe Kleine-König count = -EINVAL;
1222df9ec2daSUwe Kleine-König goto leave;
1223df9ec2daSUwe Kleine-König }
1224df9ec2daSUwe Kleine-König }
1225df9ec2daSUwe Kleine-König f71882fg_write8(data, F71882FG_REG_PWM_ENABLE, data->pwm_enable);
1226df9ec2daSUwe Kleine-König leave:
1227df9ec2daSUwe Kleine-König mutex_unlock(&data->update_lock);
1228df9ec2daSUwe Kleine-König
1229df9ec2daSUwe Kleine-König return count;
1230df9ec2daSUwe Kleine-König }
1231df9ec2daSUwe Kleine-König
show_pwm_interpolate(struct device * dev,struct device_attribute * devattr,char * buf)1232df9ec2daSUwe Kleine-König static ssize_t show_pwm_interpolate(struct device *dev,
1233df9ec2daSUwe Kleine-König struct device_attribute *devattr, char *buf)
1234df9ec2daSUwe Kleine-König {
1235df9ec2daSUwe Kleine-König int result;
1236df9ec2daSUwe Kleine-König struct f71882fg_data *data = f71882fg_update_device(dev);
1237df9ec2daSUwe Kleine-König int nr = to_sensor_dev_attr_2(devattr)->index;
1238df9ec2daSUwe Kleine-König
1239df9ec2daSUwe Kleine-König result = (data->pwm_auto_point_mapping[nr] >> 4) & 1;
1240df9ec2daSUwe Kleine-König
1241df9ec2daSUwe Kleine-König return sprintf(buf, "%d\n", result);
1242df9ec2daSUwe Kleine-König }
1243df9ec2daSUwe Kleine-König
store_pwm_interpolate(struct device * dev,struct device_attribute * devattr,const char * buf,size_t count)1244df9ec2daSUwe Kleine-König static ssize_t store_pwm_interpolate(struct device *dev,
1245df9ec2daSUwe Kleine-König struct device_attribute *devattr,
1246df9ec2daSUwe Kleine-König const char *buf, size_t count)
1247df9ec2daSUwe Kleine-König {
1248df9ec2daSUwe Kleine-König struct f71882fg_data *data = dev_get_drvdata(dev);
1249df9ec2daSUwe Kleine-König int err, nr = to_sensor_dev_attr_2(devattr)->index;
1250df9ec2daSUwe Kleine-König unsigned long val;
1251df9ec2daSUwe Kleine-König
1252df9ec2daSUwe Kleine-König err = kstrtoul(buf, 10, &val);
1253df9ec2daSUwe Kleine-König if (err)
1254df9ec2daSUwe Kleine-König return err;
1255df9ec2daSUwe Kleine-König
1256df9ec2daSUwe Kleine-König mutex_lock(&data->update_lock);
1257df9ec2daSUwe Kleine-König data->pwm_auto_point_mapping[nr] =
1258df9ec2daSUwe Kleine-König f71882fg_read8(data, F71882FG_REG_POINT_MAPPING(nr));
1259df9ec2daSUwe Kleine-König if (val)
1260df9ec2daSUwe Kleine-König val = data->pwm_auto_point_mapping[nr] | (1 << 4);
1261df9ec2daSUwe Kleine-König else
1262df9ec2daSUwe Kleine-König val = data->pwm_auto_point_mapping[nr] & (~(1 << 4));
1263df9ec2daSUwe Kleine-König f71882fg_write8(data, F71882FG_REG_POINT_MAPPING(nr), val);
1264df9ec2daSUwe Kleine-König data->pwm_auto_point_mapping[nr] = val;
1265df9ec2daSUwe Kleine-König mutex_unlock(&data->update_lock);
1266df9ec2daSUwe Kleine-König
1267df9ec2daSUwe Kleine-König return count;
1268df9ec2daSUwe Kleine-König }
1269df9ec2daSUwe Kleine-König
1270ed4f7c20SHans de Goede /* Fan / PWM attr common to all models */
1271b69b0399SHans de Goede static struct sensor_device_attribute_2 fxxxx_fan_attr[4][6] = { {
1272bc37ae71SMark van Doesburg SENSOR_ATTR_2(fan1_input, S_IRUGO, show_fan, NULL, 0, 0),
12739ab796ebSMark van Doesburg SENSOR_ATTR_2(fan1_full_speed, S_IRUGO|S_IWUSR,
12749ab796ebSMark van Doesburg show_fan_full_speed,
12759ab796ebSMark van Doesburg store_fan_full_speed, 0, 0),
1276bc37ae71SMark van Doesburg SENSOR_ATTR_2(fan1_alarm, S_IRUGO, show_fan_alarm, NULL, 0, 0),
12779ab796ebSMark van Doesburg SENSOR_ATTR_2(pwm1, S_IRUGO|S_IWUSR, show_pwm, store_pwm, 0, 0),
12789ab796ebSMark van Doesburg SENSOR_ATTR_2(pwm1_enable, S_IRUGO|S_IWUSR, show_pwm_enable,
12799ab796ebSMark van Doesburg store_pwm_enable, 0, 0),
12809ab796ebSMark van Doesburg SENSOR_ATTR_2(pwm1_interpolate, S_IRUGO|S_IWUSR,
12819ab796ebSMark van Doesburg show_pwm_interpolate, store_pwm_interpolate, 0, 0),
1282b69b0399SHans de Goede }, {
1283b69b0399SHans de Goede SENSOR_ATTR_2(fan2_input, S_IRUGO, show_fan, NULL, 0, 1),
1284b69b0399SHans de Goede SENSOR_ATTR_2(fan2_full_speed, S_IRUGO|S_IWUSR,
1285b69b0399SHans de Goede show_fan_full_speed,
1286b69b0399SHans de Goede store_fan_full_speed, 0, 1),
1287b69b0399SHans de Goede SENSOR_ATTR_2(fan2_alarm, S_IRUGO, show_fan_alarm, NULL, 0, 1),
1288498be968SHans de Goede SENSOR_ATTR_2(pwm2, S_IRUGO|S_IWUSR, show_pwm, store_pwm, 0, 1),
1289498be968SHans de Goede SENSOR_ATTR_2(pwm2_enable, S_IRUGO|S_IWUSR, show_pwm_enable,
1290498be968SHans de Goede store_pwm_enable, 0, 1),
1291498be968SHans de Goede SENSOR_ATTR_2(pwm2_interpolate, S_IRUGO|S_IWUSR,
1292498be968SHans de Goede show_pwm_interpolate, store_pwm_interpolate, 0, 1),
1293b69b0399SHans de Goede }, {
1294b69b0399SHans de Goede SENSOR_ATTR_2(fan3_input, S_IRUGO, show_fan, NULL, 0, 2),
1295b69b0399SHans de Goede SENSOR_ATTR_2(fan3_full_speed, S_IRUGO|S_IWUSR,
1296b69b0399SHans de Goede show_fan_full_speed,
1297b69b0399SHans de Goede store_fan_full_speed, 0, 2),
1298b69b0399SHans de Goede SENSOR_ATTR_2(fan3_alarm, S_IRUGO, show_fan_alarm, NULL, 0, 2),
12993fc7838aSHans de Goede SENSOR_ATTR_2(pwm3, S_IRUGO|S_IWUSR, show_pwm, store_pwm, 0, 2),
13003fc7838aSHans de Goede SENSOR_ATTR_2(pwm3_enable, S_IRUGO|S_IWUSR, show_pwm_enable,
13013fc7838aSHans de Goede store_pwm_enable, 0, 2),
1302498be968SHans de Goede SENSOR_ATTR_2(pwm3_interpolate, S_IRUGO|S_IWUSR,
1303498be968SHans de Goede show_pwm_interpolate, store_pwm_interpolate, 0, 2),
1304b69b0399SHans de Goede }, {
1305b69b0399SHans de Goede SENSOR_ATTR_2(fan4_input, S_IRUGO, show_fan, NULL, 0, 3),
1306b69b0399SHans de Goede SENSOR_ATTR_2(fan4_full_speed, S_IRUGO|S_IWUSR,
1307b69b0399SHans de Goede show_fan_full_speed,
1308b69b0399SHans de Goede store_fan_full_speed, 0, 3),
1309b69b0399SHans de Goede SENSOR_ATTR_2(fan4_alarm, S_IRUGO, show_fan_alarm, NULL, 0, 3),
1310b69b0399SHans de Goede SENSOR_ATTR_2(pwm4, S_IRUGO|S_IWUSR, show_pwm, store_pwm, 0, 3),
1311b69b0399SHans de Goede SENSOR_ATTR_2(pwm4_enable, S_IRUGO|S_IWUSR, show_pwm_enable,
1312b69b0399SHans de Goede store_pwm_enable, 0, 3),
1313b69b0399SHans de Goede SENSOR_ATTR_2(pwm4_interpolate, S_IRUGO|S_IWUSR,
1314b69b0399SHans de Goede show_pwm_interpolate, store_pwm_interpolate, 0, 3),
1315b69b0399SHans de Goede } };
1316498be968SHans de Goede
show_simple_pwm(struct device * dev,struct device_attribute * devattr,char * buf)1317df9ec2daSUwe Kleine-König static ssize_t show_simple_pwm(struct device *dev,
1318df9ec2daSUwe Kleine-König struct device_attribute *devattr, char *buf)
1319df9ec2daSUwe Kleine-König {
1320df9ec2daSUwe Kleine-König struct f71882fg_data *data = f71882fg_update_device(dev);
1321df9ec2daSUwe Kleine-König int val, nr = to_sensor_dev_attr_2(devattr)->index;
1322df9ec2daSUwe Kleine-König
1323df9ec2daSUwe Kleine-König val = data->pwm[nr];
1324df9ec2daSUwe Kleine-König return sprintf(buf, "%d\n", val);
1325df9ec2daSUwe Kleine-König }
1326df9ec2daSUwe Kleine-König
store_simple_pwm(struct device * dev,struct device_attribute * devattr,const char * buf,size_t count)1327df9ec2daSUwe Kleine-König static ssize_t store_simple_pwm(struct device *dev,
1328df9ec2daSUwe Kleine-König struct device_attribute *devattr,
1329df9ec2daSUwe Kleine-König const char *buf, size_t count)
1330df9ec2daSUwe Kleine-König {
1331df9ec2daSUwe Kleine-König struct f71882fg_data *data = dev_get_drvdata(dev);
1332df9ec2daSUwe Kleine-König int err, nr = to_sensor_dev_attr_2(devattr)->index;
1333df9ec2daSUwe Kleine-König long val;
1334df9ec2daSUwe Kleine-König
1335df9ec2daSUwe Kleine-König err = kstrtol(buf, 10, &val);
1336df9ec2daSUwe Kleine-König if (err)
1337df9ec2daSUwe Kleine-König return err;
1338df9ec2daSUwe Kleine-König
1339df9ec2daSUwe Kleine-König val = clamp_val(val, 0, 255);
1340df9ec2daSUwe Kleine-König
1341df9ec2daSUwe Kleine-König mutex_lock(&data->update_lock);
1342df9ec2daSUwe Kleine-König f71882fg_write8(data, F71882FG_REG_PWM(nr), val);
1343df9ec2daSUwe Kleine-König data->pwm[nr] = val;
1344df9ec2daSUwe Kleine-König mutex_unlock(&data->update_lock);
1345df9ec2daSUwe Kleine-König
1346df9ec2daSUwe Kleine-König return count;
1347df9ec2daSUwe Kleine-König }
1348df9ec2daSUwe Kleine-König
1349629c58baSHans de Goede /* Attr for the third fan of the f71808a, which only has manual pwm */
1350629c58baSHans de Goede static struct sensor_device_attribute_2 f71808a_fan3_attr[] = {
1351629c58baSHans de Goede SENSOR_ATTR_2(fan3_input, S_IRUGO, show_fan, NULL, 0, 2),
1352629c58baSHans de Goede SENSOR_ATTR_2(fan3_alarm, S_IRUGO, show_fan_alarm, NULL, 0, 2),
1353629c58baSHans de Goede SENSOR_ATTR_2(pwm3, S_IRUGO|S_IWUSR,
1354629c58baSHans de Goede show_simple_pwm, store_simple_pwm, 0, 2),
1355629c58baSHans de Goede };
1356629c58baSHans de Goede
show_fan_beep(struct device * dev,struct device_attribute * devattr,char * buf)1357df9ec2daSUwe Kleine-König static ssize_t show_fan_beep(struct device *dev, struct device_attribute
1358df9ec2daSUwe Kleine-König *devattr, char *buf)
1359df9ec2daSUwe Kleine-König {
1360df9ec2daSUwe Kleine-König struct f71882fg_data *data = f71882fg_update_device(dev);
1361df9ec2daSUwe Kleine-König int nr = to_sensor_dev_attr_2(devattr)->index;
1362df9ec2daSUwe Kleine-König
1363df9ec2daSUwe Kleine-König if (data->fan_beep & (1 << nr))
1364df9ec2daSUwe Kleine-König return sprintf(buf, "1\n");
1365df9ec2daSUwe Kleine-König else
1366df9ec2daSUwe Kleine-König return sprintf(buf, "0\n");
1367df9ec2daSUwe Kleine-König }
1368df9ec2daSUwe Kleine-König
store_fan_beep(struct device * dev,struct device_attribute * devattr,const char * buf,size_t count)1369df9ec2daSUwe Kleine-König static ssize_t store_fan_beep(struct device *dev, struct device_attribute
1370df9ec2daSUwe Kleine-König *devattr, const char *buf, size_t count)
1371df9ec2daSUwe Kleine-König {
1372df9ec2daSUwe Kleine-König struct f71882fg_data *data = dev_get_drvdata(dev);
1373df9ec2daSUwe Kleine-König int err, nr = to_sensor_dev_attr_2(devattr)->index;
1374df9ec2daSUwe Kleine-König unsigned long val;
1375df9ec2daSUwe Kleine-König
1376df9ec2daSUwe Kleine-König err = kstrtoul(buf, 10, &val);
1377df9ec2daSUwe Kleine-König if (err)
1378df9ec2daSUwe Kleine-König return err;
1379df9ec2daSUwe Kleine-König
1380df9ec2daSUwe Kleine-König mutex_lock(&data->update_lock);
1381df9ec2daSUwe Kleine-König data->fan_beep = f71882fg_read8(data, F71882FG_REG_FAN_BEEP);
1382df9ec2daSUwe Kleine-König if (val)
1383df9ec2daSUwe Kleine-König data->fan_beep |= 1 << nr;
1384df9ec2daSUwe Kleine-König else
1385df9ec2daSUwe Kleine-König data->fan_beep &= ~(1 << nr);
1386df9ec2daSUwe Kleine-König
1387df9ec2daSUwe Kleine-König f71882fg_write8(data, F71882FG_REG_FAN_BEEP, data->fan_beep);
1388df9ec2daSUwe Kleine-König mutex_unlock(&data->update_lock);
1389df9ec2daSUwe Kleine-König
1390df9ec2daSUwe Kleine-König return count;
1391df9ec2daSUwe Kleine-König }
1392df9ec2daSUwe Kleine-König
139366344aa6SHans de Goede /* Attr for models which can beep on Fan alarm */
139466344aa6SHans de Goede static struct sensor_device_attribute_2 fxxxx_fan_beep_attr[] = {
1395ed4f7c20SHans de Goede SENSOR_ATTR_2(fan1_beep, S_IRUGO|S_IWUSR, show_fan_beep,
1396ed4f7c20SHans de Goede store_fan_beep, 0, 0),
1397ed4f7c20SHans de Goede SENSOR_ATTR_2(fan2_beep, S_IRUGO|S_IWUSR, show_fan_beep,
1398ed4f7c20SHans de Goede store_fan_beep, 0, 1),
1399ed4f7c20SHans de Goede SENSOR_ATTR_2(fan3_beep, S_IRUGO|S_IWUSR, show_fan_beep,
1400ed4f7c20SHans de Goede store_fan_beep, 0, 2),
1401b69b0399SHans de Goede SENSOR_ATTR_2(fan4_beep, S_IRUGO|S_IWUSR, show_fan_beep,
1402b69b0399SHans de Goede store_fan_beep, 0, 3),
140366344aa6SHans de Goede };
1404ed4f7c20SHans de Goede
show_pwm_auto_point_channel(struct device * dev,struct device_attribute * devattr,char * buf)1405df9ec2daSUwe Kleine-König static ssize_t show_pwm_auto_point_channel(struct device *dev,
1406df9ec2daSUwe Kleine-König struct device_attribute *devattr,
1407df9ec2daSUwe Kleine-König char *buf)
1408df9ec2daSUwe Kleine-König {
1409df9ec2daSUwe Kleine-König int result;
1410df9ec2daSUwe Kleine-König struct f71882fg_data *data = f71882fg_update_device(dev);
1411df9ec2daSUwe Kleine-König int nr = to_sensor_dev_attr_2(devattr)->index;
1412df9ec2daSUwe Kleine-König
1413df9ec2daSUwe Kleine-König result = 1 << ((data->pwm_auto_point_mapping[nr] & 3) -
1414df9ec2daSUwe Kleine-König data->temp_start);
1415df9ec2daSUwe Kleine-König
1416df9ec2daSUwe Kleine-König return sprintf(buf, "%d\n", result);
1417df9ec2daSUwe Kleine-König }
1418df9ec2daSUwe Kleine-König
store_pwm_auto_point_channel(struct device * dev,struct device_attribute * devattr,const char * buf,size_t count)1419df9ec2daSUwe Kleine-König static ssize_t store_pwm_auto_point_channel(struct device *dev,
1420df9ec2daSUwe Kleine-König struct device_attribute *devattr,
1421df9ec2daSUwe Kleine-König const char *buf, size_t count)
1422df9ec2daSUwe Kleine-König {
1423df9ec2daSUwe Kleine-König struct f71882fg_data *data = dev_get_drvdata(dev);
1424df9ec2daSUwe Kleine-König int err, nr = to_sensor_dev_attr_2(devattr)->index;
1425df9ec2daSUwe Kleine-König long val;
1426df9ec2daSUwe Kleine-König
1427df9ec2daSUwe Kleine-König err = kstrtol(buf, 10, &val);
1428df9ec2daSUwe Kleine-König if (err)
1429df9ec2daSUwe Kleine-König return err;
1430df9ec2daSUwe Kleine-König
1431df9ec2daSUwe Kleine-König switch (val) {
1432df9ec2daSUwe Kleine-König case 1:
1433df9ec2daSUwe Kleine-König val = 0;
1434df9ec2daSUwe Kleine-König break;
1435df9ec2daSUwe Kleine-König case 2:
1436df9ec2daSUwe Kleine-König val = 1;
1437df9ec2daSUwe Kleine-König break;
1438df9ec2daSUwe Kleine-König case 4:
1439df9ec2daSUwe Kleine-König val = 2;
1440df9ec2daSUwe Kleine-König break;
1441df9ec2daSUwe Kleine-König default:
1442df9ec2daSUwe Kleine-König return -EINVAL;
1443df9ec2daSUwe Kleine-König }
1444df9ec2daSUwe Kleine-König val += data->temp_start;
1445df9ec2daSUwe Kleine-König mutex_lock(&data->update_lock);
1446df9ec2daSUwe Kleine-König data->pwm_auto_point_mapping[nr] =
1447df9ec2daSUwe Kleine-König f71882fg_read8(data, F71882FG_REG_POINT_MAPPING(nr));
1448df9ec2daSUwe Kleine-König val = (data->pwm_auto_point_mapping[nr] & 0xfc) | val;
1449df9ec2daSUwe Kleine-König f71882fg_write8(data, F71882FG_REG_POINT_MAPPING(nr), val);
1450df9ec2daSUwe Kleine-König data->pwm_auto_point_mapping[nr] = val;
1451df9ec2daSUwe Kleine-König mutex_unlock(&data->update_lock);
1452df9ec2daSUwe Kleine-König
1453df9ec2daSUwe Kleine-König return count;
1454df9ec2daSUwe Kleine-König }
1455df9ec2daSUwe Kleine-König
show_pwm_auto_point_pwm(struct device * dev,struct device_attribute * devattr,char * buf)1456df9ec2daSUwe Kleine-König static ssize_t show_pwm_auto_point_pwm(struct device *dev,
1457df9ec2daSUwe Kleine-König struct device_attribute *devattr,
1458df9ec2daSUwe Kleine-König char *buf)
1459df9ec2daSUwe Kleine-König {
1460df9ec2daSUwe Kleine-König int result;
1461df9ec2daSUwe Kleine-König struct f71882fg_data *data = f71882fg_update_device(dev);
1462df9ec2daSUwe Kleine-König int pwm = to_sensor_dev_attr_2(devattr)->index;
1463df9ec2daSUwe Kleine-König int point = to_sensor_dev_attr_2(devattr)->nr;
1464df9ec2daSUwe Kleine-König
1465df9ec2daSUwe Kleine-König mutex_lock(&data->update_lock);
1466df9ec2daSUwe Kleine-König if (data->pwm_enable & (1 << (2 * pwm))) {
1467df9ec2daSUwe Kleine-König /* PWM mode */
1468df9ec2daSUwe Kleine-König result = data->pwm_auto_point_pwm[pwm][point];
1469df9ec2daSUwe Kleine-König } else {
1470df9ec2daSUwe Kleine-König /* RPM mode */
1471df9ec2daSUwe Kleine-König result = 32 * 255 / (32 + data->pwm_auto_point_pwm[pwm][point]);
1472df9ec2daSUwe Kleine-König }
1473df9ec2daSUwe Kleine-König mutex_unlock(&data->update_lock);
1474df9ec2daSUwe Kleine-König
1475df9ec2daSUwe Kleine-König return sprintf(buf, "%d\n", result);
1476df9ec2daSUwe Kleine-König }
1477df9ec2daSUwe Kleine-König
store_pwm_auto_point_pwm(struct device * dev,struct device_attribute * devattr,const char * buf,size_t count)1478df9ec2daSUwe Kleine-König static ssize_t store_pwm_auto_point_pwm(struct device *dev,
1479df9ec2daSUwe Kleine-König struct device_attribute *devattr,
1480df9ec2daSUwe Kleine-König const char *buf, size_t count)
1481df9ec2daSUwe Kleine-König {
1482df9ec2daSUwe Kleine-König struct f71882fg_data *data = dev_get_drvdata(dev);
1483df9ec2daSUwe Kleine-König int err, pwm = to_sensor_dev_attr_2(devattr)->index;
1484df9ec2daSUwe Kleine-König int point = to_sensor_dev_attr_2(devattr)->nr;
1485df9ec2daSUwe Kleine-König long val;
1486df9ec2daSUwe Kleine-König
1487df9ec2daSUwe Kleine-König err = kstrtol(buf, 10, &val);
1488df9ec2daSUwe Kleine-König if (err)
1489df9ec2daSUwe Kleine-König return err;
1490df9ec2daSUwe Kleine-König
1491df9ec2daSUwe Kleine-König val = clamp_val(val, 0, 255);
1492df9ec2daSUwe Kleine-König
1493df9ec2daSUwe Kleine-König mutex_lock(&data->update_lock);
1494df9ec2daSUwe Kleine-König data->pwm_enable = f71882fg_read8(data, F71882FG_REG_PWM_ENABLE);
1495df9ec2daSUwe Kleine-König if (data->pwm_enable & (1 << (2 * pwm))) {
1496df9ec2daSUwe Kleine-König /* PWM mode */
1497df9ec2daSUwe Kleine-König } else {
1498df9ec2daSUwe Kleine-König /* RPM mode */
1499df9ec2daSUwe Kleine-König if (val < 29) /* Prevent negative numbers */
1500df9ec2daSUwe Kleine-König val = 255;
1501df9ec2daSUwe Kleine-König else
1502df9ec2daSUwe Kleine-König val = (255 - val) * 32 / val;
1503df9ec2daSUwe Kleine-König }
1504df9ec2daSUwe Kleine-König f71882fg_write8(data, F71882FG_REG_POINT_PWM(pwm, point), val);
1505df9ec2daSUwe Kleine-König data->pwm_auto_point_pwm[pwm][point] = val;
1506df9ec2daSUwe Kleine-König mutex_unlock(&data->update_lock);
1507df9ec2daSUwe Kleine-König
1508df9ec2daSUwe Kleine-König return count;
1509df9ec2daSUwe Kleine-König }
1510df9ec2daSUwe Kleine-König
show_pwm_auto_point_temp(struct device * dev,struct device_attribute * devattr,char * buf)1511df9ec2daSUwe Kleine-König static ssize_t show_pwm_auto_point_temp(struct device *dev,
1512df9ec2daSUwe Kleine-König struct device_attribute *devattr,
1513df9ec2daSUwe Kleine-König char *buf)
1514df9ec2daSUwe Kleine-König {
1515df9ec2daSUwe Kleine-König int result;
1516df9ec2daSUwe Kleine-König struct f71882fg_data *data = f71882fg_update_device(dev);
1517df9ec2daSUwe Kleine-König int pwm = to_sensor_dev_attr_2(devattr)->index;
1518df9ec2daSUwe Kleine-König int point = to_sensor_dev_attr_2(devattr)->nr;
1519df9ec2daSUwe Kleine-König
1520df9ec2daSUwe Kleine-König result = data->pwm_auto_point_temp[pwm][point];
1521df9ec2daSUwe Kleine-König return sprintf(buf, "%d\n", 1000 * result);
1522df9ec2daSUwe Kleine-König }
1523df9ec2daSUwe Kleine-König
store_pwm_auto_point_temp(struct device * dev,struct device_attribute * devattr,const char * buf,size_t count)1524df9ec2daSUwe Kleine-König static ssize_t store_pwm_auto_point_temp(struct device *dev,
1525df9ec2daSUwe Kleine-König struct device_attribute *devattr,
1526df9ec2daSUwe Kleine-König const char *buf, size_t count)
1527df9ec2daSUwe Kleine-König {
1528df9ec2daSUwe Kleine-König struct f71882fg_data *data = dev_get_drvdata(dev);
1529df9ec2daSUwe Kleine-König int err, pwm = to_sensor_dev_attr_2(devattr)->index;
1530df9ec2daSUwe Kleine-König int point = to_sensor_dev_attr_2(devattr)->nr;
1531df9ec2daSUwe Kleine-König long val;
1532df9ec2daSUwe Kleine-König
1533df9ec2daSUwe Kleine-König err = kstrtol(buf, 10, &val);
1534df9ec2daSUwe Kleine-König if (err)
1535df9ec2daSUwe Kleine-König return err;
1536df9ec2daSUwe Kleine-König
1537df9ec2daSUwe Kleine-König val /= 1000;
1538df9ec2daSUwe Kleine-König
1539df9ec2daSUwe Kleine-König if (data->auto_point_temp_signed)
1540df9ec2daSUwe Kleine-König val = clamp_val(val, -128, 127);
1541df9ec2daSUwe Kleine-König else
1542df9ec2daSUwe Kleine-König val = clamp_val(val, 0, 127);
1543df9ec2daSUwe Kleine-König
1544df9ec2daSUwe Kleine-König mutex_lock(&data->update_lock);
1545df9ec2daSUwe Kleine-König f71882fg_write8(data, F71882FG_REG_POINT_TEMP(pwm, point), val);
1546df9ec2daSUwe Kleine-König data->pwm_auto_point_temp[pwm][point] = val;
1547df9ec2daSUwe Kleine-König mutex_unlock(&data->update_lock);
1548df9ec2daSUwe Kleine-König
1549df9ec2daSUwe Kleine-König return count;
1550df9ec2daSUwe Kleine-König }
1551df9ec2daSUwe Kleine-König
show_pwm_auto_point_temp_hyst(struct device * dev,struct device_attribute * devattr,char * buf)1552df9ec2daSUwe Kleine-König static ssize_t show_pwm_auto_point_temp_hyst(struct device *dev,
1553df9ec2daSUwe Kleine-König struct device_attribute *devattr,
1554df9ec2daSUwe Kleine-König char *buf)
1555df9ec2daSUwe Kleine-König {
1556df9ec2daSUwe Kleine-König int result = 0;
1557df9ec2daSUwe Kleine-König struct f71882fg_data *data = f71882fg_update_device(dev);
1558df9ec2daSUwe Kleine-König int nr = to_sensor_dev_attr_2(devattr)->index;
1559df9ec2daSUwe Kleine-König int point = to_sensor_dev_attr_2(devattr)->nr;
1560df9ec2daSUwe Kleine-König
1561df9ec2daSUwe Kleine-König mutex_lock(&data->update_lock);
1562df9ec2daSUwe Kleine-König if (nr & 1)
1563df9ec2daSUwe Kleine-König result = data->pwm_auto_point_hyst[nr / 2] >> 4;
1564df9ec2daSUwe Kleine-König else
1565df9ec2daSUwe Kleine-König result = data->pwm_auto_point_hyst[nr / 2] & 0x0f;
1566df9ec2daSUwe Kleine-König result = 1000 * (data->pwm_auto_point_temp[nr][point] - result);
1567df9ec2daSUwe Kleine-König mutex_unlock(&data->update_lock);
1568df9ec2daSUwe Kleine-König
1569df9ec2daSUwe Kleine-König return sprintf(buf, "%d\n", result);
1570df9ec2daSUwe Kleine-König }
1571df9ec2daSUwe Kleine-König
store_pwm_auto_point_temp_hyst(struct device * dev,struct device_attribute * devattr,const char * buf,size_t count)1572df9ec2daSUwe Kleine-König static ssize_t store_pwm_auto_point_temp_hyst(struct device *dev,
1573df9ec2daSUwe Kleine-König struct device_attribute *devattr,
1574df9ec2daSUwe Kleine-König const char *buf, size_t count)
1575df9ec2daSUwe Kleine-König {
1576df9ec2daSUwe Kleine-König struct f71882fg_data *data = dev_get_drvdata(dev);
1577df9ec2daSUwe Kleine-König int err, nr = to_sensor_dev_attr_2(devattr)->index;
1578df9ec2daSUwe Kleine-König int point = to_sensor_dev_attr_2(devattr)->nr;
1579df9ec2daSUwe Kleine-König u8 reg;
1580df9ec2daSUwe Kleine-König long val;
1581df9ec2daSUwe Kleine-König
1582df9ec2daSUwe Kleine-König err = kstrtol(buf, 10, &val);
1583df9ec2daSUwe Kleine-König if (err)
1584df9ec2daSUwe Kleine-König return err;
1585df9ec2daSUwe Kleine-König
1586df9ec2daSUwe Kleine-König val /= 1000;
1587df9ec2daSUwe Kleine-König
1588df9ec2daSUwe Kleine-König mutex_lock(&data->update_lock);
1589df9ec2daSUwe Kleine-König data->pwm_auto_point_temp[nr][point] =
1590df9ec2daSUwe Kleine-König f71882fg_read8(data, F71882FG_REG_POINT_TEMP(nr, point));
1591df9ec2daSUwe Kleine-König val = clamp_val(val, data->pwm_auto_point_temp[nr][point] - 15,
1592df9ec2daSUwe Kleine-König data->pwm_auto_point_temp[nr][point]);
1593df9ec2daSUwe Kleine-König val = data->pwm_auto_point_temp[nr][point] - val;
1594df9ec2daSUwe Kleine-König
1595df9ec2daSUwe Kleine-König reg = f71882fg_read8(data, F71882FG_REG_FAN_HYST(nr / 2));
1596df9ec2daSUwe Kleine-König if (nr & 1)
1597df9ec2daSUwe Kleine-König reg = (reg & 0x0f) | (val << 4);
1598df9ec2daSUwe Kleine-König else
1599df9ec2daSUwe Kleine-König reg = (reg & 0xf0) | val;
1600df9ec2daSUwe Kleine-König
1601df9ec2daSUwe Kleine-König f71882fg_write8(data, F71882FG_REG_FAN_HYST(nr / 2), reg);
1602df9ec2daSUwe Kleine-König data->pwm_auto_point_hyst[nr / 2] = reg;
1603df9ec2daSUwe Kleine-König mutex_unlock(&data->update_lock);
1604df9ec2daSUwe Kleine-König
1605df9ec2daSUwe Kleine-König return count;
1606df9ec2daSUwe Kleine-König }
1607df9ec2daSUwe Kleine-König
160820eaf724SGuenter Roeck /*
160920eaf724SGuenter Roeck * PWM attr for the f71862fg, fewer pwms and fewer zones per pwm than the
161020eaf724SGuenter Roeck * standard models
161120eaf724SGuenter Roeck */
161255840142SHans de Goede static struct sensor_device_attribute_2 f71862fg_auto_pwm_attr[3][7] = { {
161366344aa6SHans de Goede SENSOR_ATTR_2(pwm1_auto_channels_temp, S_IRUGO|S_IWUSR,
161466344aa6SHans de Goede show_pwm_auto_point_channel,
161566344aa6SHans de Goede store_pwm_auto_point_channel, 0, 0),
1616498be968SHans de Goede SENSOR_ATTR_2(pwm1_auto_point1_pwm, S_IRUGO|S_IWUSR,
1617498be968SHans de Goede show_pwm_auto_point_pwm, store_pwm_auto_point_pwm,
1618498be968SHans de Goede 1, 0),
1619498be968SHans de Goede SENSOR_ATTR_2(pwm1_auto_point2_pwm, S_IRUGO|S_IWUSR,
1620498be968SHans de Goede show_pwm_auto_point_pwm, store_pwm_auto_point_pwm,
1621498be968SHans de Goede 4, 0),
1622498be968SHans de Goede SENSOR_ATTR_2(pwm1_auto_point1_temp, S_IRUGO|S_IWUSR,
1623498be968SHans de Goede show_pwm_auto_point_temp, store_pwm_auto_point_temp,
1624498be968SHans de Goede 0, 0),
1625498be968SHans de Goede SENSOR_ATTR_2(pwm1_auto_point2_temp, S_IRUGO|S_IWUSR,
1626498be968SHans de Goede show_pwm_auto_point_temp, store_pwm_auto_point_temp,
1627498be968SHans de Goede 3, 0),
1628498be968SHans de Goede SENSOR_ATTR_2(pwm1_auto_point1_temp_hyst, S_IRUGO|S_IWUSR,
1629498be968SHans de Goede show_pwm_auto_point_temp_hyst,
1630498be968SHans de Goede store_pwm_auto_point_temp_hyst,
1631498be968SHans de Goede 0, 0),
1632498be968SHans de Goede SENSOR_ATTR_2(pwm1_auto_point2_temp_hyst, S_IRUGO,
1633498be968SHans de Goede show_pwm_auto_point_temp_hyst, NULL, 3, 0),
163455840142SHans de Goede }, {
163566344aa6SHans de Goede SENSOR_ATTR_2(pwm2_auto_channels_temp, S_IRUGO|S_IWUSR,
163666344aa6SHans de Goede show_pwm_auto_point_channel,
163766344aa6SHans de Goede store_pwm_auto_point_channel, 0, 1),
1638498be968SHans de Goede SENSOR_ATTR_2(pwm2_auto_point1_pwm, S_IRUGO|S_IWUSR,
1639498be968SHans de Goede show_pwm_auto_point_pwm, store_pwm_auto_point_pwm,
1640498be968SHans de Goede 1, 1),
1641498be968SHans de Goede SENSOR_ATTR_2(pwm2_auto_point2_pwm, S_IRUGO|S_IWUSR,
1642498be968SHans de Goede show_pwm_auto_point_pwm, store_pwm_auto_point_pwm,
1643498be968SHans de Goede 4, 1),
1644498be968SHans de Goede SENSOR_ATTR_2(pwm2_auto_point1_temp, S_IRUGO|S_IWUSR,
1645498be968SHans de Goede show_pwm_auto_point_temp, store_pwm_auto_point_temp,
1646498be968SHans de Goede 0, 1),
1647498be968SHans de Goede SENSOR_ATTR_2(pwm2_auto_point2_temp, S_IRUGO|S_IWUSR,
1648498be968SHans de Goede show_pwm_auto_point_temp, store_pwm_auto_point_temp,
1649498be968SHans de Goede 3, 1),
1650498be968SHans de Goede SENSOR_ATTR_2(pwm2_auto_point1_temp_hyst, S_IRUGO|S_IWUSR,
1651498be968SHans de Goede show_pwm_auto_point_temp_hyst,
1652498be968SHans de Goede store_pwm_auto_point_temp_hyst,
1653498be968SHans de Goede 0, 1),
1654498be968SHans de Goede SENSOR_ATTR_2(pwm2_auto_point2_temp_hyst, S_IRUGO,
1655498be968SHans de Goede show_pwm_auto_point_temp_hyst, NULL, 3, 1),
165655840142SHans de Goede }, {
165766344aa6SHans de Goede SENSOR_ATTR_2(pwm3_auto_channels_temp, S_IRUGO|S_IWUSR,
165866344aa6SHans de Goede show_pwm_auto_point_channel,
165966344aa6SHans de Goede store_pwm_auto_point_channel, 0, 2),
16604901062fSHans de Goede SENSOR_ATTR_2(pwm3_auto_point1_pwm, S_IRUGO|S_IWUSR,
16614901062fSHans de Goede show_pwm_auto_point_pwm, store_pwm_auto_point_pwm,
16624901062fSHans de Goede 1, 2),
16634901062fSHans de Goede SENSOR_ATTR_2(pwm3_auto_point2_pwm, S_IRUGO|S_IWUSR,
16644901062fSHans de Goede show_pwm_auto_point_pwm, store_pwm_auto_point_pwm,
16654901062fSHans de Goede 4, 2),
16664901062fSHans de Goede SENSOR_ATTR_2(pwm3_auto_point1_temp, S_IRUGO|S_IWUSR,
16674901062fSHans de Goede show_pwm_auto_point_temp, store_pwm_auto_point_temp,
16684901062fSHans de Goede 0, 2),
16694901062fSHans de Goede SENSOR_ATTR_2(pwm3_auto_point2_temp, S_IRUGO|S_IWUSR,
16704901062fSHans de Goede show_pwm_auto_point_temp, store_pwm_auto_point_temp,
16714901062fSHans de Goede 3, 2),
16724901062fSHans de Goede SENSOR_ATTR_2(pwm3_auto_point1_temp_hyst, S_IRUGO|S_IWUSR,
16734901062fSHans de Goede show_pwm_auto_point_temp_hyst,
16744901062fSHans de Goede store_pwm_auto_point_temp_hyst,
16754901062fSHans de Goede 0, 2),
16764901062fSHans de Goede SENSOR_ATTR_2(pwm3_auto_point2_temp_hyst, S_IRUGO,
16774901062fSHans de Goede show_pwm_auto_point_temp_hyst, NULL, 3, 2),
167855840142SHans de Goede } };
1679498be968SHans de Goede
168020eaf724SGuenter Roeck /*
168120eaf724SGuenter Roeck * PWM attr for the f71808e/f71869, almost identical to the f71862fg, but the
168220eaf724SGuenter Roeck * pwm setting when the temperature is above the pwmX_auto_point1_temp can be
168320eaf724SGuenter Roeck * programmed instead of being hardcoded to 0xff
168420eaf724SGuenter Roeck */
168555840142SHans de Goede static struct sensor_device_attribute_2 f71869_auto_pwm_attr[3][8] = { {
1686c11bb993SHans de Goede SENSOR_ATTR_2(pwm1_auto_channels_temp, S_IRUGO|S_IWUSR,
1687c11bb993SHans de Goede show_pwm_auto_point_channel,
1688c11bb993SHans de Goede store_pwm_auto_point_channel, 0, 0),
1689c11bb993SHans de Goede SENSOR_ATTR_2(pwm1_auto_point1_pwm, S_IRUGO|S_IWUSR,
1690c11bb993SHans de Goede show_pwm_auto_point_pwm, store_pwm_auto_point_pwm,
1691c11bb993SHans de Goede 0, 0),
1692c11bb993SHans de Goede SENSOR_ATTR_2(pwm1_auto_point2_pwm, S_IRUGO|S_IWUSR,
1693c11bb993SHans de Goede show_pwm_auto_point_pwm, store_pwm_auto_point_pwm,
1694c11bb993SHans de Goede 1, 0),
1695c11bb993SHans de Goede SENSOR_ATTR_2(pwm1_auto_point3_pwm, S_IRUGO|S_IWUSR,
1696c11bb993SHans de Goede show_pwm_auto_point_pwm, store_pwm_auto_point_pwm,
1697c11bb993SHans de Goede 4, 0),
1698c11bb993SHans de Goede SENSOR_ATTR_2(pwm1_auto_point1_temp, S_IRUGO|S_IWUSR,
1699c11bb993SHans de Goede show_pwm_auto_point_temp, store_pwm_auto_point_temp,
1700c11bb993SHans de Goede 0, 0),
1701c11bb993SHans de Goede SENSOR_ATTR_2(pwm1_auto_point2_temp, S_IRUGO|S_IWUSR,
1702c11bb993SHans de Goede show_pwm_auto_point_temp, store_pwm_auto_point_temp,
1703c11bb993SHans de Goede 3, 0),
1704c11bb993SHans de Goede SENSOR_ATTR_2(pwm1_auto_point1_temp_hyst, S_IRUGO|S_IWUSR,
1705c11bb993SHans de Goede show_pwm_auto_point_temp_hyst,
1706c11bb993SHans de Goede store_pwm_auto_point_temp_hyst,
1707c11bb993SHans de Goede 0, 0),
1708c11bb993SHans de Goede SENSOR_ATTR_2(pwm1_auto_point2_temp_hyst, S_IRUGO,
1709c11bb993SHans de Goede show_pwm_auto_point_temp_hyst, NULL, 3, 0),
171055840142SHans de Goede }, {
1711c11bb993SHans de Goede SENSOR_ATTR_2(pwm2_auto_channels_temp, S_IRUGO|S_IWUSR,
1712c11bb993SHans de Goede show_pwm_auto_point_channel,
1713c11bb993SHans de Goede store_pwm_auto_point_channel, 0, 1),
1714c11bb993SHans de Goede SENSOR_ATTR_2(pwm2_auto_point1_pwm, S_IRUGO|S_IWUSR,
1715c11bb993SHans de Goede show_pwm_auto_point_pwm, store_pwm_auto_point_pwm,
1716c11bb993SHans de Goede 0, 1),
1717c11bb993SHans de Goede SENSOR_ATTR_2(pwm2_auto_point2_pwm, S_IRUGO|S_IWUSR,
1718c11bb993SHans de Goede show_pwm_auto_point_pwm, store_pwm_auto_point_pwm,
1719c11bb993SHans de Goede 1, 1),
1720c11bb993SHans de Goede SENSOR_ATTR_2(pwm2_auto_point3_pwm, S_IRUGO|S_IWUSR,
1721c11bb993SHans de Goede show_pwm_auto_point_pwm, store_pwm_auto_point_pwm,
1722c11bb993SHans de Goede 4, 1),
1723c11bb993SHans de Goede SENSOR_ATTR_2(pwm2_auto_point1_temp, S_IRUGO|S_IWUSR,
1724c11bb993SHans de Goede show_pwm_auto_point_temp, store_pwm_auto_point_temp,
1725c11bb993SHans de Goede 0, 1),
1726c11bb993SHans de Goede SENSOR_ATTR_2(pwm2_auto_point2_temp, S_IRUGO|S_IWUSR,
1727c11bb993SHans de Goede show_pwm_auto_point_temp, store_pwm_auto_point_temp,
1728c11bb993SHans de Goede 3, 1),
1729c11bb993SHans de Goede SENSOR_ATTR_2(pwm2_auto_point1_temp_hyst, S_IRUGO|S_IWUSR,
1730c11bb993SHans de Goede show_pwm_auto_point_temp_hyst,
1731c11bb993SHans de Goede store_pwm_auto_point_temp_hyst,
1732c11bb993SHans de Goede 0, 1),
1733c11bb993SHans de Goede SENSOR_ATTR_2(pwm2_auto_point2_temp_hyst, S_IRUGO,
1734c11bb993SHans de Goede show_pwm_auto_point_temp_hyst, NULL, 3, 1),
173555840142SHans de Goede }, {
1736c11bb993SHans de Goede SENSOR_ATTR_2(pwm3_auto_channels_temp, S_IRUGO|S_IWUSR,
1737c11bb993SHans de Goede show_pwm_auto_point_channel,
1738c11bb993SHans de Goede store_pwm_auto_point_channel, 0, 2),
1739c11bb993SHans de Goede SENSOR_ATTR_2(pwm3_auto_point1_pwm, S_IRUGO|S_IWUSR,
1740c11bb993SHans de Goede show_pwm_auto_point_pwm, store_pwm_auto_point_pwm,
1741c11bb993SHans de Goede 0, 2),
1742c11bb993SHans de Goede SENSOR_ATTR_2(pwm3_auto_point2_pwm, S_IRUGO|S_IWUSR,
1743c11bb993SHans de Goede show_pwm_auto_point_pwm, store_pwm_auto_point_pwm,
1744c11bb993SHans de Goede 1, 2),
1745c11bb993SHans de Goede SENSOR_ATTR_2(pwm3_auto_point3_pwm, S_IRUGO|S_IWUSR,
1746c11bb993SHans de Goede show_pwm_auto_point_pwm, store_pwm_auto_point_pwm,
1747c11bb993SHans de Goede 4, 2),
1748c11bb993SHans de Goede SENSOR_ATTR_2(pwm3_auto_point1_temp, S_IRUGO|S_IWUSR,
1749c11bb993SHans de Goede show_pwm_auto_point_temp, store_pwm_auto_point_temp,
1750c11bb993SHans de Goede 0, 2),
1751c11bb993SHans de Goede SENSOR_ATTR_2(pwm3_auto_point2_temp, S_IRUGO|S_IWUSR,
1752c11bb993SHans de Goede show_pwm_auto_point_temp, store_pwm_auto_point_temp,
1753c11bb993SHans de Goede 3, 2),
1754c11bb993SHans de Goede SENSOR_ATTR_2(pwm3_auto_point1_temp_hyst, S_IRUGO|S_IWUSR,
1755c11bb993SHans de Goede show_pwm_auto_point_temp_hyst,
1756c11bb993SHans de Goede store_pwm_auto_point_temp_hyst,
1757c11bb993SHans de Goede 0, 2),
1758c11bb993SHans de Goede SENSOR_ATTR_2(pwm3_auto_point2_temp_hyst, S_IRUGO,
1759c11bb993SHans de Goede show_pwm_auto_point_temp_hyst, NULL, 3, 2),
176055840142SHans de Goede } };
1761c11bb993SHans de Goede
17623cad4022SHans de Goede /* PWM attr for the standard models */
1763b69b0399SHans de Goede static struct sensor_device_attribute_2 fxxxx_auto_pwm_attr[4][14] = { {
176466344aa6SHans de Goede SENSOR_ATTR_2(pwm1_auto_channels_temp, S_IRUGO|S_IWUSR,
176566344aa6SHans de Goede show_pwm_auto_point_channel,
176666344aa6SHans de Goede store_pwm_auto_point_channel, 0, 0),
17679ab796ebSMark van Doesburg SENSOR_ATTR_2(pwm1_auto_point1_pwm, S_IRUGO|S_IWUSR,
17689ab796ebSMark van Doesburg show_pwm_auto_point_pwm, store_pwm_auto_point_pwm,
17699ab796ebSMark van Doesburg 0, 0),
17709ab796ebSMark van Doesburg SENSOR_ATTR_2(pwm1_auto_point2_pwm, S_IRUGO|S_IWUSR,
17719ab796ebSMark van Doesburg show_pwm_auto_point_pwm, store_pwm_auto_point_pwm,
17729ab796ebSMark van Doesburg 1, 0),
17739ab796ebSMark van Doesburg SENSOR_ATTR_2(pwm1_auto_point3_pwm, S_IRUGO|S_IWUSR,
17749ab796ebSMark van Doesburg show_pwm_auto_point_pwm, store_pwm_auto_point_pwm,
17759ab796ebSMark van Doesburg 2, 0),
17769ab796ebSMark van Doesburg SENSOR_ATTR_2(pwm1_auto_point4_pwm, S_IRUGO|S_IWUSR,
17779ab796ebSMark van Doesburg show_pwm_auto_point_pwm, store_pwm_auto_point_pwm,
17789ab796ebSMark van Doesburg 3, 0),
17799ab796ebSMark van Doesburg SENSOR_ATTR_2(pwm1_auto_point5_pwm, S_IRUGO|S_IWUSR,
17809ab796ebSMark van Doesburg show_pwm_auto_point_pwm, store_pwm_auto_point_pwm,
17819ab796ebSMark van Doesburg 4, 0),
17829ab796ebSMark van Doesburg SENSOR_ATTR_2(pwm1_auto_point1_temp, S_IRUGO|S_IWUSR,
17839ab796ebSMark van Doesburg show_pwm_auto_point_temp, store_pwm_auto_point_temp,
17849ab796ebSMark van Doesburg 0, 0),
17859ab796ebSMark van Doesburg SENSOR_ATTR_2(pwm1_auto_point2_temp, S_IRUGO|S_IWUSR,
17869ab796ebSMark van Doesburg show_pwm_auto_point_temp, store_pwm_auto_point_temp,
17879ab796ebSMark van Doesburg 1, 0),
17889ab796ebSMark van Doesburg SENSOR_ATTR_2(pwm1_auto_point3_temp, S_IRUGO|S_IWUSR,
17899ab796ebSMark van Doesburg show_pwm_auto_point_temp, store_pwm_auto_point_temp,
17909ab796ebSMark van Doesburg 2, 0),
17919ab796ebSMark van Doesburg SENSOR_ATTR_2(pwm1_auto_point4_temp, S_IRUGO|S_IWUSR,
17929ab796ebSMark van Doesburg show_pwm_auto_point_temp, store_pwm_auto_point_temp,
17939ab796ebSMark van Doesburg 3, 0),
17949ab796ebSMark van Doesburg SENSOR_ATTR_2(pwm1_auto_point1_temp_hyst, S_IRUGO|S_IWUSR,
17959ab796ebSMark van Doesburg show_pwm_auto_point_temp_hyst,
17969ab796ebSMark van Doesburg store_pwm_auto_point_temp_hyst,
17979ab796ebSMark van Doesburg 0, 0),
17989ab796ebSMark van Doesburg SENSOR_ATTR_2(pwm1_auto_point2_temp_hyst, S_IRUGO,
17999ab796ebSMark van Doesburg show_pwm_auto_point_temp_hyst, NULL, 1, 0),
18009ab796ebSMark van Doesburg SENSOR_ATTR_2(pwm1_auto_point3_temp_hyst, S_IRUGO,
18019ab796ebSMark van Doesburg show_pwm_auto_point_temp_hyst, NULL, 2, 0),
18029ab796ebSMark van Doesburg SENSOR_ATTR_2(pwm1_auto_point4_temp_hyst, S_IRUGO,
18039ab796ebSMark van Doesburg show_pwm_auto_point_temp_hyst, NULL, 3, 0),
1804b69b0399SHans de Goede }, {
180566344aa6SHans de Goede SENSOR_ATTR_2(pwm2_auto_channels_temp, S_IRUGO|S_IWUSR,
180666344aa6SHans de Goede show_pwm_auto_point_channel,
180766344aa6SHans de Goede store_pwm_auto_point_channel, 0, 1),
18089ab796ebSMark van Doesburg SENSOR_ATTR_2(pwm2_auto_point1_pwm, S_IRUGO|S_IWUSR,
18099ab796ebSMark van Doesburg show_pwm_auto_point_pwm, store_pwm_auto_point_pwm,
18109ab796ebSMark van Doesburg 0, 1),
18119ab796ebSMark van Doesburg SENSOR_ATTR_2(pwm2_auto_point2_pwm, S_IRUGO|S_IWUSR,
18129ab796ebSMark van Doesburg show_pwm_auto_point_pwm, store_pwm_auto_point_pwm,
18139ab796ebSMark van Doesburg 1, 1),
18149ab796ebSMark van Doesburg SENSOR_ATTR_2(pwm2_auto_point3_pwm, S_IRUGO|S_IWUSR,
18159ab796ebSMark van Doesburg show_pwm_auto_point_pwm, store_pwm_auto_point_pwm,
18169ab796ebSMark van Doesburg 2, 1),
18179ab796ebSMark van Doesburg SENSOR_ATTR_2(pwm2_auto_point4_pwm, S_IRUGO|S_IWUSR,
18189ab796ebSMark van Doesburg show_pwm_auto_point_pwm, store_pwm_auto_point_pwm,
18199ab796ebSMark van Doesburg 3, 1),
18209ab796ebSMark van Doesburg SENSOR_ATTR_2(pwm2_auto_point5_pwm, S_IRUGO|S_IWUSR,
18219ab796ebSMark van Doesburg show_pwm_auto_point_pwm, store_pwm_auto_point_pwm,
18229ab796ebSMark van Doesburg 4, 1),
18239ab796ebSMark van Doesburg SENSOR_ATTR_2(pwm2_auto_point1_temp, S_IRUGO|S_IWUSR,
18249ab796ebSMark van Doesburg show_pwm_auto_point_temp, store_pwm_auto_point_temp,
18259ab796ebSMark van Doesburg 0, 1),
18269ab796ebSMark van Doesburg SENSOR_ATTR_2(pwm2_auto_point2_temp, S_IRUGO|S_IWUSR,
18279ab796ebSMark van Doesburg show_pwm_auto_point_temp, store_pwm_auto_point_temp,
18289ab796ebSMark van Doesburg 1, 1),
18299ab796ebSMark van Doesburg SENSOR_ATTR_2(pwm2_auto_point3_temp, S_IRUGO|S_IWUSR,
18309ab796ebSMark van Doesburg show_pwm_auto_point_temp, store_pwm_auto_point_temp,
18319ab796ebSMark van Doesburg 2, 1),
18329ab796ebSMark van Doesburg SENSOR_ATTR_2(pwm2_auto_point4_temp, S_IRUGO|S_IWUSR,
18339ab796ebSMark van Doesburg show_pwm_auto_point_temp, store_pwm_auto_point_temp,
18349ab796ebSMark van Doesburg 3, 1),
18359ab796ebSMark van Doesburg SENSOR_ATTR_2(pwm2_auto_point1_temp_hyst, S_IRUGO|S_IWUSR,
18369ab796ebSMark van Doesburg show_pwm_auto_point_temp_hyst,
18379ab796ebSMark van Doesburg store_pwm_auto_point_temp_hyst,
18389ab796ebSMark van Doesburg 0, 1),
18399ab796ebSMark van Doesburg SENSOR_ATTR_2(pwm2_auto_point2_temp_hyst, S_IRUGO,
18409ab796ebSMark van Doesburg show_pwm_auto_point_temp_hyst, NULL, 1, 1),
18419ab796ebSMark van Doesburg SENSOR_ATTR_2(pwm2_auto_point3_temp_hyst, S_IRUGO,
18429ab796ebSMark van Doesburg show_pwm_auto_point_temp_hyst, NULL, 2, 1),
18439ab796ebSMark van Doesburg SENSOR_ATTR_2(pwm2_auto_point4_temp_hyst, S_IRUGO,
18449ab796ebSMark van Doesburg show_pwm_auto_point_temp_hyst, NULL, 3, 1),
1845b69b0399SHans de Goede }, {
184666344aa6SHans de Goede SENSOR_ATTR_2(pwm3_auto_channels_temp, S_IRUGO|S_IWUSR,
184766344aa6SHans de Goede show_pwm_auto_point_channel,
184866344aa6SHans de Goede store_pwm_auto_point_channel, 0, 2),
18499ab796ebSMark van Doesburg SENSOR_ATTR_2(pwm3_auto_point1_pwm, S_IRUGO|S_IWUSR,
18509ab796ebSMark van Doesburg show_pwm_auto_point_pwm, store_pwm_auto_point_pwm,
18519ab796ebSMark van Doesburg 0, 2),
18529ab796ebSMark van Doesburg SENSOR_ATTR_2(pwm3_auto_point2_pwm, S_IRUGO|S_IWUSR,
18539ab796ebSMark van Doesburg show_pwm_auto_point_pwm, store_pwm_auto_point_pwm,
18549ab796ebSMark van Doesburg 1, 2),
18559ab796ebSMark van Doesburg SENSOR_ATTR_2(pwm3_auto_point3_pwm, S_IRUGO|S_IWUSR,
18569ab796ebSMark van Doesburg show_pwm_auto_point_pwm, store_pwm_auto_point_pwm,
18579ab796ebSMark van Doesburg 2, 2),
18589ab796ebSMark van Doesburg SENSOR_ATTR_2(pwm3_auto_point4_pwm, S_IRUGO|S_IWUSR,
18599ab796ebSMark van Doesburg show_pwm_auto_point_pwm, store_pwm_auto_point_pwm,
18609ab796ebSMark van Doesburg 3, 2),
18619ab796ebSMark van Doesburg SENSOR_ATTR_2(pwm3_auto_point5_pwm, S_IRUGO|S_IWUSR,
18629ab796ebSMark van Doesburg show_pwm_auto_point_pwm, store_pwm_auto_point_pwm,
18639ab796ebSMark van Doesburg 4, 2),
18649ab796ebSMark van Doesburg SENSOR_ATTR_2(pwm3_auto_point1_temp, S_IRUGO|S_IWUSR,
18659ab796ebSMark van Doesburg show_pwm_auto_point_temp, store_pwm_auto_point_temp,
18669ab796ebSMark van Doesburg 0, 2),
18679ab796ebSMark van Doesburg SENSOR_ATTR_2(pwm3_auto_point2_temp, S_IRUGO|S_IWUSR,
18689ab796ebSMark van Doesburg show_pwm_auto_point_temp, store_pwm_auto_point_temp,
18699ab796ebSMark van Doesburg 1, 2),
18709ab796ebSMark van Doesburg SENSOR_ATTR_2(pwm3_auto_point3_temp, S_IRUGO|S_IWUSR,
18719ab796ebSMark van Doesburg show_pwm_auto_point_temp, store_pwm_auto_point_temp,
18729ab796ebSMark van Doesburg 2, 2),
18739ab796ebSMark van Doesburg SENSOR_ATTR_2(pwm3_auto_point4_temp, S_IRUGO|S_IWUSR,
18749ab796ebSMark van Doesburg show_pwm_auto_point_temp, store_pwm_auto_point_temp,
18759ab796ebSMark van Doesburg 3, 2),
18769ab796ebSMark van Doesburg SENSOR_ATTR_2(pwm3_auto_point1_temp_hyst, S_IRUGO|S_IWUSR,
18779ab796ebSMark van Doesburg show_pwm_auto_point_temp_hyst,
18789ab796ebSMark van Doesburg store_pwm_auto_point_temp_hyst,
18799ab796ebSMark van Doesburg 0, 2),
18809ab796ebSMark van Doesburg SENSOR_ATTR_2(pwm3_auto_point2_temp_hyst, S_IRUGO,
18819ab796ebSMark van Doesburg show_pwm_auto_point_temp_hyst, NULL, 1, 2),
18829ab796ebSMark van Doesburg SENSOR_ATTR_2(pwm3_auto_point3_temp_hyst, S_IRUGO,
18839ab796ebSMark van Doesburg show_pwm_auto_point_temp_hyst, NULL, 2, 2),
18849ab796ebSMark van Doesburg SENSOR_ATTR_2(pwm3_auto_point4_temp_hyst, S_IRUGO,
18859ab796ebSMark van Doesburg show_pwm_auto_point_temp_hyst, NULL, 3, 2),
1886b69b0399SHans de Goede }, {
18879ab796ebSMark van Doesburg SENSOR_ATTR_2(pwm4_auto_channels_temp, S_IRUGO|S_IWUSR,
18889ab796ebSMark van Doesburg show_pwm_auto_point_channel,
18899ab796ebSMark van Doesburg store_pwm_auto_point_channel, 0, 3),
18909ab796ebSMark van Doesburg SENSOR_ATTR_2(pwm4_auto_point1_pwm, S_IRUGO|S_IWUSR,
18919ab796ebSMark van Doesburg show_pwm_auto_point_pwm, store_pwm_auto_point_pwm,
18929ab796ebSMark van Doesburg 0, 3),
18939ab796ebSMark van Doesburg SENSOR_ATTR_2(pwm4_auto_point2_pwm, S_IRUGO|S_IWUSR,
18949ab796ebSMark van Doesburg show_pwm_auto_point_pwm, store_pwm_auto_point_pwm,
18959ab796ebSMark van Doesburg 1, 3),
18969ab796ebSMark van Doesburg SENSOR_ATTR_2(pwm4_auto_point3_pwm, S_IRUGO|S_IWUSR,
18979ab796ebSMark van Doesburg show_pwm_auto_point_pwm, store_pwm_auto_point_pwm,
18989ab796ebSMark van Doesburg 2, 3),
18999ab796ebSMark van Doesburg SENSOR_ATTR_2(pwm4_auto_point4_pwm, S_IRUGO|S_IWUSR,
19009ab796ebSMark van Doesburg show_pwm_auto_point_pwm, store_pwm_auto_point_pwm,
19019ab796ebSMark van Doesburg 3, 3),
19029ab796ebSMark van Doesburg SENSOR_ATTR_2(pwm4_auto_point5_pwm, S_IRUGO|S_IWUSR,
19039ab796ebSMark van Doesburg show_pwm_auto_point_pwm, store_pwm_auto_point_pwm,
19049ab796ebSMark van Doesburg 4, 3),
19059ab796ebSMark van Doesburg SENSOR_ATTR_2(pwm4_auto_point1_temp, S_IRUGO|S_IWUSR,
19069ab796ebSMark van Doesburg show_pwm_auto_point_temp, store_pwm_auto_point_temp,
19079ab796ebSMark van Doesburg 0, 3),
19089ab796ebSMark van Doesburg SENSOR_ATTR_2(pwm4_auto_point2_temp, S_IRUGO|S_IWUSR,
19099ab796ebSMark van Doesburg show_pwm_auto_point_temp, store_pwm_auto_point_temp,
19109ab796ebSMark van Doesburg 1, 3),
19119ab796ebSMark van Doesburg SENSOR_ATTR_2(pwm4_auto_point3_temp, S_IRUGO|S_IWUSR,
19129ab796ebSMark van Doesburg show_pwm_auto_point_temp, store_pwm_auto_point_temp,
19139ab796ebSMark van Doesburg 2, 3),
19149ab796ebSMark van Doesburg SENSOR_ATTR_2(pwm4_auto_point4_temp, S_IRUGO|S_IWUSR,
19159ab796ebSMark van Doesburg show_pwm_auto_point_temp, store_pwm_auto_point_temp,
19169ab796ebSMark van Doesburg 3, 3),
19179ab796ebSMark van Doesburg SENSOR_ATTR_2(pwm4_auto_point1_temp_hyst, S_IRUGO|S_IWUSR,
19189ab796ebSMark van Doesburg show_pwm_auto_point_temp_hyst,
19199ab796ebSMark van Doesburg store_pwm_auto_point_temp_hyst,
19209ab796ebSMark van Doesburg 0, 3),
19219ab796ebSMark van Doesburg SENSOR_ATTR_2(pwm4_auto_point2_temp_hyst, S_IRUGO,
19229ab796ebSMark van Doesburg show_pwm_auto_point_temp_hyst, NULL, 1, 3),
19239ab796ebSMark van Doesburg SENSOR_ATTR_2(pwm4_auto_point3_temp_hyst, S_IRUGO,
19249ab796ebSMark van Doesburg show_pwm_auto_point_temp_hyst, NULL, 2, 3),
19259ab796ebSMark van Doesburg SENSOR_ATTR_2(pwm4_auto_point4_temp_hyst, S_IRUGO,
19269ab796ebSMark van Doesburg show_pwm_auto_point_temp_hyst, NULL, 3, 3),
1927b69b0399SHans de Goede } };
192845fb3669SHans de Goede
192966344aa6SHans de Goede /* Fan attr specific to the f8000 (4th fan input can only measure speed) */
1930ed4f7c20SHans de Goede static struct sensor_device_attribute_2 f8000_fan_attr[] = {
1931ed4f7c20SHans de Goede SENSOR_ATTR_2(fan4_input, S_IRUGO, show_fan, NULL, 0, 3),
193266344aa6SHans de Goede };
1933ed4f7c20SHans de Goede
193420eaf724SGuenter Roeck /*
193520eaf724SGuenter Roeck * PWM attr for the f8000, zones mapped to temp instead of to pwm!
193620eaf724SGuenter Roeck * Also the register block at offset A0 maps to TEMP1 (so our temp2, as the
193720eaf724SGuenter Roeck * F8000 starts counting temps at 0), B0 maps the TEMP2 and C0 maps to TEMP0
193820eaf724SGuenter Roeck */
193955840142SHans de Goede static struct sensor_device_attribute_2 f8000_auto_pwm_attr[3][14] = { {
194066344aa6SHans de Goede SENSOR_ATTR_2(pwm1_auto_channels_temp, S_IRUGO|S_IWUSR,
194166344aa6SHans de Goede show_pwm_auto_point_channel,
194266344aa6SHans de Goede store_pwm_auto_point_channel, 0, 0),
1943ed4f7c20SHans de Goede SENSOR_ATTR_2(temp1_auto_point1_pwm, S_IRUGO|S_IWUSR,
1944ed4f7c20SHans de Goede show_pwm_auto_point_pwm, store_pwm_auto_point_pwm,
1945ed4f7c20SHans de Goede 0, 2),
1946ed4f7c20SHans de Goede SENSOR_ATTR_2(temp1_auto_point2_pwm, S_IRUGO|S_IWUSR,
1947ed4f7c20SHans de Goede show_pwm_auto_point_pwm, store_pwm_auto_point_pwm,
1948ed4f7c20SHans de Goede 1, 2),
1949ed4f7c20SHans de Goede SENSOR_ATTR_2(temp1_auto_point3_pwm, S_IRUGO|S_IWUSR,
1950ed4f7c20SHans de Goede show_pwm_auto_point_pwm, store_pwm_auto_point_pwm,
1951ed4f7c20SHans de Goede 2, 2),
1952ed4f7c20SHans de Goede SENSOR_ATTR_2(temp1_auto_point4_pwm, S_IRUGO|S_IWUSR,
1953ed4f7c20SHans de Goede show_pwm_auto_point_pwm, store_pwm_auto_point_pwm,
1954ed4f7c20SHans de Goede 3, 2),
1955ed4f7c20SHans de Goede SENSOR_ATTR_2(temp1_auto_point5_pwm, S_IRUGO|S_IWUSR,
1956ed4f7c20SHans de Goede show_pwm_auto_point_pwm, store_pwm_auto_point_pwm,
1957ed4f7c20SHans de Goede 4, 2),
1958ed4f7c20SHans de Goede SENSOR_ATTR_2(temp1_auto_point1_temp, S_IRUGO|S_IWUSR,
1959ed4f7c20SHans de Goede show_pwm_auto_point_temp, store_pwm_auto_point_temp,
1960ed4f7c20SHans de Goede 0, 2),
1961ed4f7c20SHans de Goede SENSOR_ATTR_2(temp1_auto_point2_temp, S_IRUGO|S_IWUSR,
1962ed4f7c20SHans de Goede show_pwm_auto_point_temp, store_pwm_auto_point_temp,
1963ed4f7c20SHans de Goede 1, 2),
1964ed4f7c20SHans de Goede SENSOR_ATTR_2(temp1_auto_point3_temp, S_IRUGO|S_IWUSR,
1965ed4f7c20SHans de Goede show_pwm_auto_point_temp, store_pwm_auto_point_temp,
1966ed4f7c20SHans de Goede 2, 2),
1967ed4f7c20SHans de Goede SENSOR_ATTR_2(temp1_auto_point4_temp, S_IRUGO|S_IWUSR,
1968ed4f7c20SHans de Goede show_pwm_auto_point_temp, store_pwm_auto_point_temp,
1969ed4f7c20SHans de Goede 3, 2),
1970ed4f7c20SHans de Goede SENSOR_ATTR_2(temp1_auto_point1_temp_hyst, S_IRUGO|S_IWUSR,
1971ed4f7c20SHans de Goede show_pwm_auto_point_temp_hyst,
1972ed4f7c20SHans de Goede store_pwm_auto_point_temp_hyst,
1973ed4f7c20SHans de Goede 0, 2),
1974ed4f7c20SHans de Goede SENSOR_ATTR_2(temp1_auto_point2_temp_hyst, S_IRUGO,
1975ed4f7c20SHans de Goede show_pwm_auto_point_temp_hyst, NULL, 1, 2),
1976ed4f7c20SHans de Goede SENSOR_ATTR_2(temp1_auto_point3_temp_hyst, S_IRUGO,
1977ed4f7c20SHans de Goede show_pwm_auto_point_temp_hyst, NULL, 2, 2),
1978ed4f7c20SHans de Goede SENSOR_ATTR_2(temp1_auto_point4_temp_hyst, S_IRUGO,
1979ed4f7c20SHans de Goede show_pwm_auto_point_temp_hyst, NULL, 3, 2),
198055840142SHans de Goede }, {
198166344aa6SHans de Goede SENSOR_ATTR_2(pwm2_auto_channels_temp, S_IRUGO|S_IWUSR,
198266344aa6SHans de Goede show_pwm_auto_point_channel,
198366344aa6SHans de Goede store_pwm_auto_point_channel, 0, 1),
1984ed4f7c20SHans de Goede SENSOR_ATTR_2(temp2_auto_point1_pwm, S_IRUGO|S_IWUSR,
1985ed4f7c20SHans de Goede show_pwm_auto_point_pwm, store_pwm_auto_point_pwm,
1986ed4f7c20SHans de Goede 0, 0),
1987ed4f7c20SHans de Goede SENSOR_ATTR_2(temp2_auto_point2_pwm, S_IRUGO|S_IWUSR,
1988ed4f7c20SHans de Goede show_pwm_auto_point_pwm, store_pwm_auto_point_pwm,
1989ed4f7c20SHans de Goede 1, 0),
1990ed4f7c20SHans de Goede SENSOR_ATTR_2(temp2_auto_point3_pwm, S_IRUGO|S_IWUSR,
1991ed4f7c20SHans de Goede show_pwm_auto_point_pwm, store_pwm_auto_point_pwm,
1992ed4f7c20SHans de Goede 2, 0),
1993ed4f7c20SHans de Goede SENSOR_ATTR_2(temp2_auto_point4_pwm, S_IRUGO|S_IWUSR,
1994ed4f7c20SHans de Goede show_pwm_auto_point_pwm, store_pwm_auto_point_pwm,
1995ed4f7c20SHans de Goede 3, 0),
1996ed4f7c20SHans de Goede SENSOR_ATTR_2(temp2_auto_point5_pwm, S_IRUGO|S_IWUSR,
1997ed4f7c20SHans de Goede show_pwm_auto_point_pwm, store_pwm_auto_point_pwm,
1998ed4f7c20SHans de Goede 4, 0),
1999ed4f7c20SHans de Goede SENSOR_ATTR_2(temp2_auto_point1_temp, S_IRUGO|S_IWUSR,
2000ed4f7c20SHans de Goede show_pwm_auto_point_temp, store_pwm_auto_point_temp,
2001ed4f7c20SHans de Goede 0, 0),
2002ed4f7c20SHans de Goede SENSOR_ATTR_2(temp2_auto_point2_temp, S_IRUGO|S_IWUSR,
2003ed4f7c20SHans de Goede show_pwm_auto_point_temp, store_pwm_auto_point_temp,
2004ed4f7c20SHans de Goede 1, 0),
2005ed4f7c20SHans de Goede SENSOR_ATTR_2(temp2_auto_point3_temp, S_IRUGO|S_IWUSR,
2006ed4f7c20SHans de Goede show_pwm_auto_point_temp, store_pwm_auto_point_temp,
2007ed4f7c20SHans de Goede 2, 0),
2008ed4f7c20SHans de Goede SENSOR_ATTR_2(temp2_auto_point4_temp, S_IRUGO|S_IWUSR,
2009ed4f7c20SHans de Goede show_pwm_auto_point_temp, store_pwm_auto_point_temp,
2010ed4f7c20SHans de Goede 3, 0),
2011ed4f7c20SHans de Goede SENSOR_ATTR_2(temp2_auto_point1_temp_hyst, S_IRUGO|S_IWUSR,
2012ed4f7c20SHans de Goede show_pwm_auto_point_temp_hyst,
2013ed4f7c20SHans de Goede store_pwm_auto_point_temp_hyst,
2014ed4f7c20SHans de Goede 0, 0),
2015ed4f7c20SHans de Goede SENSOR_ATTR_2(temp2_auto_point2_temp_hyst, S_IRUGO,
2016ed4f7c20SHans de Goede show_pwm_auto_point_temp_hyst, NULL, 1, 0),
2017ed4f7c20SHans de Goede SENSOR_ATTR_2(temp2_auto_point3_temp_hyst, S_IRUGO,
2018ed4f7c20SHans de Goede show_pwm_auto_point_temp_hyst, NULL, 2, 0),
2019ed4f7c20SHans de Goede SENSOR_ATTR_2(temp2_auto_point4_temp_hyst, S_IRUGO,
2020ed4f7c20SHans de Goede show_pwm_auto_point_temp_hyst, NULL, 3, 0),
202155840142SHans de Goede }, {
202266344aa6SHans de Goede SENSOR_ATTR_2(pwm3_auto_channels_temp, S_IRUGO|S_IWUSR,
202366344aa6SHans de Goede show_pwm_auto_point_channel,
202466344aa6SHans de Goede store_pwm_auto_point_channel, 0, 2),
2025ed4f7c20SHans de Goede SENSOR_ATTR_2(temp3_auto_point1_pwm, S_IRUGO|S_IWUSR,
2026ed4f7c20SHans de Goede show_pwm_auto_point_pwm, store_pwm_auto_point_pwm,
2027ed4f7c20SHans de Goede 0, 1),
2028ed4f7c20SHans de Goede SENSOR_ATTR_2(temp3_auto_point2_pwm, S_IRUGO|S_IWUSR,
2029ed4f7c20SHans de Goede show_pwm_auto_point_pwm, store_pwm_auto_point_pwm,
2030ed4f7c20SHans de Goede 1, 1),
2031ed4f7c20SHans de Goede SENSOR_ATTR_2(temp3_auto_point3_pwm, S_IRUGO|S_IWUSR,
2032ed4f7c20SHans de Goede show_pwm_auto_point_pwm, store_pwm_auto_point_pwm,
2033ed4f7c20SHans de Goede 2, 1),
2034ed4f7c20SHans de Goede SENSOR_ATTR_2(temp3_auto_point4_pwm, S_IRUGO|S_IWUSR,
2035ed4f7c20SHans de Goede show_pwm_auto_point_pwm, store_pwm_auto_point_pwm,
2036ed4f7c20SHans de Goede 3, 1),
2037ed4f7c20SHans de Goede SENSOR_ATTR_2(temp3_auto_point5_pwm, S_IRUGO|S_IWUSR,
2038ed4f7c20SHans de Goede show_pwm_auto_point_pwm, store_pwm_auto_point_pwm,
2039ed4f7c20SHans de Goede 4, 1),
2040ed4f7c20SHans de Goede SENSOR_ATTR_2(temp3_auto_point1_temp, S_IRUGO|S_IWUSR,
2041ed4f7c20SHans de Goede show_pwm_auto_point_temp, store_pwm_auto_point_temp,
2042ed4f7c20SHans de Goede 0, 1),
2043ed4f7c20SHans de Goede SENSOR_ATTR_2(temp3_auto_point2_temp, S_IRUGO|S_IWUSR,
2044ed4f7c20SHans de Goede show_pwm_auto_point_temp, store_pwm_auto_point_temp,
2045ed4f7c20SHans de Goede 1, 1),
2046ed4f7c20SHans de Goede SENSOR_ATTR_2(temp3_auto_point3_temp, S_IRUGO|S_IWUSR,
2047ed4f7c20SHans de Goede show_pwm_auto_point_temp, store_pwm_auto_point_temp,
2048ed4f7c20SHans de Goede 2, 1),
2049ed4f7c20SHans de Goede SENSOR_ATTR_2(temp3_auto_point4_temp, S_IRUGO|S_IWUSR,
2050ed4f7c20SHans de Goede show_pwm_auto_point_temp, store_pwm_auto_point_temp,
2051ed4f7c20SHans de Goede 3, 1),
2052ed4f7c20SHans de Goede SENSOR_ATTR_2(temp3_auto_point1_temp_hyst, S_IRUGO|S_IWUSR,
2053ed4f7c20SHans de Goede show_pwm_auto_point_temp_hyst,
2054ed4f7c20SHans de Goede store_pwm_auto_point_temp_hyst,
2055ed4f7c20SHans de Goede 0, 1),
2056ed4f7c20SHans de Goede SENSOR_ATTR_2(temp3_auto_point2_temp_hyst, S_IRUGO,
2057ed4f7c20SHans de Goede show_pwm_auto_point_temp_hyst, NULL, 1, 1),
2058ed4f7c20SHans de Goede SENSOR_ATTR_2(temp3_auto_point3_temp_hyst, S_IRUGO,
2059ed4f7c20SHans de Goede show_pwm_auto_point_temp_hyst, NULL, 2, 1),
2060ed4f7c20SHans de Goede SENSOR_ATTR_2(temp3_auto_point4_temp_hyst, S_IRUGO,
2061ed4f7c20SHans de Goede show_pwm_auto_point_temp_hyst, NULL, 3, 1),
206255840142SHans de Goede } };
206345fb3669SHans de Goede
206445fb3669SHans de Goede /* Super I/O functions */
superio_inb(int base,int reg)206545fb3669SHans de Goede static inline int superio_inb(int base, int reg)
206645fb3669SHans de Goede {
206745fb3669SHans de Goede outb(reg, base);
206845fb3669SHans de Goede return inb(base + 1);
206945fb3669SHans de Goede }
207045fb3669SHans de Goede
superio_inw(int base,int reg)207145fb3669SHans de Goede static int superio_inw(int base, int reg)
207245fb3669SHans de Goede {
207345fb3669SHans de Goede int val;
2074bd328acdSGiel van Schijndel val = superio_inb(base, reg) << 8;
2075bd328acdSGiel van Schijndel val |= superio_inb(base, reg + 1);
207645fb3669SHans de Goede return val;
207745fb3669SHans de Goede }
207845fb3669SHans de Goede
superio_enter(int base)2079cadb8657SGiel van Schijndel static inline int superio_enter(int base)
208045fb3669SHans de Goede {
2081cadb8657SGiel van Schijndel /* Don't step on other drivers' I/O space by accident */
2082cadb8657SGiel van Schijndel if (!request_muxed_region(base, 2, DRVNAME)) {
208322d3b412SJoe Perches pr_err("I/O address 0x%04x already in use\n", base);
2084cadb8657SGiel van Schijndel return -EBUSY;
2085cadb8657SGiel van Schijndel }
2086cadb8657SGiel van Schijndel
208745fb3669SHans de Goede /* according to the datasheet the key must be send twice! */
208845fb3669SHans de Goede outb(SIO_UNLOCK_KEY, base);
208945fb3669SHans de Goede outb(SIO_UNLOCK_KEY, base);
2090cadb8657SGiel van Schijndel
2091cadb8657SGiel van Schijndel return 0;
209245fb3669SHans de Goede }
209345fb3669SHans de Goede
superio_select(int base,int ld)209445fb3669SHans de Goede static inline void superio_select(int base, int ld)
209545fb3669SHans de Goede {
209645fb3669SHans de Goede outb(SIO_REG_LDSEL, base);
209745fb3669SHans de Goede outb(ld, base + 1);
209845fb3669SHans de Goede }
209945fb3669SHans de Goede
superio_exit(int base)210045fb3669SHans de Goede static inline void superio_exit(int base)
210145fb3669SHans de Goede {
210245fb3669SHans de Goede outb(SIO_LOCK_KEY, base);
2103cadb8657SGiel van Schijndel release_region(base, 2);
210445fb3669SHans de Goede }
210545fb3669SHans de Goede
f71882fg_create_sysfs_files(struct platform_device * pdev,struct sensor_device_attribute_2 * attr,int count)21066c931ae1SBill Pemberton static int f71882fg_create_sysfs_files(struct platform_device *pdev,
2107c13548c5SHans de Goede struct sensor_device_attribute_2 *attr, int count)
2108c13548c5SHans de Goede {
2109c13548c5SHans de Goede int err, i;
2110c13548c5SHans de Goede
2111c13548c5SHans de Goede for (i = 0; i < count; i++) {
2112c13548c5SHans de Goede err = device_create_file(&pdev->dev, &attr[i].dev_attr);
2113c13548c5SHans de Goede if (err)
2114c13548c5SHans de Goede return err;
2115c13548c5SHans de Goede }
2116c13548c5SHans de Goede return 0;
2117c13548c5SHans de Goede }
211845fb3669SHans de Goede
f71882fg_remove_sysfs_files(struct platform_device * pdev,struct sensor_device_attribute_2 * attr,int count)2119fc16c56eSHans de Goede static void f71882fg_remove_sysfs_files(struct platform_device *pdev,
2120fc16c56eSHans de Goede struct sensor_device_attribute_2 *attr, int count)
2121fc16c56eSHans de Goede {
2122fc16c56eSHans de Goede int i;
2123fc16c56eSHans de Goede
2124fc16c56eSHans de Goede for (i = 0; i < count; i++)
2125fc16c56eSHans de Goede device_remove_file(&pdev->dev, &attr[i].dev_attr);
2126fc16c56eSHans de Goede }
2127fc16c56eSHans de Goede
f71882fg_create_fan_sysfs_files(struct platform_device * pdev,int idx)21286c931ae1SBill Pemberton static int f71882fg_create_fan_sysfs_files(
21296543439fSHans de Goede struct platform_device *pdev, int idx)
21309af0794cSHans de Goede {
21319af0794cSHans de Goede struct f71882fg_data *data = platform_get_drvdata(pdev);
21329af0794cSHans de Goede int err;
21339af0794cSHans de Goede
21346543439fSHans de Goede /* Sanity check the pwm setting */
21356543439fSHans de Goede err = 0;
21366543439fSHans de Goede switch (data->type) {
21376543439fSHans de Goede case f71858fg:
21386543439fSHans de Goede if (((data->pwm_enable >> (idx * 2)) & 3) == 3)
21396543439fSHans de Goede err = 1;
21406543439fSHans de Goede break;
21416543439fSHans de Goede case f71862fg:
21426543439fSHans de Goede if (((data->pwm_enable >> (idx * 2)) & 1) != 1)
21436543439fSHans de Goede err = 1;
21446543439fSHans de Goede break;
21456543439fSHans de Goede case f8000:
21466543439fSHans de Goede if (idx == 2)
21476543439fSHans de Goede err = data->pwm_enable & 0x20;
21486543439fSHans de Goede break;
21496543439fSHans de Goede default:
21506543439fSHans de Goede break;
21516543439fSHans de Goede }
21526543439fSHans de Goede if (err) {
21536543439fSHans de Goede dev_err(&pdev->dev,
21546543439fSHans de Goede "Invalid (reserved) pwm settings: 0x%02x, "
21556543439fSHans de Goede "skipping fan %d\n",
21566543439fSHans de Goede (data->pwm_enable >> (idx * 2)) & 3, idx + 1);
21576543439fSHans de Goede return 0; /* This is a non fatal condition */
21586543439fSHans de Goede }
21596543439fSHans de Goede
21609af0794cSHans de Goede err = f71882fg_create_sysfs_files(pdev, &fxxxx_fan_attr[idx][0],
21619af0794cSHans de Goede ARRAY_SIZE(fxxxx_fan_attr[0]));
21629af0794cSHans de Goede if (err)
21639af0794cSHans de Goede return err;
21649af0794cSHans de Goede
21659af0794cSHans de Goede if (f71882fg_fan_has_beep[data->type]) {
21669af0794cSHans de Goede err = f71882fg_create_sysfs_files(pdev,
21679af0794cSHans de Goede &fxxxx_fan_beep_attr[idx],
21689af0794cSHans de Goede 1);
21699af0794cSHans de Goede if (err)
21709af0794cSHans de Goede return err;
21719af0794cSHans de Goede }
21729af0794cSHans de Goede
21736543439fSHans de Goede dev_info(&pdev->dev, "Fan: %d is in %s mode\n", idx + 1,
21746543439fSHans de Goede (data->pwm_enable & (1 << (2 * idx))) ? "duty-cycle" : "RPM");
21756543439fSHans de Goede
21766543439fSHans de Goede /* Check for unsupported auto pwm settings */
21776543439fSHans de Goede switch (data->type) {
21786543439fSHans de Goede case f71808e:
21796543439fSHans de Goede case f71808a:
21806543439fSHans de Goede case f71869:
21816543439fSHans de Goede case f71869a:
21826543439fSHans de Goede case f71889fg:
21836543439fSHans de Goede case f71889ed:
21846543439fSHans de Goede case f71889a:
21856543439fSHans de Goede data->pwm_auto_point_mapping[idx] =
21866543439fSHans de Goede f71882fg_read8(data, F71882FG_REG_POINT_MAPPING(idx));
21876543439fSHans de Goede if ((data->pwm_auto_point_mapping[idx] & 0x80) ||
21886543439fSHans de Goede (data->pwm_auto_point_mapping[idx] & 3) == 0) {
21896543439fSHans de Goede dev_warn(&pdev->dev,
21906543439fSHans de Goede "Auto pwm controlled by raw digital "
21916543439fSHans de Goede "data, disabling pwm auto_point "
21926543439fSHans de Goede "sysfs attributes for fan %d\n", idx + 1);
21936543439fSHans de Goede return 0; /* This is a non fatal condition */
21946543439fSHans de Goede }
21956543439fSHans de Goede break;
21966543439fSHans de Goede default:
21976543439fSHans de Goede break;
21986543439fSHans de Goede }
21999af0794cSHans de Goede
22009af0794cSHans de Goede switch (data->type) {
22019af0794cSHans de Goede case f71862fg:
22029af0794cSHans de Goede err = f71882fg_create_sysfs_files(pdev,
22039af0794cSHans de Goede &f71862fg_auto_pwm_attr[idx][0],
22049af0794cSHans de Goede ARRAY_SIZE(f71862fg_auto_pwm_attr[0]));
22059af0794cSHans de Goede break;
22069af0794cSHans de Goede case f71808e:
22079af0794cSHans de Goede case f71869:
22089af0794cSHans de Goede err = f71882fg_create_sysfs_files(pdev,
22099af0794cSHans de Goede &f71869_auto_pwm_attr[idx][0],
22109af0794cSHans de Goede ARRAY_SIZE(f71869_auto_pwm_attr[0]));
22119af0794cSHans de Goede break;
22129af0794cSHans de Goede case f8000:
22139af0794cSHans de Goede err = f71882fg_create_sysfs_files(pdev,
22149af0794cSHans de Goede &f8000_auto_pwm_attr[idx][0],
22159af0794cSHans de Goede ARRAY_SIZE(f8000_auto_pwm_attr[0]));
22169af0794cSHans de Goede break;
22179af0794cSHans de Goede default:
22189af0794cSHans de Goede err = f71882fg_create_sysfs_files(pdev,
22199af0794cSHans de Goede &fxxxx_auto_pwm_attr[idx][0],
22209af0794cSHans de Goede ARRAY_SIZE(fxxxx_auto_pwm_attr[0]));
22219af0794cSHans de Goede }
22229af0794cSHans de Goede
22239af0794cSHans de Goede return err;
22249af0794cSHans de Goede }
22259af0794cSHans de Goede
f71882fg_remove(struct platform_device * pdev)2226df9ec2daSUwe Kleine-König static int f71882fg_remove(struct platform_device *pdev)
2227df9ec2daSUwe Kleine-König {
2228df9ec2daSUwe Kleine-König struct f71882fg_data *data = platform_get_drvdata(pdev);
2229df9ec2daSUwe Kleine-König int nr_fans = f71882fg_nr_fans[data->type];
2230df9ec2daSUwe Kleine-König int nr_temps = f71882fg_nr_temps[data->type];
2231df9ec2daSUwe Kleine-König int i;
2232df9ec2daSUwe Kleine-König u8 start_reg = f71882fg_read8(data, F71882FG_REG_START);
2233df9ec2daSUwe Kleine-König
2234df9ec2daSUwe Kleine-König if (data->hwmon_dev)
2235df9ec2daSUwe Kleine-König hwmon_device_unregister(data->hwmon_dev);
2236df9ec2daSUwe Kleine-König
2237df9ec2daSUwe Kleine-König device_remove_file(&pdev->dev, &dev_attr_name);
2238df9ec2daSUwe Kleine-König
2239df9ec2daSUwe Kleine-König if (start_reg & 0x01) {
2240df9ec2daSUwe Kleine-König switch (data->type) {
2241df9ec2daSUwe Kleine-König case f71858fg:
2242df9ec2daSUwe Kleine-König if (data->temp_config & 0x10)
2243df9ec2daSUwe Kleine-König f71882fg_remove_sysfs_files(pdev,
2244df9ec2daSUwe Kleine-König f8000_temp_attr,
2245df9ec2daSUwe Kleine-König ARRAY_SIZE(f8000_temp_attr));
2246df9ec2daSUwe Kleine-König else
2247df9ec2daSUwe Kleine-König f71882fg_remove_sysfs_files(pdev,
2248df9ec2daSUwe Kleine-König f71858fg_temp_attr,
2249df9ec2daSUwe Kleine-König ARRAY_SIZE(f71858fg_temp_attr));
2250df9ec2daSUwe Kleine-König break;
2251df9ec2daSUwe Kleine-König case f8000:
2252df9ec2daSUwe Kleine-König f71882fg_remove_sysfs_files(pdev,
2253df9ec2daSUwe Kleine-König f8000_temp_attr,
2254df9ec2daSUwe Kleine-König ARRAY_SIZE(f8000_temp_attr));
2255df9ec2daSUwe Kleine-König break;
2256df9ec2daSUwe Kleine-König case f81866a:
2257df9ec2daSUwe Kleine-König f71882fg_remove_sysfs_files(pdev,
2258df9ec2daSUwe Kleine-König f71858fg_temp_attr,
2259df9ec2daSUwe Kleine-König ARRAY_SIZE(f71858fg_temp_attr));
2260df9ec2daSUwe Kleine-König break;
2261df9ec2daSUwe Kleine-König default:
2262df9ec2daSUwe Kleine-König f71882fg_remove_sysfs_files(pdev,
2263df9ec2daSUwe Kleine-König &fxxxx_temp_attr[0][0],
2264df9ec2daSUwe Kleine-König ARRAY_SIZE(fxxxx_temp_attr[0]) * nr_temps);
2265df9ec2daSUwe Kleine-König }
2266df9ec2daSUwe Kleine-König if (f71882fg_temp_has_beep[data->type]) {
2267df9ec2daSUwe Kleine-König if (data->type == f81866a)
2268df9ec2daSUwe Kleine-König f71882fg_remove_sysfs_files(pdev,
2269df9ec2daSUwe Kleine-König &f81866_temp_beep_attr[0][0],
2270df9ec2daSUwe Kleine-König ARRAY_SIZE(f81866_temp_beep_attr[0])
2271df9ec2daSUwe Kleine-König * nr_temps);
2272df9ec2daSUwe Kleine-König else
2273df9ec2daSUwe Kleine-König f71882fg_remove_sysfs_files(pdev,
2274df9ec2daSUwe Kleine-König &fxxxx_temp_beep_attr[0][0],
2275df9ec2daSUwe Kleine-König ARRAY_SIZE(fxxxx_temp_beep_attr[0])
2276df9ec2daSUwe Kleine-König * nr_temps);
2277df9ec2daSUwe Kleine-König }
2278df9ec2daSUwe Kleine-König
2279df9ec2daSUwe Kleine-König for (i = 0; i < F71882FG_MAX_INS; i++) {
2280df9ec2daSUwe Kleine-König if (f71882fg_has_in[data->type][i]) {
2281df9ec2daSUwe Kleine-König device_remove_file(&pdev->dev,
2282df9ec2daSUwe Kleine-König &fxxxx_in_attr[i].dev_attr);
2283df9ec2daSUwe Kleine-König }
2284df9ec2daSUwe Kleine-König }
2285df9ec2daSUwe Kleine-König if (f71882fg_has_in1_alarm[data->type]) {
2286df9ec2daSUwe Kleine-König f71882fg_remove_sysfs_files(pdev,
2287df9ec2daSUwe Kleine-König fxxxx_in1_alarm_attr,
2288df9ec2daSUwe Kleine-König ARRAY_SIZE(fxxxx_in1_alarm_attr));
2289df9ec2daSUwe Kleine-König }
2290df9ec2daSUwe Kleine-König }
2291df9ec2daSUwe Kleine-König
2292df9ec2daSUwe Kleine-König if (start_reg & 0x02) {
2293df9ec2daSUwe Kleine-König f71882fg_remove_sysfs_files(pdev, &fxxxx_fan_attr[0][0],
2294df9ec2daSUwe Kleine-König ARRAY_SIZE(fxxxx_fan_attr[0]) * nr_fans);
2295df9ec2daSUwe Kleine-König
2296df9ec2daSUwe Kleine-König if (f71882fg_fan_has_beep[data->type]) {
2297df9ec2daSUwe Kleine-König f71882fg_remove_sysfs_files(pdev,
2298df9ec2daSUwe Kleine-König fxxxx_fan_beep_attr, nr_fans);
2299df9ec2daSUwe Kleine-König }
2300df9ec2daSUwe Kleine-König
2301df9ec2daSUwe Kleine-König switch (data->type) {
2302df9ec2daSUwe Kleine-König case f71808a:
2303df9ec2daSUwe Kleine-König f71882fg_remove_sysfs_files(pdev,
2304df9ec2daSUwe Kleine-König &fxxxx_auto_pwm_attr[0][0],
2305df9ec2daSUwe Kleine-König ARRAY_SIZE(fxxxx_auto_pwm_attr[0]) * nr_fans);
2306df9ec2daSUwe Kleine-König f71882fg_remove_sysfs_files(pdev,
2307df9ec2daSUwe Kleine-König f71808a_fan3_attr,
2308df9ec2daSUwe Kleine-König ARRAY_SIZE(f71808a_fan3_attr));
2309df9ec2daSUwe Kleine-König break;
2310df9ec2daSUwe Kleine-König case f71862fg:
2311df9ec2daSUwe Kleine-König f71882fg_remove_sysfs_files(pdev,
2312df9ec2daSUwe Kleine-König &f71862fg_auto_pwm_attr[0][0],
2313df9ec2daSUwe Kleine-König ARRAY_SIZE(f71862fg_auto_pwm_attr[0]) *
2314df9ec2daSUwe Kleine-König nr_fans);
2315df9ec2daSUwe Kleine-König break;
2316df9ec2daSUwe Kleine-König case f71808e:
2317df9ec2daSUwe Kleine-König case f71869:
2318df9ec2daSUwe Kleine-König f71882fg_remove_sysfs_files(pdev,
2319df9ec2daSUwe Kleine-König &f71869_auto_pwm_attr[0][0],
2320df9ec2daSUwe Kleine-König ARRAY_SIZE(f71869_auto_pwm_attr[0]) * nr_fans);
2321df9ec2daSUwe Kleine-König break;
2322df9ec2daSUwe Kleine-König case f8000:
2323df9ec2daSUwe Kleine-König f71882fg_remove_sysfs_files(pdev,
2324df9ec2daSUwe Kleine-König f8000_fan_attr,
2325df9ec2daSUwe Kleine-König ARRAY_SIZE(f8000_fan_attr));
2326df9ec2daSUwe Kleine-König f71882fg_remove_sysfs_files(pdev,
2327df9ec2daSUwe Kleine-König &f8000_auto_pwm_attr[0][0],
2328df9ec2daSUwe Kleine-König ARRAY_SIZE(f8000_auto_pwm_attr[0]) * nr_fans);
2329df9ec2daSUwe Kleine-König break;
2330df9ec2daSUwe Kleine-König default:
2331df9ec2daSUwe Kleine-König f71882fg_remove_sysfs_files(pdev,
2332df9ec2daSUwe Kleine-König &fxxxx_auto_pwm_attr[0][0],
2333df9ec2daSUwe Kleine-König ARRAY_SIZE(fxxxx_auto_pwm_attr[0]) * nr_fans);
2334df9ec2daSUwe Kleine-König }
2335df9ec2daSUwe Kleine-König }
2336df9ec2daSUwe Kleine-König return 0;
2337df9ec2daSUwe Kleine-König }
2338df9ec2daSUwe Kleine-König
f71882fg_probe(struct platform_device * pdev)23396c931ae1SBill Pemberton static int f71882fg_probe(struct platform_device *pdev)
234045fb3669SHans de Goede {
234145fb3669SHans de Goede struct f71882fg_data *data;
2342a8b3a3a5SJingoo Han struct f71882fg_sio_data *sio_data = dev_get_platdata(&pdev->dev);
2343f27def07SJean Delvare int nr_fans = f71882fg_nr_fans[sio_data->type];
2344f27def07SJean Delvare int nr_temps = f71882fg_nr_temps[sio_data->type];
2345f27def07SJean Delvare int err, i;
2346dcd956fcSPeter Hung int size;
234798f7ba19SHans de Goede u8 start_reg, reg;
234845fb3669SHans de Goede
234933cd66e3SGuenter Roeck data = devm_kzalloc(&pdev->dev, sizeof(struct f71882fg_data),
235033cd66e3SGuenter Roeck GFP_KERNEL);
2351c13548c5SHans de Goede if (!data)
235245fb3669SHans de Goede return -ENOMEM;
235345fb3669SHans de Goede
235445fb3669SHans de Goede data->addr = platform_get_resource(pdev, IORESOURCE_IO, 0)->start;
2355498be968SHans de Goede data->type = sio_data->type;
235609475d32SHans de Goede data->temp_start =
2357dcd956fcSPeter Hung (data->type == f71858fg || data->type == f8000 ||
2358dcd956fcSPeter Hung data->type == f81866a) ? 0 : 1;
235945fb3669SHans de Goede mutex_init(&data->update_lock);
236045fb3669SHans de Goede platform_set_drvdata(pdev, data);
236145fb3669SHans de Goede
23623cc74758SHans de Goede start_reg = f71882fg_read8(data, F71882FG_REG_START);
236312d66e84SHans de Goede if (start_reg & 0x04) {
236412d66e84SHans de Goede dev_warn(&pdev->dev, "Hardware monitor is powered down\n");
236533cd66e3SGuenter Roeck return -ENODEV;
236612d66e84SHans de Goede }
23673cc74758SHans de Goede if (!(start_reg & 0x03)) {
23683cc74758SHans de Goede dev_warn(&pdev->dev, "Hardware monitoring not activated\n");
236933cd66e3SGuenter Roeck return -ENODEV;
23703cc74758SHans de Goede }
23713cc74758SHans de Goede
237245fb3669SHans de Goede /* Register sysfs interface files */
2373c13548c5SHans de Goede err = device_create_file(&pdev->dev, &dev_attr_name);
237445fb3669SHans de Goede if (err)
237545fb3669SHans de Goede goto exit_unregister_sysfs;
237645fb3669SHans de Goede
237745fb3669SHans de Goede if (start_reg & 0x01) {
2378ed4f7c20SHans de Goede switch (data->type) {
237909475d32SHans de Goede case f71858fg:
238009475d32SHans de Goede data->temp_config =
238109475d32SHans de Goede f71882fg_read8(data, F71882FG_REG_TEMP_CONFIG);
238209475d32SHans de Goede if (data->temp_config & 0x10)
238320eaf724SGuenter Roeck /*
238420eaf724SGuenter Roeck * The f71858fg temperature alarms behave as
238520eaf724SGuenter Roeck * the f8000 alarms in this mode
238620eaf724SGuenter Roeck */
238709475d32SHans de Goede err = f71882fg_create_sysfs_files(pdev,
23880bae6400SHans de Goede f8000_temp_attr,
23890bae6400SHans de Goede ARRAY_SIZE(f8000_temp_attr));
239009475d32SHans de Goede else
239109475d32SHans de Goede err = f71882fg_create_sysfs_files(pdev,
23920bae6400SHans de Goede f71858fg_temp_attr,
23930bae6400SHans de Goede ARRAY_SIZE(f71858fg_temp_attr));
239409475d32SHans de Goede break;
23950bae6400SHans de Goede case f8000:
23960bae6400SHans de Goede err = f71882fg_create_sysfs_files(pdev,
23970bae6400SHans de Goede f8000_temp_attr,
23980bae6400SHans de Goede ARRAY_SIZE(f8000_temp_attr));
23990bae6400SHans de Goede break;
2400dcd956fcSPeter Hung case f81866a:
2401dcd956fcSPeter Hung err = f71882fg_create_sysfs_files(pdev,
2402dcd956fcSPeter Hung f71858fg_temp_attr,
2403dcd956fcSPeter Hung ARRAY_SIZE(f71858fg_temp_attr));
2404dcd956fcSPeter Hung break;
24050bae6400SHans de Goede default:
24060bae6400SHans de Goede err = f71882fg_create_sysfs_files(pdev,
240760d2b378SHans de Goede &fxxxx_temp_attr[0][0],
240860d2b378SHans de Goede ARRAY_SIZE(fxxxx_temp_attr[0]) * nr_temps);
24090bae6400SHans de Goede }
24100bae6400SHans de Goede if (err)
24110bae6400SHans de Goede goto exit_unregister_sysfs;
24120bae6400SHans de Goede
24134d53811aSHans de Goede if (f71882fg_temp_has_beep[data->type]) {
2414dcd956fcSPeter Hung if (data->type == f81866a) {
2415dcd956fcSPeter Hung size = ARRAY_SIZE(f81866_temp_beep_attr[0]);
2416dcd956fcSPeter Hung err = f71882fg_create_sysfs_files(pdev,
2417dcd956fcSPeter Hung &f81866_temp_beep_attr[0][0],
2418dcd956fcSPeter Hung size * nr_temps);
2419dcd956fcSPeter Hung
2420dcd956fcSPeter Hung } else {
2421dcd956fcSPeter Hung size = ARRAY_SIZE(fxxxx_temp_beep_attr[0]);
242278aa4f72SHans de Goede err = f71882fg_create_sysfs_files(pdev,
242378aa4f72SHans de Goede &fxxxx_temp_beep_attr[0][0],
2424dcd956fcSPeter Hung size * nr_temps);
2425dcd956fcSPeter Hung }
242678aa4f72SHans de Goede if (err)
242778aa4f72SHans de Goede goto exit_unregister_sysfs;
242878aa4f72SHans de Goede }
242978aa4f72SHans de Goede
24300bae6400SHans de Goede for (i = 0; i < F71882FG_MAX_INS; i++) {
24310bae6400SHans de Goede if (f71882fg_has_in[data->type][i]) {
24320bae6400SHans de Goede err = device_create_file(&pdev->dev,
24330bae6400SHans de Goede &fxxxx_in_attr[i].dev_attr);
24340bae6400SHans de Goede if (err)
24350bae6400SHans de Goede goto exit_unregister_sysfs;
24360bae6400SHans de Goede }
24370bae6400SHans de Goede }
24380bae6400SHans de Goede if (f71882fg_has_in1_alarm[data->type]) {
2439498be968SHans de Goede err = f71882fg_create_sysfs_files(pdev,
244066344aa6SHans de Goede fxxxx_in1_alarm_attr,
244166344aa6SHans de Goede ARRAY_SIZE(fxxxx_in1_alarm_attr));
244245fb3669SHans de Goede if (err)
244345fb3669SHans de Goede goto exit_unregister_sysfs;
244445fb3669SHans de Goede }
2445498be968SHans de Goede }
244645fb3669SHans de Goede
244745fb3669SHans de Goede if (start_reg & 0x02) {
244898f7ba19SHans de Goede switch (data->type) {
2449e5e713cbSHans de Goede case f71808e:
2450629c58baSHans de Goede case f71808a:
2451c11bb993SHans de Goede case f71869:
24525da556e3SHans de Goede case f71869a:
2453e5e713cbSHans de Goede /* These always have signed auto point temps */
2454c11bb993SHans de Goede data->auto_point_temp_signed = 1;
2455df561f66SGustavo A. R. Silva fallthrough; /* to select correct fan/pwm reg bank! */
245698f7ba19SHans de Goede case f71889fg:
24573cad4022SHans de Goede case f71889ed:
2458a66c1088SHans de Goede case f71889a:
245998f7ba19SHans de Goede reg = f71882fg_read8(data, F71882FG_REG_FAN_FAULT_T);
246098f7ba19SHans de Goede if (reg & F71882FG_FAN_NEG_TEMP_EN)
246198f7ba19SHans de Goede data->auto_point_temp_signed = 1;
24623cad4022SHans de Goede /* Ensure banked pwm registers point to right bank */
24633cad4022SHans de Goede reg &= ~F71882FG_FAN_PROG_SEL;
24643cad4022SHans de Goede f71882fg_write8(data, F71882FG_REG_FAN_FAULT_T, reg);
246598f7ba19SHans de Goede break;
246698f7ba19SHans de Goede default:
246798f7ba19SHans de Goede break;
246898f7ba19SHans de Goede }
246998f7ba19SHans de Goede
2470996cadb2SHans de Goede data->pwm_enable =
2471996cadb2SHans de Goede f71882fg_read8(data, F71882FG_REG_PWM_ENABLE);
2472996cadb2SHans de Goede
2473e48a7f1aSHans de Goede for (i = 0; i < nr_fans; i++) {
24746543439fSHans de Goede err = f71882fg_create_fan_sysfs_files(pdev, i);
24759af0794cSHans de Goede if (err)
24769af0794cSHans de Goede goto exit_unregister_sysfs;
24779af0794cSHans de Goede }
24789af0794cSHans de Goede
24799af0794cSHans de Goede /* Some types have 1 extra fan with limited functionality */
2480e48a7f1aSHans de Goede switch (data->type) {
2481629c58baSHans de Goede case f71808a:
2482629c58baSHans de Goede err = f71882fg_create_sysfs_files(pdev,
2483629c58baSHans de Goede f71808a_fan3_attr,
2484629c58baSHans de Goede ARRAY_SIZE(f71808a_fan3_attr));
2485629c58baSHans de Goede break;
2486ed4f7c20SHans de Goede case f8000:
2487ed4f7c20SHans de Goede err = f71882fg_create_sysfs_files(pdev,
2488ed4f7c20SHans de Goede f8000_fan_attr,
2489ed4f7c20SHans de Goede ARRAY_SIZE(f8000_fan_attr));
2490ed4f7c20SHans de Goede break;
2491e48a7f1aSHans de Goede default:
24929af0794cSHans de Goede break;
2493498be968SHans de Goede }
249445fb3669SHans de Goede if (err)
249545fb3669SHans de Goede goto exit_unregister_sysfs;
249645fb3669SHans de Goede }
249745fb3669SHans de Goede
24981beeffe4STony Jones data->hwmon_dev = hwmon_device_register(&pdev->dev);
24991beeffe4STony Jones if (IS_ERR(data->hwmon_dev)) {
25001beeffe4STony Jones err = PTR_ERR(data->hwmon_dev);
2501c13548c5SHans de Goede data->hwmon_dev = NULL;
250245fb3669SHans de Goede goto exit_unregister_sysfs;
250345fb3669SHans de Goede }
250445fb3669SHans de Goede
250545fb3669SHans de Goede return 0;
250645fb3669SHans de Goede
250745fb3669SHans de Goede exit_unregister_sysfs:
2508c13548c5SHans de Goede f71882fg_remove(pdev); /* Will unregister the sysfs files for us */
25093cc74758SHans de Goede return err; /* f71882fg_remove() also frees our data */
251045fb3669SHans de Goede }
251145fb3669SHans de Goede
f71882fg_find(int sioaddr,struct f71882fg_sio_data * sio_data)25120038389aSGuenter Roeck static int __init f71882fg_find(int sioaddr, struct f71882fg_sio_data *sio_data)
251345fb3669SHans de Goede {
251445fb3669SHans de Goede u16 devid;
25150038389aSGuenter Roeck unsigned short address;
2516cadb8657SGiel van Schijndel int err = superio_enter(sioaddr);
2517cadb8657SGiel van Schijndel if (err)
2518cadb8657SGiel van Schijndel return err;
251945fb3669SHans de Goede
252045fb3669SHans de Goede devid = superio_inw(sioaddr, SIO_REG_MANID);
252145fb3669SHans de Goede if (devid != SIO_FINTEK_ID) {
252222d3b412SJoe Perches pr_debug("Not a Fintek device\n");
2523cadb8657SGiel van Schijndel err = -ENODEV;
252445fb3669SHans de Goede goto exit;
252545fb3669SHans de Goede }
252645fb3669SHans de Goede
252767b671bcSJean Delvare devid = force_id ? force_id : superio_inw(sioaddr, SIO_REG_DEVID);
2528498be968SHans de Goede switch (devid) {
2529e5e713cbSHans de Goede case SIO_F71808E_ID:
2530e5e713cbSHans de Goede sio_data->type = f71808e;
2531e5e713cbSHans de Goede break;
2532629c58baSHans de Goede case SIO_F71808A_ID:
2533629c58baSHans de Goede sio_data->type = f71808a;
2534629c58baSHans de Goede break;
253509475d32SHans de Goede case SIO_F71858_ID:
2536739743ecSAleksander Mazur case SIO_F71858AD_ID:
253709475d32SHans de Goede sio_data->type = f71858fg;
253809475d32SHans de Goede break;
2539498be968SHans de Goede case SIO_F71862_ID:
2540498be968SHans de Goede sio_data->type = f71862fg;
2541498be968SHans de Goede break;
25422725fe2bSPeter Hung case SIO_F71868_ID:
25432725fe2bSPeter Hung sio_data->type = f71868a;
25442725fe2bSPeter Hung break;
2545c11bb993SHans de Goede case SIO_F71869_ID:
2546c11bb993SHans de Goede sio_data->type = f71869;
2547c11bb993SHans de Goede break;
25485da556e3SHans de Goede case SIO_F71869A_ID:
25495da556e3SHans de Goede sio_data->type = f71869a;
25505da556e3SHans de Goede break;
2551498be968SHans de Goede case SIO_F71882_ID:
2552498be968SHans de Goede sio_data->type = f71882fg;
2553498be968SHans de Goede break;
25547669896fSHans de Goede case SIO_F71889_ID:
25557669896fSHans de Goede sio_data->type = f71889fg;
25567669896fSHans de Goede break;
25573cad4022SHans de Goede case SIO_F71889E_ID:
25583cad4022SHans de Goede sio_data->type = f71889ed;
25593cad4022SHans de Goede break;
2560a66c1088SHans de Goede case SIO_F71889A_ID:
2561a66c1088SHans de Goede sio_data->type = f71889a;
2562a66c1088SHans de Goede break;
2563ed4f7c20SHans de Goede case SIO_F8000_ID:
2564ed4f7c20SHans de Goede sio_data->type = f8000;
2565ed4f7c20SHans de Goede break;
2566d8363bb5SGeorge Joseph case SIO_F81768D_ID:
2567d8363bb5SGeorge Joseph sio_data->type = f81768d;
2568d8363bb5SGeorge Joseph break;
2569383586b1SJean Delvare case SIO_F81865_ID:
2570383586b1SJean Delvare sio_data->type = f81865f;
2571383586b1SJean Delvare break;
25722725fe2bSPeter Hung case SIO_F81866_ID:
2573df293076SMenghui Wu case SIO_F81966_ID:
25742725fe2bSPeter Hung sio_data->type = f81866a;
25752725fe2bSPeter Hung break;
2576498be968SHans de Goede default:
257722d3b412SJoe Perches pr_info("Unsupported Fintek device: %04x\n",
25787669896fSHans de Goede (unsigned int)devid);
2579cadb8657SGiel van Schijndel err = -ENODEV;
258045fb3669SHans de Goede goto exit;
258145fb3669SHans de Goede }
258245fb3669SHans de Goede
258309475d32SHans de Goede if (sio_data->type == f71858fg)
258409475d32SHans de Goede superio_select(sioaddr, SIO_F71858FG_LD_HWM);
258509475d32SHans de Goede else
258645fb3669SHans de Goede superio_select(sioaddr, SIO_F71882FG_LD_HWM);
258709475d32SHans de Goede
258845fb3669SHans de Goede if (!(superio_inb(sioaddr, SIO_REG_ENABLE) & 0x01)) {
258922d3b412SJoe Perches pr_warn("Device not activated\n");
2590cadb8657SGiel van Schijndel err = -ENODEV;
259145fb3669SHans de Goede goto exit;
259245fb3669SHans de Goede }
259345fb3669SHans de Goede
25940038389aSGuenter Roeck address = superio_inw(sioaddr, SIO_REG_ADDR);
25950038389aSGuenter Roeck if (address == 0) {
259622d3b412SJoe Perches pr_warn("Base address not set\n");
2597cadb8657SGiel van Schijndel err = -ENODEV;
259845fb3669SHans de Goede goto exit;
259945fb3669SHans de Goede }
26000038389aSGuenter Roeck address &= ~(REGION_LENGTH - 1); /* Ignore 3 LSB */
260145fb3669SHans de Goede
26020038389aSGuenter Roeck err = address;
260322d3b412SJoe Perches pr_info("Found %s chip at %#x, revision %d\n",
26040038389aSGuenter Roeck f71882fg_names[sio_data->type], (unsigned int)address,
260545fb3669SHans de Goede (int)superio_inb(sioaddr, SIO_REG_DEVREV));
260645fb3669SHans de Goede exit:
260745fb3669SHans de Goede superio_exit(sioaddr);
260845fb3669SHans de Goede return err;
260945fb3669SHans de Goede }
261045fb3669SHans de Goede
f71882fg_device_add(int address,const struct f71882fg_sio_data * sio_data)26110038389aSGuenter Roeck static int __init f71882fg_device_add(int address,
2612498be968SHans de Goede const struct f71882fg_sio_data *sio_data)
261345fb3669SHans de Goede {
261445fb3669SHans de Goede struct resource res = {
261545fb3669SHans de Goede .start = address,
261645fb3669SHans de Goede .end = address + REGION_LENGTH - 1,
261745fb3669SHans de Goede .flags = IORESOURCE_IO,
261845fb3669SHans de Goede };
261945fb3669SHans de Goede int err;
262045fb3669SHans de Goede
262145fb3669SHans de Goede f71882fg_pdev = platform_device_alloc(DRVNAME, address);
262245fb3669SHans de Goede if (!f71882fg_pdev)
262345fb3669SHans de Goede return -ENOMEM;
262445fb3669SHans de Goede
262545fb3669SHans de Goede res.name = f71882fg_pdev->name;
2626b9acb64aSJean Delvare err = acpi_check_resource_conflict(&res);
2627b9acb64aSJean Delvare if (err)
262818632f84SHans de Goede goto exit_device_put;
2629b9acb64aSJean Delvare
263045fb3669SHans de Goede err = platform_device_add_resources(f71882fg_pdev, &res, 1);
263145fb3669SHans de Goede if (err) {
263222d3b412SJoe Perches pr_err("Device resource addition failed\n");
263345fb3669SHans de Goede goto exit_device_put;
263445fb3669SHans de Goede }
263545fb3669SHans de Goede
2636498be968SHans de Goede err = platform_device_add_data(f71882fg_pdev, sio_data,
2637498be968SHans de Goede sizeof(struct f71882fg_sio_data));
2638498be968SHans de Goede if (err) {
263922d3b412SJoe Perches pr_err("Platform data allocation failed\n");
2640498be968SHans de Goede goto exit_device_put;
2641498be968SHans de Goede }
2642498be968SHans de Goede
264345fb3669SHans de Goede err = platform_device_add(f71882fg_pdev);
264445fb3669SHans de Goede if (err) {
264522d3b412SJoe Perches pr_err("Device addition failed\n");
264645fb3669SHans de Goede goto exit_device_put;
264745fb3669SHans de Goede }
264845fb3669SHans de Goede
264945fb3669SHans de Goede return 0;
265045fb3669SHans de Goede
265145fb3669SHans de Goede exit_device_put:
265245fb3669SHans de Goede platform_device_put(f71882fg_pdev);
265345fb3669SHans de Goede
265445fb3669SHans de Goede return err;
265545fb3669SHans de Goede }
265645fb3669SHans de Goede
2657df9ec2daSUwe Kleine-König static struct platform_driver f71882fg_driver = {
2658df9ec2daSUwe Kleine-König .driver = {
2659df9ec2daSUwe Kleine-König .name = DRVNAME,
2660df9ec2daSUwe Kleine-König },
2661df9ec2daSUwe Kleine-König .probe = f71882fg_probe,
2662df9ec2daSUwe Kleine-König .remove = f71882fg_remove,
2663df9ec2daSUwe Kleine-König };
2664df9ec2daSUwe Kleine-König
f71882fg_init(void)266545fb3669SHans de Goede static int __init f71882fg_init(void)
266645fb3669SHans de Goede {
26670038389aSGuenter Roeck int err;
26680038389aSGuenter Roeck int address;
2669498be968SHans de Goede struct f71882fg_sio_data sio_data;
267045fb3669SHans de Goede
2671498be968SHans de Goede memset(&sio_data, 0, sizeof(sio_data));
2672498be968SHans de Goede
26730038389aSGuenter Roeck address = f71882fg_find(0x2e, &sio_data);
26740038389aSGuenter Roeck if (address < 0)
26750038389aSGuenter Roeck address = f71882fg_find(0x4e, &sio_data);
26760038389aSGuenter Roeck if (address < 0)
26770038389aSGuenter Roeck return address;
267845fb3669SHans de Goede
2679c13548c5SHans de Goede err = platform_driver_register(&f71882fg_driver);
2680c13548c5SHans de Goede if (err)
26810038389aSGuenter Roeck return err;
268245fb3669SHans de Goede
2683498be968SHans de Goede err = f71882fg_device_add(address, &sio_data);
2684c13548c5SHans de Goede if (err)
268545fb3669SHans de Goede goto exit_driver;
268645fb3669SHans de Goede
268745fb3669SHans de Goede return 0;
268845fb3669SHans de Goede
268945fb3669SHans de Goede exit_driver:
269045fb3669SHans de Goede platform_driver_unregister(&f71882fg_driver);
269145fb3669SHans de Goede return err;
269245fb3669SHans de Goede }
269345fb3669SHans de Goede
f71882fg_exit(void)269445fb3669SHans de Goede static void __exit f71882fg_exit(void)
269545fb3669SHans de Goede {
269645fb3669SHans de Goede platform_device_unregister(f71882fg_pdev);
269745fb3669SHans de Goede platform_driver_unregister(&f71882fg_driver);
269845fb3669SHans de Goede }
269945fb3669SHans de Goede
270045fb3669SHans de Goede MODULE_DESCRIPTION("F71882FG Hardware Monitoring Driver");
27017958e3b4SHans de Goede MODULE_AUTHOR("Hans Edgington, Hans de Goede <hdegoede@redhat.com>");
270245fb3669SHans de Goede MODULE_LICENSE("GPL");
270345fb3669SHans de Goede
270445fb3669SHans de Goede module_init(f71882fg_init);
270545fb3669SHans de Goede module_exit(f71882fg_exit);
2706