xref: /openbmc/linux/drivers/hwmon/w83791d.c (revision 2612e3bbc0386368a850140a6c9b990cd496a5ec)
174ba9207SThomas Gleixner // SPDX-License-Identifier: GPL-2.0-or-later
29873964dSCharles Spirakis /*
3ec1c3194SGuenter Roeck  * w83791d.c - Part of lm_sensors, Linux kernel modules for hardware
4ec1c3194SGuenter Roeck  *	       monitoring
5ec1c3194SGuenter Roeck  *
6ec1c3194SGuenter Roeck  * Copyright (C) 2006-2007 Charles Spirakis <bezaur@gmail.com>
79873964dSCharles Spirakis  */
89873964dSCharles Spirakis 
99873964dSCharles Spirakis /*
10ec1c3194SGuenter Roeck  * Supports following chips:
11ec1c3194SGuenter Roeck  *
12ec1c3194SGuenter Roeck  * Chip		#vin	#fanin	#pwm	#temp	wchipid	vendid	i2c	ISA
13ec1c3194SGuenter Roeck  * w83791d	10	5	5	3	0x71	0x5ca3	yes	no
14ec1c3194SGuenter Roeck  *
15ec1c3194SGuenter Roeck  * The w83791d chip appears to be part way between the 83781d and the
16ec1c3194SGuenter Roeck  * 83792d. Thus, this file is derived from both the w83792d.c and
17ec1c3194SGuenter Roeck  * w83781d.c files.
18ec1c3194SGuenter Roeck  *
19ec1c3194SGuenter Roeck  * The w83791g chip is the same as the w83791d but lead-free.
209873964dSCharles Spirakis  */
219873964dSCharles Spirakis 
229873964dSCharles Spirakis #include <linux/module.h>
239873964dSCharles Spirakis #include <linux/init.h>
249873964dSCharles Spirakis #include <linux/slab.h>
259873964dSCharles Spirakis #include <linux/i2c.h>
269873964dSCharles Spirakis #include <linux/hwmon.h>
279873964dSCharles Spirakis #include <linux/hwmon-vid.h>
289873964dSCharles Spirakis #include <linux/hwmon-sysfs.h>
299873964dSCharles Spirakis #include <linux/err.h>
309873964dSCharles Spirakis #include <linux/mutex.h>
31dcd8f392SJean Delvare #include <linux/jiffies.h>
329873964dSCharles Spirakis 
339873964dSCharles Spirakis #define NUMBER_OF_VIN		10
349873964dSCharles Spirakis #define NUMBER_OF_FANIN		5
359873964dSCharles Spirakis #define NUMBER_OF_TEMPIN	3
366495ce18SMarc Hulsman #define NUMBER_OF_PWM		5
379873964dSCharles Spirakis 
389873964dSCharles Spirakis /* Addresses to scan */
3925e9c86dSMark M. Hoffman static const unsigned short normal_i2c[] = { 0x2c, 0x2d, 0x2e, 0x2f,
4025e9c86dSMark M. Hoffman 						I2C_CLIENT_END };
419873964dSCharles Spirakis 
429873964dSCharles Spirakis /* Insmod parameters */
433aed198cSJean Delvare 
443aed198cSJean Delvare static unsigned short force_subclients[4];
453aed198cSJean Delvare module_param_array(force_subclients, short, NULL, 0);
46b55f3757SGuenter Roeck MODULE_PARM_DESC(force_subclients,
47b55f3757SGuenter Roeck 		 "List of subclient addresses: {bus, clientaddr, subclientaddr1, subclientaddr2}");
489873964dSCharles Spirakis 
4990ab5ee9SRusty Russell static bool reset;
509873964dSCharles Spirakis module_param(reset, bool, 0);
519873964dSCharles Spirakis MODULE_PARM_DESC(reset, "Set to one to force a hardware chip reset");
529873964dSCharles Spirakis 
5390ab5ee9SRusty Russell static bool init;
549873964dSCharles Spirakis module_param(init, bool, 0);
559873964dSCharles Spirakis MODULE_PARM_DESC(init, "Set to one to force extra software initialization");
569873964dSCharles Spirakis 
579873964dSCharles Spirakis /* The W83791D registers */
589873964dSCharles Spirakis static const u8 W83791D_REG_IN[NUMBER_OF_VIN] = {
599873964dSCharles Spirakis 	0x20,			/* VCOREA in DataSheet */
609873964dSCharles Spirakis 	0x21,			/* VINR0 in DataSheet */
619873964dSCharles Spirakis 	0x22,			/* +3.3VIN in DataSheet */
629873964dSCharles Spirakis 	0x23,			/* VDD5V in DataSheet */
639873964dSCharles Spirakis 	0x24,			/* +12VIN in DataSheet */
649873964dSCharles Spirakis 	0x25,			/* -12VIN in DataSheet */
659873964dSCharles Spirakis 	0x26,			/* -5VIN in DataSheet */
669873964dSCharles Spirakis 	0xB0,			/* 5VSB in DataSheet */
679873964dSCharles Spirakis 	0xB1,			/* VBAT in DataSheet */
689873964dSCharles Spirakis 	0xB2			/* VINR1 in DataSheet */
699873964dSCharles Spirakis };
709873964dSCharles Spirakis 
719873964dSCharles Spirakis static const u8 W83791D_REG_IN_MAX[NUMBER_OF_VIN] = {
729873964dSCharles Spirakis 	0x2B,			/* VCOREA High Limit in DataSheet */
739873964dSCharles Spirakis 	0x2D,			/* VINR0 High Limit in DataSheet */
749873964dSCharles Spirakis 	0x2F,			/* +3.3VIN High Limit in DataSheet */
759873964dSCharles Spirakis 	0x31,			/* VDD5V High Limit in DataSheet */
769873964dSCharles Spirakis 	0x33,			/* +12VIN High Limit in DataSheet */
779873964dSCharles Spirakis 	0x35,			/* -12VIN High Limit in DataSheet */
789873964dSCharles Spirakis 	0x37,			/* -5VIN High Limit in DataSheet */
799873964dSCharles Spirakis 	0xB4,			/* 5VSB High Limit in DataSheet */
809873964dSCharles Spirakis 	0xB6,			/* VBAT High Limit in DataSheet */
819873964dSCharles Spirakis 	0xB8			/* VINR1 High Limit in DataSheet */
829873964dSCharles Spirakis };
839873964dSCharles Spirakis static const u8 W83791D_REG_IN_MIN[NUMBER_OF_VIN] = {
849873964dSCharles Spirakis 	0x2C,			/* VCOREA Low Limit in DataSheet */
859873964dSCharles Spirakis 	0x2E,			/* VINR0 Low Limit in DataSheet */
869873964dSCharles Spirakis 	0x30,			/* +3.3VIN Low Limit in DataSheet */
879873964dSCharles Spirakis 	0x32,			/* VDD5V Low Limit in DataSheet */
889873964dSCharles Spirakis 	0x34,			/* +12VIN Low Limit in DataSheet */
899873964dSCharles Spirakis 	0x36,			/* -12VIN Low Limit in DataSheet */
909873964dSCharles Spirakis 	0x38,			/* -5VIN Low Limit in DataSheet */
919873964dSCharles Spirakis 	0xB5,			/* 5VSB Low Limit in DataSheet */
929873964dSCharles Spirakis 	0xB7,			/* VBAT Low Limit in DataSheet */
939873964dSCharles Spirakis 	0xB9			/* VINR1 Low Limit in DataSheet */
949873964dSCharles Spirakis };
959873964dSCharles Spirakis static const u8 W83791D_REG_FAN[NUMBER_OF_FANIN] = {
969873964dSCharles Spirakis 	0x28,			/* FAN 1 Count in DataSheet */
979873964dSCharles Spirakis 	0x29,			/* FAN 2 Count in DataSheet */
989873964dSCharles Spirakis 	0x2A,			/* FAN 3 Count in DataSheet */
999873964dSCharles Spirakis 	0xBA,			/* FAN 4 Count in DataSheet */
1009873964dSCharles Spirakis 	0xBB,			/* FAN 5 Count in DataSheet */
1019873964dSCharles Spirakis };
1029873964dSCharles Spirakis static const u8 W83791D_REG_FAN_MIN[NUMBER_OF_FANIN] = {
1039873964dSCharles Spirakis 	0x3B,			/* FAN 1 Count Low Limit in DataSheet */
1049873964dSCharles Spirakis 	0x3C,			/* FAN 2 Count Low Limit in DataSheet */
1059873964dSCharles Spirakis 	0x3D,			/* FAN 3 Count Low Limit in DataSheet */
1069873964dSCharles Spirakis 	0xBC,			/* FAN 4 Count Low Limit in DataSheet */
1079873964dSCharles Spirakis 	0xBD,			/* FAN 5 Count Low Limit in DataSheet */
1089873964dSCharles Spirakis };
1099873964dSCharles Spirakis 
1106495ce18SMarc Hulsman static const u8 W83791D_REG_PWM[NUMBER_OF_PWM] = {
1116495ce18SMarc Hulsman 	0x81,			/* PWM 1 duty cycle register in DataSheet */
1126495ce18SMarc Hulsman 	0x83,			/* PWM 2 duty cycle register in DataSheet */
1136495ce18SMarc Hulsman 	0x94,			/* PWM 3 duty cycle register in DataSheet */
1146495ce18SMarc Hulsman 	0xA0,			/* PWM 4 duty cycle register in DataSheet */
1156495ce18SMarc Hulsman 	0xA1,			/* PWM 5 duty cycle register in DataSheet */
1166495ce18SMarc Hulsman };
1176495ce18SMarc Hulsman 
118a5a4598cSMarc Hulsman static const u8 W83791D_REG_TEMP_TARGET[3] = {
119a5a4598cSMarc Hulsman 	0x85,			/* PWM 1 target temperature for temp 1 */
120a5a4598cSMarc Hulsman 	0x86,			/* PWM 2 target temperature for temp 2 */
121a5a4598cSMarc Hulsman 	0x96,			/* PWM 3 target temperature for temp 3 */
122a5a4598cSMarc Hulsman };
123a5a4598cSMarc Hulsman 
124a5a4598cSMarc Hulsman static const u8 W83791D_REG_TEMP_TOL[2] = {
125a5a4598cSMarc Hulsman 	0x87,			/* PWM 1/2 temperature tolerance */
126a5a4598cSMarc Hulsman 	0x97,			/* PWM 3 temperature tolerance */
127a5a4598cSMarc Hulsman };
128a5a4598cSMarc Hulsman 
1299873964dSCharles Spirakis static const u8 W83791D_REG_FAN_CFG[2] = {
1309873964dSCharles Spirakis 	0x84,			/* FAN 1/2 configuration */
1319873964dSCharles Spirakis 	0x95,			/* FAN 3 configuration */
1329873964dSCharles Spirakis };
1339873964dSCharles Spirakis 
1349873964dSCharles Spirakis static const u8 W83791D_REG_FAN_DIV[3] = {
1359873964dSCharles Spirakis 	0x47,			/* contains FAN1 and FAN2 Divisor */
1369873964dSCharles Spirakis 	0x4b,			/* contains FAN3 Divisor */
1379873964dSCharles Spirakis 	0x5C,			/* contains FAN4 and FAN5 Divisor */
1389873964dSCharles Spirakis };
1399873964dSCharles Spirakis 
1409873964dSCharles Spirakis #define W83791D_REG_BANK		0x4E
1419873964dSCharles Spirakis #define W83791D_REG_TEMP2_CONFIG	0xC2
1429873964dSCharles Spirakis #define W83791D_REG_TEMP3_CONFIG	0xCA
1439873964dSCharles Spirakis 
1449873964dSCharles Spirakis static const u8 W83791D_REG_TEMP1[3] = {
1459873964dSCharles Spirakis 	0x27,			/* TEMP 1 in DataSheet */
1469873964dSCharles Spirakis 	0x39,			/* TEMP 1 Over in DataSheet */
1479873964dSCharles Spirakis 	0x3A,			/* TEMP 1 Hyst in DataSheet */
1489873964dSCharles Spirakis };
1499873964dSCharles Spirakis 
1509873964dSCharles Spirakis static const u8 W83791D_REG_TEMP_ADD[2][6] = {
1519873964dSCharles Spirakis 	{0xC0,			/* TEMP 2 in DataSheet */
1529873964dSCharles Spirakis 	 0xC1,			/* TEMP 2(0.5 deg) in DataSheet */
1539873964dSCharles Spirakis 	 0xC5,			/* TEMP 2 Over High part in DataSheet */
1549873964dSCharles Spirakis 	 0xC6,			/* TEMP 2 Over Low part in DataSheet */
1559873964dSCharles Spirakis 	 0xC3,			/* TEMP 2 Thyst High part in DataSheet */
1569873964dSCharles Spirakis 	 0xC4},			/* TEMP 2 Thyst Low part in DataSheet */
1579873964dSCharles Spirakis 	{0xC8,			/* TEMP 3 in DataSheet */
1589873964dSCharles Spirakis 	 0xC9,			/* TEMP 3(0.5 deg) in DataSheet */
1599873964dSCharles Spirakis 	 0xCD,			/* TEMP 3 Over High part in DataSheet */
1609873964dSCharles Spirakis 	 0xCE,			/* TEMP 3 Over Low part in DataSheet */
1619873964dSCharles Spirakis 	 0xCB,			/* TEMP 3 Thyst High part in DataSheet */
1629873964dSCharles Spirakis 	 0xCC}			/* TEMP 3 Thyst Low part in DataSheet */
1639873964dSCharles Spirakis };
1649873964dSCharles Spirakis 
1659873964dSCharles Spirakis #define W83791D_REG_BEEP_CONFIG		0x4D
1669873964dSCharles Spirakis 
1679873964dSCharles Spirakis static const u8 W83791D_REG_BEEP_CTRL[3] = {
1689873964dSCharles Spirakis 	0x56,			/* BEEP Control Register 1 */
1699873964dSCharles Spirakis 	0x57,			/* BEEP Control Register 2 */
1709873964dSCharles Spirakis 	0xA3,			/* BEEP Control Register 3 */
1719873964dSCharles Spirakis };
1729873964dSCharles Spirakis 
1736e1ecd9bSMarc Hulsman #define W83791D_REG_GPIO		0x15
1749873964dSCharles Spirakis #define W83791D_REG_CONFIG		0x40
1759873964dSCharles Spirakis #define W83791D_REG_VID_FANDIV		0x47
1769873964dSCharles Spirakis #define W83791D_REG_DID_VID4		0x49
1779873964dSCharles Spirakis #define W83791D_REG_WCHIPID		0x58
1789873964dSCharles Spirakis #define W83791D_REG_CHIPMAN		0x4F
1799873964dSCharles Spirakis #define W83791D_REG_PIN			0x4B
1809873964dSCharles Spirakis #define W83791D_REG_I2C_SUBADDR		0x4A
1819873964dSCharles Spirakis 
1829873964dSCharles Spirakis #define W83791D_REG_ALARM1 0xA9	/* realtime status register1 */
1839873964dSCharles Spirakis #define W83791D_REG_ALARM2 0xAA	/* realtime status register2 */
1849873964dSCharles Spirakis #define W83791D_REG_ALARM3 0xAB	/* realtime status register3 */
1859873964dSCharles Spirakis 
1869873964dSCharles Spirakis #define W83791D_REG_VBAT		0x5D
1879873964dSCharles Spirakis #define W83791D_REG_I2C_ADDR		0x48
1889873964dSCharles Spirakis 
189ec1c3194SGuenter Roeck /*
190ec1c3194SGuenter Roeck  * The SMBus locks itself. The Winbond W83791D has a bank select register
191ec1c3194SGuenter Roeck  * (index 0x4e), but the driver only accesses registers in bank 0. Since
192ec1c3194SGuenter Roeck  * we don't switch banks, we don't need any special code to handle
193ec1c3194SGuenter Roeck  * locking access between bank switches
194ec1c3194SGuenter Roeck  */
w83791d_read(struct i2c_client * client,u8 reg)1959873964dSCharles Spirakis static inline int w83791d_read(struct i2c_client *client, u8 reg)
1969873964dSCharles Spirakis {
1979873964dSCharles Spirakis 	return i2c_smbus_read_byte_data(client, reg);
1989873964dSCharles Spirakis }
1999873964dSCharles Spirakis 
w83791d_write(struct i2c_client * client,u8 reg,u8 value)2009873964dSCharles Spirakis static inline int w83791d_write(struct i2c_client *client, u8 reg, u8 value)
2019873964dSCharles Spirakis {
2029873964dSCharles Spirakis 	return i2c_smbus_write_byte_data(client, reg, value);
2039873964dSCharles Spirakis }
2049873964dSCharles Spirakis 
205ec1c3194SGuenter Roeck /*
206ec1c3194SGuenter Roeck  * The analog voltage inputs have 16mV LSB. Since the sysfs output is
207ec1c3194SGuenter Roeck  * in mV as would be measured on the chip input pin, need to just
208ec1c3194SGuenter Roeck  * multiply/divide by 16 to translate from/to register values.
209ec1c3194SGuenter Roeck  */
2102a844c14SGuenter Roeck #define IN_TO_REG(val)		(clamp_val((((val) + 8) / 16), 0, 255))
2119873964dSCharles Spirakis #define IN_FROM_REG(val)	((val) * 16)
2129873964dSCharles Spirakis 
fan_to_reg(long rpm,int div)2139873964dSCharles Spirakis static u8 fan_to_reg(long rpm, int div)
2149873964dSCharles Spirakis {
2159873964dSCharles Spirakis 	if (rpm == 0)
2169873964dSCharles Spirakis 		return 255;
2172a844c14SGuenter Roeck 	rpm = clamp_val(rpm, 1, 1000000);
2182a844c14SGuenter Roeck 	return clamp_val((1350000 + rpm * div / 2) / (rpm * div), 1, 254);
2199873964dSCharles Spirakis }
2209873964dSCharles Spirakis 
2219873964dSCharles Spirakis #define FAN_FROM_REG(val, div)	((val) == 0 ? -1 : \
2229873964dSCharles Spirakis 				((val) == 255 ? 0 : \
2239873964dSCharles Spirakis 					1350000 / ((val) * (div))))
2249873964dSCharles Spirakis 
2259873964dSCharles Spirakis /* for temp1 which is 8-bit resolution, LSB = 1 degree Celsius */
2269873964dSCharles Spirakis #define TEMP1_FROM_REG(val)	((val) * 1000)
2279873964dSCharles Spirakis #define TEMP1_TO_REG(val)	((val) <= -128000 ? -128 : \
2289873964dSCharles Spirakis 				 (val) >= 127000 ? 127 : \
2299873964dSCharles Spirakis 				 (val) < 0 ? ((val) - 500) / 1000 : \
2309873964dSCharles Spirakis 				 ((val) + 500) / 1000)
2319873964dSCharles Spirakis 
232ec1c3194SGuenter Roeck /*
233ec1c3194SGuenter Roeck  * for temp2 and temp3 which are 9-bit resolution, LSB = 0.5 degree Celsius
234ec1c3194SGuenter Roeck  * Assumes the top 8 bits are the integral amount and the bottom 8 bits
235ec1c3194SGuenter Roeck  * are the fractional amount. Since we only have 0.5 degree resolution,
236ec1c3194SGuenter Roeck  * the bottom 7 bits will always be zero
237ec1c3194SGuenter Roeck  */
2389873964dSCharles Spirakis #define TEMP23_FROM_REG(val)	((val) / 128 * 500)
23940ebdb92SGuenter Roeck #define TEMP23_TO_REG(val)	(DIV_ROUND_CLOSEST(clamp_val((val), -128000, \
24040ebdb92SGuenter Roeck 						   127500), 500) * 128)
2419873964dSCharles Spirakis 
242a5a4598cSMarc Hulsman /* for thermal cruise target temp, 7-bits, LSB = 1 degree Celsius */
24340ebdb92SGuenter Roeck #define TARGET_TEMP_TO_REG(val)	DIV_ROUND_CLOSEST(clamp_val((val), 0, 127000), \
24440ebdb92SGuenter Roeck 						  1000)
245a5a4598cSMarc Hulsman 
246a5a4598cSMarc Hulsman /* for thermal cruise temp tolerance, 4-bits, LSB = 1 degree Celsius */
24740ebdb92SGuenter Roeck #define TOL_TEMP_TO_REG(val)	DIV_ROUND_CLOSEST(clamp_val((val), 0, 15000), \
24840ebdb92SGuenter Roeck 						  1000)
2499873964dSCharles Spirakis 
2509873964dSCharles Spirakis #define BEEP_MASK_TO_REG(val)		((val) & 0xffffff)
2519873964dSCharles Spirakis #define BEEP_MASK_FROM_REG(val)		((val) & 0xffffff)
2529873964dSCharles Spirakis 
2539873964dSCharles Spirakis #define DIV_FROM_REG(val)		(1 << (val))
2549873964dSCharles Spirakis 
div_to_reg(int nr,long val)2559873964dSCharles Spirakis static u8 div_to_reg(int nr, long val)
2569873964dSCharles Spirakis {
2579873964dSCharles Spirakis 	int i;
2589873964dSCharles Spirakis 
259ad02ad85SMarc Hulsman 	/* fan divisors max out at 128 */
2602a844c14SGuenter Roeck 	val = clamp_val(val, 1, 128) >> 1;
2619873964dSCharles Spirakis 	for (i = 0; i < 7; i++) {
2629873964dSCharles Spirakis 		if (val == 0)
2639873964dSCharles Spirakis 			break;
2649873964dSCharles Spirakis 		val >>= 1;
2659873964dSCharles Spirakis 	}
2669873964dSCharles Spirakis 	return (u8) i;
2679873964dSCharles Spirakis }
2689873964dSCharles Spirakis 
2699873964dSCharles Spirakis struct w83791d_data {
2701beeffe4STony Jones 	struct device *hwmon_dev;
2719873964dSCharles Spirakis 	struct mutex update_lock;
2729873964dSCharles Spirakis 
273952a11caSPaul Fertser 	bool valid;			/* true if following fields are valid */
2749873964dSCharles Spirakis 	unsigned long last_updated;	/* In jiffies */
2759873964dSCharles Spirakis 
2769873964dSCharles Spirakis 	/* volts */
2779873964dSCharles Spirakis 	u8 in[NUMBER_OF_VIN];		/* Register value */
2789873964dSCharles Spirakis 	u8 in_max[NUMBER_OF_VIN];	/* Register value */
2799873964dSCharles Spirakis 	u8 in_min[NUMBER_OF_VIN];	/* Register value */
2809873964dSCharles Spirakis 
2819873964dSCharles Spirakis 	/* fans */
2829873964dSCharles Spirakis 	u8 fan[NUMBER_OF_FANIN];	/* Register value */
2839873964dSCharles Spirakis 	u8 fan_min[NUMBER_OF_FANIN];	/* Register value */
2849873964dSCharles Spirakis 	u8 fan_div[NUMBER_OF_FANIN];	/* Register encoding, shifted right */
2859873964dSCharles Spirakis 
2869873964dSCharles Spirakis 	/* Temperature sensors */
2879873964dSCharles Spirakis 
2889873964dSCharles Spirakis 	s8 temp1[3];		/* current, over, thyst */
2899873964dSCharles Spirakis 	s16 temp_add[2][3];	/* fixed point value. Top 8 bits are the
290ec1c3194SGuenter Roeck 				 * integral part, bottom 8 bits are the
291ec1c3194SGuenter Roeck 				 * fractional part. We only use the top
292ec1c3194SGuenter Roeck 				 * 9 bits as the resolution is only
293ec1c3194SGuenter Roeck 				 * to the 0.5 degree C...
294ec1c3194SGuenter Roeck 				 * two sensors with three values
295ec1c3194SGuenter Roeck 				 * (cur, over, hyst)
296ec1c3194SGuenter Roeck 				 */
2979873964dSCharles Spirakis 
2986495ce18SMarc Hulsman 	/* PWMs */
2996495ce18SMarc Hulsman 	u8 pwm[5];		/* pwm duty cycle */
300b5938f8cSMarc Hulsman 	u8 pwm_enable[3];	/* pwm enable status for fan 1-3
301ec1c3194SGuenter Roeck 				 * (fan 4-5 only support manual mode)
302ec1c3194SGuenter Roeck 				 */
3036495ce18SMarc Hulsman 
304a5a4598cSMarc Hulsman 	u8 temp_target[3];	/* pwm 1-3 target temperature */
305a5a4598cSMarc Hulsman 	u8 temp_tolerance[3];	/* pwm 1-3 temperature tolerance */
306a5a4598cSMarc Hulsman 
3079873964dSCharles Spirakis 	/* Misc */
3089873964dSCharles Spirakis 	u32 alarms;		/* realtime status register encoding,combined */
3099873964dSCharles Spirakis 	u8 beep_enable;		/* Global beep enable */
3109873964dSCharles Spirakis 	u32 beep_mask;		/* Mask off specific beeps */
3119873964dSCharles Spirakis 	u8 vid;			/* Register encoding, combined */
3129873964dSCharles Spirakis 	u8 vrm;			/* hwmon-vid */
3139873964dSCharles Spirakis };
3149873964dSCharles Spirakis 
31577b5b8a8SStephen Kitt static int w83791d_probe(struct i2c_client *client);
316310ec792SJean Delvare static int w83791d_detect(struct i2c_client *client,
317cb0c1af3SJean Delvare 			  struct i2c_board_info *info);
318ed5c2f5fSUwe Kleine-König static void w83791d_remove(struct i2c_client *client);
3199873964dSCharles Spirakis 
3207cbe1ceeSChris Peterson static int w83791d_read(struct i2c_client *client, u8 reg);
3217cbe1ceeSChris Peterson static int w83791d_write(struct i2c_client *client, u8 reg, u8 value);
3229873964dSCharles Spirakis static struct w83791d_data *w83791d_update_device(struct device *dev);
3239873964dSCharles Spirakis 
3249873964dSCharles Spirakis #ifdef DEBUG
3259873964dSCharles Spirakis static void w83791d_print_debug(struct w83791d_data *data, struct device *dev);
3269873964dSCharles Spirakis #endif
3279873964dSCharles Spirakis 
3289873964dSCharles Spirakis static void w83791d_init_client(struct i2c_client *client);
3299873964dSCharles Spirakis 
330cb0c1af3SJean Delvare static const struct i2c_device_id w83791d_id[] = {
3311f86df49SJean Delvare 	{ "w83791d", 0 },
332cb0c1af3SJean Delvare 	{ }
333cb0c1af3SJean Delvare };
334cb0c1af3SJean Delvare MODULE_DEVICE_TABLE(i2c, w83791d_id);
335cb0c1af3SJean Delvare 
3369873964dSCharles Spirakis static struct i2c_driver w83791d_driver = {
337cb0c1af3SJean Delvare 	.class		= I2C_CLASS_HWMON,
3389873964dSCharles Spirakis 	.driver = {
3399873964dSCharles Spirakis 		.name = "w83791d",
3409873964dSCharles Spirakis 	},
341*1975d167SUwe Kleine-König 	.probe		= w83791d_probe,
342cb0c1af3SJean Delvare 	.remove		= w83791d_remove,
343cb0c1af3SJean Delvare 	.id_table	= w83791d_id,
344cb0c1af3SJean Delvare 	.detect		= w83791d_detect,
345c3813d6aSJean Delvare 	.address_list	= normal_i2c,
3469873964dSCharles Spirakis };
3479873964dSCharles Spirakis 
3489873964dSCharles Spirakis /* following are the sysfs callback functions */
3499873964dSCharles Spirakis #define show_in_reg(reg) \
3509873964dSCharles Spirakis static ssize_t show_##reg(struct device *dev, struct device_attribute *attr, \
3519873964dSCharles Spirakis 			char *buf) \
3529873964dSCharles Spirakis { \
3539873964dSCharles Spirakis 	struct sensor_device_attribute *sensor_attr = \
3549873964dSCharles Spirakis 						to_sensor_dev_attr(attr); \
3559873964dSCharles Spirakis 	struct w83791d_data *data = w83791d_update_device(dev); \
3569873964dSCharles Spirakis 	int nr = sensor_attr->index; \
3579873964dSCharles Spirakis 	return sprintf(buf, "%d\n", IN_FROM_REG(data->reg[nr])); \
3589873964dSCharles Spirakis }
3599873964dSCharles Spirakis 
3609873964dSCharles Spirakis show_in_reg(in);
3619873964dSCharles Spirakis show_in_reg(in_min);
3629873964dSCharles Spirakis show_in_reg(in_max);
3639873964dSCharles Spirakis 
3649873964dSCharles Spirakis #define store_in_reg(REG, reg) \
3659873964dSCharles Spirakis static ssize_t store_in_##reg(struct device *dev, \
3669873964dSCharles Spirakis 				struct device_attribute *attr, \
3679873964dSCharles Spirakis 				const char *buf, size_t count) \
3689873964dSCharles Spirakis { \
3699873964dSCharles Spirakis 	struct sensor_device_attribute *sensor_attr = \
3709873964dSCharles Spirakis 						to_sensor_dev_attr(attr); \
3719873964dSCharles Spirakis 	struct i2c_client *client = to_i2c_client(dev); \
3729873964dSCharles Spirakis 	struct w83791d_data *data = i2c_get_clientdata(client); \
3739873964dSCharles Spirakis 	int nr = sensor_attr->index; \
374ec1c3194SGuenter Roeck 	unsigned long val; \
375ec1c3194SGuenter Roeck 	int err = kstrtoul(buf, 10, &val); \
376ec1c3194SGuenter Roeck 	if (err) \
377ec1c3194SGuenter Roeck 		return err; \
3789873964dSCharles Spirakis 	mutex_lock(&data->update_lock); \
3799873964dSCharles Spirakis 	data->in_##reg[nr] = IN_TO_REG(val); \
3809873964dSCharles Spirakis 	w83791d_write(client, W83791D_REG_IN_##REG[nr], data->in_##reg[nr]); \
3819873964dSCharles Spirakis 	mutex_unlock(&data->update_lock); \
3829873964dSCharles Spirakis 	 \
3839873964dSCharles Spirakis 	return count; \
3849873964dSCharles Spirakis }
3859873964dSCharles Spirakis store_in_reg(MIN, min);
3869873964dSCharles Spirakis store_in_reg(MAX, max);
3879873964dSCharles Spirakis 
3889873964dSCharles Spirakis static struct sensor_device_attribute sda_in_input[] = {
3899873964dSCharles Spirakis 	SENSOR_ATTR(in0_input, S_IRUGO, show_in, NULL, 0),
3909873964dSCharles Spirakis 	SENSOR_ATTR(in1_input, S_IRUGO, show_in, NULL, 1),
3919873964dSCharles Spirakis 	SENSOR_ATTR(in2_input, S_IRUGO, show_in, NULL, 2),
3929873964dSCharles Spirakis 	SENSOR_ATTR(in3_input, S_IRUGO, show_in, NULL, 3),
3939873964dSCharles Spirakis 	SENSOR_ATTR(in4_input, S_IRUGO, show_in, NULL, 4),
3949873964dSCharles Spirakis 	SENSOR_ATTR(in5_input, S_IRUGO, show_in, NULL, 5),
3959873964dSCharles Spirakis 	SENSOR_ATTR(in6_input, S_IRUGO, show_in, NULL, 6),
3969873964dSCharles Spirakis 	SENSOR_ATTR(in7_input, S_IRUGO, show_in, NULL, 7),
3979873964dSCharles Spirakis 	SENSOR_ATTR(in8_input, S_IRUGO, show_in, NULL, 8),
3989873964dSCharles Spirakis 	SENSOR_ATTR(in9_input, S_IRUGO, show_in, NULL, 9),
3999873964dSCharles Spirakis };
4009873964dSCharles Spirakis 
4019873964dSCharles Spirakis static struct sensor_device_attribute sda_in_min[] = {
4029873964dSCharles Spirakis 	SENSOR_ATTR(in0_min, S_IWUSR | S_IRUGO, show_in_min, store_in_min, 0),
4039873964dSCharles Spirakis 	SENSOR_ATTR(in1_min, S_IWUSR | S_IRUGO, show_in_min, store_in_min, 1),
4049873964dSCharles Spirakis 	SENSOR_ATTR(in2_min, S_IWUSR | S_IRUGO, show_in_min, store_in_min, 2),
4059873964dSCharles Spirakis 	SENSOR_ATTR(in3_min, S_IWUSR | S_IRUGO, show_in_min, store_in_min, 3),
4069873964dSCharles Spirakis 	SENSOR_ATTR(in4_min, S_IWUSR | S_IRUGO, show_in_min, store_in_min, 4),
4079873964dSCharles Spirakis 	SENSOR_ATTR(in5_min, S_IWUSR | S_IRUGO, show_in_min, store_in_min, 5),
4089873964dSCharles Spirakis 	SENSOR_ATTR(in6_min, S_IWUSR | S_IRUGO, show_in_min, store_in_min, 6),
4099873964dSCharles Spirakis 	SENSOR_ATTR(in7_min, S_IWUSR | S_IRUGO, show_in_min, store_in_min, 7),
4109873964dSCharles Spirakis 	SENSOR_ATTR(in8_min, S_IWUSR | S_IRUGO, show_in_min, store_in_min, 8),
4119873964dSCharles Spirakis 	SENSOR_ATTR(in9_min, S_IWUSR | S_IRUGO, show_in_min, store_in_min, 9),
4129873964dSCharles Spirakis };
4139873964dSCharles Spirakis 
4149873964dSCharles Spirakis static struct sensor_device_attribute sda_in_max[] = {
4159873964dSCharles Spirakis 	SENSOR_ATTR(in0_max, S_IWUSR | S_IRUGO, show_in_max, store_in_max, 0),
4169873964dSCharles Spirakis 	SENSOR_ATTR(in1_max, S_IWUSR | S_IRUGO, show_in_max, store_in_max, 1),
4179873964dSCharles Spirakis 	SENSOR_ATTR(in2_max, S_IWUSR | S_IRUGO, show_in_max, store_in_max, 2),
4189873964dSCharles Spirakis 	SENSOR_ATTR(in3_max, S_IWUSR | S_IRUGO, show_in_max, store_in_max, 3),
4199873964dSCharles Spirakis 	SENSOR_ATTR(in4_max, S_IWUSR | S_IRUGO, show_in_max, store_in_max, 4),
4209873964dSCharles Spirakis 	SENSOR_ATTR(in5_max, S_IWUSR | S_IRUGO, show_in_max, store_in_max, 5),
4219873964dSCharles Spirakis 	SENSOR_ATTR(in6_max, S_IWUSR | S_IRUGO, show_in_max, store_in_max, 6),
4229873964dSCharles Spirakis 	SENSOR_ATTR(in7_max, S_IWUSR | S_IRUGO, show_in_max, store_in_max, 7),
4239873964dSCharles Spirakis 	SENSOR_ATTR(in8_max, S_IWUSR | S_IRUGO, show_in_max, store_in_max, 8),
4249873964dSCharles Spirakis 	SENSOR_ATTR(in9_max, S_IWUSR | S_IRUGO, show_in_max, store_in_max, 9),
4259873964dSCharles Spirakis };
4269873964dSCharles Spirakis 
42764383123SCharles Spirakis 
show_beep(struct device * dev,struct device_attribute * attr,char * buf)42864383123SCharles Spirakis static ssize_t show_beep(struct device *dev, struct device_attribute *attr,
42964383123SCharles Spirakis 			char *buf)
43064383123SCharles Spirakis {
43164383123SCharles Spirakis 	struct sensor_device_attribute *sensor_attr =
43264383123SCharles Spirakis 						to_sensor_dev_attr(attr);
43364383123SCharles Spirakis 	struct w83791d_data *data = w83791d_update_device(dev);
43464383123SCharles Spirakis 	int bitnr = sensor_attr->index;
43564383123SCharles Spirakis 
43664383123SCharles Spirakis 	return sprintf(buf, "%d\n", (data->beep_mask >> bitnr) & 1);
43764383123SCharles Spirakis }
43864383123SCharles Spirakis 
store_beep(struct device * dev,struct device_attribute * attr,const char * buf,size_t count)43964383123SCharles Spirakis static ssize_t store_beep(struct device *dev, struct device_attribute *attr,
44064383123SCharles Spirakis 			const char *buf, size_t count)
44164383123SCharles Spirakis {
44264383123SCharles Spirakis 	struct sensor_device_attribute *sensor_attr =
44364383123SCharles Spirakis 						to_sensor_dev_attr(attr);
44464383123SCharles Spirakis 	struct i2c_client *client = to_i2c_client(dev);
44564383123SCharles Spirakis 	struct w83791d_data *data = i2c_get_clientdata(client);
44664383123SCharles Spirakis 	int bitnr = sensor_attr->index;
44764383123SCharles Spirakis 	int bytenr = bitnr / 8;
448ec1c3194SGuenter Roeck 	unsigned long val;
449ec1c3194SGuenter Roeck 	int err;
450ec1c3194SGuenter Roeck 
451ec1c3194SGuenter Roeck 	err = kstrtoul(buf, 10, &val);
452ec1c3194SGuenter Roeck 	if (err)
453ec1c3194SGuenter Roeck 		return err;
454ec1c3194SGuenter Roeck 
455ec1c3194SGuenter Roeck 	val = val ? 1 : 0;
45664383123SCharles Spirakis 
45764383123SCharles Spirakis 	mutex_lock(&data->update_lock);
45864383123SCharles Spirakis 
45964383123SCharles Spirakis 	data->beep_mask &= ~(0xff << (bytenr * 8));
46064383123SCharles Spirakis 	data->beep_mask |= w83791d_read(client, W83791D_REG_BEEP_CTRL[bytenr])
46164383123SCharles Spirakis 		<< (bytenr * 8);
46264383123SCharles Spirakis 
46364383123SCharles Spirakis 	data->beep_mask &= ~(1 << bitnr);
46464383123SCharles Spirakis 	data->beep_mask |= val << bitnr;
46564383123SCharles Spirakis 
46664383123SCharles Spirakis 	w83791d_write(client, W83791D_REG_BEEP_CTRL[bytenr],
46764383123SCharles Spirakis 		(data->beep_mask >> (bytenr * 8)) & 0xff);
46864383123SCharles Spirakis 
46964383123SCharles Spirakis 	mutex_unlock(&data->update_lock);
47064383123SCharles Spirakis 
47164383123SCharles Spirakis 	return count;
47264383123SCharles Spirakis }
47364383123SCharles Spirakis 
show_alarm(struct device * dev,struct device_attribute * attr,char * buf)47464383123SCharles Spirakis static ssize_t show_alarm(struct device *dev, struct device_attribute *attr,
47564383123SCharles Spirakis 			char *buf)
47664383123SCharles Spirakis {
47764383123SCharles Spirakis 	struct sensor_device_attribute *sensor_attr =
47864383123SCharles Spirakis 						to_sensor_dev_attr(attr);
47964383123SCharles Spirakis 	struct w83791d_data *data = w83791d_update_device(dev);
48064383123SCharles Spirakis 	int bitnr = sensor_attr->index;
48164383123SCharles Spirakis 
48264383123SCharles Spirakis 	return sprintf(buf, "%d\n", (data->alarms >> bitnr) & 1);
48364383123SCharles Spirakis }
48464383123SCharles Spirakis 
485ec1c3194SGuenter Roeck /*
486ec1c3194SGuenter Roeck  * Note: The bitmask for the beep enable/disable is different than
487ec1c3194SGuenter Roeck  * the bitmask for the alarm.
488ec1c3194SGuenter Roeck  */
48964383123SCharles Spirakis static struct sensor_device_attribute sda_in_beep[] = {
49064383123SCharles Spirakis 	SENSOR_ATTR(in0_beep, S_IWUSR | S_IRUGO, show_beep, store_beep, 0),
49164383123SCharles Spirakis 	SENSOR_ATTR(in1_beep, S_IWUSR | S_IRUGO, show_beep, store_beep, 13),
49264383123SCharles Spirakis 	SENSOR_ATTR(in2_beep, S_IWUSR | S_IRUGO, show_beep, store_beep, 2),
49364383123SCharles Spirakis 	SENSOR_ATTR(in3_beep, S_IWUSR | S_IRUGO, show_beep, store_beep, 3),
49464383123SCharles Spirakis 	SENSOR_ATTR(in4_beep, S_IWUSR | S_IRUGO, show_beep, store_beep, 8),
49564383123SCharles Spirakis 	SENSOR_ATTR(in5_beep, S_IWUSR | S_IRUGO, show_beep, store_beep, 9),
49664383123SCharles Spirakis 	SENSOR_ATTR(in6_beep, S_IWUSR | S_IRUGO, show_beep, store_beep, 10),
49764383123SCharles Spirakis 	SENSOR_ATTR(in7_beep, S_IWUSR | S_IRUGO, show_beep, store_beep, 16),
49864383123SCharles Spirakis 	SENSOR_ATTR(in8_beep, S_IWUSR | S_IRUGO, show_beep, store_beep, 17),
49964383123SCharles Spirakis 	SENSOR_ATTR(in9_beep, S_IWUSR | S_IRUGO, show_beep, store_beep, 14),
50064383123SCharles Spirakis };
50164383123SCharles Spirakis 
50264383123SCharles Spirakis static struct sensor_device_attribute sda_in_alarm[] = {
50364383123SCharles Spirakis 	SENSOR_ATTR(in0_alarm, S_IRUGO, show_alarm, NULL, 0),
50464383123SCharles Spirakis 	SENSOR_ATTR(in1_alarm, S_IRUGO, show_alarm, NULL, 1),
50564383123SCharles Spirakis 	SENSOR_ATTR(in2_alarm, S_IRUGO, show_alarm, NULL, 2),
50664383123SCharles Spirakis 	SENSOR_ATTR(in3_alarm, S_IRUGO, show_alarm, NULL, 3),
50764383123SCharles Spirakis 	SENSOR_ATTR(in4_alarm, S_IRUGO, show_alarm, NULL, 8),
50864383123SCharles Spirakis 	SENSOR_ATTR(in5_alarm, S_IRUGO, show_alarm, NULL, 9),
50964383123SCharles Spirakis 	SENSOR_ATTR(in6_alarm, S_IRUGO, show_alarm, NULL, 10),
51064383123SCharles Spirakis 	SENSOR_ATTR(in7_alarm, S_IRUGO, show_alarm, NULL, 19),
51164383123SCharles Spirakis 	SENSOR_ATTR(in8_alarm, S_IRUGO, show_alarm, NULL, 20),
51264383123SCharles Spirakis 	SENSOR_ATTR(in9_alarm, S_IRUGO, show_alarm, NULL, 14),
51364383123SCharles Spirakis };
51464383123SCharles Spirakis 
5159873964dSCharles Spirakis #define show_fan_reg(reg) \
5169873964dSCharles Spirakis static ssize_t show_##reg(struct device *dev, struct device_attribute *attr, \
5179873964dSCharles Spirakis 				char *buf) \
5189873964dSCharles Spirakis { \
5199873964dSCharles Spirakis 	struct sensor_device_attribute *sensor_attr = \
5209873964dSCharles Spirakis 						to_sensor_dev_attr(attr); \
5219873964dSCharles Spirakis 	struct w83791d_data *data = w83791d_update_device(dev); \
5229873964dSCharles Spirakis 	int nr = sensor_attr->index; \
5239873964dSCharles Spirakis 	return sprintf(buf, "%d\n", \
5249873964dSCharles Spirakis 		FAN_FROM_REG(data->reg[nr], DIV_FROM_REG(data->fan_div[nr]))); \
5259873964dSCharles Spirakis }
5269873964dSCharles Spirakis 
5279873964dSCharles Spirakis show_fan_reg(fan);
5289873964dSCharles Spirakis show_fan_reg(fan_min);
5299873964dSCharles Spirakis 
store_fan_min(struct device * dev,struct device_attribute * attr,const char * buf,size_t count)5309873964dSCharles Spirakis static ssize_t store_fan_min(struct device *dev, struct device_attribute *attr,
5319873964dSCharles Spirakis 				const char *buf, size_t count)
5329873964dSCharles Spirakis {
5339873964dSCharles Spirakis 	struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr);
5349873964dSCharles Spirakis 	struct i2c_client *client = to_i2c_client(dev);
5359873964dSCharles Spirakis 	struct w83791d_data *data = i2c_get_clientdata(client);
5369873964dSCharles Spirakis 	int nr = sensor_attr->index;
537ec1c3194SGuenter Roeck 	unsigned long val;
538ec1c3194SGuenter Roeck 	int err;
539ec1c3194SGuenter Roeck 
540ec1c3194SGuenter Roeck 	err = kstrtoul(buf, 10, &val);
541ec1c3194SGuenter Roeck 	if (err)
542ec1c3194SGuenter Roeck 		return err;
5439873964dSCharles Spirakis 
5449873964dSCharles Spirakis 	mutex_lock(&data->update_lock);
5459873964dSCharles Spirakis 	data->fan_min[nr] = fan_to_reg(val, DIV_FROM_REG(data->fan_div[nr]));
5469873964dSCharles Spirakis 	w83791d_write(client, W83791D_REG_FAN_MIN[nr], data->fan_min[nr]);
5479873964dSCharles Spirakis 	mutex_unlock(&data->update_lock);
5489873964dSCharles Spirakis 
5499873964dSCharles Spirakis 	return count;
5509873964dSCharles Spirakis }
5519873964dSCharles Spirakis 
show_fan_div(struct device * dev,struct device_attribute * attr,char * buf)5529873964dSCharles Spirakis static ssize_t show_fan_div(struct device *dev, struct device_attribute *attr,
5539873964dSCharles Spirakis 				char *buf)
5549873964dSCharles Spirakis {
5559873964dSCharles Spirakis 	struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr);
5569873964dSCharles Spirakis 	int nr = sensor_attr->index;
5579873964dSCharles Spirakis 	struct w83791d_data *data = w83791d_update_device(dev);
5589873964dSCharles Spirakis 	return sprintf(buf, "%u\n", DIV_FROM_REG(data->fan_div[nr]));
5599873964dSCharles Spirakis }
5609873964dSCharles Spirakis 
561ec1c3194SGuenter Roeck /*
562ec1c3194SGuenter Roeck  * Note: we save and restore the fan minimum here, because its value is
563ec1c3194SGuenter Roeck  * determined in part by the fan divisor.  This follows the principle of
564ec1c3194SGuenter Roeck  * least surprise; the user doesn't expect the fan minimum to change just
565ec1c3194SGuenter Roeck  * because the divisor changed.
566ec1c3194SGuenter Roeck  */
store_fan_div(struct device * dev,struct device_attribute * attr,const char * buf,size_t count)5679873964dSCharles Spirakis static ssize_t store_fan_div(struct device *dev, struct device_attribute *attr,
5689873964dSCharles Spirakis 				const char *buf, size_t count)
5699873964dSCharles Spirakis {
5709873964dSCharles Spirakis 	struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr);
5719873964dSCharles Spirakis 	struct i2c_client *client = to_i2c_client(dev);
5729873964dSCharles Spirakis 	struct w83791d_data *data = i2c_get_clientdata(client);
5739873964dSCharles Spirakis 	int nr = sensor_attr->index;
5749873964dSCharles Spirakis 	unsigned long min;
5759873964dSCharles Spirakis 	u8 tmp_fan_div;
5769873964dSCharles Spirakis 	u8 fan_div_reg;
577ad02ad85SMarc Hulsman 	u8 vbat_reg;
5789873964dSCharles Spirakis 	int indx = 0;
5799873964dSCharles Spirakis 	u8 keep_mask = 0;
5809873964dSCharles Spirakis 	u8 new_shift = 0;
581ec1c3194SGuenter Roeck 	unsigned long val;
582ec1c3194SGuenter Roeck 	int err;
583ec1c3194SGuenter Roeck 
584ec1c3194SGuenter Roeck 	err = kstrtoul(buf, 10, &val);
585ec1c3194SGuenter Roeck 	if (err)
586ec1c3194SGuenter Roeck 		return err;
5879873964dSCharles Spirakis 
5889873964dSCharles Spirakis 	/* Save fan_min */
5899873964dSCharles Spirakis 	min = FAN_FROM_REG(data->fan_min[nr], DIV_FROM_REG(data->fan_div[nr]));
5909873964dSCharles Spirakis 
5919873964dSCharles Spirakis 	mutex_lock(&data->update_lock);
592ec1c3194SGuenter Roeck 	data->fan_div[nr] = div_to_reg(nr, val);
5939873964dSCharles Spirakis 
5949873964dSCharles Spirakis 	switch (nr) {
5959873964dSCharles Spirakis 	case 0:
5969873964dSCharles Spirakis 		indx = 0;
5979873964dSCharles Spirakis 		keep_mask = 0xcf;
5989873964dSCharles Spirakis 		new_shift = 4;
5999873964dSCharles Spirakis 		break;
6009873964dSCharles Spirakis 	case 1:
6019873964dSCharles Spirakis 		indx = 0;
6029873964dSCharles Spirakis 		keep_mask = 0x3f;
6039873964dSCharles Spirakis 		new_shift = 6;
6049873964dSCharles Spirakis 		break;
6059873964dSCharles Spirakis 	case 2:
6069873964dSCharles Spirakis 		indx = 1;
6079873964dSCharles Spirakis 		keep_mask = 0x3f;
6089873964dSCharles Spirakis 		new_shift = 6;
6099873964dSCharles Spirakis 		break;
6109873964dSCharles Spirakis 	case 3:
6119873964dSCharles Spirakis 		indx = 2;
6129873964dSCharles Spirakis 		keep_mask = 0xf8;
6139873964dSCharles Spirakis 		new_shift = 0;
6149873964dSCharles Spirakis 		break;
6159873964dSCharles Spirakis 	case 4:
6169873964dSCharles Spirakis 		indx = 2;
6179873964dSCharles Spirakis 		keep_mask = 0x8f;
6189873964dSCharles Spirakis 		new_shift = 4;
6199873964dSCharles Spirakis 		break;
6209873964dSCharles Spirakis #ifdef DEBUG
6219873964dSCharles Spirakis 	default:
6229873964dSCharles Spirakis 		dev_warn(dev, "store_fan_div: Unexpected nr seen: %d\n", nr);
6239873964dSCharles Spirakis 		count = -EINVAL;
6249873964dSCharles Spirakis 		goto err_exit;
6259873964dSCharles Spirakis #endif
6269873964dSCharles Spirakis 	}
6279873964dSCharles Spirakis 
6289873964dSCharles Spirakis 	fan_div_reg = w83791d_read(client, W83791D_REG_FAN_DIV[indx])
6299873964dSCharles Spirakis 			& keep_mask;
6309873964dSCharles Spirakis 	tmp_fan_div = (data->fan_div[nr] << new_shift) & ~keep_mask;
6319873964dSCharles Spirakis 
6329873964dSCharles Spirakis 	w83791d_write(client, W83791D_REG_FAN_DIV[indx],
6339873964dSCharles Spirakis 				fan_div_reg | tmp_fan_div);
6349873964dSCharles Spirakis 
635ad02ad85SMarc Hulsman 	/* Bit 2 of fans 0-2 is stored in the vbat register (bits 5-7) */
636ad02ad85SMarc Hulsman 	if (nr < 3) {
637ad02ad85SMarc Hulsman 		keep_mask = ~(1 << (nr + 5));
638ad02ad85SMarc Hulsman 		vbat_reg = w83791d_read(client, W83791D_REG_VBAT)
639ad02ad85SMarc Hulsman 				& keep_mask;
640ad02ad85SMarc Hulsman 		tmp_fan_div = (data->fan_div[nr] << (3 + nr)) & ~keep_mask;
641ad02ad85SMarc Hulsman 		w83791d_write(client, W83791D_REG_VBAT,
642ad02ad85SMarc Hulsman 				vbat_reg | tmp_fan_div);
643ad02ad85SMarc Hulsman 	}
644ad02ad85SMarc Hulsman 
6459873964dSCharles Spirakis 	/* Restore fan_min */
6469873964dSCharles Spirakis 	data->fan_min[nr] = fan_to_reg(min, DIV_FROM_REG(data->fan_div[nr]));
6479873964dSCharles Spirakis 	w83791d_write(client, W83791D_REG_FAN_MIN[nr], data->fan_min[nr]);
6489873964dSCharles Spirakis 
6499873964dSCharles Spirakis #ifdef DEBUG
6509873964dSCharles Spirakis err_exit:
6519873964dSCharles Spirakis #endif
6529873964dSCharles Spirakis 	mutex_unlock(&data->update_lock);
6539873964dSCharles Spirakis 
6549873964dSCharles Spirakis 	return count;
6559873964dSCharles Spirakis }
6569873964dSCharles Spirakis 
6579873964dSCharles Spirakis static struct sensor_device_attribute sda_fan_input[] = {
6589873964dSCharles Spirakis 	SENSOR_ATTR(fan1_input, S_IRUGO, show_fan, NULL, 0),
6599873964dSCharles Spirakis 	SENSOR_ATTR(fan2_input, S_IRUGO, show_fan, NULL, 1),
6609873964dSCharles Spirakis 	SENSOR_ATTR(fan3_input, S_IRUGO, show_fan, NULL, 2),
6619873964dSCharles Spirakis 	SENSOR_ATTR(fan4_input, S_IRUGO, show_fan, NULL, 3),
6629873964dSCharles Spirakis 	SENSOR_ATTR(fan5_input, S_IRUGO, show_fan, NULL, 4),
6639873964dSCharles Spirakis };
6649873964dSCharles Spirakis 
6659873964dSCharles Spirakis static struct sensor_device_attribute sda_fan_min[] = {
6669873964dSCharles Spirakis 	SENSOR_ATTR(fan1_min, S_IWUSR | S_IRUGO,
6679873964dSCharles Spirakis 			show_fan_min, store_fan_min, 0),
6689873964dSCharles Spirakis 	SENSOR_ATTR(fan2_min, S_IWUSR | S_IRUGO,
6699873964dSCharles Spirakis 			show_fan_min, store_fan_min, 1),
6709873964dSCharles Spirakis 	SENSOR_ATTR(fan3_min, S_IWUSR | S_IRUGO,
6719873964dSCharles Spirakis 			show_fan_min, store_fan_min, 2),
6729873964dSCharles Spirakis 	SENSOR_ATTR(fan4_min, S_IWUSR | S_IRUGO,
6739873964dSCharles Spirakis 			show_fan_min, store_fan_min, 3),
6749873964dSCharles Spirakis 	SENSOR_ATTR(fan5_min, S_IWUSR | S_IRUGO,
6759873964dSCharles Spirakis 			show_fan_min, store_fan_min, 4),
6769873964dSCharles Spirakis };
6779873964dSCharles Spirakis 
6789873964dSCharles Spirakis static struct sensor_device_attribute sda_fan_div[] = {
6799873964dSCharles Spirakis 	SENSOR_ATTR(fan1_div, S_IWUSR | S_IRUGO,
6809873964dSCharles Spirakis 			show_fan_div, store_fan_div, 0),
6819873964dSCharles Spirakis 	SENSOR_ATTR(fan2_div, S_IWUSR | S_IRUGO,
6829873964dSCharles Spirakis 			show_fan_div, store_fan_div, 1),
6839873964dSCharles Spirakis 	SENSOR_ATTR(fan3_div, S_IWUSR | S_IRUGO,
6849873964dSCharles Spirakis 			show_fan_div, store_fan_div, 2),
6859873964dSCharles Spirakis 	SENSOR_ATTR(fan4_div, S_IWUSR | S_IRUGO,
6869873964dSCharles Spirakis 			show_fan_div, store_fan_div, 3),
6879873964dSCharles Spirakis 	SENSOR_ATTR(fan5_div, S_IWUSR | S_IRUGO,
6889873964dSCharles Spirakis 			show_fan_div, store_fan_div, 4),
6899873964dSCharles Spirakis };
6909873964dSCharles Spirakis 
69164383123SCharles Spirakis static struct sensor_device_attribute sda_fan_beep[] = {
69264383123SCharles Spirakis 	SENSOR_ATTR(fan1_beep, S_IWUSR | S_IRUGO, show_beep, store_beep, 6),
69364383123SCharles Spirakis 	SENSOR_ATTR(fan2_beep, S_IWUSR | S_IRUGO, show_beep, store_beep, 7),
69464383123SCharles Spirakis 	SENSOR_ATTR(fan3_beep, S_IWUSR | S_IRUGO, show_beep, store_beep, 11),
69564383123SCharles Spirakis 	SENSOR_ATTR(fan4_beep, S_IWUSR | S_IRUGO, show_beep, store_beep, 21),
69664383123SCharles Spirakis 	SENSOR_ATTR(fan5_beep, S_IWUSR | S_IRUGO, show_beep, store_beep, 22),
69764383123SCharles Spirakis };
69864383123SCharles Spirakis 
69964383123SCharles Spirakis static struct sensor_device_attribute sda_fan_alarm[] = {
70064383123SCharles Spirakis 	SENSOR_ATTR(fan1_alarm, S_IRUGO, show_alarm, NULL, 6),
70164383123SCharles Spirakis 	SENSOR_ATTR(fan2_alarm, S_IRUGO, show_alarm, NULL, 7),
70264383123SCharles Spirakis 	SENSOR_ATTR(fan3_alarm, S_IRUGO, show_alarm, NULL, 11),
70364383123SCharles Spirakis 	SENSOR_ATTR(fan4_alarm, S_IRUGO, show_alarm, NULL, 21),
70464383123SCharles Spirakis 	SENSOR_ATTR(fan5_alarm, S_IRUGO, show_alarm, NULL, 22),
70564383123SCharles Spirakis };
70664383123SCharles Spirakis 
7076495ce18SMarc Hulsman /* read/write PWMs */
show_pwm(struct device * dev,struct device_attribute * attr,char * buf)7086495ce18SMarc Hulsman static ssize_t show_pwm(struct device *dev, struct device_attribute *attr,
7096495ce18SMarc Hulsman 				char *buf)
7106495ce18SMarc Hulsman {
7116495ce18SMarc Hulsman 	struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr);
7126495ce18SMarc Hulsman 	int nr = sensor_attr->index;
7136495ce18SMarc Hulsman 	struct w83791d_data *data = w83791d_update_device(dev);
7146495ce18SMarc Hulsman 	return sprintf(buf, "%u\n", data->pwm[nr]);
7156495ce18SMarc Hulsman }
7166495ce18SMarc Hulsman 
store_pwm(struct device * dev,struct device_attribute * attr,const char * buf,size_t count)7176495ce18SMarc Hulsman static ssize_t store_pwm(struct device *dev, struct device_attribute *attr,
7186495ce18SMarc Hulsman 		const char *buf, size_t count)
7196495ce18SMarc Hulsman {
7206495ce18SMarc Hulsman 	struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr);
7216495ce18SMarc Hulsman 	struct i2c_client *client = to_i2c_client(dev);
7226495ce18SMarc Hulsman 	struct w83791d_data *data = i2c_get_clientdata(client);
7236495ce18SMarc Hulsman 	int nr = sensor_attr->index;
7246495ce18SMarc Hulsman 	unsigned long val;
7256495ce18SMarc Hulsman 
726179c4fdbSFrans Meulenbroeks 	if (kstrtoul(buf, 10, &val))
7276495ce18SMarc Hulsman 		return -EINVAL;
7286495ce18SMarc Hulsman 
7296495ce18SMarc Hulsman 	mutex_lock(&data->update_lock);
7302a844c14SGuenter Roeck 	data->pwm[nr] = clamp_val(val, 0, 255);
7316495ce18SMarc Hulsman 	w83791d_write(client, W83791D_REG_PWM[nr], data->pwm[nr]);
7326495ce18SMarc Hulsman 	mutex_unlock(&data->update_lock);
7336495ce18SMarc Hulsman 	return count;
7346495ce18SMarc Hulsman }
7356495ce18SMarc Hulsman 
7366495ce18SMarc Hulsman static struct sensor_device_attribute sda_pwm[] = {
7376495ce18SMarc Hulsman 	SENSOR_ATTR(pwm1, S_IWUSR | S_IRUGO,
7386495ce18SMarc Hulsman 			show_pwm, store_pwm, 0),
7396495ce18SMarc Hulsman 	SENSOR_ATTR(pwm2, S_IWUSR | S_IRUGO,
7406495ce18SMarc Hulsman 			show_pwm, store_pwm, 1),
7416495ce18SMarc Hulsman 	SENSOR_ATTR(pwm3, S_IWUSR | S_IRUGO,
7426495ce18SMarc Hulsman 			show_pwm, store_pwm, 2),
7436495ce18SMarc Hulsman 	SENSOR_ATTR(pwm4, S_IWUSR | S_IRUGO,
7446495ce18SMarc Hulsman 			show_pwm, store_pwm, 3),
7456495ce18SMarc Hulsman 	SENSOR_ATTR(pwm5, S_IWUSR | S_IRUGO,
7466495ce18SMarc Hulsman 			show_pwm, store_pwm, 4),
7476495ce18SMarc Hulsman };
7486495ce18SMarc Hulsman 
show_pwmenable(struct device * dev,struct device_attribute * attr,char * buf)749b5938f8cSMarc Hulsman static ssize_t show_pwmenable(struct device *dev, struct device_attribute *attr,
750b5938f8cSMarc Hulsman 				char *buf)
751b5938f8cSMarc Hulsman {
752b5938f8cSMarc Hulsman 	struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr);
753b5938f8cSMarc Hulsman 	int nr = sensor_attr->index;
754b5938f8cSMarc Hulsman 	struct w83791d_data *data = w83791d_update_device(dev);
755b5938f8cSMarc Hulsman 	return sprintf(buf, "%u\n", data->pwm_enable[nr] + 1);
756b5938f8cSMarc Hulsman }
757b5938f8cSMarc Hulsman 
store_pwmenable(struct device * dev,struct device_attribute * attr,const char * buf,size_t count)758b5938f8cSMarc Hulsman static ssize_t store_pwmenable(struct device *dev,
759b5938f8cSMarc Hulsman 		struct device_attribute *attr, const char *buf, size_t count)
760b5938f8cSMarc Hulsman {
761b5938f8cSMarc Hulsman 	struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr);
762b5938f8cSMarc Hulsman 	struct i2c_client *client = to_i2c_client(dev);
763b5938f8cSMarc Hulsman 	struct w83791d_data *data = i2c_get_clientdata(client);
764b5938f8cSMarc Hulsman 	int nr = sensor_attr->index;
765b5938f8cSMarc Hulsman 	unsigned long val;
766b5938f8cSMarc Hulsman 	u8 reg_cfg_tmp;
767b5938f8cSMarc Hulsman 	u8 reg_idx = 0;
768b5938f8cSMarc Hulsman 	u8 val_shift = 0;
769b5938f8cSMarc Hulsman 	u8 keep_mask = 0;
770b5938f8cSMarc Hulsman 
771179c4fdbSFrans Meulenbroeks 	int ret = kstrtoul(buf, 10, &val);
772b5938f8cSMarc Hulsman 
773b5938f8cSMarc Hulsman 	if (ret || val < 1 || val > 3)
774b5938f8cSMarc Hulsman 		return -EINVAL;
775b5938f8cSMarc Hulsman 
776b5938f8cSMarc Hulsman 	mutex_lock(&data->update_lock);
777b5938f8cSMarc Hulsman 	data->pwm_enable[nr] = val - 1;
778b5938f8cSMarc Hulsman 	switch (nr) {
779b5938f8cSMarc Hulsman 	case 0:
780b5938f8cSMarc Hulsman 		reg_idx = 0;
781b5938f8cSMarc Hulsman 		val_shift = 2;
782b5938f8cSMarc Hulsman 		keep_mask = 0xf3;
783b5938f8cSMarc Hulsman 		break;
784b5938f8cSMarc Hulsman 	case 1:
785b5938f8cSMarc Hulsman 		reg_idx = 0;
786b5938f8cSMarc Hulsman 		val_shift = 4;
787b5938f8cSMarc Hulsman 		keep_mask = 0xcf;
788b5938f8cSMarc Hulsman 		break;
789b5938f8cSMarc Hulsman 	case 2:
790b5938f8cSMarc Hulsman 		reg_idx = 1;
791b5938f8cSMarc Hulsman 		val_shift = 2;
792b5938f8cSMarc Hulsman 		keep_mask = 0xf3;
793b5938f8cSMarc Hulsman 		break;
794b5938f8cSMarc Hulsman 	}
795b5938f8cSMarc Hulsman 
796b5938f8cSMarc Hulsman 	reg_cfg_tmp = w83791d_read(client, W83791D_REG_FAN_CFG[reg_idx]);
797b5938f8cSMarc Hulsman 	reg_cfg_tmp = (reg_cfg_tmp & keep_mask) |
798b5938f8cSMarc Hulsman 					data->pwm_enable[nr] << val_shift;
799b5938f8cSMarc Hulsman 
800b5938f8cSMarc Hulsman 	w83791d_write(client, W83791D_REG_FAN_CFG[reg_idx], reg_cfg_tmp);
801b5938f8cSMarc Hulsman 	mutex_unlock(&data->update_lock);
802b5938f8cSMarc Hulsman 
803b5938f8cSMarc Hulsman 	return count;
804b5938f8cSMarc Hulsman }
805b5938f8cSMarc Hulsman static struct sensor_device_attribute sda_pwmenable[] = {
806b5938f8cSMarc Hulsman 	SENSOR_ATTR(pwm1_enable, S_IWUSR | S_IRUGO,
807b5938f8cSMarc Hulsman 			show_pwmenable, store_pwmenable, 0),
808b5938f8cSMarc Hulsman 	SENSOR_ATTR(pwm2_enable, S_IWUSR | S_IRUGO,
809b5938f8cSMarc Hulsman 			show_pwmenable, store_pwmenable, 1),
810b5938f8cSMarc Hulsman 	SENSOR_ATTR(pwm3_enable, S_IWUSR | S_IRUGO,
811b5938f8cSMarc Hulsman 			show_pwmenable, store_pwmenable, 2),
812b5938f8cSMarc Hulsman };
813b5938f8cSMarc Hulsman 
814a5a4598cSMarc Hulsman /* For Smart Fan I / Thermal Cruise */
show_temp_target(struct device * dev,struct device_attribute * attr,char * buf)815a5a4598cSMarc Hulsman static ssize_t show_temp_target(struct device *dev,
816a5a4598cSMarc Hulsman 			struct device_attribute *attr, char *buf)
817a5a4598cSMarc Hulsman {
818a5a4598cSMarc Hulsman 	struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr);
819a5a4598cSMarc Hulsman 	struct w83791d_data *data = w83791d_update_device(dev);
820a5a4598cSMarc Hulsman 	int nr = sensor_attr->index;
821a5a4598cSMarc Hulsman 	return sprintf(buf, "%d\n", TEMP1_FROM_REG(data->temp_target[nr]));
822a5a4598cSMarc Hulsman }
823a5a4598cSMarc Hulsman 
store_temp_target(struct device * dev,struct device_attribute * attr,const char * buf,size_t count)824a5a4598cSMarc Hulsman static ssize_t store_temp_target(struct device *dev,
825a5a4598cSMarc Hulsman 		struct device_attribute *attr, const char *buf, size_t count)
826a5a4598cSMarc Hulsman {
827a5a4598cSMarc Hulsman 	struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr);
828a5a4598cSMarc Hulsman 	struct i2c_client *client = to_i2c_client(dev);
829a5a4598cSMarc Hulsman 	struct w83791d_data *data = i2c_get_clientdata(client);
830a5a4598cSMarc Hulsman 	int nr = sensor_attr->index;
831a9169813SGuenter Roeck 	long val;
832a5a4598cSMarc Hulsman 	u8 target_mask;
833a5a4598cSMarc Hulsman 
834a9169813SGuenter Roeck 	if (kstrtol(buf, 10, &val))
835a5a4598cSMarc Hulsman 		return -EINVAL;
836a5a4598cSMarc Hulsman 
837a5a4598cSMarc Hulsman 	mutex_lock(&data->update_lock);
838a5a4598cSMarc Hulsman 	data->temp_target[nr] = TARGET_TEMP_TO_REG(val);
839a5a4598cSMarc Hulsman 	target_mask = w83791d_read(client,
840a5a4598cSMarc Hulsman 				W83791D_REG_TEMP_TARGET[nr]) & 0x80;
841a5a4598cSMarc Hulsman 	w83791d_write(client, W83791D_REG_TEMP_TARGET[nr],
842a5a4598cSMarc Hulsman 				data->temp_target[nr] | target_mask);
843a5a4598cSMarc Hulsman 	mutex_unlock(&data->update_lock);
844a5a4598cSMarc Hulsman 	return count;
845a5a4598cSMarc Hulsman }
846a5a4598cSMarc Hulsman 
847a5a4598cSMarc Hulsman static struct sensor_device_attribute sda_temp_target[] = {
848a5a4598cSMarc Hulsman 	SENSOR_ATTR(temp1_target, S_IWUSR | S_IRUGO,
849a5a4598cSMarc Hulsman 			show_temp_target, store_temp_target, 0),
850a5a4598cSMarc Hulsman 	SENSOR_ATTR(temp2_target, S_IWUSR | S_IRUGO,
851a5a4598cSMarc Hulsman 			show_temp_target, store_temp_target, 1),
852a5a4598cSMarc Hulsman 	SENSOR_ATTR(temp3_target, S_IWUSR | S_IRUGO,
853a5a4598cSMarc Hulsman 			show_temp_target, store_temp_target, 2),
854a5a4598cSMarc Hulsman };
855a5a4598cSMarc Hulsman 
show_temp_tolerance(struct device * dev,struct device_attribute * attr,char * buf)856a5a4598cSMarc Hulsman static ssize_t show_temp_tolerance(struct device *dev,
857a5a4598cSMarc Hulsman 			struct device_attribute *attr, char *buf)
858a5a4598cSMarc Hulsman {
859a5a4598cSMarc Hulsman 	struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr);
860a5a4598cSMarc Hulsman 	struct w83791d_data *data = w83791d_update_device(dev);
861a5a4598cSMarc Hulsman 	int nr = sensor_attr->index;
862a5a4598cSMarc Hulsman 	return sprintf(buf, "%d\n", TEMP1_FROM_REG(data->temp_tolerance[nr]));
863a5a4598cSMarc Hulsman }
864a5a4598cSMarc Hulsman 
store_temp_tolerance(struct device * dev,struct device_attribute * attr,const char * buf,size_t count)865a5a4598cSMarc Hulsman static ssize_t store_temp_tolerance(struct device *dev,
866a5a4598cSMarc Hulsman 		struct device_attribute *attr, const char *buf, size_t count)
867a5a4598cSMarc Hulsman {
868a5a4598cSMarc Hulsman 	struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr);
869a5a4598cSMarc Hulsman 	struct i2c_client *client = to_i2c_client(dev);
870a5a4598cSMarc Hulsman 	struct w83791d_data *data = i2c_get_clientdata(client);
871a5a4598cSMarc Hulsman 	int nr = sensor_attr->index;
872a5a4598cSMarc Hulsman 	unsigned long val;
873a5a4598cSMarc Hulsman 	u8 target_mask;
874a5a4598cSMarc Hulsman 	u8 reg_idx = 0;
875a5a4598cSMarc Hulsman 	u8 val_shift = 0;
876a5a4598cSMarc Hulsman 	u8 keep_mask = 0;
877a5a4598cSMarc Hulsman 
878179c4fdbSFrans Meulenbroeks 	if (kstrtoul(buf, 10, &val))
879a5a4598cSMarc Hulsman 		return -EINVAL;
880a5a4598cSMarc Hulsman 
881a5a4598cSMarc Hulsman 	switch (nr) {
882a5a4598cSMarc Hulsman 	case 0:
883a5a4598cSMarc Hulsman 		reg_idx = 0;
884a5a4598cSMarc Hulsman 		val_shift = 0;
885a5a4598cSMarc Hulsman 		keep_mask = 0xf0;
886a5a4598cSMarc Hulsman 		break;
887a5a4598cSMarc Hulsman 	case 1:
888a5a4598cSMarc Hulsman 		reg_idx = 0;
889a5a4598cSMarc Hulsman 		val_shift = 4;
890a5a4598cSMarc Hulsman 		keep_mask = 0x0f;
891a5a4598cSMarc Hulsman 		break;
892a5a4598cSMarc Hulsman 	case 2:
893a5a4598cSMarc Hulsman 		reg_idx = 1;
894a5a4598cSMarc Hulsman 		val_shift = 0;
895a5a4598cSMarc Hulsman 		keep_mask = 0xf0;
896a5a4598cSMarc Hulsman 		break;
897a5a4598cSMarc Hulsman 	}
898a5a4598cSMarc Hulsman 
899a5a4598cSMarc Hulsman 	mutex_lock(&data->update_lock);
900a5a4598cSMarc Hulsman 	data->temp_tolerance[nr] = TOL_TEMP_TO_REG(val);
901a5a4598cSMarc Hulsman 	target_mask = w83791d_read(client,
902a5a4598cSMarc Hulsman 			W83791D_REG_TEMP_TOL[reg_idx]) & keep_mask;
903a5a4598cSMarc Hulsman 	w83791d_write(client, W83791D_REG_TEMP_TOL[reg_idx],
904a5a4598cSMarc Hulsman 			(data->temp_tolerance[nr] << val_shift) | target_mask);
905a5a4598cSMarc Hulsman 	mutex_unlock(&data->update_lock);
906a5a4598cSMarc Hulsman 	return count;
907a5a4598cSMarc Hulsman }
908a5a4598cSMarc Hulsman 
909a5a4598cSMarc Hulsman static struct sensor_device_attribute sda_temp_tolerance[] = {
910a5a4598cSMarc Hulsman 	SENSOR_ATTR(temp1_tolerance, S_IWUSR | S_IRUGO,
911a5a4598cSMarc Hulsman 			show_temp_tolerance, store_temp_tolerance, 0),
912a5a4598cSMarc Hulsman 	SENSOR_ATTR(temp2_tolerance, S_IWUSR | S_IRUGO,
913a5a4598cSMarc Hulsman 			show_temp_tolerance, store_temp_tolerance, 1),
914a5a4598cSMarc Hulsman 	SENSOR_ATTR(temp3_tolerance, S_IWUSR | S_IRUGO,
915a5a4598cSMarc Hulsman 			show_temp_tolerance, store_temp_tolerance, 2),
916a5a4598cSMarc Hulsman };
917a5a4598cSMarc Hulsman 
9189873964dSCharles Spirakis /* read/write the temperature1, includes measured value and limits */
show_temp1(struct device * dev,struct device_attribute * devattr,char * buf)9199873964dSCharles Spirakis static ssize_t show_temp1(struct device *dev, struct device_attribute *devattr,
9209873964dSCharles Spirakis 				char *buf)
9219873964dSCharles Spirakis {
9229873964dSCharles Spirakis 	struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
9239873964dSCharles Spirakis 	struct w83791d_data *data = w83791d_update_device(dev);
9249873964dSCharles Spirakis 	return sprintf(buf, "%d\n", TEMP1_FROM_REG(data->temp1[attr->index]));
9259873964dSCharles Spirakis }
9269873964dSCharles Spirakis 
store_temp1(struct device * dev,struct device_attribute * devattr,const char * buf,size_t count)9279873964dSCharles Spirakis static ssize_t store_temp1(struct device *dev, struct device_attribute *devattr,
9289873964dSCharles Spirakis 				const char *buf, size_t count)
9299873964dSCharles Spirakis {
9309873964dSCharles Spirakis 	struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
9319873964dSCharles Spirakis 	struct i2c_client *client = to_i2c_client(dev);
9329873964dSCharles Spirakis 	struct w83791d_data *data = i2c_get_clientdata(client);
9339873964dSCharles Spirakis 	int nr = attr->index;
934ec1c3194SGuenter Roeck 	long val;
935ec1c3194SGuenter Roeck 	int err;
936ec1c3194SGuenter Roeck 
937ec1c3194SGuenter Roeck 	err = kstrtol(buf, 10, &val);
938ec1c3194SGuenter Roeck 	if (err)
939ec1c3194SGuenter Roeck 		return err;
9409873964dSCharles Spirakis 
9419873964dSCharles Spirakis 	mutex_lock(&data->update_lock);
9429873964dSCharles Spirakis 	data->temp1[nr] = TEMP1_TO_REG(val);
9439873964dSCharles Spirakis 	w83791d_write(client, W83791D_REG_TEMP1[nr], data->temp1[nr]);
9449873964dSCharles Spirakis 	mutex_unlock(&data->update_lock);
9459873964dSCharles Spirakis 	return count;
9469873964dSCharles Spirakis }
9479873964dSCharles Spirakis 
9489873964dSCharles Spirakis /* read/write temperature2-3, includes measured value and limits */
show_temp23(struct device * dev,struct device_attribute * devattr,char * buf)9499873964dSCharles Spirakis static ssize_t show_temp23(struct device *dev, struct device_attribute *devattr,
9509873964dSCharles Spirakis 				char *buf)
9519873964dSCharles Spirakis {
9529873964dSCharles Spirakis 	struct sensor_device_attribute_2 *attr = to_sensor_dev_attr_2(devattr);
9539873964dSCharles Spirakis 	struct w83791d_data *data = w83791d_update_device(dev);
9549873964dSCharles Spirakis 	int nr = attr->nr;
9559873964dSCharles Spirakis 	int index = attr->index;
9569873964dSCharles Spirakis 	return sprintf(buf, "%d\n", TEMP23_FROM_REG(data->temp_add[nr][index]));
9579873964dSCharles Spirakis }
9589873964dSCharles Spirakis 
store_temp23(struct device * dev,struct device_attribute * devattr,const char * buf,size_t count)9599873964dSCharles Spirakis static ssize_t store_temp23(struct device *dev,
9609873964dSCharles Spirakis 				struct device_attribute *devattr,
9619873964dSCharles Spirakis 				const char *buf, size_t count)
9629873964dSCharles Spirakis {
9639873964dSCharles Spirakis 	struct sensor_device_attribute_2 *attr = to_sensor_dev_attr_2(devattr);
9649873964dSCharles Spirakis 	struct i2c_client *client = to_i2c_client(dev);
9659873964dSCharles Spirakis 	struct w83791d_data *data = i2c_get_clientdata(client);
966ec1c3194SGuenter Roeck 	long val;
967ec1c3194SGuenter Roeck 	int err;
9689873964dSCharles Spirakis 	int nr = attr->nr;
9699873964dSCharles Spirakis 	int index = attr->index;
9709873964dSCharles Spirakis 
971ec1c3194SGuenter Roeck 	err = kstrtol(buf, 10, &val);
972ec1c3194SGuenter Roeck 	if (err)
973ec1c3194SGuenter Roeck 		return err;
974ec1c3194SGuenter Roeck 
9759873964dSCharles Spirakis 	mutex_lock(&data->update_lock);
9769873964dSCharles Spirakis 	data->temp_add[nr][index] = TEMP23_TO_REG(val);
9779873964dSCharles Spirakis 	w83791d_write(client, W83791D_REG_TEMP_ADD[nr][index * 2],
9789873964dSCharles Spirakis 				data->temp_add[nr][index] >> 8);
9799873964dSCharles Spirakis 	w83791d_write(client, W83791D_REG_TEMP_ADD[nr][index * 2 + 1],
9809873964dSCharles Spirakis 				data->temp_add[nr][index] & 0x80);
9819873964dSCharles Spirakis 	mutex_unlock(&data->update_lock);
9829873964dSCharles Spirakis 
9839873964dSCharles Spirakis 	return count;
9849873964dSCharles Spirakis }
9859873964dSCharles Spirakis 
9869873964dSCharles Spirakis static struct sensor_device_attribute_2 sda_temp_input[] = {
9879873964dSCharles Spirakis 	SENSOR_ATTR_2(temp1_input, S_IRUGO, show_temp1, NULL, 0, 0),
9889873964dSCharles Spirakis 	SENSOR_ATTR_2(temp2_input, S_IRUGO, show_temp23, NULL, 0, 0),
9899873964dSCharles Spirakis 	SENSOR_ATTR_2(temp3_input, S_IRUGO, show_temp23, NULL, 1, 0),
9909873964dSCharles Spirakis };
9919873964dSCharles Spirakis 
9929873964dSCharles Spirakis static struct sensor_device_attribute_2 sda_temp_max[] = {
9939873964dSCharles Spirakis 	SENSOR_ATTR_2(temp1_max, S_IRUGO | S_IWUSR,
9949873964dSCharles Spirakis 			show_temp1, store_temp1, 0, 1),
9959873964dSCharles Spirakis 	SENSOR_ATTR_2(temp2_max, S_IRUGO | S_IWUSR,
9969873964dSCharles Spirakis 			show_temp23, store_temp23, 0, 1),
9979873964dSCharles Spirakis 	SENSOR_ATTR_2(temp3_max, S_IRUGO | S_IWUSR,
9989873964dSCharles Spirakis 			show_temp23, store_temp23, 1, 1),
9999873964dSCharles Spirakis };
10009873964dSCharles Spirakis 
10019873964dSCharles Spirakis static struct sensor_device_attribute_2 sda_temp_max_hyst[] = {
10029873964dSCharles Spirakis 	SENSOR_ATTR_2(temp1_max_hyst, S_IRUGO | S_IWUSR,
10039873964dSCharles Spirakis 			show_temp1, store_temp1, 0, 2),
10049873964dSCharles Spirakis 	SENSOR_ATTR_2(temp2_max_hyst, S_IRUGO | S_IWUSR,
10059873964dSCharles Spirakis 			show_temp23, store_temp23, 0, 2),
10069873964dSCharles Spirakis 	SENSOR_ATTR_2(temp3_max_hyst, S_IRUGO | S_IWUSR,
10079873964dSCharles Spirakis 			show_temp23, store_temp23, 1, 2),
10089873964dSCharles Spirakis };
10099873964dSCharles Spirakis 
1010ec1c3194SGuenter Roeck /*
1011ec1c3194SGuenter Roeck  * Note: The bitmask for the beep enable/disable is different than
1012ec1c3194SGuenter Roeck  * the bitmask for the alarm.
1013ec1c3194SGuenter Roeck  */
101464383123SCharles Spirakis static struct sensor_device_attribute sda_temp_beep[] = {
101564383123SCharles Spirakis 	SENSOR_ATTR(temp1_beep, S_IWUSR | S_IRUGO, show_beep, store_beep, 4),
101664383123SCharles Spirakis 	SENSOR_ATTR(temp2_beep, S_IWUSR | S_IRUGO, show_beep, store_beep, 5),
101764383123SCharles Spirakis 	SENSOR_ATTR(temp3_beep, S_IWUSR | S_IRUGO, show_beep, store_beep, 1),
101864383123SCharles Spirakis };
101964383123SCharles Spirakis 
102064383123SCharles Spirakis static struct sensor_device_attribute sda_temp_alarm[] = {
102164383123SCharles Spirakis 	SENSOR_ATTR(temp1_alarm, S_IRUGO, show_alarm, NULL, 4),
102264383123SCharles Spirakis 	SENSOR_ATTR(temp2_alarm, S_IRUGO, show_alarm, NULL, 5),
102364383123SCharles Spirakis 	SENSOR_ATTR(temp3_alarm, S_IRUGO, show_alarm, NULL, 13),
102464383123SCharles Spirakis };
10259873964dSCharles Spirakis 
102684fb029fSLABBE Corentin /* get realtime status of all sensors items: voltage, temp, fan */
alarms_show(struct device * dev,struct device_attribute * attr,char * buf)10278d0ec428SJulia Lawall static ssize_t alarms_show(struct device *dev, struct device_attribute *attr,
10288d0ec428SJulia Lawall 			   char *buf)
10299873964dSCharles Spirakis {
10309873964dSCharles Spirakis 	struct w83791d_data *data = w83791d_update_device(dev);
10319873964dSCharles Spirakis 	return sprintf(buf, "%u\n", data->alarms);
10329873964dSCharles Spirakis }
10339873964dSCharles Spirakis 
10348d0ec428SJulia Lawall static DEVICE_ATTR_RO(alarms);
10359873964dSCharles Spirakis 
10369873964dSCharles Spirakis /* Beep control */
10379873964dSCharles Spirakis 
10389873964dSCharles Spirakis #define GLOBAL_BEEP_ENABLE_SHIFT	15
10399873964dSCharles Spirakis #define GLOBAL_BEEP_ENABLE_MASK		(1 << GLOBAL_BEEP_ENABLE_SHIFT)
10409873964dSCharles Spirakis 
show_beep_enable(struct device * dev,struct device_attribute * attr,char * buf)10419873964dSCharles Spirakis static ssize_t show_beep_enable(struct device *dev,
10429873964dSCharles Spirakis 				struct device_attribute *attr, char *buf)
10439873964dSCharles Spirakis {
10449873964dSCharles Spirakis 	struct w83791d_data *data = w83791d_update_device(dev);
10459873964dSCharles Spirakis 	return sprintf(buf, "%d\n", data->beep_enable);
10469873964dSCharles Spirakis }
10479873964dSCharles Spirakis 
show_beep_mask(struct device * dev,struct device_attribute * attr,char * buf)10489873964dSCharles Spirakis static ssize_t show_beep_mask(struct device *dev,
10499873964dSCharles Spirakis 				struct device_attribute *attr, char *buf)
10509873964dSCharles Spirakis {
10519873964dSCharles Spirakis 	struct w83791d_data *data = w83791d_update_device(dev);
10529873964dSCharles Spirakis 	return sprintf(buf, "%d\n", BEEP_MASK_FROM_REG(data->beep_mask));
10539873964dSCharles Spirakis }
10549873964dSCharles Spirakis 
10559873964dSCharles Spirakis 
store_beep_mask(struct device * dev,struct device_attribute * attr,const char * buf,size_t count)10569873964dSCharles Spirakis static ssize_t store_beep_mask(struct device *dev,
10579873964dSCharles Spirakis 				struct device_attribute *attr,
10589873964dSCharles Spirakis 				const char *buf, size_t count)
10599873964dSCharles Spirakis {
10609873964dSCharles Spirakis 	struct i2c_client *client = to_i2c_client(dev);
10619873964dSCharles Spirakis 	struct w83791d_data *data = i2c_get_clientdata(client);
10629873964dSCharles Spirakis 	int i;
1063ec1c3194SGuenter Roeck 	long val;
1064ec1c3194SGuenter Roeck 	int err;
1065ec1c3194SGuenter Roeck 
1066ec1c3194SGuenter Roeck 	err = kstrtol(buf, 10, &val);
1067ec1c3194SGuenter Roeck 	if (err)
1068ec1c3194SGuenter Roeck 		return err;
10699873964dSCharles Spirakis 
10709873964dSCharles Spirakis 	mutex_lock(&data->update_lock);
10719873964dSCharles Spirakis 
1072ec1c3194SGuenter Roeck 	/*
1073ec1c3194SGuenter Roeck 	 * The beep_enable state overrides any enabling request from
1074ec1c3194SGuenter Roeck 	 * the masks
1075ec1c3194SGuenter Roeck 	 */
10769873964dSCharles Spirakis 	data->beep_mask = BEEP_MASK_TO_REG(val) & ~GLOBAL_BEEP_ENABLE_MASK;
10779873964dSCharles Spirakis 	data->beep_mask |= (data->beep_enable << GLOBAL_BEEP_ENABLE_SHIFT);
10789873964dSCharles Spirakis 
10799873964dSCharles Spirakis 	val = data->beep_mask;
10809873964dSCharles Spirakis 
10819873964dSCharles Spirakis 	for (i = 0; i < 3; i++) {
10829873964dSCharles Spirakis 		w83791d_write(client, W83791D_REG_BEEP_CTRL[i], (val & 0xff));
10839873964dSCharles Spirakis 		val >>= 8;
10849873964dSCharles Spirakis 	}
10859873964dSCharles Spirakis 
10869873964dSCharles Spirakis 	mutex_unlock(&data->update_lock);
10879873964dSCharles Spirakis 
10889873964dSCharles Spirakis 	return count;
10899873964dSCharles Spirakis }
10909873964dSCharles Spirakis 
store_beep_enable(struct device * dev,struct device_attribute * attr,const char * buf,size_t count)10919873964dSCharles Spirakis static ssize_t store_beep_enable(struct device *dev,
10929873964dSCharles Spirakis 				struct device_attribute *attr,
10939873964dSCharles Spirakis 				const char *buf, size_t count)
10949873964dSCharles Spirakis {
10959873964dSCharles Spirakis 	struct i2c_client *client = to_i2c_client(dev);
10969873964dSCharles Spirakis 	struct w83791d_data *data = i2c_get_clientdata(client);
1097ec1c3194SGuenter Roeck 	long val;
1098ec1c3194SGuenter Roeck 	int err;
1099ec1c3194SGuenter Roeck 
1100ec1c3194SGuenter Roeck 	err = kstrtol(buf, 10, &val);
1101ec1c3194SGuenter Roeck 	if (err)
1102ec1c3194SGuenter Roeck 		return err;
11039873964dSCharles Spirakis 
11049873964dSCharles Spirakis 	mutex_lock(&data->update_lock);
11059873964dSCharles Spirakis 
11069873964dSCharles Spirakis 	data->beep_enable = val ? 1 : 0;
11079873964dSCharles Spirakis 
11089873964dSCharles Spirakis 	/* Keep the full mask value in sync with the current enable */
11099873964dSCharles Spirakis 	data->beep_mask &= ~GLOBAL_BEEP_ENABLE_MASK;
11109873964dSCharles Spirakis 	data->beep_mask |= (data->beep_enable << GLOBAL_BEEP_ENABLE_SHIFT);
11119873964dSCharles Spirakis 
1112ec1c3194SGuenter Roeck 	/*
1113ec1c3194SGuenter Roeck 	 * The global control is in the second beep control register
1114ec1c3194SGuenter Roeck 	 * so only need to update that register
1115ec1c3194SGuenter Roeck 	 */
11169873964dSCharles Spirakis 	val = (data->beep_mask >> 8) & 0xff;
11179873964dSCharles Spirakis 
11189873964dSCharles Spirakis 	w83791d_write(client, W83791D_REG_BEEP_CTRL[1], val);
11199873964dSCharles Spirakis 
11209873964dSCharles Spirakis 	mutex_unlock(&data->update_lock);
11219873964dSCharles Spirakis 
11229873964dSCharles Spirakis 	return count;
11239873964dSCharles Spirakis }
11249873964dSCharles Spirakis 
11259873964dSCharles Spirakis static struct sensor_device_attribute sda_beep_ctrl[] = {
11269873964dSCharles Spirakis 	SENSOR_ATTR(beep_enable, S_IRUGO | S_IWUSR,
11279873964dSCharles Spirakis 			show_beep_enable, store_beep_enable, 0),
11289873964dSCharles Spirakis 	SENSOR_ATTR(beep_mask, S_IRUGO | S_IWUSR,
11299873964dSCharles Spirakis 			show_beep_mask, store_beep_mask, 1)
11309873964dSCharles Spirakis };
11319873964dSCharles Spirakis 
11329873964dSCharles Spirakis /* cpu voltage regulation information */
cpu0_vid_show(struct device * dev,struct device_attribute * attr,char * buf)11338d0ec428SJulia Lawall static ssize_t cpu0_vid_show(struct device *dev,
11349873964dSCharles Spirakis 			     struct device_attribute *attr, char *buf)
11359873964dSCharles Spirakis {
11369873964dSCharles Spirakis 	struct w83791d_data *data = w83791d_update_device(dev);
11379873964dSCharles Spirakis 	return sprintf(buf, "%d\n", vid_from_reg(data->vid, data->vrm));
11389873964dSCharles Spirakis }
11399873964dSCharles Spirakis 
11408d0ec428SJulia Lawall static DEVICE_ATTR_RO(cpu0_vid);
11419873964dSCharles Spirakis 
vrm_show(struct device * dev,struct device_attribute * attr,char * buf)11428d0ec428SJulia Lawall static ssize_t vrm_show(struct device *dev, struct device_attribute *attr,
11438d0ec428SJulia Lawall 			char *buf)
11449873964dSCharles Spirakis {
114590d6619aSJean Delvare 	struct w83791d_data *data = dev_get_drvdata(dev);
11469873964dSCharles Spirakis 	return sprintf(buf, "%d\n", data->vrm);
11479873964dSCharles Spirakis }
11489873964dSCharles Spirakis 
vrm_store(struct device * dev,struct device_attribute * attr,const char * buf,size_t count)11498d0ec428SJulia Lawall static ssize_t vrm_store(struct device *dev, struct device_attribute *attr,
11509873964dSCharles Spirakis 			 const char *buf, size_t count)
11519873964dSCharles Spirakis {
11528f74efe8SJean Delvare 	struct w83791d_data *data = dev_get_drvdata(dev);
1153ec1c3194SGuenter Roeck 	unsigned long val;
1154ec1c3194SGuenter Roeck 	int err;
11559873964dSCharles Spirakis 
1156ec1c3194SGuenter Roeck 	/*
1157ec1c3194SGuenter Roeck 	 * No lock needed as vrm is internal to the driver
1158ec1c3194SGuenter Roeck 	 * (not read from a chip register) and so is not
1159ec1c3194SGuenter Roeck 	 * updated in w83791d_update_device()
1160ec1c3194SGuenter Roeck 	 */
11619873964dSCharles Spirakis 
1162ec1c3194SGuenter Roeck 	err = kstrtoul(buf, 10, &val);
1163ec1c3194SGuenter Roeck 	if (err)
1164ec1c3194SGuenter Roeck 		return err;
1165ec1c3194SGuenter Roeck 
1166fe04f24bSAxel Lin 	if (val > 255)
1167fe04f24bSAxel Lin 		return -EINVAL;
1168fe04f24bSAxel Lin 
1169ec1c3194SGuenter Roeck 	data->vrm = val;
11709873964dSCharles Spirakis 	return count;
11719873964dSCharles Spirakis }
11729873964dSCharles Spirakis 
11738d0ec428SJulia Lawall static DEVICE_ATTR_RW(vrm);
11749873964dSCharles Spirakis 
117534fc921aSJim Cromie #define IN_UNIT_ATTRS(X) \
117634fc921aSJim Cromie 	&sda_in_input[X].dev_attr.attr,	\
117734fc921aSJim Cromie 	&sda_in_min[X].dev_attr.attr,	\
117864383123SCharles Spirakis 	&sda_in_max[X].dev_attr.attr,	\
117964383123SCharles Spirakis 	&sda_in_beep[X].dev_attr.attr,	\
118064383123SCharles Spirakis 	&sda_in_alarm[X].dev_attr.attr
118134fc921aSJim Cromie 
118234fc921aSJim Cromie #define FAN_UNIT_ATTRS(X) \
118334fc921aSJim Cromie 	&sda_fan_input[X].dev_attr.attr,	\
118434fc921aSJim Cromie 	&sda_fan_min[X].dev_attr.attr,		\
118564383123SCharles Spirakis 	&sda_fan_div[X].dev_attr.attr,		\
118664383123SCharles Spirakis 	&sda_fan_beep[X].dev_attr.attr,		\
118764383123SCharles Spirakis 	&sda_fan_alarm[X].dev_attr.attr
118834fc921aSJim Cromie 
118934fc921aSJim Cromie #define TEMP_UNIT_ATTRS(X) \
119034fc921aSJim Cromie 	&sda_temp_input[X].dev_attr.attr,	\
119134fc921aSJim Cromie 	&sda_temp_max[X].dev_attr.attr,		\
119264383123SCharles Spirakis 	&sda_temp_max_hyst[X].dev_attr.attr,	\
119364383123SCharles Spirakis 	&sda_temp_beep[X].dev_attr.attr,	\
119464383123SCharles Spirakis 	&sda_temp_alarm[X].dev_attr.attr
119534fc921aSJim Cromie 
119634fc921aSJim Cromie static struct attribute *w83791d_attributes[] = {
119734fc921aSJim Cromie 	IN_UNIT_ATTRS(0),
119834fc921aSJim Cromie 	IN_UNIT_ATTRS(1),
119934fc921aSJim Cromie 	IN_UNIT_ATTRS(2),
120034fc921aSJim Cromie 	IN_UNIT_ATTRS(3),
120134fc921aSJim Cromie 	IN_UNIT_ATTRS(4),
120234fc921aSJim Cromie 	IN_UNIT_ATTRS(5),
120334fc921aSJim Cromie 	IN_UNIT_ATTRS(6),
120434fc921aSJim Cromie 	IN_UNIT_ATTRS(7),
120534fc921aSJim Cromie 	IN_UNIT_ATTRS(8),
120634fc921aSJim Cromie 	IN_UNIT_ATTRS(9),
120734fc921aSJim Cromie 	FAN_UNIT_ATTRS(0),
120834fc921aSJim Cromie 	FAN_UNIT_ATTRS(1),
120934fc921aSJim Cromie 	FAN_UNIT_ATTRS(2),
121034fc921aSJim Cromie 	TEMP_UNIT_ATTRS(0),
121134fc921aSJim Cromie 	TEMP_UNIT_ATTRS(1),
121234fc921aSJim Cromie 	TEMP_UNIT_ATTRS(2),
121334fc921aSJim Cromie 	&dev_attr_alarms.attr,
121434fc921aSJim Cromie 	&sda_beep_ctrl[0].dev_attr.attr,
121534fc921aSJim Cromie 	&sda_beep_ctrl[1].dev_attr.attr,
121634fc921aSJim Cromie 	&dev_attr_cpu0_vid.attr,
121734fc921aSJim Cromie 	&dev_attr_vrm.attr,
12186495ce18SMarc Hulsman 	&sda_pwm[0].dev_attr.attr,
12196495ce18SMarc Hulsman 	&sda_pwm[1].dev_attr.attr,
12206495ce18SMarc Hulsman 	&sda_pwm[2].dev_attr.attr,
1221b5938f8cSMarc Hulsman 	&sda_pwmenable[0].dev_attr.attr,
1222b5938f8cSMarc Hulsman 	&sda_pwmenable[1].dev_attr.attr,
1223b5938f8cSMarc Hulsman 	&sda_pwmenable[2].dev_attr.attr,
1224a5a4598cSMarc Hulsman 	&sda_temp_target[0].dev_attr.attr,
1225a5a4598cSMarc Hulsman 	&sda_temp_target[1].dev_attr.attr,
1226a5a4598cSMarc Hulsman 	&sda_temp_target[2].dev_attr.attr,
1227a5a4598cSMarc Hulsman 	&sda_temp_tolerance[0].dev_attr.attr,
1228a5a4598cSMarc Hulsman 	&sda_temp_tolerance[1].dev_attr.attr,
1229a5a4598cSMarc Hulsman 	&sda_temp_tolerance[2].dev_attr.attr,
123034fc921aSJim Cromie 	NULL
123134fc921aSJim Cromie };
123234fc921aSJim Cromie 
123334fc921aSJim Cromie static const struct attribute_group w83791d_group = {
123434fc921aSJim Cromie 	.attrs = w83791d_attributes,
123534fc921aSJim Cromie };
123634fc921aSJim Cromie 
1237ec1c3194SGuenter Roeck /*
1238ec1c3194SGuenter Roeck  * Separate group of attributes for fan/pwm 4-5. Their pins can also be
1239ec1c3194SGuenter Roeck  * in use for GPIO in which case their sysfs-interface should not be made
1240ec1c3194SGuenter Roeck  * available
1241ec1c3194SGuenter Roeck  */
12426e1ecd9bSMarc Hulsman static struct attribute *w83791d_attributes_fanpwm45[] = {
12436e1ecd9bSMarc Hulsman 	FAN_UNIT_ATTRS(3),
12446e1ecd9bSMarc Hulsman 	FAN_UNIT_ATTRS(4),
12456495ce18SMarc Hulsman 	&sda_pwm[3].dev_attr.attr,
12466495ce18SMarc Hulsman 	&sda_pwm[4].dev_attr.attr,
12476e1ecd9bSMarc Hulsman 	NULL
12486e1ecd9bSMarc Hulsman };
12496e1ecd9bSMarc Hulsman 
12506e1ecd9bSMarc Hulsman static const struct attribute_group w83791d_group_fanpwm45 = {
12516e1ecd9bSMarc Hulsman 	.attrs = w83791d_attributes_fanpwm45,
12526e1ecd9bSMarc Hulsman };
1253cb0c1af3SJean Delvare 
w83791d_detect_subclients(struct i2c_client * client)1254cb0c1af3SJean Delvare static int w83791d_detect_subclients(struct i2c_client *client)
12559873964dSCharles Spirakis {
1256cb0c1af3SJean Delvare 	struct i2c_adapter *adapter = client->adapter;
1257cb0c1af3SJean Delvare 	int address = client->addr;
1258358d2071SWolfram Sang 	int i, id;
12599873964dSCharles Spirakis 	u8 val;
12609873964dSCharles Spirakis 
12619873964dSCharles Spirakis 	id = i2c_adapter_id(adapter);
12629873964dSCharles Spirakis 	if (force_subclients[0] == id && force_subclients[1] == address) {
12639873964dSCharles Spirakis 		for (i = 2; i <= 3; i++) {
12649873964dSCharles Spirakis 			if (force_subclients[i] < 0x48 ||
12659873964dSCharles Spirakis 			    force_subclients[i] > 0x4f) {
12669873964dSCharles Spirakis 				dev_err(&client->dev,
12679873964dSCharles Spirakis 					"invalid subclient "
12689873964dSCharles Spirakis 					"address %d; must be 0x48-0x4f\n",
12699873964dSCharles Spirakis 					force_subclients[i]);
1270358d2071SWolfram Sang 				return -ENODEV;
12719873964dSCharles Spirakis 			}
12729873964dSCharles Spirakis 		}
12739873964dSCharles Spirakis 		w83791d_write(client, W83791D_REG_I2C_SUBADDR,
12749873964dSCharles Spirakis 					(force_subclients[2] & 0x07) |
12759873964dSCharles Spirakis 					((force_subclients[3] & 0x07) << 4));
12769873964dSCharles Spirakis 	}
12779873964dSCharles Spirakis 
12789873964dSCharles Spirakis 	val = w83791d_read(client, W83791D_REG_I2C_SUBADDR);
1279943c15acSNadezda Lutovinova 
1280943c15acSNadezda Lutovinova 	if (!(val & 0x88) && (val & 0x7) == ((val >> 4) & 0x7)) {
12819873964dSCharles Spirakis 		dev_err(&client->dev,
1282943c15acSNadezda Lutovinova 			"duplicate addresses 0x%x, use force_subclient\n", 0x48 + (val & 0x7));
1283358d2071SWolfram Sang 		return -ENODEV;
12849873964dSCharles Spirakis 	}
1285943c15acSNadezda Lutovinova 
1286943c15acSNadezda Lutovinova 	if (!(val & 0x08))
1287943c15acSNadezda Lutovinova 		devm_i2c_new_dummy_device(&client->dev, adapter, 0x48 + (val & 0x7));
1288943c15acSNadezda Lutovinova 
1289943c15acSNadezda Lutovinova 	if (!(val & 0x80))
1290943c15acSNadezda Lutovinova 		devm_i2c_new_dummy_device(&client->dev, adapter, 0x48 + ((val >> 4) & 0x7));
12919873964dSCharles Spirakis 
12929873964dSCharles Spirakis 	return 0;
12939873964dSCharles Spirakis }
12949873964dSCharles Spirakis 
12959873964dSCharles Spirakis 
1296cb0c1af3SJean Delvare /* Return 0 if detection is successful, -ENODEV otherwise */
w83791d_detect(struct i2c_client * client,struct i2c_board_info * info)1297310ec792SJean Delvare static int w83791d_detect(struct i2c_client *client,
1298cb0c1af3SJean Delvare 			  struct i2c_board_info *info)
12999873964dSCharles Spirakis {
1300cb0c1af3SJean Delvare 	struct i2c_adapter *adapter = client->adapter;
1301cb0c1af3SJean Delvare 	int val1, val2;
1302cb0c1af3SJean Delvare 	unsigned short address = client->addr;
13039873964dSCharles Spirakis 
1304ec1c3194SGuenter Roeck 	if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA))
1305cb0c1af3SJean Delvare 		return -ENODEV;
13069873964dSCharles Spirakis 
13073f8b8459SJean Delvare 	if (w83791d_read(client, W83791D_REG_CONFIG) & 0x80)
1308cb0c1af3SJean Delvare 		return -ENODEV;
13093f8b8459SJean Delvare 
13109873964dSCharles Spirakis 	val1 = w83791d_read(client, W83791D_REG_BANK);
13119873964dSCharles Spirakis 	val2 = w83791d_read(client, W83791D_REG_CHIPMAN);
13129873964dSCharles Spirakis 	/* Check for Winbond ID if in bank 0 */
13139873964dSCharles Spirakis 	if (!(val1 & 0x07)) {
13143f8b8459SJean Delvare 		if ((!(val1 & 0x80) && val2 != 0xa3) ||
13153f8b8459SJean Delvare 		    ((val1 & 0x80) && val2 != 0x5c)) {
1316cb0c1af3SJean Delvare 			return -ENODEV;
13179873964dSCharles Spirakis 		}
13189873964dSCharles Spirakis 	}
1319ec1c3194SGuenter Roeck 	/*
1320ec1c3194SGuenter Roeck 	 * If Winbond chip, address of chip and W83791D_REG_I2C_ADDR
1321ec1c3194SGuenter Roeck 	 * should match
1322ec1c3194SGuenter Roeck 	 */
13233f8b8459SJean Delvare 	if (w83791d_read(client, W83791D_REG_I2C_ADDR) != address)
1324cb0c1af3SJean Delvare 		return -ENODEV;
13259873964dSCharles Spirakis 
13263f8b8459SJean Delvare 	/* We want bank 0 and Vendor ID high byte */
13279873964dSCharles Spirakis 	val1 = w83791d_read(client, W83791D_REG_BANK) & 0x78;
13289873964dSCharles Spirakis 	w83791d_write(client, W83791D_REG_BANK, val1 | 0x80);
13299873964dSCharles Spirakis 
13309873964dSCharles Spirakis 	/* Verify it is a Winbond w83791d */
13319873964dSCharles Spirakis 	val1 = w83791d_read(client, W83791D_REG_WCHIPID);
13323f8b8459SJean Delvare 	val2 = w83791d_read(client, W83791D_REG_CHIPMAN);
13333f8b8459SJean Delvare 	if (val1 != 0x71 || val2 != 0x5c)
1334cb0c1af3SJean Delvare 		return -ENODEV;
13359873964dSCharles Spirakis 
1336f2f394dbSWolfram Sang 	strscpy(info->type, "w83791d", I2C_NAME_SIZE);
1337cb0c1af3SJean Delvare 
1338cb0c1af3SJean Delvare 	return 0;
13399873964dSCharles Spirakis }
13409873964dSCharles Spirakis 
w83791d_probe(struct i2c_client * client)134177b5b8a8SStephen Kitt static int w83791d_probe(struct i2c_client *client)
1342cb0c1af3SJean Delvare {
1343cb0c1af3SJean Delvare 	struct w83791d_data *data;
1344cb0c1af3SJean Delvare 	struct device *dev = &client->dev;
134516a515fdSMichael Borisov 	int i, err;
13466e1ecd9bSMarc Hulsman 	u8 has_fanpwm45;
1347cb0c1af3SJean Delvare 
13489873964dSCharles Spirakis #ifdef DEBUG
134916a515fdSMichael Borisov 	int val1;
13509873964dSCharles Spirakis 	val1 = w83791d_read(client, W83791D_REG_DID_VID4);
13519873964dSCharles Spirakis 	dev_dbg(dev, "Device ID version: %d.%d (0x%02x)\n",
13529873964dSCharles Spirakis 			(val1 >> 5) & 0x07, (val1 >> 1) & 0x0f, val1);
13539873964dSCharles Spirakis #endif
13549873964dSCharles Spirakis 
13556e13bb06SGuenter Roeck 	data = devm_kzalloc(&client->dev, sizeof(struct w83791d_data),
13566e13bb06SGuenter Roeck 			    GFP_KERNEL);
13576e13bb06SGuenter Roeck 	if (!data)
13586e13bb06SGuenter Roeck 		return -ENOMEM;
13599873964dSCharles Spirakis 
1360cb0c1af3SJean Delvare 	i2c_set_clientdata(client, data);
1361cb0c1af3SJean Delvare 	mutex_init(&data->update_lock);
1362cb0c1af3SJean Delvare 
1363cb0c1af3SJean Delvare 	err = w83791d_detect_subclients(client);
1364cb0c1af3SJean Delvare 	if (err)
13656e13bb06SGuenter Roeck 		return err;
13669873964dSCharles Spirakis 
13679873964dSCharles Spirakis 	/* Initialize the chip */
13689873964dSCharles Spirakis 	w83791d_init_client(client);
13699873964dSCharles Spirakis 
1370ec1c3194SGuenter Roeck 	/*
1371ec1c3194SGuenter Roeck 	 * If the fan_div is changed, make sure there is a rational
1372ec1c3194SGuenter Roeck 	 * fan_min in place
1373ec1c3194SGuenter Roeck 	 */
1374ec1c3194SGuenter Roeck 	for (i = 0; i < NUMBER_OF_FANIN; i++)
13759873964dSCharles Spirakis 		data->fan_min[i] = w83791d_read(client, W83791D_REG_FAN_MIN[i]);
13769873964dSCharles Spirakis 
13779873964dSCharles Spirakis 	/* Register sysfs hooks */
1378ec1c3194SGuenter Roeck 	err = sysfs_create_group(&client->dev.kobj, &w83791d_group);
1379ec1c3194SGuenter Roeck 	if (err)
1380358d2071SWolfram Sang 		return err;
138134fc921aSJim Cromie 
13826e1ecd9bSMarc Hulsman 	/* Check if pins of fan/pwm 4-5 are in use as GPIO */
13836e1ecd9bSMarc Hulsman 	has_fanpwm45 = w83791d_read(client, W83791D_REG_GPIO) & 0x10;
13846e1ecd9bSMarc Hulsman 	if (has_fanpwm45) {
13856e1ecd9bSMarc Hulsman 		err = sysfs_create_group(&client->dev.kobj,
13866e1ecd9bSMarc Hulsman 					 &w83791d_group_fanpwm45);
13876e1ecd9bSMarc Hulsman 		if (err)
13886e1ecd9bSMarc Hulsman 			goto error4;
13896e1ecd9bSMarc Hulsman 	}
13906e1ecd9bSMarc Hulsman 
139134fc921aSJim Cromie 	/* Everything is ready, now register the working device */
13921beeffe4STony Jones 	data->hwmon_dev = hwmon_device_register(dev);
13931beeffe4STony Jones 	if (IS_ERR(data->hwmon_dev)) {
13941beeffe4STony Jones 		err = PTR_ERR(data->hwmon_dev);
13956e1ecd9bSMarc Hulsman 		goto error5;
13969873964dSCharles Spirakis 	}
13979873964dSCharles Spirakis 
13989873964dSCharles Spirakis 	return 0;
13999873964dSCharles Spirakis 
14006e1ecd9bSMarc Hulsman error5:
14016e1ecd9bSMarc Hulsman 	if (has_fanpwm45)
14026e1ecd9bSMarc Hulsman 		sysfs_remove_group(&client->dev.kobj, &w83791d_group_fanpwm45);
140334fc921aSJim Cromie error4:
140434fc921aSJim Cromie 	sysfs_remove_group(&client->dev.kobj, &w83791d_group);
14059873964dSCharles Spirakis 	return err;
14069873964dSCharles Spirakis }
14079873964dSCharles Spirakis 
w83791d_remove(struct i2c_client * client)1408ed5c2f5fSUwe Kleine-König static void w83791d_remove(struct i2c_client *client)
14099873964dSCharles Spirakis {
14109873964dSCharles Spirakis 	struct w83791d_data *data = i2c_get_clientdata(client);
14119873964dSCharles Spirakis 
14121beeffe4STony Jones 	hwmon_device_unregister(data->hwmon_dev);
141334fc921aSJim Cromie 	sysfs_remove_group(&client->dev.kobj, &w83791d_group);
14149873964dSCharles Spirakis }
14159873964dSCharles Spirakis 
w83791d_init_client(struct i2c_client * client)14169873964dSCharles Spirakis static void w83791d_init_client(struct i2c_client *client)
14179873964dSCharles Spirakis {
14189873964dSCharles Spirakis 	struct w83791d_data *data = i2c_get_clientdata(client);
14199873964dSCharles Spirakis 	u8 tmp;
14209873964dSCharles Spirakis 	u8 old_beep;
14219873964dSCharles Spirakis 
1422ec1c3194SGuenter Roeck 	/*
1423ec1c3194SGuenter Roeck 	 * The difference between reset and init is that reset
1424ec1c3194SGuenter Roeck 	 * does a hard reset of the chip via index 0x40, bit 7,
1425ec1c3194SGuenter Roeck 	 * but init simply forces certain registers to have "sane"
1426ec1c3194SGuenter Roeck 	 * values. The hope is that the BIOS has done the right
1427ec1c3194SGuenter Roeck 	 * thing (which is why the default is reset=0, init=0),
1428ec1c3194SGuenter Roeck 	 * but if not, reset is the hard hammer and init
1429ec1c3194SGuenter Roeck 	 * is the soft mallet both of which are trying to whack
1430ec1c3194SGuenter Roeck 	 * things into place...
1431ec1c3194SGuenter Roeck 	 * NOTE: The data sheet makes a distinction between
1432ec1c3194SGuenter Roeck 	 * "power on defaults" and "reset by MR". As far as I can tell,
1433ec1c3194SGuenter Roeck 	 * the hard reset puts everything into a power-on state so I'm
1434ec1c3194SGuenter Roeck 	 * not sure what "reset by MR" means or how it can happen.
14359873964dSCharles Spirakis 	 */
14369873964dSCharles Spirakis 	if (reset || init) {
14379873964dSCharles Spirakis 		/* keep some BIOS settings when we... */
14389873964dSCharles Spirakis 		old_beep = w83791d_read(client, W83791D_REG_BEEP_CONFIG);
14399873964dSCharles Spirakis 
14409873964dSCharles Spirakis 		if (reset) {
14419873964dSCharles Spirakis 			/* ... reset the chip and ... */
14429873964dSCharles Spirakis 			w83791d_write(client, W83791D_REG_CONFIG, 0x80);
14439873964dSCharles Spirakis 		}
14449873964dSCharles Spirakis 
14459873964dSCharles Spirakis 		/* ... disable power-on abnormal beep */
14469873964dSCharles Spirakis 		w83791d_write(client, W83791D_REG_BEEP_CONFIG, old_beep | 0x80);
14479873964dSCharles Spirakis 
14489873964dSCharles Spirakis 		/* disable the global beep (not done by hard reset) */
14499873964dSCharles Spirakis 		tmp = w83791d_read(client, W83791D_REG_BEEP_CTRL[1]);
14509873964dSCharles Spirakis 		w83791d_write(client, W83791D_REG_BEEP_CTRL[1], tmp & 0xef);
14519873964dSCharles Spirakis 
14529873964dSCharles Spirakis 		if (init) {
14539873964dSCharles Spirakis 			/* Make sure monitoring is turned on for add-ons */
14549873964dSCharles Spirakis 			tmp = w83791d_read(client, W83791D_REG_TEMP2_CONFIG);
14559873964dSCharles Spirakis 			if (tmp & 1) {
14569873964dSCharles Spirakis 				w83791d_write(client, W83791D_REG_TEMP2_CONFIG,
14579873964dSCharles Spirakis 					tmp & 0xfe);
14589873964dSCharles Spirakis 			}
14599873964dSCharles Spirakis 
14609873964dSCharles Spirakis 			tmp = w83791d_read(client, W83791D_REG_TEMP3_CONFIG);
14619873964dSCharles Spirakis 			if (tmp & 1) {
14629873964dSCharles Spirakis 				w83791d_write(client, W83791D_REG_TEMP3_CONFIG,
14639873964dSCharles Spirakis 					tmp & 0xfe);
14649873964dSCharles Spirakis 			}
14659873964dSCharles Spirakis 
14669873964dSCharles Spirakis 			/* Start monitoring */
14679873964dSCharles Spirakis 			tmp = w83791d_read(client, W83791D_REG_CONFIG) & 0xf7;
14689873964dSCharles Spirakis 			w83791d_write(client, W83791D_REG_CONFIG, tmp | 0x01);
14699873964dSCharles Spirakis 		}
14709873964dSCharles Spirakis 	}
14719873964dSCharles Spirakis 
14729873964dSCharles Spirakis 	data->vrm = vid_which_vrm();
14739873964dSCharles Spirakis }
14749873964dSCharles Spirakis 
w83791d_update_device(struct device * dev)14759873964dSCharles Spirakis static struct w83791d_data *w83791d_update_device(struct device *dev)
14769873964dSCharles Spirakis {
14779873964dSCharles Spirakis 	struct i2c_client *client = to_i2c_client(dev);
14789873964dSCharles Spirakis 	struct w83791d_data *data = i2c_get_clientdata(client);
14799873964dSCharles Spirakis 	int i, j;
14809873964dSCharles Spirakis 	u8 reg_array_tmp[3];
1481ad02ad85SMarc Hulsman 	u8 vbat_reg;
14829873964dSCharles Spirakis 
14839873964dSCharles Spirakis 	mutex_lock(&data->update_lock);
14849873964dSCharles Spirakis 
14859873964dSCharles Spirakis 	if (time_after(jiffies, data->last_updated + (HZ * 3))
14869873964dSCharles Spirakis 			|| !data->valid) {
14879873964dSCharles Spirakis 		dev_dbg(dev, "Starting w83791d device update\n");
14889873964dSCharles Spirakis 
14899873964dSCharles Spirakis 		/* Update the voltages measured value and limits */
14909873964dSCharles Spirakis 		for (i = 0; i < NUMBER_OF_VIN; i++) {
14919873964dSCharles Spirakis 			data->in[i] = w83791d_read(client,
14929873964dSCharles Spirakis 						W83791D_REG_IN[i]);
14939873964dSCharles Spirakis 			data->in_max[i] = w83791d_read(client,
14949873964dSCharles Spirakis 						W83791D_REG_IN_MAX[i]);
14959873964dSCharles Spirakis 			data->in_min[i] = w83791d_read(client,
14969873964dSCharles Spirakis 						W83791D_REG_IN_MIN[i]);
14979873964dSCharles Spirakis 		}
14989873964dSCharles Spirakis 
14999873964dSCharles Spirakis 		/* Update the fan counts and limits */
15009873964dSCharles Spirakis 		for (i = 0; i < NUMBER_OF_FANIN; i++) {
15019873964dSCharles Spirakis 			/* Update the Fan measured value and limits */
15029873964dSCharles Spirakis 			data->fan[i] = w83791d_read(client,
15039873964dSCharles Spirakis 						W83791D_REG_FAN[i]);
15049873964dSCharles Spirakis 			data->fan_min[i] = w83791d_read(client,
15059873964dSCharles Spirakis 						W83791D_REG_FAN_MIN[i]);
15069873964dSCharles Spirakis 		}
15079873964dSCharles Spirakis 
15089873964dSCharles Spirakis 		/* Update the fan divisor */
15099873964dSCharles Spirakis 		for (i = 0; i < 3; i++) {
15109873964dSCharles Spirakis 			reg_array_tmp[i] = w83791d_read(client,
15119873964dSCharles Spirakis 						W83791D_REG_FAN_DIV[i]);
15129873964dSCharles Spirakis 		}
15139873964dSCharles Spirakis 		data->fan_div[0] = (reg_array_tmp[0] >> 4) & 0x03;
15149873964dSCharles Spirakis 		data->fan_div[1] = (reg_array_tmp[0] >> 6) & 0x03;
15159873964dSCharles Spirakis 		data->fan_div[2] = (reg_array_tmp[1] >> 6) & 0x03;
15169873964dSCharles Spirakis 		data->fan_div[3] = reg_array_tmp[2] & 0x07;
15179873964dSCharles Spirakis 		data->fan_div[4] = (reg_array_tmp[2] >> 4) & 0x07;
15189873964dSCharles Spirakis 
1519ec1c3194SGuenter Roeck 		/*
1520ec1c3194SGuenter Roeck 		 * The fan divisor for fans 0-2 get bit 2 from
1521ec1c3194SGuenter Roeck 		 * bits 5-7 respectively of vbat register
1522ec1c3194SGuenter Roeck 		 */
1523ad02ad85SMarc Hulsman 		vbat_reg = w83791d_read(client, W83791D_REG_VBAT);
1524ad02ad85SMarc Hulsman 		for (i = 0; i < 3; i++)
1525ad02ad85SMarc Hulsman 			data->fan_div[i] |= (vbat_reg >> (3 + i)) & 0x04;
1526ad02ad85SMarc Hulsman 
15276495ce18SMarc Hulsman 		/* Update PWM duty cycle */
15286495ce18SMarc Hulsman 		for (i = 0; i < NUMBER_OF_PWM; i++) {
15296495ce18SMarc Hulsman 			data->pwm[i] =  w83791d_read(client,
15306495ce18SMarc Hulsman 						W83791D_REG_PWM[i]);
15316495ce18SMarc Hulsman 		}
15326495ce18SMarc Hulsman 
1533b5938f8cSMarc Hulsman 		/* Update PWM enable status */
1534b5938f8cSMarc Hulsman 		for (i = 0; i < 2; i++) {
1535b5938f8cSMarc Hulsman 			reg_array_tmp[i] = w83791d_read(client,
1536b5938f8cSMarc Hulsman 						W83791D_REG_FAN_CFG[i]);
1537b5938f8cSMarc Hulsman 		}
1538b5938f8cSMarc Hulsman 		data->pwm_enable[0] = (reg_array_tmp[0] >> 2) & 0x03;
1539b5938f8cSMarc Hulsman 		data->pwm_enable[1] = (reg_array_tmp[0] >> 4) & 0x03;
1540b5938f8cSMarc Hulsman 		data->pwm_enable[2] = (reg_array_tmp[1] >> 2) & 0x03;
1541b5938f8cSMarc Hulsman 
1542a5a4598cSMarc Hulsman 		/* Update PWM target temperature */
1543a5a4598cSMarc Hulsman 		for (i = 0; i < 3; i++) {
1544a5a4598cSMarc Hulsman 			data->temp_target[i] = w83791d_read(client,
1545a5a4598cSMarc Hulsman 				W83791D_REG_TEMP_TARGET[i]) & 0x7f;
1546a5a4598cSMarc Hulsman 		}
1547a5a4598cSMarc Hulsman 
1548a5a4598cSMarc Hulsman 		/* Update PWM temperature tolerance */
1549a5a4598cSMarc Hulsman 		for (i = 0; i < 2; i++) {
1550a5a4598cSMarc Hulsman 			reg_array_tmp[i] = w83791d_read(client,
1551a5a4598cSMarc Hulsman 					W83791D_REG_TEMP_TOL[i]);
1552a5a4598cSMarc Hulsman 		}
1553a5a4598cSMarc Hulsman 		data->temp_tolerance[0] = reg_array_tmp[0] & 0x0f;
1554a5a4598cSMarc Hulsman 		data->temp_tolerance[1] = (reg_array_tmp[0] >> 4) & 0x0f;
1555a5a4598cSMarc Hulsman 		data->temp_tolerance[2] = reg_array_tmp[1] & 0x0f;
1556a5a4598cSMarc Hulsman 
15579873964dSCharles Spirakis 		/* Update the first temperature sensor */
15589873964dSCharles Spirakis 		for (i = 0; i < 3; i++) {
15599873964dSCharles Spirakis 			data->temp1[i] = w83791d_read(client,
15609873964dSCharles Spirakis 						W83791D_REG_TEMP1[i]);
15619873964dSCharles Spirakis 		}
15629873964dSCharles Spirakis 
15639873964dSCharles Spirakis 		/* Update the rest of the temperature sensors */
15649873964dSCharles Spirakis 		for (i = 0; i < 2; i++) {
15659873964dSCharles Spirakis 			for (j = 0; j < 3; j++) {
15669873964dSCharles Spirakis 				data->temp_add[i][j] =
15679873964dSCharles Spirakis 					(w83791d_read(client,
15689873964dSCharles Spirakis 					W83791D_REG_TEMP_ADD[i][j * 2]) << 8) |
15699873964dSCharles Spirakis 					w83791d_read(client,
15709873964dSCharles Spirakis 					W83791D_REG_TEMP_ADD[i][j * 2 + 1]);
15719873964dSCharles Spirakis 			}
15729873964dSCharles Spirakis 		}
15739873964dSCharles Spirakis 
15749873964dSCharles Spirakis 		/* Update the realtime status */
15759873964dSCharles Spirakis 		data->alarms =
15769873964dSCharles Spirakis 			w83791d_read(client, W83791D_REG_ALARM1) +
15779873964dSCharles Spirakis 			(w83791d_read(client, W83791D_REG_ALARM2) << 8) +
15789873964dSCharles Spirakis 			(w83791d_read(client, W83791D_REG_ALARM3) << 16);
15799873964dSCharles Spirakis 
15809873964dSCharles Spirakis 		/* Update the beep configuration information */
15819873964dSCharles Spirakis 		data->beep_mask =
15829873964dSCharles Spirakis 			w83791d_read(client, W83791D_REG_BEEP_CTRL[0]) +
15839873964dSCharles Spirakis 			(w83791d_read(client, W83791D_REG_BEEP_CTRL[1]) << 8) +
15849873964dSCharles Spirakis 			(w83791d_read(client, W83791D_REG_BEEP_CTRL[2]) << 16);
15859873964dSCharles Spirakis 
1586125751cbSCharles Spirakis 		/* Extract global beep enable flag */
15879873964dSCharles Spirakis 		data->beep_enable =
15889873964dSCharles Spirakis 			(data->beep_mask >> GLOBAL_BEEP_ENABLE_SHIFT) & 0x01;
15899873964dSCharles Spirakis 
15909873964dSCharles Spirakis 		/* Update the cpu voltage information */
15919873964dSCharles Spirakis 		i = w83791d_read(client, W83791D_REG_VID_FANDIV);
15929873964dSCharles Spirakis 		data->vid = i & 0x0f;
15939873964dSCharles Spirakis 		data->vid |= (w83791d_read(client, W83791D_REG_DID_VID4) & 0x01)
15949873964dSCharles Spirakis 				<< 4;
15959873964dSCharles Spirakis 
15969873964dSCharles Spirakis 		data->last_updated = jiffies;
1597952a11caSPaul Fertser 		data->valid = true;
15989873964dSCharles Spirakis 	}
15999873964dSCharles Spirakis 
16009873964dSCharles Spirakis 	mutex_unlock(&data->update_lock);
16019873964dSCharles Spirakis 
16029873964dSCharles Spirakis #ifdef DEBUG
16039873964dSCharles Spirakis 	w83791d_print_debug(data, dev);
16049873964dSCharles Spirakis #endif
16059873964dSCharles Spirakis 
16069873964dSCharles Spirakis 	return data;
16079873964dSCharles Spirakis }
16089873964dSCharles Spirakis 
16099873964dSCharles Spirakis #ifdef DEBUG
w83791d_print_debug(struct w83791d_data * data,struct device * dev)16109873964dSCharles Spirakis static void w83791d_print_debug(struct w83791d_data *data, struct device *dev)
16119873964dSCharles Spirakis {
16129873964dSCharles Spirakis 	int i = 0, j = 0;
16139873964dSCharles Spirakis 
16149873964dSCharles Spirakis 	dev_dbg(dev, "======Start of w83791d debug values======\n");
16159873964dSCharles Spirakis 	dev_dbg(dev, "%d set of Voltages: ===>\n", NUMBER_OF_VIN);
16169873964dSCharles Spirakis 	for (i = 0; i < NUMBER_OF_VIN; i++) {
16179873964dSCharles Spirakis 		dev_dbg(dev, "vin[%d] is:     0x%02x\n", i, data->in[i]);
16189873964dSCharles Spirakis 		dev_dbg(dev, "vin[%d] min is: 0x%02x\n", i, data->in_min[i]);
16199873964dSCharles Spirakis 		dev_dbg(dev, "vin[%d] max is: 0x%02x\n", i, data->in_max[i]);
16209873964dSCharles Spirakis 	}
16219873964dSCharles Spirakis 	dev_dbg(dev, "%d set of Fan Counts/Divisors: ===>\n", NUMBER_OF_FANIN);
16229873964dSCharles Spirakis 	for (i = 0; i < NUMBER_OF_FANIN; i++) {
16239873964dSCharles Spirakis 		dev_dbg(dev, "fan[%d] is:     0x%02x\n", i, data->fan[i]);
16249873964dSCharles Spirakis 		dev_dbg(dev, "fan[%d] min is: 0x%02x\n", i, data->fan_min[i]);
16259873964dSCharles Spirakis 		dev_dbg(dev, "fan_div[%d] is: 0x%02x\n", i, data->fan_div[i]);
16269873964dSCharles Spirakis 	}
16279873964dSCharles Spirakis 
1628ec1c3194SGuenter Roeck 	/*
1629ec1c3194SGuenter Roeck 	 * temperature math is signed, but only print out the
1630ec1c3194SGuenter Roeck 	 * bits that matter
1631ec1c3194SGuenter Roeck 	 */
16329873964dSCharles Spirakis 	dev_dbg(dev, "%d set of Temperatures: ===>\n", NUMBER_OF_TEMPIN);
1633ec1c3194SGuenter Roeck 	for (i = 0; i < 3; i++)
16349873964dSCharles Spirakis 		dev_dbg(dev, "temp1[%d] is: 0x%02x\n", i, (u8) data->temp1[i]);
16359873964dSCharles Spirakis 	for (i = 0; i < 2; i++) {
16369873964dSCharles Spirakis 		for (j = 0; j < 3; j++) {
16379873964dSCharles Spirakis 			dev_dbg(dev, "temp_add[%d][%d] is: 0x%04x\n", i, j,
16389873964dSCharles Spirakis 				(u16) data->temp_add[i][j]);
16399873964dSCharles Spirakis 		}
16409873964dSCharles Spirakis 	}
16419873964dSCharles Spirakis 
16429873964dSCharles Spirakis 	dev_dbg(dev, "Misc Information: ===>\n");
16439873964dSCharles Spirakis 	dev_dbg(dev, "alarm is:     0x%08x\n", data->alarms);
16449873964dSCharles Spirakis 	dev_dbg(dev, "beep_mask is: 0x%08x\n", data->beep_mask);
16459873964dSCharles Spirakis 	dev_dbg(dev, "beep_enable is: %d\n", data->beep_enable);
16469873964dSCharles Spirakis 	dev_dbg(dev, "vid is: 0x%02x\n", data->vid);
16479873964dSCharles Spirakis 	dev_dbg(dev, "vrm is: 0x%02x\n", data->vrm);
16489873964dSCharles Spirakis 	dev_dbg(dev, "=======End of w83791d debug values========\n");
16499873964dSCharles Spirakis 	dev_dbg(dev, "\n");
16509873964dSCharles Spirakis }
16519873964dSCharles Spirakis #endif
16529873964dSCharles Spirakis 
1653f0967eeaSAxel Lin module_i2c_driver(w83791d_driver);
16549873964dSCharles Spirakis 
16559873964dSCharles Spirakis MODULE_AUTHOR("Charles Spirakis <bezaur@gmail.com>");
16569873964dSCharles Spirakis MODULE_DESCRIPTION("W83791D driver");
16579873964dSCharles Spirakis MODULE_LICENSE("GPL");
1658