11da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*
286aa3e22106be3d6338113ff5acd7a87c40056c4Guenter Roeck * adm1026.c - Part of lm_sensors, Linux kernel modules for hardware
386aa3e22106be3d6338113ff5acd7a87c40056c4Guenter Roeck *	       monitoring
486aa3e22106be3d6338113ff5acd7a87c40056c4Guenter Roeck * Copyright (C) 2002, 2003  Philip Pokorny <ppokorny@penguincomputing.com>
586aa3e22106be3d6338113ff5acd7a87c40056c4Guenter Roeck * Copyright (C) 2004 Justin Thiessen <jthiessen@penguincomputing.com>
686aa3e22106be3d6338113ff5acd7a87c40056c4Guenter Roeck *
786aa3e22106be3d6338113ff5acd7a87c40056c4Guenter Roeck * Chip details at:
886aa3e22106be3d6338113ff5acd7a87c40056c4Guenter Roeck *
986aa3e22106be3d6338113ff5acd7a87c40056c4Guenter Roeck * <http://www.onsemi.com/PowerSolutions/product.do?id=ADM1026>
1086aa3e22106be3d6338113ff5acd7a87c40056c4Guenter Roeck *
1186aa3e22106be3d6338113ff5acd7a87c40056c4Guenter Roeck * This program is free software; you can redistribute it and/or modify
1286aa3e22106be3d6338113ff5acd7a87c40056c4Guenter Roeck * it under the terms of the GNU General Public License as published by
1386aa3e22106be3d6338113ff5acd7a87c40056c4Guenter Roeck * the Free Software Foundation; either version 2 of the License, or
1486aa3e22106be3d6338113ff5acd7a87c40056c4Guenter Roeck * (at your option) any later version.
1586aa3e22106be3d6338113ff5acd7a87c40056c4Guenter Roeck *
1686aa3e22106be3d6338113ff5acd7a87c40056c4Guenter Roeck * This program is distributed in the hope that it will be useful,
1786aa3e22106be3d6338113ff5acd7a87c40056c4Guenter Roeck * but WITHOUT ANY WARRANTY; without even the implied warranty of
1886aa3e22106be3d6338113ff5acd7a87c40056c4Guenter Roeck * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
1986aa3e22106be3d6338113ff5acd7a87c40056c4Guenter Roeck * GNU General Public License for more details.
2086aa3e22106be3d6338113ff5acd7a87c40056c4Guenter Roeck *
2186aa3e22106be3d6338113ff5acd7a87c40056c4Guenter Roeck * You should have received a copy of the GNU General Public License
2286aa3e22106be3d6338113ff5acd7a87c40056c4Guenter Roeck * along with this program; if not, write to the Free Software
2386aa3e22106be3d6338113ff5acd7a87c40056c4Guenter Roeck * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
2486aa3e22106be3d6338113ff5acd7a87c40056c4Guenter Roeck */
251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/module.h>
271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/init.h>
281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/slab.h>
291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/jiffies.h>
301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/i2c.h>
31943b0830cebe4711354945ed3cb44e84152aaca0Mark M. Hoffman#include <linux/hwmon.h>
32303760b44a7a142cb9f4c9df4609fb63bbda98dbJean Delvare#include <linux/hwmon-sysfs.h>
33303760b44a7a142cb9f4c9df4609fb63bbda98dbJean Delvare#include <linux/hwmon-vid.h>
34943b0830cebe4711354945ed3cb44e84152aaca0Mark M. Hoffman#include <linux/err.h>
359a61bf6300533d3b64d7ff29adfec00e596de67dIngo Molnar#include <linux/mutex.h>
361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* Addresses to scan */
3825e9c86d5a6d82ea45eb680fc66bf73ac5e50dffMark M. Hoffmanstatic const unsigned short normal_i2c[] = { 0x2c, 0x2d, 0x2e, I2C_CLIENT_END };
391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
40cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvarestatic int gpio_input[17] = { -1, -1, -1, -1, -1, -1, -1, -1, -1,
41cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvare				-1, -1, -1, -1, -1, -1, -1, -1 };
421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int gpio_output[17] = { -1, -1, -1, -1, -1, -1, -1, -1, -1,
431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				-1, -1, -1, -1, -1, -1, -1, -1 };
441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int gpio_inverted[17] = { -1, -1, -1, -1, -1, -1, -1, -1, -1,
451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				-1, -1, -1, -1, -1, -1, -1, -1 };
461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int gpio_normal[17] = { -1, -1, -1, -1, -1, -1, -1, -1, -1,
471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				-1, -1, -1, -1, -1, -1, -1, -1 };
481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int gpio_fan[8] = { -1, -1, -1, -1, -1, -1, -1, -1 };
49cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvaremodule_param_array(gpio_input, int, NULL, 0);
50cb01a2312f56c93d2740e827718966b92b7cbb91Jean DelvareMODULE_PARM_DESC(gpio_input, "List of GPIO pins (0-16) to program as inputs");
51cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvaremodule_param_array(gpio_output, int, NULL, 0);
52b55f375725ff85aada394da488802b0a3cc99e88Guenter RoeckMODULE_PARM_DESC(gpio_output,
53b55f375725ff85aada394da488802b0a3cc99e88Guenter Roeck		 "List of GPIO pins (0-16) to program as outputs");
54cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvaremodule_param_array(gpio_inverted, int, NULL, 0);
55b55f375725ff85aada394da488802b0a3cc99e88Guenter RoeckMODULE_PARM_DESC(gpio_inverted,
56b55f375725ff85aada394da488802b0a3cc99e88Guenter Roeck		 "List of GPIO pins (0-16) to program as inverted");
57cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvaremodule_param_array(gpio_normal, int, NULL, 0);
58b55f375725ff85aada394da488802b0a3cc99e88Guenter RoeckMODULE_PARM_DESC(gpio_normal,
59b55f375725ff85aada394da488802b0a3cc99e88Guenter Roeck		 "List of GPIO pins (0-16) to program as normal/non-inverted");
60cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvaremodule_param_array(gpio_fan, int, NULL, 0);
61cb01a2312f56c93d2740e827718966b92b7cbb91Jean DelvareMODULE_PARM_DESC(gpio_fan, "List of GPIO pins (0-7) to program as fan tachs");
621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* Many ADM1026 constants specified below */
641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* The ADM1026 registers */
66cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvare#define ADM1026_REG_CONFIG1	0x00
67cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvare#define CFG1_MONITOR		0x01
68cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvare#define CFG1_INT_ENABLE		0x02
69cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvare#define CFG1_INT_CLEAR		0x04
70cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvare#define CFG1_AIN8_9		0x08
71cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvare#define CFG1_THERM_HOT		0x10
72cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvare#define CFG1_DAC_AFC		0x20
73cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvare#define CFG1_PWM_AFC		0x40
74cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvare#define CFG1_RESET		0x80
75cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvare
76cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvare#define ADM1026_REG_CONFIG2	0x01
771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* CONFIG2 controls FAN0/GPIO0 through FAN7/GPIO7 */
78cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvare
79cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvare#define ADM1026_REG_CONFIG3	0x07
80cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvare#define CFG3_GPIO16_ENABLE	0x01
81cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvare#define CFG3_CI_CLEAR		0x02
82cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvare#define CFG3_VREF_250		0x04
83cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvare#define CFG3_GPIO16_DIR		0x40
84cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvare#define CFG3_GPIO16_POL		0x80
85cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvare
86cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvare#define ADM1026_REG_E2CONFIG	0x13
87cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvare#define E2CFG_READ		0x01
88cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvare#define E2CFG_WRITE		0x02
89cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvare#define E2CFG_ERASE		0x04
90cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvare#define E2CFG_ROM		0x08
91cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvare#define E2CFG_CLK_EXT		0x80
921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
9386aa3e22106be3d6338113ff5acd7a87c40056c4Guenter Roeck/*
9486aa3e22106be3d6338113ff5acd7a87c40056c4Guenter Roeck * There are 10 general analog inputs and 7 dedicated inputs
951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * They are:
961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *    0 - 9  =  AIN0 - AIN9
971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *       10  =  Vbat
981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *       11  =  3.3V Standby
991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *       12  =  3.3V Main
1001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *       13  =  +5V
1011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *       14  =  Vccp (CPU core voltage)
1021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *       15  =  +12V
1031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *       16  =  -12V
1041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
1051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic u16 ADM1026_REG_IN[] = {
1061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		0x30, 0x31, 0x32, 0x33, 0x34, 0x35,
1071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		0x36, 0x37, 0x27, 0x29, 0x26, 0x2a,
1081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		0x2b, 0x2c, 0x2d, 0x2e, 0x2f
1091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	};
1101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic u16 ADM1026_REG_IN_MIN[] = {
1111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		0x58, 0x59, 0x5a, 0x5b, 0x5c, 0x5d,
1121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		0x5e, 0x5f, 0x6d, 0x49, 0x6b, 0x4a,
1131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		0x4b, 0x4c, 0x4d, 0x4e, 0x4f
1141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	};
1151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic u16 ADM1026_REG_IN_MAX[] = {
1161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		0x50, 0x51, 0x52, 0x53, 0x54, 0x55,
1171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		0x56, 0x57, 0x6c, 0x41, 0x6a, 0x42,
1181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		0x43, 0x44, 0x45, 0x46, 0x47
1191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	};
1201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
12186aa3e22106be3d6338113ff5acd7a87c40056c4Guenter Roeck/*
12286aa3e22106be3d6338113ff5acd7a87c40056c4Guenter Roeck * Temperatures are:
1231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *    0 - Internal
1241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *    1 - External 1
1251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *    2 - External 2
1261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
1271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic u16 ADM1026_REG_TEMP[] = { 0x1f, 0x28, 0x29 };
1281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic u16 ADM1026_REG_TEMP_MIN[] = { 0x69, 0x48, 0x49 };
1291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic u16 ADM1026_REG_TEMP_MAX[] = { 0x68, 0x40, 0x41 };
1301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic u16 ADM1026_REG_TEMP_TMIN[] = { 0x10, 0x11, 0x12 };
1311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic u16 ADM1026_REG_TEMP_THERM[] = { 0x0d, 0x0e, 0x0f };
1321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic u16 ADM1026_REG_TEMP_OFFSET[] = { 0x1e, 0x6e, 0x6f };
1331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
134cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvare#define ADM1026_REG_FAN(nr)		(0x38 + (nr))
135cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvare#define ADM1026_REG_FAN_MIN(nr)		(0x60 + (nr))
136cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvare#define ADM1026_REG_FAN_DIV_0_3		0x02
137cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvare#define ADM1026_REG_FAN_DIV_4_7		0x03
1381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
139cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvare#define ADM1026_REG_DAC			0x04
140cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvare#define ADM1026_REG_PWM			0x05
1411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
142cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvare#define ADM1026_REG_GPIO_CFG_0_3	0x08
143cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvare#define ADM1026_REG_GPIO_CFG_4_7	0x09
144cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvare#define ADM1026_REG_GPIO_CFG_8_11	0x0a
145cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvare#define ADM1026_REG_GPIO_CFG_12_15	0x0b
1461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* CFG_16 in REG_CFG3 */
147cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvare#define ADM1026_REG_GPIO_STATUS_0_7	0x24
148cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvare#define ADM1026_REG_GPIO_STATUS_8_15	0x25
1491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* STATUS_16 in REG_STATUS4 */
150cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvare#define ADM1026_REG_GPIO_MASK_0_7	0x1c
151cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvare#define ADM1026_REG_GPIO_MASK_8_15	0x1d
1521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* MASK_16 in REG_MASK4 */
1531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
154cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvare#define ADM1026_REG_COMPANY		0x16
155cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvare#define ADM1026_REG_VERSTEP		0x17
1561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* These are the recognized values for the above regs */
157cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvare#define ADM1026_COMPANY_ANALOG_DEV	0x41
158cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvare#define ADM1026_VERSTEP_GENERIC		0x40
159cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvare#define ADM1026_VERSTEP_ADM1026		0x44
1601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
161cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvare#define ADM1026_REG_MASK1		0x18
162cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvare#define ADM1026_REG_MASK2		0x19
163cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvare#define ADM1026_REG_MASK3		0x1a
164cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvare#define ADM1026_REG_MASK4		0x1b
1651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
166cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvare#define ADM1026_REG_STATUS1		0x20
167cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvare#define ADM1026_REG_STATUS2		0x21
168cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvare#define ADM1026_REG_STATUS3		0x22
169cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvare#define ADM1026_REG_STATUS4		0x23
1701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define ADM1026_FAN_ACTIVATION_TEMP_HYST -6
172cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvare#define ADM1026_FAN_CONTROL_TEMP_RANGE	20
173cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvare#define ADM1026_PWM_MAX			255
1741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
17586aa3e22106be3d6338113ff5acd7a87c40056c4Guenter Roeck/*
17686aa3e22106be3d6338113ff5acd7a87c40056c4Guenter Roeck * Conversions. Rounding and limit checking is only done on the TO_REG
1771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * variants. Note that you should be a bit careful with which arguments
1781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * these macros are called: arguments may be evaluated more than once.
1791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
1801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
18186aa3e22106be3d6338113ff5acd7a87c40056c4Guenter Roeck/*
18286aa3e22106be3d6338113ff5acd7a87c40056c4Guenter Roeck * IN are scaled according to built-in resistors.  These are the
1831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *   voltages corresponding to 3/4 of full scale (192 or 0xc0)
1841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *   NOTE: The -12V input needs an additional factor to account
1851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *      for the Vref pullup resistor.
1861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *      NEG12_OFFSET = SCALE * Vref / V-192 - Vref
1871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *                   = 13875 * 2.50 / 1.875 - 2500
1881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *                   = 16000
1891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
1901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * The values in this table are based on Table II, page 15 of the
1911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *    datasheet.
1921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
193cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvarestatic int adm1026_scaling[] = { /* .001 Volts */
194cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvare		2250, 2250, 2250, 2250, 2250, 2250,
195cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvare		1875, 1875, 1875, 1875, 3000, 3330,
1961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		3330, 4995, 2250, 12000, 13875
1971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	};
1981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define NEG12_OFFSET  16000
199cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvare#define SCALE(val, from, to) (((val)*(to) + ((from)/2))/(from))
2002a844c148e1f714ebf42cb96e1b172ce394c36c9Guenter Roeck#define INS_TO_REG(n, val)  (clamp_val(SCALE(val, adm1026_scaling[n], 192),\
201cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvare	0, 255))
202cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvare#define INS_FROM_REG(n, val) (SCALE(val, 192, adm1026_scaling[n]))
2031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
20486aa3e22106be3d6338113ff5acd7a87c40056c4Guenter Roeck/*
20586aa3e22106be3d6338113ff5acd7a87c40056c4Guenter Roeck * FAN speed is measured using 22.5kHz clock and counts for 2 pulses
2061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *   and we assume a 2 pulse-per-rev fan tach signal
2071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *      22500 kHz * 60 (sec/min) * 2 (pulse) / 2 (pulse/rev) == 1350000
2081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
209cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvare#define FAN_TO_REG(val, div)  ((val) <= 0 ? 0xff : \
2102a844c148e1f714ebf42cb96e1b172ce394c36c9Guenter Roeck				clamp_val(1350000 / ((val) * (div)), \
21186aa3e22106be3d6338113ff5acd7a87c40056c4Guenter Roeck					      1, 254))
21286aa3e22106be3d6338113ff5acd7a87c40056c4Guenter Roeck#define FAN_FROM_REG(val, div) ((val) == 0 ? -1 : (val) == 0xff ? 0 : \
21386aa3e22106be3d6338113ff5acd7a87c40056c4Guenter Roeck				1350000 / ((val) * (div)))
21486aa3e22106be3d6338113ff5acd7a87c40056c4Guenter Roeck#define DIV_FROM_REG(val) (1 << (val))
215cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvare#define DIV_TO_REG(val) ((val) >= 8 ? 3 : (val) >= 4 ? 2 : (val) >= 2 ? 1 : 0)
2161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* Temperature is reported in 1 degC increments */
2182a844c148e1f714ebf42cb96e1b172ce394c36c9Guenter Roeck#define TEMP_TO_REG(val) (clamp_val(((val) + ((val) < 0 ? -500 : 500)) \
21986aa3e22106be3d6338113ff5acd7a87c40056c4Guenter Roeck					/ 1000, -127, 127))
2201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define TEMP_FROM_REG(val) ((val) * 1000)
2212a844c148e1f714ebf42cb96e1b172ce394c36c9Guenter Roeck#define OFFSET_TO_REG(val) (clamp_val(((val) + ((val) < 0 ? -500 : 500)) \
22286aa3e22106be3d6338113ff5acd7a87c40056c4Guenter Roeck					  / 1000, -127, 127))
2231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define OFFSET_FROM_REG(val) ((val) * 1000)
2241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2252a844c148e1f714ebf42cb96e1b172ce394c36c9Guenter Roeck#define PWM_TO_REG(val) (clamp_val(val, 0, 255))
2261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define PWM_FROM_REG(val) (val)
2271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define PWM_MIN_TO_REG(val) ((val) & 0xf0)
2291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define PWM_MIN_FROM_REG(val) (((val) & 0xf0) + ((val) >> 4))
2301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
23186aa3e22106be3d6338113ff5acd7a87c40056c4Guenter Roeck/*
23286aa3e22106be3d6338113ff5acd7a87c40056c4Guenter Roeck * Analog output is a voltage, and scaled to millivolts.  The datasheet
233cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvare *   indicates that the DAC could be used to drive the fans, but in our
2341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *   example board (Arima HDAMA) it isn't connected to the fans at all.
2351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
2362a844c148e1f714ebf42cb96e1b172ce394c36c9Guenter Roeck#define DAC_TO_REG(val) (clamp_val(((((val) * 255) + 500) / 2500), 0, 255))
23786aa3e22106be3d6338113ff5acd7a87c40056c4Guenter Roeck#define DAC_FROM_REG(val) (((val) * 2500) / 255)
2381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
23986aa3e22106be3d6338113ff5acd7a87c40056c4Guenter Roeck/*
24086aa3e22106be3d6338113ff5acd7a87c40056c4Guenter Roeck * Chip sampling rates
2411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
2421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Some sensors are not updated more frequently than once per second
2431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *    so it doesn't make sense to read them more often than that.
2441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *    We cache the results and return the saved data if the driver
2451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *    is called again before a second has elapsed.
2461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
2471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Also, there is significant configuration data for this chip
2481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *    So, we keep the config data up to date in the cache
2491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *    when it is written and only sample it once every 5 *minutes*
2501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
251cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvare#define ADM1026_DATA_INTERVAL		(1 * HZ)
252cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvare#define ADM1026_CONFIG_INTERVAL		(5 * 60 * HZ)
2531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
25486aa3e22106be3d6338113ff5acd7a87c40056c4Guenter Roeck/*
25586aa3e22106be3d6338113ff5acd7a87c40056c4Guenter Roeck * We allow for multiple chips in a single system.
2561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
2571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * For each registered ADM1026, we need to keep state information
2581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * at client->data. The adm1026_data structure is dynamically
25986aa3e22106be3d6338113ff5acd7a87c40056c4Guenter Roeck * allocated, when a new client structure is allocated.
26086aa3e22106be3d6338113ff5acd7a87c40056c4Guenter Roeck */
2611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstruct pwm_data {
2631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	u8 pwm;
2641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	u8 enable;
2651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	u8 auto_pwm_min;
2661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds};
2671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstruct adm1026_data {
269b591d3c1964e7cba6582eb22c7033d37c31a4e99Axel Lin	struct i2c_client *client;
270b591d3c1964e7cba6582eb22c7033d37c31a4e99Axel Lin	const struct attribute_group *groups[3];
2711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2729a61bf6300533d3b64d7ff29adfec00e596de67dIngo Molnar	struct mutex update_lock;
2731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int valid;		/* !=0 if following fields are valid */
2741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	unsigned long last_reading;	/* In jiffies */
2751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	unsigned long last_config;	/* In jiffies */
2761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
277cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvare	u8 in[17];		/* Register value */
278cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvare	u8 in_max[17];		/* Register value */
279cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvare	u8 in_min[17];		/* Register value */
280cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvare	s8 temp[3];		/* Register value */
281cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvare	s8 temp_min[3];		/* Register value */
282cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvare	s8 temp_max[3];		/* Register value */
283cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvare	s8 temp_tmin[3];	/* Register value */
284cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvare	s8 temp_crit[3];	/* Register value */
285cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvare	s8 temp_offset[3];	/* Register value */
286cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvare	u8 fan[8];		/* Register value */
287cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvare	u8 fan_min[8];		/* Register value */
288cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvare	u8 fan_div[8];		/* Decoded value */
289cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvare	struct pwm_data pwm1;	/* Pwm control values */
290cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvare	u8 vrm;			/* VRM version */
2911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	u8 analog_out;		/* Register value (DAC) */
292cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvare	long alarms;		/* Register encoding, combined */
293cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvare	long alarm_mask;	/* Register encoding, combined */
294cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvare	long gpio;		/* Register encoding, combined */
295cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvare	long gpio_mask;		/* Register encoding, combined */
296cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvare	u8 gpio_config[17];	/* Decoded value */
297cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvare	u8 config1;		/* Register value */
298cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvare	u8 config2;		/* Register value */
299cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvare	u8 config3;		/* Register value */
3001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds};
3011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
302c49efceffa599299ab3f38b1cdf8c2f1bf9811c4Ben Dooksstatic int adm1026_read_value(struct i2c_client *client, u8 reg)
3031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
3041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int res;
3051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (reg < 0x80) {
3071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		/* "RAM" locations */
3081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		res = i2c_smbus_read_byte_data(client, reg) & 0xff;
3091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	} else {
3101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		/* EEPROM, do nothing */
3111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		res = 0;
3121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
3131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return res;
3141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
3151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
316c49efceffa599299ab3f38b1cdf8c2f1bf9811c4Ben Dooksstatic int adm1026_write_value(struct i2c_client *client, u8 reg, int value)
3171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
3181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int res;
3191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (reg < 0x80) {
3211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		/* "RAM" locations */
3221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		res = i2c_smbus_write_byte_data(client, reg, value);
3231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	} else {
3241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		/* EEPROM, do nothing */
3251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		res = 0;
3261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
3271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return res;
3281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
3291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic struct adm1026_data *adm1026_update_device(struct device *dev)
3311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
332b591d3c1964e7cba6582eb22c7033d37c31a4e99Axel Lin	struct adm1026_data *data = dev_get_drvdata(dev);
333b591d3c1964e7cba6582eb22c7033d37c31a4e99Axel Lin	struct i2c_client *client = data->client;
3341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int i;
3351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	long value, alarms, gpio;
3361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3379a61bf6300533d3b64d7ff29adfec00e596de67dIngo Molnar	mutex_lock(&data->update_lock);
3381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (!data->valid
33986aa3e22106be3d6338113ff5acd7a87c40056c4Guenter Roeck	    || time_after(jiffies,
34086aa3e22106be3d6338113ff5acd7a87c40056c4Guenter Roeck			  data->last_reading + ADM1026_DATA_INTERVAL)) {
3411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		/* Things that change quickly */
342cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvare		dev_dbg(&client->dev, "Reading sensor values\n");
34386aa3e22106be3d6338113ff5acd7a87c40056c4Guenter Roeck		for (i = 0; i <= 16; ++i) {
3441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			data->in[i] =
3451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			    adm1026_read_value(client, ADM1026_REG_IN[i]);
3461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
3471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
34886aa3e22106be3d6338113ff5acd7a87c40056c4Guenter Roeck		for (i = 0; i <= 7; ++i) {
3491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			data->fan[i] =
3501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			    adm1026_read_value(client, ADM1026_REG_FAN(i));
3511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
3521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
35386aa3e22106be3d6338113ff5acd7a87c40056c4Guenter Roeck		for (i = 0; i <= 2; ++i) {
35486aa3e22106be3d6338113ff5acd7a87c40056c4Guenter Roeck			/*
35586aa3e22106be3d6338113ff5acd7a87c40056c4Guenter Roeck			 * NOTE: temp[] is s8 and we assume 2's complement
35686aa3e22106be3d6338113ff5acd7a87c40056c4Guenter Roeck			 *   "conversion" in the assignment
35786aa3e22106be3d6338113ff5acd7a87c40056c4Guenter Roeck			 */
3581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			data->temp[i] =
3591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			    adm1026_read_value(client, ADM1026_REG_TEMP[i]);
3601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
3611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
362cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvare		data->pwm1.pwm = adm1026_read_value(client,
3631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			ADM1026_REG_PWM);
364cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvare		data->analog_out = adm1026_read_value(client,
3651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			ADM1026_REG_DAC);
3661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		/* GPIO16 is MSbit of alarms, move it to gpio */
3671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		alarms = adm1026_read_value(client, ADM1026_REG_STATUS4);
368cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvare		gpio = alarms & 0x80 ? 0x0100 : 0; /* GPIO16 */
3691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		alarms &= 0x7f;
3701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		alarms <<= 8;
3711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		alarms |= adm1026_read_value(client, ADM1026_REG_STATUS3);
3721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		alarms <<= 8;
3731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		alarms |= adm1026_read_value(client, ADM1026_REG_STATUS2);
3741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		alarms <<= 8;
3751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		alarms |= adm1026_read_value(client, ADM1026_REG_STATUS1);
3761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		data->alarms = alarms;
3771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		/* Read the GPIO values */
379cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvare		gpio |= adm1026_read_value(client,
3801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			ADM1026_REG_GPIO_STATUS_8_15);
3811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		gpio <<= 8;
382cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvare		gpio |= adm1026_read_value(client,
3831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			ADM1026_REG_GPIO_STATUS_0_7);
3841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		data->gpio = gpio;
3851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		data->last_reading = jiffies;
387a0393713530c49697e49ce0456c039228ab7facbGuenter Roeck	}	/* last_reading */
3881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (!data->valid ||
3901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	    time_after(jiffies, data->last_config + ADM1026_CONFIG_INTERVAL)) {
3911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		/* Things that don't change often */
3921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		dev_dbg(&client->dev, "Reading config values\n");
39386aa3e22106be3d6338113ff5acd7a87c40056c4Guenter Roeck		for (i = 0; i <= 16; ++i) {
394cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvare			data->in_min[i] = adm1026_read_value(client,
3951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				ADM1026_REG_IN_MIN[i]);
396cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvare			data->in_max[i] = adm1026_read_value(client,
3971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				ADM1026_REG_IN_MAX[i]);
3981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
3991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		value = adm1026_read_value(client, ADM1026_REG_FAN_DIV_0_3)
4011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			| (adm1026_read_value(client, ADM1026_REG_FAN_DIV_4_7)
4021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			<< 8);
40386aa3e22106be3d6338113ff5acd7a87c40056c4Guenter Roeck		for (i = 0; i <= 7; ++i) {
404cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvare			data->fan_min[i] = adm1026_read_value(client,
4051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				ADM1026_REG_FAN_MIN(i));
4061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			data->fan_div[i] = DIV_FROM_REG(value & 0x03);
4071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			value >>= 2;
4081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
4091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		for (i = 0; i <= 2; ++i) {
41186aa3e22106be3d6338113ff5acd7a87c40056c4Guenter Roeck			/*
41286aa3e22106be3d6338113ff5acd7a87c40056c4Guenter Roeck			 * NOTE: temp_xxx[] are s8 and we assume 2's
4131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			 *    complement "conversion" in the assignment
4141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			 */
415cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvare			data->temp_min[i] = adm1026_read_value(client,
4161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				ADM1026_REG_TEMP_MIN[i]);
417cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvare			data->temp_max[i] = adm1026_read_value(client,
4181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				ADM1026_REG_TEMP_MAX[i]);
419cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvare			data->temp_tmin[i] = adm1026_read_value(client,
4201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				ADM1026_REG_TEMP_TMIN[i]);
421cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvare			data->temp_crit[i] = adm1026_read_value(client,
4221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				ADM1026_REG_TEMP_THERM[i]);
423cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvare			data->temp_offset[i] = adm1026_read_value(client,
4241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				ADM1026_REG_TEMP_OFFSET[i]);
4251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
4261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		/* Read the STATUS/alarm masks */
428cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvare		alarms = adm1026_read_value(client, ADM1026_REG_MASK4);
429cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvare		gpio = alarms & 0x80 ? 0x0100 : 0; /* GPIO16 */
430cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvare		alarms = (alarms & 0x7f) << 8;
4311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		alarms |= adm1026_read_value(client, ADM1026_REG_MASK3);
4321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		alarms <<= 8;
4331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		alarms |= adm1026_read_value(client, ADM1026_REG_MASK2);
4341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		alarms <<= 8;
4351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		alarms |= adm1026_read_value(client, ADM1026_REG_MASK1);
4361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		data->alarm_mask = alarms;
4371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		/* Read the GPIO values */
439cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvare		gpio |= adm1026_read_value(client,
4401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			ADM1026_REG_GPIO_MASK_8_15);
4411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		gpio <<= 8;
4421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		gpio |= adm1026_read_value(client, ADM1026_REG_GPIO_MASK_0_7);
4431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		data->gpio_mask = gpio;
4441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		/* Read various values from CONFIG1 */
446cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvare		data->config1 = adm1026_read_value(client,
4471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			ADM1026_REG_CONFIG1);
4481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (data->config1 & CFG1_PWM_AFC) {
4491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			data->pwm1.enable = 2;
450cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvare			data->pwm1.auto_pwm_min =
4511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				PWM_MIN_FROM_REG(data->pwm1.pwm);
4521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
4531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		/* Read the GPIO config */
454cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvare		data->config2 = adm1026_read_value(client,
4551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			ADM1026_REG_CONFIG2);
456cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvare		data->config3 = adm1026_read_value(client,
4571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			ADM1026_REG_CONFIG3);
4581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		data->gpio_config[16] = (data->config3 >> 6) & 0x03;
4591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		value = 0;
46186aa3e22106be3d6338113ff5acd7a87c40056c4Guenter Roeck		for (i = 0; i <= 15; ++i) {
4621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			if ((i & 0x03) == 0) {
4631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				value = adm1026_read_value(client,
4641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds					    ADM1026_REG_GPIO_CFG_0_3 + i/4);
4651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			}
4661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			data->gpio_config[i] = value & 0x03;
4671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			value >>= 2;
4681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
4691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		data->last_config = jiffies;
471a0393713530c49697e49ce0456c039228ab7facbGuenter Roeck	}	/* last_config */
4721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	data->valid = 1;
4749a61bf6300533d3b64d7ff29adfec00e596de67dIngo Molnar	mutex_unlock(&data->update_lock);
4751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return data;
4761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
4771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
478050480f12aeab62d39a1a07546606a47217ebefaYani Ioannoustatic ssize_t show_in(struct device *dev, struct device_attribute *attr,
479050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou		char *buf)
4801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
481050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou	struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr);
482050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou	int nr = sensor_attr->index;
4831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct adm1026_data *data = adm1026_update_device(dev);
484cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvare	return sprintf(buf, "%d\n", INS_FROM_REG(nr, data->in[nr]));
4851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
486050480f12aeab62d39a1a07546606a47217ebefaYani Ioannoustatic ssize_t show_in_min(struct device *dev, struct device_attribute *attr,
487050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou		char *buf)
4881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
489050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou	struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr);
490050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou	int nr = sensor_attr->index;
491cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvare	struct adm1026_data *data = adm1026_update_device(dev);
492cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvare	return sprintf(buf, "%d\n", INS_FROM_REG(nr, data->in_min[nr]));
4931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
494050480f12aeab62d39a1a07546606a47217ebefaYani Ioannoustatic ssize_t set_in_min(struct device *dev, struct device_attribute *attr,
495050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou		const char *buf, size_t count)
4961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
497050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou	struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr);
498050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou	int nr = sensor_attr->index;
499b591d3c1964e7cba6582eb22c7033d37c31a4e99Axel Lin	struct adm1026_data *data = dev_get_drvdata(dev);
500b591d3c1964e7cba6582eb22c7033d37c31a4e99Axel Lin	struct i2c_client *client = data->client;
50186aa3e22106be3d6338113ff5acd7a87c40056c4Guenter Roeck	long val;
50286aa3e22106be3d6338113ff5acd7a87c40056c4Guenter Roeck	int err;
50386aa3e22106be3d6338113ff5acd7a87c40056c4Guenter Roeck
50486aa3e22106be3d6338113ff5acd7a87c40056c4Guenter Roeck	err = kstrtol(buf, 10, &val);
50586aa3e22106be3d6338113ff5acd7a87c40056c4Guenter Roeck	if (err)
50686aa3e22106be3d6338113ff5acd7a87c40056c4Guenter Roeck		return err;
5071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5089a61bf6300533d3b64d7ff29adfec00e596de67dIngo Molnar	mutex_lock(&data->update_lock);
5091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	data->in_min[nr] = INS_TO_REG(nr, val);
5101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	adm1026_write_value(client, ADM1026_REG_IN_MIN[nr], data->in_min[nr]);
5119a61bf6300533d3b64d7ff29adfec00e596de67dIngo Molnar	mutex_unlock(&data->update_lock);
512cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvare	return count;
5131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
514050480f12aeab62d39a1a07546606a47217ebefaYani Ioannoustatic ssize_t show_in_max(struct device *dev, struct device_attribute *attr,
515050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou		char *buf)
5161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
517050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou	struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr);
518050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou	int nr = sensor_attr->index;
5191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct adm1026_data *data = adm1026_update_device(dev);
520cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvare	return sprintf(buf, "%d\n", INS_FROM_REG(nr, data->in_max[nr]));
5211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
522050480f12aeab62d39a1a07546606a47217ebefaYani Ioannoustatic ssize_t set_in_max(struct device *dev, struct device_attribute *attr,
523050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou		const char *buf, size_t count)
5241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
525050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou	struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr);
526050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou	int nr = sensor_attr->index;
527b591d3c1964e7cba6582eb22c7033d37c31a4e99Axel Lin	struct adm1026_data *data = dev_get_drvdata(dev);
528b591d3c1964e7cba6582eb22c7033d37c31a4e99Axel Lin	struct i2c_client *client = data->client;
52986aa3e22106be3d6338113ff5acd7a87c40056c4Guenter Roeck	long val;
53086aa3e22106be3d6338113ff5acd7a87c40056c4Guenter Roeck	int err;
53186aa3e22106be3d6338113ff5acd7a87c40056c4Guenter Roeck
53286aa3e22106be3d6338113ff5acd7a87c40056c4Guenter Roeck	err = kstrtol(buf, 10, &val);
53386aa3e22106be3d6338113ff5acd7a87c40056c4Guenter Roeck	if (err)
53486aa3e22106be3d6338113ff5acd7a87c40056c4Guenter Roeck		return err;
5351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5369a61bf6300533d3b64d7ff29adfec00e596de67dIngo Molnar	mutex_lock(&data->update_lock);
5371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	data->in_max[nr] = INS_TO_REG(nr, val);
5381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	adm1026_write_value(client, ADM1026_REG_IN_MAX[nr], data->in_max[nr]);
5399a61bf6300533d3b64d7ff29adfec00e596de67dIngo Molnar	mutex_unlock(&data->update_lock);
5401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return count;
5411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
5421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
543050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou#define in_reg(offset)						\
544050480f12aeab62d39a1a07546606a47217ebefaYani Ioannoustatic SENSOR_DEVICE_ATTR(in##offset##_input, S_IRUGO, show_in,	\
545050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou		NULL, offset);					\
546050480f12aeab62d39a1a07546606a47217ebefaYani Ioannoustatic SENSOR_DEVICE_ATTR(in##offset##_min, S_IRUGO | S_IWUSR,	\
547050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou		show_in_min, set_in_min, offset);		\
548050480f12aeab62d39a1a07546606a47217ebefaYani Ioannoustatic SENSOR_DEVICE_ATTR(in##offset##_max, S_IRUGO | S_IWUSR,	\
549050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou		show_in_max, set_in_max, offset);
5501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsin_reg(0);
5531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsin_reg(1);
5541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsin_reg(2);
5551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsin_reg(3);
5561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsin_reg(4);
5571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsin_reg(5);
5581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsin_reg(6);
5591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsin_reg(7);
5601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsin_reg(8);
5611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsin_reg(9);
5621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsin_reg(10);
5631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsin_reg(11);
5641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsin_reg(12);
5651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsin_reg(13);
5661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsin_reg(14);
5671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsin_reg(15);
5681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
56986aa3e22106be3d6338113ff5acd7a87c40056c4Guenter Roeckstatic ssize_t show_in16(struct device *dev, struct device_attribute *attr,
57086aa3e22106be3d6338113ff5acd7a87c40056c4Guenter Roeck			 char *buf)
5711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
5721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct adm1026_data *data = adm1026_update_device(dev);
573cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvare	return sprintf(buf, "%d\n", INS_FROM_REG(16, data->in[16]) -
5741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		NEG12_OFFSET);
5751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
57686aa3e22106be3d6338113ff5acd7a87c40056c4Guenter Roeckstatic ssize_t show_in16_min(struct device *dev, struct device_attribute *attr,
57786aa3e22106be3d6338113ff5acd7a87c40056c4Guenter Roeck			     char *buf)
5781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
579cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvare	struct adm1026_data *data = adm1026_update_device(dev);
580cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvare	return sprintf(buf, "%d\n", INS_FROM_REG(16, data->in_min[16])
5811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		- NEG12_OFFSET);
5821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
58386aa3e22106be3d6338113ff5acd7a87c40056c4Guenter Roeckstatic ssize_t set_in16_min(struct device *dev, struct device_attribute *attr,
58486aa3e22106be3d6338113ff5acd7a87c40056c4Guenter Roeck			    const char *buf, size_t count)
5851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
586b591d3c1964e7cba6582eb22c7033d37c31a4e99Axel Lin	struct adm1026_data *data = dev_get_drvdata(dev);
587b591d3c1964e7cba6582eb22c7033d37c31a4e99Axel Lin	struct i2c_client *client = data->client;
58886aa3e22106be3d6338113ff5acd7a87c40056c4Guenter Roeck	long val;
58986aa3e22106be3d6338113ff5acd7a87c40056c4Guenter Roeck	int err;
59086aa3e22106be3d6338113ff5acd7a87c40056c4Guenter Roeck
59186aa3e22106be3d6338113ff5acd7a87c40056c4Guenter Roeck	err = kstrtol(buf, 10, &val);
59286aa3e22106be3d6338113ff5acd7a87c40056c4Guenter Roeck	if (err)
59386aa3e22106be3d6338113ff5acd7a87c40056c4Guenter Roeck		return err;
5941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5959a61bf6300533d3b64d7ff29adfec00e596de67dIngo Molnar	mutex_lock(&data->update_lock);
5961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	data->in_min[16] = INS_TO_REG(16, val + NEG12_OFFSET);
5971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	adm1026_write_value(client, ADM1026_REG_IN_MIN[16], data->in_min[16]);
5989a61bf6300533d3b64d7ff29adfec00e596de67dIngo Molnar	mutex_unlock(&data->update_lock);
599cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvare	return count;
6001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
60186aa3e22106be3d6338113ff5acd7a87c40056c4Guenter Roeckstatic ssize_t show_in16_max(struct device *dev, struct device_attribute *attr,
60286aa3e22106be3d6338113ff5acd7a87c40056c4Guenter Roeck			     char *buf)
6031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
6041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct adm1026_data *data = adm1026_update_device(dev);
605cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvare	return sprintf(buf, "%d\n", INS_FROM_REG(16, data->in_max[16])
6061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			- NEG12_OFFSET);
6071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
60886aa3e22106be3d6338113ff5acd7a87c40056c4Guenter Roeckstatic ssize_t set_in16_max(struct device *dev, struct device_attribute *attr,
60986aa3e22106be3d6338113ff5acd7a87c40056c4Guenter Roeck			    const char *buf, size_t count)
6101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
611b591d3c1964e7cba6582eb22c7033d37c31a4e99Axel Lin	struct adm1026_data *data = dev_get_drvdata(dev);
612b591d3c1964e7cba6582eb22c7033d37c31a4e99Axel Lin	struct i2c_client *client = data->client;
61386aa3e22106be3d6338113ff5acd7a87c40056c4Guenter Roeck	long val;
61486aa3e22106be3d6338113ff5acd7a87c40056c4Guenter Roeck	int err;
61586aa3e22106be3d6338113ff5acd7a87c40056c4Guenter Roeck
61686aa3e22106be3d6338113ff5acd7a87c40056c4Guenter Roeck	err = kstrtol(buf, 10, &val);
61786aa3e22106be3d6338113ff5acd7a87c40056c4Guenter Roeck	if (err)
61886aa3e22106be3d6338113ff5acd7a87c40056c4Guenter Roeck		return err;
6191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
6209a61bf6300533d3b64d7ff29adfec00e596de67dIngo Molnar	mutex_lock(&data->update_lock);
6211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	data->in_max[16] = INS_TO_REG(16, val+NEG12_OFFSET);
6221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	adm1026_write_value(client, ADM1026_REG_IN_MAX[16], data->in_max[16]);
6239a61bf6300533d3b64d7ff29adfec00e596de67dIngo Molnar	mutex_unlock(&data->update_lock);
6241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return count;
6251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
6261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
627050480f12aeab62d39a1a07546606a47217ebefaYani Ioannoustatic SENSOR_DEVICE_ATTR(in16_input, S_IRUGO, show_in16, NULL, 16);
62886aa3e22106be3d6338113ff5acd7a87c40056c4Guenter Roeckstatic SENSOR_DEVICE_ATTR(in16_min, S_IRUGO | S_IWUSR, show_in16_min,
62986aa3e22106be3d6338113ff5acd7a87c40056c4Guenter Roeck			  set_in16_min, 16);
63086aa3e22106be3d6338113ff5acd7a87c40056c4Guenter Roeckstatic SENSOR_DEVICE_ATTR(in16_max, S_IRUGO | S_IWUSR, show_in16_max,
63186aa3e22106be3d6338113ff5acd7a87c40056c4Guenter Roeck			  set_in16_max, 16);
6321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
6331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
6341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* Now add fan read/write functions */
6351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
636050480f12aeab62d39a1a07546606a47217ebefaYani Ioannoustatic ssize_t show_fan(struct device *dev, struct device_attribute *attr,
637050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou		char *buf)
6381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
639050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou	struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr);
640050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou	int nr = sensor_attr->index;
6411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct adm1026_data *data = adm1026_update_device(dev);
642cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvare	return sprintf(buf, "%d\n", FAN_FROM_REG(data->fan[nr],
6431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		data->fan_div[nr]));
6441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
645050480f12aeab62d39a1a07546606a47217ebefaYani Ioannoustatic ssize_t show_fan_min(struct device *dev, struct device_attribute *attr,
646050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou		char *buf)
6471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
648050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou	struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr);
649050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou	int nr = sensor_attr->index;
6501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct adm1026_data *data = adm1026_update_device(dev);
651cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvare	return sprintf(buf, "%d\n", FAN_FROM_REG(data->fan_min[nr],
6521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		data->fan_div[nr]));
6531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
654050480f12aeab62d39a1a07546606a47217ebefaYani Ioannoustatic ssize_t set_fan_min(struct device *dev, struct device_attribute *attr,
655050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou		const char *buf, size_t count)
6561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
657050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou	struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr);
658050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou	int nr = sensor_attr->index;
659b591d3c1964e7cba6582eb22c7033d37c31a4e99Axel Lin	struct adm1026_data *data = dev_get_drvdata(dev);
660b591d3c1964e7cba6582eb22c7033d37c31a4e99Axel Lin	struct i2c_client *client = data->client;
66186aa3e22106be3d6338113ff5acd7a87c40056c4Guenter Roeck	long val;
66286aa3e22106be3d6338113ff5acd7a87c40056c4Guenter Roeck	int err;
66386aa3e22106be3d6338113ff5acd7a87c40056c4Guenter Roeck
66486aa3e22106be3d6338113ff5acd7a87c40056c4Guenter Roeck	err = kstrtol(buf, 10, &val);
66586aa3e22106be3d6338113ff5acd7a87c40056c4Guenter Roeck	if (err)
66686aa3e22106be3d6338113ff5acd7a87c40056c4Guenter Roeck		return err;
6671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
6689a61bf6300533d3b64d7ff29adfec00e596de67dIngo Molnar	mutex_lock(&data->update_lock);
6691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	data->fan_min[nr] = FAN_TO_REG(val, data->fan_div[nr]);
6701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	adm1026_write_value(client, ADM1026_REG_FAN_MIN(nr),
6711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		data->fan_min[nr]);
6729a61bf6300533d3b64d7ff29adfec00e596de67dIngo Molnar	mutex_unlock(&data->update_lock);
6731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return count;
6741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
6751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
676cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvare#define fan_offset(offset)						\
677cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvarestatic SENSOR_DEVICE_ATTR(fan##offset##_input, S_IRUGO, show_fan, NULL,	\
678cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvare		offset - 1);						\
679cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvarestatic SENSOR_DEVICE_ATTR(fan##offset##_min, S_IRUGO | S_IWUSR,		\
680050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou		show_fan_min, set_fan_min, offset - 1);
6811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
6821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsfan_offset(1);
6831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsfan_offset(2);
6841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsfan_offset(3);
6851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsfan_offset(4);
6861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsfan_offset(5);
6871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsfan_offset(6);
6881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsfan_offset(7);
6891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsfan_offset(8);
6901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
6911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* Adjust fan_min to account for new fan divisor */
6921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void fixup_fan_min(struct device *dev, int fan, int old_div)
6931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
694b591d3c1964e7cba6582eb22c7033d37c31a4e99Axel Lin	struct adm1026_data *data = dev_get_drvdata(dev);
695b591d3c1964e7cba6582eb22c7033d37c31a4e99Axel Lin	struct i2c_client *client = data->client;
696cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvare	int new_min;
697cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvare	int new_div = data->fan_div[fan];
6981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
6991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* 0 and 0xff are special.  Don't adjust them */
70086aa3e22106be3d6338113ff5acd7a87c40056c4Guenter Roeck	if (data->fan_min[fan] == 0 || data->fan_min[fan] == 0xff)
7011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return;
7021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
7031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	new_min = data->fan_min[fan] * old_div / new_div;
7042a844c148e1f714ebf42cb96e1b172ce394c36c9Guenter Roeck	new_min = clamp_val(new_min, 1, 254);
7051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	data->fan_min[fan] = new_min;
7061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	adm1026_write_value(client, ADM1026_REG_FAN_MIN(fan), new_min);
7071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
7081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
7091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* Now add fan_div read/write functions */
710050480f12aeab62d39a1a07546606a47217ebefaYani Ioannoustatic ssize_t show_fan_div(struct device *dev, struct device_attribute *attr,
711050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou		char *buf)
7121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
713050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou	struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr);
714050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou	int nr = sensor_attr->index;
7151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct adm1026_data *data = adm1026_update_device(dev);
716cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvare	return sprintf(buf, "%d\n", data->fan_div[nr]);
7171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
718050480f12aeab62d39a1a07546606a47217ebefaYani Ioannoustatic ssize_t set_fan_div(struct device *dev, struct device_attribute *attr,
719050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou		const char *buf, size_t count)
7201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
721050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou	struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr);
722050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou	int nr = sensor_attr->index;
723b591d3c1964e7cba6582eb22c7033d37c31a4e99Axel Lin	struct adm1026_data *data = dev_get_drvdata(dev);
724b591d3c1964e7cba6582eb22c7033d37c31a4e99Axel Lin	struct i2c_client *client = data->client;
72586aa3e22106be3d6338113ff5acd7a87c40056c4Guenter Roeck	long val;
72686aa3e22106be3d6338113ff5acd7a87c40056c4Guenter Roeck	int orig_div, new_div;
72786aa3e22106be3d6338113ff5acd7a87c40056c4Guenter Roeck	int err;
72886aa3e22106be3d6338113ff5acd7a87c40056c4Guenter Roeck
72986aa3e22106be3d6338113ff5acd7a87c40056c4Guenter Roeck	err = kstrtol(buf, 10, &val);
73086aa3e22106be3d6338113ff5acd7a87c40056c4Guenter Roeck	if (err)
73186aa3e22106be3d6338113ff5acd7a87c40056c4Guenter Roeck		return err;
7321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
733cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvare	new_div = DIV_TO_REG(val);
7348b0f1840a46449e1946fc88860ef3ec8d6b1c2c7Gabriele Gorla
7359a61bf6300533d3b64d7ff29adfec00e596de67dIngo Molnar	mutex_lock(&data->update_lock);
7361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	orig_div = data->fan_div[nr];
7371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	data->fan_div[nr] = DIV_FROM_REG(new_div);
7381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
7391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (nr < 4) { /* 0 <= nr < 4 */
7401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		adm1026_write_value(client, ADM1026_REG_FAN_DIV_0_3,
74152bc9802ce849d0d287cc5fe76d06b0daa3986caGabriele Gorla				    (DIV_TO_REG(data->fan_div[0]) << 0) |
74252bc9802ce849d0d287cc5fe76d06b0daa3986caGabriele Gorla				    (DIV_TO_REG(data->fan_div[1]) << 2) |
74352bc9802ce849d0d287cc5fe76d06b0daa3986caGabriele Gorla				    (DIV_TO_REG(data->fan_div[2]) << 4) |
74452bc9802ce849d0d287cc5fe76d06b0daa3986caGabriele Gorla				    (DIV_TO_REG(data->fan_div[3]) << 6));
7451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	} else { /* 3 < nr < 8 */
7461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		adm1026_write_value(client, ADM1026_REG_FAN_DIV_4_7,
74752bc9802ce849d0d287cc5fe76d06b0daa3986caGabriele Gorla				    (DIV_TO_REG(data->fan_div[4]) << 0) |
74852bc9802ce849d0d287cc5fe76d06b0daa3986caGabriele Gorla				    (DIV_TO_REG(data->fan_div[5]) << 2) |
74952bc9802ce849d0d287cc5fe76d06b0daa3986caGabriele Gorla				    (DIV_TO_REG(data->fan_div[6]) << 4) |
75052bc9802ce849d0d287cc5fe76d06b0daa3986caGabriele Gorla				    (DIV_TO_REG(data->fan_div[7]) << 6));
7511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
7521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
75386aa3e22106be3d6338113ff5acd7a87c40056c4Guenter Roeck	if (data->fan_div[nr] != orig_div)
754cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvare		fixup_fan_min(dev, nr, orig_div);
75586aa3e22106be3d6338113ff5acd7a87c40056c4Guenter Roeck
7569a61bf6300533d3b64d7ff29adfec00e596de67dIngo Molnar	mutex_unlock(&data->update_lock);
7571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return count;
7581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
7591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
760cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvare#define fan_offset_div(offset)						\
761cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvarestatic SENSOR_DEVICE_ATTR(fan##offset##_div, S_IRUGO | S_IWUSR,		\
762050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou		show_fan_div, set_fan_div, offset - 1);
7631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
7641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsfan_offset_div(1);
7651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsfan_offset_div(2);
7661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsfan_offset_div(3);
7671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsfan_offset_div(4);
7681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsfan_offset_div(5);
7691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsfan_offset_div(6);
7701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsfan_offset_div(7);
7711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsfan_offset_div(8);
7721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
7731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* Temps */
774050480f12aeab62d39a1a07546606a47217ebefaYani Ioannoustatic ssize_t show_temp(struct device *dev, struct device_attribute *attr,
775050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou		char *buf)
7761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
777050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou	struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr);
778050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou	int nr = sensor_attr->index;
7791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct adm1026_data *data = adm1026_update_device(dev);
780cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvare	return sprintf(buf, "%d\n", TEMP_FROM_REG(data->temp[nr]));
7811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
782050480f12aeab62d39a1a07546606a47217ebefaYani Ioannoustatic ssize_t show_temp_min(struct device *dev, struct device_attribute *attr,
783050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou		char *buf)
7841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
785050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou	struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr);
786050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou	int nr = sensor_attr->index;
7871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct adm1026_data *data = adm1026_update_device(dev);
788cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvare	return sprintf(buf, "%d\n", TEMP_FROM_REG(data->temp_min[nr]));
7891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
790050480f12aeab62d39a1a07546606a47217ebefaYani Ioannoustatic ssize_t set_temp_min(struct device *dev, struct device_attribute *attr,
791050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou		const char *buf, size_t count)
7921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
793050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou	struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr);
794050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou	int nr = sensor_attr->index;
795b591d3c1964e7cba6582eb22c7033d37c31a4e99Axel Lin	struct adm1026_data *data = dev_get_drvdata(dev);
796b591d3c1964e7cba6582eb22c7033d37c31a4e99Axel Lin	struct i2c_client *client = data->client;
79786aa3e22106be3d6338113ff5acd7a87c40056c4Guenter Roeck	long val;
79886aa3e22106be3d6338113ff5acd7a87c40056c4Guenter Roeck	int err;
79986aa3e22106be3d6338113ff5acd7a87c40056c4Guenter Roeck
80086aa3e22106be3d6338113ff5acd7a87c40056c4Guenter Roeck	err = kstrtol(buf, 10, &val);
80186aa3e22106be3d6338113ff5acd7a87c40056c4Guenter Roeck	if (err)
80286aa3e22106be3d6338113ff5acd7a87c40056c4Guenter Roeck		return err;
8031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
8049a61bf6300533d3b64d7ff29adfec00e596de67dIngo Molnar	mutex_lock(&data->update_lock);
8051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	data->temp_min[nr] = TEMP_TO_REG(val);
8061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	adm1026_write_value(client, ADM1026_REG_TEMP_MIN[nr],
8071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		data->temp_min[nr]);
8089a61bf6300533d3b64d7ff29adfec00e596de67dIngo Molnar	mutex_unlock(&data->update_lock);
8091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return count;
8101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
811050480f12aeab62d39a1a07546606a47217ebefaYani Ioannoustatic ssize_t show_temp_max(struct device *dev, struct device_attribute *attr,
812050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou		char *buf)
8131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
814050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou	struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr);
815050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou	int nr = sensor_attr->index;
8161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct adm1026_data *data = adm1026_update_device(dev);
817cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvare	return sprintf(buf, "%d\n", TEMP_FROM_REG(data->temp_max[nr]));
8181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
819050480f12aeab62d39a1a07546606a47217ebefaYani Ioannoustatic ssize_t set_temp_max(struct device *dev, struct device_attribute *attr,
820050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou		const char *buf, size_t count)
8211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
822050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou	struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr);
823050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou	int nr = sensor_attr->index;
824b591d3c1964e7cba6582eb22c7033d37c31a4e99Axel Lin	struct adm1026_data *data = dev_get_drvdata(dev);
825b591d3c1964e7cba6582eb22c7033d37c31a4e99Axel Lin	struct i2c_client *client = data->client;
82686aa3e22106be3d6338113ff5acd7a87c40056c4Guenter Roeck	long val;
82786aa3e22106be3d6338113ff5acd7a87c40056c4Guenter Roeck	int err;
82886aa3e22106be3d6338113ff5acd7a87c40056c4Guenter Roeck
82986aa3e22106be3d6338113ff5acd7a87c40056c4Guenter Roeck	err = kstrtol(buf, 10, &val);
83086aa3e22106be3d6338113ff5acd7a87c40056c4Guenter Roeck	if (err)
83186aa3e22106be3d6338113ff5acd7a87c40056c4Guenter Roeck		return err;
8321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
8339a61bf6300533d3b64d7ff29adfec00e596de67dIngo Molnar	mutex_lock(&data->update_lock);
8341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	data->temp_max[nr] = TEMP_TO_REG(val);
8351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	adm1026_write_value(client, ADM1026_REG_TEMP_MAX[nr],
8361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		data->temp_max[nr]);
8379a61bf6300533d3b64d7ff29adfec00e596de67dIngo Molnar	mutex_unlock(&data->update_lock);
8381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return count;
8391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
840050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou
841050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou#define temp_reg(offset)						\
842cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvarestatic SENSOR_DEVICE_ATTR(temp##offset##_input, S_IRUGO, show_temp,	\
843050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou		NULL, offset - 1);					\
844050480f12aeab62d39a1a07546606a47217ebefaYani Ioannoustatic SENSOR_DEVICE_ATTR(temp##offset##_min, S_IRUGO | S_IWUSR,	\
845050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou		show_temp_min, set_temp_min, offset - 1);		\
846050480f12aeab62d39a1a07546606a47217ebefaYani Ioannoustatic SENSOR_DEVICE_ATTR(temp##offset##_max, S_IRUGO | S_IWUSR,	\
847050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou		show_temp_max, set_temp_max, offset - 1);
8481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
8491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
8501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldstemp_reg(1);
8511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldstemp_reg(2);
8521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldstemp_reg(3);
8531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
854050480f12aeab62d39a1a07546606a47217ebefaYani Ioannoustatic ssize_t show_temp_offset(struct device *dev,
855050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou		struct device_attribute *attr, char *buf)
8561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
857050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou	struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr);
858050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou	int nr = sensor_attr->index;
8591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct adm1026_data *data = adm1026_update_device(dev);
860cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvare	return sprintf(buf, "%d\n", TEMP_FROM_REG(data->temp_offset[nr]));
8611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
862050480f12aeab62d39a1a07546606a47217ebefaYani Ioannoustatic ssize_t set_temp_offset(struct device *dev,
863050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou		struct device_attribute *attr, const char *buf,
864050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou		size_t count)
8651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
866050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou	struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr);
867050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou	int nr = sensor_attr->index;
868b591d3c1964e7cba6582eb22c7033d37c31a4e99Axel Lin	struct adm1026_data *data = dev_get_drvdata(dev);
869b591d3c1964e7cba6582eb22c7033d37c31a4e99Axel Lin	struct i2c_client *client = data->client;
87086aa3e22106be3d6338113ff5acd7a87c40056c4Guenter Roeck	long val;
87186aa3e22106be3d6338113ff5acd7a87c40056c4Guenter Roeck	int err;
87286aa3e22106be3d6338113ff5acd7a87c40056c4Guenter Roeck
87386aa3e22106be3d6338113ff5acd7a87c40056c4Guenter Roeck	err = kstrtol(buf, 10, &val);
87486aa3e22106be3d6338113ff5acd7a87c40056c4Guenter Roeck	if (err)
87586aa3e22106be3d6338113ff5acd7a87c40056c4Guenter Roeck		return err;
8761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
8779a61bf6300533d3b64d7ff29adfec00e596de67dIngo Molnar	mutex_lock(&data->update_lock);
8781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	data->temp_offset[nr] = TEMP_TO_REG(val);
8791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	adm1026_write_value(client, ADM1026_REG_TEMP_OFFSET[nr],
8801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		data->temp_offset[nr]);
8819a61bf6300533d3b64d7ff29adfec00e596de67dIngo Molnar	mutex_unlock(&data->update_lock);
8821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return count;
8831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
8841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
88586aa3e22106be3d6338113ff5acd7a87c40056c4Guenter Roeck#define temp_offset_reg(offset)						\
88686aa3e22106be3d6338113ff5acd7a87c40056c4Guenter Roeckstatic SENSOR_DEVICE_ATTR(temp##offset##_offset, S_IRUGO | S_IWUSR,	\
887050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou		show_temp_offset, set_temp_offset, offset - 1);
8881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
8891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldstemp_offset_reg(1);
8901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldstemp_offset_reg(2);
8911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldstemp_offset_reg(3);
8921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
893050480f12aeab62d39a1a07546606a47217ebefaYani Ioannoustatic ssize_t show_temp_auto_point1_temp_hyst(struct device *dev,
894050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou		struct device_attribute *attr, char *buf)
8951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
896050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou	struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr);
897050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou	int nr = sensor_attr->index;
8981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct adm1026_data *data = adm1026_update_device(dev);
899cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvare	return sprintf(buf, "%d\n", TEMP_FROM_REG(
9001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		ADM1026_FAN_ACTIVATION_TEMP_HYST + data->temp_tmin[nr]));
9011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
902050480f12aeab62d39a1a07546606a47217ebefaYani Ioannoustatic ssize_t show_temp_auto_point2_temp(struct device *dev,
903050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou		struct device_attribute *attr, char *buf)
9041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
905050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou	struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr);
906050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou	int nr = sensor_attr->index;
9071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct adm1026_data *data = adm1026_update_device(dev);
908cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvare	return sprintf(buf, "%d\n", TEMP_FROM_REG(data->temp_tmin[nr] +
9091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		ADM1026_FAN_CONTROL_TEMP_RANGE));
9101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
911050480f12aeab62d39a1a07546606a47217ebefaYani Ioannoustatic ssize_t show_temp_auto_point1_temp(struct device *dev,
912050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou		struct device_attribute *attr, char *buf)
9131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
914050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou	struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr);
915050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou	int nr = sensor_attr->index;
9161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct adm1026_data *data = adm1026_update_device(dev);
917cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvare	return sprintf(buf, "%d\n", TEMP_FROM_REG(data->temp_tmin[nr]));
9181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
919050480f12aeab62d39a1a07546606a47217ebefaYani Ioannoustatic ssize_t set_temp_auto_point1_temp(struct device *dev,
920050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou		struct device_attribute *attr, const char *buf, size_t count)
9211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
922050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou	struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr);
923050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou	int nr = sensor_attr->index;
924b591d3c1964e7cba6582eb22c7033d37c31a4e99Axel Lin	struct adm1026_data *data = dev_get_drvdata(dev);
925b591d3c1964e7cba6582eb22c7033d37c31a4e99Axel Lin	struct i2c_client *client = data->client;
92686aa3e22106be3d6338113ff5acd7a87c40056c4Guenter Roeck	long val;
92786aa3e22106be3d6338113ff5acd7a87c40056c4Guenter Roeck	int err;
92886aa3e22106be3d6338113ff5acd7a87c40056c4Guenter Roeck
92986aa3e22106be3d6338113ff5acd7a87c40056c4Guenter Roeck	err = kstrtol(buf, 10, &val);
93086aa3e22106be3d6338113ff5acd7a87c40056c4Guenter Roeck	if (err)
93186aa3e22106be3d6338113ff5acd7a87c40056c4Guenter Roeck		return err;
9321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
9339a61bf6300533d3b64d7ff29adfec00e596de67dIngo Molnar	mutex_lock(&data->update_lock);
9341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	data->temp_tmin[nr] = TEMP_TO_REG(val);
9351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	adm1026_write_value(client, ADM1026_REG_TEMP_TMIN[nr],
9361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		data->temp_tmin[nr]);
9379a61bf6300533d3b64d7ff29adfec00e596de67dIngo Molnar	mutex_unlock(&data->update_lock);
9381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return count;
9391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
9401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
941cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvare#define temp_auto_point(offset)						\
942cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvarestatic SENSOR_DEVICE_ATTR(temp##offset##_auto_point1_temp,		\
943cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvare		S_IRUGO | S_IWUSR, show_temp_auto_point1_temp,		\
944cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvare		set_temp_auto_point1_temp, offset - 1);			\
945cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvarestatic SENSOR_DEVICE_ATTR(temp##offset##_auto_point1_temp_hyst, S_IRUGO,\
946cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvare		show_temp_auto_point1_temp_hyst, NULL, offset - 1);	\
947cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvarestatic SENSOR_DEVICE_ATTR(temp##offset##_auto_point2_temp, S_IRUGO,	\
948050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou		show_temp_auto_point2_temp, NULL, offset - 1);
9491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
9501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldstemp_auto_point(1);
9511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldstemp_auto_point(2);
9521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldstemp_auto_point(3);
9531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
954050480f12aeab62d39a1a07546606a47217ebefaYani Ioannoustatic ssize_t show_temp_crit_enable(struct device *dev,
955050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou		struct device_attribute *attr, char *buf)
9561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
9571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct adm1026_data *data = adm1026_update_device(dev);
958cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvare	return sprintf(buf, "%d\n", (data->config1 & CFG1_THERM_HOT) >> 4);
9591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
960050480f12aeab62d39a1a07546606a47217ebefaYani Ioannoustatic ssize_t set_temp_crit_enable(struct device *dev,
961050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou		struct device_attribute *attr, const char *buf, size_t count)
9621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
963b591d3c1964e7cba6582eb22c7033d37c31a4e99Axel Lin	struct adm1026_data *data = dev_get_drvdata(dev);
964b591d3c1964e7cba6582eb22c7033d37c31a4e99Axel Lin	struct i2c_client *client = data->client;
96586aa3e22106be3d6338113ff5acd7a87c40056c4Guenter Roeck	unsigned long val;
96686aa3e22106be3d6338113ff5acd7a87c40056c4Guenter Roeck	int err;
96786aa3e22106be3d6338113ff5acd7a87c40056c4Guenter Roeck
96886aa3e22106be3d6338113ff5acd7a87c40056c4Guenter Roeck	err = kstrtoul(buf, 10, &val);
96986aa3e22106be3d6338113ff5acd7a87c40056c4Guenter Roeck	if (err)
97086aa3e22106be3d6338113ff5acd7a87c40056c4Guenter Roeck		return err;
97186aa3e22106be3d6338113ff5acd7a87c40056c4Guenter Roeck
97286aa3e22106be3d6338113ff5acd7a87c40056c4Guenter Roeck	if (val > 1)
97386aa3e22106be3d6338113ff5acd7a87c40056c4Guenter Roeck		return -EINVAL;
97486aa3e22106be3d6338113ff5acd7a87c40056c4Guenter Roeck
97586aa3e22106be3d6338113ff5acd7a87c40056c4Guenter Roeck	mutex_lock(&data->update_lock);
97686aa3e22106be3d6338113ff5acd7a87c40056c4Guenter Roeck	data->config1 = (data->config1 & ~CFG1_THERM_HOT) | (val << 4);
97786aa3e22106be3d6338113ff5acd7a87c40056c4Guenter Roeck	adm1026_write_value(client, ADM1026_REG_CONFIG1, data->config1);
97886aa3e22106be3d6338113ff5acd7a87c40056c4Guenter Roeck	mutex_unlock(&data->update_lock);
9791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
9801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return count;
9811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
9821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
983050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou#define temp_crit_enable(offset)				\
984050480f12aeab62d39a1a07546606a47217ebefaYani Ioannoustatic DEVICE_ATTR(temp##offset##_crit_enable, S_IRUGO | S_IWUSR, \
9851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	show_temp_crit_enable, set_temp_crit_enable);
9861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
987050480f12aeab62d39a1a07546606a47217ebefaYani Ioannoutemp_crit_enable(1);
988050480f12aeab62d39a1a07546606a47217ebefaYani Ioannoutemp_crit_enable(2);
989050480f12aeab62d39a1a07546606a47217ebefaYani Ioannoutemp_crit_enable(3);
9901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
991050480f12aeab62d39a1a07546606a47217ebefaYani Ioannoustatic ssize_t show_temp_crit(struct device *dev,
992050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou		struct device_attribute *attr, char *buf)
9931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
994050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou	struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr);
995050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou	int nr = sensor_attr->index;
9961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct adm1026_data *data = adm1026_update_device(dev);
997cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvare	return sprintf(buf, "%d\n", TEMP_FROM_REG(data->temp_crit[nr]));
9981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
999050480f12aeab62d39a1a07546606a47217ebefaYani Ioannoustatic ssize_t set_temp_crit(struct device *dev, struct device_attribute *attr,
1000050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou		const char *buf, size_t count)
10011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
1002050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou	struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr);
1003050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou	int nr = sensor_attr->index;
1004b591d3c1964e7cba6582eb22c7033d37c31a4e99Axel Lin	struct adm1026_data *data = dev_get_drvdata(dev);
1005b591d3c1964e7cba6582eb22c7033d37c31a4e99Axel Lin	struct i2c_client *client = data->client;
100686aa3e22106be3d6338113ff5acd7a87c40056c4Guenter Roeck	long val;
100786aa3e22106be3d6338113ff5acd7a87c40056c4Guenter Roeck	int err;
100886aa3e22106be3d6338113ff5acd7a87c40056c4Guenter Roeck
100986aa3e22106be3d6338113ff5acd7a87c40056c4Guenter Roeck	err = kstrtol(buf, 10, &val);
101086aa3e22106be3d6338113ff5acd7a87c40056c4Guenter Roeck	if (err)
101186aa3e22106be3d6338113ff5acd7a87c40056c4Guenter Roeck		return err;
10121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
10139a61bf6300533d3b64d7ff29adfec00e596de67dIngo Molnar	mutex_lock(&data->update_lock);
10141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	data->temp_crit[nr] = TEMP_TO_REG(val);
10151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	adm1026_write_value(client, ADM1026_REG_TEMP_THERM[nr],
10161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		data->temp_crit[nr]);
10179a61bf6300533d3b64d7ff29adfec00e596de67dIngo Molnar	mutex_unlock(&data->update_lock);
10181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return count;
10191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
10201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1021050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou#define temp_crit_reg(offset)						\
1022050480f12aeab62d39a1a07546606a47217ebefaYani Ioannoustatic SENSOR_DEVICE_ATTR(temp##offset##_crit, S_IRUGO | S_IWUSR,	\
1023050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou		show_temp_crit, set_temp_crit, offset - 1);
10241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
10251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldstemp_crit_reg(1);
10261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldstemp_crit_reg(2);
10271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldstemp_crit_reg(3);
10281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
102986aa3e22106be3d6338113ff5acd7a87c40056c4Guenter Roeckstatic ssize_t show_analog_out_reg(struct device *dev,
103086aa3e22106be3d6338113ff5acd7a87c40056c4Guenter Roeck				   struct device_attribute *attr, char *buf)
10311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
10321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct adm1026_data *data = adm1026_update_device(dev);
1033cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvare	return sprintf(buf, "%d\n", DAC_FROM_REG(data->analog_out));
10341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
103586aa3e22106be3d6338113ff5acd7a87c40056c4Guenter Roeckstatic ssize_t set_analog_out_reg(struct device *dev,
103686aa3e22106be3d6338113ff5acd7a87c40056c4Guenter Roeck				  struct device_attribute *attr,
103786aa3e22106be3d6338113ff5acd7a87c40056c4Guenter Roeck				  const char *buf, size_t count)
10381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
1039b591d3c1964e7cba6582eb22c7033d37c31a4e99Axel Lin	struct adm1026_data *data = dev_get_drvdata(dev);
1040b591d3c1964e7cba6582eb22c7033d37c31a4e99Axel Lin	struct i2c_client *client = data->client;
104186aa3e22106be3d6338113ff5acd7a87c40056c4Guenter Roeck	long val;
104286aa3e22106be3d6338113ff5acd7a87c40056c4Guenter Roeck	int err;
104386aa3e22106be3d6338113ff5acd7a87c40056c4Guenter Roeck
104486aa3e22106be3d6338113ff5acd7a87c40056c4Guenter Roeck	err = kstrtol(buf, 10, &val);
104586aa3e22106be3d6338113ff5acd7a87c40056c4Guenter Roeck	if (err)
104686aa3e22106be3d6338113ff5acd7a87c40056c4Guenter Roeck		return err;
10471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
10489a61bf6300533d3b64d7ff29adfec00e596de67dIngo Molnar	mutex_lock(&data->update_lock);
10491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	data->analog_out = DAC_TO_REG(val);
10501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	adm1026_write_value(client, ADM1026_REG_DAC, data->analog_out);
10519a61bf6300533d3b64d7ff29adfec00e596de67dIngo Molnar	mutex_unlock(&data->update_lock);
10521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return count;
10531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
10541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1055cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvarestatic DEVICE_ATTR(analog_out, S_IRUGO | S_IWUSR, show_analog_out_reg,
10561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	set_analog_out_reg);
10571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
105886aa3e22106be3d6338113ff5acd7a87c40056c4Guenter Roeckstatic ssize_t show_vid_reg(struct device *dev, struct device_attribute *attr,
105986aa3e22106be3d6338113ff5acd7a87c40056c4Guenter Roeck			    char *buf)
10601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
10611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct adm1026_data *data = adm1026_update_device(dev);
1062a0cf354a71bd2969b2f1868530d3fecaebd6dc3dJean Delvare	int vid = (data->gpio >> 11) & 0x1f;
1063a0cf354a71bd2969b2f1868530d3fecaebd6dc3dJean Delvare
1064a0cf354a71bd2969b2f1868530d3fecaebd6dc3dJean Delvare	dev_dbg(dev, "Setting VID from GPIO11-15.\n");
1065a0cf354a71bd2969b2f1868530d3fecaebd6dc3dJean Delvare	return sprintf(buf, "%d\n", vid_from_reg(vid, data->vrm));
10661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
106786aa3e22106be3d6338113ff5acd7a87c40056c4Guenter Roeck
1068937df8df907ce63b0f7e19adf6e3cdef1687fac3Grant Coadystatic DEVICE_ATTR(cpu0_vid, S_IRUGO, show_vid_reg, NULL);
10691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
107086aa3e22106be3d6338113ff5acd7a87c40056c4Guenter Roeckstatic ssize_t show_vrm_reg(struct device *dev, struct device_attribute *attr,
107186aa3e22106be3d6338113ff5acd7a87c40056c4Guenter Roeck			    char *buf)
10721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
107390d6619a916062cb75a176aacb318d108758b4a5Jean Delvare	struct adm1026_data *data = dev_get_drvdata(dev);
1074cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvare	return sprintf(buf, "%d\n", data->vrm);
10751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
107686aa3e22106be3d6338113ff5acd7a87c40056c4Guenter Roeck
107786aa3e22106be3d6338113ff5acd7a87c40056c4Guenter Roeckstatic ssize_t store_vrm_reg(struct device *dev, struct device_attribute *attr,
107886aa3e22106be3d6338113ff5acd7a87c40056c4Guenter Roeck			     const char *buf, size_t count)
10791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
1080f67fdabfb94b0bb96623a4b48d22be5329a06277Jean Delvare	struct adm1026_data *data = dev_get_drvdata(dev);
108186aa3e22106be3d6338113ff5acd7a87c40056c4Guenter Roeck	unsigned long val;
108286aa3e22106be3d6338113ff5acd7a87c40056c4Guenter Roeck	int err;
108386aa3e22106be3d6338113ff5acd7a87c40056c4Guenter Roeck
108486aa3e22106be3d6338113ff5acd7a87c40056c4Guenter Roeck	err = kstrtoul(buf, 10, &val);
108586aa3e22106be3d6338113ff5acd7a87c40056c4Guenter Roeck	if (err)
108686aa3e22106be3d6338113ff5acd7a87c40056c4Guenter Roeck		return err;
10871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1088a4461647f66c6e12676f9e9ce43c1578a2ba02a1Axel Lin	if (val > 255)
1089a4461647f66c6e12676f9e9ce43c1578a2ba02a1Axel Lin		return -EINVAL;
1090a4461647f66c6e12676f9e9ce43c1578a2ba02a1Axel Lin
109186aa3e22106be3d6338113ff5acd7a87c40056c4Guenter Roeck	data->vrm = val;
10921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return count;
10931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
10941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
10951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic DEVICE_ATTR(vrm, S_IRUGO | S_IWUSR, show_vrm_reg, store_vrm_reg);
10961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
109786aa3e22106be3d6338113ff5acd7a87c40056c4Guenter Roeckstatic ssize_t show_alarms_reg(struct device *dev,
109886aa3e22106be3d6338113ff5acd7a87c40056c4Guenter Roeck			       struct device_attribute *attr, char *buf)
10991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
11001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct adm1026_data *data = adm1026_update_device(dev);
1101f67fdabfb94b0bb96623a4b48d22be5329a06277Jean Delvare	return sprintf(buf, "%ld\n", data->alarms);
11021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
11031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
11041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic DEVICE_ATTR(alarms, S_IRUGO, show_alarms_reg, NULL);
11051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1106a9273cb8eea503f6b8e28bd5f613962ecba278c5Jean Delvarestatic ssize_t show_alarm(struct device *dev, struct device_attribute *attr,
1107a9273cb8eea503f6b8e28bd5f613962ecba278c5Jean Delvare			  char *buf)
1108a9273cb8eea503f6b8e28bd5f613962ecba278c5Jean Delvare{
1109a9273cb8eea503f6b8e28bd5f613962ecba278c5Jean Delvare	struct adm1026_data *data = adm1026_update_device(dev);
1110a9273cb8eea503f6b8e28bd5f613962ecba278c5Jean Delvare	int bitnr = to_sensor_dev_attr(attr)->index;
1111a9273cb8eea503f6b8e28bd5f613962ecba278c5Jean Delvare	return sprintf(buf, "%ld\n", (data->alarms >> bitnr) & 1);
1112a9273cb8eea503f6b8e28bd5f613962ecba278c5Jean Delvare}
1113a9273cb8eea503f6b8e28bd5f613962ecba278c5Jean Delvare
1114a9273cb8eea503f6b8e28bd5f613962ecba278c5Jean Delvarestatic SENSOR_DEVICE_ATTR(temp2_alarm, S_IRUGO, show_alarm, NULL, 0);
1115a9273cb8eea503f6b8e28bd5f613962ecba278c5Jean Delvarestatic SENSOR_DEVICE_ATTR(temp3_alarm, S_IRUGO, show_alarm, NULL, 1);
1116a9273cb8eea503f6b8e28bd5f613962ecba278c5Jean Delvarestatic SENSOR_DEVICE_ATTR(in9_alarm, S_IRUGO, show_alarm, NULL, 1);
1117a9273cb8eea503f6b8e28bd5f613962ecba278c5Jean Delvarestatic SENSOR_DEVICE_ATTR(in11_alarm, S_IRUGO, show_alarm, NULL, 2);
1118a9273cb8eea503f6b8e28bd5f613962ecba278c5Jean Delvarestatic SENSOR_DEVICE_ATTR(in12_alarm, S_IRUGO, show_alarm, NULL, 3);
1119a9273cb8eea503f6b8e28bd5f613962ecba278c5Jean Delvarestatic SENSOR_DEVICE_ATTR(in13_alarm, S_IRUGO, show_alarm, NULL, 4);
1120a9273cb8eea503f6b8e28bd5f613962ecba278c5Jean Delvarestatic SENSOR_DEVICE_ATTR(in14_alarm, S_IRUGO, show_alarm, NULL, 5);
1121a9273cb8eea503f6b8e28bd5f613962ecba278c5Jean Delvarestatic SENSOR_DEVICE_ATTR(in15_alarm, S_IRUGO, show_alarm, NULL, 6);
1122a9273cb8eea503f6b8e28bd5f613962ecba278c5Jean Delvarestatic SENSOR_DEVICE_ATTR(in16_alarm, S_IRUGO, show_alarm, NULL, 7);
1123a9273cb8eea503f6b8e28bd5f613962ecba278c5Jean Delvarestatic SENSOR_DEVICE_ATTR(in0_alarm, S_IRUGO, show_alarm, NULL, 8);
1124a9273cb8eea503f6b8e28bd5f613962ecba278c5Jean Delvarestatic SENSOR_DEVICE_ATTR(in1_alarm, S_IRUGO, show_alarm, NULL, 9);
1125a9273cb8eea503f6b8e28bd5f613962ecba278c5Jean Delvarestatic SENSOR_DEVICE_ATTR(in2_alarm, S_IRUGO, show_alarm, NULL, 10);
1126a9273cb8eea503f6b8e28bd5f613962ecba278c5Jean Delvarestatic SENSOR_DEVICE_ATTR(in3_alarm, S_IRUGO, show_alarm, NULL, 11);
1127a9273cb8eea503f6b8e28bd5f613962ecba278c5Jean Delvarestatic SENSOR_DEVICE_ATTR(in4_alarm, S_IRUGO, show_alarm, NULL, 12);
1128a9273cb8eea503f6b8e28bd5f613962ecba278c5Jean Delvarestatic SENSOR_DEVICE_ATTR(in5_alarm, S_IRUGO, show_alarm, NULL, 13);
1129a9273cb8eea503f6b8e28bd5f613962ecba278c5Jean Delvarestatic SENSOR_DEVICE_ATTR(in6_alarm, S_IRUGO, show_alarm, NULL, 14);
1130a9273cb8eea503f6b8e28bd5f613962ecba278c5Jean Delvarestatic SENSOR_DEVICE_ATTR(in7_alarm, S_IRUGO, show_alarm, NULL, 15);
1131a9273cb8eea503f6b8e28bd5f613962ecba278c5Jean Delvarestatic SENSOR_DEVICE_ATTR(fan1_alarm, S_IRUGO, show_alarm, NULL, 16);
1132a9273cb8eea503f6b8e28bd5f613962ecba278c5Jean Delvarestatic SENSOR_DEVICE_ATTR(fan2_alarm, S_IRUGO, show_alarm, NULL, 17);
1133a9273cb8eea503f6b8e28bd5f613962ecba278c5Jean Delvarestatic SENSOR_DEVICE_ATTR(fan3_alarm, S_IRUGO, show_alarm, NULL, 18);
1134a9273cb8eea503f6b8e28bd5f613962ecba278c5Jean Delvarestatic SENSOR_DEVICE_ATTR(fan4_alarm, S_IRUGO, show_alarm, NULL, 19);
1135a9273cb8eea503f6b8e28bd5f613962ecba278c5Jean Delvarestatic SENSOR_DEVICE_ATTR(fan5_alarm, S_IRUGO, show_alarm, NULL, 20);
1136a9273cb8eea503f6b8e28bd5f613962ecba278c5Jean Delvarestatic SENSOR_DEVICE_ATTR(fan6_alarm, S_IRUGO, show_alarm, NULL, 21);
1137a9273cb8eea503f6b8e28bd5f613962ecba278c5Jean Delvarestatic SENSOR_DEVICE_ATTR(fan7_alarm, S_IRUGO, show_alarm, NULL, 22);
1138a9273cb8eea503f6b8e28bd5f613962ecba278c5Jean Delvarestatic SENSOR_DEVICE_ATTR(fan8_alarm, S_IRUGO, show_alarm, NULL, 23);
1139a9273cb8eea503f6b8e28bd5f613962ecba278c5Jean Delvarestatic SENSOR_DEVICE_ATTR(temp1_alarm, S_IRUGO, show_alarm, NULL, 24);
1140a9273cb8eea503f6b8e28bd5f613962ecba278c5Jean Delvarestatic SENSOR_DEVICE_ATTR(in10_alarm, S_IRUGO, show_alarm, NULL, 25);
1141a9273cb8eea503f6b8e28bd5f613962ecba278c5Jean Delvarestatic SENSOR_DEVICE_ATTR(in8_alarm, S_IRUGO, show_alarm, NULL, 26);
1142a9273cb8eea503f6b8e28bd5f613962ecba278c5Jean Delvare
114386aa3e22106be3d6338113ff5acd7a87c40056c4Guenter Roeckstatic ssize_t show_alarm_mask(struct device *dev,
114486aa3e22106be3d6338113ff5acd7a87c40056c4Guenter Roeck			       struct device_attribute *attr, char *buf)
11451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
11461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct adm1026_data *data = adm1026_update_device(dev);
1147cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvare	return sprintf(buf, "%ld\n", data->alarm_mask);
11481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
114986aa3e22106be3d6338113ff5acd7a87c40056c4Guenter Roeckstatic ssize_t set_alarm_mask(struct device *dev, struct device_attribute *attr,
115086aa3e22106be3d6338113ff5acd7a87c40056c4Guenter Roeck			      const char *buf, size_t count)
11511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
1152b591d3c1964e7cba6582eb22c7033d37c31a4e99Axel Lin	struct adm1026_data *data = dev_get_drvdata(dev);
1153b591d3c1964e7cba6582eb22c7033d37c31a4e99Axel Lin	struct i2c_client *client = data->client;
11541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	unsigned long mask;
115586aa3e22106be3d6338113ff5acd7a87c40056c4Guenter Roeck	long val;
115686aa3e22106be3d6338113ff5acd7a87c40056c4Guenter Roeck	int err;
115786aa3e22106be3d6338113ff5acd7a87c40056c4Guenter Roeck
115886aa3e22106be3d6338113ff5acd7a87c40056c4Guenter Roeck	err = kstrtol(buf, 10, &val);
115986aa3e22106be3d6338113ff5acd7a87c40056c4Guenter Roeck	if (err)
116086aa3e22106be3d6338113ff5acd7a87c40056c4Guenter Roeck		return err;
11611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
11629a61bf6300533d3b64d7ff29adfec00e596de67dIngo Molnar	mutex_lock(&data->update_lock);
11631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	data->alarm_mask = val & 0x7fffffff;
11641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	mask = data->alarm_mask
11651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		| (data->gpio_mask & 0x10000 ? 0x80000000 : 0);
11661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	adm1026_write_value(client, ADM1026_REG_MASK1,
11671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		mask & 0xff);
11681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	mask >>= 8;
11691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	adm1026_write_value(client, ADM1026_REG_MASK2,
11701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		mask & 0xff);
11711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	mask >>= 8;
11721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	adm1026_write_value(client, ADM1026_REG_MASK3,
11731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		mask & 0xff);
11741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	mask >>= 8;
11751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	adm1026_write_value(client, ADM1026_REG_MASK4,
11761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		mask & 0xff);
11779a61bf6300533d3b64d7ff29adfec00e596de67dIngo Molnar	mutex_unlock(&data->update_lock);
11781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return count;
11791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
11801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
11811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic DEVICE_ATTR(alarm_mask, S_IRUGO | S_IWUSR, show_alarm_mask,
11821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	set_alarm_mask);
11831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
11841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
118586aa3e22106be3d6338113ff5acd7a87c40056c4Guenter Roeckstatic ssize_t show_gpio(struct device *dev, struct device_attribute *attr,
118686aa3e22106be3d6338113ff5acd7a87c40056c4Guenter Roeck			 char *buf)
11871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
11881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct adm1026_data *data = adm1026_update_device(dev);
1189cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvare	return sprintf(buf, "%ld\n", data->gpio);
11901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
119186aa3e22106be3d6338113ff5acd7a87c40056c4Guenter Roeckstatic ssize_t set_gpio(struct device *dev, struct device_attribute *attr,
119286aa3e22106be3d6338113ff5acd7a87c40056c4Guenter Roeck			const char *buf, size_t count)
11931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
1194b591d3c1964e7cba6582eb22c7033d37c31a4e99Axel Lin	struct adm1026_data *data = dev_get_drvdata(dev);
1195b591d3c1964e7cba6582eb22c7033d37c31a4e99Axel Lin	struct i2c_client *client = data->client;
1196cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvare	long gpio;
119786aa3e22106be3d6338113ff5acd7a87c40056c4Guenter Roeck	long val;
119886aa3e22106be3d6338113ff5acd7a87c40056c4Guenter Roeck	int err;
119986aa3e22106be3d6338113ff5acd7a87c40056c4Guenter Roeck
120086aa3e22106be3d6338113ff5acd7a87c40056c4Guenter Roeck	err = kstrtol(buf, 10, &val);
120186aa3e22106be3d6338113ff5acd7a87c40056c4Guenter Roeck	if (err)
120286aa3e22106be3d6338113ff5acd7a87c40056c4Guenter Roeck		return err;
12031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
12049a61bf6300533d3b64d7ff29adfec00e596de67dIngo Molnar	mutex_lock(&data->update_lock);
12051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	data->gpio = val & 0x1ffff;
12061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	gpio = data->gpio;
1207cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvare	adm1026_write_value(client, ADM1026_REG_GPIO_STATUS_0_7, gpio & 0xff);
12081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	gpio >>= 8;
1209cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvare	adm1026_write_value(client, ADM1026_REG_GPIO_STATUS_8_15, gpio & 0xff);
12101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	gpio = ((gpio >> 1) & 0x80) | (data->alarms >> 24 & 0x7f);
1211cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvare	adm1026_write_value(client, ADM1026_REG_STATUS4, gpio & 0xff);
12129a61bf6300533d3b64d7ff29adfec00e596de67dIngo Molnar	mutex_unlock(&data->update_lock);
12131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return count;
12141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
12151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
12161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic DEVICE_ATTR(gpio, S_IRUGO | S_IWUSR, show_gpio, set_gpio);
12171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
121886aa3e22106be3d6338113ff5acd7a87c40056c4Guenter Roeckstatic ssize_t show_gpio_mask(struct device *dev, struct device_attribute *attr,
121986aa3e22106be3d6338113ff5acd7a87c40056c4Guenter Roeck			      char *buf)
12201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
12211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct adm1026_data *data = adm1026_update_device(dev);
1222cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvare	return sprintf(buf, "%ld\n", data->gpio_mask);
12231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
122486aa3e22106be3d6338113ff5acd7a87c40056c4Guenter Roeckstatic ssize_t set_gpio_mask(struct device *dev, struct device_attribute *attr,
122586aa3e22106be3d6338113ff5acd7a87c40056c4Guenter Roeck			     const char *buf, size_t count)
12261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
1227b591d3c1964e7cba6582eb22c7033d37c31a4e99Axel Lin	struct adm1026_data *data = dev_get_drvdata(dev);
1228b591d3c1964e7cba6582eb22c7033d37c31a4e99Axel Lin	struct i2c_client *client = data->client;
1229cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvare	long mask;
123086aa3e22106be3d6338113ff5acd7a87c40056c4Guenter Roeck	long val;
123186aa3e22106be3d6338113ff5acd7a87c40056c4Guenter Roeck	int err;
123286aa3e22106be3d6338113ff5acd7a87c40056c4Guenter Roeck
123386aa3e22106be3d6338113ff5acd7a87c40056c4Guenter Roeck	err = kstrtol(buf, 10, &val);
123486aa3e22106be3d6338113ff5acd7a87c40056c4Guenter Roeck	if (err)
123586aa3e22106be3d6338113ff5acd7a87c40056c4Guenter Roeck		return err;
12361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
12379a61bf6300533d3b64d7ff29adfec00e596de67dIngo Molnar	mutex_lock(&data->update_lock);
12381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	data->gpio_mask = val & 0x1ffff;
12391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	mask = data->gpio_mask;
1240cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvare	adm1026_write_value(client, ADM1026_REG_GPIO_MASK_0_7, mask & 0xff);
12411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	mask >>= 8;
1242cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvare	adm1026_write_value(client, ADM1026_REG_GPIO_MASK_8_15, mask & 0xff);
12431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	mask = ((mask >> 1) & 0x80) | (data->alarm_mask >> 24 & 0x7f);
1244cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvare	adm1026_write_value(client, ADM1026_REG_MASK1, mask & 0xff);
12459a61bf6300533d3b64d7ff29adfec00e596de67dIngo Molnar	mutex_unlock(&data->update_lock);
12461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return count;
12471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
12481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
12491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic DEVICE_ATTR(gpio_mask, S_IRUGO | S_IWUSR, show_gpio_mask, set_gpio_mask);
12501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
125186aa3e22106be3d6338113ff5acd7a87c40056c4Guenter Roeckstatic ssize_t show_pwm_reg(struct device *dev, struct device_attribute *attr,
125286aa3e22106be3d6338113ff5acd7a87c40056c4Guenter Roeck			    char *buf)
12531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
12541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct adm1026_data *data = adm1026_update_device(dev);
1255cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvare	return sprintf(buf, "%d\n", PWM_FROM_REG(data->pwm1.pwm));
12561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
125786aa3e22106be3d6338113ff5acd7a87c40056c4Guenter Roeck
125886aa3e22106be3d6338113ff5acd7a87c40056c4Guenter Roeckstatic ssize_t set_pwm_reg(struct device *dev, struct device_attribute *attr,
125986aa3e22106be3d6338113ff5acd7a87c40056c4Guenter Roeck			   const char *buf, size_t count)
12601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
1261b591d3c1964e7cba6582eb22c7033d37c31a4e99Axel Lin	struct adm1026_data *data = dev_get_drvdata(dev);
1262b591d3c1964e7cba6582eb22c7033d37c31a4e99Axel Lin	struct i2c_client *client = data->client;
12631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
12641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (data->pwm1.enable == 1) {
126586aa3e22106be3d6338113ff5acd7a87c40056c4Guenter Roeck		long val;
126686aa3e22106be3d6338113ff5acd7a87c40056c4Guenter Roeck		int err;
126786aa3e22106be3d6338113ff5acd7a87c40056c4Guenter Roeck
126886aa3e22106be3d6338113ff5acd7a87c40056c4Guenter Roeck		err = kstrtol(buf, 10, &val);
126986aa3e22106be3d6338113ff5acd7a87c40056c4Guenter Roeck		if (err)
127086aa3e22106be3d6338113ff5acd7a87c40056c4Guenter Roeck			return err;
12711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
12729a61bf6300533d3b64d7ff29adfec00e596de67dIngo Molnar		mutex_lock(&data->update_lock);
12731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		data->pwm1.pwm = PWM_TO_REG(val);
12741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		adm1026_write_value(client, ADM1026_REG_PWM, data->pwm1.pwm);
12759a61bf6300533d3b64d7ff29adfec00e596de67dIngo Molnar		mutex_unlock(&data->update_lock);
12761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
12771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return count;
12781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
127986aa3e22106be3d6338113ff5acd7a87c40056c4Guenter Roeck
128086aa3e22106be3d6338113ff5acd7a87c40056c4Guenter Roeckstatic ssize_t show_auto_pwm_min(struct device *dev,
128186aa3e22106be3d6338113ff5acd7a87c40056c4Guenter Roeck				 struct device_attribute *attr, char *buf)
12821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
12831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct adm1026_data *data = adm1026_update_device(dev);
1284cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvare	return sprintf(buf, "%d\n", data->pwm1.auto_pwm_min);
12851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
128686aa3e22106be3d6338113ff5acd7a87c40056c4Guenter Roeck
128786aa3e22106be3d6338113ff5acd7a87c40056c4Guenter Roeckstatic ssize_t set_auto_pwm_min(struct device *dev,
128886aa3e22106be3d6338113ff5acd7a87c40056c4Guenter Roeck				struct device_attribute *attr, const char *buf,
128986aa3e22106be3d6338113ff5acd7a87c40056c4Guenter Roeck				size_t count)
12901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
1291b591d3c1964e7cba6582eb22c7033d37c31a4e99Axel Lin	struct adm1026_data *data = dev_get_drvdata(dev);
1292b591d3c1964e7cba6582eb22c7033d37c31a4e99Axel Lin	struct i2c_client *client = data->client;
129386aa3e22106be3d6338113ff5acd7a87c40056c4Guenter Roeck	unsigned long val;
129486aa3e22106be3d6338113ff5acd7a87c40056c4Guenter Roeck	int err;
129586aa3e22106be3d6338113ff5acd7a87c40056c4Guenter Roeck
129686aa3e22106be3d6338113ff5acd7a87c40056c4Guenter Roeck	err = kstrtoul(buf, 10, &val);
129786aa3e22106be3d6338113ff5acd7a87c40056c4Guenter Roeck	if (err)
129886aa3e22106be3d6338113ff5acd7a87c40056c4Guenter Roeck		return err;
12991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
13009a61bf6300533d3b64d7ff29adfec00e596de67dIngo Molnar	mutex_lock(&data->update_lock);
13012a844c148e1f714ebf42cb96e1b172ce394c36c9Guenter Roeck	data->pwm1.auto_pwm_min = clamp_val(val, 0, 255);
13021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (data->pwm1.enable == 2) { /* apply immediately */
13031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		data->pwm1.pwm = PWM_TO_REG((data->pwm1.pwm & 0x0f) |
1304cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvare			PWM_MIN_TO_REG(data->pwm1.auto_pwm_min));
13051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		adm1026_write_value(client, ADM1026_REG_PWM, data->pwm1.pwm);
13061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
13079a61bf6300533d3b64d7ff29adfec00e596de67dIngo Molnar	mutex_unlock(&data->update_lock);
13081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return count;
13091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
131086aa3e22106be3d6338113ff5acd7a87c40056c4Guenter Roeck
131186aa3e22106be3d6338113ff5acd7a87c40056c4Guenter Roeckstatic ssize_t show_auto_pwm_max(struct device *dev,
131286aa3e22106be3d6338113ff5acd7a87c40056c4Guenter Roeck				 struct device_attribute *attr, char *buf)
13131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
1314cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvare	return sprintf(buf, "%d\n", ADM1026_PWM_MAX);
13151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
131686aa3e22106be3d6338113ff5acd7a87c40056c4Guenter Roeck
131786aa3e22106be3d6338113ff5acd7a87c40056c4Guenter Roeckstatic ssize_t show_pwm_enable(struct device *dev,
131886aa3e22106be3d6338113ff5acd7a87c40056c4Guenter Roeck			       struct device_attribute *attr, char *buf)
13191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
13201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct adm1026_data *data = adm1026_update_device(dev);
1321cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvare	return sprintf(buf, "%d\n", data->pwm1.enable);
13221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
132386aa3e22106be3d6338113ff5acd7a87c40056c4Guenter Roeck
132486aa3e22106be3d6338113ff5acd7a87c40056c4Guenter Roeckstatic ssize_t set_pwm_enable(struct device *dev, struct device_attribute *attr,
132586aa3e22106be3d6338113ff5acd7a87c40056c4Guenter Roeck			      const char *buf, size_t count)
13261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
1327b591d3c1964e7cba6582eb22c7033d37c31a4e99Axel Lin	struct adm1026_data *data = dev_get_drvdata(dev);
1328b591d3c1964e7cba6582eb22c7033d37c31a4e99Axel Lin	struct i2c_client *client = data->client;
1329cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvare	int old_enable;
133086aa3e22106be3d6338113ff5acd7a87c40056c4Guenter Roeck	unsigned long val;
133186aa3e22106be3d6338113ff5acd7a87c40056c4Guenter Roeck	int err;
13321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
133386aa3e22106be3d6338113ff5acd7a87c40056c4Guenter Roeck	err = kstrtoul(buf, 10, &val);
133486aa3e22106be3d6338113ff5acd7a87c40056c4Guenter Roeck	if (err)
133586aa3e22106be3d6338113ff5acd7a87c40056c4Guenter Roeck		return err;
133686aa3e22106be3d6338113ff5acd7a87c40056c4Guenter Roeck
133786aa3e22106be3d6338113ff5acd7a87c40056c4Guenter Roeck	if (val >= 3)
133886aa3e22106be3d6338113ff5acd7a87c40056c4Guenter Roeck		return -EINVAL;
133986aa3e22106be3d6338113ff5acd7a87c40056c4Guenter Roeck
134086aa3e22106be3d6338113ff5acd7a87c40056c4Guenter Roeck	mutex_lock(&data->update_lock);
134186aa3e22106be3d6338113ff5acd7a87c40056c4Guenter Roeck	old_enable = data->pwm1.enable;
134286aa3e22106be3d6338113ff5acd7a87c40056c4Guenter Roeck	data->pwm1.enable = val;
134386aa3e22106be3d6338113ff5acd7a87c40056c4Guenter Roeck	data->config1 = (data->config1 & ~CFG1_PWM_AFC)
134486aa3e22106be3d6338113ff5acd7a87c40056c4Guenter Roeck			| ((val == 2) ? CFG1_PWM_AFC : 0);
134586aa3e22106be3d6338113ff5acd7a87c40056c4Guenter Roeck	adm1026_write_value(client, ADM1026_REG_CONFIG1, data->config1);
134686aa3e22106be3d6338113ff5acd7a87c40056c4Guenter Roeck	if (val == 2) { /* apply pwm1_auto_pwm_min to pwm1 */
134786aa3e22106be3d6338113ff5acd7a87c40056c4Guenter Roeck		data->pwm1.pwm = PWM_TO_REG((data->pwm1.pwm & 0x0f) |
134886aa3e22106be3d6338113ff5acd7a87c40056c4Guenter Roeck			PWM_MIN_TO_REG(data->pwm1.auto_pwm_min));
134986aa3e22106be3d6338113ff5acd7a87c40056c4Guenter Roeck		adm1026_write_value(client, ADM1026_REG_PWM, data->pwm1.pwm);
135086aa3e22106be3d6338113ff5acd7a87c40056c4Guenter Roeck	} else if (!((old_enable == 1) && (val == 1))) {
135186aa3e22106be3d6338113ff5acd7a87c40056c4Guenter Roeck		/* set pwm to safe value */
135286aa3e22106be3d6338113ff5acd7a87c40056c4Guenter Roeck		data->pwm1.pwm = 255;
135386aa3e22106be3d6338113ff5acd7a87c40056c4Guenter Roeck		adm1026_write_value(client, ADM1026_REG_PWM, data->pwm1.pwm);
13541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
135586aa3e22106be3d6338113ff5acd7a87c40056c4Guenter Roeck	mutex_unlock(&data->update_lock);
135686aa3e22106be3d6338113ff5acd7a87c40056c4Guenter Roeck
13571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return count;
13581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
13591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
13601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* enable PWM fan control */
1361cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvarestatic DEVICE_ATTR(pwm1, S_IRUGO | S_IWUSR, show_pwm_reg, set_pwm_reg);
1362cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvarestatic DEVICE_ATTR(pwm2, S_IRUGO | S_IWUSR, show_pwm_reg, set_pwm_reg);
1363cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvarestatic DEVICE_ATTR(pwm3, S_IRUGO | S_IWUSR, show_pwm_reg, set_pwm_reg);
1364cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvarestatic DEVICE_ATTR(pwm1_enable, S_IRUGO | S_IWUSR, show_pwm_enable,
13651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	set_pwm_enable);
1366cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvarestatic DEVICE_ATTR(pwm2_enable, S_IRUGO | S_IWUSR, show_pwm_enable,
13671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	set_pwm_enable);
1368cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvarestatic DEVICE_ATTR(pwm3_enable, S_IRUGO | S_IWUSR, show_pwm_enable,
13691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	set_pwm_enable);
1370cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvarestatic DEVICE_ATTR(temp1_auto_point1_pwm, S_IRUGO | S_IWUSR,
13711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	show_auto_pwm_min, set_auto_pwm_min);
1372cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvarestatic DEVICE_ATTR(temp2_auto_point1_pwm, S_IRUGO | S_IWUSR,
13731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	show_auto_pwm_min, set_auto_pwm_min);
1374cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvarestatic DEVICE_ATTR(temp3_auto_point1_pwm, S_IRUGO | S_IWUSR,
13751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	show_auto_pwm_min, set_auto_pwm_min);
13761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
13771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic DEVICE_ATTR(temp1_auto_point2_pwm, S_IRUGO, show_auto_pwm_max, NULL);
13781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic DEVICE_ATTR(temp2_auto_point2_pwm, S_IRUGO, show_auto_pwm_max, NULL);
13791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic DEVICE_ATTR(temp3_auto_point2_pwm, S_IRUGO, show_auto_pwm_max, NULL);
13801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1381681c6f7a6702f208d48b501c8829dbc03a2ca238Mark M. Hoffmanstatic struct attribute *adm1026_attributes[] = {
1382681c6f7a6702f208d48b501c8829dbc03a2ca238Mark M. Hoffman	&sensor_dev_attr_in0_input.dev_attr.attr,
1383681c6f7a6702f208d48b501c8829dbc03a2ca238Mark M. Hoffman	&sensor_dev_attr_in0_max.dev_attr.attr,
1384681c6f7a6702f208d48b501c8829dbc03a2ca238Mark M. Hoffman	&sensor_dev_attr_in0_min.dev_attr.attr,
1385a9273cb8eea503f6b8e28bd5f613962ecba278c5Jean Delvare	&sensor_dev_attr_in0_alarm.dev_attr.attr,
1386681c6f7a6702f208d48b501c8829dbc03a2ca238Mark M. Hoffman	&sensor_dev_attr_in1_input.dev_attr.attr,
1387681c6f7a6702f208d48b501c8829dbc03a2ca238Mark M. Hoffman	&sensor_dev_attr_in1_max.dev_attr.attr,
1388681c6f7a6702f208d48b501c8829dbc03a2ca238Mark M. Hoffman	&sensor_dev_attr_in1_min.dev_attr.attr,
1389a9273cb8eea503f6b8e28bd5f613962ecba278c5Jean Delvare	&sensor_dev_attr_in1_alarm.dev_attr.attr,
1390681c6f7a6702f208d48b501c8829dbc03a2ca238Mark M. Hoffman	&sensor_dev_attr_in2_input.dev_attr.attr,
1391681c6f7a6702f208d48b501c8829dbc03a2ca238Mark M. Hoffman	&sensor_dev_attr_in2_max.dev_attr.attr,
1392681c6f7a6702f208d48b501c8829dbc03a2ca238Mark M. Hoffman	&sensor_dev_attr_in2_min.dev_attr.attr,
1393a9273cb8eea503f6b8e28bd5f613962ecba278c5Jean Delvare	&sensor_dev_attr_in2_alarm.dev_attr.attr,
1394681c6f7a6702f208d48b501c8829dbc03a2ca238Mark M. Hoffman	&sensor_dev_attr_in3_input.dev_attr.attr,
1395681c6f7a6702f208d48b501c8829dbc03a2ca238Mark M. Hoffman	&sensor_dev_attr_in3_max.dev_attr.attr,
1396681c6f7a6702f208d48b501c8829dbc03a2ca238Mark M. Hoffman	&sensor_dev_attr_in3_min.dev_attr.attr,
1397a9273cb8eea503f6b8e28bd5f613962ecba278c5Jean Delvare	&sensor_dev_attr_in3_alarm.dev_attr.attr,
1398681c6f7a6702f208d48b501c8829dbc03a2ca238Mark M. Hoffman	&sensor_dev_attr_in4_input.dev_attr.attr,
1399681c6f7a6702f208d48b501c8829dbc03a2ca238Mark M. Hoffman	&sensor_dev_attr_in4_max.dev_attr.attr,
1400681c6f7a6702f208d48b501c8829dbc03a2ca238Mark M. Hoffman	&sensor_dev_attr_in4_min.dev_attr.attr,
1401a9273cb8eea503f6b8e28bd5f613962ecba278c5Jean Delvare	&sensor_dev_attr_in4_alarm.dev_attr.attr,
1402681c6f7a6702f208d48b501c8829dbc03a2ca238Mark M. Hoffman	&sensor_dev_attr_in5_input.dev_attr.attr,
1403681c6f7a6702f208d48b501c8829dbc03a2ca238Mark M. Hoffman	&sensor_dev_attr_in5_max.dev_attr.attr,
1404681c6f7a6702f208d48b501c8829dbc03a2ca238Mark M. Hoffman	&sensor_dev_attr_in5_min.dev_attr.attr,
1405a9273cb8eea503f6b8e28bd5f613962ecba278c5Jean Delvare	&sensor_dev_attr_in5_alarm.dev_attr.attr,
1406681c6f7a6702f208d48b501c8829dbc03a2ca238Mark M. Hoffman	&sensor_dev_attr_in6_input.dev_attr.attr,
1407681c6f7a6702f208d48b501c8829dbc03a2ca238Mark M. Hoffman	&sensor_dev_attr_in6_max.dev_attr.attr,
1408681c6f7a6702f208d48b501c8829dbc03a2ca238Mark M. Hoffman	&sensor_dev_attr_in6_min.dev_attr.attr,
1409a9273cb8eea503f6b8e28bd5f613962ecba278c5Jean Delvare	&sensor_dev_attr_in6_alarm.dev_attr.attr,
1410681c6f7a6702f208d48b501c8829dbc03a2ca238Mark M. Hoffman	&sensor_dev_attr_in7_input.dev_attr.attr,
1411681c6f7a6702f208d48b501c8829dbc03a2ca238Mark M. Hoffman	&sensor_dev_attr_in7_max.dev_attr.attr,
1412681c6f7a6702f208d48b501c8829dbc03a2ca238Mark M. Hoffman	&sensor_dev_attr_in7_min.dev_attr.attr,
1413a9273cb8eea503f6b8e28bd5f613962ecba278c5Jean Delvare	&sensor_dev_attr_in7_alarm.dev_attr.attr,
1414681c6f7a6702f208d48b501c8829dbc03a2ca238Mark M. Hoffman	&sensor_dev_attr_in10_input.dev_attr.attr,
1415681c6f7a6702f208d48b501c8829dbc03a2ca238Mark M. Hoffman	&sensor_dev_attr_in10_max.dev_attr.attr,
1416681c6f7a6702f208d48b501c8829dbc03a2ca238Mark M. Hoffman	&sensor_dev_attr_in10_min.dev_attr.attr,
1417a9273cb8eea503f6b8e28bd5f613962ecba278c5Jean Delvare	&sensor_dev_attr_in10_alarm.dev_attr.attr,
1418681c6f7a6702f208d48b501c8829dbc03a2ca238Mark M. Hoffman	&sensor_dev_attr_in11_input.dev_attr.attr,
1419681c6f7a6702f208d48b501c8829dbc03a2ca238Mark M. Hoffman	&sensor_dev_attr_in11_max.dev_attr.attr,
1420681c6f7a6702f208d48b501c8829dbc03a2ca238Mark M. Hoffman	&sensor_dev_attr_in11_min.dev_attr.attr,
1421a9273cb8eea503f6b8e28bd5f613962ecba278c5Jean Delvare	&sensor_dev_attr_in11_alarm.dev_attr.attr,
1422681c6f7a6702f208d48b501c8829dbc03a2ca238Mark M. Hoffman	&sensor_dev_attr_in12_input.dev_attr.attr,
1423681c6f7a6702f208d48b501c8829dbc03a2ca238Mark M. Hoffman	&sensor_dev_attr_in12_max.dev_attr.attr,
1424681c6f7a6702f208d48b501c8829dbc03a2ca238Mark M. Hoffman	&sensor_dev_attr_in12_min.dev_attr.attr,
1425a9273cb8eea503f6b8e28bd5f613962ecba278c5Jean Delvare	&sensor_dev_attr_in12_alarm.dev_attr.attr,
1426681c6f7a6702f208d48b501c8829dbc03a2ca238Mark M. Hoffman	&sensor_dev_attr_in13_input.dev_attr.attr,
1427681c6f7a6702f208d48b501c8829dbc03a2ca238Mark M. Hoffman	&sensor_dev_attr_in13_max.dev_attr.attr,
1428681c6f7a6702f208d48b501c8829dbc03a2ca238Mark M. Hoffman	&sensor_dev_attr_in13_min.dev_attr.attr,
1429a9273cb8eea503f6b8e28bd5f613962ecba278c5Jean Delvare	&sensor_dev_attr_in13_alarm.dev_attr.attr,
1430681c6f7a6702f208d48b501c8829dbc03a2ca238Mark M. Hoffman	&sensor_dev_attr_in14_input.dev_attr.attr,
1431681c6f7a6702f208d48b501c8829dbc03a2ca238Mark M. Hoffman	&sensor_dev_attr_in14_max.dev_attr.attr,
1432681c6f7a6702f208d48b501c8829dbc03a2ca238Mark M. Hoffman	&sensor_dev_attr_in14_min.dev_attr.attr,
1433a9273cb8eea503f6b8e28bd5f613962ecba278c5Jean Delvare	&sensor_dev_attr_in14_alarm.dev_attr.attr,
1434681c6f7a6702f208d48b501c8829dbc03a2ca238Mark M. Hoffman	&sensor_dev_attr_in15_input.dev_attr.attr,
1435681c6f7a6702f208d48b501c8829dbc03a2ca238Mark M. Hoffman	&sensor_dev_attr_in15_max.dev_attr.attr,
1436681c6f7a6702f208d48b501c8829dbc03a2ca238Mark M. Hoffman	&sensor_dev_attr_in15_min.dev_attr.attr,
1437a9273cb8eea503f6b8e28bd5f613962ecba278c5Jean Delvare	&sensor_dev_attr_in15_alarm.dev_attr.attr,
1438681c6f7a6702f208d48b501c8829dbc03a2ca238Mark M. Hoffman	&sensor_dev_attr_in16_input.dev_attr.attr,
1439681c6f7a6702f208d48b501c8829dbc03a2ca238Mark M. Hoffman	&sensor_dev_attr_in16_max.dev_attr.attr,
1440681c6f7a6702f208d48b501c8829dbc03a2ca238Mark M. Hoffman	&sensor_dev_attr_in16_min.dev_attr.attr,
1441a9273cb8eea503f6b8e28bd5f613962ecba278c5Jean Delvare	&sensor_dev_attr_in16_alarm.dev_attr.attr,
1442681c6f7a6702f208d48b501c8829dbc03a2ca238Mark M. Hoffman	&sensor_dev_attr_fan1_input.dev_attr.attr,
1443681c6f7a6702f208d48b501c8829dbc03a2ca238Mark M. Hoffman	&sensor_dev_attr_fan1_div.dev_attr.attr,
1444681c6f7a6702f208d48b501c8829dbc03a2ca238Mark M. Hoffman	&sensor_dev_attr_fan1_min.dev_attr.attr,
1445a9273cb8eea503f6b8e28bd5f613962ecba278c5Jean Delvare	&sensor_dev_attr_fan1_alarm.dev_attr.attr,
1446681c6f7a6702f208d48b501c8829dbc03a2ca238Mark M. Hoffman	&sensor_dev_attr_fan2_input.dev_attr.attr,
1447681c6f7a6702f208d48b501c8829dbc03a2ca238Mark M. Hoffman	&sensor_dev_attr_fan2_div.dev_attr.attr,
1448681c6f7a6702f208d48b501c8829dbc03a2ca238Mark M. Hoffman	&sensor_dev_attr_fan2_min.dev_attr.attr,
1449a9273cb8eea503f6b8e28bd5f613962ecba278c5Jean Delvare	&sensor_dev_attr_fan2_alarm.dev_attr.attr,
1450681c6f7a6702f208d48b501c8829dbc03a2ca238Mark M. Hoffman	&sensor_dev_attr_fan3_input.dev_attr.attr,
1451681c6f7a6702f208d48b501c8829dbc03a2ca238Mark M. Hoffman	&sensor_dev_attr_fan3_div.dev_attr.attr,
1452681c6f7a6702f208d48b501c8829dbc03a2ca238Mark M. Hoffman	&sensor_dev_attr_fan3_min.dev_attr.attr,
1453a9273cb8eea503f6b8e28bd5f613962ecba278c5Jean Delvare	&sensor_dev_attr_fan3_alarm.dev_attr.attr,
1454681c6f7a6702f208d48b501c8829dbc03a2ca238Mark M. Hoffman	&sensor_dev_attr_fan4_input.dev_attr.attr,
1455681c6f7a6702f208d48b501c8829dbc03a2ca238Mark M. Hoffman	&sensor_dev_attr_fan4_div.dev_attr.attr,
1456681c6f7a6702f208d48b501c8829dbc03a2ca238Mark M. Hoffman	&sensor_dev_attr_fan4_min.dev_attr.attr,
1457a9273cb8eea503f6b8e28bd5f613962ecba278c5Jean Delvare	&sensor_dev_attr_fan4_alarm.dev_attr.attr,
1458681c6f7a6702f208d48b501c8829dbc03a2ca238Mark M. Hoffman	&sensor_dev_attr_fan5_input.dev_attr.attr,
1459681c6f7a6702f208d48b501c8829dbc03a2ca238Mark M. Hoffman	&sensor_dev_attr_fan5_div.dev_attr.attr,
1460681c6f7a6702f208d48b501c8829dbc03a2ca238Mark M. Hoffman	&sensor_dev_attr_fan5_min.dev_attr.attr,
1461a9273cb8eea503f6b8e28bd5f613962ecba278c5Jean Delvare	&sensor_dev_attr_fan5_alarm.dev_attr.attr,
1462681c6f7a6702f208d48b501c8829dbc03a2ca238Mark M. Hoffman	&sensor_dev_attr_fan6_input.dev_attr.attr,
1463681c6f7a6702f208d48b501c8829dbc03a2ca238Mark M. Hoffman	&sensor_dev_attr_fan6_div.dev_attr.attr,
1464681c6f7a6702f208d48b501c8829dbc03a2ca238Mark M. Hoffman	&sensor_dev_attr_fan6_min.dev_attr.attr,
1465a9273cb8eea503f6b8e28bd5f613962ecba278c5Jean Delvare	&sensor_dev_attr_fan6_alarm.dev_attr.attr,
1466681c6f7a6702f208d48b501c8829dbc03a2ca238Mark M. Hoffman	&sensor_dev_attr_fan7_input.dev_attr.attr,
1467681c6f7a6702f208d48b501c8829dbc03a2ca238Mark M. Hoffman	&sensor_dev_attr_fan7_div.dev_attr.attr,
1468681c6f7a6702f208d48b501c8829dbc03a2ca238Mark M. Hoffman	&sensor_dev_attr_fan7_min.dev_attr.attr,
1469a9273cb8eea503f6b8e28bd5f613962ecba278c5Jean Delvare	&sensor_dev_attr_fan7_alarm.dev_attr.attr,
1470681c6f7a6702f208d48b501c8829dbc03a2ca238Mark M. Hoffman	&sensor_dev_attr_fan8_input.dev_attr.attr,
1471681c6f7a6702f208d48b501c8829dbc03a2ca238Mark M. Hoffman	&sensor_dev_attr_fan8_div.dev_attr.attr,
1472681c6f7a6702f208d48b501c8829dbc03a2ca238Mark M. Hoffman	&sensor_dev_attr_fan8_min.dev_attr.attr,
1473a9273cb8eea503f6b8e28bd5f613962ecba278c5Jean Delvare	&sensor_dev_attr_fan8_alarm.dev_attr.attr,
1474681c6f7a6702f208d48b501c8829dbc03a2ca238Mark M. Hoffman	&sensor_dev_attr_temp1_input.dev_attr.attr,
1475681c6f7a6702f208d48b501c8829dbc03a2ca238Mark M. Hoffman	&sensor_dev_attr_temp1_max.dev_attr.attr,
1476681c6f7a6702f208d48b501c8829dbc03a2ca238Mark M. Hoffman	&sensor_dev_attr_temp1_min.dev_attr.attr,
1477a9273cb8eea503f6b8e28bd5f613962ecba278c5Jean Delvare	&sensor_dev_attr_temp1_alarm.dev_attr.attr,
1478681c6f7a6702f208d48b501c8829dbc03a2ca238Mark M. Hoffman	&sensor_dev_attr_temp2_input.dev_attr.attr,
1479681c6f7a6702f208d48b501c8829dbc03a2ca238Mark M. Hoffman	&sensor_dev_attr_temp2_max.dev_attr.attr,
1480681c6f7a6702f208d48b501c8829dbc03a2ca238Mark M. Hoffman	&sensor_dev_attr_temp2_min.dev_attr.attr,
1481a9273cb8eea503f6b8e28bd5f613962ecba278c5Jean Delvare	&sensor_dev_attr_temp2_alarm.dev_attr.attr,
1482681c6f7a6702f208d48b501c8829dbc03a2ca238Mark M. Hoffman	&sensor_dev_attr_temp1_offset.dev_attr.attr,
1483681c6f7a6702f208d48b501c8829dbc03a2ca238Mark M. Hoffman	&sensor_dev_attr_temp2_offset.dev_attr.attr,
1484681c6f7a6702f208d48b501c8829dbc03a2ca238Mark M. Hoffman	&sensor_dev_attr_temp1_auto_point1_temp.dev_attr.attr,
1485681c6f7a6702f208d48b501c8829dbc03a2ca238Mark M. Hoffman	&sensor_dev_attr_temp2_auto_point1_temp.dev_attr.attr,
1486681c6f7a6702f208d48b501c8829dbc03a2ca238Mark M. Hoffman	&sensor_dev_attr_temp1_auto_point1_temp_hyst.dev_attr.attr,
1487681c6f7a6702f208d48b501c8829dbc03a2ca238Mark M. Hoffman	&sensor_dev_attr_temp2_auto_point1_temp_hyst.dev_attr.attr,
1488681c6f7a6702f208d48b501c8829dbc03a2ca238Mark M. Hoffman	&sensor_dev_attr_temp1_auto_point2_temp.dev_attr.attr,
1489681c6f7a6702f208d48b501c8829dbc03a2ca238Mark M. Hoffman	&sensor_dev_attr_temp2_auto_point2_temp.dev_attr.attr,
1490681c6f7a6702f208d48b501c8829dbc03a2ca238Mark M. Hoffman	&sensor_dev_attr_temp1_crit.dev_attr.attr,
1491681c6f7a6702f208d48b501c8829dbc03a2ca238Mark M. Hoffman	&sensor_dev_attr_temp2_crit.dev_attr.attr,
1492681c6f7a6702f208d48b501c8829dbc03a2ca238Mark M. Hoffman	&dev_attr_temp1_crit_enable.attr,
1493681c6f7a6702f208d48b501c8829dbc03a2ca238Mark M. Hoffman	&dev_attr_temp2_crit_enable.attr,
1494681c6f7a6702f208d48b501c8829dbc03a2ca238Mark M. Hoffman	&dev_attr_cpu0_vid.attr,
1495681c6f7a6702f208d48b501c8829dbc03a2ca238Mark M. Hoffman	&dev_attr_vrm.attr,
1496681c6f7a6702f208d48b501c8829dbc03a2ca238Mark M. Hoffman	&dev_attr_alarms.attr,
1497681c6f7a6702f208d48b501c8829dbc03a2ca238Mark M. Hoffman	&dev_attr_alarm_mask.attr,
1498681c6f7a6702f208d48b501c8829dbc03a2ca238Mark M. Hoffman	&dev_attr_gpio.attr,
1499681c6f7a6702f208d48b501c8829dbc03a2ca238Mark M. Hoffman	&dev_attr_gpio_mask.attr,
1500681c6f7a6702f208d48b501c8829dbc03a2ca238Mark M. Hoffman	&dev_attr_pwm1.attr,
1501681c6f7a6702f208d48b501c8829dbc03a2ca238Mark M. Hoffman	&dev_attr_pwm2.attr,
1502681c6f7a6702f208d48b501c8829dbc03a2ca238Mark M. Hoffman	&dev_attr_pwm3.attr,
1503681c6f7a6702f208d48b501c8829dbc03a2ca238Mark M. Hoffman	&dev_attr_pwm1_enable.attr,
1504681c6f7a6702f208d48b501c8829dbc03a2ca238Mark M. Hoffman	&dev_attr_pwm2_enable.attr,
1505681c6f7a6702f208d48b501c8829dbc03a2ca238Mark M. Hoffman	&dev_attr_pwm3_enable.attr,
1506681c6f7a6702f208d48b501c8829dbc03a2ca238Mark M. Hoffman	&dev_attr_temp1_auto_point1_pwm.attr,
1507681c6f7a6702f208d48b501c8829dbc03a2ca238Mark M. Hoffman	&dev_attr_temp2_auto_point1_pwm.attr,
1508681c6f7a6702f208d48b501c8829dbc03a2ca238Mark M. Hoffman	&dev_attr_temp1_auto_point2_pwm.attr,
1509681c6f7a6702f208d48b501c8829dbc03a2ca238Mark M. Hoffman	&dev_attr_temp2_auto_point2_pwm.attr,
1510681c6f7a6702f208d48b501c8829dbc03a2ca238Mark M. Hoffman	&dev_attr_analog_out.attr,
1511681c6f7a6702f208d48b501c8829dbc03a2ca238Mark M. Hoffman	NULL
1512681c6f7a6702f208d48b501c8829dbc03a2ca238Mark M. Hoffman};
1513681c6f7a6702f208d48b501c8829dbc03a2ca238Mark M. Hoffman
1514681c6f7a6702f208d48b501c8829dbc03a2ca238Mark M. Hoffmanstatic const struct attribute_group adm1026_group = {
1515681c6f7a6702f208d48b501c8829dbc03a2ca238Mark M. Hoffman	.attrs = adm1026_attributes,
1516681c6f7a6702f208d48b501c8829dbc03a2ca238Mark M. Hoffman};
1517681c6f7a6702f208d48b501c8829dbc03a2ca238Mark M. Hoffman
15185b34dbcd88251508d02e48ad9b0f9b8232a13ee0Jean Delvarestatic struct attribute *adm1026_attributes_temp3[] = {
15195b34dbcd88251508d02e48ad9b0f9b8232a13ee0Jean Delvare	&sensor_dev_attr_temp3_input.dev_attr.attr,
15205b34dbcd88251508d02e48ad9b0f9b8232a13ee0Jean Delvare	&sensor_dev_attr_temp3_max.dev_attr.attr,
15215b34dbcd88251508d02e48ad9b0f9b8232a13ee0Jean Delvare	&sensor_dev_attr_temp3_min.dev_attr.attr,
15225b34dbcd88251508d02e48ad9b0f9b8232a13ee0Jean Delvare	&sensor_dev_attr_temp3_alarm.dev_attr.attr,
15235b34dbcd88251508d02e48ad9b0f9b8232a13ee0Jean Delvare	&sensor_dev_attr_temp3_offset.dev_attr.attr,
15245b34dbcd88251508d02e48ad9b0f9b8232a13ee0Jean Delvare	&sensor_dev_attr_temp3_auto_point1_temp.dev_attr.attr,
15255b34dbcd88251508d02e48ad9b0f9b8232a13ee0Jean Delvare	&sensor_dev_attr_temp3_auto_point1_temp_hyst.dev_attr.attr,
15265b34dbcd88251508d02e48ad9b0f9b8232a13ee0Jean Delvare	&sensor_dev_attr_temp3_auto_point2_temp.dev_attr.attr,
15275b34dbcd88251508d02e48ad9b0f9b8232a13ee0Jean Delvare	&sensor_dev_attr_temp3_crit.dev_attr.attr,
15285b34dbcd88251508d02e48ad9b0f9b8232a13ee0Jean Delvare	&dev_attr_temp3_crit_enable.attr,
15295b34dbcd88251508d02e48ad9b0f9b8232a13ee0Jean Delvare	&dev_attr_temp3_auto_point1_pwm.attr,
15305b34dbcd88251508d02e48ad9b0f9b8232a13ee0Jean Delvare	&dev_attr_temp3_auto_point2_pwm.attr,
15311d5f2c16c6125ae6da1435ac5a190ae08429902aJean Delvare	NULL
15325b34dbcd88251508d02e48ad9b0f9b8232a13ee0Jean Delvare};
15335b34dbcd88251508d02e48ad9b0f9b8232a13ee0Jean Delvare
15345b34dbcd88251508d02e48ad9b0f9b8232a13ee0Jean Delvarestatic const struct attribute_group adm1026_group_temp3 = {
15355b34dbcd88251508d02e48ad9b0f9b8232a13ee0Jean Delvare	.attrs = adm1026_attributes_temp3,
15365b34dbcd88251508d02e48ad9b0f9b8232a13ee0Jean Delvare};
15375b34dbcd88251508d02e48ad9b0f9b8232a13ee0Jean Delvare
15385b34dbcd88251508d02e48ad9b0f9b8232a13ee0Jean Delvarestatic struct attribute *adm1026_attributes_in8_9[] = {
15395b34dbcd88251508d02e48ad9b0f9b8232a13ee0Jean Delvare	&sensor_dev_attr_in8_input.dev_attr.attr,
15405b34dbcd88251508d02e48ad9b0f9b8232a13ee0Jean Delvare	&sensor_dev_attr_in8_max.dev_attr.attr,
15415b34dbcd88251508d02e48ad9b0f9b8232a13ee0Jean Delvare	&sensor_dev_attr_in8_min.dev_attr.attr,
15425b34dbcd88251508d02e48ad9b0f9b8232a13ee0Jean Delvare	&sensor_dev_attr_in8_alarm.dev_attr.attr,
15435b34dbcd88251508d02e48ad9b0f9b8232a13ee0Jean Delvare	&sensor_dev_attr_in9_input.dev_attr.attr,
15445b34dbcd88251508d02e48ad9b0f9b8232a13ee0Jean Delvare	&sensor_dev_attr_in9_max.dev_attr.attr,
15455b34dbcd88251508d02e48ad9b0f9b8232a13ee0Jean Delvare	&sensor_dev_attr_in9_min.dev_attr.attr,
15465b34dbcd88251508d02e48ad9b0f9b8232a13ee0Jean Delvare	&sensor_dev_attr_in9_alarm.dev_attr.attr,
15471d5f2c16c6125ae6da1435ac5a190ae08429902aJean Delvare	NULL
15485b34dbcd88251508d02e48ad9b0f9b8232a13ee0Jean Delvare};
15495b34dbcd88251508d02e48ad9b0f9b8232a13ee0Jean Delvare
15505b34dbcd88251508d02e48ad9b0f9b8232a13ee0Jean Delvarestatic const struct attribute_group adm1026_group_in8_9 = {
15515b34dbcd88251508d02e48ad9b0f9b8232a13ee0Jean Delvare	.attrs = adm1026_attributes_in8_9,
15525b34dbcd88251508d02e48ad9b0f9b8232a13ee0Jean Delvare};
15535b34dbcd88251508d02e48ad9b0f9b8232a13ee0Jean Delvare
155457f7eb0bcb2316dc264cd26f38b33dd2cf3151c1Jean Delvare/* Return 0 if detection is successful, -ENODEV otherwise */
1555310ec79210d754afe51e2e4a983e846b60179abdJean Delvarestatic int adm1026_detect(struct i2c_client *client,
155657f7eb0bcb2316dc264cd26f38b33dd2cf3151c1Jean Delvare			  struct i2c_board_info *info)
15571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
155857f7eb0bcb2316dc264cd26f38b33dd2cf3151c1Jean Delvare	struct i2c_adapter *adapter = client->adapter;
155957f7eb0bcb2316dc264cd26f38b33dd2cf3151c1Jean Delvare	int address = client->addr;
15601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int company, verstep;
15611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
15621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA)) {
15631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		/* We need to be able to do byte I/O */
156457f7eb0bcb2316dc264cd26f38b33dd2cf3151c1Jean Delvare		return -ENODEV;
1565a0393713530c49697e49ce0456c039228ab7facbGuenter Roeck	}
15661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
15671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* Now, we do the remaining detection. */
15681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1569f67fdabfb94b0bb96623a4b48d22be5329a06277Jean Delvare	company = adm1026_read_value(client, ADM1026_REG_COMPANY);
1570f67fdabfb94b0bb96623a4b48d22be5329a06277Jean Delvare	verstep = adm1026_read_value(client, ADM1026_REG_VERSTEP);
15711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1572b55f375725ff85aada394da488802b0a3cc99e88Guenter Roeck	dev_dbg(&adapter->dev,
1573b55f375725ff85aada394da488802b0a3cc99e88Guenter Roeck		"Detecting device at %d,0x%02x with COMPANY: 0x%02x and VERSTEP: 0x%02x\n",
1574f67fdabfb94b0bb96623a4b48d22be5329a06277Jean Delvare		i2c_adapter_id(client->adapter), client->addr,
15751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		company, verstep);
15761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
157752df6440a29123eed912183fe785bbe174ef14b9Jean Delvare	/* Determine the chip type. */
157852df6440a29123eed912183fe785bbe174ef14b9Jean Delvare	dev_dbg(&adapter->dev, "Autodetecting device at %d,0x%02x...\n",
157952df6440a29123eed912183fe785bbe174ef14b9Jean Delvare		i2c_adapter_id(adapter), address);
158052df6440a29123eed912183fe785bbe174ef14b9Jean Delvare	if (company == ADM1026_COMPANY_ANALOG_DEV
158152df6440a29123eed912183fe785bbe174ef14b9Jean Delvare	    && verstep == ADM1026_VERSTEP_ADM1026) {
158252df6440a29123eed912183fe785bbe174ef14b9Jean Delvare		/* Analog Devices ADM1026 */
158352df6440a29123eed912183fe785bbe174ef14b9Jean Delvare	} else if (company == ADM1026_COMPANY_ANALOG_DEV
158452df6440a29123eed912183fe785bbe174ef14b9Jean Delvare		&& (verstep & 0xf0) == ADM1026_VERSTEP_GENERIC) {
1585b55f375725ff85aada394da488802b0a3cc99e88Guenter Roeck		dev_err(&adapter->dev,
1586b55f375725ff85aada394da488802b0a3cc99e88Guenter Roeck			"Unrecognized stepping 0x%02x. Defaulting to ADM1026.\n",
1587b55f375725ff85aada394da488802b0a3cc99e88Guenter Roeck			verstep);
158852df6440a29123eed912183fe785bbe174ef14b9Jean Delvare	} else if ((verstep & 0xf0) == ADM1026_VERSTEP_GENERIC) {
1589b55f375725ff85aada394da488802b0a3cc99e88Guenter Roeck		dev_err(&adapter->dev,
1590b55f375725ff85aada394da488802b0a3cc99e88Guenter Roeck			"Found version/stepping 0x%02x. Assuming generic ADM1026.\n",
159152df6440a29123eed912183fe785bbe174ef14b9Jean Delvare			verstep);
159252df6440a29123eed912183fe785bbe174ef14b9Jean Delvare	} else {
159352df6440a29123eed912183fe785bbe174ef14b9Jean Delvare		dev_dbg(&adapter->dev, "Autodetection failed\n");
159452df6440a29123eed912183fe785bbe174ef14b9Jean Delvare		/* Not an ADM1026... */
159552df6440a29123eed912183fe785bbe174ef14b9Jean Delvare		return -ENODEV;
15961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
159752df6440a29123eed912183fe785bbe174ef14b9Jean Delvare
159857f7eb0bcb2316dc264cd26f38b33dd2cf3151c1Jean Delvare	strlcpy(info->type, "adm1026", I2C_NAME_SIZE);
15991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
160057f7eb0bcb2316dc264cd26f38b33dd2cf3151c1Jean Delvare	return 0;
160157f7eb0bcb2316dc264cd26f38b33dd2cf3151c1Jean Delvare}
160257f7eb0bcb2316dc264cd26f38b33dd2cf3151c1Jean Delvare
160397df55661a2d60e6554ce9a9ee6fb47606ddc772Axel Linstatic void adm1026_print_gpio(struct i2c_client *client)
160497df55661a2d60e6554ce9a9ee6fb47606ddc772Axel Lin{
160597df55661a2d60e6554ce9a9ee6fb47606ddc772Axel Lin	struct adm1026_data *data = i2c_get_clientdata(client);
160697df55661a2d60e6554ce9a9ee6fb47606ddc772Axel Lin	int i;
160797df55661a2d60e6554ce9a9ee6fb47606ddc772Axel Lin
160897df55661a2d60e6554ce9a9ee6fb47606ddc772Axel Lin	dev_dbg(&client->dev, "GPIO config is:\n");
160997df55661a2d60e6554ce9a9ee6fb47606ddc772Axel Lin	for (i = 0; i <= 7; ++i) {
161097df55661a2d60e6554ce9a9ee6fb47606ddc772Axel Lin		if (data->config2 & (1 << i)) {
161197df55661a2d60e6554ce9a9ee6fb47606ddc772Axel Lin			dev_dbg(&client->dev, "\t%sGP%s%d\n",
161297df55661a2d60e6554ce9a9ee6fb47606ddc772Axel Lin				data->gpio_config[i] & 0x02 ? "" : "!",
161397df55661a2d60e6554ce9a9ee6fb47606ddc772Axel Lin				data->gpio_config[i] & 0x01 ? "OUT" : "IN",
161497df55661a2d60e6554ce9a9ee6fb47606ddc772Axel Lin				i);
161597df55661a2d60e6554ce9a9ee6fb47606ddc772Axel Lin		} else {
161697df55661a2d60e6554ce9a9ee6fb47606ddc772Axel Lin			dev_dbg(&client->dev, "\tFAN%d\n", i);
161797df55661a2d60e6554ce9a9ee6fb47606ddc772Axel Lin		}
161897df55661a2d60e6554ce9a9ee6fb47606ddc772Axel Lin	}
161997df55661a2d60e6554ce9a9ee6fb47606ddc772Axel Lin	for (i = 8; i <= 15; ++i) {
162097df55661a2d60e6554ce9a9ee6fb47606ddc772Axel Lin		dev_dbg(&client->dev, "\t%sGP%s%d\n",
162197df55661a2d60e6554ce9a9ee6fb47606ddc772Axel Lin			data->gpio_config[i] & 0x02 ? "" : "!",
162297df55661a2d60e6554ce9a9ee6fb47606ddc772Axel Lin			data->gpio_config[i] & 0x01 ? "OUT" : "IN",
162397df55661a2d60e6554ce9a9ee6fb47606ddc772Axel Lin			i);
162497df55661a2d60e6554ce9a9ee6fb47606ddc772Axel Lin	}
162597df55661a2d60e6554ce9a9ee6fb47606ddc772Axel Lin	if (data->config3 & CFG3_GPIO16_ENABLE) {
162697df55661a2d60e6554ce9a9ee6fb47606ddc772Axel Lin		dev_dbg(&client->dev, "\t%sGP%s16\n",
162797df55661a2d60e6554ce9a9ee6fb47606ddc772Axel Lin			data->gpio_config[16] & 0x02 ? "" : "!",
162897df55661a2d60e6554ce9a9ee6fb47606ddc772Axel Lin			data->gpio_config[16] & 0x01 ? "OUT" : "IN");
162997df55661a2d60e6554ce9a9ee6fb47606ddc772Axel Lin	} else {
163097df55661a2d60e6554ce9a9ee6fb47606ddc772Axel Lin		/* GPIO16 is THERM */
163197df55661a2d60e6554ce9a9ee6fb47606ddc772Axel Lin		dev_dbg(&client->dev, "\tTHERM\n");
163297df55661a2d60e6554ce9a9ee6fb47606ddc772Axel Lin	}
163397df55661a2d60e6554ce9a9ee6fb47606ddc772Axel Lin}
163497df55661a2d60e6554ce9a9ee6fb47606ddc772Axel Lin
163597df55661a2d60e6554ce9a9ee6fb47606ddc772Axel Linstatic void adm1026_fixup_gpio(struct i2c_client *client)
163697df55661a2d60e6554ce9a9ee6fb47606ddc772Axel Lin{
163797df55661a2d60e6554ce9a9ee6fb47606ddc772Axel Lin	struct adm1026_data *data = i2c_get_clientdata(client);
163897df55661a2d60e6554ce9a9ee6fb47606ddc772Axel Lin	int i;
163997df55661a2d60e6554ce9a9ee6fb47606ddc772Axel Lin	int value;
164097df55661a2d60e6554ce9a9ee6fb47606ddc772Axel Lin
164197df55661a2d60e6554ce9a9ee6fb47606ddc772Axel Lin	/* Make the changes requested. */
164297df55661a2d60e6554ce9a9ee6fb47606ddc772Axel Lin	/*
164397df55661a2d60e6554ce9a9ee6fb47606ddc772Axel Lin	 * We may need to unlock/stop monitoring or soft-reset the
164497df55661a2d60e6554ce9a9ee6fb47606ddc772Axel Lin	 *    chip before we can make changes.  This hasn't been
164597df55661a2d60e6554ce9a9ee6fb47606ddc772Axel Lin	 *    tested much.  FIXME
164697df55661a2d60e6554ce9a9ee6fb47606ddc772Axel Lin	 */
164797df55661a2d60e6554ce9a9ee6fb47606ddc772Axel Lin
164897df55661a2d60e6554ce9a9ee6fb47606ddc772Axel Lin	/* Make outputs */
164997df55661a2d60e6554ce9a9ee6fb47606ddc772Axel Lin	for (i = 0; i <= 16; ++i) {
165097df55661a2d60e6554ce9a9ee6fb47606ddc772Axel Lin		if (gpio_output[i] >= 0 && gpio_output[i] <= 16)
165197df55661a2d60e6554ce9a9ee6fb47606ddc772Axel Lin			data->gpio_config[gpio_output[i]] |= 0x01;
165297df55661a2d60e6554ce9a9ee6fb47606ddc772Axel Lin		/* if GPIO0-7 is output, it isn't a FAN tach */
165397df55661a2d60e6554ce9a9ee6fb47606ddc772Axel Lin		if (gpio_output[i] >= 0 && gpio_output[i] <= 7)
165497df55661a2d60e6554ce9a9ee6fb47606ddc772Axel Lin			data->config2 |= 1 << gpio_output[i];
165597df55661a2d60e6554ce9a9ee6fb47606ddc772Axel Lin	}
165697df55661a2d60e6554ce9a9ee6fb47606ddc772Axel Lin
165797df55661a2d60e6554ce9a9ee6fb47606ddc772Axel Lin	/* Input overrides output */
165897df55661a2d60e6554ce9a9ee6fb47606ddc772Axel Lin	for (i = 0; i <= 16; ++i) {
165997df55661a2d60e6554ce9a9ee6fb47606ddc772Axel Lin		if (gpio_input[i] >= 0 && gpio_input[i] <= 16)
166097df55661a2d60e6554ce9a9ee6fb47606ddc772Axel Lin			data->gpio_config[gpio_input[i]] &= ~0x01;
166197df55661a2d60e6554ce9a9ee6fb47606ddc772Axel Lin		/* if GPIO0-7 is input, it isn't a FAN tach */
166297df55661a2d60e6554ce9a9ee6fb47606ddc772Axel Lin		if (gpio_input[i] >= 0 && gpio_input[i] <= 7)
166397df55661a2d60e6554ce9a9ee6fb47606ddc772Axel Lin			data->config2 |= 1 << gpio_input[i];
166497df55661a2d60e6554ce9a9ee6fb47606ddc772Axel Lin	}
166597df55661a2d60e6554ce9a9ee6fb47606ddc772Axel Lin
166697df55661a2d60e6554ce9a9ee6fb47606ddc772Axel Lin	/* Inverted */
166797df55661a2d60e6554ce9a9ee6fb47606ddc772Axel Lin	for (i = 0; i <= 16; ++i) {
166897df55661a2d60e6554ce9a9ee6fb47606ddc772Axel Lin		if (gpio_inverted[i] >= 0 && gpio_inverted[i] <= 16)
166997df55661a2d60e6554ce9a9ee6fb47606ddc772Axel Lin			data->gpio_config[gpio_inverted[i]] &= ~0x02;
167097df55661a2d60e6554ce9a9ee6fb47606ddc772Axel Lin	}
167197df55661a2d60e6554ce9a9ee6fb47606ddc772Axel Lin
167297df55661a2d60e6554ce9a9ee6fb47606ddc772Axel Lin	/* Normal overrides inverted */
167397df55661a2d60e6554ce9a9ee6fb47606ddc772Axel Lin	for (i = 0; i <= 16; ++i) {
167497df55661a2d60e6554ce9a9ee6fb47606ddc772Axel Lin		if (gpio_normal[i] >= 0 && gpio_normal[i] <= 16)
167597df55661a2d60e6554ce9a9ee6fb47606ddc772Axel Lin			data->gpio_config[gpio_normal[i]] |= 0x02;
167697df55661a2d60e6554ce9a9ee6fb47606ddc772Axel Lin	}
167797df55661a2d60e6554ce9a9ee6fb47606ddc772Axel Lin
167897df55661a2d60e6554ce9a9ee6fb47606ddc772Axel Lin	/* Fan overrides input and output */
167997df55661a2d60e6554ce9a9ee6fb47606ddc772Axel Lin	for (i = 0; i <= 7; ++i) {
168097df55661a2d60e6554ce9a9ee6fb47606ddc772Axel Lin		if (gpio_fan[i] >= 0 && gpio_fan[i] <= 7)
168197df55661a2d60e6554ce9a9ee6fb47606ddc772Axel Lin			data->config2 &= ~(1 << gpio_fan[i]);
168297df55661a2d60e6554ce9a9ee6fb47606ddc772Axel Lin	}
168397df55661a2d60e6554ce9a9ee6fb47606ddc772Axel Lin
168497df55661a2d60e6554ce9a9ee6fb47606ddc772Axel Lin	/* Write new configs to registers */
168597df55661a2d60e6554ce9a9ee6fb47606ddc772Axel Lin	adm1026_write_value(client, ADM1026_REG_CONFIG2, data->config2);
168697df55661a2d60e6554ce9a9ee6fb47606ddc772Axel Lin	data->config3 = (data->config3 & 0x3f)
168797df55661a2d60e6554ce9a9ee6fb47606ddc772Axel Lin			| ((data->gpio_config[16] & 0x03) << 6);
168897df55661a2d60e6554ce9a9ee6fb47606ddc772Axel Lin	adm1026_write_value(client, ADM1026_REG_CONFIG3, data->config3);
168997df55661a2d60e6554ce9a9ee6fb47606ddc772Axel Lin	for (i = 15, value = 0; i >= 0; --i) {
169097df55661a2d60e6554ce9a9ee6fb47606ddc772Axel Lin		value <<= 2;
169197df55661a2d60e6554ce9a9ee6fb47606ddc772Axel Lin		value |= data->gpio_config[i] & 0x03;
169297df55661a2d60e6554ce9a9ee6fb47606ddc772Axel Lin		if ((i & 0x03) == 0) {
169397df55661a2d60e6554ce9a9ee6fb47606ddc772Axel Lin			adm1026_write_value(client,
169497df55661a2d60e6554ce9a9ee6fb47606ddc772Axel Lin					ADM1026_REG_GPIO_CFG_0_3 + i/4,
169597df55661a2d60e6554ce9a9ee6fb47606ddc772Axel Lin					value);
169697df55661a2d60e6554ce9a9ee6fb47606ddc772Axel Lin			value = 0;
169797df55661a2d60e6554ce9a9ee6fb47606ddc772Axel Lin		}
169897df55661a2d60e6554ce9a9ee6fb47606ddc772Axel Lin	}
169997df55661a2d60e6554ce9a9ee6fb47606ddc772Axel Lin
170097df55661a2d60e6554ce9a9ee6fb47606ddc772Axel Lin	/* Print the new config */
170197df55661a2d60e6554ce9a9ee6fb47606ddc772Axel Lin	adm1026_print_gpio(client);
170297df55661a2d60e6554ce9a9ee6fb47606ddc772Axel Lin}
170397df55661a2d60e6554ce9a9ee6fb47606ddc772Axel Lin
170497df55661a2d60e6554ce9a9ee6fb47606ddc772Axel Linstatic void adm1026_init_client(struct i2c_client *client)
170597df55661a2d60e6554ce9a9ee6fb47606ddc772Axel Lin{
170697df55661a2d60e6554ce9a9ee6fb47606ddc772Axel Lin	int value, i;
170797df55661a2d60e6554ce9a9ee6fb47606ddc772Axel Lin	struct adm1026_data *data = i2c_get_clientdata(client);
170897df55661a2d60e6554ce9a9ee6fb47606ddc772Axel Lin
170997df55661a2d60e6554ce9a9ee6fb47606ddc772Axel Lin	dev_dbg(&client->dev, "Initializing device\n");
171097df55661a2d60e6554ce9a9ee6fb47606ddc772Axel Lin	/* Read chip config */
171197df55661a2d60e6554ce9a9ee6fb47606ddc772Axel Lin	data->config1 = adm1026_read_value(client, ADM1026_REG_CONFIG1);
171297df55661a2d60e6554ce9a9ee6fb47606ddc772Axel Lin	data->config2 = adm1026_read_value(client, ADM1026_REG_CONFIG2);
171397df55661a2d60e6554ce9a9ee6fb47606ddc772Axel Lin	data->config3 = adm1026_read_value(client, ADM1026_REG_CONFIG3);
171497df55661a2d60e6554ce9a9ee6fb47606ddc772Axel Lin
171597df55661a2d60e6554ce9a9ee6fb47606ddc772Axel Lin	/* Inform user of chip config */
171697df55661a2d60e6554ce9a9ee6fb47606ddc772Axel Lin	dev_dbg(&client->dev, "ADM1026_REG_CONFIG1 is: 0x%02x\n",
171797df55661a2d60e6554ce9a9ee6fb47606ddc772Axel Lin		data->config1);
171897df55661a2d60e6554ce9a9ee6fb47606ddc772Axel Lin	if ((data->config1 & CFG1_MONITOR) == 0) {
171997df55661a2d60e6554ce9a9ee6fb47606ddc772Axel Lin		dev_dbg(&client->dev,
172097df55661a2d60e6554ce9a9ee6fb47606ddc772Axel Lin			"Monitoring not currently enabled.\n");
172197df55661a2d60e6554ce9a9ee6fb47606ddc772Axel Lin	}
172297df55661a2d60e6554ce9a9ee6fb47606ddc772Axel Lin	if (data->config1 & CFG1_INT_ENABLE) {
172397df55661a2d60e6554ce9a9ee6fb47606ddc772Axel Lin		dev_dbg(&client->dev,
172497df55661a2d60e6554ce9a9ee6fb47606ddc772Axel Lin			"SMBALERT interrupts are enabled.\n");
172597df55661a2d60e6554ce9a9ee6fb47606ddc772Axel Lin	}
172697df55661a2d60e6554ce9a9ee6fb47606ddc772Axel Lin	if (data->config1 & CFG1_AIN8_9) {
172797df55661a2d60e6554ce9a9ee6fb47606ddc772Axel Lin		dev_dbg(&client->dev,
172897df55661a2d60e6554ce9a9ee6fb47606ddc772Axel Lin			"in8 and in9 enabled. temp3 disabled.\n");
172997df55661a2d60e6554ce9a9ee6fb47606ddc772Axel Lin	} else {
173097df55661a2d60e6554ce9a9ee6fb47606ddc772Axel Lin		dev_dbg(&client->dev,
173197df55661a2d60e6554ce9a9ee6fb47606ddc772Axel Lin			"temp3 enabled.  in8 and in9 disabled.\n");
173297df55661a2d60e6554ce9a9ee6fb47606ddc772Axel Lin	}
173397df55661a2d60e6554ce9a9ee6fb47606ddc772Axel Lin	if (data->config1 & CFG1_THERM_HOT) {
173497df55661a2d60e6554ce9a9ee6fb47606ddc772Axel Lin		dev_dbg(&client->dev,
173597df55661a2d60e6554ce9a9ee6fb47606ddc772Axel Lin			"Automatic THERM, PWM, and temp limits enabled.\n");
173697df55661a2d60e6554ce9a9ee6fb47606ddc772Axel Lin	}
173797df55661a2d60e6554ce9a9ee6fb47606ddc772Axel Lin
173897df55661a2d60e6554ce9a9ee6fb47606ddc772Axel Lin	if (data->config3 & CFG3_GPIO16_ENABLE) {
173997df55661a2d60e6554ce9a9ee6fb47606ddc772Axel Lin		dev_dbg(&client->dev,
174097df55661a2d60e6554ce9a9ee6fb47606ddc772Axel Lin			"GPIO16 enabled.  THERM pin disabled.\n");
174197df55661a2d60e6554ce9a9ee6fb47606ddc772Axel Lin	} else {
174297df55661a2d60e6554ce9a9ee6fb47606ddc772Axel Lin		dev_dbg(&client->dev,
174397df55661a2d60e6554ce9a9ee6fb47606ddc772Axel Lin			"THERM pin enabled.  GPIO16 disabled.\n");
174497df55661a2d60e6554ce9a9ee6fb47606ddc772Axel Lin	}
174597df55661a2d60e6554ce9a9ee6fb47606ddc772Axel Lin	if (data->config3 & CFG3_VREF_250)
174697df55661a2d60e6554ce9a9ee6fb47606ddc772Axel Lin		dev_dbg(&client->dev, "Vref is 2.50 Volts.\n");
174797df55661a2d60e6554ce9a9ee6fb47606ddc772Axel Lin	else
174897df55661a2d60e6554ce9a9ee6fb47606ddc772Axel Lin		dev_dbg(&client->dev, "Vref is 1.82 Volts.\n");
174997df55661a2d60e6554ce9a9ee6fb47606ddc772Axel Lin	/* Read and pick apart the existing GPIO configuration */
175097df55661a2d60e6554ce9a9ee6fb47606ddc772Axel Lin	value = 0;
175197df55661a2d60e6554ce9a9ee6fb47606ddc772Axel Lin	for (i = 0; i <= 15; ++i) {
175297df55661a2d60e6554ce9a9ee6fb47606ddc772Axel Lin		if ((i & 0x03) == 0) {
175397df55661a2d60e6554ce9a9ee6fb47606ddc772Axel Lin			value = adm1026_read_value(client,
175497df55661a2d60e6554ce9a9ee6fb47606ddc772Axel Lin					ADM1026_REG_GPIO_CFG_0_3 + i / 4);
175597df55661a2d60e6554ce9a9ee6fb47606ddc772Axel Lin		}
175697df55661a2d60e6554ce9a9ee6fb47606ddc772Axel Lin		data->gpio_config[i] = value & 0x03;
175797df55661a2d60e6554ce9a9ee6fb47606ddc772Axel Lin		value >>= 2;
175897df55661a2d60e6554ce9a9ee6fb47606ddc772Axel Lin	}
175997df55661a2d60e6554ce9a9ee6fb47606ddc772Axel Lin	data->gpio_config[16] = (data->config3 >> 6) & 0x03;
176097df55661a2d60e6554ce9a9ee6fb47606ddc772Axel Lin
176197df55661a2d60e6554ce9a9ee6fb47606ddc772Axel Lin	/* ... and then print it */
176297df55661a2d60e6554ce9a9ee6fb47606ddc772Axel Lin	adm1026_print_gpio(client);
176397df55661a2d60e6554ce9a9ee6fb47606ddc772Axel Lin
176497df55661a2d60e6554ce9a9ee6fb47606ddc772Axel Lin	/*
176597df55661a2d60e6554ce9a9ee6fb47606ddc772Axel Lin	 * If the user asks us to reprogram the GPIO config, then
176697df55661a2d60e6554ce9a9ee6fb47606ddc772Axel Lin	 * do it now.
176797df55661a2d60e6554ce9a9ee6fb47606ddc772Axel Lin	 */
176897df55661a2d60e6554ce9a9ee6fb47606ddc772Axel Lin	if (gpio_input[0] != -1 || gpio_output[0] != -1
176997df55661a2d60e6554ce9a9ee6fb47606ddc772Axel Lin		|| gpio_inverted[0] != -1 || gpio_normal[0] != -1
177097df55661a2d60e6554ce9a9ee6fb47606ddc772Axel Lin		|| gpio_fan[0] != -1) {
177197df55661a2d60e6554ce9a9ee6fb47606ddc772Axel Lin		adm1026_fixup_gpio(client);
177297df55661a2d60e6554ce9a9ee6fb47606ddc772Axel Lin	}
177397df55661a2d60e6554ce9a9ee6fb47606ddc772Axel Lin
177497df55661a2d60e6554ce9a9ee6fb47606ddc772Axel Lin	/*
177597df55661a2d60e6554ce9a9ee6fb47606ddc772Axel Lin	 * WE INTENTIONALLY make no changes to the limits,
177697df55661a2d60e6554ce9a9ee6fb47606ddc772Axel Lin	 *   offsets, pwms, fans and zones.  If they were
177797df55661a2d60e6554ce9a9ee6fb47606ddc772Axel Lin	 *   configured, we don't want to mess with them.
177897df55661a2d60e6554ce9a9ee6fb47606ddc772Axel Lin	 *   If they weren't, the default is 100% PWM, no
177997df55661a2d60e6554ce9a9ee6fb47606ddc772Axel Lin	 *   control and will suffice until 'sensors -s'
178097df55661a2d60e6554ce9a9ee6fb47606ddc772Axel Lin	 *   can be run by the user.  We DO set the default
178197df55661a2d60e6554ce9a9ee6fb47606ddc772Axel Lin	 *   value for pwm1.auto_pwm_min to its maximum
178297df55661a2d60e6554ce9a9ee6fb47606ddc772Axel Lin	 *   so that enabling automatic pwm fan control
178397df55661a2d60e6554ce9a9ee6fb47606ddc772Axel Lin	 *   without first setting a value for pwm1.auto_pwm_min
178497df55661a2d60e6554ce9a9ee6fb47606ddc772Axel Lin	 *   will not result in potentially dangerous fan speed decrease.
178597df55661a2d60e6554ce9a9ee6fb47606ddc772Axel Lin	 */
178697df55661a2d60e6554ce9a9ee6fb47606ddc772Axel Lin	data->pwm1.auto_pwm_min = 255;
178797df55661a2d60e6554ce9a9ee6fb47606ddc772Axel Lin	/* Start monitoring */
178897df55661a2d60e6554ce9a9ee6fb47606ddc772Axel Lin	value = adm1026_read_value(client, ADM1026_REG_CONFIG1);
178997df55661a2d60e6554ce9a9ee6fb47606ddc772Axel Lin	/* Set MONITOR, clear interrupt acknowledge and s/w reset */
179097df55661a2d60e6554ce9a9ee6fb47606ddc772Axel Lin	value = (value | CFG1_MONITOR) & (~CFG1_INT_CLEAR & ~CFG1_RESET);
179197df55661a2d60e6554ce9a9ee6fb47606ddc772Axel Lin	dev_dbg(&client->dev, "Setting CONFIG to: 0x%02x\n", value);
179297df55661a2d60e6554ce9a9ee6fb47606ddc772Axel Lin	data->config1 = value;
179397df55661a2d60e6554ce9a9ee6fb47606ddc772Axel Lin	adm1026_write_value(client, ADM1026_REG_CONFIG1, value);
179497df55661a2d60e6554ce9a9ee6fb47606ddc772Axel Lin
179597df55661a2d60e6554ce9a9ee6fb47606ddc772Axel Lin	/* initialize fan_div[] to hardware defaults */
179697df55661a2d60e6554ce9a9ee6fb47606ddc772Axel Lin	value = adm1026_read_value(client, ADM1026_REG_FAN_DIV_0_3) |
179797df55661a2d60e6554ce9a9ee6fb47606ddc772Axel Lin		(adm1026_read_value(client, ADM1026_REG_FAN_DIV_4_7) << 8);
179897df55661a2d60e6554ce9a9ee6fb47606ddc772Axel Lin	for (i = 0; i <= 7; ++i) {
179997df55661a2d60e6554ce9a9ee6fb47606ddc772Axel Lin		data->fan_div[i] = DIV_FROM_REG(value & 0x03);
180097df55661a2d60e6554ce9a9ee6fb47606ddc772Axel Lin		value >>= 2;
180197df55661a2d60e6554ce9a9ee6fb47606ddc772Axel Lin	}
180297df55661a2d60e6554ce9a9ee6fb47606ddc772Axel Lin}
180397df55661a2d60e6554ce9a9ee6fb47606ddc772Axel Lin
180457f7eb0bcb2316dc264cd26f38b33dd2cf3151c1Jean Delvarestatic int adm1026_probe(struct i2c_client *client,
180557f7eb0bcb2316dc264cd26f38b33dd2cf3151c1Jean Delvare			 const struct i2c_device_id *id)
180657f7eb0bcb2316dc264cd26f38b33dd2cf3151c1Jean Delvare{
1807b591d3c1964e7cba6582eb22c7033d37c31a4e99Axel Lin	struct device *dev = &client->dev;
1808b591d3c1964e7cba6582eb22c7033d37c31a4e99Axel Lin	struct device *hwmon_dev;
180957f7eb0bcb2316dc264cd26f38b33dd2cf3151c1Jean Delvare	struct adm1026_data *data;
181057f7eb0bcb2316dc264cd26f38b33dd2cf3151c1Jean Delvare
1811b591d3c1964e7cba6582eb22c7033d37c31a4e99Axel Lin	data = devm_kzalloc(dev, sizeof(struct adm1026_data), GFP_KERNEL);
18123421e212e6dfa6792877ef0b9e7a147ee15a59c0Guenter Roeck	if (!data)
18133421e212e6dfa6792877ef0b9e7a147ee15a59c0Guenter Roeck		return -ENOMEM;
18141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
181557f7eb0bcb2316dc264cd26f38b33dd2cf3151c1Jean Delvare	i2c_set_clientdata(client, data);
1816b591d3c1964e7cba6582eb22c7033d37c31a4e99Axel Lin	data->client = client;
18179a61bf6300533d3b64d7ff29adfec00e596de67dIngo Molnar	mutex_init(&data->update_lock);
18181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
18191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* Set the VRM version */
1820303760b44a7a142cb9f4c9df4609fb63bbda98dbJean Delvare	data->vrm = vid_which_vrm();
18211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
18221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* Initialize the ADM1026 chip */
1823f67fdabfb94b0bb96623a4b48d22be5329a06277Jean Delvare	adm1026_init_client(client);
18241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1825b591d3c1964e7cba6582eb22c7033d37c31a4e99Axel Lin	/* sysfs hooks */
1826b591d3c1964e7cba6582eb22c7033d37c31a4e99Axel Lin	data->groups[0] = &adm1026_group;
18275b34dbcd88251508d02e48ad9b0f9b8232a13ee0Jean Delvare	if (data->config1 & CFG1_AIN8_9)
1828b591d3c1964e7cba6582eb22c7033d37c31a4e99Axel Lin		data->groups[1] = &adm1026_group_in8_9;
18295b34dbcd88251508d02e48ad9b0f9b8232a13ee0Jean Delvare	else
1830b591d3c1964e7cba6582eb22c7033d37c31a4e99Axel Lin		data->groups[1] = &adm1026_group_temp3;
1831681c6f7a6702f208d48b501c8829dbc03a2ca238Mark M. Hoffman
1832b591d3c1964e7cba6582eb22c7033d37c31a4e99Axel Lin	hwmon_dev = devm_hwmon_device_register_with_groups(dev, client->name,
1833b591d3c1964e7cba6582eb22c7033d37c31a4e99Axel Lin							   data, data->groups);
1834b591d3c1964e7cba6582eb22c7033d37c31a4e99Axel Lin	return PTR_ERR_OR_ZERO(hwmon_dev);
1835681c6f7a6702f208d48b501c8829dbc03a2ca238Mark M. Hoffman}
1836681c6f7a6702f208d48b501c8829dbc03a2ca238Mark M. Hoffman
183797df55661a2d60e6554ce9a9ee6fb47606ddc772Axel Linstatic const struct i2c_device_id adm1026_id[] = {
183897df55661a2d60e6554ce9a9ee6fb47606ddc772Axel Lin	{ "adm1026", 0 },
183997df55661a2d60e6554ce9a9ee6fb47606ddc772Axel Lin	{ }
184097df55661a2d60e6554ce9a9ee6fb47606ddc772Axel Lin};
184197df55661a2d60e6554ce9a9ee6fb47606ddc772Axel LinMODULE_DEVICE_TABLE(i2c, adm1026_id);
184297df55661a2d60e6554ce9a9ee6fb47606ddc772Axel Lin
184397df55661a2d60e6554ce9a9ee6fb47606ddc772Axel Linstatic struct i2c_driver adm1026_driver = {
184497df55661a2d60e6554ce9a9ee6fb47606ddc772Axel Lin	.class		= I2C_CLASS_HWMON,
184597df55661a2d60e6554ce9a9ee6fb47606ddc772Axel Lin	.driver = {
184697df55661a2d60e6554ce9a9ee6fb47606ddc772Axel Lin		.name	= "adm1026",
184797df55661a2d60e6554ce9a9ee6fb47606ddc772Axel Lin	},
184897df55661a2d60e6554ce9a9ee6fb47606ddc772Axel Lin	.probe		= adm1026_probe,
184997df55661a2d60e6554ce9a9ee6fb47606ddc772Axel Lin	.id_table	= adm1026_id,
185097df55661a2d60e6554ce9a9ee6fb47606ddc772Axel Lin	.detect		= adm1026_detect,
185197df55661a2d60e6554ce9a9ee6fb47606ddc772Axel Lin	.address_list	= normal_i2c,
185297df55661a2d60e6554ce9a9ee6fb47606ddc772Axel Lin};
185397df55661a2d60e6554ce9a9ee6fb47606ddc772Axel Lin
1854f0967eea80ec2a19a4fe1ad27e3ff1b22c79a3c7Axel Linmodule_i2c_driver(adm1026_driver);
18551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
18561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsMODULE_LICENSE("GPL");
18571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsMODULE_AUTHOR("Philip Pokorny <ppokorny@penguincomputing.com>, "
1858cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvare	      "Justin Thiessen <jthiessen@penguincomputing.com>");
18591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsMODULE_DESCRIPTION("ADM1026 driver");
1860