18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-or-later
28c2ecf20Sopenharmony_ci/*
38c2ecf20Sopenharmony_ci * adm1026.c - Part of lm_sensors, Linux kernel modules for hardware
48c2ecf20Sopenharmony_ci *	       monitoring
58c2ecf20Sopenharmony_ci * Copyright (C) 2002, 2003  Philip Pokorny <ppokorny@penguincomputing.com>
68c2ecf20Sopenharmony_ci * Copyright (C) 2004 Justin Thiessen <jthiessen@penguincomputing.com>
78c2ecf20Sopenharmony_ci *
88c2ecf20Sopenharmony_ci * Chip details at:
98c2ecf20Sopenharmony_ci *
108c2ecf20Sopenharmony_ci * <https://www.onsemi.com/PowerSolutions/product.do?id=ADM1026>
118c2ecf20Sopenharmony_ci */
128c2ecf20Sopenharmony_ci
138c2ecf20Sopenharmony_ci#include <linux/module.h>
148c2ecf20Sopenharmony_ci#include <linux/init.h>
158c2ecf20Sopenharmony_ci#include <linux/slab.h>
168c2ecf20Sopenharmony_ci#include <linux/jiffies.h>
178c2ecf20Sopenharmony_ci#include <linux/i2c.h>
188c2ecf20Sopenharmony_ci#include <linux/hwmon.h>
198c2ecf20Sopenharmony_ci#include <linux/hwmon-sysfs.h>
208c2ecf20Sopenharmony_ci#include <linux/hwmon-vid.h>
218c2ecf20Sopenharmony_ci#include <linux/err.h>
228c2ecf20Sopenharmony_ci#include <linux/mutex.h>
238c2ecf20Sopenharmony_ci
248c2ecf20Sopenharmony_ci/* Addresses to scan */
258c2ecf20Sopenharmony_cistatic const unsigned short normal_i2c[] = { 0x2c, 0x2d, 0x2e, I2C_CLIENT_END };
268c2ecf20Sopenharmony_ci
278c2ecf20Sopenharmony_cistatic int gpio_input[17] = { -1, -1, -1, -1, -1, -1, -1, -1, -1,
288c2ecf20Sopenharmony_ci				-1, -1, -1, -1, -1, -1, -1, -1 };
298c2ecf20Sopenharmony_cistatic int gpio_output[17] = { -1, -1, -1, -1, -1, -1, -1, -1, -1,
308c2ecf20Sopenharmony_ci				-1, -1, -1, -1, -1, -1, -1, -1 };
318c2ecf20Sopenharmony_cistatic int gpio_inverted[17] = { -1, -1, -1, -1, -1, -1, -1, -1, -1,
328c2ecf20Sopenharmony_ci				-1, -1, -1, -1, -1, -1, -1, -1 };
338c2ecf20Sopenharmony_cistatic int gpio_normal[17] = { -1, -1, -1, -1, -1, -1, -1, -1, -1,
348c2ecf20Sopenharmony_ci				-1, -1, -1, -1, -1, -1, -1, -1 };
358c2ecf20Sopenharmony_cistatic int gpio_fan[8] = { -1, -1, -1, -1, -1, -1, -1, -1 };
368c2ecf20Sopenharmony_cimodule_param_array(gpio_input, int, NULL, 0);
378c2ecf20Sopenharmony_ciMODULE_PARM_DESC(gpio_input, "List of GPIO pins (0-16) to program as inputs");
388c2ecf20Sopenharmony_cimodule_param_array(gpio_output, int, NULL, 0);
398c2ecf20Sopenharmony_ciMODULE_PARM_DESC(gpio_output,
408c2ecf20Sopenharmony_ci		 "List of GPIO pins (0-16) to program as outputs");
418c2ecf20Sopenharmony_cimodule_param_array(gpio_inverted, int, NULL, 0);
428c2ecf20Sopenharmony_ciMODULE_PARM_DESC(gpio_inverted,
438c2ecf20Sopenharmony_ci		 "List of GPIO pins (0-16) to program as inverted");
448c2ecf20Sopenharmony_cimodule_param_array(gpio_normal, int, NULL, 0);
458c2ecf20Sopenharmony_ciMODULE_PARM_DESC(gpio_normal,
468c2ecf20Sopenharmony_ci		 "List of GPIO pins (0-16) to program as normal/non-inverted");
478c2ecf20Sopenharmony_cimodule_param_array(gpio_fan, int, NULL, 0);
488c2ecf20Sopenharmony_ciMODULE_PARM_DESC(gpio_fan, "List of GPIO pins (0-7) to program as fan tachs");
498c2ecf20Sopenharmony_ci
508c2ecf20Sopenharmony_ci/* Many ADM1026 constants specified below */
518c2ecf20Sopenharmony_ci
528c2ecf20Sopenharmony_ci/* The ADM1026 registers */
538c2ecf20Sopenharmony_ci#define ADM1026_REG_CONFIG1	0x00
548c2ecf20Sopenharmony_ci#define CFG1_MONITOR		0x01
558c2ecf20Sopenharmony_ci#define CFG1_INT_ENABLE		0x02
568c2ecf20Sopenharmony_ci#define CFG1_INT_CLEAR		0x04
578c2ecf20Sopenharmony_ci#define CFG1_AIN8_9		0x08
588c2ecf20Sopenharmony_ci#define CFG1_THERM_HOT		0x10
598c2ecf20Sopenharmony_ci#define CFG1_DAC_AFC		0x20
608c2ecf20Sopenharmony_ci#define CFG1_PWM_AFC		0x40
618c2ecf20Sopenharmony_ci#define CFG1_RESET		0x80
628c2ecf20Sopenharmony_ci
638c2ecf20Sopenharmony_ci#define ADM1026_REG_CONFIG2	0x01
648c2ecf20Sopenharmony_ci/* CONFIG2 controls FAN0/GPIO0 through FAN7/GPIO7 */
658c2ecf20Sopenharmony_ci
668c2ecf20Sopenharmony_ci#define ADM1026_REG_CONFIG3	0x07
678c2ecf20Sopenharmony_ci#define CFG3_GPIO16_ENABLE	0x01
688c2ecf20Sopenharmony_ci#define CFG3_CI_CLEAR		0x02
698c2ecf20Sopenharmony_ci#define CFG3_VREF_250		0x04
708c2ecf20Sopenharmony_ci#define CFG3_GPIO16_DIR		0x40
718c2ecf20Sopenharmony_ci#define CFG3_GPIO16_POL		0x80
728c2ecf20Sopenharmony_ci
738c2ecf20Sopenharmony_ci#define ADM1026_REG_E2CONFIG	0x13
748c2ecf20Sopenharmony_ci#define E2CFG_READ		0x01
758c2ecf20Sopenharmony_ci#define E2CFG_WRITE		0x02
768c2ecf20Sopenharmony_ci#define E2CFG_ERASE		0x04
778c2ecf20Sopenharmony_ci#define E2CFG_ROM		0x08
788c2ecf20Sopenharmony_ci#define E2CFG_CLK_EXT		0x80
798c2ecf20Sopenharmony_ci
808c2ecf20Sopenharmony_ci/*
818c2ecf20Sopenharmony_ci * There are 10 general analog inputs and 7 dedicated inputs
828c2ecf20Sopenharmony_ci * They are:
838c2ecf20Sopenharmony_ci *    0 - 9  =  AIN0 - AIN9
848c2ecf20Sopenharmony_ci *       10  =  Vbat
858c2ecf20Sopenharmony_ci *       11  =  3.3V Standby
868c2ecf20Sopenharmony_ci *       12  =  3.3V Main
878c2ecf20Sopenharmony_ci *       13  =  +5V
888c2ecf20Sopenharmony_ci *       14  =  Vccp (CPU core voltage)
898c2ecf20Sopenharmony_ci *       15  =  +12V
908c2ecf20Sopenharmony_ci *       16  =  -12V
918c2ecf20Sopenharmony_ci */
928c2ecf20Sopenharmony_cistatic u16 ADM1026_REG_IN[] = {
938c2ecf20Sopenharmony_ci		0x30, 0x31, 0x32, 0x33, 0x34, 0x35,
948c2ecf20Sopenharmony_ci		0x36, 0x37, 0x27, 0x29, 0x26, 0x2a,
958c2ecf20Sopenharmony_ci		0x2b, 0x2c, 0x2d, 0x2e, 0x2f
968c2ecf20Sopenharmony_ci	};
978c2ecf20Sopenharmony_cistatic u16 ADM1026_REG_IN_MIN[] = {
988c2ecf20Sopenharmony_ci		0x58, 0x59, 0x5a, 0x5b, 0x5c, 0x5d,
998c2ecf20Sopenharmony_ci		0x5e, 0x5f, 0x6d, 0x49, 0x6b, 0x4a,
1008c2ecf20Sopenharmony_ci		0x4b, 0x4c, 0x4d, 0x4e, 0x4f
1018c2ecf20Sopenharmony_ci	};
1028c2ecf20Sopenharmony_cistatic u16 ADM1026_REG_IN_MAX[] = {
1038c2ecf20Sopenharmony_ci		0x50, 0x51, 0x52, 0x53, 0x54, 0x55,
1048c2ecf20Sopenharmony_ci		0x56, 0x57, 0x6c, 0x41, 0x6a, 0x42,
1058c2ecf20Sopenharmony_ci		0x43, 0x44, 0x45, 0x46, 0x47
1068c2ecf20Sopenharmony_ci	};
1078c2ecf20Sopenharmony_ci
1088c2ecf20Sopenharmony_ci/*
1098c2ecf20Sopenharmony_ci * Temperatures are:
1108c2ecf20Sopenharmony_ci *    0 - Internal
1118c2ecf20Sopenharmony_ci *    1 - External 1
1128c2ecf20Sopenharmony_ci *    2 - External 2
1138c2ecf20Sopenharmony_ci */
1148c2ecf20Sopenharmony_cistatic u16 ADM1026_REG_TEMP[] = { 0x1f, 0x28, 0x29 };
1158c2ecf20Sopenharmony_cistatic u16 ADM1026_REG_TEMP_MIN[] = { 0x69, 0x48, 0x49 };
1168c2ecf20Sopenharmony_cistatic u16 ADM1026_REG_TEMP_MAX[] = { 0x68, 0x40, 0x41 };
1178c2ecf20Sopenharmony_cistatic u16 ADM1026_REG_TEMP_TMIN[] = { 0x10, 0x11, 0x12 };
1188c2ecf20Sopenharmony_cistatic u16 ADM1026_REG_TEMP_THERM[] = { 0x0d, 0x0e, 0x0f };
1198c2ecf20Sopenharmony_cistatic u16 ADM1026_REG_TEMP_OFFSET[] = { 0x1e, 0x6e, 0x6f };
1208c2ecf20Sopenharmony_ci
1218c2ecf20Sopenharmony_ci#define ADM1026_REG_FAN(nr)		(0x38 + (nr))
1228c2ecf20Sopenharmony_ci#define ADM1026_REG_FAN_MIN(nr)		(0x60 + (nr))
1238c2ecf20Sopenharmony_ci#define ADM1026_REG_FAN_DIV_0_3		0x02
1248c2ecf20Sopenharmony_ci#define ADM1026_REG_FAN_DIV_4_7		0x03
1258c2ecf20Sopenharmony_ci
1268c2ecf20Sopenharmony_ci#define ADM1026_REG_DAC			0x04
1278c2ecf20Sopenharmony_ci#define ADM1026_REG_PWM			0x05
1288c2ecf20Sopenharmony_ci
1298c2ecf20Sopenharmony_ci#define ADM1026_REG_GPIO_CFG_0_3	0x08
1308c2ecf20Sopenharmony_ci#define ADM1026_REG_GPIO_CFG_4_7	0x09
1318c2ecf20Sopenharmony_ci#define ADM1026_REG_GPIO_CFG_8_11	0x0a
1328c2ecf20Sopenharmony_ci#define ADM1026_REG_GPIO_CFG_12_15	0x0b
1338c2ecf20Sopenharmony_ci/* CFG_16 in REG_CFG3 */
1348c2ecf20Sopenharmony_ci#define ADM1026_REG_GPIO_STATUS_0_7	0x24
1358c2ecf20Sopenharmony_ci#define ADM1026_REG_GPIO_STATUS_8_15	0x25
1368c2ecf20Sopenharmony_ci/* STATUS_16 in REG_STATUS4 */
1378c2ecf20Sopenharmony_ci#define ADM1026_REG_GPIO_MASK_0_7	0x1c
1388c2ecf20Sopenharmony_ci#define ADM1026_REG_GPIO_MASK_8_15	0x1d
1398c2ecf20Sopenharmony_ci/* MASK_16 in REG_MASK4 */
1408c2ecf20Sopenharmony_ci
1418c2ecf20Sopenharmony_ci#define ADM1026_REG_COMPANY		0x16
1428c2ecf20Sopenharmony_ci#define ADM1026_REG_VERSTEP		0x17
1438c2ecf20Sopenharmony_ci/* These are the recognized values for the above regs */
1448c2ecf20Sopenharmony_ci#define ADM1026_COMPANY_ANALOG_DEV	0x41
1458c2ecf20Sopenharmony_ci#define ADM1026_VERSTEP_GENERIC		0x40
1468c2ecf20Sopenharmony_ci#define ADM1026_VERSTEP_ADM1026		0x44
1478c2ecf20Sopenharmony_ci
1488c2ecf20Sopenharmony_ci#define ADM1026_REG_MASK1		0x18
1498c2ecf20Sopenharmony_ci#define ADM1026_REG_MASK2		0x19
1508c2ecf20Sopenharmony_ci#define ADM1026_REG_MASK3		0x1a
1518c2ecf20Sopenharmony_ci#define ADM1026_REG_MASK4		0x1b
1528c2ecf20Sopenharmony_ci
1538c2ecf20Sopenharmony_ci#define ADM1026_REG_STATUS1		0x20
1548c2ecf20Sopenharmony_ci#define ADM1026_REG_STATUS2		0x21
1558c2ecf20Sopenharmony_ci#define ADM1026_REG_STATUS3		0x22
1568c2ecf20Sopenharmony_ci#define ADM1026_REG_STATUS4		0x23
1578c2ecf20Sopenharmony_ci
1588c2ecf20Sopenharmony_ci#define ADM1026_FAN_ACTIVATION_TEMP_HYST -6
1598c2ecf20Sopenharmony_ci#define ADM1026_FAN_CONTROL_TEMP_RANGE	20
1608c2ecf20Sopenharmony_ci#define ADM1026_PWM_MAX			255
1618c2ecf20Sopenharmony_ci
1628c2ecf20Sopenharmony_ci/*
1638c2ecf20Sopenharmony_ci * Conversions. Rounding and limit checking is only done on the TO_REG
1648c2ecf20Sopenharmony_ci * variants. Note that you should be a bit careful with which arguments
1658c2ecf20Sopenharmony_ci * these macros are called: arguments may be evaluated more than once.
1668c2ecf20Sopenharmony_ci */
1678c2ecf20Sopenharmony_ci
1688c2ecf20Sopenharmony_ci/*
1698c2ecf20Sopenharmony_ci * IN are scaled according to built-in resistors.  These are the
1708c2ecf20Sopenharmony_ci *   voltages corresponding to 3/4 of full scale (192 or 0xc0)
1718c2ecf20Sopenharmony_ci *   NOTE: The -12V input needs an additional factor to account
1728c2ecf20Sopenharmony_ci *      for the Vref pullup resistor.
1738c2ecf20Sopenharmony_ci *      NEG12_OFFSET = SCALE * Vref / V-192 - Vref
1748c2ecf20Sopenharmony_ci *                   = 13875 * 2.50 / 1.875 - 2500
1758c2ecf20Sopenharmony_ci *                   = 16000
1768c2ecf20Sopenharmony_ci *
1778c2ecf20Sopenharmony_ci * The values in this table are based on Table II, page 15 of the
1788c2ecf20Sopenharmony_ci *    datasheet.
1798c2ecf20Sopenharmony_ci */
1808c2ecf20Sopenharmony_cistatic int adm1026_scaling[] = { /* .001 Volts */
1818c2ecf20Sopenharmony_ci		2250, 2250, 2250, 2250, 2250, 2250,
1828c2ecf20Sopenharmony_ci		1875, 1875, 1875, 1875, 3000, 3330,
1838c2ecf20Sopenharmony_ci		3330, 4995, 2250, 12000, 13875
1848c2ecf20Sopenharmony_ci	};
1858c2ecf20Sopenharmony_ci#define NEG12_OFFSET  16000
1868c2ecf20Sopenharmony_ci#define SCALE(val, from, to) (((val)*(to) + ((from)/2))/(from))
1878c2ecf20Sopenharmony_ci#define INS_TO_REG(n, val)	\
1888c2ecf20Sopenharmony_ci		SCALE(clamp_val(val, 0, 255 * adm1026_scaling[n] / 192), \
1898c2ecf20Sopenharmony_ci		      adm1026_scaling[n], 192)
1908c2ecf20Sopenharmony_ci#define INS_FROM_REG(n, val) (SCALE(val, 192, adm1026_scaling[n]))
1918c2ecf20Sopenharmony_ci
1928c2ecf20Sopenharmony_ci/*
1938c2ecf20Sopenharmony_ci * FAN speed is measured using 22.5kHz clock and counts for 2 pulses
1948c2ecf20Sopenharmony_ci *   and we assume a 2 pulse-per-rev fan tach signal
1958c2ecf20Sopenharmony_ci *      22500 kHz * 60 (sec/min) * 2 (pulse) / 2 (pulse/rev) == 1350000
1968c2ecf20Sopenharmony_ci */
1978c2ecf20Sopenharmony_ci#define FAN_TO_REG(val, div)  ((val) <= 0 ? 0xff : \
1988c2ecf20Sopenharmony_ci				clamp_val(1350000 / ((val) * (div)), \
1998c2ecf20Sopenharmony_ci					      1, 254))
2008c2ecf20Sopenharmony_ci#define FAN_FROM_REG(val, div) ((val) == 0 ? -1 : (val) == 0xff ? 0 : \
2018c2ecf20Sopenharmony_ci				1350000 / ((val) * (div)))
2028c2ecf20Sopenharmony_ci#define DIV_FROM_REG(val) (1 << (val))
2038c2ecf20Sopenharmony_ci#define DIV_TO_REG(val) ((val) >= 8 ? 3 : (val) >= 4 ? 2 : (val) >= 2 ? 1 : 0)
2048c2ecf20Sopenharmony_ci
2058c2ecf20Sopenharmony_ci/* Temperature is reported in 1 degC increments */
2068c2ecf20Sopenharmony_ci#define TEMP_TO_REG(val) DIV_ROUND_CLOSEST(clamp_val(val, -128000, 127000), \
2078c2ecf20Sopenharmony_ci					   1000)
2088c2ecf20Sopenharmony_ci#define TEMP_FROM_REG(val) ((val) * 1000)
2098c2ecf20Sopenharmony_ci#define OFFSET_TO_REG(val) DIV_ROUND_CLOSEST(clamp_val(val, -128000, 127000), \
2108c2ecf20Sopenharmony_ci					     1000)
2118c2ecf20Sopenharmony_ci#define OFFSET_FROM_REG(val) ((val) * 1000)
2128c2ecf20Sopenharmony_ci
2138c2ecf20Sopenharmony_ci#define PWM_TO_REG(val) (clamp_val(val, 0, 255))
2148c2ecf20Sopenharmony_ci#define PWM_FROM_REG(val) (val)
2158c2ecf20Sopenharmony_ci
2168c2ecf20Sopenharmony_ci#define PWM_MIN_TO_REG(val) ((val) & 0xf0)
2178c2ecf20Sopenharmony_ci#define PWM_MIN_FROM_REG(val) (((val) & 0xf0) + ((val) >> 4))
2188c2ecf20Sopenharmony_ci
2198c2ecf20Sopenharmony_ci/*
2208c2ecf20Sopenharmony_ci * Analog output is a voltage, and scaled to millivolts.  The datasheet
2218c2ecf20Sopenharmony_ci *   indicates that the DAC could be used to drive the fans, but in our
2228c2ecf20Sopenharmony_ci *   example board (Arima HDAMA) it isn't connected to the fans at all.
2238c2ecf20Sopenharmony_ci */
2248c2ecf20Sopenharmony_ci#define DAC_TO_REG(val) DIV_ROUND_CLOSEST(clamp_val(val, 0, 2500) * 255, \
2258c2ecf20Sopenharmony_ci					  2500)
2268c2ecf20Sopenharmony_ci#define DAC_FROM_REG(val) (((val) * 2500) / 255)
2278c2ecf20Sopenharmony_ci
2288c2ecf20Sopenharmony_ci/*
2298c2ecf20Sopenharmony_ci * Chip sampling rates
2308c2ecf20Sopenharmony_ci *
2318c2ecf20Sopenharmony_ci * Some sensors are not updated more frequently than once per second
2328c2ecf20Sopenharmony_ci *    so it doesn't make sense to read them more often than that.
2338c2ecf20Sopenharmony_ci *    We cache the results and return the saved data if the driver
2348c2ecf20Sopenharmony_ci *    is called again before a second has elapsed.
2358c2ecf20Sopenharmony_ci *
2368c2ecf20Sopenharmony_ci * Also, there is significant configuration data for this chip
2378c2ecf20Sopenharmony_ci *    So, we keep the config data up to date in the cache
2388c2ecf20Sopenharmony_ci *    when it is written and only sample it once every 5 *minutes*
2398c2ecf20Sopenharmony_ci */
2408c2ecf20Sopenharmony_ci#define ADM1026_DATA_INTERVAL		(1 * HZ)
2418c2ecf20Sopenharmony_ci#define ADM1026_CONFIG_INTERVAL		(5 * 60 * HZ)
2428c2ecf20Sopenharmony_ci
2438c2ecf20Sopenharmony_ci/*
2448c2ecf20Sopenharmony_ci * We allow for multiple chips in a single system.
2458c2ecf20Sopenharmony_ci *
2468c2ecf20Sopenharmony_ci * For each registered ADM1026, we need to keep state information
2478c2ecf20Sopenharmony_ci * at client->data. The adm1026_data structure is dynamically
2488c2ecf20Sopenharmony_ci * allocated, when a new client structure is allocated.
2498c2ecf20Sopenharmony_ci */
2508c2ecf20Sopenharmony_ci
2518c2ecf20Sopenharmony_cistruct pwm_data {
2528c2ecf20Sopenharmony_ci	u8 pwm;
2538c2ecf20Sopenharmony_ci	u8 enable;
2548c2ecf20Sopenharmony_ci	u8 auto_pwm_min;
2558c2ecf20Sopenharmony_ci};
2568c2ecf20Sopenharmony_ci
2578c2ecf20Sopenharmony_cistruct adm1026_data {
2588c2ecf20Sopenharmony_ci	struct i2c_client *client;
2598c2ecf20Sopenharmony_ci	const struct attribute_group *groups[3];
2608c2ecf20Sopenharmony_ci
2618c2ecf20Sopenharmony_ci	struct mutex update_lock;
2628c2ecf20Sopenharmony_ci	int valid;		/* !=0 if following fields are valid */
2638c2ecf20Sopenharmony_ci	unsigned long last_reading;	/* In jiffies */
2648c2ecf20Sopenharmony_ci	unsigned long last_config;	/* In jiffies */
2658c2ecf20Sopenharmony_ci
2668c2ecf20Sopenharmony_ci	u8 in[17];		/* Register value */
2678c2ecf20Sopenharmony_ci	u8 in_max[17];		/* Register value */
2688c2ecf20Sopenharmony_ci	u8 in_min[17];		/* Register value */
2698c2ecf20Sopenharmony_ci	s8 temp[3];		/* Register value */
2708c2ecf20Sopenharmony_ci	s8 temp_min[3];		/* Register value */
2718c2ecf20Sopenharmony_ci	s8 temp_max[3];		/* Register value */
2728c2ecf20Sopenharmony_ci	s8 temp_tmin[3];	/* Register value */
2738c2ecf20Sopenharmony_ci	s8 temp_crit[3];	/* Register value */
2748c2ecf20Sopenharmony_ci	s8 temp_offset[3];	/* Register value */
2758c2ecf20Sopenharmony_ci	u8 fan[8];		/* Register value */
2768c2ecf20Sopenharmony_ci	u8 fan_min[8];		/* Register value */
2778c2ecf20Sopenharmony_ci	u8 fan_div[8];		/* Decoded value */
2788c2ecf20Sopenharmony_ci	struct pwm_data pwm1;	/* Pwm control values */
2798c2ecf20Sopenharmony_ci	u8 vrm;			/* VRM version */
2808c2ecf20Sopenharmony_ci	u8 analog_out;		/* Register value (DAC) */
2818c2ecf20Sopenharmony_ci	long alarms;		/* Register encoding, combined */
2828c2ecf20Sopenharmony_ci	long alarm_mask;	/* Register encoding, combined */
2838c2ecf20Sopenharmony_ci	long gpio;		/* Register encoding, combined */
2848c2ecf20Sopenharmony_ci	long gpio_mask;		/* Register encoding, combined */
2858c2ecf20Sopenharmony_ci	u8 gpio_config[17];	/* Decoded value */
2868c2ecf20Sopenharmony_ci	u8 config1;		/* Register value */
2878c2ecf20Sopenharmony_ci	u8 config2;		/* Register value */
2888c2ecf20Sopenharmony_ci	u8 config3;		/* Register value */
2898c2ecf20Sopenharmony_ci};
2908c2ecf20Sopenharmony_ci
2918c2ecf20Sopenharmony_cistatic int adm1026_read_value(struct i2c_client *client, u8 reg)
2928c2ecf20Sopenharmony_ci{
2938c2ecf20Sopenharmony_ci	int res;
2948c2ecf20Sopenharmony_ci
2958c2ecf20Sopenharmony_ci	if (reg < 0x80) {
2968c2ecf20Sopenharmony_ci		/* "RAM" locations */
2978c2ecf20Sopenharmony_ci		res = i2c_smbus_read_byte_data(client, reg) & 0xff;
2988c2ecf20Sopenharmony_ci	} else {
2998c2ecf20Sopenharmony_ci		/* EEPROM, do nothing */
3008c2ecf20Sopenharmony_ci		res = 0;
3018c2ecf20Sopenharmony_ci	}
3028c2ecf20Sopenharmony_ci	return res;
3038c2ecf20Sopenharmony_ci}
3048c2ecf20Sopenharmony_ci
3058c2ecf20Sopenharmony_cistatic int adm1026_write_value(struct i2c_client *client, u8 reg, int value)
3068c2ecf20Sopenharmony_ci{
3078c2ecf20Sopenharmony_ci	int res;
3088c2ecf20Sopenharmony_ci
3098c2ecf20Sopenharmony_ci	if (reg < 0x80) {
3108c2ecf20Sopenharmony_ci		/* "RAM" locations */
3118c2ecf20Sopenharmony_ci		res = i2c_smbus_write_byte_data(client, reg, value);
3128c2ecf20Sopenharmony_ci	} else {
3138c2ecf20Sopenharmony_ci		/* EEPROM, do nothing */
3148c2ecf20Sopenharmony_ci		res = 0;
3158c2ecf20Sopenharmony_ci	}
3168c2ecf20Sopenharmony_ci	return res;
3178c2ecf20Sopenharmony_ci}
3188c2ecf20Sopenharmony_ci
3198c2ecf20Sopenharmony_cistatic struct adm1026_data *adm1026_update_device(struct device *dev)
3208c2ecf20Sopenharmony_ci{
3218c2ecf20Sopenharmony_ci	struct adm1026_data *data = dev_get_drvdata(dev);
3228c2ecf20Sopenharmony_ci	struct i2c_client *client = data->client;
3238c2ecf20Sopenharmony_ci	int i;
3248c2ecf20Sopenharmony_ci	long value, alarms, gpio;
3258c2ecf20Sopenharmony_ci
3268c2ecf20Sopenharmony_ci	mutex_lock(&data->update_lock);
3278c2ecf20Sopenharmony_ci	if (!data->valid
3288c2ecf20Sopenharmony_ci	    || time_after(jiffies,
3298c2ecf20Sopenharmony_ci			  data->last_reading + ADM1026_DATA_INTERVAL)) {
3308c2ecf20Sopenharmony_ci		/* Things that change quickly */
3318c2ecf20Sopenharmony_ci		dev_dbg(&client->dev, "Reading sensor values\n");
3328c2ecf20Sopenharmony_ci		for (i = 0; i <= 16; ++i) {
3338c2ecf20Sopenharmony_ci			data->in[i] =
3348c2ecf20Sopenharmony_ci			    adm1026_read_value(client, ADM1026_REG_IN[i]);
3358c2ecf20Sopenharmony_ci		}
3368c2ecf20Sopenharmony_ci
3378c2ecf20Sopenharmony_ci		for (i = 0; i <= 7; ++i) {
3388c2ecf20Sopenharmony_ci			data->fan[i] =
3398c2ecf20Sopenharmony_ci			    adm1026_read_value(client, ADM1026_REG_FAN(i));
3408c2ecf20Sopenharmony_ci		}
3418c2ecf20Sopenharmony_ci
3428c2ecf20Sopenharmony_ci		for (i = 0; i <= 2; ++i) {
3438c2ecf20Sopenharmony_ci			/*
3448c2ecf20Sopenharmony_ci			 * NOTE: temp[] is s8 and we assume 2's complement
3458c2ecf20Sopenharmony_ci			 *   "conversion" in the assignment
3468c2ecf20Sopenharmony_ci			 */
3478c2ecf20Sopenharmony_ci			data->temp[i] =
3488c2ecf20Sopenharmony_ci			    adm1026_read_value(client, ADM1026_REG_TEMP[i]);
3498c2ecf20Sopenharmony_ci		}
3508c2ecf20Sopenharmony_ci
3518c2ecf20Sopenharmony_ci		data->pwm1.pwm = adm1026_read_value(client,
3528c2ecf20Sopenharmony_ci			ADM1026_REG_PWM);
3538c2ecf20Sopenharmony_ci		data->analog_out = adm1026_read_value(client,
3548c2ecf20Sopenharmony_ci			ADM1026_REG_DAC);
3558c2ecf20Sopenharmony_ci		/* GPIO16 is MSbit of alarms, move it to gpio */
3568c2ecf20Sopenharmony_ci		alarms = adm1026_read_value(client, ADM1026_REG_STATUS4);
3578c2ecf20Sopenharmony_ci		gpio = alarms & 0x80 ? 0x0100 : 0; /* GPIO16 */
3588c2ecf20Sopenharmony_ci		alarms &= 0x7f;
3598c2ecf20Sopenharmony_ci		alarms <<= 8;
3608c2ecf20Sopenharmony_ci		alarms |= adm1026_read_value(client, ADM1026_REG_STATUS3);
3618c2ecf20Sopenharmony_ci		alarms <<= 8;
3628c2ecf20Sopenharmony_ci		alarms |= adm1026_read_value(client, ADM1026_REG_STATUS2);
3638c2ecf20Sopenharmony_ci		alarms <<= 8;
3648c2ecf20Sopenharmony_ci		alarms |= adm1026_read_value(client, ADM1026_REG_STATUS1);
3658c2ecf20Sopenharmony_ci		data->alarms = alarms;
3668c2ecf20Sopenharmony_ci
3678c2ecf20Sopenharmony_ci		/* Read the GPIO values */
3688c2ecf20Sopenharmony_ci		gpio |= adm1026_read_value(client,
3698c2ecf20Sopenharmony_ci			ADM1026_REG_GPIO_STATUS_8_15);
3708c2ecf20Sopenharmony_ci		gpio <<= 8;
3718c2ecf20Sopenharmony_ci		gpio |= adm1026_read_value(client,
3728c2ecf20Sopenharmony_ci			ADM1026_REG_GPIO_STATUS_0_7);
3738c2ecf20Sopenharmony_ci		data->gpio = gpio;
3748c2ecf20Sopenharmony_ci
3758c2ecf20Sopenharmony_ci		data->last_reading = jiffies;
3768c2ecf20Sopenharmony_ci	}	/* last_reading */
3778c2ecf20Sopenharmony_ci
3788c2ecf20Sopenharmony_ci	if (!data->valid ||
3798c2ecf20Sopenharmony_ci	    time_after(jiffies, data->last_config + ADM1026_CONFIG_INTERVAL)) {
3808c2ecf20Sopenharmony_ci		/* Things that don't change often */
3818c2ecf20Sopenharmony_ci		dev_dbg(&client->dev, "Reading config values\n");
3828c2ecf20Sopenharmony_ci		for (i = 0; i <= 16; ++i) {
3838c2ecf20Sopenharmony_ci			data->in_min[i] = adm1026_read_value(client,
3848c2ecf20Sopenharmony_ci				ADM1026_REG_IN_MIN[i]);
3858c2ecf20Sopenharmony_ci			data->in_max[i] = adm1026_read_value(client,
3868c2ecf20Sopenharmony_ci				ADM1026_REG_IN_MAX[i]);
3878c2ecf20Sopenharmony_ci		}
3888c2ecf20Sopenharmony_ci
3898c2ecf20Sopenharmony_ci		value = adm1026_read_value(client, ADM1026_REG_FAN_DIV_0_3)
3908c2ecf20Sopenharmony_ci			| (adm1026_read_value(client, ADM1026_REG_FAN_DIV_4_7)
3918c2ecf20Sopenharmony_ci			<< 8);
3928c2ecf20Sopenharmony_ci		for (i = 0; i <= 7; ++i) {
3938c2ecf20Sopenharmony_ci			data->fan_min[i] = adm1026_read_value(client,
3948c2ecf20Sopenharmony_ci				ADM1026_REG_FAN_MIN(i));
3958c2ecf20Sopenharmony_ci			data->fan_div[i] = DIV_FROM_REG(value & 0x03);
3968c2ecf20Sopenharmony_ci			value >>= 2;
3978c2ecf20Sopenharmony_ci		}
3988c2ecf20Sopenharmony_ci
3998c2ecf20Sopenharmony_ci		for (i = 0; i <= 2; ++i) {
4008c2ecf20Sopenharmony_ci			/*
4018c2ecf20Sopenharmony_ci			 * NOTE: temp_xxx[] are s8 and we assume 2's
4028c2ecf20Sopenharmony_ci			 *    complement "conversion" in the assignment
4038c2ecf20Sopenharmony_ci			 */
4048c2ecf20Sopenharmony_ci			data->temp_min[i] = adm1026_read_value(client,
4058c2ecf20Sopenharmony_ci				ADM1026_REG_TEMP_MIN[i]);
4068c2ecf20Sopenharmony_ci			data->temp_max[i] = adm1026_read_value(client,
4078c2ecf20Sopenharmony_ci				ADM1026_REG_TEMP_MAX[i]);
4088c2ecf20Sopenharmony_ci			data->temp_tmin[i] = adm1026_read_value(client,
4098c2ecf20Sopenharmony_ci				ADM1026_REG_TEMP_TMIN[i]);
4108c2ecf20Sopenharmony_ci			data->temp_crit[i] = adm1026_read_value(client,
4118c2ecf20Sopenharmony_ci				ADM1026_REG_TEMP_THERM[i]);
4128c2ecf20Sopenharmony_ci			data->temp_offset[i] = adm1026_read_value(client,
4138c2ecf20Sopenharmony_ci				ADM1026_REG_TEMP_OFFSET[i]);
4148c2ecf20Sopenharmony_ci		}
4158c2ecf20Sopenharmony_ci
4168c2ecf20Sopenharmony_ci		/* Read the STATUS/alarm masks */
4178c2ecf20Sopenharmony_ci		alarms = adm1026_read_value(client, ADM1026_REG_MASK4);
4188c2ecf20Sopenharmony_ci		gpio = alarms & 0x80 ? 0x0100 : 0; /* GPIO16 */
4198c2ecf20Sopenharmony_ci		alarms = (alarms & 0x7f) << 8;
4208c2ecf20Sopenharmony_ci		alarms |= adm1026_read_value(client, ADM1026_REG_MASK3);
4218c2ecf20Sopenharmony_ci		alarms <<= 8;
4228c2ecf20Sopenharmony_ci		alarms |= adm1026_read_value(client, ADM1026_REG_MASK2);
4238c2ecf20Sopenharmony_ci		alarms <<= 8;
4248c2ecf20Sopenharmony_ci		alarms |= adm1026_read_value(client, ADM1026_REG_MASK1);
4258c2ecf20Sopenharmony_ci		data->alarm_mask = alarms;
4268c2ecf20Sopenharmony_ci
4278c2ecf20Sopenharmony_ci		/* Read the GPIO values */
4288c2ecf20Sopenharmony_ci		gpio |= adm1026_read_value(client,
4298c2ecf20Sopenharmony_ci			ADM1026_REG_GPIO_MASK_8_15);
4308c2ecf20Sopenharmony_ci		gpio <<= 8;
4318c2ecf20Sopenharmony_ci		gpio |= adm1026_read_value(client, ADM1026_REG_GPIO_MASK_0_7);
4328c2ecf20Sopenharmony_ci		data->gpio_mask = gpio;
4338c2ecf20Sopenharmony_ci
4348c2ecf20Sopenharmony_ci		/* Read various values from CONFIG1 */
4358c2ecf20Sopenharmony_ci		data->config1 = adm1026_read_value(client,
4368c2ecf20Sopenharmony_ci			ADM1026_REG_CONFIG1);
4378c2ecf20Sopenharmony_ci		if (data->config1 & CFG1_PWM_AFC) {
4388c2ecf20Sopenharmony_ci			data->pwm1.enable = 2;
4398c2ecf20Sopenharmony_ci			data->pwm1.auto_pwm_min =
4408c2ecf20Sopenharmony_ci				PWM_MIN_FROM_REG(data->pwm1.pwm);
4418c2ecf20Sopenharmony_ci		}
4428c2ecf20Sopenharmony_ci		/* Read the GPIO config */
4438c2ecf20Sopenharmony_ci		data->config2 = adm1026_read_value(client,
4448c2ecf20Sopenharmony_ci			ADM1026_REG_CONFIG2);
4458c2ecf20Sopenharmony_ci		data->config3 = adm1026_read_value(client,
4468c2ecf20Sopenharmony_ci			ADM1026_REG_CONFIG3);
4478c2ecf20Sopenharmony_ci		data->gpio_config[16] = (data->config3 >> 6) & 0x03;
4488c2ecf20Sopenharmony_ci
4498c2ecf20Sopenharmony_ci		value = 0;
4508c2ecf20Sopenharmony_ci		for (i = 0; i <= 15; ++i) {
4518c2ecf20Sopenharmony_ci			if ((i & 0x03) == 0) {
4528c2ecf20Sopenharmony_ci				value = adm1026_read_value(client,
4538c2ecf20Sopenharmony_ci					    ADM1026_REG_GPIO_CFG_0_3 + i/4);
4548c2ecf20Sopenharmony_ci			}
4558c2ecf20Sopenharmony_ci			data->gpio_config[i] = value & 0x03;
4568c2ecf20Sopenharmony_ci			value >>= 2;
4578c2ecf20Sopenharmony_ci		}
4588c2ecf20Sopenharmony_ci
4598c2ecf20Sopenharmony_ci		data->last_config = jiffies;
4608c2ecf20Sopenharmony_ci	}	/* last_config */
4618c2ecf20Sopenharmony_ci
4628c2ecf20Sopenharmony_ci	data->valid = 1;
4638c2ecf20Sopenharmony_ci	mutex_unlock(&data->update_lock);
4648c2ecf20Sopenharmony_ci	return data;
4658c2ecf20Sopenharmony_ci}
4668c2ecf20Sopenharmony_ci
4678c2ecf20Sopenharmony_cistatic ssize_t in_show(struct device *dev, struct device_attribute *attr,
4688c2ecf20Sopenharmony_ci		       char *buf)
4698c2ecf20Sopenharmony_ci{
4708c2ecf20Sopenharmony_ci	struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr);
4718c2ecf20Sopenharmony_ci	int nr = sensor_attr->index;
4728c2ecf20Sopenharmony_ci	struct adm1026_data *data = adm1026_update_device(dev);
4738c2ecf20Sopenharmony_ci	return sprintf(buf, "%d\n", INS_FROM_REG(nr, data->in[nr]));
4748c2ecf20Sopenharmony_ci}
4758c2ecf20Sopenharmony_cistatic ssize_t in_min_show(struct device *dev, struct device_attribute *attr,
4768c2ecf20Sopenharmony_ci			   char *buf)
4778c2ecf20Sopenharmony_ci{
4788c2ecf20Sopenharmony_ci	struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr);
4798c2ecf20Sopenharmony_ci	int nr = sensor_attr->index;
4808c2ecf20Sopenharmony_ci	struct adm1026_data *data = adm1026_update_device(dev);
4818c2ecf20Sopenharmony_ci	return sprintf(buf, "%d\n", INS_FROM_REG(nr, data->in_min[nr]));
4828c2ecf20Sopenharmony_ci}
4838c2ecf20Sopenharmony_cistatic ssize_t in_min_store(struct device *dev, struct device_attribute *attr,
4848c2ecf20Sopenharmony_ci			    const char *buf, size_t count)
4858c2ecf20Sopenharmony_ci{
4868c2ecf20Sopenharmony_ci	struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr);
4878c2ecf20Sopenharmony_ci	int nr = sensor_attr->index;
4888c2ecf20Sopenharmony_ci	struct adm1026_data *data = dev_get_drvdata(dev);
4898c2ecf20Sopenharmony_ci	struct i2c_client *client = data->client;
4908c2ecf20Sopenharmony_ci	long val;
4918c2ecf20Sopenharmony_ci	int err;
4928c2ecf20Sopenharmony_ci
4938c2ecf20Sopenharmony_ci	err = kstrtol(buf, 10, &val);
4948c2ecf20Sopenharmony_ci	if (err)
4958c2ecf20Sopenharmony_ci		return err;
4968c2ecf20Sopenharmony_ci
4978c2ecf20Sopenharmony_ci	mutex_lock(&data->update_lock);
4988c2ecf20Sopenharmony_ci	data->in_min[nr] = INS_TO_REG(nr, val);
4998c2ecf20Sopenharmony_ci	adm1026_write_value(client, ADM1026_REG_IN_MIN[nr], data->in_min[nr]);
5008c2ecf20Sopenharmony_ci	mutex_unlock(&data->update_lock);
5018c2ecf20Sopenharmony_ci	return count;
5028c2ecf20Sopenharmony_ci}
5038c2ecf20Sopenharmony_cistatic ssize_t in_max_show(struct device *dev, struct device_attribute *attr,
5048c2ecf20Sopenharmony_ci			   char *buf)
5058c2ecf20Sopenharmony_ci{
5068c2ecf20Sopenharmony_ci	struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr);
5078c2ecf20Sopenharmony_ci	int nr = sensor_attr->index;
5088c2ecf20Sopenharmony_ci	struct adm1026_data *data = adm1026_update_device(dev);
5098c2ecf20Sopenharmony_ci	return sprintf(buf, "%d\n", INS_FROM_REG(nr, data->in_max[nr]));
5108c2ecf20Sopenharmony_ci}
5118c2ecf20Sopenharmony_cistatic ssize_t in_max_store(struct device *dev, struct device_attribute *attr,
5128c2ecf20Sopenharmony_ci			    const char *buf, size_t count)
5138c2ecf20Sopenharmony_ci{
5148c2ecf20Sopenharmony_ci	struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr);
5158c2ecf20Sopenharmony_ci	int nr = sensor_attr->index;
5168c2ecf20Sopenharmony_ci	struct adm1026_data *data = dev_get_drvdata(dev);
5178c2ecf20Sopenharmony_ci	struct i2c_client *client = data->client;
5188c2ecf20Sopenharmony_ci	long val;
5198c2ecf20Sopenharmony_ci	int err;
5208c2ecf20Sopenharmony_ci
5218c2ecf20Sopenharmony_ci	err = kstrtol(buf, 10, &val);
5228c2ecf20Sopenharmony_ci	if (err)
5238c2ecf20Sopenharmony_ci		return err;
5248c2ecf20Sopenharmony_ci
5258c2ecf20Sopenharmony_ci	mutex_lock(&data->update_lock);
5268c2ecf20Sopenharmony_ci	data->in_max[nr] = INS_TO_REG(nr, val);
5278c2ecf20Sopenharmony_ci	adm1026_write_value(client, ADM1026_REG_IN_MAX[nr], data->in_max[nr]);
5288c2ecf20Sopenharmony_ci	mutex_unlock(&data->update_lock);
5298c2ecf20Sopenharmony_ci	return count;
5308c2ecf20Sopenharmony_ci}
5318c2ecf20Sopenharmony_ci
5328c2ecf20Sopenharmony_cistatic SENSOR_DEVICE_ATTR_RO(in0_input, in, 0);
5338c2ecf20Sopenharmony_cistatic SENSOR_DEVICE_ATTR_RW(in0_min, in_min, 0);
5348c2ecf20Sopenharmony_cistatic SENSOR_DEVICE_ATTR_RW(in0_max, in_max, 0);
5358c2ecf20Sopenharmony_cistatic SENSOR_DEVICE_ATTR_RO(in1_input, in, 1);
5368c2ecf20Sopenharmony_cistatic SENSOR_DEVICE_ATTR_RW(in1_min, in_min, 1);
5378c2ecf20Sopenharmony_cistatic SENSOR_DEVICE_ATTR_RW(in1_max, in_max, 1);
5388c2ecf20Sopenharmony_cistatic SENSOR_DEVICE_ATTR_RO(in2_input, in, 2);
5398c2ecf20Sopenharmony_cistatic SENSOR_DEVICE_ATTR_RW(in2_min, in_min, 2);
5408c2ecf20Sopenharmony_cistatic SENSOR_DEVICE_ATTR_RW(in2_max, in_max, 2);
5418c2ecf20Sopenharmony_cistatic SENSOR_DEVICE_ATTR_RO(in3_input, in, 3);
5428c2ecf20Sopenharmony_cistatic SENSOR_DEVICE_ATTR_RW(in3_min, in_min, 3);
5438c2ecf20Sopenharmony_cistatic SENSOR_DEVICE_ATTR_RW(in3_max, in_max, 3);
5448c2ecf20Sopenharmony_cistatic SENSOR_DEVICE_ATTR_RO(in4_input, in, 4);
5458c2ecf20Sopenharmony_cistatic SENSOR_DEVICE_ATTR_RW(in4_min, in_min, 4);
5468c2ecf20Sopenharmony_cistatic SENSOR_DEVICE_ATTR_RW(in4_max, in_max, 4);
5478c2ecf20Sopenharmony_cistatic SENSOR_DEVICE_ATTR_RO(in5_input, in, 5);
5488c2ecf20Sopenharmony_cistatic SENSOR_DEVICE_ATTR_RW(in5_min, in_min, 5);
5498c2ecf20Sopenharmony_cistatic SENSOR_DEVICE_ATTR_RW(in5_max, in_max, 5);
5508c2ecf20Sopenharmony_cistatic SENSOR_DEVICE_ATTR_RO(in6_input, in, 6);
5518c2ecf20Sopenharmony_cistatic SENSOR_DEVICE_ATTR_RW(in6_min, in_min, 6);
5528c2ecf20Sopenharmony_cistatic SENSOR_DEVICE_ATTR_RW(in6_max, in_max, 6);
5538c2ecf20Sopenharmony_cistatic SENSOR_DEVICE_ATTR_RO(in7_input, in, 7);
5548c2ecf20Sopenharmony_cistatic SENSOR_DEVICE_ATTR_RW(in7_min, in_min, 7);
5558c2ecf20Sopenharmony_cistatic SENSOR_DEVICE_ATTR_RW(in7_max, in_max, 7);
5568c2ecf20Sopenharmony_cistatic SENSOR_DEVICE_ATTR_RO(in8_input, in, 8);
5578c2ecf20Sopenharmony_cistatic SENSOR_DEVICE_ATTR_RW(in8_min, in_min, 8);
5588c2ecf20Sopenharmony_cistatic SENSOR_DEVICE_ATTR_RW(in8_max, in_max, 8);
5598c2ecf20Sopenharmony_cistatic SENSOR_DEVICE_ATTR_RO(in9_input, in, 9);
5608c2ecf20Sopenharmony_cistatic SENSOR_DEVICE_ATTR_RW(in9_min, in_min, 9);
5618c2ecf20Sopenharmony_cistatic SENSOR_DEVICE_ATTR_RW(in9_max, in_max, 9);
5628c2ecf20Sopenharmony_cistatic SENSOR_DEVICE_ATTR_RO(in10_input, in, 10);
5638c2ecf20Sopenharmony_cistatic SENSOR_DEVICE_ATTR_RW(in10_min, in_min, 10);
5648c2ecf20Sopenharmony_cistatic SENSOR_DEVICE_ATTR_RW(in10_max, in_max, 10);
5658c2ecf20Sopenharmony_cistatic SENSOR_DEVICE_ATTR_RO(in11_input, in, 11);
5668c2ecf20Sopenharmony_cistatic SENSOR_DEVICE_ATTR_RW(in11_min, in_min, 11);
5678c2ecf20Sopenharmony_cistatic SENSOR_DEVICE_ATTR_RW(in11_max, in_max, 11);
5688c2ecf20Sopenharmony_cistatic SENSOR_DEVICE_ATTR_RO(in12_input, in, 12);
5698c2ecf20Sopenharmony_cistatic SENSOR_DEVICE_ATTR_RW(in12_min, in_min, 12);
5708c2ecf20Sopenharmony_cistatic SENSOR_DEVICE_ATTR_RW(in12_max, in_max, 12);
5718c2ecf20Sopenharmony_cistatic SENSOR_DEVICE_ATTR_RO(in13_input, in, 13);
5728c2ecf20Sopenharmony_cistatic SENSOR_DEVICE_ATTR_RW(in13_min, in_min, 13);
5738c2ecf20Sopenharmony_cistatic SENSOR_DEVICE_ATTR_RW(in13_max, in_max, 13);
5748c2ecf20Sopenharmony_cistatic SENSOR_DEVICE_ATTR_RO(in14_input, in, 14);
5758c2ecf20Sopenharmony_cistatic SENSOR_DEVICE_ATTR_RW(in14_min, in_min, 14);
5768c2ecf20Sopenharmony_cistatic SENSOR_DEVICE_ATTR_RW(in14_max, in_max, 14);
5778c2ecf20Sopenharmony_cistatic SENSOR_DEVICE_ATTR_RO(in15_input, in, 15);
5788c2ecf20Sopenharmony_cistatic SENSOR_DEVICE_ATTR_RW(in15_min, in_min, 15);
5798c2ecf20Sopenharmony_cistatic SENSOR_DEVICE_ATTR_RW(in15_max, in_max, 15);
5808c2ecf20Sopenharmony_ci
5818c2ecf20Sopenharmony_cistatic ssize_t in16_show(struct device *dev, struct device_attribute *attr,
5828c2ecf20Sopenharmony_ci			 char *buf)
5838c2ecf20Sopenharmony_ci{
5848c2ecf20Sopenharmony_ci	struct adm1026_data *data = adm1026_update_device(dev);
5858c2ecf20Sopenharmony_ci	return sprintf(buf, "%d\n", INS_FROM_REG(16, data->in[16]) -
5868c2ecf20Sopenharmony_ci		NEG12_OFFSET);
5878c2ecf20Sopenharmony_ci}
5888c2ecf20Sopenharmony_cistatic ssize_t in16_min_show(struct device *dev,
5898c2ecf20Sopenharmony_ci			     struct device_attribute *attr, char *buf)
5908c2ecf20Sopenharmony_ci{
5918c2ecf20Sopenharmony_ci	struct adm1026_data *data = adm1026_update_device(dev);
5928c2ecf20Sopenharmony_ci	return sprintf(buf, "%d\n", INS_FROM_REG(16, data->in_min[16])
5938c2ecf20Sopenharmony_ci		- NEG12_OFFSET);
5948c2ecf20Sopenharmony_ci}
5958c2ecf20Sopenharmony_cistatic ssize_t in16_min_store(struct device *dev,
5968c2ecf20Sopenharmony_ci			      struct device_attribute *attr, const char *buf,
5978c2ecf20Sopenharmony_ci			      size_t count)
5988c2ecf20Sopenharmony_ci{
5998c2ecf20Sopenharmony_ci	struct adm1026_data *data = dev_get_drvdata(dev);
6008c2ecf20Sopenharmony_ci	struct i2c_client *client = data->client;
6018c2ecf20Sopenharmony_ci	long val;
6028c2ecf20Sopenharmony_ci	int err;
6038c2ecf20Sopenharmony_ci
6048c2ecf20Sopenharmony_ci	err = kstrtol(buf, 10, &val);
6058c2ecf20Sopenharmony_ci	if (err)
6068c2ecf20Sopenharmony_ci		return err;
6078c2ecf20Sopenharmony_ci
6088c2ecf20Sopenharmony_ci	mutex_lock(&data->update_lock);
6098c2ecf20Sopenharmony_ci	data->in_min[16] = INS_TO_REG(16,
6108c2ecf20Sopenharmony_ci				      clamp_val(val, INT_MIN,
6118c2ecf20Sopenharmony_ci						INT_MAX - NEG12_OFFSET) +
6128c2ecf20Sopenharmony_ci				      NEG12_OFFSET);
6138c2ecf20Sopenharmony_ci	adm1026_write_value(client, ADM1026_REG_IN_MIN[16], data->in_min[16]);
6148c2ecf20Sopenharmony_ci	mutex_unlock(&data->update_lock);
6158c2ecf20Sopenharmony_ci	return count;
6168c2ecf20Sopenharmony_ci}
6178c2ecf20Sopenharmony_cistatic ssize_t in16_max_show(struct device *dev,
6188c2ecf20Sopenharmony_ci			     struct device_attribute *attr, char *buf)
6198c2ecf20Sopenharmony_ci{
6208c2ecf20Sopenharmony_ci	struct adm1026_data *data = adm1026_update_device(dev);
6218c2ecf20Sopenharmony_ci	return sprintf(buf, "%d\n", INS_FROM_REG(16, data->in_max[16])
6228c2ecf20Sopenharmony_ci			- NEG12_OFFSET);
6238c2ecf20Sopenharmony_ci}
6248c2ecf20Sopenharmony_cistatic ssize_t in16_max_store(struct device *dev,
6258c2ecf20Sopenharmony_ci			      struct device_attribute *attr, const char *buf,
6268c2ecf20Sopenharmony_ci			      size_t count)
6278c2ecf20Sopenharmony_ci{
6288c2ecf20Sopenharmony_ci	struct adm1026_data *data = dev_get_drvdata(dev);
6298c2ecf20Sopenharmony_ci	struct i2c_client *client = data->client;
6308c2ecf20Sopenharmony_ci	long val;
6318c2ecf20Sopenharmony_ci	int err;
6328c2ecf20Sopenharmony_ci
6338c2ecf20Sopenharmony_ci	err = kstrtol(buf, 10, &val);
6348c2ecf20Sopenharmony_ci	if (err)
6358c2ecf20Sopenharmony_ci		return err;
6368c2ecf20Sopenharmony_ci
6378c2ecf20Sopenharmony_ci	mutex_lock(&data->update_lock);
6388c2ecf20Sopenharmony_ci	data->in_max[16] = INS_TO_REG(16,
6398c2ecf20Sopenharmony_ci				      clamp_val(val, INT_MIN,
6408c2ecf20Sopenharmony_ci						INT_MAX - NEG12_OFFSET) +
6418c2ecf20Sopenharmony_ci				      NEG12_OFFSET);
6428c2ecf20Sopenharmony_ci	adm1026_write_value(client, ADM1026_REG_IN_MAX[16], data->in_max[16]);
6438c2ecf20Sopenharmony_ci	mutex_unlock(&data->update_lock);
6448c2ecf20Sopenharmony_ci	return count;
6458c2ecf20Sopenharmony_ci}
6468c2ecf20Sopenharmony_ci
6478c2ecf20Sopenharmony_cistatic SENSOR_DEVICE_ATTR_RO(in16_input, in16, 16);
6488c2ecf20Sopenharmony_cistatic SENSOR_DEVICE_ATTR_RW(in16_min, in16_min, 16);
6498c2ecf20Sopenharmony_cistatic SENSOR_DEVICE_ATTR_RW(in16_max, in16_max, 16);
6508c2ecf20Sopenharmony_ci
6518c2ecf20Sopenharmony_ci/* Now add fan read/write functions */
6528c2ecf20Sopenharmony_ci
6538c2ecf20Sopenharmony_cistatic ssize_t fan_show(struct device *dev, struct device_attribute *attr,
6548c2ecf20Sopenharmony_ci			char *buf)
6558c2ecf20Sopenharmony_ci{
6568c2ecf20Sopenharmony_ci	struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr);
6578c2ecf20Sopenharmony_ci	int nr = sensor_attr->index;
6588c2ecf20Sopenharmony_ci	struct adm1026_data *data = adm1026_update_device(dev);
6598c2ecf20Sopenharmony_ci	return sprintf(buf, "%d\n", FAN_FROM_REG(data->fan[nr],
6608c2ecf20Sopenharmony_ci		data->fan_div[nr]));
6618c2ecf20Sopenharmony_ci}
6628c2ecf20Sopenharmony_cistatic ssize_t fan_min_show(struct device *dev, struct device_attribute *attr,
6638c2ecf20Sopenharmony_ci			    char *buf)
6648c2ecf20Sopenharmony_ci{
6658c2ecf20Sopenharmony_ci	struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr);
6668c2ecf20Sopenharmony_ci	int nr = sensor_attr->index;
6678c2ecf20Sopenharmony_ci	struct adm1026_data *data = adm1026_update_device(dev);
6688c2ecf20Sopenharmony_ci	return sprintf(buf, "%d\n", FAN_FROM_REG(data->fan_min[nr],
6698c2ecf20Sopenharmony_ci		data->fan_div[nr]));
6708c2ecf20Sopenharmony_ci}
6718c2ecf20Sopenharmony_cistatic ssize_t fan_min_store(struct device *dev,
6728c2ecf20Sopenharmony_ci			     struct device_attribute *attr, const char *buf,
6738c2ecf20Sopenharmony_ci			     size_t count)
6748c2ecf20Sopenharmony_ci{
6758c2ecf20Sopenharmony_ci	struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr);
6768c2ecf20Sopenharmony_ci	int nr = sensor_attr->index;
6778c2ecf20Sopenharmony_ci	struct adm1026_data *data = dev_get_drvdata(dev);
6788c2ecf20Sopenharmony_ci	struct i2c_client *client = data->client;
6798c2ecf20Sopenharmony_ci	long val;
6808c2ecf20Sopenharmony_ci	int err;
6818c2ecf20Sopenharmony_ci
6828c2ecf20Sopenharmony_ci	err = kstrtol(buf, 10, &val);
6838c2ecf20Sopenharmony_ci	if (err)
6848c2ecf20Sopenharmony_ci		return err;
6858c2ecf20Sopenharmony_ci
6868c2ecf20Sopenharmony_ci	mutex_lock(&data->update_lock);
6878c2ecf20Sopenharmony_ci	data->fan_min[nr] = FAN_TO_REG(val, data->fan_div[nr]);
6888c2ecf20Sopenharmony_ci	adm1026_write_value(client, ADM1026_REG_FAN_MIN(nr),
6898c2ecf20Sopenharmony_ci		data->fan_min[nr]);
6908c2ecf20Sopenharmony_ci	mutex_unlock(&data->update_lock);
6918c2ecf20Sopenharmony_ci	return count;
6928c2ecf20Sopenharmony_ci}
6938c2ecf20Sopenharmony_ci
6948c2ecf20Sopenharmony_cistatic SENSOR_DEVICE_ATTR_RO(fan1_input, fan, 0);
6958c2ecf20Sopenharmony_cistatic SENSOR_DEVICE_ATTR_RW(fan1_min, fan_min, 0);
6968c2ecf20Sopenharmony_cistatic SENSOR_DEVICE_ATTR_RO(fan2_input, fan, 1);
6978c2ecf20Sopenharmony_cistatic SENSOR_DEVICE_ATTR_RW(fan2_min, fan_min, 1);
6988c2ecf20Sopenharmony_cistatic SENSOR_DEVICE_ATTR_RO(fan3_input, fan, 2);
6998c2ecf20Sopenharmony_cistatic SENSOR_DEVICE_ATTR_RW(fan3_min, fan_min, 2);
7008c2ecf20Sopenharmony_cistatic SENSOR_DEVICE_ATTR_RO(fan4_input, fan, 3);
7018c2ecf20Sopenharmony_cistatic SENSOR_DEVICE_ATTR_RW(fan4_min, fan_min, 3);
7028c2ecf20Sopenharmony_cistatic SENSOR_DEVICE_ATTR_RO(fan5_input, fan, 4);
7038c2ecf20Sopenharmony_cistatic SENSOR_DEVICE_ATTR_RW(fan5_min, fan_min, 4);
7048c2ecf20Sopenharmony_cistatic SENSOR_DEVICE_ATTR_RO(fan6_input, fan, 5);
7058c2ecf20Sopenharmony_cistatic SENSOR_DEVICE_ATTR_RW(fan6_min, fan_min, 5);
7068c2ecf20Sopenharmony_cistatic SENSOR_DEVICE_ATTR_RO(fan7_input, fan, 6);
7078c2ecf20Sopenharmony_cistatic SENSOR_DEVICE_ATTR_RW(fan7_min, fan_min, 6);
7088c2ecf20Sopenharmony_cistatic SENSOR_DEVICE_ATTR_RO(fan8_input, fan, 7);
7098c2ecf20Sopenharmony_cistatic SENSOR_DEVICE_ATTR_RW(fan8_min, fan_min, 7);
7108c2ecf20Sopenharmony_ci
7118c2ecf20Sopenharmony_ci/* Adjust fan_min to account for new fan divisor */
7128c2ecf20Sopenharmony_cistatic void fixup_fan_min(struct device *dev, int fan, int old_div)
7138c2ecf20Sopenharmony_ci{
7148c2ecf20Sopenharmony_ci	struct adm1026_data *data = dev_get_drvdata(dev);
7158c2ecf20Sopenharmony_ci	struct i2c_client *client = data->client;
7168c2ecf20Sopenharmony_ci	int new_min;
7178c2ecf20Sopenharmony_ci	int new_div = data->fan_div[fan];
7188c2ecf20Sopenharmony_ci
7198c2ecf20Sopenharmony_ci	/* 0 and 0xff are special.  Don't adjust them */
7208c2ecf20Sopenharmony_ci	if (data->fan_min[fan] == 0 || data->fan_min[fan] == 0xff)
7218c2ecf20Sopenharmony_ci		return;
7228c2ecf20Sopenharmony_ci
7238c2ecf20Sopenharmony_ci	new_min = data->fan_min[fan] * old_div / new_div;
7248c2ecf20Sopenharmony_ci	new_min = clamp_val(new_min, 1, 254);
7258c2ecf20Sopenharmony_ci	data->fan_min[fan] = new_min;
7268c2ecf20Sopenharmony_ci	adm1026_write_value(client, ADM1026_REG_FAN_MIN(fan), new_min);
7278c2ecf20Sopenharmony_ci}
7288c2ecf20Sopenharmony_ci
7298c2ecf20Sopenharmony_ci/* Now add fan_div read/write functions */
7308c2ecf20Sopenharmony_cistatic ssize_t fan_div_show(struct device *dev, struct device_attribute *attr,
7318c2ecf20Sopenharmony_ci			    char *buf)
7328c2ecf20Sopenharmony_ci{
7338c2ecf20Sopenharmony_ci	struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr);
7348c2ecf20Sopenharmony_ci	int nr = sensor_attr->index;
7358c2ecf20Sopenharmony_ci	struct adm1026_data *data = adm1026_update_device(dev);
7368c2ecf20Sopenharmony_ci	return sprintf(buf, "%d\n", data->fan_div[nr]);
7378c2ecf20Sopenharmony_ci}
7388c2ecf20Sopenharmony_cistatic ssize_t fan_div_store(struct device *dev,
7398c2ecf20Sopenharmony_ci			     struct device_attribute *attr, const char *buf,
7408c2ecf20Sopenharmony_ci			     size_t count)
7418c2ecf20Sopenharmony_ci{
7428c2ecf20Sopenharmony_ci	struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr);
7438c2ecf20Sopenharmony_ci	int nr = sensor_attr->index;
7448c2ecf20Sopenharmony_ci	struct adm1026_data *data = dev_get_drvdata(dev);
7458c2ecf20Sopenharmony_ci	struct i2c_client *client = data->client;
7468c2ecf20Sopenharmony_ci	long val;
7478c2ecf20Sopenharmony_ci	int orig_div, new_div;
7488c2ecf20Sopenharmony_ci	int err;
7498c2ecf20Sopenharmony_ci
7508c2ecf20Sopenharmony_ci	err = kstrtol(buf, 10, &val);
7518c2ecf20Sopenharmony_ci	if (err)
7528c2ecf20Sopenharmony_ci		return err;
7538c2ecf20Sopenharmony_ci
7548c2ecf20Sopenharmony_ci	new_div = DIV_TO_REG(val);
7558c2ecf20Sopenharmony_ci
7568c2ecf20Sopenharmony_ci	mutex_lock(&data->update_lock);
7578c2ecf20Sopenharmony_ci	orig_div = data->fan_div[nr];
7588c2ecf20Sopenharmony_ci	data->fan_div[nr] = DIV_FROM_REG(new_div);
7598c2ecf20Sopenharmony_ci
7608c2ecf20Sopenharmony_ci	if (nr < 4) { /* 0 <= nr < 4 */
7618c2ecf20Sopenharmony_ci		adm1026_write_value(client, ADM1026_REG_FAN_DIV_0_3,
7628c2ecf20Sopenharmony_ci				    (DIV_TO_REG(data->fan_div[0]) << 0) |
7638c2ecf20Sopenharmony_ci				    (DIV_TO_REG(data->fan_div[1]) << 2) |
7648c2ecf20Sopenharmony_ci				    (DIV_TO_REG(data->fan_div[2]) << 4) |
7658c2ecf20Sopenharmony_ci				    (DIV_TO_REG(data->fan_div[3]) << 6));
7668c2ecf20Sopenharmony_ci	} else { /* 3 < nr < 8 */
7678c2ecf20Sopenharmony_ci		adm1026_write_value(client, ADM1026_REG_FAN_DIV_4_7,
7688c2ecf20Sopenharmony_ci				    (DIV_TO_REG(data->fan_div[4]) << 0) |
7698c2ecf20Sopenharmony_ci				    (DIV_TO_REG(data->fan_div[5]) << 2) |
7708c2ecf20Sopenharmony_ci				    (DIV_TO_REG(data->fan_div[6]) << 4) |
7718c2ecf20Sopenharmony_ci				    (DIV_TO_REG(data->fan_div[7]) << 6));
7728c2ecf20Sopenharmony_ci	}
7738c2ecf20Sopenharmony_ci
7748c2ecf20Sopenharmony_ci	if (data->fan_div[nr] != orig_div)
7758c2ecf20Sopenharmony_ci		fixup_fan_min(dev, nr, orig_div);
7768c2ecf20Sopenharmony_ci
7778c2ecf20Sopenharmony_ci	mutex_unlock(&data->update_lock);
7788c2ecf20Sopenharmony_ci	return count;
7798c2ecf20Sopenharmony_ci}
7808c2ecf20Sopenharmony_ci
7818c2ecf20Sopenharmony_cistatic SENSOR_DEVICE_ATTR_RW(fan1_div, fan_div, 0);
7828c2ecf20Sopenharmony_cistatic SENSOR_DEVICE_ATTR_RW(fan2_div, fan_div, 1);
7838c2ecf20Sopenharmony_cistatic SENSOR_DEVICE_ATTR_RW(fan3_div, fan_div, 2);
7848c2ecf20Sopenharmony_cistatic SENSOR_DEVICE_ATTR_RW(fan4_div, fan_div, 3);
7858c2ecf20Sopenharmony_cistatic SENSOR_DEVICE_ATTR_RW(fan5_div, fan_div, 4);
7868c2ecf20Sopenharmony_cistatic SENSOR_DEVICE_ATTR_RW(fan6_div, fan_div, 5);
7878c2ecf20Sopenharmony_cistatic SENSOR_DEVICE_ATTR_RW(fan7_div, fan_div, 6);
7888c2ecf20Sopenharmony_cistatic SENSOR_DEVICE_ATTR_RW(fan8_div, fan_div, 7);
7898c2ecf20Sopenharmony_ci
7908c2ecf20Sopenharmony_ci/* Temps */
7918c2ecf20Sopenharmony_cistatic ssize_t temp_show(struct device *dev, struct device_attribute *attr,
7928c2ecf20Sopenharmony_ci			 char *buf)
7938c2ecf20Sopenharmony_ci{
7948c2ecf20Sopenharmony_ci	struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr);
7958c2ecf20Sopenharmony_ci	int nr = sensor_attr->index;
7968c2ecf20Sopenharmony_ci	struct adm1026_data *data = adm1026_update_device(dev);
7978c2ecf20Sopenharmony_ci	return sprintf(buf, "%d\n", TEMP_FROM_REG(data->temp[nr]));
7988c2ecf20Sopenharmony_ci}
7998c2ecf20Sopenharmony_cistatic ssize_t temp_min_show(struct device *dev,
8008c2ecf20Sopenharmony_ci			     struct device_attribute *attr, char *buf)
8018c2ecf20Sopenharmony_ci{
8028c2ecf20Sopenharmony_ci	struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr);
8038c2ecf20Sopenharmony_ci	int nr = sensor_attr->index;
8048c2ecf20Sopenharmony_ci	struct adm1026_data *data = adm1026_update_device(dev);
8058c2ecf20Sopenharmony_ci	return sprintf(buf, "%d\n", TEMP_FROM_REG(data->temp_min[nr]));
8068c2ecf20Sopenharmony_ci}
8078c2ecf20Sopenharmony_cistatic ssize_t temp_min_store(struct device *dev,
8088c2ecf20Sopenharmony_ci			      struct device_attribute *attr, const char *buf,
8098c2ecf20Sopenharmony_ci			      size_t count)
8108c2ecf20Sopenharmony_ci{
8118c2ecf20Sopenharmony_ci	struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr);
8128c2ecf20Sopenharmony_ci	int nr = sensor_attr->index;
8138c2ecf20Sopenharmony_ci	struct adm1026_data *data = dev_get_drvdata(dev);
8148c2ecf20Sopenharmony_ci	struct i2c_client *client = data->client;
8158c2ecf20Sopenharmony_ci	long val;
8168c2ecf20Sopenharmony_ci	int err;
8178c2ecf20Sopenharmony_ci
8188c2ecf20Sopenharmony_ci	err = kstrtol(buf, 10, &val);
8198c2ecf20Sopenharmony_ci	if (err)
8208c2ecf20Sopenharmony_ci		return err;
8218c2ecf20Sopenharmony_ci
8228c2ecf20Sopenharmony_ci	mutex_lock(&data->update_lock);
8238c2ecf20Sopenharmony_ci	data->temp_min[nr] = TEMP_TO_REG(val);
8248c2ecf20Sopenharmony_ci	adm1026_write_value(client, ADM1026_REG_TEMP_MIN[nr],
8258c2ecf20Sopenharmony_ci		data->temp_min[nr]);
8268c2ecf20Sopenharmony_ci	mutex_unlock(&data->update_lock);
8278c2ecf20Sopenharmony_ci	return count;
8288c2ecf20Sopenharmony_ci}
8298c2ecf20Sopenharmony_cistatic ssize_t temp_max_show(struct device *dev,
8308c2ecf20Sopenharmony_ci			     struct device_attribute *attr, char *buf)
8318c2ecf20Sopenharmony_ci{
8328c2ecf20Sopenharmony_ci	struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr);
8338c2ecf20Sopenharmony_ci	int nr = sensor_attr->index;
8348c2ecf20Sopenharmony_ci	struct adm1026_data *data = adm1026_update_device(dev);
8358c2ecf20Sopenharmony_ci	return sprintf(buf, "%d\n", TEMP_FROM_REG(data->temp_max[nr]));
8368c2ecf20Sopenharmony_ci}
8378c2ecf20Sopenharmony_cistatic ssize_t temp_max_store(struct device *dev,
8388c2ecf20Sopenharmony_ci			      struct device_attribute *attr, const char *buf,
8398c2ecf20Sopenharmony_ci			      size_t count)
8408c2ecf20Sopenharmony_ci{
8418c2ecf20Sopenharmony_ci	struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr);
8428c2ecf20Sopenharmony_ci	int nr = sensor_attr->index;
8438c2ecf20Sopenharmony_ci	struct adm1026_data *data = dev_get_drvdata(dev);
8448c2ecf20Sopenharmony_ci	struct i2c_client *client = data->client;
8458c2ecf20Sopenharmony_ci	long val;
8468c2ecf20Sopenharmony_ci	int err;
8478c2ecf20Sopenharmony_ci
8488c2ecf20Sopenharmony_ci	err = kstrtol(buf, 10, &val);
8498c2ecf20Sopenharmony_ci	if (err)
8508c2ecf20Sopenharmony_ci		return err;
8518c2ecf20Sopenharmony_ci
8528c2ecf20Sopenharmony_ci	mutex_lock(&data->update_lock);
8538c2ecf20Sopenharmony_ci	data->temp_max[nr] = TEMP_TO_REG(val);
8548c2ecf20Sopenharmony_ci	adm1026_write_value(client, ADM1026_REG_TEMP_MAX[nr],
8558c2ecf20Sopenharmony_ci		data->temp_max[nr]);
8568c2ecf20Sopenharmony_ci	mutex_unlock(&data->update_lock);
8578c2ecf20Sopenharmony_ci	return count;
8588c2ecf20Sopenharmony_ci}
8598c2ecf20Sopenharmony_ci
8608c2ecf20Sopenharmony_cistatic SENSOR_DEVICE_ATTR_RO(temp1_input, temp, 0);
8618c2ecf20Sopenharmony_cistatic SENSOR_DEVICE_ATTR_RW(temp1_min, temp_min, 0);
8628c2ecf20Sopenharmony_cistatic SENSOR_DEVICE_ATTR_RW(temp1_max, temp_max, 0);
8638c2ecf20Sopenharmony_cistatic SENSOR_DEVICE_ATTR_RO(temp2_input, temp, 1);
8648c2ecf20Sopenharmony_cistatic SENSOR_DEVICE_ATTR_RW(temp2_min, temp_min, 1);
8658c2ecf20Sopenharmony_cistatic SENSOR_DEVICE_ATTR_RW(temp2_max, temp_max, 1);
8668c2ecf20Sopenharmony_cistatic SENSOR_DEVICE_ATTR_RO(temp3_input, temp, 2);
8678c2ecf20Sopenharmony_cistatic SENSOR_DEVICE_ATTR_RW(temp3_min, temp_min, 2);
8688c2ecf20Sopenharmony_cistatic SENSOR_DEVICE_ATTR_RW(temp3_max, temp_max, 2);
8698c2ecf20Sopenharmony_ci
8708c2ecf20Sopenharmony_cistatic ssize_t temp_offset_show(struct device *dev,
8718c2ecf20Sopenharmony_ci				struct device_attribute *attr, char *buf)
8728c2ecf20Sopenharmony_ci{
8738c2ecf20Sopenharmony_ci	struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr);
8748c2ecf20Sopenharmony_ci	int nr = sensor_attr->index;
8758c2ecf20Sopenharmony_ci	struct adm1026_data *data = adm1026_update_device(dev);
8768c2ecf20Sopenharmony_ci	return sprintf(buf, "%d\n", TEMP_FROM_REG(data->temp_offset[nr]));
8778c2ecf20Sopenharmony_ci}
8788c2ecf20Sopenharmony_cistatic ssize_t temp_offset_store(struct device *dev,
8798c2ecf20Sopenharmony_ci				 struct device_attribute *attr,
8808c2ecf20Sopenharmony_ci				 const char *buf, size_t count)
8818c2ecf20Sopenharmony_ci{
8828c2ecf20Sopenharmony_ci	struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr);
8838c2ecf20Sopenharmony_ci	int nr = sensor_attr->index;
8848c2ecf20Sopenharmony_ci	struct adm1026_data *data = dev_get_drvdata(dev);
8858c2ecf20Sopenharmony_ci	struct i2c_client *client = data->client;
8868c2ecf20Sopenharmony_ci	long val;
8878c2ecf20Sopenharmony_ci	int err;
8888c2ecf20Sopenharmony_ci
8898c2ecf20Sopenharmony_ci	err = kstrtol(buf, 10, &val);
8908c2ecf20Sopenharmony_ci	if (err)
8918c2ecf20Sopenharmony_ci		return err;
8928c2ecf20Sopenharmony_ci
8938c2ecf20Sopenharmony_ci	mutex_lock(&data->update_lock);
8948c2ecf20Sopenharmony_ci	data->temp_offset[nr] = TEMP_TO_REG(val);
8958c2ecf20Sopenharmony_ci	adm1026_write_value(client, ADM1026_REG_TEMP_OFFSET[nr],
8968c2ecf20Sopenharmony_ci		data->temp_offset[nr]);
8978c2ecf20Sopenharmony_ci	mutex_unlock(&data->update_lock);
8988c2ecf20Sopenharmony_ci	return count;
8998c2ecf20Sopenharmony_ci}
9008c2ecf20Sopenharmony_ci
9018c2ecf20Sopenharmony_cistatic SENSOR_DEVICE_ATTR_RW(temp1_offset, temp_offset, 0);
9028c2ecf20Sopenharmony_cistatic SENSOR_DEVICE_ATTR_RW(temp2_offset, temp_offset, 1);
9038c2ecf20Sopenharmony_cistatic SENSOR_DEVICE_ATTR_RW(temp3_offset, temp_offset, 2);
9048c2ecf20Sopenharmony_ci
9058c2ecf20Sopenharmony_cistatic ssize_t temp_auto_point1_temp_hyst_show(struct device *dev,
9068c2ecf20Sopenharmony_ci					       struct device_attribute *attr,
9078c2ecf20Sopenharmony_ci					       char *buf)
9088c2ecf20Sopenharmony_ci{
9098c2ecf20Sopenharmony_ci	struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr);
9108c2ecf20Sopenharmony_ci	int nr = sensor_attr->index;
9118c2ecf20Sopenharmony_ci	struct adm1026_data *data = adm1026_update_device(dev);
9128c2ecf20Sopenharmony_ci	return sprintf(buf, "%d\n", TEMP_FROM_REG(
9138c2ecf20Sopenharmony_ci		ADM1026_FAN_ACTIVATION_TEMP_HYST + data->temp_tmin[nr]));
9148c2ecf20Sopenharmony_ci}
9158c2ecf20Sopenharmony_cistatic ssize_t temp_auto_point2_temp_show(struct device *dev,
9168c2ecf20Sopenharmony_ci					  struct device_attribute *attr,
9178c2ecf20Sopenharmony_ci					  char *buf)
9188c2ecf20Sopenharmony_ci{
9198c2ecf20Sopenharmony_ci	struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr);
9208c2ecf20Sopenharmony_ci	int nr = sensor_attr->index;
9218c2ecf20Sopenharmony_ci	struct adm1026_data *data = adm1026_update_device(dev);
9228c2ecf20Sopenharmony_ci	return sprintf(buf, "%d\n", TEMP_FROM_REG(data->temp_tmin[nr] +
9238c2ecf20Sopenharmony_ci		ADM1026_FAN_CONTROL_TEMP_RANGE));
9248c2ecf20Sopenharmony_ci}
9258c2ecf20Sopenharmony_cistatic ssize_t temp_auto_point1_temp_show(struct device *dev,
9268c2ecf20Sopenharmony_ci					  struct device_attribute *attr,
9278c2ecf20Sopenharmony_ci					  char *buf)
9288c2ecf20Sopenharmony_ci{
9298c2ecf20Sopenharmony_ci	struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr);
9308c2ecf20Sopenharmony_ci	int nr = sensor_attr->index;
9318c2ecf20Sopenharmony_ci	struct adm1026_data *data = adm1026_update_device(dev);
9328c2ecf20Sopenharmony_ci	return sprintf(buf, "%d\n", TEMP_FROM_REG(data->temp_tmin[nr]));
9338c2ecf20Sopenharmony_ci}
9348c2ecf20Sopenharmony_cistatic ssize_t temp_auto_point1_temp_store(struct device *dev,
9358c2ecf20Sopenharmony_ci					   struct device_attribute *attr,
9368c2ecf20Sopenharmony_ci					   const char *buf, size_t count)
9378c2ecf20Sopenharmony_ci{
9388c2ecf20Sopenharmony_ci	struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr);
9398c2ecf20Sopenharmony_ci	int nr = sensor_attr->index;
9408c2ecf20Sopenharmony_ci	struct adm1026_data *data = dev_get_drvdata(dev);
9418c2ecf20Sopenharmony_ci	struct i2c_client *client = data->client;
9428c2ecf20Sopenharmony_ci	long val;
9438c2ecf20Sopenharmony_ci	int err;
9448c2ecf20Sopenharmony_ci
9458c2ecf20Sopenharmony_ci	err = kstrtol(buf, 10, &val);
9468c2ecf20Sopenharmony_ci	if (err)
9478c2ecf20Sopenharmony_ci		return err;
9488c2ecf20Sopenharmony_ci
9498c2ecf20Sopenharmony_ci	mutex_lock(&data->update_lock);
9508c2ecf20Sopenharmony_ci	data->temp_tmin[nr] = TEMP_TO_REG(val);
9518c2ecf20Sopenharmony_ci	adm1026_write_value(client, ADM1026_REG_TEMP_TMIN[nr],
9528c2ecf20Sopenharmony_ci		data->temp_tmin[nr]);
9538c2ecf20Sopenharmony_ci	mutex_unlock(&data->update_lock);
9548c2ecf20Sopenharmony_ci	return count;
9558c2ecf20Sopenharmony_ci}
9568c2ecf20Sopenharmony_ci
9578c2ecf20Sopenharmony_cistatic SENSOR_DEVICE_ATTR_RW(temp1_auto_point1_temp, temp_auto_point1_temp, 0);
9588c2ecf20Sopenharmony_cistatic SENSOR_DEVICE_ATTR_RO(temp1_auto_point1_temp_hyst,
9598c2ecf20Sopenharmony_ci			     temp_auto_point1_temp_hyst, 0);
9608c2ecf20Sopenharmony_cistatic SENSOR_DEVICE_ATTR_RO(temp1_auto_point2_temp, temp_auto_point2_temp, 0);
9618c2ecf20Sopenharmony_cistatic SENSOR_DEVICE_ATTR_RW(temp2_auto_point1_temp, temp_auto_point1_temp, 1);
9628c2ecf20Sopenharmony_cistatic SENSOR_DEVICE_ATTR_RO(temp2_auto_point1_temp_hyst,
9638c2ecf20Sopenharmony_ci			     temp_auto_point1_temp_hyst, 1);
9648c2ecf20Sopenharmony_cistatic SENSOR_DEVICE_ATTR_RO(temp2_auto_point2_temp, temp_auto_point2_temp, 1);
9658c2ecf20Sopenharmony_cistatic SENSOR_DEVICE_ATTR_RW(temp3_auto_point1_temp, temp_auto_point1_temp, 2);
9668c2ecf20Sopenharmony_cistatic SENSOR_DEVICE_ATTR_RO(temp3_auto_point1_temp_hyst,
9678c2ecf20Sopenharmony_ci			     temp_auto_point1_temp_hyst, 2);
9688c2ecf20Sopenharmony_cistatic SENSOR_DEVICE_ATTR_RO(temp3_auto_point2_temp, temp_auto_point2_temp, 2);
9698c2ecf20Sopenharmony_ci
9708c2ecf20Sopenharmony_cistatic ssize_t show_temp_crit_enable(struct device *dev,
9718c2ecf20Sopenharmony_ci		struct device_attribute *attr, char *buf)
9728c2ecf20Sopenharmony_ci{
9738c2ecf20Sopenharmony_ci	struct adm1026_data *data = adm1026_update_device(dev);
9748c2ecf20Sopenharmony_ci	return sprintf(buf, "%d\n", (data->config1 & CFG1_THERM_HOT) >> 4);
9758c2ecf20Sopenharmony_ci}
9768c2ecf20Sopenharmony_cistatic ssize_t set_temp_crit_enable(struct device *dev,
9778c2ecf20Sopenharmony_ci		struct device_attribute *attr, const char *buf, size_t count)
9788c2ecf20Sopenharmony_ci{
9798c2ecf20Sopenharmony_ci	struct adm1026_data *data = dev_get_drvdata(dev);
9808c2ecf20Sopenharmony_ci	struct i2c_client *client = data->client;
9818c2ecf20Sopenharmony_ci	unsigned long val;
9828c2ecf20Sopenharmony_ci	int err;
9838c2ecf20Sopenharmony_ci
9848c2ecf20Sopenharmony_ci	err = kstrtoul(buf, 10, &val);
9858c2ecf20Sopenharmony_ci	if (err)
9868c2ecf20Sopenharmony_ci		return err;
9878c2ecf20Sopenharmony_ci
9888c2ecf20Sopenharmony_ci	if (val > 1)
9898c2ecf20Sopenharmony_ci		return -EINVAL;
9908c2ecf20Sopenharmony_ci
9918c2ecf20Sopenharmony_ci	mutex_lock(&data->update_lock);
9928c2ecf20Sopenharmony_ci	data->config1 = (data->config1 & ~CFG1_THERM_HOT) | (val << 4);
9938c2ecf20Sopenharmony_ci	adm1026_write_value(client, ADM1026_REG_CONFIG1, data->config1);
9948c2ecf20Sopenharmony_ci	mutex_unlock(&data->update_lock);
9958c2ecf20Sopenharmony_ci
9968c2ecf20Sopenharmony_ci	return count;
9978c2ecf20Sopenharmony_ci}
9988c2ecf20Sopenharmony_ci
9998c2ecf20Sopenharmony_cistatic DEVICE_ATTR(temp1_crit_enable, 0644, show_temp_crit_enable,
10008c2ecf20Sopenharmony_ci		   set_temp_crit_enable);
10018c2ecf20Sopenharmony_cistatic DEVICE_ATTR(temp2_crit_enable, 0644, show_temp_crit_enable,
10028c2ecf20Sopenharmony_ci		   set_temp_crit_enable);
10038c2ecf20Sopenharmony_cistatic DEVICE_ATTR(temp3_crit_enable, 0644, show_temp_crit_enable,
10048c2ecf20Sopenharmony_ci		   set_temp_crit_enable);
10058c2ecf20Sopenharmony_ci
10068c2ecf20Sopenharmony_cistatic ssize_t temp_crit_show(struct device *dev,
10078c2ecf20Sopenharmony_ci			      struct device_attribute *attr, char *buf)
10088c2ecf20Sopenharmony_ci{
10098c2ecf20Sopenharmony_ci	struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr);
10108c2ecf20Sopenharmony_ci	int nr = sensor_attr->index;
10118c2ecf20Sopenharmony_ci	struct adm1026_data *data = adm1026_update_device(dev);
10128c2ecf20Sopenharmony_ci	return sprintf(buf, "%d\n", TEMP_FROM_REG(data->temp_crit[nr]));
10138c2ecf20Sopenharmony_ci}
10148c2ecf20Sopenharmony_cistatic ssize_t temp_crit_store(struct device *dev,
10158c2ecf20Sopenharmony_ci			       struct device_attribute *attr, const char *buf,
10168c2ecf20Sopenharmony_ci			       size_t count)
10178c2ecf20Sopenharmony_ci{
10188c2ecf20Sopenharmony_ci	struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr);
10198c2ecf20Sopenharmony_ci	int nr = sensor_attr->index;
10208c2ecf20Sopenharmony_ci	struct adm1026_data *data = dev_get_drvdata(dev);
10218c2ecf20Sopenharmony_ci	struct i2c_client *client = data->client;
10228c2ecf20Sopenharmony_ci	long val;
10238c2ecf20Sopenharmony_ci	int err;
10248c2ecf20Sopenharmony_ci
10258c2ecf20Sopenharmony_ci	err = kstrtol(buf, 10, &val);
10268c2ecf20Sopenharmony_ci	if (err)
10278c2ecf20Sopenharmony_ci		return err;
10288c2ecf20Sopenharmony_ci
10298c2ecf20Sopenharmony_ci	mutex_lock(&data->update_lock);
10308c2ecf20Sopenharmony_ci	data->temp_crit[nr] = TEMP_TO_REG(val);
10318c2ecf20Sopenharmony_ci	adm1026_write_value(client, ADM1026_REG_TEMP_THERM[nr],
10328c2ecf20Sopenharmony_ci		data->temp_crit[nr]);
10338c2ecf20Sopenharmony_ci	mutex_unlock(&data->update_lock);
10348c2ecf20Sopenharmony_ci	return count;
10358c2ecf20Sopenharmony_ci}
10368c2ecf20Sopenharmony_ci
10378c2ecf20Sopenharmony_cistatic SENSOR_DEVICE_ATTR_RW(temp1_crit, temp_crit, 0);
10388c2ecf20Sopenharmony_cistatic SENSOR_DEVICE_ATTR_RW(temp2_crit, temp_crit, 1);
10398c2ecf20Sopenharmony_cistatic SENSOR_DEVICE_ATTR_RW(temp3_crit, temp_crit, 2);
10408c2ecf20Sopenharmony_ci
10418c2ecf20Sopenharmony_cistatic ssize_t analog_out_show(struct device *dev,
10428c2ecf20Sopenharmony_ci			       struct device_attribute *attr, char *buf)
10438c2ecf20Sopenharmony_ci{
10448c2ecf20Sopenharmony_ci	struct adm1026_data *data = adm1026_update_device(dev);
10458c2ecf20Sopenharmony_ci	return sprintf(buf, "%d\n", DAC_FROM_REG(data->analog_out));
10468c2ecf20Sopenharmony_ci}
10478c2ecf20Sopenharmony_cistatic ssize_t analog_out_store(struct device *dev,
10488c2ecf20Sopenharmony_ci				struct device_attribute *attr,
10498c2ecf20Sopenharmony_ci				const char *buf, size_t count)
10508c2ecf20Sopenharmony_ci{
10518c2ecf20Sopenharmony_ci	struct adm1026_data *data = dev_get_drvdata(dev);
10528c2ecf20Sopenharmony_ci	struct i2c_client *client = data->client;
10538c2ecf20Sopenharmony_ci	long val;
10548c2ecf20Sopenharmony_ci	int err;
10558c2ecf20Sopenharmony_ci
10568c2ecf20Sopenharmony_ci	err = kstrtol(buf, 10, &val);
10578c2ecf20Sopenharmony_ci	if (err)
10588c2ecf20Sopenharmony_ci		return err;
10598c2ecf20Sopenharmony_ci
10608c2ecf20Sopenharmony_ci	mutex_lock(&data->update_lock);
10618c2ecf20Sopenharmony_ci	data->analog_out = DAC_TO_REG(val);
10628c2ecf20Sopenharmony_ci	adm1026_write_value(client, ADM1026_REG_DAC, data->analog_out);
10638c2ecf20Sopenharmony_ci	mutex_unlock(&data->update_lock);
10648c2ecf20Sopenharmony_ci	return count;
10658c2ecf20Sopenharmony_ci}
10668c2ecf20Sopenharmony_ci
10678c2ecf20Sopenharmony_cistatic DEVICE_ATTR_RW(analog_out);
10688c2ecf20Sopenharmony_ci
10698c2ecf20Sopenharmony_cistatic ssize_t cpu0_vid_show(struct device *dev,
10708c2ecf20Sopenharmony_ci			     struct device_attribute *attr, char *buf)
10718c2ecf20Sopenharmony_ci{
10728c2ecf20Sopenharmony_ci	struct adm1026_data *data = adm1026_update_device(dev);
10738c2ecf20Sopenharmony_ci	int vid = (data->gpio >> 11) & 0x1f;
10748c2ecf20Sopenharmony_ci
10758c2ecf20Sopenharmony_ci	dev_dbg(dev, "Setting VID from GPIO11-15.\n");
10768c2ecf20Sopenharmony_ci	return sprintf(buf, "%d\n", vid_from_reg(vid, data->vrm));
10778c2ecf20Sopenharmony_ci}
10788c2ecf20Sopenharmony_ci
10798c2ecf20Sopenharmony_cistatic DEVICE_ATTR_RO(cpu0_vid);
10808c2ecf20Sopenharmony_ci
10818c2ecf20Sopenharmony_cistatic ssize_t vrm_show(struct device *dev, struct device_attribute *attr,
10828c2ecf20Sopenharmony_ci			char *buf)
10838c2ecf20Sopenharmony_ci{
10848c2ecf20Sopenharmony_ci	struct adm1026_data *data = dev_get_drvdata(dev);
10858c2ecf20Sopenharmony_ci	return sprintf(buf, "%d\n", data->vrm);
10868c2ecf20Sopenharmony_ci}
10878c2ecf20Sopenharmony_ci
10888c2ecf20Sopenharmony_cistatic ssize_t vrm_store(struct device *dev, struct device_attribute *attr,
10898c2ecf20Sopenharmony_ci			 const char *buf, size_t count)
10908c2ecf20Sopenharmony_ci{
10918c2ecf20Sopenharmony_ci	struct adm1026_data *data = dev_get_drvdata(dev);
10928c2ecf20Sopenharmony_ci	unsigned long val;
10938c2ecf20Sopenharmony_ci	int err;
10948c2ecf20Sopenharmony_ci
10958c2ecf20Sopenharmony_ci	err = kstrtoul(buf, 10, &val);
10968c2ecf20Sopenharmony_ci	if (err)
10978c2ecf20Sopenharmony_ci		return err;
10988c2ecf20Sopenharmony_ci
10998c2ecf20Sopenharmony_ci	if (val > 255)
11008c2ecf20Sopenharmony_ci		return -EINVAL;
11018c2ecf20Sopenharmony_ci
11028c2ecf20Sopenharmony_ci	data->vrm = val;
11038c2ecf20Sopenharmony_ci	return count;
11048c2ecf20Sopenharmony_ci}
11058c2ecf20Sopenharmony_ci
11068c2ecf20Sopenharmony_cistatic DEVICE_ATTR_RW(vrm);
11078c2ecf20Sopenharmony_ci
11088c2ecf20Sopenharmony_cistatic ssize_t alarms_show(struct device *dev, struct device_attribute *attr,
11098c2ecf20Sopenharmony_ci			   char *buf)
11108c2ecf20Sopenharmony_ci{
11118c2ecf20Sopenharmony_ci	struct adm1026_data *data = adm1026_update_device(dev);
11128c2ecf20Sopenharmony_ci	return sprintf(buf, "%ld\n", data->alarms);
11138c2ecf20Sopenharmony_ci}
11148c2ecf20Sopenharmony_ci
11158c2ecf20Sopenharmony_cistatic DEVICE_ATTR_RO(alarms);
11168c2ecf20Sopenharmony_ci
11178c2ecf20Sopenharmony_cistatic ssize_t alarm_show(struct device *dev, struct device_attribute *attr,
11188c2ecf20Sopenharmony_ci			  char *buf)
11198c2ecf20Sopenharmony_ci{
11208c2ecf20Sopenharmony_ci	struct adm1026_data *data = adm1026_update_device(dev);
11218c2ecf20Sopenharmony_ci	int bitnr = to_sensor_dev_attr(attr)->index;
11228c2ecf20Sopenharmony_ci	return sprintf(buf, "%ld\n", (data->alarms >> bitnr) & 1);
11238c2ecf20Sopenharmony_ci}
11248c2ecf20Sopenharmony_ci
11258c2ecf20Sopenharmony_cistatic SENSOR_DEVICE_ATTR_RO(temp2_alarm, alarm, 0);
11268c2ecf20Sopenharmony_cistatic SENSOR_DEVICE_ATTR_RO(temp3_alarm, alarm, 1);
11278c2ecf20Sopenharmony_cistatic SENSOR_DEVICE_ATTR_RO(in9_alarm, alarm, 1);
11288c2ecf20Sopenharmony_cistatic SENSOR_DEVICE_ATTR_RO(in11_alarm, alarm, 2);
11298c2ecf20Sopenharmony_cistatic SENSOR_DEVICE_ATTR_RO(in12_alarm, alarm, 3);
11308c2ecf20Sopenharmony_cistatic SENSOR_DEVICE_ATTR_RO(in13_alarm, alarm, 4);
11318c2ecf20Sopenharmony_cistatic SENSOR_DEVICE_ATTR_RO(in14_alarm, alarm, 5);
11328c2ecf20Sopenharmony_cistatic SENSOR_DEVICE_ATTR_RO(in15_alarm, alarm, 6);
11338c2ecf20Sopenharmony_cistatic SENSOR_DEVICE_ATTR_RO(in16_alarm, alarm, 7);
11348c2ecf20Sopenharmony_cistatic SENSOR_DEVICE_ATTR_RO(in0_alarm, alarm, 8);
11358c2ecf20Sopenharmony_cistatic SENSOR_DEVICE_ATTR_RO(in1_alarm, alarm, 9);
11368c2ecf20Sopenharmony_cistatic SENSOR_DEVICE_ATTR_RO(in2_alarm, alarm, 10);
11378c2ecf20Sopenharmony_cistatic SENSOR_DEVICE_ATTR_RO(in3_alarm, alarm, 11);
11388c2ecf20Sopenharmony_cistatic SENSOR_DEVICE_ATTR_RO(in4_alarm, alarm, 12);
11398c2ecf20Sopenharmony_cistatic SENSOR_DEVICE_ATTR_RO(in5_alarm, alarm, 13);
11408c2ecf20Sopenharmony_cistatic SENSOR_DEVICE_ATTR_RO(in6_alarm, alarm, 14);
11418c2ecf20Sopenharmony_cistatic SENSOR_DEVICE_ATTR_RO(in7_alarm, alarm, 15);
11428c2ecf20Sopenharmony_cistatic SENSOR_DEVICE_ATTR_RO(fan1_alarm, alarm, 16);
11438c2ecf20Sopenharmony_cistatic SENSOR_DEVICE_ATTR_RO(fan2_alarm, alarm, 17);
11448c2ecf20Sopenharmony_cistatic SENSOR_DEVICE_ATTR_RO(fan3_alarm, alarm, 18);
11458c2ecf20Sopenharmony_cistatic SENSOR_DEVICE_ATTR_RO(fan4_alarm, alarm, 19);
11468c2ecf20Sopenharmony_cistatic SENSOR_DEVICE_ATTR_RO(fan5_alarm, alarm, 20);
11478c2ecf20Sopenharmony_cistatic SENSOR_DEVICE_ATTR_RO(fan6_alarm, alarm, 21);
11488c2ecf20Sopenharmony_cistatic SENSOR_DEVICE_ATTR_RO(fan7_alarm, alarm, 22);
11498c2ecf20Sopenharmony_cistatic SENSOR_DEVICE_ATTR_RO(fan8_alarm, alarm, 23);
11508c2ecf20Sopenharmony_cistatic SENSOR_DEVICE_ATTR_RO(temp1_alarm, alarm, 24);
11518c2ecf20Sopenharmony_cistatic SENSOR_DEVICE_ATTR_RO(in10_alarm, alarm, 25);
11528c2ecf20Sopenharmony_cistatic SENSOR_DEVICE_ATTR_RO(in8_alarm, alarm, 26);
11538c2ecf20Sopenharmony_ci
11548c2ecf20Sopenharmony_cistatic ssize_t alarm_mask_show(struct device *dev,
11558c2ecf20Sopenharmony_ci			       struct device_attribute *attr, char *buf)
11568c2ecf20Sopenharmony_ci{
11578c2ecf20Sopenharmony_ci	struct adm1026_data *data = adm1026_update_device(dev);
11588c2ecf20Sopenharmony_ci	return sprintf(buf, "%ld\n", data->alarm_mask);
11598c2ecf20Sopenharmony_ci}
11608c2ecf20Sopenharmony_cistatic ssize_t alarm_mask_store(struct device *dev,
11618c2ecf20Sopenharmony_ci				struct device_attribute *attr,
11628c2ecf20Sopenharmony_ci				const char *buf, size_t count)
11638c2ecf20Sopenharmony_ci{
11648c2ecf20Sopenharmony_ci	struct adm1026_data *data = dev_get_drvdata(dev);
11658c2ecf20Sopenharmony_ci	struct i2c_client *client = data->client;
11668c2ecf20Sopenharmony_ci	unsigned long mask;
11678c2ecf20Sopenharmony_ci	long val;
11688c2ecf20Sopenharmony_ci	int err;
11698c2ecf20Sopenharmony_ci
11708c2ecf20Sopenharmony_ci	err = kstrtol(buf, 10, &val);
11718c2ecf20Sopenharmony_ci	if (err)
11728c2ecf20Sopenharmony_ci		return err;
11738c2ecf20Sopenharmony_ci
11748c2ecf20Sopenharmony_ci	mutex_lock(&data->update_lock);
11758c2ecf20Sopenharmony_ci	data->alarm_mask = val & 0x7fffffff;
11768c2ecf20Sopenharmony_ci	mask = data->alarm_mask
11778c2ecf20Sopenharmony_ci		| (data->gpio_mask & 0x10000 ? 0x80000000 : 0);
11788c2ecf20Sopenharmony_ci	adm1026_write_value(client, ADM1026_REG_MASK1,
11798c2ecf20Sopenharmony_ci		mask & 0xff);
11808c2ecf20Sopenharmony_ci	mask >>= 8;
11818c2ecf20Sopenharmony_ci	adm1026_write_value(client, ADM1026_REG_MASK2,
11828c2ecf20Sopenharmony_ci		mask & 0xff);
11838c2ecf20Sopenharmony_ci	mask >>= 8;
11848c2ecf20Sopenharmony_ci	adm1026_write_value(client, ADM1026_REG_MASK3,
11858c2ecf20Sopenharmony_ci		mask & 0xff);
11868c2ecf20Sopenharmony_ci	mask >>= 8;
11878c2ecf20Sopenharmony_ci	adm1026_write_value(client, ADM1026_REG_MASK4,
11888c2ecf20Sopenharmony_ci		mask & 0xff);
11898c2ecf20Sopenharmony_ci	mutex_unlock(&data->update_lock);
11908c2ecf20Sopenharmony_ci	return count;
11918c2ecf20Sopenharmony_ci}
11928c2ecf20Sopenharmony_ci
11938c2ecf20Sopenharmony_cistatic DEVICE_ATTR_RW(alarm_mask);
11948c2ecf20Sopenharmony_ci
11958c2ecf20Sopenharmony_cistatic ssize_t gpio_show(struct device *dev, struct device_attribute *attr,
11968c2ecf20Sopenharmony_ci			 char *buf)
11978c2ecf20Sopenharmony_ci{
11988c2ecf20Sopenharmony_ci	struct adm1026_data *data = adm1026_update_device(dev);
11998c2ecf20Sopenharmony_ci	return sprintf(buf, "%ld\n", data->gpio);
12008c2ecf20Sopenharmony_ci}
12018c2ecf20Sopenharmony_cistatic ssize_t gpio_store(struct device *dev, struct device_attribute *attr,
12028c2ecf20Sopenharmony_ci			  const char *buf, size_t count)
12038c2ecf20Sopenharmony_ci{
12048c2ecf20Sopenharmony_ci	struct adm1026_data *data = dev_get_drvdata(dev);
12058c2ecf20Sopenharmony_ci	struct i2c_client *client = data->client;
12068c2ecf20Sopenharmony_ci	long gpio;
12078c2ecf20Sopenharmony_ci	long val;
12088c2ecf20Sopenharmony_ci	int err;
12098c2ecf20Sopenharmony_ci
12108c2ecf20Sopenharmony_ci	err = kstrtol(buf, 10, &val);
12118c2ecf20Sopenharmony_ci	if (err)
12128c2ecf20Sopenharmony_ci		return err;
12138c2ecf20Sopenharmony_ci
12148c2ecf20Sopenharmony_ci	mutex_lock(&data->update_lock);
12158c2ecf20Sopenharmony_ci	data->gpio = val & 0x1ffff;
12168c2ecf20Sopenharmony_ci	gpio = data->gpio;
12178c2ecf20Sopenharmony_ci	adm1026_write_value(client, ADM1026_REG_GPIO_STATUS_0_7, gpio & 0xff);
12188c2ecf20Sopenharmony_ci	gpio >>= 8;
12198c2ecf20Sopenharmony_ci	adm1026_write_value(client, ADM1026_REG_GPIO_STATUS_8_15, gpio & 0xff);
12208c2ecf20Sopenharmony_ci	gpio = ((gpio >> 1) & 0x80) | (data->alarms >> 24 & 0x7f);
12218c2ecf20Sopenharmony_ci	adm1026_write_value(client, ADM1026_REG_STATUS4, gpio & 0xff);
12228c2ecf20Sopenharmony_ci	mutex_unlock(&data->update_lock);
12238c2ecf20Sopenharmony_ci	return count;
12248c2ecf20Sopenharmony_ci}
12258c2ecf20Sopenharmony_ci
12268c2ecf20Sopenharmony_cistatic DEVICE_ATTR_RW(gpio);
12278c2ecf20Sopenharmony_ci
12288c2ecf20Sopenharmony_cistatic ssize_t gpio_mask_show(struct device *dev,
12298c2ecf20Sopenharmony_ci			      struct device_attribute *attr,
12308c2ecf20Sopenharmony_ci			      char *buf)
12318c2ecf20Sopenharmony_ci{
12328c2ecf20Sopenharmony_ci	struct adm1026_data *data = adm1026_update_device(dev);
12338c2ecf20Sopenharmony_ci	return sprintf(buf, "%ld\n", data->gpio_mask);
12348c2ecf20Sopenharmony_ci}
12358c2ecf20Sopenharmony_cistatic ssize_t gpio_mask_store(struct device *dev,
12368c2ecf20Sopenharmony_ci			       struct device_attribute *attr, const char *buf,
12378c2ecf20Sopenharmony_ci			       size_t count)
12388c2ecf20Sopenharmony_ci{
12398c2ecf20Sopenharmony_ci	struct adm1026_data *data = dev_get_drvdata(dev);
12408c2ecf20Sopenharmony_ci	struct i2c_client *client = data->client;
12418c2ecf20Sopenharmony_ci	long mask;
12428c2ecf20Sopenharmony_ci	long val;
12438c2ecf20Sopenharmony_ci	int err;
12448c2ecf20Sopenharmony_ci
12458c2ecf20Sopenharmony_ci	err = kstrtol(buf, 10, &val);
12468c2ecf20Sopenharmony_ci	if (err)
12478c2ecf20Sopenharmony_ci		return err;
12488c2ecf20Sopenharmony_ci
12498c2ecf20Sopenharmony_ci	mutex_lock(&data->update_lock);
12508c2ecf20Sopenharmony_ci	data->gpio_mask = val & 0x1ffff;
12518c2ecf20Sopenharmony_ci	mask = data->gpio_mask;
12528c2ecf20Sopenharmony_ci	adm1026_write_value(client, ADM1026_REG_GPIO_MASK_0_7, mask & 0xff);
12538c2ecf20Sopenharmony_ci	mask >>= 8;
12548c2ecf20Sopenharmony_ci	adm1026_write_value(client, ADM1026_REG_GPIO_MASK_8_15, mask & 0xff);
12558c2ecf20Sopenharmony_ci	mask = ((mask >> 1) & 0x80) | (data->alarm_mask >> 24 & 0x7f);
12568c2ecf20Sopenharmony_ci	adm1026_write_value(client, ADM1026_REG_MASK1, mask & 0xff);
12578c2ecf20Sopenharmony_ci	mutex_unlock(&data->update_lock);
12588c2ecf20Sopenharmony_ci	return count;
12598c2ecf20Sopenharmony_ci}
12608c2ecf20Sopenharmony_ci
12618c2ecf20Sopenharmony_cistatic DEVICE_ATTR_RW(gpio_mask);
12628c2ecf20Sopenharmony_ci
12638c2ecf20Sopenharmony_cistatic ssize_t pwm1_show(struct device *dev, struct device_attribute *attr,
12648c2ecf20Sopenharmony_ci			 char *buf)
12658c2ecf20Sopenharmony_ci{
12668c2ecf20Sopenharmony_ci	struct adm1026_data *data = adm1026_update_device(dev);
12678c2ecf20Sopenharmony_ci	return sprintf(buf, "%d\n", PWM_FROM_REG(data->pwm1.pwm));
12688c2ecf20Sopenharmony_ci}
12698c2ecf20Sopenharmony_ci
12708c2ecf20Sopenharmony_cistatic ssize_t pwm1_store(struct device *dev, struct device_attribute *attr,
12718c2ecf20Sopenharmony_ci			  const char *buf, size_t count)
12728c2ecf20Sopenharmony_ci{
12738c2ecf20Sopenharmony_ci	struct adm1026_data *data = dev_get_drvdata(dev);
12748c2ecf20Sopenharmony_ci	struct i2c_client *client = data->client;
12758c2ecf20Sopenharmony_ci
12768c2ecf20Sopenharmony_ci	if (data->pwm1.enable == 1) {
12778c2ecf20Sopenharmony_ci		long val;
12788c2ecf20Sopenharmony_ci		int err;
12798c2ecf20Sopenharmony_ci
12808c2ecf20Sopenharmony_ci		err = kstrtol(buf, 10, &val);
12818c2ecf20Sopenharmony_ci		if (err)
12828c2ecf20Sopenharmony_ci			return err;
12838c2ecf20Sopenharmony_ci
12848c2ecf20Sopenharmony_ci		mutex_lock(&data->update_lock);
12858c2ecf20Sopenharmony_ci		data->pwm1.pwm = PWM_TO_REG(val);
12868c2ecf20Sopenharmony_ci		adm1026_write_value(client, ADM1026_REG_PWM, data->pwm1.pwm);
12878c2ecf20Sopenharmony_ci		mutex_unlock(&data->update_lock);
12888c2ecf20Sopenharmony_ci	}
12898c2ecf20Sopenharmony_ci	return count;
12908c2ecf20Sopenharmony_ci}
12918c2ecf20Sopenharmony_ci
12928c2ecf20Sopenharmony_cistatic ssize_t temp1_auto_point1_pwm_show(struct device *dev,
12938c2ecf20Sopenharmony_ci					  struct device_attribute *attr,
12948c2ecf20Sopenharmony_ci					  char *buf)
12958c2ecf20Sopenharmony_ci{
12968c2ecf20Sopenharmony_ci	struct adm1026_data *data = adm1026_update_device(dev);
12978c2ecf20Sopenharmony_ci	return sprintf(buf, "%d\n", data->pwm1.auto_pwm_min);
12988c2ecf20Sopenharmony_ci}
12998c2ecf20Sopenharmony_ci
13008c2ecf20Sopenharmony_cistatic ssize_t temp1_auto_point1_pwm_store(struct device *dev,
13018c2ecf20Sopenharmony_ci					   struct device_attribute *attr,
13028c2ecf20Sopenharmony_ci					   const char *buf, size_t count)
13038c2ecf20Sopenharmony_ci{
13048c2ecf20Sopenharmony_ci	struct adm1026_data *data = dev_get_drvdata(dev);
13058c2ecf20Sopenharmony_ci	struct i2c_client *client = data->client;
13068c2ecf20Sopenharmony_ci	unsigned long val;
13078c2ecf20Sopenharmony_ci	int err;
13088c2ecf20Sopenharmony_ci
13098c2ecf20Sopenharmony_ci	err = kstrtoul(buf, 10, &val);
13108c2ecf20Sopenharmony_ci	if (err)
13118c2ecf20Sopenharmony_ci		return err;
13128c2ecf20Sopenharmony_ci
13138c2ecf20Sopenharmony_ci	mutex_lock(&data->update_lock);
13148c2ecf20Sopenharmony_ci	data->pwm1.auto_pwm_min = clamp_val(val, 0, 255);
13158c2ecf20Sopenharmony_ci	if (data->pwm1.enable == 2) { /* apply immediately */
13168c2ecf20Sopenharmony_ci		data->pwm1.pwm = PWM_TO_REG((data->pwm1.pwm & 0x0f) |
13178c2ecf20Sopenharmony_ci			PWM_MIN_TO_REG(data->pwm1.auto_pwm_min));
13188c2ecf20Sopenharmony_ci		adm1026_write_value(client, ADM1026_REG_PWM, data->pwm1.pwm);
13198c2ecf20Sopenharmony_ci	}
13208c2ecf20Sopenharmony_ci	mutex_unlock(&data->update_lock);
13218c2ecf20Sopenharmony_ci	return count;
13228c2ecf20Sopenharmony_ci}
13238c2ecf20Sopenharmony_ci
13248c2ecf20Sopenharmony_cistatic ssize_t temp1_auto_point2_pwm_show(struct device *dev,
13258c2ecf20Sopenharmony_ci					  struct device_attribute *attr,
13268c2ecf20Sopenharmony_ci					  char *buf)
13278c2ecf20Sopenharmony_ci{
13288c2ecf20Sopenharmony_ci	return sprintf(buf, "%d\n", ADM1026_PWM_MAX);
13298c2ecf20Sopenharmony_ci}
13308c2ecf20Sopenharmony_ci
13318c2ecf20Sopenharmony_cistatic ssize_t pwm1_enable_show(struct device *dev,
13328c2ecf20Sopenharmony_ci				struct device_attribute *attr, char *buf)
13338c2ecf20Sopenharmony_ci{
13348c2ecf20Sopenharmony_ci	struct adm1026_data *data = adm1026_update_device(dev);
13358c2ecf20Sopenharmony_ci	return sprintf(buf, "%d\n", data->pwm1.enable);
13368c2ecf20Sopenharmony_ci}
13378c2ecf20Sopenharmony_ci
13388c2ecf20Sopenharmony_cistatic ssize_t pwm1_enable_store(struct device *dev,
13398c2ecf20Sopenharmony_ci				 struct device_attribute *attr,
13408c2ecf20Sopenharmony_ci				 const char *buf, size_t count)
13418c2ecf20Sopenharmony_ci{
13428c2ecf20Sopenharmony_ci	struct adm1026_data *data = dev_get_drvdata(dev);
13438c2ecf20Sopenharmony_ci	struct i2c_client *client = data->client;
13448c2ecf20Sopenharmony_ci	int old_enable;
13458c2ecf20Sopenharmony_ci	unsigned long val;
13468c2ecf20Sopenharmony_ci	int err;
13478c2ecf20Sopenharmony_ci
13488c2ecf20Sopenharmony_ci	err = kstrtoul(buf, 10, &val);
13498c2ecf20Sopenharmony_ci	if (err)
13508c2ecf20Sopenharmony_ci		return err;
13518c2ecf20Sopenharmony_ci
13528c2ecf20Sopenharmony_ci	if (val >= 3)
13538c2ecf20Sopenharmony_ci		return -EINVAL;
13548c2ecf20Sopenharmony_ci
13558c2ecf20Sopenharmony_ci	mutex_lock(&data->update_lock);
13568c2ecf20Sopenharmony_ci	old_enable = data->pwm1.enable;
13578c2ecf20Sopenharmony_ci	data->pwm1.enable = val;
13588c2ecf20Sopenharmony_ci	data->config1 = (data->config1 & ~CFG1_PWM_AFC)
13598c2ecf20Sopenharmony_ci			| ((val == 2) ? CFG1_PWM_AFC : 0);
13608c2ecf20Sopenharmony_ci	adm1026_write_value(client, ADM1026_REG_CONFIG1, data->config1);
13618c2ecf20Sopenharmony_ci	if (val == 2) { /* apply pwm1_auto_pwm_min to pwm1 */
13628c2ecf20Sopenharmony_ci		data->pwm1.pwm = PWM_TO_REG((data->pwm1.pwm & 0x0f) |
13638c2ecf20Sopenharmony_ci			PWM_MIN_TO_REG(data->pwm1.auto_pwm_min));
13648c2ecf20Sopenharmony_ci		adm1026_write_value(client, ADM1026_REG_PWM, data->pwm1.pwm);
13658c2ecf20Sopenharmony_ci	} else if (!((old_enable == 1) && (val == 1))) {
13668c2ecf20Sopenharmony_ci		/* set pwm to safe value */
13678c2ecf20Sopenharmony_ci		data->pwm1.pwm = 255;
13688c2ecf20Sopenharmony_ci		adm1026_write_value(client, ADM1026_REG_PWM, data->pwm1.pwm);
13698c2ecf20Sopenharmony_ci	}
13708c2ecf20Sopenharmony_ci	mutex_unlock(&data->update_lock);
13718c2ecf20Sopenharmony_ci
13728c2ecf20Sopenharmony_ci	return count;
13738c2ecf20Sopenharmony_ci}
13748c2ecf20Sopenharmony_ci
13758c2ecf20Sopenharmony_ci/* enable PWM fan control */
13768c2ecf20Sopenharmony_cistatic DEVICE_ATTR_RW(pwm1);
13778c2ecf20Sopenharmony_cistatic DEVICE_ATTR(pwm2, 0644, pwm1_show, pwm1_store);
13788c2ecf20Sopenharmony_cistatic DEVICE_ATTR(pwm3, 0644, pwm1_show, pwm1_store);
13798c2ecf20Sopenharmony_cistatic DEVICE_ATTR_RW(pwm1_enable);
13808c2ecf20Sopenharmony_cistatic DEVICE_ATTR(pwm2_enable, 0644, pwm1_enable_show,
13818c2ecf20Sopenharmony_ci		   pwm1_enable_store);
13828c2ecf20Sopenharmony_cistatic DEVICE_ATTR(pwm3_enable, 0644, pwm1_enable_show,
13838c2ecf20Sopenharmony_ci		   pwm1_enable_store);
13848c2ecf20Sopenharmony_cistatic DEVICE_ATTR_RW(temp1_auto_point1_pwm);
13858c2ecf20Sopenharmony_cistatic DEVICE_ATTR(temp2_auto_point1_pwm, 0644,
13868c2ecf20Sopenharmony_ci		   temp1_auto_point1_pwm_show, temp1_auto_point1_pwm_store);
13878c2ecf20Sopenharmony_cistatic DEVICE_ATTR(temp3_auto_point1_pwm, 0644,
13888c2ecf20Sopenharmony_ci		   temp1_auto_point1_pwm_show, temp1_auto_point1_pwm_store);
13898c2ecf20Sopenharmony_ci
13908c2ecf20Sopenharmony_cistatic DEVICE_ATTR_RO(temp1_auto_point2_pwm);
13918c2ecf20Sopenharmony_cistatic DEVICE_ATTR(temp2_auto_point2_pwm, 0444, temp1_auto_point2_pwm_show,
13928c2ecf20Sopenharmony_ci		   NULL);
13938c2ecf20Sopenharmony_cistatic DEVICE_ATTR(temp3_auto_point2_pwm, 0444, temp1_auto_point2_pwm_show,
13948c2ecf20Sopenharmony_ci		   NULL);
13958c2ecf20Sopenharmony_ci
13968c2ecf20Sopenharmony_cistatic struct attribute *adm1026_attributes[] = {
13978c2ecf20Sopenharmony_ci	&sensor_dev_attr_in0_input.dev_attr.attr,
13988c2ecf20Sopenharmony_ci	&sensor_dev_attr_in0_max.dev_attr.attr,
13998c2ecf20Sopenharmony_ci	&sensor_dev_attr_in0_min.dev_attr.attr,
14008c2ecf20Sopenharmony_ci	&sensor_dev_attr_in0_alarm.dev_attr.attr,
14018c2ecf20Sopenharmony_ci	&sensor_dev_attr_in1_input.dev_attr.attr,
14028c2ecf20Sopenharmony_ci	&sensor_dev_attr_in1_max.dev_attr.attr,
14038c2ecf20Sopenharmony_ci	&sensor_dev_attr_in1_min.dev_attr.attr,
14048c2ecf20Sopenharmony_ci	&sensor_dev_attr_in1_alarm.dev_attr.attr,
14058c2ecf20Sopenharmony_ci	&sensor_dev_attr_in2_input.dev_attr.attr,
14068c2ecf20Sopenharmony_ci	&sensor_dev_attr_in2_max.dev_attr.attr,
14078c2ecf20Sopenharmony_ci	&sensor_dev_attr_in2_min.dev_attr.attr,
14088c2ecf20Sopenharmony_ci	&sensor_dev_attr_in2_alarm.dev_attr.attr,
14098c2ecf20Sopenharmony_ci	&sensor_dev_attr_in3_input.dev_attr.attr,
14108c2ecf20Sopenharmony_ci	&sensor_dev_attr_in3_max.dev_attr.attr,
14118c2ecf20Sopenharmony_ci	&sensor_dev_attr_in3_min.dev_attr.attr,
14128c2ecf20Sopenharmony_ci	&sensor_dev_attr_in3_alarm.dev_attr.attr,
14138c2ecf20Sopenharmony_ci	&sensor_dev_attr_in4_input.dev_attr.attr,
14148c2ecf20Sopenharmony_ci	&sensor_dev_attr_in4_max.dev_attr.attr,
14158c2ecf20Sopenharmony_ci	&sensor_dev_attr_in4_min.dev_attr.attr,
14168c2ecf20Sopenharmony_ci	&sensor_dev_attr_in4_alarm.dev_attr.attr,
14178c2ecf20Sopenharmony_ci	&sensor_dev_attr_in5_input.dev_attr.attr,
14188c2ecf20Sopenharmony_ci	&sensor_dev_attr_in5_max.dev_attr.attr,
14198c2ecf20Sopenharmony_ci	&sensor_dev_attr_in5_min.dev_attr.attr,
14208c2ecf20Sopenharmony_ci	&sensor_dev_attr_in5_alarm.dev_attr.attr,
14218c2ecf20Sopenharmony_ci	&sensor_dev_attr_in6_input.dev_attr.attr,
14228c2ecf20Sopenharmony_ci	&sensor_dev_attr_in6_max.dev_attr.attr,
14238c2ecf20Sopenharmony_ci	&sensor_dev_attr_in6_min.dev_attr.attr,
14248c2ecf20Sopenharmony_ci	&sensor_dev_attr_in6_alarm.dev_attr.attr,
14258c2ecf20Sopenharmony_ci	&sensor_dev_attr_in7_input.dev_attr.attr,
14268c2ecf20Sopenharmony_ci	&sensor_dev_attr_in7_max.dev_attr.attr,
14278c2ecf20Sopenharmony_ci	&sensor_dev_attr_in7_min.dev_attr.attr,
14288c2ecf20Sopenharmony_ci	&sensor_dev_attr_in7_alarm.dev_attr.attr,
14298c2ecf20Sopenharmony_ci	&sensor_dev_attr_in10_input.dev_attr.attr,
14308c2ecf20Sopenharmony_ci	&sensor_dev_attr_in10_max.dev_attr.attr,
14318c2ecf20Sopenharmony_ci	&sensor_dev_attr_in10_min.dev_attr.attr,
14328c2ecf20Sopenharmony_ci	&sensor_dev_attr_in10_alarm.dev_attr.attr,
14338c2ecf20Sopenharmony_ci	&sensor_dev_attr_in11_input.dev_attr.attr,
14348c2ecf20Sopenharmony_ci	&sensor_dev_attr_in11_max.dev_attr.attr,
14358c2ecf20Sopenharmony_ci	&sensor_dev_attr_in11_min.dev_attr.attr,
14368c2ecf20Sopenharmony_ci	&sensor_dev_attr_in11_alarm.dev_attr.attr,
14378c2ecf20Sopenharmony_ci	&sensor_dev_attr_in12_input.dev_attr.attr,
14388c2ecf20Sopenharmony_ci	&sensor_dev_attr_in12_max.dev_attr.attr,
14398c2ecf20Sopenharmony_ci	&sensor_dev_attr_in12_min.dev_attr.attr,
14408c2ecf20Sopenharmony_ci	&sensor_dev_attr_in12_alarm.dev_attr.attr,
14418c2ecf20Sopenharmony_ci	&sensor_dev_attr_in13_input.dev_attr.attr,
14428c2ecf20Sopenharmony_ci	&sensor_dev_attr_in13_max.dev_attr.attr,
14438c2ecf20Sopenharmony_ci	&sensor_dev_attr_in13_min.dev_attr.attr,
14448c2ecf20Sopenharmony_ci	&sensor_dev_attr_in13_alarm.dev_attr.attr,
14458c2ecf20Sopenharmony_ci	&sensor_dev_attr_in14_input.dev_attr.attr,
14468c2ecf20Sopenharmony_ci	&sensor_dev_attr_in14_max.dev_attr.attr,
14478c2ecf20Sopenharmony_ci	&sensor_dev_attr_in14_min.dev_attr.attr,
14488c2ecf20Sopenharmony_ci	&sensor_dev_attr_in14_alarm.dev_attr.attr,
14498c2ecf20Sopenharmony_ci	&sensor_dev_attr_in15_input.dev_attr.attr,
14508c2ecf20Sopenharmony_ci	&sensor_dev_attr_in15_max.dev_attr.attr,
14518c2ecf20Sopenharmony_ci	&sensor_dev_attr_in15_min.dev_attr.attr,
14528c2ecf20Sopenharmony_ci	&sensor_dev_attr_in15_alarm.dev_attr.attr,
14538c2ecf20Sopenharmony_ci	&sensor_dev_attr_in16_input.dev_attr.attr,
14548c2ecf20Sopenharmony_ci	&sensor_dev_attr_in16_max.dev_attr.attr,
14558c2ecf20Sopenharmony_ci	&sensor_dev_attr_in16_min.dev_attr.attr,
14568c2ecf20Sopenharmony_ci	&sensor_dev_attr_in16_alarm.dev_attr.attr,
14578c2ecf20Sopenharmony_ci	&sensor_dev_attr_fan1_input.dev_attr.attr,
14588c2ecf20Sopenharmony_ci	&sensor_dev_attr_fan1_div.dev_attr.attr,
14598c2ecf20Sopenharmony_ci	&sensor_dev_attr_fan1_min.dev_attr.attr,
14608c2ecf20Sopenharmony_ci	&sensor_dev_attr_fan1_alarm.dev_attr.attr,
14618c2ecf20Sopenharmony_ci	&sensor_dev_attr_fan2_input.dev_attr.attr,
14628c2ecf20Sopenharmony_ci	&sensor_dev_attr_fan2_div.dev_attr.attr,
14638c2ecf20Sopenharmony_ci	&sensor_dev_attr_fan2_min.dev_attr.attr,
14648c2ecf20Sopenharmony_ci	&sensor_dev_attr_fan2_alarm.dev_attr.attr,
14658c2ecf20Sopenharmony_ci	&sensor_dev_attr_fan3_input.dev_attr.attr,
14668c2ecf20Sopenharmony_ci	&sensor_dev_attr_fan3_div.dev_attr.attr,
14678c2ecf20Sopenharmony_ci	&sensor_dev_attr_fan3_min.dev_attr.attr,
14688c2ecf20Sopenharmony_ci	&sensor_dev_attr_fan3_alarm.dev_attr.attr,
14698c2ecf20Sopenharmony_ci	&sensor_dev_attr_fan4_input.dev_attr.attr,
14708c2ecf20Sopenharmony_ci	&sensor_dev_attr_fan4_div.dev_attr.attr,
14718c2ecf20Sopenharmony_ci	&sensor_dev_attr_fan4_min.dev_attr.attr,
14728c2ecf20Sopenharmony_ci	&sensor_dev_attr_fan4_alarm.dev_attr.attr,
14738c2ecf20Sopenharmony_ci	&sensor_dev_attr_fan5_input.dev_attr.attr,
14748c2ecf20Sopenharmony_ci	&sensor_dev_attr_fan5_div.dev_attr.attr,
14758c2ecf20Sopenharmony_ci	&sensor_dev_attr_fan5_min.dev_attr.attr,
14768c2ecf20Sopenharmony_ci	&sensor_dev_attr_fan5_alarm.dev_attr.attr,
14778c2ecf20Sopenharmony_ci	&sensor_dev_attr_fan6_input.dev_attr.attr,
14788c2ecf20Sopenharmony_ci	&sensor_dev_attr_fan6_div.dev_attr.attr,
14798c2ecf20Sopenharmony_ci	&sensor_dev_attr_fan6_min.dev_attr.attr,
14808c2ecf20Sopenharmony_ci	&sensor_dev_attr_fan6_alarm.dev_attr.attr,
14818c2ecf20Sopenharmony_ci	&sensor_dev_attr_fan7_input.dev_attr.attr,
14828c2ecf20Sopenharmony_ci	&sensor_dev_attr_fan7_div.dev_attr.attr,
14838c2ecf20Sopenharmony_ci	&sensor_dev_attr_fan7_min.dev_attr.attr,
14848c2ecf20Sopenharmony_ci	&sensor_dev_attr_fan7_alarm.dev_attr.attr,
14858c2ecf20Sopenharmony_ci	&sensor_dev_attr_fan8_input.dev_attr.attr,
14868c2ecf20Sopenharmony_ci	&sensor_dev_attr_fan8_div.dev_attr.attr,
14878c2ecf20Sopenharmony_ci	&sensor_dev_attr_fan8_min.dev_attr.attr,
14888c2ecf20Sopenharmony_ci	&sensor_dev_attr_fan8_alarm.dev_attr.attr,
14898c2ecf20Sopenharmony_ci	&sensor_dev_attr_temp1_input.dev_attr.attr,
14908c2ecf20Sopenharmony_ci	&sensor_dev_attr_temp1_max.dev_attr.attr,
14918c2ecf20Sopenharmony_ci	&sensor_dev_attr_temp1_min.dev_attr.attr,
14928c2ecf20Sopenharmony_ci	&sensor_dev_attr_temp1_alarm.dev_attr.attr,
14938c2ecf20Sopenharmony_ci	&sensor_dev_attr_temp2_input.dev_attr.attr,
14948c2ecf20Sopenharmony_ci	&sensor_dev_attr_temp2_max.dev_attr.attr,
14958c2ecf20Sopenharmony_ci	&sensor_dev_attr_temp2_min.dev_attr.attr,
14968c2ecf20Sopenharmony_ci	&sensor_dev_attr_temp2_alarm.dev_attr.attr,
14978c2ecf20Sopenharmony_ci	&sensor_dev_attr_temp1_offset.dev_attr.attr,
14988c2ecf20Sopenharmony_ci	&sensor_dev_attr_temp2_offset.dev_attr.attr,
14998c2ecf20Sopenharmony_ci	&sensor_dev_attr_temp1_auto_point1_temp.dev_attr.attr,
15008c2ecf20Sopenharmony_ci	&sensor_dev_attr_temp2_auto_point1_temp.dev_attr.attr,
15018c2ecf20Sopenharmony_ci	&sensor_dev_attr_temp1_auto_point1_temp_hyst.dev_attr.attr,
15028c2ecf20Sopenharmony_ci	&sensor_dev_attr_temp2_auto_point1_temp_hyst.dev_attr.attr,
15038c2ecf20Sopenharmony_ci	&sensor_dev_attr_temp1_auto_point2_temp.dev_attr.attr,
15048c2ecf20Sopenharmony_ci	&sensor_dev_attr_temp2_auto_point2_temp.dev_attr.attr,
15058c2ecf20Sopenharmony_ci	&sensor_dev_attr_temp1_crit.dev_attr.attr,
15068c2ecf20Sopenharmony_ci	&sensor_dev_attr_temp2_crit.dev_attr.attr,
15078c2ecf20Sopenharmony_ci	&dev_attr_temp1_crit_enable.attr,
15088c2ecf20Sopenharmony_ci	&dev_attr_temp2_crit_enable.attr,
15098c2ecf20Sopenharmony_ci	&dev_attr_cpu0_vid.attr,
15108c2ecf20Sopenharmony_ci	&dev_attr_vrm.attr,
15118c2ecf20Sopenharmony_ci	&dev_attr_alarms.attr,
15128c2ecf20Sopenharmony_ci	&dev_attr_alarm_mask.attr,
15138c2ecf20Sopenharmony_ci	&dev_attr_gpio.attr,
15148c2ecf20Sopenharmony_ci	&dev_attr_gpio_mask.attr,
15158c2ecf20Sopenharmony_ci	&dev_attr_pwm1.attr,
15168c2ecf20Sopenharmony_ci	&dev_attr_pwm2.attr,
15178c2ecf20Sopenharmony_ci	&dev_attr_pwm3.attr,
15188c2ecf20Sopenharmony_ci	&dev_attr_pwm1_enable.attr,
15198c2ecf20Sopenharmony_ci	&dev_attr_pwm2_enable.attr,
15208c2ecf20Sopenharmony_ci	&dev_attr_pwm3_enable.attr,
15218c2ecf20Sopenharmony_ci	&dev_attr_temp1_auto_point1_pwm.attr,
15228c2ecf20Sopenharmony_ci	&dev_attr_temp2_auto_point1_pwm.attr,
15238c2ecf20Sopenharmony_ci	&dev_attr_temp1_auto_point2_pwm.attr,
15248c2ecf20Sopenharmony_ci	&dev_attr_temp2_auto_point2_pwm.attr,
15258c2ecf20Sopenharmony_ci	&dev_attr_analog_out.attr,
15268c2ecf20Sopenharmony_ci	NULL
15278c2ecf20Sopenharmony_ci};
15288c2ecf20Sopenharmony_ci
15298c2ecf20Sopenharmony_cistatic const struct attribute_group adm1026_group = {
15308c2ecf20Sopenharmony_ci	.attrs = adm1026_attributes,
15318c2ecf20Sopenharmony_ci};
15328c2ecf20Sopenharmony_ci
15338c2ecf20Sopenharmony_cistatic struct attribute *adm1026_attributes_temp3[] = {
15348c2ecf20Sopenharmony_ci	&sensor_dev_attr_temp3_input.dev_attr.attr,
15358c2ecf20Sopenharmony_ci	&sensor_dev_attr_temp3_max.dev_attr.attr,
15368c2ecf20Sopenharmony_ci	&sensor_dev_attr_temp3_min.dev_attr.attr,
15378c2ecf20Sopenharmony_ci	&sensor_dev_attr_temp3_alarm.dev_attr.attr,
15388c2ecf20Sopenharmony_ci	&sensor_dev_attr_temp3_offset.dev_attr.attr,
15398c2ecf20Sopenharmony_ci	&sensor_dev_attr_temp3_auto_point1_temp.dev_attr.attr,
15408c2ecf20Sopenharmony_ci	&sensor_dev_attr_temp3_auto_point1_temp_hyst.dev_attr.attr,
15418c2ecf20Sopenharmony_ci	&sensor_dev_attr_temp3_auto_point2_temp.dev_attr.attr,
15428c2ecf20Sopenharmony_ci	&sensor_dev_attr_temp3_crit.dev_attr.attr,
15438c2ecf20Sopenharmony_ci	&dev_attr_temp3_crit_enable.attr,
15448c2ecf20Sopenharmony_ci	&dev_attr_temp3_auto_point1_pwm.attr,
15458c2ecf20Sopenharmony_ci	&dev_attr_temp3_auto_point2_pwm.attr,
15468c2ecf20Sopenharmony_ci	NULL
15478c2ecf20Sopenharmony_ci};
15488c2ecf20Sopenharmony_ci
15498c2ecf20Sopenharmony_cistatic const struct attribute_group adm1026_group_temp3 = {
15508c2ecf20Sopenharmony_ci	.attrs = adm1026_attributes_temp3,
15518c2ecf20Sopenharmony_ci};
15528c2ecf20Sopenharmony_ci
15538c2ecf20Sopenharmony_cistatic struct attribute *adm1026_attributes_in8_9[] = {
15548c2ecf20Sopenharmony_ci	&sensor_dev_attr_in8_input.dev_attr.attr,
15558c2ecf20Sopenharmony_ci	&sensor_dev_attr_in8_max.dev_attr.attr,
15568c2ecf20Sopenharmony_ci	&sensor_dev_attr_in8_min.dev_attr.attr,
15578c2ecf20Sopenharmony_ci	&sensor_dev_attr_in8_alarm.dev_attr.attr,
15588c2ecf20Sopenharmony_ci	&sensor_dev_attr_in9_input.dev_attr.attr,
15598c2ecf20Sopenharmony_ci	&sensor_dev_attr_in9_max.dev_attr.attr,
15608c2ecf20Sopenharmony_ci	&sensor_dev_attr_in9_min.dev_attr.attr,
15618c2ecf20Sopenharmony_ci	&sensor_dev_attr_in9_alarm.dev_attr.attr,
15628c2ecf20Sopenharmony_ci	NULL
15638c2ecf20Sopenharmony_ci};
15648c2ecf20Sopenharmony_ci
15658c2ecf20Sopenharmony_cistatic const struct attribute_group adm1026_group_in8_9 = {
15668c2ecf20Sopenharmony_ci	.attrs = adm1026_attributes_in8_9,
15678c2ecf20Sopenharmony_ci};
15688c2ecf20Sopenharmony_ci
15698c2ecf20Sopenharmony_ci/* Return 0 if detection is successful, -ENODEV otherwise */
15708c2ecf20Sopenharmony_cistatic int adm1026_detect(struct i2c_client *client,
15718c2ecf20Sopenharmony_ci			  struct i2c_board_info *info)
15728c2ecf20Sopenharmony_ci{
15738c2ecf20Sopenharmony_ci	struct i2c_adapter *adapter = client->adapter;
15748c2ecf20Sopenharmony_ci	int address = client->addr;
15758c2ecf20Sopenharmony_ci	int company, verstep;
15768c2ecf20Sopenharmony_ci
15778c2ecf20Sopenharmony_ci	if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA)) {
15788c2ecf20Sopenharmony_ci		/* We need to be able to do byte I/O */
15798c2ecf20Sopenharmony_ci		return -ENODEV;
15808c2ecf20Sopenharmony_ci	}
15818c2ecf20Sopenharmony_ci
15828c2ecf20Sopenharmony_ci	/* Now, we do the remaining detection. */
15838c2ecf20Sopenharmony_ci
15848c2ecf20Sopenharmony_ci	company = adm1026_read_value(client, ADM1026_REG_COMPANY);
15858c2ecf20Sopenharmony_ci	verstep = adm1026_read_value(client, ADM1026_REG_VERSTEP);
15868c2ecf20Sopenharmony_ci
15878c2ecf20Sopenharmony_ci	dev_dbg(&adapter->dev,
15888c2ecf20Sopenharmony_ci		"Detecting device at %d,0x%02x with COMPANY: 0x%02x and VERSTEP: 0x%02x\n",
15898c2ecf20Sopenharmony_ci		i2c_adapter_id(client->adapter), client->addr,
15908c2ecf20Sopenharmony_ci		company, verstep);
15918c2ecf20Sopenharmony_ci
15928c2ecf20Sopenharmony_ci	/* Determine the chip type. */
15938c2ecf20Sopenharmony_ci	dev_dbg(&adapter->dev, "Autodetecting device at %d,0x%02x...\n",
15948c2ecf20Sopenharmony_ci		i2c_adapter_id(adapter), address);
15958c2ecf20Sopenharmony_ci	if (company == ADM1026_COMPANY_ANALOG_DEV
15968c2ecf20Sopenharmony_ci	    && verstep == ADM1026_VERSTEP_ADM1026) {
15978c2ecf20Sopenharmony_ci		/* Analog Devices ADM1026 */
15988c2ecf20Sopenharmony_ci	} else if (company == ADM1026_COMPANY_ANALOG_DEV
15998c2ecf20Sopenharmony_ci		&& (verstep & 0xf0) == ADM1026_VERSTEP_GENERIC) {
16008c2ecf20Sopenharmony_ci		dev_err(&adapter->dev,
16018c2ecf20Sopenharmony_ci			"Unrecognized stepping 0x%02x. Defaulting to ADM1026.\n",
16028c2ecf20Sopenharmony_ci			verstep);
16038c2ecf20Sopenharmony_ci	} else if ((verstep & 0xf0) == ADM1026_VERSTEP_GENERIC) {
16048c2ecf20Sopenharmony_ci		dev_err(&adapter->dev,
16058c2ecf20Sopenharmony_ci			"Found version/stepping 0x%02x. Assuming generic ADM1026.\n",
16068c2ecf20Sopenharmony_ci			verstep);
16078c2ecf20Sopenharmony_ci	} else {
16088c2ecf20Sopenharmony_ci		dev_dbg(&adapter->dev, "Autodetection failed\n");
16098c2ecf20Sopenharmony_ci		/* Not an ADM1026... */
16108c2ecf20Sopenharmony_ci		return -ENODEV;
16118c2ecf20Sopenharmony_ci	}
16128c2ecf20Sopenharmony_ci
16138c2ecf20Sopenharmony_ci	strlcpy(info->type, "adm1026", I2C_NAME_SIZE);
16148c2ecf20Sopenharmony_ci
16158c2ecf20Sopenharmony_ci	return 0;
16168c2ecf20Sopenharmony_ci}
16178c2ecf20Sopenharmony_ci
16188c2ecf20Sopenharmony_cistatic void adm1026_print_gpio(struct i2c_client *client)
16198c2ecf20Sopenharmony_ci{
16208c2ecf20Sopenharmony_ci	struct adm1026_data *data = i2c_get_clientdata(client);
16218c2ecf20Sopenharmony_ci	int i;
16228c2ecf20Sopenharmony_ci
16238c2ecf20Sopenharmony_ci	dev_dbg(&client->dev, "GPIO config is:\n");
16248c2ecf20Sopenharmony_ci	for (i = 0; i <= 7; ++i) {
16258c2ecf20Sopenharmony_ci		if (data->config2 & (1 << i)) {
16268c2ecf20Sopenharmony_ci			dev_dbg(&client->dev, "\t%sGP%s%d\n",
16278c2ecf20Sopenharmony_ci				data->gpio_config[i] & 0x02 ? "" : "!",
16288c2ecf20Sopenharmony_ci				data->gpio_config[i] & 0x01 ? "OUT" : "IN",
16298c2ecf20Sopenharmony_ci				i);
16308c2ecf20Sopenharmony_ci		} else {
16318c2ecf20Sopenharmony_ci			dev_dbg(&client->dev, "\tFAN%d\n", i);
16328c2ecf20Sopenharmony_ci		}
16338c2ecf20Sopenharmony_ci	}
16348c2ecf20Sopenharmony_ci	for (i = 8; i <= 15; ++i) {
16358c2ecf20Sopenharmony_ci		dev_dbg(&client->dev, "\t%sGP%s%d\n",
16368c2ecf20Sopenharmony_ci			data->gpio_config[i] & 0x02 ? "" : "!",
16378c2ecf20Sopenharmony_ci			data->gpio_config[i] & 0x01 ? "OUT" : "IN",
16388c2ecf20Sopenharmony_ci			i);
16398c2ecf20Sopenharmony_ci	}
16408c2ecf20Sopenharmony_ci	if (data->config3 & CFG3_GPIO16_ENABLE) {
16418c2ecf20Sopenharmony_ci		dev_dbg(&client->dev, "\t%sGP%s16\n",
16428c2ecf20Sopenharmony_ci			data->gpio_config[16] & 0x02 ? "" : "!",
16438c2ecf20Sopenharmony_ci			data->gpio_config[16] & 0x01 ? "OUT" : "IN");
16448c2ecf20Sopenharmony_ci	} else {
16458c2ecf20Sopenharmony_ci		/* GPIO16 is THERM */
16468c2ecf20Sopenharmony_ci		dev_dbg(&client->dev, "\tTHERM\n");
16478c2ecf20Sopenharmony_ci	}
16488c2ecf20Sopenharmony_ci}
16498c2ecf20Sopenharmony_ci
16508c2ecf20Sopenharmony_cistatic void adm1026_fixup_gpio(struct i2c_client *client)
16518c2ecf20Sopenharmony_ci{
16528c2ecf20Sopenharmony_ci	struct adm1026_data *data = i2c_get_clientdata(client);
16538c2ecf20Sopenharmony_ci	int i;
16548c2ecf20Sopenharmony_ci	int value;
16558c2ecf20Sopenharmony_ci
16568c2ecf20Sopenharmony_ci	/* Make the changes requested. */
16578c2ecf20Sopenharmony_ci	/*
16588c2ecf20Sopenharmony_ci	 * We may need to unlock/stop monitoring or soft-reset the
16598c2ecf20Sopenharmony_ci	 *    chip before we can make changes.  This hasn't been
16608c2ecf20Sopenharmony_ci	 *    tested much.  FIXME
16618c2ecf20Sopenharmony_ci	 */
16628c2ecf20Sopenharmony_ci
16638c2ecf20Sopenharmony_ci	/* Make outputs */
16648c2ecf20Sopenharmony_ci	for (i = 0; i <= 16; ++i) {
16658c2ecf20Sopenharmony_ci		if (gpio_output[i] >= 0 && gpio_output[i] <= 16)
16668c2ecf20Sopenharmony_ci			data->gpio_config[gpio_output[i]] |= 0x01;
16678c2ecf20Sopenharmony_ci		/* if GPIO0-7 is output, it isn't a FAN tach */
16688c2ecf20Sopenharmony_ci		if (gpio_output[i] >= 0 && gpio_output[i] <= 7)
16698c2ecf20Sopenharmony_ci			data->config2 |= 1 << gpio_output[i];
16708c2ecf20Sopenharmony_ci	}
16718c2ecf20Sopenharmony_ci
16728c2ecf20Sopenharmony_ci	/* Input overrides output */
16738c2ecf20Sopenharmony_ci	for (i = 0; i <= 16; ++i) {
16748c2ecf20Sopenharmony_ci		if (gpio_input[i] >= 0 && gpio_input[i] <= 16)
16758c2ecf20Sopenharmony_ci			data->gpio_config[gpio_input[i]] &= ~0x01;
16768c2ecf20Sopenharmony_ci		/* if GPIO0-7 is input, it isn't a FAN tach */
16778c2ecf20Sopenharmony_ci		if (gpio_input[i] >= 0 && gpio_input[i] <= 7)
16788c2ecf20Sopenharmony_ci			data->config2 |= 1 << gpio_input[i];
16798c2ecf20Sopenharmony_ci	}
16808c2ecf20Sopenharmony_ci
16818c2ecf20Sopenharmony_ci	/* Inverted */
16828c2ecf20Sopenharmony_ci	for (i = 0; i <= 16; ++i) {
16838c2ecf20Sopenharmony_ci		if (gpio_inverted[i] >= 0 && gpio_inverted[i] <= 16)
16848c2ecf20Sopenharmony_ci			data->gpio_config[gpio_inverted[i]] &= ~0x02;
16858c2ecf20Sopenharmony_ci	}
16868c2ecf20Sopenharmony_ci
16878c2ecf20Sopenharmony_ci	/* Normal overrides inverted */
16888c2ecf20Sopenharmony_ci	for (i = 0; i <= 16; ++i) {
16898c2ecf20Sopenharmony_ci		if (gpio_normal[i] >= 0 && gpio_normal[i] <= 16)
16908c2ecf20Sopenharmony_ci			data->gpio_config[gpio_normal[i]] |= 0x02;
16918c2ecf20Sopenharmony_ci	}
16928c2ecf20Sopenharmony_ci
16938c2ecf20Sopenharmony_ci	/* Fan overrides input and output */
16948c2ecf20Sopenharmony_ci	for (i = 0; i <= 7; ++i) {
16958c2ecf20Sopenharmony_ci		if (gpio_fan[i] >= 0 && gpio_fan[i] <= 7)
16968c2ecf20Sopenharmony_ci			data->config2 &= ~(1 << gpio_fan[i]);
16978c2ecf20Sopenharmony_ci	}
16988c2ecf20Sopenharmony_ci
16998c2ecf20Sopenharmony_ci	/* Write new configs to registers */
17008c2ecf20Sopenharmony_ci	adm1026_write_value(client, ADM1026_REG_CONFIG2, data->config2);
17018c2ecf20Sopenharmony_ci	data->config3 = (data->config3 & 0x3f)
17028c2ecf20Sopenharmony_ci			| ((data->gpio_config[16] & 0x03) << 6);
17038c2ecf20Sopenharmony_ci	adm1026_write_value(client, ADM1026_REG_CONFIG3, data->config3);
17048c2ecf20Sopenharmony_ci	for (i = 15, value = 0; i >= 0; --i) {
17058c2ecf20Sopenharmony_ci		value <<= 2;
17068c2ecf20Sopenharmony_ci		value |= data->gpio_config[i] & 0x03;
17078c2ecf20Sopenharmony_ci		if ((i & 0x03) == 0) {
17088c2ecf20Sopenharmony_ci			adm1026_write_value(client,
17098c2ecf20Sopenharmony_ci					ADM1026_REG_GPIO_CFG_0_3 + i/4,
17108c2ecf20Sopenharmony_ci					value);
17118c2ecf20Sopenharmony_ci			value = 0;
17128c2ecf20Sopenharmony_ci		}
17138c2ecf20Sopenharmony_ci	}
17148c2ecf20Sopenharmony_ci
17158c2ecf20Sopenharmony_ci	/* Print the new config */
17168c2ecf20Sopenharmony_ci	adm1026_print_gpio(client);
17178c2ecf20Sopenharmony_ci}
17188c2ecf20Sopenharmony_ci
17198c2ecf20Sopenharmony_cistatic void adm1026_init_client(struct i2c_client *client)
17208c2ecf20Sopenharmony_ci{
17218c2ecf20Sopenharmony_ci	int value, i;
17228c2ecf20Sopenharmony_ci	struct adm1026_data *data = i2c_get_clientdata(client);
17238c2ecf20Sopenharmony_ci
17248c2ecf20Sopenharmony_ci	dev_dbg(&client->dev, "Initializing device\n");
17258c2ecf20Sopenharmony_ci	/* Read chip config */
17268c2ecf20Sopenharmony_ci	data->config1 = adm1026_read_value(client, ADM1026_REG_CONFIG1);
17278c2ecf20Sopenharmony_ci	data->config2 = adm1026_read_value(client, ADM1026_REG_CONFIG2);
17288c2ecf20Sopenharmony_ci	data->config3 = adm1026_read_value(client, ADM1026_REG_CONFIG3);
17298c2ecf20Sopenharmony_ci
17308c2ecf20Sopenharmony_ci	/* Inform user of chip config */
17318c2ecf20Sopenharmony_ci	dev_dbg(&client->dev, "ADM1026_REG_CONFIG1 is: 0x%02x\n",
17328c2ecf20Sopenharmony_ci		data->config1);
17338c2ecf20Sopenharmony_ci	if ((data->config1 & CFG1_MONITOR) == 0) {
17348c2ecf20Sopenharmony_ci		dev_dbg(&client->dev,
17358c2ecf20Sopenharmony_ci			"Monitoring not currently enabled.\n");
17368c2ecf20Sopenharmony_ci	}
17378c2ecf20Sopenharmony_ci	if (data->config1 & CFG1_INT_ENABLE) {
17388c2ecf20Sopenharmony_ci		dev_dbg(&client->dev,
17398c2ecf20Sopenharmony_ci			"SMBALERT interrupts are enabled.\n");
17408c2ecf20Sopenharmony_ci	}
17418c2ecf20Sopenharmony_ci	if (data->config1 & CFG1_AIN8_9) {
17428c2ecf20Sopenharmony_ci		dev_dbg(&client->dev,
17438c2ecf20Sopenharmony_ci			"in8 and in9 enabled. temp3 disabled.\n");
17448c2ecf20Sopenharmony_ci	} else {
17458c2ecf20Sopenharmony_ci		dev_dbg(&client->dev,
17468c2ecf20Sopenharmony_ci			"temp3 enabled.  in8 and in9 disabled.\n");
17478c2ecf20Sopenharmony_ci	}
17488c2ecf20Sopenharmony_ci	if (data->config1 & CFG1_THERM_HOT) {
17498c2ecf20Sopenharmony_ci		dev_dbg(&client->dev,
17508c2ecf20Sopenharmony_ci			"Automatic THERM, PWM, and temp limits enabled.\n");
17518c2ecf20Sopenharmony_ci	}
17528c2ecf20Sopenharmony_ci
17538c2ecf20Sopenharmony_ci	if (data->config3 & CFG3_GPIO16_ENABLE) {
17548c2ecf20Sopenharmony_ci		dev_dbg(&client->dev,
17558c2ecf20Sopenharmony_ci			"GPIO16 enabled.  THERM pin disabled.\n");
17568c2ecf20Sopenharmony_ci	} else {
17578c2ecf20Sopenharmony_ci		dev_dbg(&client->dev,
17588c2ecf20Sopenharmony_ci			"THERM pin enabled.  GPIO16 disabled.\n");
17598c2ecf20Sopenharmony_ci	}
17608c2ecf20Sopenharmony_ci	if (data->config3 & CFG3_VREF_250)
17618c2ecf20Sopenharmony_ci		dev_dbg(&client->dev, "Vref is 2.50 Volts.\n");
17628c2ecf20Sopenharmony_ci	else
17638c2ecf20Sopenharmony_ci		dev_dbg(&client->dev, "Vref is 1.82 Volts.\n");
17648c2ecf20Sopenharmony_ci	/* Read and pick apart the existing GPIO configuration */
17658c2ecf20Sopenharmony_ci	value = 0;
17668c2ecf20Sopenharmony_ci	for (i = 0; i <= 15; ++i) {
17678c2ecf20Sopenharmony_ci		if ((i & 0x03) == 0) {
17688c2ecf20Sopenharmony_ci			value = adm1026_read_value(client,
17698c2ecf20Sopenharmony_ci					ADM1026_REG_GPIO_CFG_0_3 + i / 4);
17708c2ecf20Sopenharmony_ci		}
17718c2ecf20Sopenharmony_ci		data->gpio_config[i] = value & 0x03;
17728c2ecf20Sopenharmony_ci		value >>= 2;
17738c2ecf20Sopenharmony_ci	}
17748c2ecf20Sopenharmony_ci	data->gpio_config[16] = (data->config3 >> 6) & 0x03;
17758c2ecf20Sopenharmony_ci
17768c2ecf20Sopenharmony_ci	/* ... and then print it */
17778c2ecf20Sopenharmony_ci	adm1026_print_gpio(client);
17788c2ecf20Sopenharmony_ci
17798c2ecf20Sopenharmony_ci	/*
17808c2ecf20Sopenharmony_ci	 * If the user asks us to reprogram the GPIO config, then
17818c2ecf20Sopenharmony_ci	 * do it now.
17828c2ecf20Sopenharmony_ci	 */
17838c2ecf20Sopenharmony_ci	if (gpio_input[0] != -1 || gpio_output[0] != -1
17848c2ecf20Sopenharmony_ci		|| gpio_inverted[0] != -1 || gpio_normal[0] != -1
17858c2ecf20Sopenharmony_ci		|| gpio_fan[0] != -1) {
17868c2ecf20Sopenharmony_ci		adm1026_fixup_gpio(client);
17878c2ecf20Sopenharmony_ci	}
17888c2ecf20Sopenharmony_ci
17898c2ecf20Sopenharmony_ci	/*
17908c2ecf20Sopenharmony_ci	 * WE INTENTIONALLY make no changes to the limits,
17918c2ecf20Sopenharmony_ci	 *   offsets, pwms, fans and zones.  If they were
17928c2ecf20Sopenharmony_ci	 *   configured, we don't want to mess with them.
17938c2ecf20Sopenharmony_ci	 *   If they weren't, the default is 100% PWM, no
17948c2ecf20Sopenharmony_ci	 *   control and will suffice until 'sensors -s'
17958c2ecf20Sopenharmony_ci	 *   can be run by the user.  We DO set the default
17968c2ecf20Sopenharmony_ci	 *   value for pwm1.auto_pwm_min to its maximum
17978c2ecf20Sopenharmony_ci	 *   so that enabling automatic pwm fan control
17988c2ecf20Sopenharmony_ci	 *   without first setting a value for pwm1.auto_pwm_min
17998c2ecf20Sopenharmony_ci	 *   will not result in potentially dangerous fan speed decrease.
18008c2ecf20Sopenharmony_ci	 */
18018c2ecf20Sopenharmony_ci	data->pwm1.auto_pwm_min = 255;
18028c2ecf20Sopenharmony_ci	/* Start monitoring */
18038c2ecf20Sopenharmony_ci	value = adm1026_read_value(client, ADM1026_REG_CONFIG1);
18048c2ecf20Sopenharmony_ci	/* Set MONITOR, clear interrupt acknowledge and s/w reset */
18058c2ecf20Sopenharmony_ci	value = (value | CFG1_MONITOR) & (~CFG1_INT_CLEAR & ~CFG1_RESET);
18068c2ecf20Sopenharmony_ci	dev_dbg(&client->dev, "Setting CONFIG to: 0x%02x\n", value);
18078c2ecf20Sopenharmony_ci	data->config1 = value;
18088c2ecf20Sopenharmony_ci	adm1026_write_value(client, ADM1026_REG_CONFIG1, value);
18098c2ecf20Sopenharmony_ci
18108c2ecf20Sopenharmony_ci	/* initialize fan_div[] to hardware defaults */
18118c2ecf20Sopenharmony_ci	value = adm1026_read_value(client, ADM1026_REG_FAN_DIV_0_3) |
18128c2ecf20Sopenharmony_ci		(adm1026_read_value(client, ADM1026_REG_FAN_DIV_4_7) << 8);
18138c2ecf20Sopenharmony_ci	for (i = 0; i <= 7; ++i) {
18148c2ecf20Sopenharmony_ci		data->fan_div[i] = DIV_FROM_REG(value & 0x03);
18158c2ecf20Sopenharmony_ci		value >>= 2;
18168c2ecf20Sopenharmony_ci	}
18178c2ecf20Sopenharmony_ci}
18188c2ecf20Sopenharmony_ci
18198c2ecf20Sopenharmony_cistatic int adm1026_probe(struct i2c_client *client)
18208c2ecf20Sopenharmony_ci{
18218c2ecf20Sopenharmony_ci	struct device *dev = &client->dev;
18228c2ecf20Sopenharmony_ci	struct device *hwmon_dev;
18238c2ecf20Sopenharmony_ci	struct adm1026_data *data;
18248c2ecf20Sopenharmony_ci
18258c2ecf20Sopenharmony_ci	data = devm_kzalloc(dev, sizeof(struct adm1026_data), GFP_KERNEL);
18268c2ecf20Sopenharmony_ci	if (!data)
18278c2ecf20Sopenharmony_ci		return -ENOMEM;
18288c2ecf20Sopenharmony_ci
18298c2ecf20Sopenharmony_ci	i2c_set_clientdata(client, data);
18308c2ecf20Sopenharmony_ci	data->client = client;
18318c2ecf20Sopenharmony_ci	mutex_init(&data->update_lock);
18328c2ecf20Sopenharmony_ci
18338c2ecf20Sopenharmony_ci	/* Set the VRM version */
18348c2ecf20Sopenharmony_ci	data->vrm = vid_which_vrm();
18358c2ecf20Sopenharmony_ci
18368c2ecf20Sopenharmony_ci	/* Initialize the ADM1026 chip */
18378c2ecf20Sopenharmony_ci	adm1026_init_client(client);
18388c2ecf20Sopenharmony_ci
18398c2ecf20Sopenharmony_ci	/* sysfs hooks */
18408c2ecf20Sopenharmony_ci	data->groups[0] = &adm1026_group;
18418c2ecf20Sopenharmony_ci	if (data->config1 & CFG1_AIN8_9)
18428c2ecf20Sopenharmony_ci		data->groups[1] = &adm1026_group_in8_9;
18438c2ecf20Sopenharmony_ci	else
18448c2ecf20Sopenharmony_ci		data->groups[1] = &adm1026_group_temp3;
18458c2ecf20Sopenharmony_ci
18468c2ecf20Sopenharmony_ci	hwmon_dev = devm_hwmon_device_register_with_groups(dev, client->name,
18478c2ecf20Sopenharmony_ci							   data, data->groups);
18488c2ecf20Sopenharmony_ci	return PTR_ERR_OR_ZERO(hwmon_dev);
18498c2ecf20Sopenharmony_ci}
18508c2ecf20Sopenharmony_ci
18518c2ecf20Sopenharmony_cistatic const struct i2c_device_id adm1026_id[] = {
18528c2ecf20Sopenharmony_ci	{ "adm1026", 0 },
18538c2ecf20Sopenharmony_ci	{ }
18548c2ecf20Sopenharmony_ci};
18558c2ecf20Sopenharmony_ciMODULE_DEVICE_TABLE(i2c, adm1026_id);
18568c2ecf20Sopenharmony_ci
18578c2ecf20Sopenharmony_cistatic struct i2c_driver adm1026_driver = {
18588c2ecf20Sopenharmony_ci	.class		= I2C_CLASS_HWMON,
18598c2ecf20Sopenharmony_ci	.driver = {
18608c2ecf20Sopenharmony_ci		.name	= "adm1026",
18618c2ecf20Sopenharmony_ci	},
18628c2ecf20Sopenharmony_ci	.probe_new	= adm1026_probe,
18638c2ecf20Sopenharmony_ci	.id_table	= adm1026_id,
18648c2ecf20Sopenharmony_ci	.detect		= adm1026_detect,
18658c2ecf20Sopenharmony_ci	.address_list	= normal_i2c,
18668c2ecf20Sopenharmony_ci};
18678c2ecf20Sopenharmony_ci
18688c2ecf20Sopenharmony_cimodule_i2c_driver(adm1026_driver);
18698c2ecf20Sopenharmony_ci
18708c2ecf20Sopenharmony_ciMODULE_LICENSE("GPL");
18718c2ecf20Sopenharmony_ciMODULE_AUTHOR("Philip Pokorny <ppokorny@penguincomputing.com>, "
18728c2ecf20Sopenharmony_ci	      "Justin Thiessen <jthiessen@penguincomputing.com>");
18738c2ecf20Sopenharmony_ciMODULE_DESCRIPTION("ADM1026 driver");
1874