xref: /openbmc/linux/drivers/hwmon/adm1026.c (revision 2612e3bbc0386368a850140a6c9b990cd496a5ec)
174ba9207SThomas Gleixner // SPDX-License-Identifier: GPL-2.0-or-later
28d5d45fbSJean Delvare /*
386aa3e22SGuenter Roeck  * adm1026.c - Part of lm_sensors, Linux kernel modules for hardware
486aa3e22SGuenter Roeck  *	       monitoring
586aa3e22SGuenter Roeck  * Copyright (C) 2002, 2003  Philip Pokorny <ppokorny@penguincomputing.com>
686aa3e22SGuenter Roeck  * Copyright (C) 2004 Justin Thiessen <jthiessen@penguincomputing.com>
786aa3e22SGuenter Roeck  *
886aa3e22SGuenter Roeck  * Chip details at:
986aa3e22SGuenter Roeck  *
10ad736c1aSAlexander A. Klimov  * <https://www.onsemi.com/PowerSolutions/product.do?id=ADM1026>
118d5d45fbSJean Delvare  */
128d5d45fbSJean Delvare 
138d5d45fbSJean Delvare #include <linux/module.h>
148d5d45fbSJean Delvare #include <linux/init.h>
158d5d45fbSJean Delvare #include <linux/slab.h>
168d5d45fbSJean Delvare #include <linux/jiffies.h>
178d5d45fbSJean Delvare #include <linux/i2c.h>
18943b0830SMark M. Hoffman #include <linux/hwmon.h>
19303760b4SJean Delvare #include <linux/hwmon-sysfs.h>
20303760b4SJean Delvare #include <linux/hwmon-vid.h>
21943b0830SMark M. Hoffman #include <linux/err.h>
229a61bf63SIngo Molnar #include <linux/mutex.h>
238d5d45fbSJean Delvare 
248d5d45fbSJean Delvare /* Addresses to scan */
2525e9c86dSMark M. Hoffman static const unsigned short normal_i2c[] = { 0x2c, 0x2d, 0x2e, I2C_CLIENT_END };
268d5d45fbSJean Delvare 
278d5d45fbSJean Delvare static int gpio_input[17] = { -1, -1, -1, -1, -1, -1, -1, -1, -1,
288d5d45fbSJean Delvare 				-1, -1, -1, -1, -1, -1, -1, -1 };
298d5d45fbSJean Delvare static int gpio_output[17] = { -1, -1, -1, -1, -1, -1, -1, -1, -1,
308d5d45fbSJean Delvare 				-1, -1, -1, -1, -1, -1, -1, -1 };
318d5d45fbSJean Delvare static int gpio_inverted[17] = { -1, -1, -1, -1, -1, -1, -1, -1, -1,
328d5d45fbSJean Delvare 				-1, -1, -1, -1, -1, -1, -1, -1 };
338d5d45fbSJean Delvare static int gpio_normal[17] = { -1, -1, -1, -1, -1, -1, -1, -1, -1,
348d5d45fbSJean Delvare 				-1, -1, -1, -1, -1, -1, -1, -1 };
358d5d45fbSJean Delvare static int gpio_fan[8] = { -1, -1, -1, -1, -1, -1, -1, -1 };
368d5d45fbSJean Delvare module_param_array(gpio_input, int, NULL, 0);
378d5d45fbSJean Delvare MODULE_PARM_DESC(gpio_input, "List of GPIO pins (0-16) to program as inputs");
388d5d45fbSJean Delvare module_param_array(gpio_output, int, NULL, 0);
39b55f3757SGuenter Roeck MODULE_PARM_DESC(gpio_output,
40b55f3757SGuenter Roeck 		 "List of GPIO pins (0-16) to program as outputs");
418d5d45fbSJean Delvare module_param_array(gpio_inverted, int, NULL, 0);
42b55f3757SGuenter Roeck MODULE_PARM_DESC(gpio_inverted,
43b55f3757SGuenter Roeck 		 "List of GPIO pins (0-16) to program as inverted");
448d5d45fbSJean Delvare module_param_array(gpio_normal, int, NULL, 0);
45b55f3757SGuenter Roeck MODULE_PARM_DESC(gpio_normal,
46b55f3757SGuenter Roeck 		 "List of GPIO pins (0-16) to program as normal/non-inverted");
478d5d45fbSJean Delvare module_param_array(gpio_fan, int, NULL, 0);
488d5d45fbSJean Delvare MODULE_PARM_DESC(gpio_fan, "List of GPIO pins (0-7) to program as fan tachs");
498d5d45fbSJean Delvare 
508d5d45fbSJean Delvare /* Many ADM1026 constants specified below */
518d5d45fbSJean Delvare 
528d5d45fbSJean Delvare /* The ADM1026 registers */
538d5d45fbSJean Delvare #define ADM1026_REG_CONFIG1	0x00
548d5d45fbSJean Delvare #define CFG1_MONITOR		0x01
558d5d45fbSJean Delvare #define CFG1_INT_ENABLE		0x02
568d5d45fbSJean Delvare #define CFG1_INT_CLEAR		0x04
578d5d45fbSJean Delvare #define CFG1_AIN8_9		0x08
588d5d45fbSJean Delvare #define CFG1_THERM_HOT		0x10
598d5d45fbSJean Delvare #define CFG1_DAC_AFC		0x20
608d5d45fbSJean Delvare #define CFG1_PWM_AFC		0x40
618d5d45fbSJean Delvare #define CFG1_RESET		0x80
62cb01a231SJean Delvare 
638d5d45fbSJean Delvare #define ADM1026_REG_CONFIG2	0x01
648d5d45fbSJean Delvare /* CONFIG2 controls FAN0/GPIO0 through FAN7/GPIO7 */
65cb01a231SJean Delvare 
668d5d45fbSJean Delvare #define ADM1026_REG_CONFIG3	0x07
678d5d45fbSJean Delvare #define CFG3_GPIO16_ENABLE	0x01
688d5d45fbSJean Delvare #define CFG3_CI_CLEAR		0x02
698d5d45fbSJean Delvare #define CFG3_VREF_250		0x04
708d5d45fbSJean Delvare #define CFG3_GPIO16_DIR		0x40
718d5d45fbSJean Delvare #define CFG3_GPIO16_POL		0x80
72cb01a231SJean Delvare 
738d5d45fbSJean Delvare #define ADM1026_REG_E2CONFIG	0x13
748d5d45fbSJean Delvare #define E2CFG_READ		0x01
758d5d45fbSJean Delvare #define E2CFG_WRITE		0x02
768d5d45fbSJean Delvare #define E2CFG_ERASE		0x04
778d5d45fbSJean Delvare #define E2CFG_ROM		0x08
788d5d45fbSJean Delvare #define E2CFG_CLK_EXT		0x80
798d5d45fbSJean Delvare 
8086aa3e22SGuenter Roeck /*
8186aa3e22SGuenter Roeck  * There are 10 general analog inputs and 7 dedicated inputs
828d5d45fbSJean Delvare  * They are:
838d5d45fbSJean Delvare  *    0 - 9  =  AIN0 - AIN9
848d5d45fbSJean Delvare  *       10  =  Vbat
858d5d45fbSJean Delvare  *       11  =  3.3V Standby
868d5d45fbSJean Delvare  *       12  =  3.3V Main
878d5d45fbSJean Delvare  *       13  =  +5V
888d5d45fbSJean Delvare  *       14  =  Vccp (CPU core voltage)
898d5d45fbSJean Delvare  *       15  =  +12V
908d5d45fbSJean Delvare  *       16  =  -12V
918d5d45fbSJean Delvare  */
928d5d45fbSJean Delvare static u16 ADM1026_REG_IN[] = {
938d5d45fbSJean Delvare 		0x30, 0x31, 0x32, 0x33, 0x34, 0x35,
948d5d45fbSJean Delvare 		0x36, 0x37, 0x27, 0x29, 0x26, 0x2a,
958d5d45fbSJean Delvare 		0x2b, 0x2c, 0x2d, 0x2e, 0x2f
968d5d45fbSJean Delvare 	};
978d5d45fbSJean Delvare static u16 ADM1026_REG_IN_MIN[] = {
988d5d45fbSJean Delvare 		0x58, 0x59, 0x5a, 0x5b, 0x5c, 0x5d,
998d5d45fbSJean Delvare 		0x5e, 0x5f, 0x6d, 0x49, 0x6b, 0x4a,
1008d5d45fbSJean Delvare 		0x4b, 0x4c, 0x4d, 0x4e, 0x4f
1018d5d45fbSJean Delvare 	};
1028d5d45fbSJean Delvare static u16 ADM1026_REG_IN_MAX[] = {
1038d5d45fbSJean Delvare 		0x50, 0x51, 0x52, 0x53, 0x54, 0x55,
1048d5d45fbSJean Delvare 		0x56, 0x57, 0x6c, 0x41, 0x6a, 0x42,
1058d5d45fbSJean Delvare 		0x43, 0x44, 0x45, 0x46, 0x47
1068d5d45fbSJean Delvare 	};
1078d5d45fbSJean Delvare 
10886aa3e22SGuenter Roeck /*
10986aa3e22SGuenter Roeck  * Temperatures are:
1108d5d45fbSJean Delvare  *    0 - Internal
1118d5d45fbSJean Delvare  *    1 - External 1
1128d5d45fbSJean Delvare  *    2 - External 2
1138d5d45fbSJean Delvare  */
1148d5d45fbSJean Delvare static u16 ADM1026_REG_TEMP[] = { 0x1f, 0x28, 0x29 };
1158d5d45fbSJean Delvare static u16 ADM1026_REG_TEMP_MIN[] = { 0x69, 0x48, 0x49 };
1168d5d45fbSJean Delvare static u16 ADM1026_REG_TEMP_MAX[] = { 0x68, 0x40, 0x41 };
1178d5d45fbSJean Delvare static u16 ADM1026_REG_TEMP_TMIN[] = { 0x10, 0x11, 0x12 };
1188d5d45fbSJean Delvare static u16 ADM1026_REG_TEMP_THERM[] = { 0x0d, 0x0e, 0x0f };
1198d5d45fbSJean Delvare static u16 ADM1026_REG_TEMP_OFFSET[] = { 0x1e, 0x6e, 0x6f };
1208d5d45fbSJean Delvare 
1218d5d45fbSJean Delvare #define ADM1026_REG_FAN(nr)		(0x38 + (nr))
1228d5d45fbSJean Delvare #define ADM1026_REG_FAN_MIN(nr)		(0x60 + (nr))
1238d5d45fbSJean Delvare #define ADM1026_REG_FAN_DIV_0_3		0x02
1248d5d45fbSJean Delvare #define ADM1026_REG_FAN_DIV_4_7		0x03
1258d5d45fbSJean Delvare 
1268d5d45fbSJean Delvare #define ADM1026_REG_DAC			0x04
1278d5d45fbSJean Delvare #define ADM1026_REG_PWM			0x05
1288d5d45fbSJean Delvare 
1298d5d45fbSJean Delvare #define ADM1026_REG_GPIO_CFG_0_3	0x08
1308d5d45fbSJean Delvare #define ADM1026_REG_GPIO_CFG_4_7	0x09
1318d5d45fbSJean Delvare #define ADM1026_REG_GPIO_CFG_8_11	0x0a
1328d5d45fbSJean Delvare #define ADM1026_REG_GPIO_CFG_12_15	0x0b
1338d5d45fbSJean Delvare /* CFG_16 in REG_CFG3 */
1348d5d45fbSJean Delvare #define ADM1026_REG_GPIO_STATUS_0_7	0x24
1358d5d45fbSJean Delvare #define ADM1026_REG_GPIO_STATUS_8_15	0x25
1368d5d45fbSJean Delvare /* STATUS_16 in REG_STATUS4 */
1378d5d45fbSJean Delvare #define ADM1026_REG_GPIO_MASK_0_7	0x1c
1388d5d45fbSJean Delvare #define ADM1026_REG_GPIO_MASK_8_15	0x1d
1398d5d45fbSJean Delvare /* MASK_16 in REG_MASK4 */
1408d5d45fbSJean Delvare 
1418d5d45fbSJean Delvare #define ADM1026_REG_COMPANY		0x16
1428d5d45fbSJean Delvare #define ADM1026_REG_VERSTEP		0x17
1438d5d45fbSJean Delvare /* These are the recognized values for the above regs */
1448d5d45fbSJean Delvare #define ADM1026_COMPANY_ANALOG_DEV	0x41
1458d5d45fbSJean Delvare #define ADM1026_VERSTEP_GENERIC		0x40
1468d5d45fbSJean Delvare #define ADM1026_VERSTEP_ADM1026		0x44
1478d5d45fbSJean Delvare 
1488d5d45fbSJean Delvare #define ADM1026_REG_MASK1		0x18
1498d5d45fbSJean Delvare #define ADM1026_REG_MASK2		0x19
1508d5d45fbSJean Delvare #define ADM1026_REG_MASK3		0x1a
1518d5d45fbSJean Delvare #define ADM1026_REG_MASK4		0x1b
1528d5d45fbSJean Delvare 
1538d5d45fbSJean Delvare #define ADM1026_REG_STATUS1		0x20
1548d5d45fbSJean Delvare #define ADM1026_REG_STATUS2		0x21
1558d5d45fbSJean Delvare #define ADM1026_REG_STATUS3		0x22
1568d5d45fbSJean Delvare #define ADM1026_REG_STATUS4		0x23
1578d5d45fbSJean Delvare 
1588d5d45fbSJean Delvare #define ADM1026_FAN_ACTIVATION_TEMP_HYST -6
1598d5d45fbSJean Delvare #define ADM1026_FAN_CONTROL_TEMP_RANGE	20
1608d5d45fbSJean Delvare #define ADM1026_PWM_MAX			255
1618d5d45fbSJean Delvare 
16286aa3e22SGuenter Roeck /*
16386aa3e22SGuenter Roeck  * Conversions. Rounding and limit checking is only done on the TO_REG
1648d5d45fbSJean Delvare  * variants. Note that you should be a bit careful with which arguments
1658d5d45fbSJean Delvare  * these macros are called: arguments may be evaluated more than once.
1668d5d45fbSJean Delvare  */
1678d5d45fbSJean Delvare 
16886aa3e22SGuenter Roeck /*
16986aa3e22SGuenter Roeck  * IN are scaled according to built-in resistors.  These are the
1708d5d45fbSJean Delvare  *   voltages corresponding to 3/4 of full scale (192 or 0xc0)
1718d5d45fbSJean Delvare  *   NOTE: The -12V input needs an additional factor to account
1728d5d45fbSJean Delvare  *      for the Vref pullup resistor.
1738d5d45fbSJean Delvare  *      NEG12_OFFSET = SCALE * Vref / V-192 - Vref
1748d5d45fbSJean Delvare  *                   = 13875 * 2.50 / 1.875 - 2500
1758d5d45fbSJean Delvare  *                   = 16000
1768d5d45fbSJean Delvare  *
1778d5d45fbSJean Delvare  * The values in this table are based on Table II, page 15 of the
1788d5d45fbSJean Delvare  *    datasheet.
1798d5d45fbSJean Delvare  */
1808d5d45fbSJean Delvare static int adm1026_scaling[] = { /* .001 Volts */
1818d5d45fbSJean Delvare 		2250, 2250, 2250, 2250, 2250, 2250,
1828d5d45fbSJean Delvare 		1875, 1875, 1875, 1875, 3000, 3330,
1838d5d45fbSJean Delvare 		3330, 4995, 2250, 12000, 13875
1848d5d45fbSJean Delvare 	};
1858d5d45fbSJean Delvare #define NEG12_OFFSET  16000
1868d5d45fbSJean Delvare #define SCALE(val, from, to) (((val)*(to) + ((from)/2))/(from))
187f1b9baa9SGuenter Roeck #define INS_TO_REG(n, val)	\
188f1b9baa9SGuenter Roeck 		SCALE(clamp_val(val, 0, 255 * adm1026_scaling[n] / 192), \
189f1b9baa9SGuenter Roeck 		      adm1026_scaling[n], 192)
1908d5d45fbSJean Delvare #define INS_FROM_REG(n, val) (SCALE(val, 192, adm1026_scaling[n]))
1918d5d45fbSJean Delvare 
19286aa3e22SGuenter Roeck /*
19386aa3e22SGuenter Roeck  * FAN speed is measured using 22.5kHz clock and counts for 2 pulses
1948d5d45fbSJean Delvare  *   and we assume a 2 pulse-per-rev fan tach signal
1958d5d45fbSJean Delvare  *      22500 kHz * 60 (sec/min) * 2 (pulse) / 2 (pulse/rev) == 1350000
1968d5d45fbSJean Delvare  */
197cb01a231SJean Delvare #define FAN_TO_REG(val, div)  ((val) <= 0 ? 0xff : \
1982a844c14SGuenter Roeck 				clamp_val(1350000 / ((val) * (div)), \
19986aa3e22SGuenter Roeck 					      1, 254))
200cb01a231SJean Delvare #define FAN_FROM_REG(val, div) ((val) == 0 ? -1 : (val) == 0xff ? 0 : \
201cb01a231SJean Delvare 				1350000 / ((val) * (div)))
2028d5d45fbSJean Delvare #define DIV_FROM_REG(val) (1 << (val))
2038d5d45fbSJean Delvare #define DIV_TO_REG(val) ((val) >= 8 ? 3 : (val) >= 4 ? 2 : (val) >= 2 ? 1 : 0)
2048d5d45fbSJean Delvare 
2058d5d45fbSJean Delvare /* Temperature is reported in 1 degC increments */
206f1b9baa9SGuenter Roeck #define TEMP_TO_REG(val) DIV_ROUND_CLOSEST(clamp_val(val, -128000, 127000), \
207f1b9baa9SGuenter Roeck 					   1000)
2088d5d45fbSJean Delvare #define TEMP_FROM_REG(val) ((val) * 1000)
209f1b9baa9SGuenter Roeck #define OFFSET_TO_REG(val) DIV_ROUND_CLOSEST(clamp_val(val, -128000, 127000), \
210f1b9baa9SGuenter Roeck 					     1000)
2118d5d45fbSJean Delvare #define OFFSET_FROM_REG(val) ((val) * 1000)
2128d5d45fbSJean Delvare 
2132a844c14SGuenter Roeck #define PWM_TO_REG(val) (clamp_val(val, 0, 255))
2148d5d45fbSJean Delvare #define PWM_FROM_REG(val) (val)
2158d5d45fbSJean Delvare 
2168d5d45fbSJean Delvare #define PWM_MIN_TO_REG(val) ((val) & 0xf0)
2178d5d45fbSJean Delvare #define PWM_MIN_FROM_REG(val) (((val) & 0xf0) + ((val) >> 4))
2188d5d45fbSJean Delvare 
21986aa3e22SGuenter Roeck /*
22086aa3e22SGuenter Roeck  * Analog output is a voltage, and scaled to millivolts.  The datasheet
2218d5d45fbSJean Delvare  *   indicates that the DAC could be used to drive the fans, but in our
2228d5d45fbSJean Delvare  *   example board (Arima HDAMA) it isn't connected to the fans at all.
2238d5d45fbSJean Delvare  */
224f1b9baa9SGuenter Roeck #define DAC_TO_REG(val) DIV_ROUND_CLOSEST(clamp_val(val, 0, 2500) * 255, \
225f1b9baa9SGuenter Roeck 					  2500)
2268d5d45fbSJean Delvare #define DAC_FROM_REG(val) (((val) * 2500) / 255)
2278d5d45fbSJean Delvare 
22886aa3e22SGuenter Roeck /*
22986aa3e22SGuenter Roeck  * Chip sampling rates
2308d5d45fbSJean Delvare  *
2318d5d45fbSJean Delvare  * Some sensors are not updated more frequently than once per second
2328d5d45fbSJean Delvare  *    so it doesn't make sense to read them more often than that.
2338d5d45fbSJean Delvare  *    We cache the results and return the saved data if the driver
2348d5d45fbSJean Delvare  *    is called again before a second has elapsed.
2358d5d45fbSJean Delvare  *
2368d5d45fbSJean Delvare  * Also, there is significant configuration data for this chip
2378d5d45fbSJean Delvare  *    So, we keep the config data up to date in the cache
2388d5d45fbSJean Delvare  *    when it is written and only sample it once every 5 *minutes*
2398d5d45fbSJean Delvare  */
2408d5d45fbSJean Delvare #define ADM1026_DATA_INTERVAL		(1 * HZ)
2418d5d45fbSJean Delvare #define ADM1026_CONFIG_INTERVAL		(5 * 60 * HZ)
2428d5d45fbSJean Delvare 
24386aa3e22SGuenter Roeck /*
24486aa3e22SGuenter Roeck  * We allow for multiple chips in a single system.
2458d5d45fbSJean Delvare  *
2468d5d45fbSJean Delvare  * For each registered ADM1026, we need to keep state information
2478d5d45fbSJean Delvare  * at client->data. The adm1026_data structure is dynamically
24886aa3e22SGuenter Roeck  * allocated, when a new client structure is allocated.
24986aa3e22SGuenter Roeck  */
2508d5d45fbSJean Delvare 
2518d5d45fbSJean Delvare struct pwm_data {
2528d5d45fbSJean Delvare 	u8 pwm;
2538d5d45fbSJean Delvare 	u8 enable;
2548d5d45fbSJean Delvare 	u8 auto_pwm_min;
2558d5d45fbSJean Delvare };
2568d5d45fbSJean Delvare 
2578d5d45fbSJean Delvare struct adm1026_data {
258b591d3c1SAxel Lin 	struct i2c_client *client;
259b591d3c1SAxel Lin 	const struct attribute_group *groups[3];
2608d5d45fbSJean Delvare 
2619a61bf63SIngo Molnar 	struct mutex update_lock;
262952a11caSPaul Fertser 	bool valid;		/* true if following fields are valid */
2638d5d45fbSJean Delvare 	unsigned long last_reading;	/* In jiffies */
2648d5d45fbSJean Delvare 	unsigned long last_config;	/* In jiffies */
2658d5d45fbSJean Delvare 
2668d5d45fbSJean Delvare 	u8 in[17];		/* Register value */
2678d5d45fbSJean Delvare 	u8 in_max[17];		/* Register value */
2688d5d45fbSJean Delvare 	u8 in_min[17];		/* Register value */
2698d5d45fbSJean Delvare 	s8 temp[3];		/* Register value */
2708d5d45fbSJean Delvare 	s8 temp_min[3];		/* Register value */
2718d5d45fbSJean Delvare 	s8 temp_max[3];		/* Register value */
2728d5d45fbSJean Delvare 	s8 temp_tmin[3];	/* Register value */
2738d5d45fbSJean Delvare 	s8 temp_crit[3];	/* Register value */
2748d5d45fbSJean Delvare 	s8 temp_offset[3];	/* Register value */
2758d5d45fbSJean Delvare 	u8 fan[8];		/* Register value */
2768d5d45fbSJean Delvare 	u8 fan_min[8];		/* Register value */
2778d5d45fbSJean Delvare 	u8 fan_div[8];		/* Decoded value */
2788d5d45fbSJean Delvare 	struct pwm_data pwm1;	/* Pwm control values */
2798d5d45fbSJean Delvare 	u8 vrm;			/* VRM version */
2808d5d45fbSJean Delvare 	u8 analog_out;		/* Register value (DAC) */
2818d5d45fbSJean Delvare 	long alarms;		/* Register encoding, combined */
2828d5d45fbSJean Delvare 	long alarm_mask;	/* Register encoding, combined */
2838d5d45fbSJean Delvare 	long gpio;		/* Register encoding, combined */
2848d5d45fbSJean Delvare 	long gpio_mask;		/* Register encoding, combined */
2858d5d45fbSJean Delvare 	u8 gpio_config[17];	/* Decoded value */
2868d5d45fbSJean Delvare 	u8 config1;		/* Register value */
2878d5d45fbSJean Delvare 	u8 config2;		/* Register value */
2888d5d45fbSJean Delvare 	u8 config3;		/* Register value */
2898d5d45fbSJean Delvare };
2908d5d45fbSJean Delvare 
adm1026_read_value(struct i2c_client * client,u8 reg)291c49efcefSBen Dooks static int adm1026_read_value(struct i2c_client *client, u8 reg)
2928d5d45fbSJean Delvare {
2938d5d45fbSJean Delvare 	int res;
2948d5d45fbSJean Delvare 
2958d5d45fbSJean Delvare 	if (reg < 0x80) {
2968d5d45fbSJean Delvare 		/* "RAM" locations */
2978d5d45fbSJean Delvare 		res = i2c_smbus_read_byte_data(client, reg) & 0xff;
2988d5d45fbSJean Delvare 	} else {
2998d5d45fbSJean Delvare 		/* EEPROM, do nothing */
3008d5d45fbSJean Delvare 		res = 0;
3018d5d45fbSJean Delvare 	}
3028d5d45fbSJean Delvare 	return res;
3038d5d45fbSJean Delvare }
3048d5d45fbSJean Delvare 
adm1026_write_value(struct i2c_client * client,u8 reg,int value)305c49efcefSBen Dooks static int adm1026_write_value(struct i2c_client *client, u8 reg, int value)
3068d5d45fbSJean Delvare {
3078d5d45fbSJean Delvare 	int res;
3088d5d45fbSJean Delvare 
3098d5d45fbSJean Delvare 	if (reg < 0x80) {
3108d5d45fbSJean Delvare 		/* "RAM" locations */
3118d5d45fbSJean Delvare 		res = i2c_smbus_write_byte_data(client, reg, value);
3128d5d45fbSJean Delvare 	} else {
3138d5d45fbSJean Delvare 		/* EEPROM, do nothing */
3148d5d45fbSJean Delvare 		res = 0;
3158d5d45fbSJean Delvare 	}
3168d5d45fbSJean Delvare 	return res;
3178d5d45fbSJean Delvare }
3188d5d45fbSJean Delvare 
adm1026_update_device(struct device * dev)3198d5d45fbSJean Delvare static struct adm1026_data *adm1026_update_device(struct device *dev)
3208d5d45fbSJean Delvare {
321b591d3c1SAxel Lin 	struct adm1026_data *data = dev_get_drvdata(dev);
322b591d3c1SAxel Lin 	struct i2c_client *client = data->client;
3238d5d45fbSJean Delvare 	int i;
3248d5d45fbSJean Delvare 	long value, alarms, gpio;
3258d5d45fbSJean Delvare 
3269a61bf63SIngo Molnar 	mutex_lock(&data->update_lock);
3278d5d45fbSJean Delvare 	if (!data->valid
32886aa3e22SGuenter Roeck 	    || time_after(jiffies,
32986aa3e22SGuenter Roeck 			  data->last_reading + ADM1026_DATA_INTERVAL)) {
3308d5d45fbSJean Delvare 		/* Things that change quickly */
3318d5d45fbSJean Delvare 		dev_dbg(&client->dev, "Reading sensor values\n");
3328d5d45fbSJean Delvare 		for (i = 0; i <= 16; ++i) {
3338d5d45fbSJean Delvare 			data->in[i] =
3348d5d45fbSJean Delvare 			    adm1026_read_value(client, ADM1026_REG_IN[i]);
3358d5d45fbSJean Delvare 		}
3368d5d45fbSJean Delvare 
3378d5d45fbSJean Delvare 		for (i = 0; i <= 7; ++i) {
3388d5d45fbSJean Delvare 			data->fan[i] =
3398d5d45fbSJean Delvare 			    adm1026_read_value(client, ADM1026_REG_FAN(i));
3408d5d45fbSJean Delvare 		}
3418d5d45fbSJean Delvare 
3428d5d45fbSJean Delvare 		for (i = 0; i <= 2; ++i) {
34386aa3e22SGuenter Roeck 			/*
34486aa3e22SGuenter Roeck 			 * NOTE: temp[] is s8 and we assume 2's complement
34586aa3e22SGuenter Roeck 			 *   "conversion" in the assignment
34686aa3e22SGuenter Roeck 			 */
3478d5d45fbSJean Delvare 			data->temp[i] =
3488d5d45fbSJean Delvare 			    adm1026_read_value(client, ADM1026_REG_TEMP[i]);
3498d5d45fbSJean Delvare 		}
3508d5d45fbSJean Delvare 
3518d5d45fbSJean Delvare 		data->pwm1.pwm = adm1026_read_value(client,
3528d5d45fbSJean Delvare 			ADM1026_REG_PWM);
3538d5d45fbSJean Delvare 		data->analog_out = adm1026_read_value(client,
3548d5d45fbSJean Delvare 			ADM1026_REG_DAC);
3558d5d45fbSJean Delvare 		/* GPIO16 is MSbit of alarms, move it to gpio */
3568d5d45fbSJean Delvare 		alarms = adm1026_read_value(client, ADM1026_REG_STATUS4);
3578d5d45fbSJean Delvare 		gpio = alarms & 0x80 ? 0x0100 : 0; /* GPIO16 */
3588d5d45fbSJean Delvare 		alarms &= 0x7f;
3598d5d45fbSJean Delvare 		alarms <<= 8;
3608d5d45fbSJean Delvare 		alarms |= adm1026_read_value(client, ADM1026_REG_STATUS3);
3618d5d45fbSJean Delvare 		alarms <<= 8;
3628d5d45fbSJean Delvare 		alarms |= adm1026_read_value(client, ADM1026_REG_STATUS2);
3638d5d45fbSJean Delvare 		alarms <<= 8;
3648d5d45fbSJean Delvare 		alarms |= adm1026_read_value(client, ADM1026_REG_STATUS1);
3658d5d45fbSJean Delvare 		data->alarms = alarms;
3668d5d45fbSJean Delvare 
3678d5d45fbSJean Delvare 		/* Read the GPIO values */
3688d5d45fbSJean Delvare 		gpio |= adm1026_read_value(client,
3698d5d45fbSJean Delvare 			ADM1026_REG_GPIO_STATUS_8_15);
3708d5d45fbSJean Delvare 		gpio <<= 8;
3718d5d45fbSJean Delvare 		gpio |= adm1026_read_value(client,
3728d5d45fbSJean Delvare 			ADM1026_REG_GPIO_STATUS_0_7);
3738d5d45fbSJean Delvare 		data->gpio = gpio;
3748d5d45fbSJean Delvare 
3758d5d45fbSJean Delvare 		data->last_reading = jiffies;
376a0393713SGuenter Roeck 	}	/* last_reading */
3778d5d45fbSJean Delvare 
3788d5d45fbSJean Delvare 	if (!data->valid ||
3798d5d45fbSJean Delvare 	    time_after(jiffies, data->last_config + ADM1026_CONFIG_INTERVAL)) {
3808d5d45fbSJean Delvare 		/* Things that don't change often */
3818d5d45fbSJean Delvare 		dev_dbg(&client->dev, "Reading config values\n");
3828d5d45fbSJean Delvare 		for (i = 0; i <= 16; ++i) {
3838d5d45fbSJean Delvare 			data->in_min[i] = adm1026_read_value(client,
3848d5d45fbSJean Delvare 				ADM1026_REG_IN_MIN[i]);
3858d5d45fbSJean Delvare 			data->in_max[i] = adm1026_read_value(client,
3868d5d45fbSJean Delvare 				ADM1026_REG_IN_MAX[i]);
3878d5d45fbSJean Delvare 		}
3888d5d45fbSJean Delvare 
3898d5d45fbSJean Delvare 		value = adm1026_read_value(client, ADM1026_REG_FAN_DIV_0_3)
3908d5d45fbSJean Delvare 			| (adm1026_read_value(client, ADM1026_REG_FAN_DIV_4_7)
3918d5d45fbSJean Delvare 			<< 8);
3928d5d45fbSJean Delvare 		for (i = 0; i <= 7; ++i) {
3938d5d45fbSJean Delvare 			data->fan_min[i] = adm1026_read_value(client,
3948d5d45fbSJean Delvare 				ADM1026_REG_FAN_MIN(i));
3958d5d45fbSJean Delvare 			data->fan_div[i] = DIV_FROM_REG(value & 0x03);
3968d5d45fbSJean Delvare 			value >>= 2;
3978d5d45fbSJean Delvare 		}
3988d5d45fbSJean Delvare 
3998d5d45fbSJean Delvare 		for (i = 0; i <= 2; ++i) {
40086aa3e22SGuenter Roeck 			/*
40186aa3e22SGuenter Roeck 			 * NOTE: temp_xxx[] are s8 and we assume 2's
4028d5d45fbSJean Delvare 			 *    complement "conversion" in the assignment
4038d5d45fbSJean Delvare 			 */
4048d5d45fbSJean Delvare 			data->temp_min[i] = adm1026_read_value(client,
4058d5d45fbSJean Delvare 				ADM1026_REG_TEMP_MIN[i]);
4068d5d45fbSJean Delvare 			data->temp_max[i] = adm1026_read_value(client,
4078d5d45fbSJean Delvare 				ADM1026_REG_TEMP_MAX[i]);
4088d5d45fbSJean Delvare 			data->temp_tmin[i] = adm1026_read_value(client,
4098d5d45fbSJean Delvare 				ADM1026_REG_TEMP_TMIN[i]);
4108d5d45fbSJean Delvare 			data->temp_crit[i] = adm1026_read_value(client,
4118d5d45fbSJean Delvare 				ADM1026_REG_TEMP_THERM[i]);
4128d5d45fbSJean Delvare 			data->temp_offset[i] = adm1026_read_value(client,
4138d5d45fbSJean Delvare 				ADM1026_REG_TEMP_OFFSET[i]);
4148d5d45fbSJean Delvare 		}
4158d5d45fbSJean Delvare 
4168d5d45fbSJean Delvare 		/* Read the STATUS/alarm masks */
4178d5d45fbSJean Delvare 		alarms = adm1026_read_value(client, ADM1026_REG_MASK4);
4188d5d45fbSJean Delvare 		gpio = alarms & 0x80 ? 0x0100 : 0; /* GPIO16 */
4198d5d45fbSJean Delvare 		alarms = (alarms & 0x7f) << 8;
4208d5d45fbSJean Delvare 		alarms |= adm1026_read_value(client, ADM1026_REG_MASK3);
4218d5d45fbSJean Delvare 		alarms <<= 8;
4228d5d45fbSJean Delvare 		alarms |= adm1026_read_value(client, ADM1026_REG_MASK2);
4238d5d45fbSJean Delvare 		alarms <<= 8;
4248d5d45fbSJean Delvare 		alarms |= adm1026_read_value(client, ADM1026_REG_MASK1);
4258d5d45fbSJean Delvare 		data->alarm_mask = alarms;
4268d5d45fbSJean Delvare 
4278d5d45fbSJean Delvare 		/* Read the GPIO values */
4288d5d45fbSJean Delvare 		gpio |= adm1026_read_value(client,
4298d5d45fbSJean Delvare 			ADM1026_REG_GPIO_MASK_8_15);
4308d5d45fbSJean Delvare 		gpio <<= 8;
4318d5d45fbSJean Delvare 		gpio |= adm1026_read_value(client, ADM1026_REG_GPIO_MASK_0_7);
4328d5d45fbSJean Delvare 		data->gpio_mask = gpio;
4338d5d45fbSJean Delvare 
4348d5d45fbSJean Delvare 		/* Read various values from CONFIG1 */
4358d5d45fbSJean Delvare 		data->config1 = adm1026_read_value(client,
4368d5d45fbSJean Delvare 			ADM1026_REG_CONFIG1);
4378d5d45fbSJean Delvare 		if (data->config1 & CFG1_PWM_AFC) {
4388d5d45fbSJean Delvare 			data->pwm1.enable = 2;
4398d5d45fbSJean Delvare 			data->pwm1.auto_pwm_min =
4408d5d45fbSJean Delvare 				PWM_MIN_FROM_REG(data->pwm1.pwm);
4418d5d45fbSJean Delvare 		}
4428d5d45fbSJean Delvare 		/* Read the GPIO config */
4438d5d45fbSJean Delvare 		data->config2 = adm1026_read_value(client,
4448d5d45fbSJean Delvare 			ADM1026_REG_CONFIG2);
4458d5d45fbSJean Delvare 		data->config3 = adm1026_read_value(client,
4468d5d45fbSJean Delvare 			ADM1026_REG_CONFIG3);
4478d5d45fbSJean Delvare 		data->gpio_config[16] = (data->config3 >> 6) & 0x03;
4488d5d45fbSJean Delvare 
4498d5d45fbSJean Delvare 		value = 0;
4508d5d45fbSJean Delvare 		for (i = 0; i <= 15; ++i) {
4518d5d45fbSJean Delvare 			if ((i & 0x03) == 0) {
4528d5d45fbSJean Delvare 				value = adm1026_read_value(client,
4538d5d45fbSJean Delvare 					    ADM1026_REG_GPIO_CFG_0_3 + i/4);
4548d5d45fbSJean Delvare 			}
4558d5d45fbSJean Delvare 			data->gpio_config[i] = value & 0x03;
4568d5d45fbSJean Delvare 			value >>= 2;
4578d5d45fbSJean Delvare 		}
4588d5d45fbSJean Delvare 
4598d5d45fbSJean Delvare 		data->last_config = jiffies;
460a0393713SGuenter Roeck 	}	/* last_config */
4618d5d45fbSJean Delvare 
462952a11caSPaul Fertser 	data->valid = true;
4639a61bf63SIngo Molnar 	mutex_unlock(&data->update_lock);
4648d5d45fbSJean Delvare 	return data;
4658d5d45fbSJean Delvare }
4668d5d45fbSJean Delvare 
in_show(struct device * dev,struct device_attribute * attr,char * buf)4677ded2315SGuenter Roeck static ssize_t in_show(struct device *dev, struct device_attribute *attr,
4688d5d45fbSJean Delvare 		       char *buf)
4698d5d45fbSJean Delvare {
4708d5d45fbSJean Delvare 	struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr);
4718d5d45fbSJean Delvare 	int nr = sensor_attr->index;
4728d5d45fbSJean Delvare 	struct adm1026_data *data = adm1026_update_device(dev);
4738d5d45fbSJean Delvare 	return sprintf(buf, "%d\n", INS_FROM_REG(nr, data->in[nr]));
4748d5d45fbSJean Delvare }
in_min_show(struct device * dev,struct device_attribute * attr,char * buf)4757ded2315SGuenter Roeck static ssize_t in_min_show(struct device *dev, struct device_attribute *attr,
4768d5d45fbSJean Delvare 			   char *buf)
4778d5d45fbSJean Delvare {
4788d5d45fbSJean Delvare 	struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr);
4798d5d45fbSJean Delvare 	int nr = sensor_attr->index;
4808d5d45fbSJean Delvare 	struct adm1026_data *data = adm1026_update_device(dev);
4818d5d45fbSJean Delvare 	return sprintf(buf, "%d\n", INS_FROM_REG(nr, data->in_min[nr]));
4828d5d45fbSJean Delvare }
in_min_store(struct device * dev,struct device_attribute * attr,const char * buf,size_t count)4837ded2315SGuenter Roeck static ssize_t in_min_store(struct device *dev, struct device_attribute *attr,
4848d5d45fbSJean Delvare 			    const char *buf, size_t count)
4858d5d45fbSJean Delvare {
4868d5d45fbSJean Delvare 	struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr);
4878d5d45fbSJean Delvare 	int nr = sensor_attr->index;
488b591d3c1SAxel Lin 	struct adm1026_data *data = dev_get_drvdata(dev);
489b591d3c1SAxel Lin 	struct i2c_client *client = data->client;
49086aa3e22SGuenter Roeck 	long val;
49186aa3e22SGuenter Roeck 	int err;
49286aa3e22SGuenter Roeck 
49386aa3e22SGuenter Roeck 	err = kstrtol(buf, 10, &val);
49486aa3e22SGuenter Roeck 	if (err)
49586aa3e22SGuenter Roeck 		return err;
4968d5d45fbSJean Delvare 
4979a61bf63SIngo Molnar 	mutex_lock(&data->update_lock);
4988d5d45fbSJean Delvare 	data->in_min[nr] = INS_TO_REG(nr, val);
4998d5d45fbSJean Delvare 	adm1026_write_value(client, ADM1026_REG_IN_MIN[nr], data->in_min[nr]);
5009a61bf63SIngo Molnar 	mutex_unlock(&data->update_lock);
5018d5d45fbSJean Delvare 	return count;
5028d5d45fbSJean Delvare }
in_max_show(struct device * dev,struct device_attribute * attr,char * buf)5037ded2315SGuenter Roeck static ssize_t in_max_show(struct device *dev, struct device_attribute *attr,
5048d5d45fbSJean Delvare 			   char *buf)
5058d5d45fbSJean Delvare {
5068d5d45fbSJean Delvare 	struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr);
5078d5d45fbSJean Delvare 	int nr = sensor_attr->index;
5088d5d45fbSJean Delvare 	struct adm1026_data *data = adm1026_update_device(dev);
5098d5d45fbSJean Delvare 	return sprintf(buf, "%d\n", INS_FROM_REG(nr, data->in_max[nr]));
5108d5d45fbSJean Delvare }
in_max_store(struct device * dev,struct device_attribute * attr,const char * buf,size_t count)5117ded2315SGuenter Roeck static ssize_t in_max_store(struct device *dev, struct device_attribute *attr,
5128d5d45fbSJean Delvare 			    const char *buf, size_t count)
5138d5d45fbSJean Delvare {
5148d5d45fbSJean Delvare 	struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr);
5158d5d45fbSJean Delvare 	int nr = sensor_attr->index;
516b591d3c1SAxel Lin 	struct adm1026_data *data = dev_get_drvdata(dev);
517b591d3c1SAxel Lin 	struct i2c_client *client = data->client;
51886aa3e22SGuenter Roeck 	long val;
51986aa3e22SGuenter Roeck 	int err;
52086aa3e22SGuenter Roeck 
52186aa3e22SGuenter Roeck 	err = kstrtol(buf, 10, &val);
52286aa3e22SGuenter Roeck 	if (err)
52386aa3e22SGuenter Roeck 		return err;
5248d5d45fbSJean Delvare 
5259a61bf63SIngo Molnar 	mutex_lock(&data->update_lock);
5268d5d45fbSJean Delvare 	data->in_max[nr] = INS_TO_REG(nr, val);
5278d5d45fbSJean Delvare 	adm1026_write_value(client, ADM1026_REG_IN_MAX[nr], data->in_max[nr]);
5289a61bf63SIngo Molnar 	mutex_unlock(&data->update_lock);
5298d5d45fbSJean Delvare 	return count;
5308d5d45fbSJean Delvare }
5318d5d45fbSJean Delvare 
5327ded2315SGuenter Roeck static SENSOR_DEVICE_ATTR_RO(in0_input, in, 0);
5337ded2315SGuenter Roeck static SENSOR_DEVICE_ATTR_RW(in0_min, in_min, 0);
5347ded2315SGuenter Roeck static SENSOR_DEVICE_ATTR_RW(in0_max, in_max, 0);
5357ded2315SGuenter Roeck static SENSOR_DEVICE_ATTR_RO(in1_input, in, 1);
5367ded2315SGuenter Roeck static SENSOR_DEVICE_ATTR_RW(in1_min, in_min, 1);
5377ded2315SGuenter Roeck static SENSOR_DEVICE_ATTR_RW(in1_max, in_max, 1);
5387ded2315SGuenter Roeck static SENSOR_DEVICE_ATTR_RO(in2_input, in, 2);
5397ded2315SGuenter Roeck static SENSOR_DEVICE_ATTR_RW(in2_min, in_min, 2);
5407ded2315SGuenter Roeck static SENSOR_DEVICE_ATTR_RW(in2_max, in_max, 2);
5417ded2315SGuenter Roeck static SENSOR_DEVICE_ATTR_RO(in3_input, in, 3);
5427ded2315SGuenter Roeck static SENSOR_DEVICE_ATTR_RW(in3_min, in_min, 3);
5437ded2315SGuenter Roeck static SENSOR_DEVICE_ATTR_RW(in3_max, in_max, 3);
5447ded2315SGuenter Roeck static SENSOR_DEVICE_ATTR_RO(in4_input, in, 4);
5457ded2315SGuenter Roeck static SENSOR_DEVICE_ATTR_RW(in4_min, in_min, 4);
5467ded2315SGuenter Roeck static SENSOR_DEVICE_ATTR_RW(in4_max, in_max, 4);
5477ded2315SGuenter Roeck static SENSOR_DEVICE_ATTR_RO(in5_input, in, 5);
5487ded2315SGuenter Roeck static SENSOR_DEVICE_ATTR_RW(in5_min, in_min, 5);
5497ded2315SGuenter Roeck static SENSOR_DEVICE_ATTR_RW(in5_max, in_max, 5);
5507ded2315SGuenter Roeck static SENSOR_DEVICE_ATTR_RO(in6_input, in, 6);
5517ded2315SGuenter Roeck static SENSOR_DEVICE_ATTR_RW(in6_min, in_min, 6);
5527ded2315SGuenter Roeck static SENSOR_DEVICE_ATTR_RW(in6_max, in_max, 6);
5537ded2315SGuenter Roeck static SENSOR_DEVICE_ATTR_RO(in7_input, in, 7);
5547ded2315SGuenter Roeck static SENSOR_DEVICE_ATTR_RW(in7_min, in_min, 7);
5557ded2315SGuenter Roeck static SENSOR_DEVICE_ATTR_RW(in7_max, in_max, 7);
5567ded2315SGuenter Roeck static SENSOR_DEVICE_ATTR_RO(in8_input, in, 8);
5577ded2315SGuenter Roeck static SENSOR_DEVICE_ATTR_RW(in8_min, in_min, 8);
5587ded2315SGuenter Roeck static SENSOR_DEVICE_ATTR_RW(in8_max, in_max, 8);
5597ded2315SGuenter Roeck static SENSOR_DEVICE_ATTR_RO(in9_input, in, 9);
5607ded2315SGuenter Roeck static SENSOR_DEVICE_ATTR_RW(in9_min, in_min, 9);
5617ded2315SGuenter Roeck static SENSOR_DEVICE_ATTR_RW(in9_max, in_max, 9);
5627ded2315SGuenter Roeck static SENSOR_DEVICE_ATTR_RO(in10_input, in, 10);
5637ded2315SGuenter Roeck static SENSOR_DEVICE_ATTR_RW(in10_min, in_min, 10);
5647ded2315SGuenter Roeck static SENSOR_DEVICE_ATTR_RW(in10_max, in_max, 10);
5657ded2315SGuenter Roeck static SENSOR_DEVICE_ATTR_RO(in11_input, in, 11);
5667ded2315SGuenter Roeck static SENSOR_DEVICE_ATTR_RW(in11_min, in_min, 11);
5677ded2315SGuenter Roeck static SENSOR_DEVICE_ATTR_RW(in11_max, in_max, 11);
5687ded2315SGuenter Roeck static SENSOR_DEVICE_ATTR_RO(in12_input, in, 12);
5697ded2315SGuenter Roeck static SENSOR_DEVICE_ATTR_RW(in12_min, in_min, 12);
5707ded2315SGuenter Roeck static SENSOR_DEVICE_ATTR_RW(in12_max, in_max, 12);
5717ded2315SGuenter Roeck static SENSOR_DEVICE_ATTR_RO(in13_input, in, 13);
5727ded2315SGuenter Roeck static SENSOR_DEVICE_ATTR_RW(in13_min, in_min, 13);
5737ded2315SGuenter Roeck static SENSOR_DEVICE_ATTR_RW(in13_max, in_max, 13);
5747ded2315SGuenter Roeck static SENSOR_DEVICE_ATTR_RO(in14_input, in, 14);
5757ded2315SGuenter Roeck static SENSOR_DEVICE_ATTR_RW(in14_min, in_min, 14);
5767ded2315SGuenter Roeck static SENSOR_DEVICE_ATTR_RW(in14_max, in_max, 14);
5777ded2315SGuenter Roeck static SENSOR_DEVICE_ATTR_RO(in15_input, in, 15);
5787ded2315SGuenter Roeck static SENSOR_DEVICE_ATTR_RW(in15_min, in_min, 15);
5797ded2315SGuenter Roeck static SENSOR_DEVICE_ATTR_RW(in15_max, in_max, 15);
5808d5d45fbSJean Delvare 
in16_show(struct device * dev,struct device_attribute * attr,char * buf)5817ded2315SGuenter Roeck static ssize_t in16_show(struct device *dev, struct device_attribute *attr,
58286aa3e22SGuenter Roeck 			 char *buf)
5838d5d45fbSJean Delvare {
5848d5d45fbSJean Delvare 	struct adm1026_data *data = adm1026_update_device(dev);
5858d5d45fbSJean Delvare 	return sprintf(buf, "%d\n", INS_FROM_REG(16, data->in[16]) -
5868d5d45fbSJean Delvare 		NEG12_OFFSET);
5878d5d45fbSJean Delvare }
in16_min_show(struct device * dev,struct device_attribute * attr,char * buf)5887ded2315SGuenter Roeck static ssize_t in16_min_show(struct device *dev,
5897ded2315SGuenter Roeck 			     struct device_attribute *attr, char *buf)
5908d5d45fbSJean Delvare {
5918d5d45fbSJean Delvare 	struct adm1026_data *data = adm1026_update_device(dev);
5928d5d45fbSJean Delvare 	return sprintf(buf, "%d\n", INS_FROM_REG(16, data->in_min[16])
5938d5d45fbSJean Delvare 		- NEG12_OFFSET);
5948d5d45fbSJean Delvare }
in16_min_store(struct device * dev,struct device_attribute * attr,const char * buf,size_t count)5957ded2315SGuenter Roeck static ssize_t in16_min_store(struct device *dev,
5967ded2315SGuenter Roeck 			      struct device_attribute *attr, const char *buf,
5977ded2315SGuenter Roeck 			      size_t count)
5988d5d45fbSJean Delvare {
599b591d3c1SAxel Lin 	struct adm1026_data *data = dev_get_drvdata(dev);
600b591d3c1SAxel Lin 	struct i2c_client *client = data->client;
60186aa3e22SGuenter Roeck 	long val;
60286aa3e22SGuenter Roeck 	int err;
60386aa3e22SGuenter Roeck 
60486aa3e22SGuenter Roeck 	err = kstrtol(buf, 10, &val);
60586aa3e22SGuenter Roeck 	if (err)
60686aa3e22SGuenter Roeck 		return err;
6078d5d45fbSJean Delvare 
6089a61bf63SIngo Molnar 	mutex_lock(&data->update_lock);
609f1b9baa9SGuenter Roeck 	data->in_min[16] = INS_TO_REG(16,
610f1b9baa9SGuenter Roeck 				      clamp_val(val, INT_MIN,
611f1b9baa9SGuenter Roeck 						INT_MAX - NEG12_OFFSET) +
612f1b9baa9SGuenter Roeck 				      NEG12_OFFSET);
6138d5d45fbSJean Delvare 	adm1026_write_value(client, ADM1026_REG_IN_MIN[16], data->in_min[16]);
6149a61bf63SIngo Molnar 	mutex_unlock(&data->update_lock);
6158d5d45fbSJean Delvare 	return count;
6168d5d45fbSJean Delvare }
in16_max_show(struct device * dev,struct device_attribute * attr,char * buf)6177ded2315SGuenter Roeck static ssize_t in16_max_show(struct device *dev,
6187ded2315SGuenter Roeck 			     struct device_attribute *attr, char *buf)
6198d5d45fbSJean Delvare {
6208d5d45fbSJean Delvare 	struct adm1026_data *data = adm1026_update_device(dev);
6218d5d45fbSJean Delvare 	return sprintf(buf, "%d\n", INS_FROM_REG(16, data->in_max[16])
6228d5d45fbSJean Delvare 			- NEG12_OFFSET);
6238d5d45fbSJean Delvare }
in16_max_store(struct device * dev,struct device_attribute * attr,const char * buf,size_t count)6247ded2315SGuenter Roeck static ssize_t in16_max_store(struct device *dev,
6257ded2315SGuenter Roeck 			      struct device_attribute *attr, const char *buf,
6267ded2315SGuenter Roeck 			      size_t count)
6278d5d45fbSJean Delvare {
628b591d3c1SAxel Lin 	struct adm1026_data *data = dev_get_drvdata(dev);
629b591d3c1SAxel Lin 	struct i2c_client *client = data->client;
63086aa3e22SGuenter Roeck 	long val;
63186aa3e22SGuenter Roeck 	int err;
63286aa3e22SGuenter Roeck 
63386aa3e22SGuenter Roeck 	err = kstrtol(buf, 10, &val);
63486aa3e22SGuenter Roeck 	if (err)
63586aa3e22SGuenter Roeck 		return err;
6368d5d45fbSJean Delvare 
6379a61bf63SIngo Molnar 	mutex_lock(&data->update_lock);
638f1b9baa9SGuenter Roeck 	data->in_max[16] = INS_TO_REG(16,
639f1b9baa9SGuenter Roeck 				      clamp_val(val, INT_MIN,
640f1b9baa9SGuenter Roeck 						INT_MAX - NEG12_OFFSET) +
641f1b9baa9SGuenter Roeck 				      NEG12_OFFSET);
6428d5d45fbSJean Delvare 	adm1026_write_value(client, ADM1026_REG_IN_MAX[16], data->in_max[16]);
6439a61bf63SIngo Molnar 	mutex_unlock(&data->update_lock);
6448d5d45fbSJean Delvare 	return count;
6458d5d45fbSJean Delvare }
6468d5d45fbSJean Delvare 
6477ded2315SGuenter Roeck static SENSOR_DEVICE_ATTR_RO(in16_input, in16, 16);
6487ded2315SGuenter Roeck static SENSOR_DEVICE_ATTR_RW(in16_min, in16_min, 16);
6497ded2315SGuenter Roeck static SENSOR_DEVICE_ATTR_RW(in16_max, in16_max, 16);
6508d5d45fbSJean Delvare 
6518d5d45fbSJean Delvare /* Now add fan read/write functions */
6528d5d45fbSJean Delvare 
fan_show(struct device * dev,struct device_attribute * attr,char * buf)6537ded2315SGuenter Roeck static ssize_t fan_show(struct device *dev, struct device_attribute *attr,
6548d5d45fbSJean Delvare 			char *buf)
6558d5d45fbSJean Delvare {
6568d5d45fbSJean Delvare 	struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr);
6578d5d45fbSJean Delvare 	int nr = sensor_attr->index;
6588d5d45fbSJean Delvare 	struct adm1026_data *data = adm1026_update_device(dev);
6598d5d45fbSJean Delvare 	return sprintf(buf, "%d\n", FAN_FROM_REG(data->fan[nr],
6608d5d45fbSJean Delvare 		data->fan_div[nr]));
6618d5d45fbSJean Delvare }
fan_min_show(struct device * dev,struct device_attribute * attr,char * buf)6627ded2315SGuenter Roeck static ssize_t fan_min_show(struct device *dev, struct device_attribute *attr,
6638d5d45fbSJean Delvare 			    char *buf)
6648d5d45fbSJean Delvare {
6658d5d45fbSJean Delvare 	struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr);
6668d5d45fbSJean Delvare 	int nr = sensor_attr->index;
6678d5d45fbSJean Delvare 	struct adm1026_data *data = adm1026_update_device(dev);
6688d5d45fbSJean Delvare 	return sprintf(buf, "%d\n", FAN_FROM_REG(data->fan_min[nr],
6698d5d45fbSJean Delvare 		data->fan_div[nr]));
6708d5d45fbSJean Delvare }
fan_min_store(struct device * dev,struct device_attribute * attr,const char * buf,size_t count)6717ded2315SGuenter Roeck static ssize_t fan_min_store(struct device *dev,
6727ded2315SGuenter Roeck 			     struct device_attribute *attr, const char *buf,
6737ded2315SGuenter Roeck 			     size_t count)
6748d5d45fbSJean Delvare {
6758d5d45fbSJean Delvare 	struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr);
6768d5d45fbSJean Delvare 	int nr = sensor_attr->index;
677b591d3c1SAxel Lin 	struct adm1026_data *data = dev_get_drvdata(dev);
678b591d3c1SAxel Lin 	struct i2c_client *client = data->client;
67986aa3e22SGuenter Roeck 	long val;
68086aa3e22SGuenter Roeck 	int err;
68186aa3e22SGuenter Roeck 
68286aa3e22SGuenter Roeck 	err = kstrtol(buf, 10, &val);
68386aa3e22SGuenter Roeck 	if (err)
68486aa3e22SGuenter Roeck 		return err;
6858d5d45fbSJean Delvare 
6869a61bf63SIngo Molnar 	mutex_lock(&data->update_lock);
6878d5d45fbSJean Delvare 	data->fan_min[nr] = FAN_TO_REG(val, data->fan_div[nr]);
6888d5d45fbSJean Delvare 	adm1026_write_value(client, ADM1026_REG_FAN_MIN(nr),
6898d5d45fbSJean Delvare 		data->fan_min[nr]);
6909a61bf63SIngo Molnar 	mutex_unlock(&data->update_lock);
6918d5d45fbSJean Delvare 	return count;
6928d5d45fbSJean Delvare }
6938d5d45fbSJean Delvare 
6947ded2315SGuenter Roeck static SENSOR_DEVICE_ATTR_RO(fan1_input, fan, 0);
6957ded2315SGuenter Roeck static SENSOR_DEVICE_ATTR_RW(fan1_min, fan_min, 0);
6967ded2315SGuenter Roeck static SENSOR_DEVICE_ATTR_RO(fan2_input, fan, 1);
6977ded2315SGuenter Roeck static SENSOR_DEVICE_ATTR_RW(fan2_min, fan_min, 1);
6987ded2315SGuenter Roeck static SENSOR_DEVICE_ATTR_RO(fan3_input, fan, 2);
6997ded2315SGuenter Roeck static SENSOR_DEVICE_ATTR_RW(fan3_min, fan_min, 2);
7007ded2315SGuenter Roeck static SENSOR_DEVICE_ATTR_RO(fan4_input, fan, 3);
7017ded2315SGuenter Roeck static SENSOR_DEVICE_ATTR_RW(fan4_min, fan_min, 3);
7027ded2315SGuenter Roeck static SENSOR_DEVICE_ATTR_RO(fan5_input, fan, 4);
7037ded2315SGuenter Roeck static SENSOR_DEVICE_ATTR_RW(fan5_min, fan_min, 4);
7047ded2315SGuenter Roeck static SENSOR_DEVICE_ATTR_RO(fan6_input, fan, 5);
7057ded2315SGuenter Roeck static SENSOR_DEVICE_ATTR_RW(fan6_min, fan_min, 5);
7067ded2315SGuenter Roeck static SENSOR_DEVICE_ATTR_RO(fan7_input, fan, 6);
7077ded2315SGuenter Roeck static SENSOR_DEVICE_ATTR_RW(fan7_min, fan_min, 6);
7087ded2315SGuenter Roeck static SENSOR_DEVICE_ATTR_RO(fan8_input, fan, 7);
7097ded2315SGuenter Roeck static SENSOR_DEVICE_ATTR_RW(fan8_min, fan_min, 7);
7108d5d45fbSJean Delvare 
7118d5d45fbSJean Delvare /* Adjust fan_min to account for new fan divisor */
fixup_fan_min(struct device * dev,int fan,int old_div)7128d5d45fbSJean Delvare static void fixup_fan_min(struct device *dev, int fan, int old_div)
7138d5d45fbSJean Delvare {
714b591d3c1SAxel Lin 	struct adm1026_data *data = dev_get_drvdata(dev);
715b591d3c1SAxel Lin 	struct i2c_client *client = data->client;
7168d5d45fbSJean Delvare 	int new_min;
7178d5d45fbSJean Delvare 	int new_div = data->fan_div[fan];
7188d5d45fbSJean Delvare 
7198d5d45fbSJean Delvare 	/* 0 and 0xff are special.  Don't adjust them */
72086aa3e22SGuenter Roeck 	if (data->fan_min[fan] == 0 || data->fan_min[fan] == 0xff)
7218d5d45fbSJean Delvare 		return;
7228d5d45fbSJean Delvare 
7238d5d45fbSJean Delvare 	new_min = data->fan_min[fan] * old_div / new_div;
7242a844c14SGuenter Roeck 	new_min = clamp_val(new_min, 1, 254);
7258d5d45fbSJean Delvare 	data->fan_min[fan] = new_min;
7268d5d45fbSJean Delvare 	adm1026_write_value(client, ADM1026_REG_FAN_MIN(fan), new_min);
7278d5d45fbSJean Delvare }
7288d5d45fbSJean Delvare 
7298d5d45fbSJean Delvare /* Now add fan_div read/write functions */
fan_div_show(struct device * dev,struct device_attribute * attr,char * buf)7307ded2315SGuenter Roeck static ssize_t fan_div_show(struct device *dev, struct device_attribute *attr,
7318d5d45fbSJean Delvare 			    char *buf)
7328d5d45fbSJean Delvare {
7338d5d45fbSJean Delvare 	struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr);
7348d5d45fbSJean Delvare 	int nr = sensor_attr->index;
7358d5d45fbSJean Delvare 	struct adm1026_data *data = adm1026_update_device(dev);
7368d5d45fbSJean Delvare 	return sprintf(buf, "%d\n", data->fan_div[nr]);
7378d5d45fbSJean Delvare }
fan_div_store(struct device * dev,struct device_attribute * attr,const char * buf,size_t count)7387ded2315SGuenter Roeck static ssize_t fan_div_store(struct device *dev,
7397ded2315SGuenter Roeck 			     struct device_attribute *attr, const char *buf,
7407ded2315SGuenter Roeck 			     size_t count)
7418d5d45fbSJean Delvare {
7428d5d45fbSJean Delvare 	struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr);
7438d5d45fbSJean Delvare 	int nr = sensor_attr->index;
744b591d3c1SAxel Lin 	struct adm1026_data *data = dev_get_drvdata(dev);
745b591d3c1SAxel Lin 	struct i2c_client *client = data->client;
74686aa3e22SGuenter Roeck 	long val;
74786aa3e22SGuenter Roeck 	int orig_div, new_div;
74886aa3e22SGuenter Roeck 	int err;
7498d5d45fbSJean Delvare 
75086aa3e22SGuenter Roeck 	err = kstrtol(buf, 10, &val);
75186aa3e22SGuenter Roeck 	if (err)
75286aa3e22SGuenter Roeck 		return err;
75386aa3e22SGuenter Roeck 
7548d5d45fbSJean Delvare 	new_div = DIV_TO_REG(val);
7558b0f1840SGabriele Gorla 
7569a61bf63SIngo Molnar 	mutex_lock(&data->update_lock);
7578d5d45fbSJean Delvare 	orig_div = data->fan_div[nr];
7588d5d45fbSJean Delvare 	data->fan_div[nr] = DIV_FROM_REG(new_div);
7598d5d45fbSJean Delvare 
7608d5d45fbSJean Delvare 	if (nr < 4) { /* 0 <= nr < 4 */
7618d5d45fbSJean Delvare 		adm1026_write_value(client, ADM1026_REG_FAN_DIV_0_3,
76252bc9802SGabriele Gorla 				    (DIV_TO_REG(data->fan_div[0]) << 0) |
76352bc9802SGabriele Gorla 				    (DIV_TO_REG(data->fan_div[1]) << 2) |
76452bc9802SGabriele Gorla 				    (DIV_TO_REG(data->fan_div[2]) << 4) |
76552bc9802SGabriele Gorla 				    (DIV_TO_REG(data->fan_div[3]) << 6));
7668d5d45fbSJean Delvare 	} else { /* 3 < nr < 8 */
7678d5d45fbSJean Delvare 		adm1026_write_value(client, ADM1026_REG_FAN_DIV_4_7,
76852bc9802SGabriele Gorla 				    (DIV_TO_REG(data->fan_div[4]) << 0) |
76952bc9802SGabriele Gorla 				    (DIV_TO_REG(data->fan_div[5]) << 2) |
77052bc9802SGabriele Gorla 				    (DIV_TO_REG(data->fan_div[6]) << 4) |
77152bc9802SGabriele Gorla 				    (DIV_TO_REG(data->fan_div[7]) << 6));
7728d5d45fbSJean Delvare 	}
7738d5d45fbSJean Delvare 
77486aa3e22SGuenter Roeck 	if (data->fan_div[nr] != orig_div)
7758d5d45fbSJean Delvare 		fixup_fan_min(dev, nr, orig_div);
77686aa3e22SGuenter Roeck 
7779a61bf63SIngo Molnar 	mutex_unlock(&data->update_lock);
7788d5d45fbSJean Delvare 	return count;
7798d5d45fbSJean Delvare }
7808d5d45fbSJean Delvare 
7817ded2315SGuenter Roeck static SENSOR_DEVICE_ATTR_RW(fan1_div, fan_div, 0);
7827ded2315SGuenter Roeck static SENSOR_DEVICE_ATTR_RW(fan2_div, fan_div, 1);
7837ded2315SGuenter Roeck static SENSOR_DEVICE_ATTR_RW(fan3_div, fan_div, 2);
7847ded2315SGuenter Roeck static SENSOR_DEVICE_ATTR_RW(fan4_div, fan_div, 3);
7857ded2315SGuenter Roeck static SENSOR_DEVICE_ATTR_RW(fan5_div, fan_div, 4);
7867ded2315SGuenter Roeck static SENSOR_DEVICE_ATTR_RW(fan6_div, fan_div, 5);
7877ded2315SGuenter Roeck static SENSOR_DEVICE_ATTR_RW(fan7_div, fan_div, 6);
7887ded2315SGuenter Roeck static SENSOR_DEVICE_ATTR_RW(fan8_div, fan_div, 7);
7898d5d45fbSJean Delvare 
7908d5d45fbSJean Delvare /* Temps */
temp_show(struct device * dev,struct device_attribute * attr,char * buf)7917ded2315SGuenter Roeck static ssize_t temp_show(struct device *dev, struct device_attribute *attr,
7928d5d45fbSJean Delvare 			 char *buf)
7938d5d45fbSJean Delvare {
7948d5d45fbSJean Delvare 	struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr);
7958d5d45fbSJean Delvare 	int nr = sensor_attr->index;
7968d5d45fbSJean Delvare 	struct adm1026_data *data = adm1026_update_device(dev);
7978d5d45fbSJean Delvare 	return sprintf(buf, "%d\n", TEMP_FROM_REG(data->temp[nr]));
7988d5d45fbSJean Delvare }
temp_min_show(struct device * dev,struct device_attribute * attr,char * buf)7997ded2315SGuenter Roeck static ssize_t temp_min_show(struct device *dev,
8007ded2315SGuenter Roeck 			     struct device_attribute *attr, char *buf)
8018d5d45fbSJean Delvare {
8028d5d45fbSJean Delvare 	struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr);
8038d5d45fbSJean Delvare 	int nr = sensor_attr->index;
8048d5d45fbSJean Delvare 	struct adm1026_data *data = adm1026_update_device(dev);
8058d5d45fbSJean Delvare 	return sprintf(buf, "%d\n", TEMP_FROM_REG(data->temp_min[nr]));
8068d5d45fbSJean Delvare }
temp_min_store(struct device * dev,struct device_attribute * attr,const char * buf,size_t count)8077ded2315SGuenter Roeck static ssize_t temp_min_store(struct device *dev,
8087ded2315SGuenter Roeck 			      struct device_attribute *attr, const char *buf,
8097ded2315SGuenter Roeck 			      size_t count)
8108d5d45fbSJean Delvare {
8118d5d45fbSJean Delvare 	struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr);
8128d5d45fbSJean Delvare 	int nr = sensor_attr->index;
813b591d3c1SAxel Lin 	struct adm1026_data *data = dev_get_drvdata(dev);
814b591d3c1SAxel Lin 	struct i2c_client *client = data->client;
81586aa3e22SGuenter Roeck 	long val;
81686aa3e22SGuenter Roeck 	int err;
81786aa3e22SGuenter Roeck 
81886aa3e22SGuenter Roeck 	err = kstrtol(buf, 10, &val);
81986aa3e22SGuenter Roeck 	if (err)
82086aa3e22SGuenter Roeck 		return err;
8218d5d45fbSJean Delvare 
8229a61bf63SIngo Molnar 	mutex_lock(&data->update_lock);
8238d5d45fbSJean Delvare 	data->temp_min[nr] = TEMP_TO_REG(val);
8248d5d45fbSJean Delvare 	adm1026_write_value(client, ADM1026_REG_TEMP_MIN[nr],
8258d5d45fbSJean Delvare 		data->temp_min[nr]);
8269a61bf63SIngo Molnar 	mutex_unlock(&data->update_lock);
8278d5d45fbSJean Delvare 	return count;
8288d5d45fbSJean Delvare }
temp_max_show(struct device * dev,struct device_attribute * attr,char * buf)8297ded2315SGuenter Roeck static ssize_t temp_max_show(struct device *dev,
8307ded2315SGuenter Roeck 			     struct device_attribute *attr, char *buf)
8318d5d45fbSJean Delvare {
8328d5d45fbSJean Delvare 	struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr);
8338d5d45fbSJean Delvare 	int nr = sensor_attr->index;
8348d5d45fbSJean Delvare 	struct adm1026_data *data = adm1026_update_device(dev);
8358d5d45fbSJean Delvare 	return sprintf(buf, "%d\n", TEMP_FROM_REG(data->temp_max[nr]));
8368d5d45fbSJean Delvare }
temp_max_store(struct device * dev,struct device_attribute * attr,const char * buf,size_t count)8377ded2315SGuenter Roeck static ssize_t temp_max_store(struct device *dev,
8387ded2315SGuenter Roeck 			      struct device_attribute *attr, const char *buf,
8397ded2315SGuenter Roeck 			      size_t count)
8408d5d45fbSJean Delvare {
8418d5d45fbSJean Delvare 	struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr);
8428d5d45fbSJean Delvare 	int nr = sensor_attr->index;
843b591d3c1SAxel Lin 	struct adm1026_data *data = dev_get_drvdata(dev);
844b591d3c1SAxel Lin 	struct i2c_client *client = data->client;
84586aa3e22SGuenter Roeck 	long val;
84686aa3e22SGuenter Roeck 	int err;
84786aa3e22SGuenter Roeck 
84886aa3e22SGuenter Roeck 	err = kstrtol(buf, 10, &val);
84986aa3e22SGuenter Roeck 	if (err)
85086aa3e22SGuenter Roeck 		return err;
8518d5d45fbSJean Delvare 
8529a61bf63SIngo Molnar 	mutex_lock(&data->update_lock);
8538d5d45fbSJean Delvare 	data->temp_max[nr] = TEMP_TO_REG(val);
8548d5d45fbSJean Delvare 	adm1026_write_value(client, ADM1026_REG_TEMP_MAX[nr],
8558d5d45fbSJean Delvare 		data->temp_max[nr]);
8569a61bf63SIngo Molnar 	mutex_unlock(&data->update_lock);
8578d5d45fbSJean Delvare 	return count;
8588d5d45fbSJean Delvare }
8598d5d45fbSJean Delvare 
8607ded2315SGuenter Roeck static SENSOR_DEVICE_ATTR_RO(temp1_input, temp, 0);
8617ded2315SGuenter Roeck static SENSOR_DEVICE_ATTR_RW(temp1_min, temp_min, 0);
8627ded2315SGuenter Roeck static SENSOR_DEVICE_ATTR_RW(temp1_max, temp_max, 0);
8637ded2315SGuenter Roeck static SENSOR_DEVICE_ATTR_RO(temp2_input, temp, 1);
8647ded2315SGuenter Roeck static SENSOR_DEVICE_ATTR_RW(temp2_min, temp_min, 1);
8657ded2315SGuenter Roeck static SENSOR_DEVICE_ATTR_RW(temp2_max, temp_max, 1);
8667ded2315SGuenter Roeck static SENSOR_DEVICE_ATTR_RO(temp3_input, temp, 2);
8677ded2315SGuenter Roeck static SENSOR_DEVICE_ATTR_RW(temp3_min, temp_min, 2);
8687ded2315SGuenter Roeck static SENSOR_DEVICE_ATTR_RW(temp3_max, temp_max, 2);
8698d5d45fbSJean Delvare 
temp_offset_show(struct device * dev,struct device_attribute * attr,char * buf)8707ded2315SGuenter Roeck static ssize_t temp_offset_show(struct device *dev,
8718d5d45fbSJean Delvare 				struct device_attribute *attr, char *buf)
8728d5d45fbSJean Delvare {
8738d5d45fbSJean Delvare 	struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr);
8748d5d45fbSJean Delvare 	int nr = sensor_attr->index;
8758d5d45fbSJean Delvare 	struct adm1026_data *data = adm1026_update_device(dev);
8768d5d45fbSJean Delvare 	return sprintf(buf, "%d\n", TEMP_FROM_REG(data->temp_offset[nr]));
8778d5d45fbSJean Delvare }
temp_offset_store(struct device * dev,struct device_attribute * attr,const char * buf,size_t count)8787ded2315SGuenter Roeck static ssize_t temp_offset_store(struct device *dev,
8797ded2315SGuenter Roeck 				 struct device_attribute *attr,
8807ded2315SGuenter Roeck 				 const char *buf, size_t count)
8818d5d45fbSJean Delvare {
8828d5d45fbSJean Delvare 	struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr);
8838d5d45fbSJean Delvare 	int nr = sensor_attr->index;
884b591d3c1SAxel Lin 	struct adm1026_data *data = dev_get_drvdata(dev);
885b591d3c1SAxel Lin 	struct i2c_client *client = data->client;
88686aa3e22SGuenter Roeck 	long val;
88786aa3e22SGuenter Roeck 	int err;
88886aa3e22SGuenter Roeck 
88986aa3e22SGuenter Roeck 	err = kstrtol(buf, 10, &val);
89086aa3e22SGuenter Roeck 	if (err)
89186aa3e22SGuenter Roeck 		return err;
8928d5d45fbSJean Delvare 
8939a61bf63SIngo Molnar 	mutex_lock(&data->update_lock);
8948d5d45fbSJean Delvare 	data->temp_offset[nr] = TEMP_TO_REG(val);
8958d5d45fbSJean Delvare 	adm1026_write_value(client, ADM1026_REG_TEMP_OFFSET[nr],
8968d5d45fbSJean Delvare 		data->temp_offset[nr]);
8979a61bf63SIngo Molnar 	mutex_unlock(&data->update_lock);
8988d5d45fbSJean Delvare 	return count;
8998d5d45fbSJean Delvare }
9008d5d45fbSJean Delvare 
9017ded2315SGuenter Roeck static SENSOR_DEVICE_ATTR_RW(temp1_offset, temp_offset, 0);
9027ded2315SGuenter Roeck static SENSOR_DEVICE_ATTR_RW(temp2_offset, temp_offset, 1);
9037ded2315SGuenter Roeck static SENSOR_DEVICE_ATTR_RW(temp3_offset, temp_offset, 2);
9048d5d45fbSJean Delvare 
temp_auto_point1_temp_hyst_show(struct device * dev,struct device_attribute * attr,char * buf)9057ded2315SGuenter Roeck static ssize_t temp_auto_point1_temp_hyst_show(struct device *dev,
9067ded2315SGuenter Roeck 					       struct device_attribute *attr,
9077ded2315SGuenter Roeck 					       char *buf)
9088d5d45fbSJean Delvare {
9098d5d45fbSJean Delvare 	struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr);
9108d5d45fbSJean Delvare 	int nr = sensor_attr->index;
9118d5d45fbSJean Delvare 	struct adm1026_data *data = adm1026_update_device(dev);
9128d5d45fbSJean Delvare 	return sprintf(buf, "%d\n", TEMP_FROM_REG(
9138d5d45fbSJean Delvare 		ADM1026_FAN_ACTIVATION_TEMP_HYST + data->temp_tmin[nr]));
9148d5d45fbSJean Delvare }
temp_auto_point2_temp_show(struct device * dev,struct device_attribute * attr,char * buf)9157ded2315SGuenter Roeck static ssize_t temp_auto_point2_temp_show(struct device *dev,
9167ded2315SGuenter Roeck 					  struct device_attribute *attr,
9177ded2315SGuenter Roeck 					  char *buf)
9188d5d45fbSJean Delvare {
9198d5d45fbSJean Delvare 	struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr);
9208d5d45fbSJean Delvare 	int nr = sensor_attr->index;
9218d5d45fbSJean Delvare 	struct adm1026_data *data = adm1026_update_device(dev);
9228d5d45fbSJean Delvare 	return sprintf(buf, "%d\n", TEMP_FROM_REG(data->temp_tmin[nr] +
9238d5d45fbSJean Delvare 		ADM1026_FAN_CONTROL_TEMP_RANGE));
9248d5d45fbSJean Delvare }
temp_auto_point1_temp_show(struct device * dev,struct device_attribute * attr,char * buf)9257ded2315SGuenter Roeck static ssize_t temp_auto_point1_temp_show(struct device *dev,
9267ded2315SGuenter Roeck 					  struct device_attribute *attr,
9277ded2315SGuenter Roeck 					  char *buf)
9288d5d45fbSJean Delvare {
9298d5d45fbSJean Delvare 	struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr);
9308d5d45fbSJean Delvare 	int nr = sensor_attr->index;
9318d5d45fbSJean Delvare 	struct adm1026_data *data = adm1026_update_device(dev);
9328d5d45fbSJean Delvare 	return sprintf(buf, "%d\n", TEMP_FROM_REG(data->temp_tmin[nr]));
9338d5d45fbSJean Delvare }
temp_auto_point1_temp_store(struct device * dev,struct device_attribute * attr,const char * buf,size_t count)9347ded2315SGuenter Roeck static ssize_t temp_auto_point1_temp_store(struct device *dev,
9357ded2315SGuenter Roeck 					   struct device_attribute *attr,
9367ded2315SGuenter Roeck 					   const char *buf, size_t count)
9378d5d45fbSJean Delvare {
9388d5d45fbSJean Delvare 	struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr);
9398d5d45fbSJean Delvare 	int nr = sensor_attr->index;
940b591d3c1SAxel Lin 	struct adm1026_data *data = dev_get_drvdata(dev);
941b591d3c1SAxel Lin 	struct i2c_client *client = data->client;
94286aa3e22SGuenter Roeck 	long val;
94386aa3e22SGuenter Roeck 	int err;
94486aa3e22SGuenter Roeck 
94586aa3e22SGuenter Roeck 	err = kstrtol(buf, 10, &val);
94686aa3e22SGuenter Roeck 	if (err)
94786aa3e22SGuenter Roeck 		return err;
9488d5d45fbSJean Delvare 
9499a61bf63SIngo Molnar 	mutex_lock(&data->update_lock);
9508d5d45fbSJean Delvare 	data->temp_tmin[nr] = TEMP_TO_REG(val);
9518d5d45fbSJean Delvare 	adm1026_write_value(client, ADM1026_REG_TEMP_TMIN[nr],
9528d5d45fbSJean Delvare 		data->temp_tmin[nr]);
9539a61bf63SIngo Molnar 	mutex_unlock(&data->update_lock);
9548d5d45fbSJean Delvare 	return count;
9558d5d45fbSJean Delvare }
9568d5d45fbSJean Delvare 
9577ded2315SGuenter Roeck static SENSOR_DEVICE_ATTR_RW(temp1_auto_point1_temp, temp_auto_point1_temp, 0);
9587ded2315SGuenter Roeck static SENSOR_DEVICE_ATTR_RO(temp1_auto_point1_temp_hyst,
9597ded2315SGuenter Roeck 			     temp_auto_point1_temp_hyst, 0);
9607ded2315SGuenter Roeck static SENSOR_DEVICE_ATTR_RO(temp1_auto_point2_temp, temp_auto_point2_temp, 0);
9617ded2315SGuenter Roeck static SENSOR_DEVICE_ATTR_RW(temp2_auto_point1_temp, temp_auto_point1_temp, 1);
9627ded2315SGuenter Roeck static SENSOR_DEVICE_ATTR_RO(temp2_auto_point1_temp_hyst,
9637ded2315SGuenter Roeck 			     temp_auto_point1_temp_hyst, 1);
9647ded2315SGuenter Roeck static SENSOR_DEVICE_ATTR_RO(temp2_auto_point2_temp, temp_auto_point2_temp, 1);
9657ded2315SGuenter Roeck static SENSOR_DEVICE_ATTR_RW(temp3_auto_point1_temp, temp_auto_point1_temp, 2);
9667ded2315SGuenter Roeck static SENSOR_DEVICE_ATTR_RO(temp3_auto_point1_temp_hyst,
9677ded2315SGuenter Roeck 			     temp_auto_point1_temp_hyst, 2);
9687ded2315SGuenter Roeck static SENSOR_DEVICE_ATTR_RO(temp3_auto_point2_temp, temp_auto_point2_temp, 2);
9698d5d45fbSJean Delvare 
show_temp_crit_enable(struct device * dev,struct device_attribute * attr,char * buf)9708d5d45fbSJean Delvare static ssize_t show_temp_crit_enable(struct device *dev,
9718d5d45fbSJean Delvare 		struct device_attribute *attr, char *buf)
9728d5d45fbSJean Delvare {
9738d5d45fbSJean Delvare 	struct adm1026_data *data = adm1026_update_device(dev);
9748d5d45fbSJean Delvare 	return sprintf(buf, "%d\n", (data->config1 & CFG1_THERM_HOT) >> 4);
9758d5d45fbSJean Delvare }
set_temp_crit_enable(struct device * dev,struct device_attribute * attr,const char * buf,size_t count)9768d5d45fbSJean Delvare static ssize_t set_temp_crit_enable(struct device *dev,
9778d5d45fbSJean Delvare 		struct device_attribute *attr, const char *buf, size_t count)
9788d5d45fbSJean Delvare {
979b591d3c1SAxel Lin 	struct adm1026_data *data = dev_get_drvdata(dev);
980b591d3c1SAxel Lin 	struct i2c_client *client = data->client;
98186aa3e22SGuenter Roeck 	unsigned long val;
98286aa3e22SGuenter Roeck 	int err;
9838d5d45fbSJean Delvare 
98486aa3e22SGuenter Roeck 	err = kstrtoul(buf, 10, &val);
98586aa3e22SGuenter Roeck 	if (err)
98686aa3e22SGuenter Roeck 		return err;
98786aa3e22SGuenter Roeck 
98886aa3e22SGuenter Roeck 	if (val > 1)
98986aa3e22SGuenter Roeck 		return -EINVAL;
99086aa3e22SGuenter Roeck 
9919a61bf63SIngo Molnar 	mutex_lock(&data->update_lock);
9928d5d45fbSJean Delvare 	data->config1 = (data->config1 & ~CFG1_THERM_HOT) | (val << 4);
99386aa3e22SGuenter Roeck 	adm1026_write_value(client, ADM1026_REG_CONFIG1, data->config1);
9949a61bf63SIngo Molnar 	mutex_unlock(&data->update_lock);
99586aa3e22SGuenter Roeck 
9968d5d45fbSJean Delvare 	return count;
9978d5d45fbSJean Delvare }
9988d5d45fbSJean Delvare 
9997ded2315SGuenter Roeck static DEVICE_ATTR(temp1_crit_enable, 0644, show_temp_crit_enable,
10007ded2315SGuenter Roeck 		   set_temp_crit_enable);
10017ded2315SGuenter Roeck static DEVICE_ATTR(temp2_crit_enable, 0644, show_temp_crit_enable,
10027ded2315SGuenter Roeck 		   set_temp_crit_enable);
10037ded2315SGuenter Roeck static DEVICE_ATTR(temp3_crit_enable, 0644, show_temp_crit_enable,
10047ded2315SGuenter Roeck 		   set_temp_crit_enable);
10058d5d45fbSJean Delvare 
temp_crit_show(struct device * dev,struct device_attribute * attr,char * buf)10067ded2315SGuenter Roeck static ssize_t temp_crit_show(struct device *dev,
10078d5d45fbSJean Delvare 			      struct device_attribute *attr, char *buf)
10088d5d45fbSJean Delvare {
10098d5d45fbSJean Delvare 	struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr);
10108d5d45fbSJean Delvare 	int nr = sensor_attr->index;
10118d5d45fbSJean Delvare 	struct adm1026_data *data = adm1026_update_device(dev);
10128d5d45fbSJean Delvare 	return sprintf(buf, "%d\n", TEMP_FROM_REG(data->temp_crit[nr]));
10138d5d45fbSJean Delvare }
temp_crit_store(struct device * dev,struct device_attribute * attr,const char * buf,size_t count)10147ded2315SGuenter Roeck static ssize_t temp_crit_store(struct device *dev,
10157ded2315SGuenter Roeck 			       struct device_attribute *attr, const char *buf,
10167ded2315SGuenter Roeck 			       size_t count)
10178d5d45fbSJean Delvare {
10188d5d45fbSJean Delvare 	struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr);
10198d5d45fbSJean Delvare 	int nr = sensor_attr->index;
1020b591d3c1SAxel Lin 	struct adm1026_data *data = dev_get_drvdata(dev);
1021b591d3c1SAxel Lin 	struct i2c_client *client = data->client;
102286aa3e22SGuenter Roeck 	long val;
102386aa3e22SGuenter Roeck 	int err;
102486aa3e22SGuenter Roeck 
102586aa3e22SGuenter Roeck 	err = kstrtol(buf, 10, &val);
102686aa3e22SGuenter Roeck 	if (err)
102786aa3e22SGuenter Roeck 		return err;
10288d5d45fbSJean Delvare 
10299a61bf63SIngo Molnar 	mutex_lock(&data->update_lock);
10308d5d45fbSJean Delvare 	data->temp_crit[nr] = TEMP_TO_REG(val);
10318d5d45fbSJean Delvare 	adm1026_write_value(client, ADM1026_REG_TEMP_THERM[nr],
10328d5d45fbSJean Delvare 		data->temp_crit[nr]);
10339a61bf63SIngo Molnar 	mutex_unlock(&data->update_lock);
10348d5d45fbSJean Delvare 	return count;
10358d5d45fbSJean Delvare }
10368d5d45fbSJean Delvare 
10377ded2315SGuenter Roeck static SENSOR_DEVICE_ATTR_RW(temp1_crit, temp_crit, 0);
10387ded2315SGuenter Roeck static SENSOR_DEVICE_ATTR_RW(temp2_crit, temp_crit, 1);
10397ded2315SGuenter Roeck static SENSOR_DEVICE_ATTR_RW(temp3_crit, temp_crit, 2);
10408d5d45fbSJean Delvare 
analog_out_show(struct device * dev,struct device_attribute * attr,char * buf)10416d3c213dSJulia Lawall static ssize_t analog_out_show(struct device *dev,
104286aa3e22SGuenter Roeck 			       struct device_attribute *attr, char *buf)
10438d5d45fbSJean Delvare {
10448d5d45fbSJean Delvare 	struct adm1026_data *data = adm1026_update_device(dev);
10458d5d45fbSJean Delvare 	return sprintf(buf, "%d\n", DAC_FROM_REG(data->analog_out));
10468d5d45fbSJean Delvare }
analog_out_store(struct device * dev,struct device_attribute * attr,const char * buf,size_t count)10476d3c213dSJulia Lawall static ssize_t analog_out_store(struct device *dev,
104886aa3e22SGuenter Roeck 				struct device_attribute *attr,
104986aa3e22SGuenter Roeck 				const char *buf, size_t count)
10508d5d45fbSJean Delvare {
1051b591d3c1SAxel Lin 	struct adm1026_data *data = dev_get_drvdata(dev);
1052b591d3c1SAxel Lin 	struct i2c_client *client = data->client;
105386aa3e22SGuenter Roeck 	long val;
105486aa3e22SGuenter Roeck 	int err;
105586aa3e22SGuenter Roeck 
105686aa3e22SGuenter Roeck 	err = kstrtol(buf, 10, &val);
105786aa3e22SGuenter Roeck 	if (err)
105886aa3e22SGuenter Roeck 		return err;
10598d5d45fbSJean Delvare 
10609a61bf63SIngo Molnar 	mutex_lock(&data->update_lock);
10618d5d45fbSJean Delvare 	data->analog_out = DAC_TO_REG(val);
10628d5d45fbSJean Delvare 	adm1026_write_value(client, ADM1026_REG_DAC, data->analog_out);
10639a61bf63SIngo Molnar 	mutex_unlock(&data->update_lock);
10648d5d45fbSJean Delvare 	return count;
10658d5d45fbSJean Delvare }
10668d5d45fbSJean Delvare 
10676d3c213dSJulia Lawall static DEVICE_ATTR_RW(analog_out);
10688d5d45fbSJean Delvare 
cpu0_vid_show(struct device * dev,struct device_attribute * attr,char * buf)10696d3c213dSJulia Lawall static ssize_t cpu0_vid_show(struct device *dev,
10706d3c213dSJulia Lawall 			     struct device_attribute *attr, char *buf)
10718d5d45fbSJean Delvare {
10728d5d45fbSJean Delvare 	struct adm1026_data *data = adm1026_update_device(dev);
1073a0cf354aSJean Delvare 	int vid = (data->gpio >> 11) & 0x1f;
1074a0cf354aSJean Delvare 
1075a0cf354aSJean Delvare 	dev_dbg(dev, "Setting VID from GPIO11-15.\n");
1076a0cf354aSJean Delvare 	return sprintf(buf, "%d\n", vid_from_reg(vid, data->vrm));
10778d5d45fbSJean Delvare }
107886aa3e22SGuenter Roeck 
10796d3c213dSJulia Lawall static DEVICE_ATTR_RO(cpu0_vid);
10808d5d45fbSJean Delvare 
vrm_show(struct device * dev,struct device_attribute * attr,char * buf)10816d3c213dSJulia Lawall static ssize_t vrm_show(struct device *dev, struct device_attribute *attr,
108286aa3e22SGuenter Roeck 			char *buf)
10838d5d45fbSJean Delvare {
108490d6619aSJean Delvare 	struct adm1026_data *data = dev_get_drvdata(dev);
10858d5d45fbSJean Delvare 	return sprintf(buf, "%d\n", data->vrm);
10868d5d45fbSJean Delvare }
108786aa3e22SGuenter Roeck 
vrm_store(struct device * dev,struct device_attribute * attr,const char * buf,size_t count)10886d3c213dSJulia Lawall static ssize_t vrm_store(struct device *dev, struct device_attribute *attr,
108986aa3e22SGuenter Roeck 			 const char *buf, size_t count)
10908d5d45fbSJean Delvare {
1091f67fdabfSJean Delvare 	struct adm1026_data *data = dev_get_drvdata(dev);
109286aa3e22SGuenter Roeck 	unsigned long val;
109386aa3e22SGuenter Roeck 	int err;
10948d5d45fbSJean Delvare 
109586aa3e22SGuenter Roeck 	err = kstrtoul(buf, 10, &val);
109686aa3e22SGuenter Roeck 	if (err)
109786aa3e22SGuenter Roeck 		return err;
109886aa3e22SGuenter Roeck 
1099a4461647SAxel Lin 	if (val > 255)
1100a4461647SAxel Lin 		return -EINVAL;
1101a4461647SAxel Lin 
110286aa3e22SGuenter Roeck 	data->vrm = val;
11038d5d45fbSJean Delvare 	return count;
11048d5d45fbSJean Delvare }
11058d5d45fbSJean Delvare 
11066d3c213dSJulia Lawall static DEVICE_ATTR_RW(vrm);
11078d5d45fbSJean Delvare 
alarms_show(struct device * dev,struct device_attribute * attr,char * buf)11086d3c213dSJulia Lawall static ssize_t alarms_show(struct device *dev, struct device_attribute *attr,
11096d3c213dSJulia Lawall 			   char *buf)
11108d5d45fbSJean Delvare {
11118d5d45fbSJean Delvare 	struct adm1026_data *data = adm1026_update_device(dev);
1112f67fdabfSJean Delvare 	return sprintf(buf, "%ld\n", data->alarms);
11138d5d45fbSJean Delvare }
11148d5d45fbSJean Delvare 
11156d3c213dSJulia Lawall static DEVICE_ATTR_RO(alarms);
11168d5d45fbSJean Delvare 
alarm_show(struct device * dev,struct device_attribute * attr,char * buf)11177ded2315SGuenter Roeck static ssize_t alarm_show(struct device *dev, struct device_attribute *attr,
1118a9273cb8SJean Delvare 			  char *buf)
1119a9273cb8SJean Delvare {
1120a9273cb8SJean Delvare 	struct adm1026_data *data = adm1026_update_device(dev);
1121a9273cb8SJean Delvare 	int bitnr = to_sensor_dev_attr(attr)->index;
1122a9273cb8SJean Delvare 	return sprintf(buf, "%ld\n", (data->alarms >> bitnr) & 1);
1123a9273cb8SJean Delvare }
1124a9273cb8SJean Delvare 
11257ded2315SGuenter Roeck static SENSOR_DEVICE_ATTR_RO(temp2_alarm, alarm, 0);
11267ded2315SGuenter Roeck static SENSOR_DEVICE_ATTR_RO(temp3_alarm, alarm, 1);
11277ded2315SGuenter Roeck static SENSOR_DEVICE_ATTR_RO(in9_alarm, alarm, 1);
11287ded2315SGuenter Roeck static SENSOR_DEVICE_ATTR_RO(in11_alarm, alarm, 2);
11297ded2315SGuenter Roeck static SENSOR_DEVICE_ATTR_RO(in12_alarm, alarm, 3);
11307ded2315SGuenter Roeck static SENSOR_DEVICE_ATTR_RO(in13_alarm, alarm, 4);
11317ded2315SGuenter Roeck static SENSOR_DEVICE_ATTR_RO(in14_alarm, alarm, 5);
11327ded2315SGuenter Roeck static SENSOR_DEVICE_ATTR_RO(in15_alarm, alarm, 6);
11337ded2315SGuenter Roeck static SENSOR_DEVICE_ATTR_RO(in16_alarm, alarm, 7);
11347ded2315SGuenter Roeck static SENSOR_DEVICE_ATTR_RO(in0_alarm, alarm, 8);
11357ded2315SGuenter Roeck static SENSOR_DEVICE_ATTR_RO(in1_alarm, alarm, 9);
11367ded2315SGuenter Roeck static SENSOR_DEVICE_ATTR_RO(in2_alarm, alarm, 10);
11377ded2315SGuenter Roeck static SENSOR_DEVICE_ATTR_RO(in3_alarm, alarm, 11);
11387ded2315SGuenter Roeck static SENSOR_DEVICE_ATTR_RO(in4_alarm, alarm, 12);
11397ded2315SGuenter Roeck static SENSOR_DEVICE_ATTR_RO(in5_alarm, alarm, 13);
11407ded2315SGuenter Roeck static SENSOR_DEVICE_ATTR_RO(in6_alarm, alarm, 14);
11417ded2315SGuenter Roeck static SENSOR_DEVICE_ATTR_RO(in7_alarm, alarm, 15);
11427ded2315SGuenter Roeck static SENSOR_DEVICE_ATTR_RO(fan1_alarm, alarm, 16);
11437ded2315SGuenter Roeck static SENSOR_DEVICE_ATTR_RO(fan2_alarm, alarm, 17);
11447ded2315SGuenter Roeck static SENSOR_DEVICE_ATTR_RO(fan3_alarm, alarm, 18);
11457ded2315SGuenter Roeck static SENSOR_DEVICE_ATTR_RO(fan4_alarm, alarm, 19);
11467ded2315SGuenter Roeck static SENSOR_DEVICE_ATTR_RO(fan5_alarm, alarm, 20);
11477ded2315SGuenter Roeck static SENSOR_DEVICE_ATTR_RO(fan6_alarm, alarm, 21);
11487ded2315SGuenter Roeck static SENSOR_DEVICE_ATTR_RO(fan7_alarm, alarm, 22);
11497ded2315SGuenter Roeck static SENSOR_DEVICE_ATTR_RO(fan8_alarm, alarm, 23);
11507ded2315SGuenter Roeck static SENSOR_DEVICE_ATTR_RO(temp1_alarm, alarm, 24);
11517ded2315SGuenter Roeck static SENSOR_DEVICE_ATTR_RO(in10_alarm, alarm, 25);
11527ded2315SGuenter Roeck static SENSOR_DEVICE_ATTR_RO(in8_alarm, alarm, 26);
1153a9273cb8SJean Delvare 
alarm_mask_show(struct device * dev,struct device_attribute * attr,char * buf)11546d3c213dSJulia Lawall static ssize_t alarm_mask_show(struct device *dev,
115586aa3e22SGuenter Roeck 			       struct device_attribute *attr, char *buf)
11568d5d45fbSJean Delvare {
11578d5d45fbSJean Delvare 	struct adm1026_data *data = adm1026_update_device(dev);
11588d5d45fbSJean Delvare 	return sprintf(buf, "%ld\n", data->alarm_mask);
11598d5d45fbSJean Delvare }
alarm_mask_store(struct device * dev,struct device_attribute * attr,const char * buf,size_t count)11606d3c213dSJulia Lawall static ssize_t alarm_mask_store(struct device *dev,
11616d3c213dSJulia Lawall 				struct device_attribute *attr,
116286aa3e22SGuenter Roeck 				const char *buf, size_t count)
11638d5d45fbSJean Delvare {
1164b591d3c1SAxel Lin 	struct adm1026_data *data = dev_get_drvdata(dev);
1165b591d3c1SAxel Lin 	struct i2c_client *client = data->client;
11668d5d45fbSJean Delvare 	unsigned long mask;
116786aa3e22SGuenter Roeck 	long val;
116886aa3e22SGuenter Roeck 	int err;
116986aa3e22SGuenter Roeck 
117086aa3e22SGuenter Roeck 	err = kstrtol(buf, 10, &val);
117186aa3e22SGuenter Roeck 	if (err)
117286aa3e22SGuenter Roeck 		return err;
11738d5d45fbSJean Delvare 
11749a61bf63SIngo Molnar 	mutex_lock(&data->update_lock);
11758d5d45fbSJean Delvare 	data->alarm_mask = val & 0x7fffffff;
11768d5d45fbSJean Delvare 	mask = data->alarm_mask
11778d5d45fbSJean Delvare 		| (data->gpio_mask & 0x10000 ? 0x80000000 : 0);
11788d5d45fbSJean Delvare 	adm1026_write_value(client, ADM1026_REG_MASK1,
11798d5d45fbSJean Delvare 		mask & 0xff);
11808d5d45fbSJean Delvare 	mask >>= 8;
11818d5d45fbSJean Delvare 	adm1026_write_value(client, ADM1026_REG_MASK2,
11828d5d45fbSJean Delvare 		mask & 0xff);
11838d5d45fbSJean Delvare 	mask >>= 8;
11848d5d45fbSJean Delvare 	adm1026_write_value(client, ADM1026_REG_MASK3,
11858d5d45fbSJean Delvare 		mask & 0xff);
11868d5d45fbSJean Delvare 	mask >>= 8;
11878d5d45fbSJean Delvare 	adm1026_write_value(client, ADM1026_REG_MASK4,
11888d5d45fbSJean Delvare 		mask & 0xff);
11899a61bf63SIngo Molnar 	mutex_unlock(&data->update_lock);
11908d5d45fbSJean Delvare 	return count;
11918d5d45fbSJean Delvare }
11928d5d45fbSJean Delvare 
11936d3c213dSJulia Lawall static DEVICE_ATTR_RW(alarm_mask);
11948d5d45fbSJean Delvare 
gpio_show(struct device * dev,struct device_attribute * attr,char * buf)11956d3c213dSJulia Lawall static ssize_t gpio_show(struct device *dev, struct device_attribute *attr,
119686aa3e22SGuenter Roeck 			 char *buf)
11978d5d45fbSJean Delvare {
11988d5d45fbSJean Delvare 	struct adm1026_data *data = adm1026_update_device(dev);
11998d5d45fbSJean Delvare 	return sprintf(buf, "%ld\n", data->gpio);
12008d5d45fbSJean Delvare }
gpio_store(struct device * dev,struct device_attribute * attr,const char * buf,size_t count)12016d3c213dSJulia Lawall static ssize_t gpio_store(struct device *dev, struct device_attribute *attr,
120286aa3e22SGuenter Roeck 			  const char *buf, size_t count)
12038d5d45fbSJean Delvare {
1204b591d3c1SAxel Lin 	struct adm1026_data *data = dev_get_drvdata(dev);
1205b591d3c1SAxel Lin 	struct i2c_client *client = data->client;
12068d5d45fbSJean Delvare 	long gpio;
120786aa3e22SGuenter Roeck 	long val;
120886aa3e22SGuenter Roeck 	int err;
120986aa3e22SGuenter Roeck 
121086aa3e22SGuenter Roeck 	err = kstrtol(buf, 10, &val);
121186aa3e22SGuenter Roeck 	if (err)
121286aa3e22SGuenter Roeck 		return err;
12138d5d45fbSJean Delvare 
12149a61bf63SIngo Molnar 	mutex_lock(&data->update_lock);
12158d5d45fbSJean Delvare 	data->gpio = val & 0x1ffff;
12168d5d45fbSJean Delvare 	gpio = data->gpio;
12178d5d45fbSJean Delvare 	adm1026_write_value(client, ADM1026_REG_GPIO_STATUS_0_7, gpio & 0xff);
12188d5d45fbSJean Delvare 	gpio >>= 8;
12198d5d45fbSJean Delvare 	adm1026_write_value(client, ADM1026_REG_GPIO_STATUS_8_15, gpio & 0xff);
12208d5d45fbSJean Delvare 	gpio = ((gpio >> 1) & 0x80) | (data->alarms >> 24 & 0x7f);
12218d5d45fbSJean Delvare 	adm1026_write_value(client, ADM1026_REG_STATUS4, gpio & 0xff);
12229a61bf63SIngo Molnar 	mutex_unlock(&data->update_lock);
12238d5d45fbSJean Delvare 	return count;
12248d5d45fbSJean Delvare }
12258d5d45fbSJean Delvare 
12266d3c213dSJulia Lawall static DEVICE_ATTR_RW(gpio);
12278d5d45fbSJean Delvare 
gpio_mask_show(struct device * dev,struct device_attribute * attr,char * buf)12286d3c213dSJulia Lawall static ssize_t gpio_mask_show(struct device *dev,
12296d3c213dSJulia Lawall 			      struct device_attribute *attr,
123086aa3e22SGuenter Roeck 			      char *buf)
12318d5d45fbSJean Delvare {
12328d5d45fbSJean Delvare 	struct adm1026_data *data = adm1026_update_device(dev);
12338d5d45fbSJean Delvare 	return sprintf(buf, "%ld\n", data->gpio_mask);
12348d5d45fbSJean Delvare }
gpio_mask_store(struct device * dev,struct device_attribute * attr,const char * buf,size_t count)12356d3c213dSJulia Lawall static ssize_t gpio_mask_store(struct device *dev,
12366d3c213dSJulia Lawall 			       struct device_attribute *attr, const char *buf,
12376d3c213dSJulia Lawall 			       size_t count)
12388d5d45fbSJean Delvare {
1239b591d3c1SAxel Lin 	struct adm1026_data *data = dev_get_drvdata(dev);
1240b591d3c1SAxel Lin 	struct i2c_client *client = data->client;
12418d5d45fbSJean Delvare 	long mask;
124286aa3e22SGuenter Roeck 	long val;
124386aa3e22SGuenter Roeck 	int err;
124486aa3e22SGuenter Roeck 
124586aa3e22SGuenter Roeck 	err = kstrtol(buf, 10, &val);
124686aa3e22SGuenter Roeck 	if (err)
124786aa3e22SGuenter Roeck 		return err;
12488d5d45fbSJean Delvare 
12499a61bf63SIngo Molnar 	mutex_lock(&data->update_lock);
12508d5d45fbSJean Delvare 	data->gpio_mask = val & 0x1ffff;
12518d5d45fbSJean Delvare 	mask = data->gpio_mask;
12528d5d45fbSJean Delvare 	adm1026_write_value(client, ADM1026_REG_GPIO_MASK_0_7, mask & 0xff);
12538d5d45fbSJean Delvare 	mask >>= 8;
12548d5d45fbSJean Delvare 	adm1026_write_value(client, ADM1026_REG_GPIO_MASK_8_15, mask & 0xff);
12558d5d45fbSJean Delvare 	mask = ((mask >> 1) & 0x80) | (data->alarm_mask >> 24 & 0x7f);
12568d5d45fbSJean Delvare 	adm1026_write_value(client, ADM1026_REG_MASK1, mask & 0xff);
12579a61bf63SIngo Molnar 	mutex_unlock(&data->update_lock);
12588d5d45fbSJean Delvare 	return count;
12598d5d45fbSJean Delvare }
12608d5d45fbSJean Delvare 
12616d3c213dSJulia Lawall static DEVICE_ATTR_RW(gpio_mask);
12628d5d45fbSJean Delvare 
pwm1_show(struct device * dev,struct device_attribute * attr,char * buf)12636d3c213dSJulia Lawall static ssize_t pwm1_show(struct device *dev, struct device_attribute *attr,
126486aa3e22SGuenter Roeck 			 char *buf)
12658d5d45fbSJean Delvare {
12668d5d45fbSJean Delvare 	struct adm1026_data *data = adm1026_update_device(dev);
12678d5d45fbSJean Delvare 	return sprintf(buf, "%d\n", PWM_FROM_REG(data->pwm1.pwm));
12688d5d45fbSJean Delvare }
126986aa3e22SGuenter Roeck 
pwm1_store(struct device * dev,struct device_attribute * attr,const char * buf,size_t count)12706d3c213dSJulia Lawall static ssize_t pwm1_store(struct device *dev, struct device_attribute *attr,
127186aa3e22SGuenter Roeck 			  const char *buf, size_t count)
12728d5d45fbSJean Delvare {
1273b591d3c1SAxel Lin 	struct adm1026_data *data = dev_get_drvdata(dev);
1274b591d3c1SAxel Lin 	struct i2c_client *client = data->client;
12758d5d45fbSJean Delvare 
12768d5d45fbSJean Delvare 	if (data->pwm1.enable == 1) {
127786aa3e22SGuenter Roeck 		long val;
127886aa3e22SGuenter Roeck 		int err;
127986aa3e22SGuenter Roeck 
128086aa3e22SGuenter Roeck 		err = kstrtol(buf, 10, &val);
128186aa3e22SGuenter Roeck 		if (err)
128286aa3e22SGuenter Roeck 			return err;
12838d5d45fbSJean Delvare 
12849a61bf63SIngo Molnar 		mutex_lock(&data->update_lock);
12858d5d45fbSJean Delvare 		data->pwm1.pwm = PWM_TO_REG(val);
12868d5d45fbSJean Delvare 		adm1026_write_value(client, ADM1026_REG_PWM, data->pwm1.pwm);
12879a61bf63SIngo Molnar 		mutex_unlock(&data->update_lock);
12888d5d45fbSJean Delvare 	}
12898d5d45fbSJean Delvare 	return count;
12908d5d45fbSJean Delvare }
129186aa3e22SGuenter Roeck 
temp1_auto_point1_pwm_show(struct device * dev,struct device_attribute * attr,char * buf)12926d3c213dSJulia Lawall static ssize_t temp1_auto_point1_pwm_show(struct device *dev,
12936d3c213dSJulia Lawall 					  struct device_attribute *attr,
12946d3c213dSJulia Lawall 					  char *buf)
12958d5d45fbSJean Delvare {
12968d5d45fbSJean Delvare 	struct adm1026_data *data = adm1026_update_device(dev);
12978d5d45fbSJean Delvare 	return sprintf(buf, "%d\n", data->pwm1.auto_pwm_min);
12988d5d45fbSJean Delvare }
129986aa3e22SGuenter Roeck 
temp1_auto_point1_pwm_store(struct device * dev,struct device_attribute * attr,const char * buf,size_t count)13006d3c213dSJulia Lawall static ssize_t temp1_auto_point1_pwm_store(struct device *dev,
13016d3c213dSJulia Lawall 					   struct device_attribute *attr,
13026d3c213dSJulia Lawall 					   const char *buf, size_t count)
13038d5d45fbSJean Delvare {
1304b591d3c1SAxel Lin 	struct adm1026_data *data = dev_get_drvdata(dev);
1305b591d3c1SAxel Lin 	struct i2c_client *client = data->client;
130686aa3e22SGuenter Roeck 	unsigned long val;
130786aa3e22SGuenter Roeck 	int err;
130886aa3e22SGuenter Roeck 
130986aa3e22SGuenter Roeck 	err = kstrtoul(buf, 10, &val);
131086aa3e22SGuenter Roeck 	if (err)
131186aa3e22SGuenter Roeck 		return err;
13128d5d45fbSJean Delvare 
13139a61bf63SIngo Molnar 	mutex_lock(&data->update_lock);
13142a844c14SGuenter Roeck 	data->pwm1.auto_pwm_min = clamp_val(val, 0, 255);
13158d5d45fbSJean Delvare 	if (data->pwm1.enable == 2) { /* apply immediately */
13168d5d45fbSJean Delvare 		data->pwm1.pwm = PWM_TO_REG((data->pwm1.pwm & 0x0f) |
13178d5d45fbSJean Delvare 			PWM_MIN_TO_REG(data->pwm1.auto_pwm_min));
13188d5d45fbSJean Delvare 		adm1026_write_value(client, ADM1026_REG_PWM, data->pwm1.pwm);
13198d5d45fbSJean Delvare 	}
13209a61bf63SIngo Molnar 	mutex_unlock(&data->update_lock);
13218d5d45fbSJean Delvare 	return count;
13228d5d45fbSJean Delvare }
132386aa3e22SGuenter Roeck 
temp1_auto_point2_pwm_show(struct device * dev,struct device_attribute * attr,char * buf)13246d3c213dSJulia Lawall static ssize_t temp1_auto_point2_pwm_show(struct device *dev,
13256d3c213dSJulia Lawall 					  struct device_attribute *attr,
13266d3c213dSJulia Lawall 					  char *buf)
13278d5d45fbSJean Delvare {
13288d5d45fbSJean Delvare 	return sprintf(buf, "%d\n", ADM1026_PWM_MAX);
13298d5d45fbSJean Delvare }
133086aa3e22SGuenter Roeck 
pwm1_enable_show(struct device * dev,struct device_attribute * attr,char * buf)13316d3c213dSJulia Lawall static ssize_t pwm1_enable_show(struct device *dev,
133286aa3e22SGuenter Roeck 				struct device_attribute *attr, char *buf)
13338d5d45fbSJean Delvare {
13348d5d45fbSJean Delvare 	struct adm1026_data *data = adm1026_update_device(dev);
13358d5d45fbSJean Delvare 	return sprintf(buf, "%d\n", data->pwm1.enable);
13368d5d45fbSJean Delvare }
133786aa3e22SGuenter Roeck 
pwm1_enable_store(struct device * dev,struct device_attribute * attr,const char * buf,size_t count)13386d3c213dSJulia Lawall static ssize_t pwm1_enable_store(struct device *dev,
13396d3c213dSJulia Lawall 				 struct device_attribute *attr,
134086aa3e22SGuenter Roeck 				 const char *buf, size_t count)
13418d5d45fbSJean Delvare {
1342b591d3c1SAxel Lin 	struct adm1026_data *data = dev_get_drvdata(dev);
1343b591d3c1SAxel Lin 	struct i2c_client *client = data->client;
13448d5d45fbSJean Delvare 	int old_enable;
134586aa3e22SGuenter Roeck 	unsigned long val;
134686aa3e22SGuenter Roeck 	int err;
13478d5d45fbSJean Delvare 
134886aa3e22SGuenter Roeck 	err = kstrtoul(buf, 10, &val);
134986aa3e22SGuenter Roeck 	if (err)
135086aa3e22SGuenter Roeck 		return err;
135186aa3e22SGuenter Roeck 
135286aa3e22SGuenter Roeck 	if (val >= 3)
135386aa3e22SGuenter Roeck 		return -EINVAL;
135486aa3e22SGuenter Roeck 
13559a61bf63SIngo Molnar 	mutex_lock(&data->update_lock);
13568d5d45fbSJean Delvare 	old_enable = data->pwm1.enable;
13578d5d45fbSJean Delvare 	data->pwm1.enable = val;
13588d5d45fbSJean Delvare 	data->config1 = (data->config1 & ~CFG1_PWM_AFC)
13598d5d45fbSJean Delvare 			| ((val == 2) ? CFG1_PWM_AFC : 0);
136086aa3e22SGuenter Roeck 	adm1026_write_value(client, ADM1026_REG_CONFIG1, data->config1);
13618d5d45fbSJean Delvare 	if (val == 2) { /* apply pwm1_auto_pwm_min to pwm1 */
13628d5d45fbSJean Delvare 		data->pwm1.pwm = PWM_TO_REG((data->pwm1.pwm & 0x0f) |
13638d5d45fbSJean Delvare 			PWM_MIN_TO_REG(data->pwm1.auto_pwm_min));
136486aa3e22SGuenter Roeck 		adm1026_write_value(client, ADM1026_REG_PWM, data->pwm1.pwm);
13658d5d45fbSJean Delvare 	} else if (!((old_enable == 1) && (val == 1))) {
13668d5d45fbSJean Delvare 		/* set pwm to safe value */
13678d5d45fbSJean Delvare 		data->pwm1.pwm = 255;
136886aa3e22SGuenter Roeck 		adm1026_write_value(client, ADM1026_REG_PWM, data->pwm1.pwm);
13698d5d45fbSJean Delvare 	}
13709a61bf63SIngo Molnar 	mutex_unlock(&data->update_lock);
137186aa3e22SGuenter Roeck 
13728d5d45fbSJean Delvare 	return count;
13738d5d45fbSJean Delvare }
13748d5d45fbSJean Delvare 
13758d5d45fbSJean Delvare /* enable PWM fan control */
13766d3c213dSJulia Lawall static DEVICE_ATTR_RW(pwm1);
13777ded2315SGuenter Roeck static DEVICE_ATTR(pwm2, 0644, pwm1_show, pwm1_store);
13787ded2315SGuenter Roeck static DEVICE_ATTR(pwm3, 0644, pwm1_show, pwm1_store);
13796d3c213dSJulia Lawall static DEVICE_ATTR_RW(pwm1_enable);
13807ded2315SGuenter Roeck static DEVICE_ATTR(pwm2_enable, 0644, pwm1_enable_show,
13816d3c213dSJulia Lawall 		   pwm1_enable_store);
13827ded2315SGuenter Roeck static DEVICE_ATTR(pwm3_enable, 0644, pwm1_enable_show,
13836d3c213dSJulia Lawall 		   pwm1_enable_store);
13846d3c213dSJulia Lawall static DEVICE_ATTR_RW(temp1_auto_point1_pwm);
13857ded2315SGuenter Roeck static DEVICE_ATTR(temp2_auto_point1_pwm, 0644,
13866d3c213dSJulia Lawall 		   temp1_auto_point1_pwm_show, temp1_auto_point1_pwm_store);
13877ded2315SGuenter Roeck static DEVICE_ATTR(temp3_auto_point1_pwm, 0644,
13886d3c213dSJulia Lawall 		   temp1_auto_point1_pwm_show, temp1_auto_point1_pwm_store);
13898d5d45fbSJean Delvare 
13906d3c213dSJulia Lawall static DEVICE_ATTR_RO(temp1_auto_point2_pwm);
13917ded2315SGuenter Roeck static DEVICE_ATTR(temp2_auto_point2_pwm, 0444, temp1_auto_point2_pwm_show,
13926d3c213dSJulia Lawall 		   NULL);
13937ded2315SGuenter Roeck static DEVICE_ATTR(temp3_auto_point2_pwm, 0444, temp1_auto_point2_pwm_show,
13946d3c213dSJulia Lawall 		   NULL);
13958d5d45fbSJean Delvare 
1396681c6f7aSMark M. Hoffman static struct attribute *adm1026_attributes[] = {
1397681c6f7aSMark M. Hoffman 	&sensor_dev_attr_in0_input.dev_attr.attr,
1398681c6f7aSMark M. Hoffman 	&sensor_dev_attr_in0_max.dev_attr.attr,
1399681c6f7aSMark M. Hoffman 	&sensor_dev_attr_in0_min.dev_attr.attr,
1400a9273cb8SJean Delvare 	&sensor_dev_attr_in0_alarm.dev_attr.attr,
1401681c6f7aSMark M. Hoffman 	&sensor_dev_attr_in1_input.dev_attr.attr,
1402681c6f7aSMark M. Hoffman 	&sensor_dev_attr_in1_max.dev_attr.attr,
1403681c6f7aSMark M. Hoffman 	&sensor_dev_attr_in1_min.dev_attr.attr,
1404a9273cb8SJean Delvare 	&sensor_dev_attr_in1_alarm.dev_attr.attr,
1405681c6f7aSMark M. Hoffman 	&sensor_dev_attr_in2_input.dev_attr.attr,
1406681c6f7aSMark M. Hoffman 	&sensor_dev_attr_in2_max.dev_attr.attr,
1407681c6f7aSMark M. Hoffman 	&sensor_dev_attr_in2_min.dev_attr.attr,
1408a9273cb8SJean Delvare 	&sensor_dev_attr_in2_alarm.dev_attr.attr,
1409681c6f7aSMark M. Hoffman 	&sensor_dev_attr_in3_input.dev_attr.attr,
1410681c6f7aSMark M. Hoffman 	&sensor_dev_attr_in3_max.dev_attr.attr,
1411681c6f7aSMark M. Hoffman 	&sensor_dev_attr_in3_min.dev_attr.attr,
1412a9273cb8SJean Delvare 	&sensor_dev_attr_in3_alarm.dev_attr.attr,
1413681c6f7aSMark M. Hoffman 	&sensor_dev_attr_in4_input.dev_attr.attr,
1414681c6f7aSMark M. Hoffman 	&sensor_dev_attr_in4_max.dev_attr.attr,
1415681c6f7aSMark M. Hoffman 	&sensor_dev_attr_in4_min.dev_attr.attr,
1416a9273cb8SJean Delvare 	&sensor_dev_attr_in4_alarm.dev_attr.attr,
1417681c6f7aSMark M. Hoffman 	&sensor_dev_attr_in5_input.dev_attr.attr,
1418681c6f7aSMark M. Hoffman 	&sensor_dev_attr_in5_max.dev_attr.attr,
1419681c6f7aSMark M. Hoffman 	&sensor_dev_attr_in5_min.dev_attr.attr,
1420a9273cb8SJean Delvare 	&sensor_dev_attr_in5_alarm.dev_attr.attr,
1421681c6f7aSMark M. Hoffman 	&sensor_dev_attr_in6_input.dev_attr.attr,
1422681c6f7aSMark M. Hoffman 	&sensor_dev_attr_in6_max.dev_attr.attr,
1423681c6f7aSMark M. Hoffman 	&sensor_dev_attr_in6_min.dev_attr.attr,
1424a9273cb8SJean Delvare 	&sensor_dev_attr_in6_alarm.dev_attr.attr,
1425681c6f7aSMark M. Hoffman 	&sensor_dev_attr_in7_input.dev_attr.attr,
1426681c6f7aSMark M. Hoffman 	&sensor_dev_attr_in7_max.dev_attr.attr,
1427681c6f7aSMark M. Hoffman 	&sensor_dev_attr_in7_min.dev_attr.attr,
1428a9273cb8SJean Delvare 	&sensor_dev_attr_in7_alarm.dev_attr.attr,
1429681c6f7aSMark M. Hoffman 	&sensor_dev_attr_in10_input.dev_attr.attr,
1430681c6f7aSMark M. Hoffman 	&sensor_dev_attr_in10_max.dev_attr.attr,
1431681c6f7aSMark M. Hoffman 	&sensor_dev_attr_in10_min.dev_attr.attr,
1432a9273cb8SJean Delvare 	&sensor_dev_attr_in10_alarm.dev_attr.attr,
1433681c6f7aSMark M. Hoffman 	&sensor_dev_attr_in11_input.dev_attr.attr,
1434681c6f7aSMark M. Hoffman 	&sensor_dev_attr_in11_max.dev_attr.attr,
1435681c6f7aSMark M. Hoffman 	&sensor_dev_attr_in11_min.dev_attr.attr,
1436a9273cb8SJean Delvare 	&sensor_dev_attr_in11_alarm.dev_attr.attr,
1437681c6f7aSMark M. Hoffman 	&sensor_dev_attr_in12_input.dev_attr.attr,
1438681c6f7aSMark M. Hoffman 	&sensor_dev_attr_in12_max.dev_attr.attr,
1439681c6f7aSMark M. Hoffman 	&sensor_dev_attr_in12_min.dev_attr.attr,
1440a9273cb8SJean Delvare 	&sensor_dev_attr_in12_alarm.dev_attr.attr,
1441681c6f7aSMark M. Hoffman 	&sensor_dev_attr_in13_input.dev_attr.attr,
1442681c6f7aSMark M. Hoffman 	&sensor_dev_attr_in13_max.dev_attr.attr,
1443681c6f7aSMark M. Hoffman 	&sensor_dev_attr_in13_min.dev_attr.attr,
1444a9273cb8SJean Delvare 	&sensor_dev_attr_in13_alarm.dev_attr.attr,
1445681c6f7aSMark M. Hoffman 	&sensor_dev_attr_in14_input.dev_attr.attr,
1446681c6f7aSMark M. Hoffman 	&sensor_dev_attr_in14_max.dev_attr.attr,
1447681c6f7aSMark M. Hoffman 	&sensor_dev_attr_in14_min.dev_attr.attr,
1448a9273cb8SJean Delvare 	&sensor_dev_attr_in14_alarm.dev_attr.attr,
1449681c6f7aSMark M. Hoffman 	&sensor_dev_attr_in15_input.dev_attr.attr,
1450681c6f7aSMark M. Hoffman 	&sensor_dev_attr_in15_max.dev_attr.attr,
1451681c6f7aSMark M. Hoffman 	&sensor_dev_attr_in15_min.dev_attr.attr,
1452a9273cb8SJean Delvare 	&sensor_dev_attr_in15_alarm.dev_attr.attr,
1453681c6f7aSMark M. Hoffman 	&sensor_dev_attr_in16_input.dev_attr.attr,
1454681c6f7aSMark M. Hoffman 	&sensor_dev_attr_in16_max.dev_attr.attr,
1455681c6f7aSMark M. Hoffman 	&sensor_dev_attr_in16_min.dev_attr.attr,
1456a9273cb8SJean Delvare 	&sensor_dev_attr_in16_alarm.dev_attr.attr,
1457681c6f7aSMark M. Hoffman 	&sensor_dev_attr_fan1_input.dev_attr.attr,
1458681c6f7aSMark M. Hoffman 	&sensor_dev_attr_fan1_div.dev_attr.attr,
1459681c6f7aSMark M. Hoffman 	&sensor_dev_attr_fan1_min.dev_attr.attr,
1460a9273cb8SJean Delvare 	&sensor_dev_attr_fan1_alarm.dev_attr.attr,
1461681c6f7aSMark M. Hoffman 	&sensor_dev_attr_fan2_input.dev_attr.attr,
1462681c6f7aSMark M. Hoffman 	&sensor_dev_attr_fan2_div.dev_attr.attr,
1463681c6f7aSMark M. Hoffman 	&sensor_dev_attr_fan2_min.dev_attr.attr,
1464a9273cb8SJean Delvare 	&sensor_dev_attr_fan2_alarm.dev_attr.attr,
1465681c6f7aSMark M. Hoffman 	&sensor_dev_attr_fan3_input.dev_attr.attr,
1466681c6f7aSMark M. Hoffman 	&sensor_dev_attr_fan3_div.dev_attr.attr,
1467681c6f7aSMark M. Hoffman 	&sensor_dev_attr_fan3_min.dev_attr.attr,
1468a9273cb8SJean Delvare 	&sensor_dev_attr_fan3_alarm.dev_attr.attr,
1469681c6f7aSMark M. Hoffman 	&sensor_dev_attr_fan4_input.dev_attr.attr,
1470681c6f7aSMark M. Hoffman 	&sensor_dev_attr_fan4_div.dev_attr.attr,
1471681c6f7aSMark M. Hoffman 	&sensor_dev_attr_fan4_min.dev_attr.attr,
1472a9273cb8SJean Delvare 	&sensor_dev_attr_fan4_alarm.dev_attr.attr,
1473681c6f7aSMark M. Hoffman 	&sensor_dev_attr_fan5_input.dev_attr.attr,
1474681c6f7aSMark M. Hoffman 	&sensor_dev_attr_fan5_div.dev_attr.attr,
1475681c6f7aSMark M. Hoffman 	&sensor_dev_attr_fan5_min.dev_attr.attr,
1476a9273cb8SJean Delvare 	&sensor_dev_attr_fan5_alarm.dev_attr.attr,
1477681c6f7aSMark M. Hoffman 	&sensor_dev_attr_fan6_input.dev_attr.attr,
1478681c6f7aSMark M. Hoffman 	&sensor_dev_attr_fan6_div.dev_attr.attr,
1479681c6f7aSMark M. Hoffman 	&sensor_dev_attr_fan6_min.dev_attr.attr,
1480a9273cb8SJean Delvare 	&sensor_dev_attr_fan6_alarm.dev_attr.attr,
1481681c6f7aSMark M. Hoffman 	&sensor_dev_attr_fan7_input.dev_attr.attr,
1482681c6f7aSMark M. Hoffman 	&sensor_dev_attr_fan7_div.dev_attr.attr,
1483681c6f7aSMark M. Hoffman 	&sensor_dev_attr_fan7_min.dev_attr.attr,
1484a9273cb8SJean Delvare 	&sensor_dev_attr_fan7_alarm.dev_attr.attr,
1485681c6f7aSMark M. Hoffman 	&sensor_dev_attr_fan8_input.dev_attr.attr,
1486681c6f7aSMark M. Hoffman 	&sensor_dev_attr_fan8_div.dev_attr.attr,
1487681c6f7aSMark M. Hoffman 	&sensor_dev_attr_fan8_min.dev_attr.attr,
1488a9273cb8SJean Delvare 	&sensor_dev_attr_fan8_alarm.dev_attr.attr,
1489681c6f7aSMark M. Hoffman 	&sensor_dev_attr_temp1_input.dev_attr.attr,
1490681c6f7aSMark M. Hoffman 	&sensor_dev_attr_temp1_max.dev_attr.attr,
1491681c6f7aSMark M. Hoffman 	&sensor_dev_attr_temp1_min.dev_attr.attr,
1492a9273cb8SJean Delvare 	&sensor_dev_attr_temp1_alarm.dev_attr.attr,
1493681c6f7aSMark M. Hoffman 	&sensor_dev_attr_temp2_input.dev_attr.attr,
1494681c6f7aSMark M. Hoffman 	&sensor_dev_attr_temp2_max.dev_attr.attr,
1495681c6f7aSMark M. Hoffman 	&sensor_dev_attr_temp2_min.dev_attr.attr,
1496a9273cb8SJean Delvare 	&sensor_dev_attr_temp2_alarm.dev_attr.attr,
1497681c6f7aSMark M. Hoffman 	&sensor_dev_attr_temp1_offset.dev_attr.attr,
1498681c6f7aSMark M. Hoffman 	&sensor_dev_attr_temp2_offset.dev_attr.attr,
1499681c6f7aSMark M. Hoffman 	&sensor_dev_attr_temp1_auto_point1_temp.dev_attr.attr,
1500681c6f7aSMark M. Hoffman 	&sensor_dev_attr_temp2_auto_point1_temp.dev_attr.attr,
1501681c6f7aSMark M. Hoffman 	&sensor_dev_attr_temp1_auto_point1_temp_hyst.dev_attr.attr,
1502681c6f7aSMark M. Hoffman 	&sensor_dev_attr_temp2_auto_point1_temp_hyst.dev_attr.attr,
1503681c6f7aSMark M. Hoffman 	&sensor_dev_attr_temp1_auto_point2_temp.dev_attr.attr,
1504681c6f7aSMark M. Hoffman 	&sensor_dev_attr_temp2_auto_point2_temp.dev_attr.attr,
1505681c6f7aSMark M. Hoffman 	&sensor_dev_attr_temp1_crit.dev_attr.attr,
1506681c6f7aSMark M. Hoffman 	&sensor_dev_attr_temp2_crit.dev_attr.attr,
1507681c6f7aSMark M. Hoffman 	&dev_attr_temp1_crit_enable.attr,
1508681c6f7aSMark M. Hoffman 	&dev_attr_temp2_crit_enable.attr,
1509681c6f7aSMark M. Hoffman 	&dev_attr_cpu0_vid.attr,
1510681c6f7aSMark M. Hoffman 	&dev_attr_vrm.attr,
1511681c6f7aSMark M. Hoffman 	&dev_attr_alarms.attr,
1512681c6f7aSMark M. Hoffman 	&dev_attr_alarm_mask.attr,
1513681c6f7aSMark M. Hoffman 	&dev_attr_gpio.attr,
1514681c6f7aSMark M. Hoffman 	&dev_attr_gpio_mask.attr,
1515681c6f7aSMark M. Hoffman 	&dev_attr_pwm1.attr,
1516681c6f7aSMark M. Hoffman 	&dev_attr_pwm2.attr,
1517681c6f7aSMark M. Hoffman 	&dev_attr_pwm3.attr,
1518681c6f7aSMark M. Hoffman 	&dev_attr_pwm1_enable.attr,
1519681c6f7aSMark M. Hoffman 	&dev_attr_pwm2_enable.attr,
1520681c6f7aSMark M. Hoffman 	&dev_attr_pwm3_enable.attr,
1521681c6f7aSMark M. Hoffman 	&dev_attr_temp1_auto_point1_pwm.attr,
1522681c6f7aSMark M. Hoffman 	&dev_attr_temp2_auto_point1_pwm.attr,
1523681c6f7aSMark M. Hoffman 	&dev_attr_temp1_auto_point2_pwm.attr,
1524681c6f7aSMark M. Hoffman 	&dev_attr_temp2_auto_point2_pwm.attr,
1525681c6f7aSMark M. Hoffman 	&dev_attr_analog_out.attr,
1526681c6f7aSMark M. Hoffman 	NULL
1527681c6f7aSMark M. Hoffman };
1528681c6f7aSMark M. Hoffman 
1529681c6f7aSMark M. Hoffman static const struct attribute_group adm1026_group = {
1530681c6f7aSMark M. Hoffman 	.attrs = adm1026_attributes,
1531681c6f7aSMark M. Hoffman };
1532681c6f7aSMark M. Hoffman 
15335b34dbcdSJean Delvare static struct attribute *adm1026_attributes_temp3[] = {
15345b34dbcdSJean Delvare 	&sensor_dev_attr_temp3_input.dev_attr.attr,
15355b34dbcdSJean Delvare 	&sensor_dev_attr_temp3_max.dev_attr.attr,
15365b34dbcdSJean Delvare 	&sensor_dev_attr_temp3_min.dev_attr.attr,
15375b34dbcdSJean Delvare 	&sensor_dev_attr_temp3_alarm.dev_attr.attr,
15385b34dbcdSJean Delvare 	&sensor_dev_attr_temp3_offset.dev_attr.attr,
15395b34dbcdSJean Delvare 	&sensor_dev_attr_temp3_auto_point1_temp.dev_attr.attr,
15405b34dbcdSJean Delvare 	&sensor_dev_attr_temp3_auto_point1_temp_hyst.dev_attr.attr,
15415b34dbcdSJean Delvare 	&sensor_dev_attr_temp3_auto_point2_temp.dev_attr.attr,
15425b34dbcdSJean Delvare 	&sensor_dev_attr_temp3_crit.dev_attr.attr,
15435b34dbcdSJean Delvare 	&dev_attr_temp3_crit_enable.attr,
15445b34dbcdSJean Delvare 	&dev_attr_temp3_auto_point1_pwm.attr,
15455b34dbcdSJean Delvare 	&dev_attr_temp3_auto_point2_pwm.attr,
15461d5f2c16SJean Delvare 	NULL
15475b34dbcdSJean Delvare };
15485b34dbcdSJean Delvare 
15495b34dbcdSJean Delvare static const struct attribute_group adm1026_group_temp3 = {
15505b34dbcdSJean Delvare 	.attrs = adm1026_attributes_temp3,
15515b34dbcdSJean Delvare };
15525b34dbcdSJean Delvare 
15535b34dbcdSJean Delvare static struct attribute *adm1026_attributes_in8_9[] = {
15545b34dbcdSJean Delvare 	&sensor_dev_attr_in8_input.dev_attr.attr,
15555b34dbcdSJean Delvare 	&sensor_dev_attr_in8_max.dev_attr.attr,
15565b34dbcdSJean Delvare 	&sensor_dev_attr_in8_min.dev_attr.attr,
15575b34dbcdSJean Delvare 	&sensor_dev_attr_in8_alarm.dev_attr.attr,
15585b34dbcdSJean Delvare 	&sensor_dev_attr_in9_input.dev_attr.attr,
15595b34dbcdSJean Delvare 	&sensor_dev_attr_in9_max.dev_attr.attr,
15605b34dbcdSJean Delvare 	&sensor_dev_attr_in9_min.dev_attr.attr,
15615b34dbcdSJean Delvare 	&sensor_dev_attr_in9_alarm.dev_attr.attr,
15621d5f2c16SJean Delvare 	NULL
15635b34dbcdSJean Delvare };
15645b34dbcdSJean Delvare 
15655b34dbcdSJean Delvare static const struct attribute_group adm1026_group_in8_9 = {
15665b34dbcdSJean Delvare 	.attrs = adm1026_attributes_in8_9,
15675b34dbcdSJean Delvare };
15685b34dbcdSJean Delvare 
156957f7eb0bSJean Delvare /* Return 0 if detection is successful, -ENODEV otherwise */
adm1026_detect(struct i2c_client * client,struct i2c_board_info * info)1570310ec792SJean Delvare static int adm1026_detect(struct i2c_client *client,
157157f7eb0bSJean Delvare 			  struct i2c_board_info *info)
15728d5d45fbSJean Delvare {
157357f7eb0bSJean Delvare 	struct i2c_adapter *adapter = client->adapter;
157457f7eb0bSJean Delvare 	int address = client->addr;
15758d5d45fbSJean Delvare 	int company, verstep;
15768d5d45fbSJean Delvare 
15778d5d45fbSJean Delvare 	if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA)) {
15788d5d45fbSJean Delvare 		/* We need to be able to do byte I/O */
157957f7eb0bSJean Delvare 		return -ENODEV;
1580a0393713SGuenter Roeck 	}
15818d5d45fbSJean Delvare 
15828d5d45fbSJean Delvare 	/* Now, we do the remaining detection. */
15838d5d45fbSJean Delvare 
1584f67fdabfSJean Delvare 	company = adm1026_read_value(client, ADM1026_REG_COMPANY);
1585f67fdabfSJean Delvare 	verstep = adm1026_read_value(client, ADM1026_REG_VERSTEP);
15868d5d45fbSJean Delvare 
1587b55f3757SGuenter Roeck 	dev_dbg(&adapter->dev,
1588b55f3757SGuenter Roeck 		"Detecting device at %d,0x%02x with COMPANY: 0x%02x and VERSTEP: 0x%02x\n",
1589f67fdabfSJean Delvare 		i2c_adapter_id(client->adapter), client->addr,
15908d5d45fbSJean Delvare 		company, verstep);
15918d5d45fbSJean Delvare 
159252df6440SJean Delvare 	/* Determine the chip type. */
159352df6440SJean Delvare 	dev_dbg(&adapter->dev, "Autodetecting device at %d,0x%02x...\n",
159452df6440SJean Delvare 		i2c_adapter_id(adapter), address);
15958d5d45fbSJean Delvare 	if (company == ADM1026_COMPANY_ANALOG_DEV
15968d5d45fbSJean Delvare 	    && verstep == ADM1026_VERSTEP_ADM1026) {
159752df6440SJean Delvare 		/* Analog Devices ADM1026 */
15988d5d45fbSJean Delvare 	} else if (company == ADM1026_COMPANY_ANALOG_DEV
15998d5d45fbSJean Delvare 		&& (verstep & 0xf0) == ADM1026_VERSTEP_GENERIC) {
1600b55f3757SGuenter Roeck 		dev_err(&adapter->dev,
1601b55f3757SGuenter Roeck 			"Unrecognized stepping 0x%02x. Defaulting to ADM1026.\n",
1602b55f3757SGuenter Roeck 			verstep);
16038d5d45fbSJean Delvare 	} else if ((verstep & 0xf0) == ADM1026_VERSTEP_GENERIC) {
1604b55f3757SGuenter Roeck 		dev_err(&adapter->dev,
1605b55f3757SGuenter Roeck 			"Found version/stepping 0x%02x. Assuming generic ADM1026.\n",
16068d5d45fbSJean Delvare 			verstep);
16078d5d45fbSJean Delvare 	} else {
1608885fe4b1SJean Delvare 		dev_dbg(&adapter->dev, "Autodetection failed\n");
16098d5d45fbSJean Delvare 		/* Not an ADM1026... */
161057f7eb0bSJean Delvare 		return -ENODEV;
16118d5d45fbSJean Delvare 	}
161252df6440SJean Delvare 
1613f2f394dbSWolfram Sang 	strscpy(info->type, "adm1026", I2C_NAME_SIZE);
161457f7eb0bSJean Delvare 
161557f7eb0bSJean Delvare 	return 0;
161657f7eb0bSJean Delvare }
16178d5d45fbSJean Delvare 
adm1026_print_gpio(struct i2c_client * client)161897df5566SAxel Lin static void adm1026_print_gpio(struct i2c_client *client)
161997df5566SAxel Lin {
162097df5566SAxel Lin 	struct adm1026_data *data = i2c_get_clientdata(client);
162197df5566SAxel Lin 	int i;
162297df5566SAxel Lin 
162397df5566SAxel Lin 	dev_dbg(&client->dev, "GPIO config is:\n");
162497df5566SAxel Lin 	for (i = 0; i <= 7; ++i) {
162597df5566SAxel Lin 		if (data->config2 & (1 << i)) {
162697df5566SAxel Lin 			dev_dbg(&client->dev, "\t%sGP%s%d\n",
162797df5566SAxel Lin 				data->gpio_config[i] & 0x02 ? "" : "!",
162897df5566SAxel Lin 				data->gpio_config[i] & 0x01 ? "OUT" : "IN",
162997df5566SAxel Lin 				i);
163097df5566SAxel Lin 		} else {
163197df5566SAxel Lin 			dev_dbg(&client->dev, "\tFAN%d\n", i);
163297df5566SAxel Lin 		}
163397df5566SAxel Lin 	}
163497df5566SAxel Lin 	for (i = 8; i <= 15; ++i) {
163597df5566SAxel Lin 		dev_dbg(&client->dev, "\t%sGP%s%d\n",
163697df5566SAxel Lin 			data->gpio_config[i] & 0x02 ? "" : "!",
163797df5566SAxel Lin 			data->gpio_config[i] & 0x01 ? "OUT" : "IN",
163897df5566SAxel Lin 			i);
163997df5566SAxel Lin 	}
164097df5566SAxel Lin 	if (data->config3 & CFG3_GPIO16_ENABLE) {
164197df5566SAxel Lin 		dev_dbg(&client->dev, "\t%sGP%s16\n",
164297df5566SAxel Lin 			data->gpio_config[16] & 0x02 ? "" : "!",
164397df5566SAxel Lin 			data->gpio_config[16] & 0x01 ? "OUT" : "IN");
164497df5566SAxel Lin 	} else {
164597df5566SAxel Lin 		/* GPIO16 is THERM */
164697df5566SAxel Lin 		dev_dbg(&client->dev, "\tTHERM\n");
164797df5566SAxel Lin 	}
164897df5566SAxel Lin }
164997df5566SAxel Lin 
adm1026_fixup_gpio(struct i2c_client * client)165097df5566SAxel Lin static void adm1026_fixup_gpio(struct i2c_client *client)
165197df5566SAxel Lin {
165297df5566SAxel Lin 	struct adm1026_data *data = i2c_get_clientdata(client);
165397df5566SAxel Lin 	int i;
165497df5566SAxel Lin 	int value;
165597df5566SAxel Lin 
165697df5566SAxel Lin 	/* Make the changes requested. */
165797df5566SAxel Lin 	/*
165897df5566SAxel Lin 	 * We may need to unlock/stop monitoring or soft-reset the
165997df5566SAxel Lin 	 *    chip before we can make changes.  This hasn't been
166097df5566SAxel Lin 	 *    tested much.  FIXME
166197df5566SAxel Lin 	 */
166297df5566SAxel Lin 
166397df5566SAxel Lin 	/* Make outputs */
166497df5566SAxel Lin 	for (i = 0; i <= 16; ++i) {
166597df5566SAxel Lin 		if (gpio_output[i] >= 0 && gpio_output[i] <= 16)
166697df5566SAxel Lin 			data->gpio_config[gpio_output[i]] |= 0x01;
166797df5566SAxel Lin 		/* if GPIO0-7 is output, it isn't a FAN tach */
166897df5566SAxel Lin 		if (gpio_output[i] >= 0 && gpio_output[i] <= 7)
166997df5566SAxel Lin 			data->config2 |= 1 << gpio_output[i];
167097df5566SAxel Lin 	}
167197df5566SAxel Lin 
167297df5566SAxel Lin 	/* Input overrides output */
167397df5566SAxel Lin 	for (i = 0; i <= 16; ++i) {
167497df5566SAxel Lin 		if (gpio_input[i] >= 0 && gpio_input[i] <= 16)
167597df5566SAxel Lin 			data->gpio_config[gpio_input[i]] &= ~0x01;
167697df5566SAxel Lin 		/* if GPIO0-7 is input, it isn't a FAN tach */
167797df5566SAxel Lin 		if (gpio_input[i] >= 0 && gpio_input[i] <= 7)
167897df5566SAxel Lin 			data->config2 |= 1 << gpio_input[i];
167997df5566SAxel Lin 	}
168097df5566SAxel Lin 
168197df5566SAxel Lin 	/* Inverted */
168297df5566SAxel Lin 	for (i = 0; i <= 16; ++i) {
168397df5566SAxel Lin 		if (gpio_inverted[i] >= 0 && gpio_inverted[i] <= 16)
168497df5566SAxel Lin 			data->gpio_config[gpio_inverted[i]] &= ~0x02;
168597df5566SAxel Lin 	}
168697df5566SAxel Lin 
168797df5566SAxel Lin 	/* Normal overrides inverted */
168897df5566SAxel Lin 	for (i = 0; i <= 16; ++i) {
168997df5566SAxel Lin 		if (gpio_normal[i] >= 0 && gpio_normal[i] <= 16)
169097df5566SAxel Lin 			data->gpio_config[gpio_normal[i]] |= 0x02;
169197df5566SAxel Lin 	}
169297df5566SAxel Lin 
169397df5566SAxel Lin 	/* Fan overrides input and output */
169497df5566SAxel Lin 	for (i = 0; i <= 7; ++i) {
169597df5566SAxel Lin 		if (gpio_fan[i] >= 0 && gpio_fan[i] <= 7)
169697df5566SAxel Lin 			data->config2 &= ~(1 << gpio_fan[i]);
169797df5566SAxel Lin 	}
169897df5566SAxel Lin 
169997df5566SAxel Lin 	/* Write new configs to registers */
170097df5566SAxel Lin 	adm1026_write_value(client, ADM1026_REG_CONFIG2, data->config2);
170197df5566SAxel Lin 	data->config3 = (data->config3 & 0x3f)
170297df5566SAxel Lin 			| ((data->gpio_config[16] & 0x03) << 6);
170397df5566SAxel Lin 	adm1026_write_value(client, ADM1026_REG_CONFIG3, data->config3);
170497df5566SAxel Lin 	for (i = 15, value = 0; i >= 0; --i) {
170597df5566SAxel Lin 		value <<= 2;
170697df5566SAxel Lin 		value |= data->gpio_config[i] & 0x03;
170797df5566SAxel Lin 		if ((i & 0x03) == 0) {
170897df5566SAxel Lin 			adm1026_write_value(client,
170997df5566SAxel Lin 					ADM1026_REG_GPIO_CFG_0_3 + i/4,
171097df5566SAxel Lin 					value);
171197df5566SAxel Lin 			value = 0;
171297df5566SAxel Lin 		}
171397df5566SAxel Lin 	}
171497df5566SAxel Lin 
171597df5566SAxel Lin 	/* Print the new config */
171697df5566SAxel Lin 	adm1026_print_gpio(client);
171797df5566SAxel Lin }
171897df5566SAxel Lin 
adm1026_init_client(struct i2c_client * client)171997df5566SAxel Lin static void adm1026_init_client(struct i2c_client *client)
172097df5566SAxel Lin {
172197df5566SAxel Lin 	int value, i;
172297df5566SAxel Lin 	struct adm1026_data *data = i2c_get_clientdata(client);
172397df5566SAxel Lin 
172497df5566SAxel Lin 	dev_dbg(&client->dev, "Initializing device\n");
172597df5566SAxel Lin 	/* Read chip config */
172697df5566SAxel Lin 	data->config1 = adm1026_read_value(client, ADM1026_REG_CONFIG1);
172797df5566SAxel Lin 	data->config2 = adm1026_read_value(client, ADM1026_REG_CONFIG2);
172897df5566SAxel Lin 	data->config3 = adm1026_read_value(client, ADM1026_REG_CONFIG3);
172997df5566SAxel Lin 
173097df5566SAxel Lin 	/* Inform user of chip config */
173197df5566SAxel Lin 	dev_dbg(&client->dev, "ADM1026_REG_CONFIG1 is: 0x%02x\n",
173297df5566SAxel Lin 		data->config1);
173397df5566SAxel Lin 	if ((data->config1 & CFG1_MONITOR) == 0) {
173497df5566SAxel Lin 		dev_dbg(&client->dev,
173597df5566SAxel Lin 			"Monitoring not currently enabled.\n");
173697df5566SAxel Lin 	}
173797df5566SAxel Lin 	if (data->config1 & CFG1_INT_ENABLE) {
173897df5566SAxel Lin 		dev_dbg(&client->dev,
173997df5566SAxel Lin 			"SMBALERT interrupts are enabled.\n");
174097df5566SAxel Lin 	}
174197df5566SAxel Lin 	if (data->config1 & CFG1_AIN8_9) {
174297df5566SAxel Lin 		dev_dbg(&client->dev,
174397df5566SAxel Lin 			"in8 and in9 enabled. temp3 disabled.\n");
174497df5566SAxel Lin 	} else {
174597df5566SAxel Lin 		dev_dbg(&client->dev,
174697df5566SAxel Lin 			"temp3 enabled.  in8 and in9 disabled.\n");
174797df5566SAxel Lin 	}
174897df5566SAxel Lin 	if (data->config1 & CFG1_THERM_HOT) {
174997df5566SAxel Lin 		dev_dbg(&client->dev,
175097df5566SAxel Lin 			"Automatic THERM, PWM, and temp limits enabled.\n");
175197df5566SAxel Lin 	}
175297df5566SAxel Lin 
175397df5566SAxel Lin 	if (data->config3 & CFG3_GPIO16_ENABLE) {
175497df5566SAxel Lin 		dev_dbg(&client->dev,
175597df5566SAxel Lin 			"GPIO16 enabled.  THERM pin disabled.\n");
175697df5566SAxel Lin 	} else {
175797df5566SAxel Lin 		dev_dbg(&client->dev,
175897df5566SAxel Lin 			"THERM pin enabled.  GPIO16 disabled.\n");
175997df5566SAxel Lin 	}
176097df5566SAxel Lin 	if (data->config3 & CFG3_VREF_250)
176197df5566SAxel Lin 		dev_dbg(&client->dev, "Vref is 2.50 Volts.\n");
176297df5566SAxel Lin 	else
176397df5566SAxel Lin 		dev_dbg(&client->dev, "Vref is 1.82 Volts.\n");
176497df5566SAxel Lin 	/* Read and pick apart the existing GPIO configuration */
176597df5566SAxel Lin 	value = 0;
176697df5566SAxel Lin 	for (i = 0; i <= 15; ++i) {
176797df5566SAxel Lin 		if ((i & 0x03) == 0) {
176897df5566SAxel Lin 			value = adm1026_read_value(client,
176997df5566SAxel Lin 					ADM1026_REG_GPIO_CFG_0_3 + i / 4);
177097df5566SAxel Lin 		}
177197df5566SAxel Lin 		data->gpio_config[i] = value & 0x03;
177297df5566SAxel Lin 		value >>= 2;
177397df5566SAxel Lin 	}
177497df5566SAxel Lin 	data->gpio_config[16] = (data->config3 >> 6) & 0x03;
177597df5566SAxel Lin 
177697df5566SAxel Lin 	/* ... and then print it */
177797df5566SAxel Lin 	adm1026_print_gpio(client);
177897df5566SAxel Lin 
177997df5566SAxel Lin 	/*
178097df5566SAxel Lin 	 * If the user asks us to reprogram the GPIO config, then
178197df5566SAxel Lin 	 * do it now.
178297df5566SAxel Lin 	 */
178397df5566SAxel Lin 	if (gpio_input[0] != -1 || gpio_output[0] != -1
178497df5566SAxel Lin 		|| gpio_inverted[0] != -1 || gpio_normal[0] != -1
178597df5566SAxel Lin 		|| gpio_fan[0] != -1) {
178697df5566SAxel Lin 		adm1026_fixup_gpio(client);
178797df5566SAxel Lin 	}
178897df5566SAxel Lin 
178997df5566SAxel Lin 	/*
179097df5566SAxel Lin 	 * WE INTENTIONALLY make no changes to the limits,
179197df5566SAxel Lin 	 *   offsets, pwms, fans and zones.  If they were
179297df5566SAxel Lin 	 *   configured, we don't want to mess with them.
179397df5566SAxel Lin 	 *   If they weren't, the default is 100% PWM, no
179497df5566SAxel Lin 	 *   control and will suffice until 'sensors -s'
179597df5566SAxel Lin 	 *   can be run by the user.  We DO set the default
179697df5566SAxel Lin 	 *   value for pwm1.auto_pwm_min to its maximum
179797df5566SAxel Lin 	 *   so that enabling automatic pwm fan control
179897df5566SAxel Lin 	 *   without first setting a value for pwm1.auto_pwm_min
179997df5566SAxel Lin 	 *   will not result in potentially dangerous fan speed decrease.
180097df5566SAxel Lin 	 */
180197df5566SAxel Lin 	data->pwm1.auto_pwm_min = 255;
180297df5566SAxel Lin 	/* Start monitoring */
180397df5566SAxel Lin 	value = adm1026_read_value(client, ADM1026_REG_CONFIG1);
180497df5566SAxel Lin 	/* Set MONITOR, clear interrupt acknowledge and s/w reset */
180597df5566SAxel Lin 	value = (value | CFG1_MONITOR) & (~CFG1_INT_CLEAR & ~CFG1_RESET);
180697df5566SAxel Lin 	dev_dbg(&client->dev, "Setting CONFIG to: 0x%02x\n", value);
180797df5566SAxel Lin 	data->config1 = value;
180897df5566SAxel Lin 	adm1026_write_value(client, ADM1026_REG_CONFIG1, value);
180997df5566SAxel Lin 
181097df5566SAxel Lin 	/* initialize fan_div[] to hardware defaults */
181197df5566SAxel Lin 	value = adm1026_read_value(client, ADM1026_REG_FAN_DIV_0_3) |
181297df5566SAxel Lin 		(adm1026_read_value(client, ADM1026_REG_FAN_DIV_4_7) << 8);
181397df5566SAxel Lin 	for (i = 0; i <= 7; ++i) {
181497df5566SAxel Lin 		data->fan_div[i] = DIV_FROM_REG(value & 0x03);
181597df5566SAxel Lin 		value >>= 2;
181697df5566SAxel Lin 	}
181797df5566SAxel Lin }
181897df5566SAxel Lin 
adm1026_probe(struct i2c_client * client)181967487038SStephen Kitt static int adm1026_probe(struct i2c_client *client)
182057f7eb0bSJean Delvare {
1821b591d3c1SAxel Lin 	struct device *dev = &client->dev;
1822b591d3c1SAxel Lin 	struct device *hwmon_dev;
182357f7eb0bSJean Delvare 	struct adm1026_data *data;
18248d5d45fbSJean Delvare 
1825b591d3c1SAxel Lin 	data = devm_kzalloc(dev, sizeof(struct adm1026_data), GFP_KERNEL);
18263421e212SGuenter Roeck 	if (!data)
18273421e212SGuenter Roeck 		return -ENOMEM;
182857f7eb0bSJean Delvare 
182957f7eb0bSJean Delvare 	i2c_set_clientdata(client, data);
1830b591d3c1SAxel Lin 	data->client = client;
18319a61bf63SIngo Molnar 	mutex_init(&data->update_lock);
18328d5d45fbSJean Delvare 
18338d5d45fbSJean Delvare 	/* Set the VRM version */
1834303760b4SJean Delvare 	data->vrm = vid_which_vrm();
18358d5d45fbSJean Delvare 
18368d5d45fbSJean Delvare 	/* Initialize the ADM1026 chip */
1837f67fdabfSJean Delvare 	adm1026_init_client(client);
18388d5d45fbSJean Delvare 
1839b591d3c1SAxel Lin 	/* sysfs hooks */
1840b591d3c1SAxel Lin 	data->groups[0] = &adm1026_group;
18415b34dbcdSJean Delvare 	if (data->config1 & CFG1_AIN8_9)
1842b591d3c1SAxel Lin 		data->groups[1] = &adm1026_group_in8_9;
18435b34dbcdSJean Delvare 	else
1844b591d3c1SAxel Lin 		data->groups[1] = &adm1026_group_temp3;
1845681c6f7aSMark M. Hoffman 
1846b591d3c1SAxel Lin 	hwmon_dev = devm_hwmon_device_register_with_groups(dev, client->name,
1847b591d3c1SAxel Lin 							   data, data->groups);
1848b591d3c1SAxel Lin 	return PTR_ERR_OR_ZERO(hwmon_dev);
1849681c6f7aSMark M. Hoffman }
1850681c6f7aSMark M. Hoffman 
185197df5566SAxel Lin static const struct i2c_device_id adm1026_id[] = {
185297df5566SAxel Lin 	{ "adm1026", 0 },
185397df5566SAxel Lin 	{ }
185497df5566SAxel Lin };
185597df5566SAxel Lin MODULE_DEVICE_TABLE(i2c, adm1026_id);
185697df5566SAxel Lin 
185797df5566SAxel Lin static struct i2c_driver adm1026_driver = {
185897df5566SAxel Lin 	.class		= I2C_CLASS_HWMON,
185997df5566SAxel Lin 	.driver = {
186097df5566SAxel Lin 		.name	= "adm1026",
186197df5566SAxel Lin 	},
1862*1975d167SUwe Kleine-König 	.probe		= adm1026_probe,
186397df5566SAxel Lin 	.id_table	= adm1026_id,
186497df5566SAxel Lin 	.detect		= adm1026_detect,
186597df5566SAxel Lin 	.address_list	= normal_i2c,
186697df5566SAxel Lin };
186797df5566SAxel Lin 
1868f0967eeaSAxel Lin module_i2c_driver(adm1026_driver);
18698d5d45fbSJean Delvare 
18708d5d45fbSJean Delvare MODULE_LICENSE("GPL");
18718d5d45fbSJean Delvare MODULE_AUTHOR("Philip Pokorny <ppokorny@penguincomputing.com>, "
18728d5d45fbSJean Delvare 	      "Justin Thiessen <jthiessen@penguincomputing.com>");
18738d5d45fbSJean Delvare MODULE_DESCRIPTION("ADM1026 driver");
1874