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);
52cb01a2312f56c93d2740e827718966b92b7cbb91Jean DelvareMODULE_PARM_DESC(gpio_output, "List of GPIO pins (0-16) to program as "
531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	"outputs");
54cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvaremodule_param_array(gpio_inverted, int, NULL, 0);
55cb01a2312f56c93d2740e827718966b92b7cbb91Jean DelvareMODULE_PARM_DESC(gpio_inverted, "List of GPIO pins (0-16) to program as "
561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	"inverted");
57cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvaremodule_param_array(gpio_normal, int, NULL, 0);
58cb01a2312f56c93d2740e827718966b92b7cbb91Jean DelvareMODULE_PARM_DESC(gpio_normal, "List of GPIO pins (0-16) to program as "
591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	"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))
200cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvare#define INS_TO_REG(n, val)  (SENSORS_LIMIT(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 : \
21086aa3e22106be3d6338113ff5acd7a87c40056c4Guenter Roeck				SENSORS_LIMIT(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 */
21886aa3e22106be3d6338113ff5acd7a87c40056c4Guenter Roeck#define TEMP_TO_REG(val) (SENSORS_LIMIT(((val) + ((val) < 0 ? -500 : 500)) \
21986aa3e22106be3d6338113ff5acd7a87c40056c4Guenter Roeck					/ 1000, -127, 127))
2201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define TEMP_FROM_REG(val) ((val) * 1000)
22186aa3e22106be3d6338113ff5acd7a87c40056c4Guenter Roeck#define OFFSET_TO_REG(val) (SENSORS_LIMIT(((val) + ((val) < 0 ? -500 : 500)) \
22286aa3e22106be3d6338113ff5acd7a87c40056c4Guenter Roeck					  / 1000, -127, 127))
2231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define OFFSET_FROM_REG(val) ((val) * 1000)
2241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
225cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvare#define PWM_TO_REG(val) (SENSORS_LIMIT(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 */
23686aa3e22106be3d6338113ff5acd7a87c40056c4Guenter Roeck#define DAC_TO_REG(val) (SENSORS_LIMIT(((((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 {
2691beeffe43311f64df8dd0ab08ff6b1858c58363fTony Jones	struct device *hwmon_dev;
2701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2719a61bf6300533d3b64d7ff29adfec00e596de67dIngo Molnar	struct mutex update_lock;
2721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int valid;		/* !=0 if following fields are valid */
2731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	unsigned long last_reading;	/* In jiffies */
2741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	unsigned long last_config;	/* In jiffies */
2751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
276cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvare	u8 in[17];		/* Register value */
277cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvare	u8 in_max[17];		/* Register value */
278cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvare	u8 in_min[17];		/* Register value */
279cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvare	s8 temp[3];		/* Register value */
280cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvare	s8 temp_min[3];		/* Register value */
281cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvare	s8 temp_max[3];		/* Register value */
282cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvare	s8 temp_tmin[3];	/* Register value */
283cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvare	s8 temp_crit[3];	/* Register value */
284cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvare	s8 temp_offset[3];	/* Register value */
285cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvare	u8 fan[8];		/* Register value */
286cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvare	u8 fan_min[8];		/* Register value */
287cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvare	u8 fan_div[8];		/* Decoded value */
288cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvare	struct pwm_data pwm1;	/* Pwm control values */
289cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvare	u8 vrm;			/* VRM version */
2901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	u8 analog_out;		/* Register value (DAC) */
291cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvare	long alarms;		/* Register encoding, combined */
292cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvare	long alarm_mask;	/* Register encoding, combined */
293cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvare	long gpio;		/* Register encoding, combined */
294cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvare	long gpio_mask;		/* Register encoding, combined */
295cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvare	u8 gpio_config[17];	/* Decoded value */
296cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvare	u8 config1;		/* Register value */
297cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvare	u8 config2;		/* Register value */
298cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvare	u8 config3;		/* Register value */
2991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds};
3001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
30157f7eb0bcb2316dc264cd26f38b33dd2cf3151c1Jean Delvarestatic int adm1026_probe(struct i2c_client *client,
30257f7eb0bcb2316dc264cd26f38b33dd2cf3151c1Jean Delvare			 const struct i2c_device_id *id);
303310ec79210d754afe51e2e4a983e846b60179abdJean Delvarestatic int adm1026_detect(struct i2c_client *client,
30457f7eb0bcb2316dc264cd26f38b33dd2cf3151c1Jean Delvare			  struct i2c_board_info *info);
30557f7eb0bcb2316dc264cd26f38b33dd2cf3151c1Jean Delvarestatic int adm1026_remove(struct i2c_client *client);
306f6c27fc17c5e575c5471fb344bdbd5f5f6072136Darren Jenkinsstatic int adm1026_read_value(struct i2c_client *client, u8 reg);
307f6c27fc17c5e575c5471fb344bdbd5f5f6072136Darren Jenkinsstatic int adm1026_write_value(struct i2c_client *client, u8 reg, int value);
3081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void adm1026_print_gpio(struct i2c_client *client);
309cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvarestatic void adm1026_fixup_gpio(struct i2c_client *client);
3101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic struct adm1026_data *adm1026_update_device(struct device *dev);
3111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void adm1026_init_client(struct i2c_client *client);
3121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
31457f7eb0bcb2316dc264cd26f38b33dd2cf3151c1Jean Delvarestatic const struct i2c_device_id adm1026_id[] = {
3151f86df49ddfd0067cce941187d57b2fd2f749a9eJean Delvare	{ "adm1026", 0 },
31657f7eb0bcb2316dc264cd26f38b33dd2cf3151c1Jean Delvare	{ }
31757f7eb0bcb2316dc264cd26f38b33dd2cf3151c1Jean Delvare};
31857f7eb0bcb2316dc264cd26f38b33dd2cf3151c1Jean DelvareMODULE_DEVICE_TABLE(i2c, adm1026_id);
31957f7eb0bcb2316dc264cd26f38b33dd2cf3151c1Jean Delvare
3201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic struct i2c_driver adm1026_driver = {
32157f7eb0bcb2316dc264cd26f38b33dd2cf3151c1Jean Delvare	.class		= I2C_CLASS_HWMON,
322cdaf79349c7d24e1d33acb6497849c9e956a33eaLaurent Riffard	.driver = {
323cdaf79349c7d24e1d33acb6497849c9e956a33eaLaurent Riffard		.name	= "adm1026",
324cdaf79349c7d24e1d33acb6497849c9e956a33eaLaurent Riffard	},
32557f7eb0bcb2316dc264cd26f38b33dd2cf3151c1Jean Delvare	.probe		= adm1026_probe,
32657f7eb0bcb2316dc264cd26f38b33dd2cf3151c1Jean Delvare	.remove		= adm1026_remove,
32757f7eb0bcb2316dc264cd26f38b33dd2cf3151c1Jean Delvare	.id_table	= adm1026_id,
32857f7eb0bcb2316dc264cd26f38b33dd2cf3151c1Jean Delvare	.detect		= adm1026_detect,
329c3813d6af177fab19e322f3114b1f64fbcf08d71Jean Delvare	.address_list	= normal_i2c,
3301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds};
3311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
332c49efceffa599299ab3f38b1cdf8c2f1bf9811c4Ben Dooksstatic int adm1026_read_value(struct i2c_client *client, u8 reg)
3331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
3341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int res;
3351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (reg < 0x80) {
3371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		/* "RAM" locations */
3381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		res = i2c_smbus_read_byte_data(client, reg) & 0xff;
3391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	} else {
3401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		/* EEPROM, do nothing */
3411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		res = 0;
3421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
3431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return res;
3441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
3451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
346c49efceffa599299ab3f38b1cdf8c2f1bf9811c4Ben Dooksstatic int adm1026_write_value(struct i2c_client *client, u8 reg, int value)
3471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
3481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int res;
3491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (reg < 0x80) {
3511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		/* "RAM" locations */
3521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		res = i2c_smbus_write_byte_data(client, reg, value);
3531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	} else {
3541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		/* EEPROM, do nothing */
3551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		res = 0;
3561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
3571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return res;
3581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
3591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
360c49efceffa599299ab3f38b1cdf8c2f1bf9811c4Ben Dooksstatic void adm1026_init_client(struct i2c_client *client)
3611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
3621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int value, i;
3631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct adm1026_data *data = i2c_get_clientdata(client);
3641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
365cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvare	dev_dbg(&client->dev, "Initializing device\n");
3661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* Read chip config */
3671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	data->config1 = adm1026_read_value(client, ADM1026_REG_CONFIG1);
3681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	data->config2 = adm1026_read_value(client, ADM1026_REG_CONFIG2);
3691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	data->config3 = adm1026_read_value(client, ADM1026_REG_CONFIG3);
3701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* Inform user of chip config */
3721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	dev_dbg(&client->dev, "ADM1026_REG_CONFIG1 is: 0x%02x\n",
3731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		data->config1);
3741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if ((data->config1 & CFG1_MONITOR) == 0) {
3751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		dev_dbg(&client->dev, "Monitoring not currently "
3761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			"enabled.\n");
3771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
3781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (data->config1 & CFG1_INT_ENABLE) {
3791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		dev_dbg(&client->dev, "SMBALERT interrupts are "
3801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			"enabled.\n");
3811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
3821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (data->config1 & CFG1_AIN8_9) {
3831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		dev_dbg(&client->dev, "in8 and in9 enabled. "
3841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			"temp3 disabled.\n");
3851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	} else {
3861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		dev_dbg(&client->dev, "temp3 enabled.  in8 and "
3871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			"in9 disabled.\n");
3881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
3891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (data->config1 & CFG1_THERM_HOT) {
3901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		dev_dbg(&client->dev, "Automatic THERM, PWM, "
3911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			"and temp limits enabled.\n");
3921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
3931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (data->config3 & CFG3_GPIO16_ENABLE) {
395368609c5a8bd75b77721e69726ddfd3c6a30f7d4Jean Delvare		dev_dbg(&client->dev, "GPIO16 enabled.  THERM "
3961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			"pin disabled.\n");
3971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	} else {
3981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		dev_dbg(&client->dev, "THERM pin enabled.  "
3991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			"GPIO16 disabled.\n");
4001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
40186aa3e22106be3d6338113ff5acd7a87c40056c4Guenter Roeck	if (data->config3 & CFG3_VREF_250)
4021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		dev_dbg(&client->dev, "Vref is 2.50 Volts.\n");
40386aa3e22106be3d6338113ff5acd7a87c40056c4Guenter Roeck	else
4041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		dev_dbg(&client->dev, "Vref is 1.82 Volts.\n");
4051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* Read and pick apart the existing GPIO configuration */
4061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	value = 0;
40786aa3e22106be3d6338113ff5acd7a87c40056c4Guenter Roeck	for (i = 0; i <= 15; ++i) {
4081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if ((i & 0x03) == 0) {
4091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			value = adm1026_read_value(client,
41086aa3e22106be3d6338113ff5acd7a87c40056c4Guenter Roeck					ADM1026_REG_GPIO_CFG_0_3 + i / 4);
4111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
4121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		data->gpio_config[i] = value & 0x03;
4131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		value >>= 2;
4141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
4151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	data->gpio_config[16] = (data->config3 >> 6) & 0x03;
4161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* ... and then print it */
4181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	adm1026_print_gpio(client);
4191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
42086aa3e22106be3d6338113ff5acd7a87c40056c4Guenter Roeck	/*
42186aa3e22106be3d6338113ff5acd7a87c40056c4Guenter Roeck	 * If the user asks us to reprogram the GPIO config, then
4221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * do it now.
4231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 */
4241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (gpio_input[0] != -1 || gpio_output[0] != -1
4251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		|| gpio_inverted[0] != -1 || gpio_normal[0] != -1
4261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		|| gpio_fan[0] != -1) {
4271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		adm1026_fixup_gpio(client);
4281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
4291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
43086aa3e22106be3d6338113ff5acd7a87c40056c4Guenter Roeck	/*
43186aa3e22106be3d6338113ff5acd7a87c40056c4Guenter Roeck	 * WE INTENTIONALLY make no changes to the limits,
4321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 *   offsets, pwms, fans and zones.  If they were
4331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 *   configured, we don't want to mess with them.
4341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 *   If they weren't, the default is 100% PWM, no
4351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 *   control and will suffice until 'sensors -s'
436cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvare	 *   can be run by the user.  We DO set the default
4371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 *   value for pwm1.auto_pwm_min to its maximum
4381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 *   so that enabling automatic pwm fan control
439cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvare	 *   without first setting a value for pwm1.auto_pwm_min
4401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 *   will not result in potentially dangerous fan speed decrease.
4411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 */
44286aa3e22106be3d6338113ff5acd7a87c40056c4Guenter Roeck	data->pwm1.auto_pwm_min = 255;
4431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* Start monitoring */
4441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	value = adm1026_read_value(client, ADM1026_REG_CONFIG1);
4451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* Set MONITOR, clear interrupt acknowledge and s/w reset */
4461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	value = (value | CFG1_MONITOR) & (~CFG1_INT_CLEAR & ~CFG1_RESET);
4471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	dev_dbg(&client->dev, "Setting CONFIG to: 0x%02x\n", value);
4481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	data->config1 = value;
4491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	adm1026_write_value(client, ADM1026_REG_CONFIG1, value);
4501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* initialize fan_div[] to hardware defaults */
4521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	value = adm1026_read_value(client, ADM1026_REG_FAN_DIV_0_3) |
4531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		(adm1026_read_value(client, ADM1026_REG_FAN_DIV_4_7) << 8);
45486aa3e22106be3d6338113ff5acd7a87c40056c4Guenter Roeck	for (i = 0; i <= 7; ++i) {
4551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		data->fan_div[i] = DIV_FROM_REG(value & 0x03);
4561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		value >>= 2;
4571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
4581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
4591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
460c49efceffa599299ab3f38b1cdf8c2f1bf9811c4Ben Dooksstatic void adm1026_print_gpio(struct i2c_client *client)
4611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
4621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct adm1026_data *data = i2c_get_clientdata(client);
463cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvare	int i;
4641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
465885fe4b1f621fa2c8499e222059b59dbc98583e2Jean Delvare	dev_dbg(&client->dev, "GPIO config is:\n");
46686aa3e22106be3d6338113ff5acd7a87c40056c4Guenter Roeck	for (i = 0; i <= 7; ++i) {
4671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (data->config2 & (1 << i)) {
4681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			dev_dbg(&client->dev, "\t%sGP%s%d\n",
4691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				data->gpio_config[i] & 0x02 ? "" : "!",
4701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				data->gpio_config[i] & 0x01 ? "OUT" : "IN",
4711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				i);
4721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		} else {
4731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			dev_dbg(&client->dev, "\tFAN%d\n", i);
4741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
4751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
47686aa3e22106be3d6338113ff5acd7a87c40056c4Guenter Roeck	for (i = 8; i <= 15; ++i) {
4771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		dev_dbg(&client->dev, "\t%sGP%s%d\n",
4781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			data->gpio_config[i] & 0x02 ? "" : "!",
4791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			data->gpio_config[i] & 0x01 ? "OUT" : "IN",
4801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			i);
4811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
4821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (data->config3 & CFG3_GPIO16_ENABLE) {
4831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		dev_dbg(&client->dev, "\t%sGP%s16\n",
4841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			data->gpio_config[16] & 0x02 ? "" : "!",
4851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			data->gpio_config[16] & 0x01 ? "OUT" : "IN");
4861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	} else {
487cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvare		/* GPIO16 is THERM */
4881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		dev_dbg(&client->dev, "\tTHERM\n");
4891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
4901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
4911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
492c49efceffa599299ab3f38b1cdf8c2f1bf9811c4Ben Dooksstatic void adm1026_fixup_gpio(struct i2c_client *client)
4931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
4941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct adm1026_data *data = i2c_get_clientdata(client);
495cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvare	int i;
496cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvare	int value;
4971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* Make the changes requested. */
49986aa3e22106be3d6338113ff5acd7a87c40056c4Guenter Roeck	/*
50086aa3e22106be3d6338113ff5acd7a87c40056c4Guenter Roeck	 * We may need to unlock/stop monitoring or soft-reset the
5011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 *    chip before we can make changes.  This hasn't been
5021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 *    tested much.  FIXME
5031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 */
5041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* Make outputs */
50686aa3e22106be3d6338113ff5acd7a87c40056c4Guenter Roeck	for (i = 0; i <= 16; ++i) {
50786aa3e22106be3d6338113ff5acd7a87c40056c4Guenter Roeck		if (gpio_output[i] >= 0 && gpio_output[i] <= 16)
5081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			data->gpio_config[gpio_output[i]] |= 0x01;
5091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		/* if GPIO0-7 is output, it isn't a FAN tach */
51086aa3e22106be3d6338113ff5acd7a87c40056c4Guenter Roeck		if (gpio_output[i] >= 0 && gpio_output[i] <= 7)
5111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			data->config2 |= 1 << gpio_output[i];
5121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
5131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* Input overrides output */
51586aa3e22106be3d6338113ff5acd7a87c40056c4Guenter Roeck	for (i = 0; i <= 16; ++i) {
51686aa3e22106be3d6338113ff5acd7a87c40056c4Guenter Roeck		if (gpio_input[i] >= 0 && gpio_input[i] <= 16)
51786aa3e22106be3d6338113ff5acd7a87c40056c4Guenter Roeck			data->gpio_config[gpio_input[i]] &= ~0x01;
5181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		/* if GPIO0-7 is input, it isn't a FAN tach */
51986aa3e22106be3d6338113ff5acd7a87c40056c4Guenter Roeck		if (gpio_input[i] >= 0 && gpio_input[i] <= 7)
5201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			data->config2 |= 1 << gpio_input[i];
5211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
5221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
523cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvare	/* Inverted */
52486aa3e22106be3d6338113ff5acd7a87c40056c4Guenter Roeck	for (i = 0; i <= 16; ++i) {
52586aa3e22106be3d6338113ff5acd7a87c40056c4Guenter Roeck		if (gpio_inverted[i] >= 0 && gpio_inverted[i] <= 16)
52686aa3e22106be3d6338113ff5acd7a87c40056c4Guenter Roeck			data->gpio_config[gpio_inverted[i]] &= ~0x02;
5271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
5281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
529cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvare	/* Normal overrides inverted */
53086aa3e22106be3d6338113ff5acd7a87c40056c4Guenter Roeck	for (i = 0; i <= 16; ++i) {
53186aa3e22106be3d6338113ff5acd7a87c40056c4Guenter Roeck		if (gpio_normal[i] >= 0 && gpio_normal[i] <= 16)
5321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			data->gpio_config[gpio_normal[i]] |= 0x02;
5331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
5341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* Fan overrides input and output */
53686aa3e22106be3d6338113ff5acd7a87c40056c4Guenter Roeck	for (i = 0; i <= 7; ++i) {
53786aa3e22106be3d6338113ff5acd7a87c40056c4Guenter Roeck		if (gpio_fan[i] >= 0 && gpio_fan[i] <= 7)
5381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			data->config2 &= ~(1 << gpio_fan[i]);
5391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
5401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* Write new configs to registers */
5421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	adm1026_write_value(client, ADM1026_REG_CONFIG2, data->config2);
5431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	data->config3 = (data->config3 & 0x3f)
5441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			| ((data->gpio_config[16] & 0x03) << 6);
5451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	adm1026_write_value(client, ADM1026_REG_CONFIG3, data->config3);
54686aa3e22106be3d6338113ff5acd7a87c40056c4Guenter Roeck	for (i = 15, value = 0; i >= 0; --i) {
5471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		value <<= 2;
5481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		value |= data->gpio_config[i] & 0x03;
5491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if ((i & 0x03) == 0) {
5501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			adm1026_write_value(client,
5511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds					ADM1026_REG_GPIO_CFG_0_3 + i/4,
5521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds					value);
5531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			value = 0;
5541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
5551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
5561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* Print the new config */
5581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	adm1026_print_gpio(client);
5591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
5601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic struct adm1026_data *adm1026_update_device(struct device *dev)
5631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
5641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct i2c_client *client = to_i2c_client(dev);
5651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct adm1026_data *data = i2c_get_clientdata(client);
5661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int i;
5671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	long value, alarms, gpio;
5681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5699a61bf6300533d3b64d7ff29adfec00e596de67dIngo Molnar	mutex_lock(&data->update_lock);
5701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (!data->valid
57186aa3e22106be3d6338113ff5acd7a87c40056c4Guenter Roeck	    || time_after(jiffies,
57286aa3e22106be3d6338113ff5acd7a87c40056c4Guenter Roeck			  data->last_reading + ADM1026_DATA_INTERVAL)) {
5731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		/* Things that change quickly */
574cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvare		dev_dbg(&client->dev, "Reading sensor values\n");
57586aa3e22106be3d6338113ff5acd7a87c40056c4Guenter Roeck		for (i = 0; i <= 16; ++i) {
5761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			data->in[i] =
5771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			    adm1026_read_value(client, ADM1026_REG_IN[i]);
5781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
5791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
58086aa3e22106be3d6338113ff5acd7a87c40056c4Guenter Roeck		for (i = 0; i <= 7; ++i) {
5811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			data->fan[i] =
5821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			    adm1026_read_value(client, ADM1026_REG_FAN(i));
5831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
5841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
58586aa3e22106be3d6338113ff5acd7a87c40056c4Guenter Roeck		for (i = 0; i <= 2; ++i) {
58686aa3e22106be3d6338113ff5acd7a87c40056c4Guenter Roeck			/*
58786aa3e22106be3d6338113ff5acd7a87c40056c4Guenter Roeck			 * NOTE: temp[] is s8 and we assume 2's complement
58886aa3e22106be3d6338113ff5acd7a87c40056c4Guenter Roeck			 *   "conversion" in the assignment
58986aa3e22106be3d6338113ff5acd7a87c40056c4Guenter Roeck			 */
5901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			data->temp[i] =
5911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			    adm1026_read_value(client, ADM1026_REG_TEMP[i]);
5921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
5931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
594cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvare		data->pwm1.pwm = adm1026_read_value(client,
5951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			ADM1026_REG_PWM);
596cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvare		data->analog_out = adm1026_read_value(client,
5971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			ADM1026_REG_DAC);
5981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		/* GPIO16 is MSbit of alarms, move it to gpio */
5991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		alarms = adm1026_read_value(client, ADM1026_REG_STATUS4);
600cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvare		gpio = alarms & 0x80 ? 0x0100 : 0; /* GPIO16 */
6011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		alarms &= 0x7f;
6021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		alarms <<= 8;
6031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		alarms |= adm1026_read_value(client, ADM1026_REG_STATUS3);
6041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		alarms <<= 8;
6051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		alarms |= adm1026_read_value(client, ADM1026_REG_STATUS2);
6061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		alarms <<= 8;
6071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		alarms |= adm1026_read_value(client, ADM1026_REG_STATUS1);
6081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		data->alarms = alarms;
6091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
6101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		/* Read the GPIO values */
611cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvare		gpio |= adm1026_read_value(client,
6121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			ADM1026_REG_GPIO_STATUS_8_15);
6131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		gpio <<= 8;
614cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvare		gpio |= adm1026_read_value(client,
6151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			ADM1026_REG_GPIO_STATUS_0_7);
6161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		data->gpio = gpio;
6171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
6181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		data->last_reading = jiffies;
619cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvare	}; /* last_reading */
6201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
6211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (!data->valid ||
6221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	    time_after(jiffies, data->last_config + ADM1026_CONFIG_INTERVAL)) {
6231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		/* Things that don't change often */
6241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		dev_dbg(&client->dev, "Reading config values\n");
62586aa3e22106be3d6338113ff5acd7a87c40056c4Guenter Roeck		for (i = 0; i <= 16; ++i) {
626cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvare			data->in_min[i] = adm1026_read_value(client,
6271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				ADM1026_REG_IN_MIN[i]);
628cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvare			data->in_max[i] = adm1026_read_value(client,
6291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				ADM1026_REG_IN_MAX[i]);
6301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
6311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
6321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		value = adm1026_read_value(client, ADM1026_REG_FAN_DIV_0_3)
6331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			| (adm1026_read_value(client, ADM1026_REG_FAN_DIV_4_7)
6341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			<< 8);
63586aa3e22106be3d6338113ff5acd7a87c40056c4Guenter Roeck		for (i = 0; i <= 7; ++i) {
636cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvare			data->fan_min[i] = adm1026_read_value(client,
6371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				ADM1026_REG_FAN_MIN(i));
6381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			data->fan_div[i] = DIV_FROM_REG(value & 0x03);
6391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			value >>= 2;
6401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
6411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
6421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		for (i = 0; i <= 2; ++i) {
64386aa3e22106be3d6338113ff5acd7a87c40056c4Guenter Roeck			/*
64486aa3e22106be3d6338113ff5acd7a87c40056c4Guenter Roeck			 * NOTE: temp_xxx[] are s8 and we assume 2's
6451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			 *    complement "conversion" in the assignment
6461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			 */
647cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvare			data->temp_min[i] = adm1026_read_value(client,
6481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				ADM1026_REG_TEMP_MIN[i]);
649cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvare			data->temp_max[i] = adm1026_read_value(client,
6501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				ADM1026_REG_TEMP_MAX[i]);
651cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvare			data->temp_tmin[i] = adm1026_read_value(client,
6521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				ADM1026_REG_TEMP_TMIN[i]);
653cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvare			data->temp_crit[i] = adm1026_read_value(client,
6541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				ADM1026_REG_TEMP_THERM[i]);
655cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvare			data->temp_offset[i] = adm1026_read_value(client,
6561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				ADM1026_REG_TEMP_OFFSET[i]);
6571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
6581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
6591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		/* Read the STATUS/alarm masks */
660cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvare		alarms = adm1026_read_value(client, ADM1026_REG_MASK4);
661cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvare		gpio = alarms & 0x80 ? 0x0100 : 0; /* GPIO16 */
662cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvare		alarms = (alarms & 0x7f) << 8;
6631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		alarms |= adm1026_read_value(client, ADM1026_REG_MASK3);
6641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		alarms <<= 8;
6651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		alarms |= adm1026_read_value(client, ADM1026_REG_MASK2);
6661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		alarms <<= 8;
6671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		alarms |= adm1026_read_value(client, ADM1026_REG_MASK1);
6681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		data->alarm_mask = alarms;
6691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
6701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		/* Read the GPIO values */
671cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvare		gpio |= adm1026_read_value(client,
6721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			ADM1026_REG_GPIO_MASK_8_15);
6731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		gpio <<= 8;
6741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		gpio |= adm1026_read_value(client, ADM1026_REG_GPIO_MASK_0_7);
6751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		data->gpio_mask = gpio;
6761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
6771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		/* Read various values from CONFIG1 */
678cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvare		data->config1 = adm1026_read_value(client,
6791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			ADM1026_REG_CONFIG1);
6801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (data->config1 & CFG1_PWM_AFC) {
6811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			data->pwm1.enable = 2;
682cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvare			data->pwm1.auto_pwm_min =
6831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				PWM_MIN_FROM_REG(data->pwm1.pwm);
6841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
6851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		/* Read the GPIO config */
686cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvare		data->config2 = adm1026_read_value(client,
6871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			ADM1026_REG_CONFIG2);
688cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvare		data->config3 = adm1026_read_value(client,
6891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			ADM1026_REG_CONFIG3);
6901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		data->gpio_config[16] = (data->config3 >> 6) & 0x03;
6911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
6921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		value = 0;
69386aa3e22106be3d6338113ff5acd7a87c40056c4Guenter Roeck		for (i = 0; i <= 15; ++i) {
6941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			if ((i & 0x03) == 0) {
6951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				value = adm1026_read_value(client,
6961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds					    ADM1026_REG_GPIO_CFG_0_3 + i/4);
6971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			}
6981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			data->gpio_config[i] = value & 0x03;
6991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			value >>= 2;
7001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
7011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
7021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		data->last_config = jiffies;
703cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvare	}; /* last_config */
7041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
7051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	data->valid = 1;
7069a61bf6300533d3b64d7ff29adfec00e596de67dIngo Molnar	mutex_unlock(&data->update_lock);
7071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return data;
7081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
7091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
710050480f12aeab62d39a1a07546606a47217ebefaYani Ioannoustatic ssize_t show_in(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", INS_FROM_REG(nr, data->in[nr]));
7171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
718050480f12aeab62d39a1a07546606a47217ebefaYani Ioannoustatic ssize_t show_in_min(struct device *dev, struct device_attribute *attr,
719050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou		char *buf)
7201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
721050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou	struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr);
722050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou	int nr = sensor_attr->index;
723cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvare	struct adm1026_data *data = adm1026_update_device(dev);
724cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvare	return sprintf(buf, "%d\n", INS_FROM_REG(nr, data->in_min[nr]));
7251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
726050480f12aeab62d39a1a07546606a47217ebefaYani Ioannoustatic ssize_t set_in_min(struct device *dev, struct device_attribute *attr,
727050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou		const char *buf, size_t count)
7281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
729050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou	struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr);
730050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou	int nr = sensor_attr->index;
7311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct i2c_client *client = to_i2c_client(dev);
7321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct adm1026_data *data = i2c_get_clientdata(client);
73386aa3e22106be3d6338113ff5acd7a87c40056c4Guenter Roeck	long val;
73486aa3e22106be3d6338113ff5acd7a87c40056c4Guenter Roeck	int err;
73586aa3e22106be3d6338113ff5acd7a87c40056c4Guenter Roeck
73686aa3e22106be3d6338113ff5acd7a87c40056c4Guenter Roeck	err = kstrtol(buf, 10, &val);
73786aa3e22106be3d6338113ff5acd7a87c40056c4Guenter Roeck	if (err)
73886aa3e22106be3d6338113ff5acd7a87c40056c4Guenter Roeck		return err;
7391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
7409a61bf6300533d3b64d7ff29adfec00e596de67dIngo Molnar	mutex_lock(&data->update_lock);
7411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	data->in_min[nr] = INS_TO_REG(nr, val);
7421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	adm1026_write_value(client, ADM1026_REG_IN_MIN[nr], data->in_min[nr]);
7439a61bf6300533d3b64d7ff29adfec00e596de67dIngo Molnar	mutex_unlock(&data->update_lock);
744cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvare	return count;
7451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
746050480f12aeab62d39a1a07546606a47217ebefaYani Ioannoustatic ssize_t show_in_max(struct device *dev, struct device_attribute *attr,
747050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou		char *buf)
7481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
749050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou	struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr);
750050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou	int nr = sensor_attr->index;
7511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct adm1026_data *data = adm1026_update_device(dev);
752cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvare	return sprintf(buf, "%d\n", INS_FROM_REG(nr, data->in_max[nr]));
7531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
754050480f12aeab62d39a1a07546606a47217ebefaYani Ioannoustatic ssize_t set_in_max(struct device *dev, struct device_attribute *attr,
755050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou		const char *buf, size_t count)
7561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
757050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou	struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr);
758050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou	int nr = sensor_attr->index;
7591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct i2c_client *client = to_i2c_client(dev);
7601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct adm1026_data *data = i2c_get_clientdata(client);
76186aa3e22106be3d6338113ff5acd7a87c40056c4Guenter Roeck	long val;
76286aa3e22106be3d6338113ff5acd7a87c40056c4Guenter Roeck	int err;
76386aa3e22106be3d6338113ff5acd7a87c40056c4Guenter Roeck
76486aa3e22106be3d6338113ff5acd7a87c40056c4Guenter Roeck	err = kstrtol(buf, 10, &val);
76586aa3e22106be3d6338113ff5acd7a87c40056c4Guenter Roeck	if (err)
76686aa3e22106be3d6338113ff5acd7a87c40056c4Guenter Roeck		return err;
7671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
7689a61bf6300533d3b64d7ff29adfec00e596de67dIngo Molnar	mutex_lock(&data->update_lock);
7691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	data->in_max[nr] = INS_TO_REG(nr, val);
7701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	adm1026_write_value(client, ADM1026_REG_IN_MAX[nr], data->in_max[nr]);
7719a61bf6300533d3b64d7ff29adfec00e596de67dIngo Molnar	mutex_unlock(&data->update_lock);
7721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return count;
7731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
7741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
775050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou#define in_reg(offset)						\
776050480f12aeab62d39a1a07546606a47217ebefaYani Ioannoustatic SENSOR_DEVICE_ATTR(in##offset##_input, S_IRUGO, show_in,	\
777050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou		NULL, offset);					\
778050480f12aeab62d39a1a07546606a47217ebefaYani Ioannoustatic SENSOR_DEVICE_ATTR(in##offset##_min, S_IRUGO | S_IWUSR,	\
779050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou		show_in_min, set_in_min, offset);		\
780050480f12aeab62d39a1a07546606a47217ebefaYani Ioannoustatic SENSOR_DEVICE_ATTR(in##offset##_max, S_IRUGO | S_IWUSR,	\
781050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou		show_in_max, set_in_max, offset);
7821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
7831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
7841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsin_reg(0);
7851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsin_reg(1);
7861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsin_reg(2);
7871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsin_reg(3);
7881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsin_reg(4);
7891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsin_reg(5);
7901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsin_reg(6);
7911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsin_reg(7);
7921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsin_reg(8);
7931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsin_reg(9);
7941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsin_reg(10);
7951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsin_reg(11);
7961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsin_reg(12);
7971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsin_reg(13);
7981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsin_reg(14);
7991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsin_reg(15);
8001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
80186aa3e22106be3d6338113ff5acd7a87c40056c4Guenter Roeckstatic ssize_t show_in16(struct device *dev, struct device_attribute *attr,
80286aa3e22106be3d6338113ff5acd7a87c40056c4Guenter Roeck			 char *buf)
8031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
8041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct adm1026_data *data = adm1026_update_device(dev);
805cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvare	return sprintf(buf, "%d\n", INS_FROM_REG(16, data->in[16]) -
8061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		NEG12_OFFSET);
8071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
80886aa3e22106be3d6338113ff5acd7a87c40056c4Guenter Roeckstatic ssize_t show_in16_min(struct device *dev, struct device_attribute *attr,
80986aa3e22106be3d6338113ff5acd7a87c40056c4Guenter Roeck			     char *buf)
8101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
811cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvare	struct adm1026_data *data = adm1026_update_device(dev);
812cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvare	return sprintf(buf, "%d\n", INS_FROM_REG(16, data->in_min[16])
8131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		- NEG12_OFFSET);
8141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
81586aa3e22106be3d6338113ff5acd7a87c40056c4Guenter Roeckstatic ssize_t set_in16_min(struct device *dev, struct device_attribute *attr,
81686aa3e22106be3d6338113ff5acd7a87c40056c4Guenter Roeck			    const char *buf, size_t count)
8171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
8181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct i2c_client *client = to_i2c_client(dev);
8191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct adm1026_data *data = i2c_get_clientdata(client);
82086aa3e22106be3d6338113ff5acd7a87c40056c4Guenter Roeck	long val;
82186aa3e22106be3d6338113ff5acd7a87c40056c4Guenter Roeck	int err;
82286aa3e22106be3d6338113ff5acd7a87c40056c4Guenter Roeck
82386aa3e22106be3d6338113ff5acd7a87c40056c4Guenter Roeck	err = kstrtol(buf, 10, &val);
82486aa3e22106be3d6338113ff5acd7a87c40056c4Guenter Roeck	if (err)
82586aa3e22106be3d6338113ff5acd7a87c40056c4Guenter Roeck		return err;
8261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
8279a61bf6300533d3b64d7ff29adfec00e596de67dIngo Molnar	mutex_lock(&data->update_lock);
8281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	data->in_min[16] = INS_TO_REG(16, val + NEG12_OFFSET);
8291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	adm1026_write_value(client, ADM1026_REG_IN_MIN[16], data->in_min[16]);
8309a61bf6300533d3b64d7ff29adfec00e596de67dIngo Molnar	mutex_unlock(&data->update_lock);
831cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvare	return count;
8321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
83386aa3e22106be3d6338113ff5acd7a87c40056c4Guenter Roeckstatic ssize_t show_in16_max(struct device *dev, struct device_attribute *attr,
83486aa3e22106be3d6338113ff5acd7a87c40056c4Guenter Roeck			     char *buf)
8351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
8361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct adm1026_data *data = adm1026_update_device(dev);
837cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvare	return sprintf(buf, "%d\n", INS_FROM_REG(16, data->in_max[16])
8381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			- NEG12_OFFSET);
8391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
84086aa3e22106be3d6338113ff5acd7a87c40056c4Guenter Roeckstatic ssize_t set_in16_max(struct device *dev, struct device_attribute *attr,
84186aa3e22106be3d6338113ff5acd7a87c40056c4Guenter Roeck			    const char *buf, size_t count)
8421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
8431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct i2c_client *client = to_i2c_client(dev);
8441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct adm1026_data *data = i2c_get_clientdata(client);
84586aa3e22106be3d6338113ff5acd7a87c40056c4Guenter Roeck	long val;
84686aa3e22106be3d6338113ff5acd7a87c40056c4Guenter Roeck	int err;
84786aa3e22106be3d6338113ff5acd7a87c40056c4Guenter Roeck
84886aa3e22106be3d6338113ff5acd7a87c40056c4Guenter Roeck	err = kstrtol(buf, 10, &val);
84986aa3e22106be3d6338113ff5acd7a87c40056c4Guenter Roeck	if (err)
85086aa3e22106be3d6338113ff5acd7a87c40056c4Guenter Roeck		return err;
8511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
8529a61bf6300533d3b64d7ff29adfec00e596de67dIngo Molnar	mutex_lock(&data->update_lock);
8531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	data->in_max[16] = INS_TO_REG(16, val+NEG12_OFFSET);
8541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	adm1026_write_value(client, ADM1026_REG_IN_MAX[16], data->in_max[16]);
8559a61bf6300533d3b64d7ff29adfec00e596de67dIngo Molnar	mutex_unlock(&data->update_lock);
8561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return count;
8571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
8581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
859050480f12aeab62d39a1a07546606a47217ebefaYani Ioannoustatic SENSOR_DEVICE_ATTR(in16_input, S_IRUGO, show_in16, NULL, 16);
86086aa3e22106be3d6338113ff5acd7a87c40056c4Guenter Roeckstatic SENSOR_DEVICE_ATTR(in16_min, S_IRUGO | S_IWUSR, show_in16_min,
86186aa3e22106be3d6338113ff5acd7a87c40056c4Guenter Roeck			  set_in16_min, 16);
86286aa3e22106be3d6338113ff5acd7a87c40056c4Guenter Roeckstatic SENSOR_DEVICE_ATTR(in16_max, S_IRUGO | S_IWUSR, show_in16_max,
86386aa3e22106be3d6338113ff5acd7a87c40056c4Guenter Roeck			  set_in16_max, 16);
8641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
8651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
8661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* Now add fan read/write functions */
8671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
868050480f12aeab62d39a1a07546606a47217ebefaYani Ioannoustatic ssize_t show_fan(struct device *dev, struct device_attribute *attr,
869050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou		char *buf)
8701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
871050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou	struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr);
872050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou	int nr = sensor_attr->index;
8731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct adm1026_data *data = adm1026_update_device(dev);
874cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvare	return sprintf(buf, "%d\n", FAN_FROM_REG(data->fan[nr],
8751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		data->fan_div[nr]));
8761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
877050480f12aeab62d39a1a07546606a47217ebefaYani Ioannoustatic ssize_t show_fan_min(struct device *dev, struct device_attribute *attr,
878050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou		char *buf)
8791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
880050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou	struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr);
881050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou	int nr = sensor_attr->index;
8821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct adm1026_data *data = adm1026_update_device(dev);
883cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvare	return sprintf(buf, "%d\n", FAN_FROM_REG(data->fan_min[nr],
8841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		data->fan_div[nr]));
8851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
886050480f12aeab62d39a1a07546606a47217ebefaYani Ioannoustatic ssize_t set_fan_min(struct device *dev, struct device_attribute *attr,
887050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou		const char *buf, size_t count)
8881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
889050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou	struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr);
890050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou	int nr = sensor_attr->index;
8911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct i2c_client *client = to_i2c_client(dev);
8921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct adm1026_data *data = i2c_get_clientdata(client);
89386aa3e22106be3d6338113ff5acd7a87c40056c4Guenter Roeck	long val;
89486aa3e22106be3d6338113ff5acd7a87c40056c4Guenter Roeck	int err;
89586aa3e22106be3d6338113ff5acd7a87c40056c4Guenter Roeck
89686aa3e22106be3d6338113ff5acd7a87c40056c4Guenter Roeck	err = kstrtol(buf, 10, &val);
89786aa3e22106be3d6338113ff5acd7a87c40056c4Guenter Roeck	if (err)
89886aa3e22106be3d6338113ff5acd7a87c40056c4Guenter Roeck		return err;
8991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
9009a61bf6300533d3b64d7ff29adfec00e596de67dIngo Molnar	mutex_lock(&data->update_lock);
9011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	data->fan_min[nr] = FAN_TO_REG(val, data->fan_div[nr]);
9021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	adm1026_write_value(client, ADM1026_REG_FAN_MIN(nr),
9031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		data->fan_min[nr]);
9049a61bf6300533d3b64d7ff29adfec00e596de67dIngo Molnar	mutex_unlock(&data->update_lock);
9051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return count;
9061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
9071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
908cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvare#define fan_offset(offset)						\
909cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvarestatic SENSOR_DEVICE_ATTR(fan##offset##_input, S_IRUGO, show_fan, NULL,	\
910cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvare		offset - 1);						\
911cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvarestatic SENSOR_DEVICE_ATTR(fan##offset##_min, S_IRUGO | S_IWUSR,		\
912050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou		show_fan_min, set_fan_min, offset - 1);
9131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
9141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsfan_offset(1);
9151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsfan_offset(2);
9161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsfan_offset(3);
9171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsfan_offset(4);
9181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsfan_offset(5);
9191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsfan_offset(6);
9201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsfan_offset(7);
9211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsfan_offset(8);
9221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
9231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* Adjust fan_min to account for new fan divisor */
9241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void fixup_fan_min(struct device *dev, int fan, int old_div)
9251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
9261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct i2c_client *client = to_i2c_client(dev);
9271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct adm1026_data *data = i2c_get_clientdata(client);
928cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvare	int new_min;
929cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvare	int new_div = data->fan_div[fan];
9301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
9311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* 0 and 0xff are special.  Don't adjust them */
93286aa3e22106be3d6338113ff5acd7a87c40056c4Guenter Roeck	if (data->fan_min[fan] == 0 || data->fan_min[fan] == 0xff)
9331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return;
9341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
9351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	new_min = data->fan_min[fan] * old_div / new_div;
9361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	new_min = SENSORS_LIMIT(new_min, 1, 254);
9371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	data->fan_min[fan] = new_min;
9381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	adm1026_write_value(client, ADM1026_REG_FAN_MIN(fan), new_min);
9391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
9401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
9411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* Now add fan_div read/write functions */
942050480f12aeab62d39a1a07546606a47217ebefaYani Ioannoustatic ssize_t show_fan_div(struct device *dev, struct device_attribute *attr,
943050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou		char *buf)
9441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
945050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou	struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr);
946050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou	int nr = sensor_attr->index;
9471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct adm1026_data *data = adm1026_update_device(dev);
948cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvare	return sprintf(buf, "%d\n", data->fan_div[nr]);
9491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
950050480f12aeab62d39a1a07546606a47217ebefaYani Ioannoustatic ssize_t set_fan_div(struct device *dev, struct device_attribute *attr,
951050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou		const char *buf, size_t count)
9521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
953050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou	struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr);
954050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou	int nr = sensor_attr->index;
9551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct i2c_client *client = to_i2c_client(dev);
9561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct adm1026_data *data = i2c_get_clientdata(client);
95786aa3e22106be3d6338113ff5acd7a87c40056c4Guenter Roeck	long val;
95886aa3e22106be3d6338113ff5acd7a87c40056c4Guenter Roeck	int orig_div, new_div;
95986aa3e22106be3d6338113ff5acd7a87c40056c4Guenter Roeck	int err;
96086aa3e22106be3d6338113ff5acd7a87c40056c4Guenter Roeck
96186aa3e22106be3d6338113ff5acd7a87c40056c4Guenter Roeck	err = kstrtol(buf, 10, &val);
96286aa3e22106be3d6338113ff5acd7a87c40056c4Guenter Roeck	if (err)
96386aa3e22106be3d6338113ff5acd7a87c40056c4Guenter Roeck		return err;
9641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
965cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvare	new_div = DIV_TO_REG(val);
9668b0f1840a46449e1946fc88860ef3ec8d6b1c2c7Gabriele Gorla
9679a61bf6300533d3b64d7ff29adfec00e596de67dIngo Molnar	mutex_lock(&data->update_lock);
9681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	orig_div = data->fan_div[nr];
9691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	data->fan_div[nr] = DIV_FROM_REG(new_div);
9701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
9711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (nr < 4) { /* 0 <= nr < 4 */
9721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		adm1026_write_value(client, ADM1026_REG_FAN_DIV_0_3,
97352bc9802ce849d0d287cc5fe76d06b0daa3986caGabriele Gorla				    (DIV_TO_REG(data->fan_div[0]) << 0) |
97452bc9802ce849d0d287cc5fe76d06b0daa3986caGabriele Gorla				    (DIV_TO_REG(data->fan_div[1]) << 2) |
97552bc9802ce849d0d287cc5fe76d06b0daa3986caGabriele Gorla				    (DIV_TO_REG(data->fan_div[2]) << 4) |
97652bc9802ce849d0d287cc5fe76d06b0daa3986caGabriele Gorla				    (DIV_TO_REG(data->fan_div[3]) << 6));
9771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	} else { /* 3 < nr < 8 */
9781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		adm1026_write_value(client, ADM1026_REG_FAN_DIV_4_7,
97952bc9802ce849d0d287cc5fe76d06b0daa3986caGabriele Gorla				    (DIV_TO_REG(data->fan_div[4]) << 0) |
98052bc9802ce849d0d287cc5fe76d06b0daa3986caGabriele Gorla				    (DIV_TO_REG(data->fan_div[5]) << 2) |
98152bc9802ce849d0d287cc5fe76d06b0daa3986caGabriele Gorla				    (DIV_TO_REG(data->fan_div[6]) << 4) |
98252bc9802ce849d0d287cc5fe76d06b0daa3986caGabriele Gorla				    (DIV_TO_REG(data->fan_div[7]) << 6));
9831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
9841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
98586aa3e22106be3d6338113ff5acd7a87c40056c4Guenter Roeck	if (data->fan_div[nr] != orig_div)
986cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvare		fixup_fan_min(dev, nr, orig_div);
98786aa3e22106be3d6338113ff5acd7a87c40056c4Guenter Roeck
9889a61bf6300533d3b64d7ff29adfec00e596de67dIngo Molnar	mutex_unlock(&data->update_lock);
9891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return count;
9901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
9911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
992cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvare#define fan_offset_div(offset)						\
993cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvarestatic SENSOR_DEVICE_ATTR(fan##offset##_div, S_IRUGO | S_IWUSR,		\
994050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou		show_fan_div, set_fan_div, offset - 1);
9951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
9961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsfan_offset_div(1);
9971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsfan_offset_div(2);
9981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsfan_offset_div(3);
9991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsfan_offset_div(4);
10001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsfan_offset_div(5);
10011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsfan_offset_div(6);
10021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsfan_offset_div(7);
10031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsfan_offset_div(8);
10041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
10051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* Temps */
1006050480f12aeab62d39a1a07546606a47217ebefaYani Ioannoustatic ssize_t show_temp(struct device *dev, struct device_attribute *attr,
1007050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou		char *buf)
10081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
1009050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou	struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr);
1010050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou	int nr = sensor_attr->index;
10111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct adm1026_data *data = adm1026_update_device(dev);
1012cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvare	return sprintf(buf, "%d\n", TEMP_FROM_REG(data->temp[nr]));
10131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
1014050480f12aeab62d39a1a07546606a47217ebefaYani Ioannoustatic ssize_t show_temp_min(struct device *dev, struct device_attribute *attr,
1015050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou		char *buf)
10161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
1017050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou	struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr);
1018050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou	int nr = sensor_attr->index;
10191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct adm1026_data *data = adm1026_update_device(dev);
1020cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvare	return sprintf(buf, "%d\n", TEMP_FROM_REG(data->temp_min[nr]));
10211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
1022050480f12aeab62d39a1a07546606a47217ebefaYani Ioannoustatic ssize_t set_temp_min(struct device *dev, struct device_attribute *attr,
1023050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou		const char *buf, size_t count)
10241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
1025050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou	struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr);
1026050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou	int nr = sensor_attr->index;
10271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct i2c_client *client = to_i2c_client(dev);
10281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct adm1026_data *data = i2c_get_clientdata(client);
102986aa3e22106be3d6338113ff5acd7a87c40056c4Guenter Roeck	long val;
103086aa3e22106be3d6338113ff5acd7a87c40056c4Guenter Roeck	int err;
103186aa3e22106be3d6338113ff5acd7a87c40056c4Guenter Roeck
103286aa3e22106be3d6338113ff5acd7a87c40056c4Guenter Roeck	err = kstrtol(buf, 10, &val);
103386aa3e22106be3d6338113ff5acd7a87c40056c4Guenter Roeck	if (err)
103486aa3e22106be3d6338113ff5acd7a87c40056c4Guenter Roeck		return err;
10351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
10369a61bf6300533d3b64d7ff29adfec00e596de67dIngo Molnar	mutex_lock(&data->update_lock);
10371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	data->temp_min[nr] = TEMP_TO_REG(val);
10381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	adm1026_write_value(client, ADM1026_REG_TEMP_MIN[nr],
10391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		data->temp_min[nr]);
10409a61bf6300533d3b64d7ff29adfec00e596de67dIngo Molnar	mutex_unlock(&data->update_lock);
10411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return count;
10421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
1043050480f12aeab62d39a1a07546606a47217ebefaYani Ioannoustatic ssize_t show_temp_max(struct device *dev, struct device_attribute *attr,
1044050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou		char *buf)
10451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
1046050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou	struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr);
1047050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou	int nr = sensor_attr->index;
10481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct adm1026_data *data = adm1026_update_device(dev);
1049cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvare	return sprintf(buf, "%d\n", TEMP_FROM_REG(data->temp_max[nr]));
10501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
1051050480f12aeab62d39a1a07546606a47217ebefaYani Ioannoustatic ssize_t set_temp_max(struct device *dev, struct device_attribute *attr,
1052050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou		const char *buf, size_t count)
10531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
1054050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou	struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr);
1055050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou	int nr = sensor_attr->index;
10561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct i2c_client *client = to_i2c_client(dev);
10571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct adm1026_data *data = i2c_get_clientdata(client);
105886aa3e22106be3d6338113ff5acd7a87c40056c4Guenter Roeck	long val;
105986aa3e22106be3d6338113ff5acd7a87c40056c4Guenter Roeck	int err;
106086aa3e22106be3d6338113ff5acd7a87c40056c4Guenter Roeck
106186aa3e22106be3d6338113ff5acd7a87c40056c4Guenter Roeck	err = kstrtol(buf, 10, &val);
106286aa3e22106be3d6338113ff5acd7a87c40056c4Guenter Roeck	if (err)
106386aa3e22106be3d6338113ff5acd7a87c40056c4Guenter Roeck		return err;
10641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
10659a61bf6300533d3b64d7ff29adfec00e596de67dIngo Molnar	mutex_lock(&data->update_lock);
10661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	data->temp_max[nr] = TEMP_TO_REG(val);
10671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	adm1026_write_value(client, ADM1026_REG_TEMP_MAX[nr],
10681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		data->temp_max[nr]);
10699a61bf6300533d3b64d7ff29adfec00e596de67dIngo Molnar	mutex_unlock(&data->update_lock);
10701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return count;
10711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
1072050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou
1073050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou#define temp_reg(offset)						\
1074cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvarestatic SENSOR_DEVICE_ATTR(temp##offset##_input, S_IRUGO, show_temp,	\
1075050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou		NULL, offset - 1);					\
1076050480f12aeab62d39a1a07546606a47217ebefaYani Ioannoustatic SENSOR_DEVICE_ATTR(temp##offset##_min, S_IRUGO | S_IWUSR,	\
1077050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou		show_temp_min, set_temp_min, offset - 1);		\
1078050480f12aeab62d39a1a07546606a47217ebefaYani Ioannoustatic SENSOR_DEVICE_ATTR(temp##offset##_max, S_IRUGO | S_IWUSR,	\
1079050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou		show_temp_max, set_temp_max, offset - 1);
10801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
10811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
10821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldstemp_reg(1);
10831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldstemp_reg(2);
10841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldstemp_reg(3);
10851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1086050480f12aeab62d39a1a07546606a47217ebefaYani Ioannoustatic ssize_t show_temp_offset(struct device *dev,
1087050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou		struct device_attribute *attr, char *buf)
10881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
1089050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou	struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr);
1090050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou	int nr = sensor_attr->index;
10911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct adm1026_data *data = adm1026_update_device(dev);
1092cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvare	return sprintf(buf, "%d\n", TEMP_FROM_REG(data->temp_offset[nr]));
10931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
1094050480f12aeab62d39a1a07546606a47217ebefaYani Ioannoustatic ssize_t set_temp_offset(struct device *dev,
1095050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou		struct device_attribute *attr, const char *buf,
1096050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou		size_t count)
10971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
1098050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou	struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr);
1099050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou	int nr = sensor_attr->index;
11001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct i2c_client *client = to_i2c_client(dev);
11011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct adm1026_data *data = i2c_get_clientdata(client);
110286aa3e22106be3d6338113ff5acd7a87c40056c4Guenter Roeck	long val;
110386aa3e22106be3d6338113ff5acd7a87c40056c4Guenter Roeck	int err;
110486aa3e22106be3d6338113ff5acd7a87c40056c4Guenter Roeck
110586aa3e22106be3d6338113ff5acd7a87c40056c4Guenter Roeck	err = kstrtol(buf, 10, &val);
110686aa3e22106be3d6338113ff5acd7a87c40056c4Guenter Roeck	if (err)
110786aa3e22106be3d6338113ff5acd7a87c40056c4Guenter Roeck		return err;
11081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
11099a61bf6300533d3b64d7ff29adfec00e596de67dIngo Molnar	mutex_lock(&data->update_lock);
11101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	data->temp_offset[nr] = TEMP_TO_REG(val);
11111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	adm1026_write_value(client, ADM1026_REG_TEMP_OFFSET[nr],
11121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		data->temp_offset[nr]);
11139a61bf6300533d3b64d7ff29adfec00e596de67dIngo Molnar	mutex_unlock(&data->update_lock);
11141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return count;
11151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
11161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
111786aa3e22106be3d6338113ff5acd7a87c40056c4Guenter Roeck#define temp_offset_reg(offset)						\
111886aa3e22106be3d6338113ff5acd7a87c40056c4Guenter Roeckstatic SENSOR_DEVICE_ATTR(temp##offset##_offset, S_IRUGO | S_IWUSR,	\
1119050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou		show_temp_offset, set_temp_offset, offset - 1);
11201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
11211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldstemp_offset_reg(1);
11221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldstemp_offset_reg(2);
11231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldstemp_offset_reg(3);
11241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1125050480f12aeab62d39a1a07546606a47217ebefaYani Ioannoustatic ssize_t show_temp_auto_point1_temp_hyst(struct device *dev,
1126050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou		struct device_attribute *attr, char *buf)
11271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
1128050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou	struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr);
1129050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou	int nr = sensor_attr->index;
11301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct adm1026_data *data = adm1026_update_device(dev);
1131cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvare	return sprintf(buf, "%d\n", TEMP_FROM_REG(
11321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		ADM1026_FAN_ACTIVATION_TEMP_HYST + data->temp_tmin[nr]));
11331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
1134050480f12aeab62d39a1a07546606a47217ebefaYani Ioannoustatic ssize_t show_temp_auto_point2_temp(struct device *dev,
1135050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou		struct device_attribute *attr, char *buf)
11361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
1137050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou	struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr);
1138050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou	int nr = sensor_attr->index;
11391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct adm1026_data *data = adm1026_update_device(dev);
1140cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvare	return sprintf(buf, "%d\n", TEMP_FROM_REG(data->temp_tmin[nr] +
11411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		ADM1026_FAN_CONTROL_TEMP_RANGE));
11421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
1143050480f12aeab62d39a1a07546606a47217ebefaYani Ioannoustatic ssize_t show_temp_auto_point1_temp(struct device *dev,
1144050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou		struct device_attribute *attr, char *buf)
11451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
1146050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou	struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr);
1147050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou	int nr = sensor_attr->index;
11481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct adm1026_data *data = adm1026_update_device(dev);
1149cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvare	return sprintf(buf, "%d\n", TEMP_FROM_REG(data->temp_tmin[nr]));
11501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
1151050480f12aeab62d39a1a07546606a47217ebefaYani Ioannoustatic ssize_t set_temp_auto_point1_temp(struct device *dev,
1152050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou		struct device_attribute *attr, const char *buf, size_t count)
11531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
1154050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou	struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr);
1155050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou	int nr = sensor_attr->index;
11561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct i2c_client *client = to_i2c_client(dev);
11571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct adm1026_data *data = i2c_get_clientdata(client);
115886aa3e22106be3d6338113ff5acd7a87c40056c4Guenter Roeck	long val;
115986aa3e22106be3d6338113ff5acd7a87c40056c4Guenter Roeck	int err;
116086aa3e22106be3d6338113ff5acd7a87c40056c4Guenter Roeck
116186aa3e22106be3d6338113ff5acd7a87c40056c4Guenter Roeck	err = kstrtol(buf, 10, &val);
116286aa3e22106be3d6338113ff5acd7a87c40056c4Guenter Roeck	if (err)
116386aa3e22106be3d6338113ff5acd7a87c40056c4Guenter Roeck		return err;
11641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
11659a61bf6300533d3b64d7ff29adfec00e596de67dIngo Molnar	mutex_lock(&data->update_lock);
11661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	data->temp_tmin[nr] = TEMP_TO_REG(val);
11671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	adm1026_write_value(client, ADM1026_REG_TEMP_TMIN[nr],
11681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		data->temp_tmin[nr]);
11699a61bf6300533d3b64d7ff29adfec00e596de67dIngo Molnar	mutex_unlock(&data->update_lock);
11701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return count;
11711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
11721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1173cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvare#define temp_auto_point(offset)						\
1174cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvarestatic SENSOR_DEVICE_ATTR(temp##offset##_auto_point1_temp,		\
1175cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvare		S_IRUGO | S_IWUSR, show_temp_auto_point1_temp,		\
1176cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvare		set_temp_auto_point1_temp, offset - 1);			\
1177cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvarestatic SENSOR_DEVICE_ATTR(temp##offset##_auto_point1_temp_hyst, S_IRUGO,\
1178cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvare		show_temp_auto_point1_temp_hyst, NULL, offset - 1);	\
1179cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvarestatic SENSOR_DEVICE_ATTR(temp##offset##_auto_point2_temp, S_IRUGO,	\
1180050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou		show_temp_auto_point2_temp, NULL, offset - 1);
11811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
11821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldstemp_auto_point(1);
11831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldstemp_auto_point(2);
11841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldstemp_auto_point(3);
11851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1186050480f12aeab62d39a1a07546606a47217ebefaYani Ioannoustatic ssize_t show_temp_crit_enable(struct device *dev,
1187050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou		struct device_attribute *attr, char *buf)
11881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
11891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct adm1026_data *data = adm1026_update_device(dev);
1190cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvare	return sprintf(buf, "%d\n", (data->config1 & CFG1_THERM_HOT) >> 4);
11911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
1192050480f12aeab62d39a1a07546606a47217ebefaYani Ioannoustatic ssize_t set_temp_crit_enable(struct device *dev,
1193050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou		struct device_attribute *attr, const char *buf, size_t count)
11941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
11951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct i2c_client *client = to_i2c_client(dev);
11961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct adm1026_data *data = i2c_get_clientdata(client);
119786aa3e22106be3d6338113ff5acd7a87c40056c4Guenter Roeck	unsigned long val;
119886aa3e22106be3d6338113ff5acd7a87c40056c4Guenter Roeck	int err;
119986aa3e22106be3d6338113ff5acd7a87c40056c4Guenter Roeck
120086aa3e22106be3d6338113ff5acd7a87c40056c4Guenter Roeck	err = kstrtoul(buf, 10, &val);
120186aa3e22106be3d6338113ff5acd7a87c40056c4Guenter Roeck	if (err)
120286aa3e22106be3d6338113ff5acd7a87c40056c4Guenter Roeck		return err;
120386aa3e22106be3d6338113ff5acd7a87c40056c4Guenter Roeck
120486aa3e22106be3d6338113ff5acd7a87c40056c4Guenter Roeck	if (val > 1)
120586aa3e22106be3d6338113ff5acd7a87c40056c4Guenter Roeck		return -EINVAL;
120686aa3e22106be3d6338113ff5acd7a87c40056c4Guenter Roeck
120786aa3e22106be3d6338113ff5acd7a87c40056c4Guenter Roeck	mutex_lock(&data->update_lock);
120886aa3e22106be3d6338113ff5acd7a87c40056c4Guenter Roeck	data->config1 = (data->config1 & ~CFG1_THERM_HOT) | (val << 4);
120986aa3e22106be3d6338113ff5acd7a87c40056c4Guenter Roeck	adm1026_write_value(client, ADM1026_REG_CONFIG1, data->config1);
121086aa3e22106be3d6338113ff5acd7a87c40056c4Guenter Roeck	mutex_unlock(&data->update_lock);
12111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
12121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return count;
12131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
12141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1215050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou#define temp_crit_enable(offset)				\
1216050480f12aeab62d39a1a07546606a47217ebefaYani Ioannoustatic DEVICE_ATTR(temp##offset##_crit_enable, S_IRUGO | S_IWUSR, \
12171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	show_temp_crit_enable, set_temp_crit_enable);
12181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1219050480f12aeab62d39a1a07546606a47217ebefaYani Ioannoutemp_crit_enable(1);
1220050480f12aeab62d39a1a07546606a47217ebefaYani Ioannoutemp_crit_enable(2);
1221050480f12aeab62d39a1a07546606a47217ebefaYani Ioannoutemp_crit_enable(3);
12221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1223050480f12aeab62d39a1a07546606a47217ebefaYani Ioannoustatic ssize_t show_temp_crit(struct device *dev,
1224050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou		struct device_attribute *attr, char *buf)
12251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
1226050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou	struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr);
1227050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou	int nr = sensor_attr->index;
12281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct adm1026_data *data = adm1026_update_device(dev);
1229cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvare	return sprintf(buf, "%d\n", TEMP_FROM_REG(data->temp_crit[nr]));
12301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
1231050480f12aeab62d39a1a07546606a47217ebefaYani Ioannoustatic ssize_t set_temp_crit(struct device *dev, struct device_attribute *attr,
1232050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou		const char *buf, size_t count)
12331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
1234050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou	struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr);
1235050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou	int nr = sensor_attr->index;
12361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct i2c_client *client = to_i2c_client(dev);
12371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct adm1026_data *data = i2c_get_clientdata(client);
123886aa3e22106be3d6338113ff5acd7a87c40056c4Guenter Roeck	long val;
123986aa3e22106be3d6338113ff5acd7a87c40056c4Guenter Roeck	int err;
124086aa3e22106be3d6338113ff5acd7a87c40056c4Guenter Roeck
124186aa3e22106be3d6338113ff5acd7a87c40056c4Guenter Roeck	err = kstrtol(buf, 10, &val);
124286aa3e22106be3d6338113ff5acd7a87c40056c4Guenter Roeck	if (err)
124386aa3e22106be3d6338113ff5acd7a87c40056c4Guenter Roeck		return err;
12441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
12459a61bf6300533d3b64d7ff29adfec00e596de67dIngo Molnar	mutex_lock(&data->update_lock);
12461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	data->temp_crit[nr] = TEMP_TO_REG(val);
12471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	adm1026_write_value(client, ADM1026_REG_TEMP_THERM[nr],
12481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		data->temp_crit[nr]);
12499a61bf6300533d3b64d7ff29adfec00e596de67dIngo Molnar	mutex_unlock(&data->update_lock);
12501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return count;
12511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
12521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1253050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou#define temp_crit_reg(offset)						\
1254050480f12aeab62d39a1a07546606a47217ebefaYani Ioannoustatic SENSOR_DEVICE_ATTR(temp##offset##_crit, S_IRUGO | S_IWUSR,	\
1255050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou		show_temp_crit, set_temp_crit, offset - 1);
12561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
12571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldstemp_crit_reg(1);
12581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldstemp_crit_reg(2);
12591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldstemp_crit_reg(3);
12601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
126186aa3e22106be3d6338113ff5acd7a87c40056c4Guenter Roeckstatic ssize_t show_analog_out_reg(struct device *dev,
126286aa3e22106be3d6338113ff5acd7a87c40056c4Guenter Roeck				   struct device_attribute *attr, char *buf)
12631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
12641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct adm1026_data *data = adm1026_update_device(dev);
1265cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvare	return sprintf(buf, "%d\n", DAC_FROM_REG(data->analog_out));
12661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
126786aa3e22106be3d6338113ff5acd7a87c40056c4Guenter Roeckstatic ssize_t set_analog_out_reg(struct device *dev,
126886aa3e22106be3d6338113ff5acd7a87c40056c4Guenter Roeck				  struct device_attribute *attr,
126986aa3e22106be3d6338113ff5acd7a87c40056c4Guenter Roeck				  const char *buf, size_t count)
12701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
12711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct i2c_client *client = to_i2c_client(dev);
12721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct adm1026_data *data = i2c_get_clientdata(client);
127386aa3e22106be3d6338113ff5acd7a87c40056c4Guenter Roeck	long val;
127486aa3e22106be3d6338113ff5acd7a87c40056c4Guenter Roeck	int err;
127586aa3e22106be3d6338113ff5acd7a87c40056c4Guenter Roeck
127686aa3e22106be3d6338113ff5acd7a87c40056c4Guenter Roeck	err = kstrtol(buf, 10, &val);
127786aa3e22106be3d6338113ff5acd7a87c40056c4Guenter Roeck	if (err)
127886aa3e22106be3d6338113ff5acd7a87c40056c4Guenter Roeck		return err;
12791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
12809a61bf6300533d3b64d7ff29adfec00e596de67dIngo Molnar	mutex_lock(&data->update_lock);
12811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	data->analog_out = DAC_TO_REG(val);
12821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	adm1026_write_value(client, ADM1026_REG_DAC, data->analog_out);
12839a61bf6300533d3b64d7ff29adfec00e596de67dIngo Molnar	mutex_unlock(&data->update_lock);
12841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return count;
12851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
12861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1287cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvarestatic DEVICE_ATTR(analog_out, S_IRUGO | S_IWUSR, show_analog_out_reg,
12881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	set_analog_out_reg);
12891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
129086aa3e22106be3d6338113ff5acd7a87c40056c4Guenter Roeckstatic ssize_t show_vid_reg(struct device *dev, struct device_attribute *attr,
129186aa3e22106be3d6338113ff5acd7a87c40056c4Guenter Roeck			    char *buf)
12921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
12931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct adm1026_data *data = adm1026_update_device(dev);
1294a0cf354a71bd2969b2f1868530d3fecaebd6dc3dJean Delvare	int vid = (data->gpio >> 11) & 0x1f;
1295a0cf354a71bd2969b2f1868530d3fecaebd6dc3dJean Delvare
1296a0cf354a71bd2969b2f1868530d3fecaebd6dc3dJean Delvare	dev_dbg(dev, "Setting VID from GPIO11-15.\n");
1297a0cf354a71bd2969b2f1868530d3fecaebd6dc3dJean Delvare	return sprintf(buf, "%d\n", vid_from_reg(vid, data->vrm));
12981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
129986aa3e22106be3d6338113ff5acd7a87c40056c4Guenter Roeck
1300937df8df907ce63b0f7e19adf6e3cdef1687fac3Grant Coadystatic DEVICE_ATTR(cpu0_vid, S_IRUGO, show_vid_reg, NULL);
13011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
130286aa3e22106be3d6338113ff5acd7a87c40056c4Guenter Roeckstatic ssize_t show_vrm_reg(struct device *dev, struct device_attribute *attr,
130386aa3e22106be3d6338113ff5acd7a87c40056c4Guenter Roeck			    char *buf)
13041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
130590d6619a916062cb75a176aacb318d108758b4a5Jean Delvare	struct adm1026_data *data = dev_get_drvdata(dev);
1306cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvare	return sprintf(buf, "%d\n", data->vrm);
13071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
130886aa3e22106be3d6338113ff5acd7a87c40056c4Guenter Roeck
130986aa3e22106be3d6338113ff5acd7a87c40056c4Guenter Roeckstatic ssize_t store_vrm_reg(struct device *dev, struct device_attribute *attr,
131086aa3e22106be3d6338113ff5acd7a87c40056c4Guenter Roeck			     const char *buf, size_t count)
13111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
1312f67fdabfb94b0bb96623a4b48d22be5329a06277Jean Delvare	struct adm1026_data *data = dev_get_drvdata(dev);
131386aa3e22106be3d6338113ff5acd7a87c40056c4Guenter Roeck	unsigned long val;
131486aa3e22106be3d6338113ff5acd7a87c40056c4Guenter Roeck	int err;
131586aa3e22106be3d6338113ff5acd7a87c40056c4Guenter Roeck
131686aa3e22106be3d6338113ff5acd7a87c40056c4Guenter Roeck	err = kstrtoul(buf, 10, &val);
131786aa3e22106be3d6338113ff5acd7a87c40056c4Guenter Roeck	if (err)
131886aa3e22106be3d6338113ff5acd7a87c40056c4Guenter Roeck		return err;
13191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
132086aa3e22106be3d6338113ff5acd7a87c40056c4Guenter Roeck	data->vrm = val;
13211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return count;
13221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
13231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
13241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic DEVICE_ATTR(vrm, S_IRUGO | S_IWUSR, show_vrm_reg, store_vrm_reg);
13251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
132686aa3e22106be3d6338113ff5acd7a87c40056c4Guenter Roeckstatic ssize_t show_alarms_reg(struct device *dev,
132786aa3e22106be3d6338113ff5acd7a87c40056c4Guenter Roeck			       struct device_attribute *attr, char *buf)
13281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
13291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct adm1026_data *data = adm1026_update_device(dev);
1330f67fdabfb94b0bb96623a4b48d22be5329a06277Jean Delvare	return sprintf(buf, "%ld\n", data->alarms);
13311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
13321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
13331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic DEVICE_ATTR(alarms, S_IRUGO, show_alarms_reg, NULL);
13341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1335a9273cb8eea503f6b8e28bd5f613962ecba278c5Jean Delvarestatic ssize_t show_alarm(struct device *dev, struct device_attribute *attr,
1336a9273cb8eea503f6b8e28bd5f613962ecba278c5Jean Delvare			  char *buf)
1337a9273cb8eea503f6b8e28bd5f613962ecba278c5Jean Delvare{
1338a9273cb8eea503f6b8e28bd5f613962ecba278c5Jean Delvare	struct adm1026_data *data = adm1026_update_device(dev);
1339a9273cb8eea503f6b8e28bd5f613962ecba278c5Jean Delvare	int bitnr = to_sensor_dev_attr(attr)->index;
1340a9273cb8eea503f6b8e28bd5f613962ecba278c5Jean Delvare	return sprintf(buf, "%ld\n", (data->alarms >> bitnr) & 1);
1341a9273cb8eea503f6b8e28bd5f613962ecba278c5Jean Delvare}
1342a9273cb8eea503f6b8e28bd5f613962ecba278c5Jean Delvare
1343a9273cb8eea503f6b8e28bd5f613962ecba278c5Jean Delvarestatic SENSOR_DEVICE_ATTR(temp2_alarm, S_IRUGO, show_alarm, NULL, 0);
1344a9273cb8eea503f6b8e28bd5f613962ecba278c5Jean Delvarestatic SENSOR_DEVICE_ATTR(temp3_alarm, S_IRUGO, show_alarm, NULL, 1);
1345a9273cb8eea503f6b8e28bd5f613962ecba278c5Jean Delvarestatic SENSOR_DEVICE_ATTR(in9_alarm, S_IRUGO, show_alarm, NULL, 1);
1346a9273cb8eea503f6b8e28bd5f613962ecba278c5Jean Delvarestatic SENSOR_DEVICE_ATTR(in11_alarm, S_IRUGO, show_alarm, NULL, 2);
1347a9273cb8eea503f6b8e28bd5f613962ecba278c5Jean Delvarestatic SENSOR_DEVICE_ATTR(in12_alarm, S_IRUGO, show_alarm, NULL, 3);
1348a9273cb8eea503f6b8e28bd5f613962ecba278c5Jean Delvarestatic SENSOR_DEVICE_ATTR(in13_alarm, S_IRUGO, show_alarm, NULL, 4);
1349a9273cb8eea503f6b8e28bd5f613962ecba278c5Jean Delvarestatic SENSOR_DEVICE_ATTR(in14_alarm, S_IRUGO, show_alarm, NULL, 5);
1350a9273cb8eea503f6b8e28bd5f613962ecba278c5Jean Delvarestatic SENSOR_DEVICE_ATTR(in15_alarm, S_IRUGO, show_alarm, NULL, 6);
1351a9273cb8eea503f6b8e28bd5f613962ecba278c5Jean Delvarestatic SENSOR_DEVICE_ATTR(in16_alarm, S_IRUGO, show_alarm, NULL, 7);
1352a9273cb8eea503f6b8e28bd5f613962ecba278c5Jean Delvarestatic SENSOR_DEVICE_ATTR(in0_alarm, S_IRUGO, show_alarm, NULL, 8);
1353a9273cb8eea503f6b8e28bd5f613962ecba278c5Jean Delvarestatic SENSOR_DEVICE_ATTR(in1_alarm, S_IRUGO, show_alarm, NULL, 9);
1354a9273cb8eea503f6b8e28bd5f613962ecba278c5Jean Delvarestatic SENSOR_DEVICE_ATTR(in2_alarm, S_IRUGO, show_alarm, NULL, 10);
1355a9273cb8eea503f6b8e28bd5f613962ecba278c5Jean Delvarestatic SENSOR_DEVICE_ATTR(in3_alarm, S_IRUGO, show_alarm, NULL, 11);
1356a9273cb8eea503f6b8e28bd5f613962ecba278c5Jean Delvarestatic SENSOR_DEVICE_ATTR(in4_alarm, S_IRUGO, show_alarm, NULL, 12);
1357a9273cb8eea503f6b8e28bd5f613962ecba278c5Jean Delvarestatic SENSOR_DEVICE_ATTR(in5_alarm, S_IRUGO, show_alarm, NULL, 13);
1358a9273cb8eea503f6b8e28bd5f613962ecba278c5Jean Delvarestatic SENSOR_DEVICE_ATTR(in6_alarm, S_IRUGO, show_alarm, NULL, 14);
1359a9273cb8eea503f6b8e28bd5f613962ecba278c5Jean Delvarestatic SENSOR_DEVICE_ATTR(in7_alarm, S_IRUGO, show_alarm, NULL, 15);
1360a9273cb8eea503f6b8e28bd5f613962ecba278c5Jean Delvarestatic SENSOR_DEVICE_ATTR(fan1_alarm, S_IRUGO, show_alarm, NULL, 16);
1361a9273cb8eea503f6b8e28bd5f613962ecba278c5Jean Delvarestatic SENSOR_DEVICE_ATTR(fan2_alarm, S_IRUGO, show_alarm, NULL, 17);
1362a9273cb8eea503f6b8e28bd5f613962ecba278c5Jean Delvarestatic SENSOR_DEVICE_ATTR(fan3_alarm, S_IRUGO, show_alarm, NULL, 18);
1363a9273cb8eea503f6b8e28bd5f613962ecba278c5Jean Delvarestatic SENSOR_DEVICE_ATTR(fan4_alarm, S_IRUGO, show_alarm, NULL, 19);
1364a9273cb8eea503f6b8e28bd5f613962ecba278c5Jean Delvarestatic SENSOR_DEVICE_ATTR(fan5_alarm, S_IRUGO, show_alarm, NULL, 20);
1365a9273cb8eea503f6b8e28bd5f613962ecba278c5Jean Delvarestatic SENSOR_DEVICE_ATTR(fan6_alarm, S_IRUGO, show_alarm, NULL, 21);
1366a9273cb8eea503f6b8e28bd5f613962ecba278c5Jean Delvarestatic SENSOR_DEVICE_ATTR(fan7_alarm, S_IRUGO, show_alarm, NULL, 22);
1367a9273cb8eea503f6b8e28bd5f613962ecba278c5Jean Delvarestatic SENSOR_DEVICE_ATTR(fan8_alarm, S_IRUGO, show_alarm, NULL, 23);
1368a9273cb8eea503f6b8e28bd5f613962ecba278c5Jean Delvarestatic SENSOR_DEVICE_ATTR(temp1_alarm, S_IRUGO, show_alarm, NULL, 24);
1369a9273cb8eea503f6b8e28bd5f613962ecba278c5Jean Delvarestatic SENSOR_DEVICE_ATTR(in10_alarm, S_IRUGO, show_alarm, NULL, 25);
1370a9273cb8eea503f6b8e28bd5f613962ecba278c5Jean Delvarestatic SENSOR_DEVICE_ATTR(in8_alarm, S_IRUGO, show_alarm, NULL, 26);
1371a9273cb8eea503f6b8e28bd5f613962ecba278c5Jean Delvare
137286aa3e22106be3d6338113ff5acd7a87c40056c4Guenter Roeckstatic ssize_t show_alarm_mask(struct device *dev,
137386aa3e22106be3d6338113ff5acd7a87c40056c4Guenter Roeck			       struct device_attribute *attr, char *buf)
13741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
13751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct adm1026_data *data = adm1026_update_device(dev);
1376cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvare	return sprintf(buf, "%ld\n", data->alarm_mask);
13771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
137886aa3e22106be3d6338113ff5acd7a87c40056c4Guenter Roeckstatic ssize_t set_alarm_mask(struct device *dev, struct device_attribute *attr,
137986aa3e22106be3d6338113ff5acd7a87c40056c4Guenter Roeck			      const char *buf, size_t count)
13801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
13811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct i2c_client *client = to_i2c_client(dev);
13821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct adm1026_data *data = i2c_get_clientdata(client);
13831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	unsigned long mask;
138486aa3e22106be3d6338113ff5acd7a87c40056c4Guenter Roeck	long val;
138586aa3e22106be3d6338113ff5acd7a87c40056c4Guenter Roeck	int err;
138686aa3e22106be3d6338113ff5acd7a87c40056c4Guenter Roeck
138786aa3e22106be3d6338113ff5acd7a87c40056c4Guenter Roeck	err = kstrtol(buf, 10, &val);
138886aa3e22106be3d6338113ff5acd7a87c40056c4Guenter Roeck	if (err)
138986aa3e22106be3d6338113ff5acd7a87c40056c4Guenter Roeck		return err;
13901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
13919a61bf6300533d3b64d7ff29adfec00e596de67dIngo Molnar	mutex_lock(&data->update_lock);
13921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	data->alarm_mask = val & 0x7fffffff;
13931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	mask = data->alarm_mask
13941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		| (data->gpio_mask & 0x10000 ? 0x80000000 : 0);
13951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	adm1026_write_value(client, ADM1026_REG_MASK1,
13961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		mask & 0xff);
13971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	mask >>= 8;
13981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	adm1026_write_value(client, ADM1026_REG_MASK2,
13991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		mask & 0xff);
14001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	mask >>= 8;
14011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	adm1026_write_value(client, ADM1026_REG_MASK3,
14021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		mask & 0xff);
14031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	mask >>= 8;
14041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	adm1026_write_value(client, ADM1026_REG_MASK4,
14051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		mask & 0xff);
14069a61bf6300533d3b64d7ff29adfec00e596de67dIngo Molnar	mutex_unlock(&data->update_lock);
14071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return count;
14081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
14091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
14101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic DEVICE_ATTR(alarm_mask, S_IRUGO | S_IWUSR, show_alarm_mask,
14111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	set_alarm_mask);
14121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
14131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
141486aa3e22106be3d6338113ff5acd7a87c40056c4Guenter Roeckstatic ssize_t show_gpio(struct device *dev, struct device_attribute *attr,
141586aa3e22106be3d6338113ff5acd7a87c40056c4Guenter Roeck			 char *buf)
14161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
14171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct adm1026_data *data = adm1026_update_device(dev);
1418cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvare	return sprintf(buf, "%ld\n", data->gpio);
14191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
142086aa3e22106be3d6338113ff5acd7a87c40056c4Guenter Roeckstatic ssize_t set_gpio(struct device *dev, struct device_attribute *attr,
142186aa3e22106be3d6338113ff5acd7a87c40056c4Guenter Roeck			const char *buf, size_t count)
14221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
14231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct i2c_client *client = to_i2c_client(dev);
14241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct adm1026_data *data = i2c_get_clientdata(client);
1425cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvare	long gpio;
142686aa3e22106be3d6338113ff5acd7a87c40056c4Guenter Roeck	long val;
142786aa3e22106be3d6338113ff5acd7a87c40056c4Guenter Roeck	int err;
142886aa3e22106be3d6338113ff5acd7a87c40056c4Guenter Roeck
142986aa3e22106be3d6338113ff5acd7a87c40056c4Guenter Roeck	err = kstrtol(buf, 10, &val);
143086aa3e22106be3d6338113ff5acd7a87c40056c4Guenter Roeck	if (err)
143186aa3e22106be3d6338113ff5acd7a87c40056c4Guenter Roeck		return err;
14321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
14339a61bf6300533d3b64d7ff29adfec00e596de67dIngo Molnar	mutex_lock(&data->update_lock);
14341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	data->gpio = val & 0x1ffff;
14351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	gpio = data->gpio;
1436cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvare	adm1026_write_value(client, ADM1026_REG_GPIO_STATUS_0_7, gpio & 0xff);
14371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	gpio >>= 8;
1438cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvare	adm1026_write_value(client, ADM1026_REG_GPIO_STATUS_8_15, gpio & 0xff);
14391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	gpio = ((gpio >> 1) & 0x80) | (data->alarms >> 24 & 0x7f);
1440cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvare	adm1026_write_value(client, ADM1026_REG_STATUS4, gpio & 0xff);
14419a61bf6300533d3b64d7ff29adfec00e596de67dIngo Molnar	mutex_unlock(&data->update_lock);
14421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return count;
14431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
14441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
14451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic DEVICE_ATTR(gpio, S_IRUGO | S_IWUSR, show_gpio, set_gpio);
14461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
144786aa3e22106be3d6338113ff5acd7a87c40056c4Guenter Roeckstatic ssize_t show_gpio_mask(struct device *dev, struct device_attribute *attr,
144886aa3e22106be3d6338113ff5acd7a87c40056c4Guenter Roeck			      char *buf)
14491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
14501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct adm1026_data *data = adm1026_update_device(dev);
1451cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvare	return sprintf(buf, "%ld\n", data->gpio_mask);
14521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
145386aa3e22106be3d6338113ff5acd7a87c40056c4Guenter Roeckstatic ssize_t set_gpio_mask(struct device *dev, struct device_attribute *attr,
145486aa3e22106be3d6338113ff5acd7a87c40056c4Guenter Roeck			     const char *buf, size_t count)
14551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
14561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct i2c_client *client = to_i2c_client(dev);
14571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct adm1026_data *data = i2c_get_clientdata(client);
1458cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvare	long mask;
145986aa3e22106be3d6338113ff5acd7a87c40056c4Guenter Roeck	long val;
146086aa3e22106be3d6338113ff5acd7a87c40056c4Guenter Roeck	int err;
146186aa3e22106be3d6338113ff5acd7a87c40056c4Guenter Roeck
146286aa3e22106be3d6338113ff5acd7a87c40056c4Guenter Roeck	err = kstrtol(buf, 10, &val);
146386aa3e22106be3d6338113ff5acd7a87c40056c4Guenter Roeck	if (err)
146486aa3e22106be3d6338113ff5acd7a87c40056c4Guenter Roeck		return err;
14651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
14669a61bf6300533d3b64d7ff29adfec00e596de67dIngo Molnar	mutex_lock(&data->update_lock);
14671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	data->gpio_mask = val & 0x1ffff;
14681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	mask = data->gpio_mask;
1469cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvare	adm1026_write_value(client, ADM1026_REG_GPIO_MASK_0_7, mask & 0xff);
14701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	mask >>= 8;
1471cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvare	adm1026_write_value(client, ADM1026_REG_GPIO_MASK_8_15, mask & 0xff);
14721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	mask = ((mask >> 1) & 0x80) | (data->alarm_mask >> 24 & 0x7f);
1473cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvare	adm1026_write_value(client, ADM1026_REG_MASK1, mask & 0xff);
14749a61bf6300533d3b64d7ff29adfec00e596de67dIngo Molnar	mutex_unlock(&data->update_lock);
14751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return count;
14761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
14771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
14781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic DEVICE_ATTR(gpio_mask, S_IRUGO | S_IWUSR, show_gpio_mask, set_gpio_mask);
14791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
148086aa3e22106be3d6338113ff5acd7a87c40056c4Guenter Roeckstatic ssize_t show_pwm_reg(struct device *dev, struct device_attribute *attr,
148186aa3e22106be3d6338113ff5acd7a87c40056c4Guenter Roeck			    char *buf)
14821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
14831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct adm1026_data *data = adm1026_update_device(dev);
1484cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvare	return sprintf(buf, "%d\n", PWM_FROM_REG(data->pwm1.pwm));
14851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
148686aa3e22106be3d6338113ff5acd7a87c40056c4Guenter Roeck
148786aa3e22106be3d6338113ff5acd7a87c40056c4Guenter Roeckstatic ssize_t set_pwm_reg(struct device *dev, struct device_attribute *attr,
148886aa3e22106be3d6338113ff5acd7a87c40056c4Guenter Roeck			   const char *buf, size_t count)
14891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
14901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct i2c_client *client = to_i2c_client(dev);
14911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct adm1026_data *data = i2c_get_clientdata(client);
14921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
14931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (data->pwm1.enable == 1) {
149486aa3e22106be3d6338113ff5acd7a87c40056c4Guenter Roeck		long val;
149586aa3e22106be3d6338113ff5acd7a87c40056c4Guenter Roeck		int err;
149686aa3e22106be3d6338113ff5acd7a87c40056c4Guenter Roeck
149786aa3e22106be3d6338113ff5acd7a87c40056c4Guenter Roeck		err = kstrtol(buf, 10, &val);
149886aa3e22106be3d6338113ff5acd7a87c40056c4Guenter Roeck		if (err)
149986aa3e22106be3d6338113ff5acd7a87c40056c4Guenter Roeck			return err;
15001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
15019a61bf6300533d3b64d7ff29adfec00e596de67dIngo Molnar		mutex_lock(&data->update_lock);
15021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		data->pwm1.pwm = PWM_TO_REG(val);
15031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		adm1026_write_value(client, ADM1026_REG_PWM, data->pwm1.pwm);
15049a61bf6300533d3b64d7ff29adfec00e596de67dIngo Molnar		mutex_unlock(&data->update_lock);
15051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
15061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return count;
15071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
150886aa3e22106be3d6338113ff5acd7a87c40056c4Guenter Roeck
150986aa3e22106be3d6338113ff5acd7a87c40056c4Guenter Roeckstatic ssize_t show_auto_pwm_min(struct device *dev,
151086aa3e22106be3d6338113ff5acd7a87c40056c4Guenter Roeck				 struct device_attribute *attr, char *buf)
15111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
15121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct adm1026_data *data = adm1026_update_device(dev);
1513cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvare	return sprintf(buf, "%d\n", data->pwm1.auto_pwm_min);
15141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
151586aa3e22106be3d6338113ff5acd7a87c40056c4Guenter Roeck
151686aa3e22106be3d6338113ff5acd7a87c40056c4Guenter Roeckstatic ssize_t set_auto_pwm_min(struct device *dev,
151786aa3e22106be3d6338113ff5acd7a87c40056c4Guenter Roeck				struct device_attribute *attr, const char *buf,
151886aa3e22106be3d6338113ff5acd7a87c40056c4Guenter Roeck				size_t count)
15191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
15201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct i2c_client *client = to_i2c_client(dev);
15211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct adm1026_data *data = i2c_get_clientdata(client);
152286aa3e22106be3d6338113ff5acd7a87c40056c4Guenter Roeck	unsigned long val;
152386aa3e22106be3d6338113ff5acd7a87c40056c4Guenter Roeck	int err;
152486aa3e22106be3d6338113ff5acd7a87c40056c4Guenter Roeck
152586aa3e22106be3d6338113ff5acd7a87c40056c4Guenter Roeck	err = kstrtoul(buf, 10, &val);
152686aa3e22106be3d6338113ff5acd7a87c40056c4Guenter Roeck	if (err)
152786aa3e22106be3d6338113ff5acd7a87c40056c4Guenter Roeck		return err;
15281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
15299a61bf6300533d3b64d7ff29adfec00e596de67dIngo Molnar	mutex_lock(&data->update_lock);
1530cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvare	data->pwm1.auto_pwm_min = SENSORS_LIMIT(val, 0, 255);
15311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (data->pwm1.enable == 2) { /* apply immediately */
15321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		data->pwm1.pwm = PWM_TO_REG((data->pwm1.pwm & 0x0f) |
1533cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvare			PWM_MIN_TO_REG(data->pwm1.auto_pwm_min));
15341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		adm1026_write_value(client, ADM1026_REG_PWM, data->pwm1.pwm);
15351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
15369a61bf6300533d3b64d7ff29adfec00e596de67dIngo Molnar	mutex_unlock(&data->update_lock);
15371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return count;
15381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
153986aa3e22106be3d6338113ff5acd7a87c40056c4Guenter Roeck
154086aa3e22106be3d6338113ff5acd7a87c40056c4Guenter Roeckstatic ssize_t show_auto_pwm_max(struct device *dev,
154186aa3e22106be3d6338113ff5acd7a87c40056c4Guenter Roeck				 struct device_attribute *attr, char *buf)
15421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
1543cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvare	return sprintf(buf, "%d\n", ADM1026_PWM_MAX);
15441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
154586aa3e22106be3d6338113ff5acd7a87c40056c4Guenter Roeck
154686aa3e22106be3d6338113ff5acd7a87c40056c4Guenter Roeckstatic ssize_t show_pwm_enable(struct device *dev,
154786aa3e22106be3d6338113ff5acd7a87c40056c4Guenter Roeck			       struct device_attribute *attr, char *buf)
15481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
15491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct adm1026_data *data = adm1026_update_device(dev);
1550cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvare	return sprintf(buf, "%d\n", data->pwm1.enable);
15511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
155286aa3e22106be3d6338113ff5acd7a87c40056c4Guenter Roeck
155386aa3e22106be3d6338113ff5acd7a87c40056c4Guenter Roeckstatic ssize_t set_pwm_enable(struct device *dev, struct device_attribute *attr,
155486aa3e22106be3d6338113ff5acd7a87c40056c4Guenter Roeck			      const char *buf, size_t count)
15551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
15561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct i2c_client *client = to_i2c_client(dev);
15571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct adm1026_data *data = i2c_get_clientdata(client);
1558cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvare	int old_enable;
155986aa3e22106be3d6338113ff5acd7a87c40056c4Guenter Roeck	unsigned long val;
156086aa3e22106be3d6338113ff5acd7a87c40056c4Guenter Roeck	int err;
15611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
156286aa3e22106be3d6338113ff5acd7a87c40056c4Guenter Roeck	err = kstrtoul(buf, 10, &val);
156386aa3e22106be3d6338113ff5acd7a87c40056c4Guenter Roeck	if (err)
156486aa3e22106be3d6338113ff5acd7a87c40056c4Guenter Roeck		return err;
156586aa3e22106be3d6338113ff5acd7a87c40056c4Guenter Roeck
156686aa3e22106be3d6338113ff5acd7a87c40056c4Guenter Roeck	if (val >= 3)
156786aa3e22106be3d6338113ff5acd7a87c40056c4Guenter Roeck		return -EINVAL;
156886aa3e22106be3d6338113ff5acd7a87c40056c4Guenter Roeck
156986aa3e22106be3d6338113ff5acd7a87c40056c4Guenter Roeck	mutex_lock(&data->update_lock);
157086aa3e22106be3d6338113ff5acd7a87c40056c4Guenter Roeck	old_enable = data->pwm1.enable;
157186aa3e22106be3d6338113ff5acd7a87c40056c4Guenter Roeck	data->pwm1.enable = val;
157286aa3e22106be3d6338113ff5acd7a87c40056c4Guenter Roeck	data->config1 = (data->config1 & ~CFG1_PWM_AFC)
157386aa3e22106be3d6338113ff5acd7a87c40056c4Guenter Roeck			| ((val == 2) ? CFG1_PWM_AFC : 0);
157486aa3e22106be3d6338113ff5acd7a87c40056c4Guenter Roeck	adm1026_write_value(client, ADM1026_REG_CONFIG1, data->config1);
157586aa3e22106be3d6338113ff5acd7a87c40056c4Guenter Roeck	if (val == 2) { /* apply pwm1_auto_pwm_min to pwm1 */
157686aa3e22106be3d6338113ff5acd7a87c40056c4Guenter Roeck		data->pwm1.pwm = PWM_TO_REG((data->pwm1.pwm & 0x0f) |
157786aa3e22106be3d6338113ff5acd7a87c40056c4Guenter Roeck			PWM_MIN_TO_REG(data->pwm1.auto_pwm_min));
157886aa3e22106be3d6338113ff5acd7a87c40056c4Guenter Roeck		adm1026_write_value(client, ADM1026_REG_PWM, data->pwm1.pwm);
157986aa3e22106be3d6338113ff5acd7a87c40056c4Guenter Roeck	} else if (!((old_enable == 1) && (val == 1))) {
158086aa3e22106be3d6338113ff5acd7a87c40056c4Guenter Roeck		/* set pwm to safe value */
158186aa3e22106be3d6338113ff5acd7a87c40056c4Guenter Roeck		data->pwm1.pwm = 255;
158286aa3e22106be3d6338113ff5acd7a87c40056c4Guenter Roeck		adm1026_write_value(client, ADM1026_REG_PWM, data->pwm1.pwm);
15831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
158486aa3e22106be3d6338113ff5acd7a87c40056c4Guenter Roeck	mutex_unlock(&data->update_lock);
158586aa3e22106be3d6338113ff5acd7a87c40056c4Guenter Roeck
15861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return count;
15871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
15881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
15891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* enable PWM fan control */
1590cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvarestatic DEVICE_ATTR(pwm1, S_IRUGO | S_IWUSR, show_pwm_reg, set_pwm_reg);
1591cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvarestatic DEVICE_ATTR(pwm2, S_IRUGO | S_IWUSR, show_pwm_reg, set_pwm_reg);
1592cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvarestatic DEVICE_ATTR(pwm3, S_IRUGO | S_IWUSR, show_pwm_reg, set_pwm_reg);
1593cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvarestatic DEVICE_ATTR(pwm1_enable, S_IRUGO | S_IWUSR, show_pwm_enable,
15941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	set_pwm_enable);
1595cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvarestatic DEVICE_ATTR(pwm2_enable, S_IRUGO | S_IWUSR, show_pwm_enable,
15961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	set_pwm_enable);
1597cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvarestatic DEVICE_ATTR(pwm3_enable, S_IRUGO | S_IWUSR, show_pwm_enable,
15981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	set_pwm_enable);
1599cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvarestatic DEVICE_ATTR(temp1_auto_point1_pwm, S_IRUGO | S_IWUSR,
16001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	show_auto_pwm_min, set_auto_pwm_min);
1601cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvarestatic DEVICE_ATTR(temp2_auto_point1_pwm, S_IRUGO | S_IWUSR,
16021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	show_auto_pwm_min, set_auto_pwm_min);
1603cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvarestatic DEVICE_ATTR(temp3_auto_point1_pwm, S_IRUGO | S_IWUSR,
16041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	show_auto_pwm_min, set_auto_pwm_min);
16051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
16061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic DEVICE_ATTR(temp1_auto_point2_pwm, S_IRUGO, show_auto_pwm_max, NULL);
16071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic DEVICE_ATTR(temp2_auto_point2_pwm, S_IRUGO, show_auto_pwm_max, NULL);
16081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic DEVICE_ATTR(temp3_auto_point2_pwm, S_IRUGO, show_auto_pwm_max, NULL);
16091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1610681c6f7a6702f208d48b501c8829dbc03a2ca238Mark M. Hoffmanstatic struct attribute *adm1026_attributes[] = {
1611681c6f7a6702f208d48b501c8829dbc03a2ca238Mark M. Hoffman	&sensor_dev_attr_in0_input.dev_attr.attr,
1612681c6f7a6702f208d48b501c8829dbc03a2ca238Mark M. Hoffman	&sensor_dev_attr_in0_max.dev_attr.attr,
1613681c6f7a6702f208d48b501c8829dbc03a2ca238Mark M. Hoffman	&sensor_dev_attr_in0_min.dev_attr.attr,
1614a9273cb8eea503f6b8e28bd5f613962ecba278c5Jean Delvare	&sensor_dev_attr_in0_alarm.dev_attr.attr,
1615681c6f7a6702f208d48b501c8829dbc03a2ca238Mark M. Hoffman	&sensor_dev_attr_in1_input.dev_attr.attr,
1616681c6f7a6702f208d48b501c8829dbc03a2ca238Mark M. Hoffman	&sensor_dev_attr_in1_max.dev_attr.attr,
1617681c6f7a6702f208d48b501c8829dbc03a2ca238Mark M. Hoffman	&sensor_dev_attr_in1_min.dev_attr.attr,
1618a9273cb8eea503f6b8e28bd5f613962ecba278c5Jean Delvare	&sensor_dev_attr_in1_alarm.dev_attr.attr,
1619681c6f7a6702f208d48b501c8829dbc03a2ca238Mark M. Hoffman	&sensor_dev_attr_in2_input.dev_attr.attr,
1620681c6f7a6702f208d48b501c8829dbc03a2ca238Mark M. Hoffman	&sensor_dev_attr_in2_max.dev_attr.attr,
1621681c6f7a6702f208d48b501c8829dbc03a2ca238Mark M. Hoffman	&sensor_dev_attr_in2_min.dev_attr.attr,
1622a9273cb8eea503f6b8e28bd5f613962ecba278c5Jean Delvare	&sensor_dev_attr_in2_alarm.dev_attr.attr,
1623681c6f7a6702f208d48b501c8829dbc03a2ca238Mark M. Hoffman	&sensor_dev_attr_in3_input.dev_attr.attr,
1624681c6f7a6702f208d48b501c8829dbc03a2ca238Mark M. Hoffman	&sensor_dev_attr_in3_max.dev_attr.attr,
1625681c6f7a6702f208d48b501c8829dbc03a2ca238Mark M. Hoffman	&sensor_dev_attr_in3_min.dev_attr.attr,
1626a9273cb8eea503f6b8e28bd5f613962ecba278c5Jean Delvare	&sensor_dev_attr_in3_alarm.dev_attr.attr,
1627681c6f7a6702f208d48b501c8829dbc03a2ca238Mark M. Hoffman	&sensor_dev_attr_in4_input.dev_attr.attr,
1628681c6f7a6702f208d48b501c8829dbc03a2ca238Mark M. Hoffman	&sensor_dev_attr_in4_max.dev_attr.attr,
1629681c6f7a6702f208d48b501c8829dbc03a2ca238Mark M. Hoffman	&sensor_dev_attr_in4_min.dev_attr.attr,
1630a9273cb8eea503f6b8e28bd5f613962ecba278c5Jean Delvare	&sensor_dev_attr_in4_alarm.dev_attr.attr,
1631681c6f7a6702f208d48b501c8829dbc03a2ca238Mark M. Hoffman	&sensor_dev_attr_in5_input.dev_attr.attr,
1632681c6f7a6702f208d48b501c8829dbc03a2ca238Mark M. Hoffman	&sensor_dev_attr_in5_max.dev_attr.attr,
1633681c6f7a6702f208d48b501c8829dbc03a2ca238Mark M. Hoffman	&sensor_dev_attr_in5_min.dev_attr.attr,
1634a9273cb8eea503f6b8e28bd5f613962ecba278c5Jean Delvare	&sensor_dev_attr_in5_alarm.dev_attr.attr,
1635681c6f7a6702f208d48b501c8829dbc03a2ca238Mark M. Hoffman	&sensor_dev_attr_in6_input.dev_attr.attr,
1636681c6f7a6702f208d48b501c8829dbc03a2ca238Mark M. Hoffman	&sensor_dev_attr_in6_max.dev_attr.attr,
1637681c6f7a6702f208d48b501c8829dbc03a2ca238Mark M. Hoffman	&sensor_dev_attr_in6_min.dev_attr.attr,
1638a9273cb8eea503f6b8e28bd5f613962ecba278c5Jean Delvare	&sensor_dev_attr_in6_alarm.dev_attr.attr,
1639681c6f7a6702f208d48b501c8829dbc03a2ca238Mark M. Hoffman	&sensor_dev_attr_in7_input.dev_attr.attr,
1640681c6f7a6702f208d48b501c8829dbc03a2ca238Mark M. Hoffman	&sensor_dev_attr_in7_max.dev_attr.attr,
1641681c6f7a6702f208d48b501c8829dbc03a2ca238Mark M. Hoffman	&sensor_dev_attr_in7_min.dev_attr.attr,
1642a9273cb8eea503f6b8e28bd5f613962ecba278c5Jean Delvare	&sensor_dev_attr_in7_alarm.dev_attr.attr,
1643681c6f7a6702f208d48b501c8829dbc03a2ca238Mark M. Hoffman	&sensor_dev_attr_in10_input.dev_attr.attr,
1644681c6f7a6702f208d48b501c8829dbc03a2ca238Mark M. Hoffman	&sensor_dev_attr_in10_max.dev_attr.attr,
1645681c6f7a6702f208d48b501c8829dbc03a2ca238Mark M. Hoffman	&sensor_dev_attr_in10_min.dev_attr.attr,
1646a9273cb8eea503f6b8e28bd5f613962ecba278c5Jean Delvare	&sensor_dev_attr_in10_alarm.dev_attr.attr,
1647681c6f7a6702f208d48b501c8829dbc03a2ca238Mark M. Hoffman	&sensor_dev_attr_in11_input.dev_attr.attr,
1648681c6f7a6702f208d48b501c8829dbc03a2ca238Mark M. Hoffman	&sensor_dev_attr_in11_max.dev_attr.attr,
1649681c6f7a6702f208d48b501c8829dbc03a2ca238Mark M. Hoffman	&sensor_dev_attr_in11_min.dev_attr.attr,
1650a9273cb8eea503f6b8e28bd5f613962ecba278c5Jean Delvare	&sensor_dev_attr_in11_alarm.dev_attr.attr,
1651681c6f7a6702f208d48b501c8829dbc03a2ca238Mark M. Hoffman	&sensor_dev_attr_in12_input.dev_attr.attr,
1652681c6f7a6702f208d48b501c8829dbc03a2ca238Mark M. Hoffman	&sensor_dev_attr_in12_max.dev_attr.attr,
1653681c6f7a6702f208d48b501c8829dbc03a2ca238Mark M. Hoffman	&sensor_dev_attr_in12_min.dev_attr.attr,
1654a9273cb8eea503f6b8e28bd5f613962ecba278c5Jean Delvare	&sensor_dev_attr_in12_alarm.dev_attr.attr,
1655681c6f7a6702f208d48b501c8829dbc03a2ca238Mark M. Hoffman	&sensor_dev_attr_in13_input.dev_attr.attr,
1656681c6f7a6702f208d48b501c8829dbc03a2ca238Mark M. Hoffman	&sensor_dev_attr_in13_max.dev_attr.attr,
1657681c6f7a6702f208d48b501c8829dbc03a2ca238Mark M. Hoffman	&sensor_dev_attr_in13_min.dev_attr.attr,
1658a9273cb8eea503f6b8e28bd5f613962ecba278c5Jean Delvare	&sensor_dev_attr_in13_alarm.dev_attr.attr,
1659681c6f7a6702f208d48b501c8829dbc03a2ca238Mark M. Hoffman	&sensor_dev_attr_in14_input.dev_attr.attr,
1660681c6f7a6702f208d48b501c8829dbc03a2ca238Mark M. Hoffman	&sensor_dev_attr_in14_max.dev_attr.attr,
1661681c6f7a6702f208d48b501c8829dbc03a2ca238Mark M. Hoffman	&sensor_dev_attr_in14_min.dev_attr.attr,
1662a9273cb8eea503f6b8e28bd5f613962ecba278c5Jean Delvare	&sensor_dev_attr_in14_alarm.dev_attr.attr,
1663681c6f7a6702f208d48b501c8829dbc03a2ca238Mark M. Hoffman	&sensor_dev_attr_in15_input.dev_attr.attr,
1664681c6f7a6702f208d48b501c8829dbc03a2ca238Mark M. Hoffman	&sensor_dev_attr_in15_max.dev_attr.attr,
1665681c6f7a6702f208d48b501c8829dbc03a2ca238Mark M. Hoffman	&sensor_dev_attr_in15_min.dev_attr.attr,
1666a9273cb8eea503f6b8e28bd5f613962ecba278c5Jean Delvare	&sensor_dev_attr_in15_alarm.dev_attr.attr,
1667681c6f7a6702f208d48b501c8829dbc03a2ca238Mark M. Hoffman	&sensor_dev_attr_in16_input.dev_attr.attr,
1668681c6f7a6702f208d48b501c8829dbc03a2ca238Mark M. Hoffman	&sensor_dev_attr_in16_max.dev_attr.attr,
1669681c6f7a6702f208d48b501c8829dbc03a2ca238Mark M. Hoffman	&sensor_dev_attr_in16_min.dev_attr.attr,
1670a9273cb8eea503f6b8e28bd5f613962ecba278c5Jean Delvare	&sensor_dev_attr_in16_alarm.dev_attr.attr,
1671681c6f7a6702f208d48b501c8829dbc03a2ca238Mark M. Hoffman	&sensor_dev_attr_fan1_input.dev_attr.attr,
1672681c6f7a6702f208d48b501c8829dbc03a2ca238Mark M. Hoffman	&sensor_dev_attr_fan1_div.dev_attr.attr,
1673681c6f7a6702f208d48b501c8829dbc03a2ca238Mark M. Hoffman	&sensor_dev_attr_fan1_min.dev_attr.attr,
1674a9273cb8eea503f6b8e28bd5f613962ecba278c5Jean Delvare	&sensor_dev_attr_fan1_alarm.dev_attr.attr,
1675681c6f7a6702f208d48b501c8829dbc03a2ca238Mark M. Hoffman	&sensor_dev_attr_fan2_input.dev_attr.attr,
1676681c6f7a6702f208d48b501c8829dbc03a2ca238Mark M. Hoffman	&sensor_dev_attr_fan2_div.dev_attr.attr,
1677681c6f7a6702f208d48b501c8829dbc03a2ca238Mark M. Hoffman	&sensor_dev_attr_fan2_min.dev_attr.attr,
1678a9273cb8eea503f6b8e28bd5f613962ecba278c5Jean Delvare	&sensor_dev_attr_fan2_alarm.dev_attr.attr,
1679681c6f7a6702f208d48b501c8829dbc03a2ca238Mark M. Hoffman	&sensor_dev_attr_fan3_input.dev_attr.attr,
1680681c6f7a6702f208d48b501c8829dbc03a2ca238Mark M. Hoffman	&sensor_dev_attr_fan3_div.dev_attr.attr,
1681681c6f7a6702f208d48b501c8829dbc03a2ca238Mark M. Hoffman	&sensor_dev_attr_fan3_min.dev_attr.attr,
1682a9273cb8eea503f6b8e28bd5f613962ecba278c5Jean Delvare	&sensor_dev_attr_fan3_alarm.dev_attr.attr,
1683681c6f7a6702f208d48b501c8829dbc03a2ca238Mark M. Hoffman	&sensor_dev_attr_fan4_input.dev_attr.attr,
1684681c6f7a6702f208d48b501c8829dbc03a2ca238Mark M. Hoffman	&sensor_dev_attr_fan4_div.dev_attr.attr,
1685681c6f7a6702f208d48b501c8829dbc03a2ca238Mark M. Hoffman	&sensor_dev_attr_fan4_min.dev_attr.attr,
1686a9273cb8eea503f6b8e28bd5f613962ecba278c5Jean Delvare	&sensor_dev_attr_fan4_alarm.dev_attr.attr,
1687681c6f7a6702f208d48b501c8829dbc03a2ca238Mark M. Hoffman	&sensor_dev_attr_fan5_input.dev_attr.attr,
1688681c6f7a6702f208d48b501c8829dbc03a2ca238Mark M. Hoffman	&sensor_dev_attr_fan5_div.dev_attr.attr,
1689681c6f7a6702f208d48b501c8829dbc03a2ca238Mark M. Hoffman	&sensor_dev_attr_fan5_min.dev_attr.attr,
1690a9273cb8eea503f6b8e28bd5f613962ecba278c5Jean Delvare	&sensor_dev_attr_fan5_alarm.dev_attr.attr,
1691681c6f7a6702f208d48b501c8829dbc03a2ca238Mark M. Hoffman	&sensor_dev_attr_fan6_input.dev_attr.attr,
1692681c6f7a6702f208d48b501c8829dbc03a2ca238Mark M. Hoffman	&sensor_dev_attr_fan6_div.dev_attr.attr,
1693681c6f7a6702f208d48b501c8829dbc03a2ca238Mark M. Hoffman	&sensor_dev_attr_fan6_min.dev_attr.attr,
1694a9273cb8eea503f6b8e28bd5f613962ecba278c5Jean Delvare	&sensor_dev_attr_fan6_alarm.dev_attr.attr,
1695681c6f7a6702f208d48b501c8829dbc03a2ca238Mark M. Hoffman	&sensor_dev_attr_fan7_input.dev_attr.attr,
1696681c6f7a6702f208d48b501c8829dbc03a2ca238Mark M. Hoffman	&sensor_dev_attr_fan7_div.dev_attr.attr,
1697681c6f7a6702f208d48b501c8829dbc03a2ca238Mark M. Hoffman	&sensor_dev_attr_fan7_min.dev_attr.attr,
1698a9273cb8eea503f6b8e28bd5f613962ecba278c5Jean Delvare	&sensor_dev_attr_fan7_alarm.dev_attr.attr,
1699681c6f7a6702f208d48b501c8829dbc03a2ca238Mark M. Hoffman	&sensor_dev_attr_fan8_input.dev_attr.attr,
1700681c6f7a6702f208d48b501c8829dbc03a2ca238Mark M. Hoffman	&sensor_dev_attr_fan8_div.dev_attr.attr,
1701681c6f7a6702f208d48b501c8829dbc03a2ca238Mark M. Hoffman	&sensor_dev_attr_fan8_min.dev_attr.attr,
1702a9273cb8eea503f6b8e28bd5f613962ecba278c5Jean Delvare	&sensor_dev_attr_fan8_alarm.dev_attr.attr,
1703681c6f7a6702f208d48b501c8829dbc03a2ca238Mark M. Hoffman	&sensor_dev_attr_temp1_input.dev_attr.attr,
1704681c6f7a6702f208d48b501c8829dbc03a2ca238Mark M. Hoffman	&sensor_dev_attr_temp1_max.dev_attr.attr,
1705681c6f7a6702f208d48b501c8829dbc03a2ca238Mark M. Hoffman	&sensor_dev_attr_temp1_min.dev_attr.attr,
1706a9273cb8eea503f6b8e28bd5f613962ecba278c5Jean Delvare	&sensor_dev_attr_temp1_alarm.dev_attr.attr,
1707681c6f7a6702f208d48b501c8829dbc03a2ca238Mark M. Hoffman	&sensor_dev_attr_temp2_input.dev_attr.attr,
1708681c6f7a6702f208d48b501c8829dbc03a2ca238Mark M. Hoffman	&sensor_dev_attr_temp2_max.dev_attr.attr,
1709681c6f7a6702f208d48b501c8829dbc03a2ca238Mark M. Hoffman	&sensor_dev_attr_temp2_min.dev_attr.attr,
1710a9273cb8eea503f6b8e28bd5f613962ecba278c5Jean Delvare	&sensor_dev_attr_temp2_alarm.dev_attr.attr,
1711681c6f7a6702f208d48b501c8829dbc03a2ca238Mark M. Hoffman	&sensor_dev_attr_temp1_offset.dev_attr.attr,
1712681c6f7a6702f208d48b501c8829dbc03a2ca238Mark M. Hoffman	&sensor_dev_attr_temp2_offset.dev_attr.attr,
1713681c6f7a6702f208d48b501c8829dbc03a2ca238Mark M. Hoffman	&sensor_dev_attr_temp1_auto_point1_temp.dev_attr.attr,
1714681c6f7a6702f208d48b501c8829dbc03a2ca238Mark M. Hoffman	&sensor_dev_attr_temp2_auto_point1_temp.dev_attr.attr,
1715681c6f7a6702f208d48b501c8829dbc03a2ca238Mark M. Hoffman	&sensor_dev_attr_temp1_auto_point1_temp_hyst.dev_attr.attr,
1716681c6f7a6702f208d48b501c8829dbc03a2ca238Mark M. Hoffman	&sensor_dev_attr_temp2_auto_point1_temp_hyst.dev_attr.attr,
1717681c6f7a6702f208d48b501c8829dbc03a2ca238Mark M. Hoffman	&sensor_dev_attr_temp1_auto_point2_temp.dev_attr.attr,
1718681c6f7a6702f208d48b501c8829dbc03a2ca238Mark M. Hoffman	&sensor_dev_attr_temp2_auto_point2_temp.dev_attr.attr,
1719681c6f7a6702f208d48b501c8829dbc03a2ca238Mark M. Hoffman	&sensor_dev_attr_temp1_crit.dev_attr.attr,
1720681c6f7a6702f208d48b501c8829dbc03a2ca238Mark M. Hoffman	&sensor_dev_attr_temp2_crit.dev_attr.attr,
1721681c6f7a6702f208d48b501c8829dbc03a2ca238Mark M. Hoffman	&dev_attr_temp1_crit_enable.attr,
1722681c6f7a6702f208d48b501c8829dbc03a2ca238Mark M. Hoffman	&dev_attr_temp2_crit_enable.attr,
1723681c6f7a6702f208d48b501c8829dbc03a2ca238Mark M. Hoffman	&dev_attr_cpu0_vid.attr,
1724681c6f7a6702f208d48b501c8829dbc03a2ca238Mark M. Hoffman	&dev_attr_vrm.attr,
1725681c6f7a6702f208d48b501c8829dbc03a2ca238Mark M. Hoffman	&dev_attr_alarms.attr,
1726681c6f7a6702f208d48b501c8829dbc03a2ca238Mark M. Hoffman	&dev_attr_alarm_mask.attr,
1727681c6f7a6702f208d48b501c8829dbc03a2ca238Mark M. Hoffman	&dev_attr_gpio.attr,
1728681c6f7a6702f208d48b501c8829dbc03a2ca238Mark M. Hoffman	&dev_attr_gpio_mask.attr,
1729681c6f7a6702f208d48b501c8829dbc03a2ca238Mark M. Hoffman	&dev_attr_pwm1.attr,
1730681c6f7a6702f208d48b501c8829dbc03a2ca238Mark M. Hoffman	&dev_attr_pwm2.attr,
1731681c6f7a6702f208d48b501c8829dbc03a2ca238Mark M. Hoffman	&dev_attr_pwm3.attr,
1732681c6f7a6702f208d48b501c8829dbc03a2ca238Mark M. Hoffman	&dev_attr_pwm1_enable.attr,
1733681c6f7a6702f208d48b501c8829dbc03a2ca238Mark M. Hoffman	&dev_attr_pwm2_enable.attr,
1734681c6f7a6702f208d48b501c8829dbc03a2ca238Mark M. Hoffman	&dev_attr_pwm3_enable.attr,
1735681c6f7a6702f208d48b501c8829dbc03a2ca238Mark M. Hoffman	&dev_attr_temp1_auto_point1_pwm.attr,
1736681c6f7a6702f208d48b501c8829dbc03a2ca238Mark M. Hoffman	&dev_attr_temp2_auto_point1_pwm.attr,
1737681c6f7a6702f208d48b501c8829dbc03a2ca238Mark M. Hoffman	&dev_attr_temp1_auto_point2_pwm.attr,
1738681c6f7a6702f208d48b501c8829dbc03a2ca238Mark M. Hoffman	&dev_attr_temp2_auto_point2_pwm.attr,
1739681c6f7a6702f208d48b501c8829dbc03a2ca238Mark M. Hoffman	&dev_attr_analog_out.attr,
1740681c6f7a6702f208d48b501c8829dbc03a2ca238Mark M. Hoffman	NULL
1741681c6f7a6702f208d48b501c8829dbc03a2ca238Mark M. Hoffman};
1742681c6f7a6702f208d48b501c8829dbc03a2ca238Mark M. Hoffman
1743681c6f7a6702f208d48b501c8829dbc03a2ca238Mark M. Hoffmanstatic const struct attribute_group adm1026_group = {
1744681c6f7a6702f208d48b501c8829dbc03a2ca238Mark M. Hoffman	.attrs = adm1026_attributes,
1745681c6f7a6702f208d48b501c8829dbc03a2ca238Mark M. Hoffman};
1746681c6f7a6702f208d48b501c8829dbc03a2ca238Mark M. Hoffman
17475b34dbcd88251508d02e48ad9b0f9b8232a13ee0Jean Delvarestatic struct attribute *adm1026_attributes_temp3[] = {
17485b34dbcd88251508d02e48ad9b0f9b8232a13ee0Jean Delvare	&sensor_dev_attr_temp3_input.dev_attr.attr,
17495b34dbcd88251508d02e48ad9b0f9b8232a13ee0Jean Delvare	&sensor_dev_attr_temp3_max.dev_attr.attr,
17505b34dbcd88251508d02e48ad9b0f9b8232a13ee0Jean Delvare	&sensor_dev_attr_temp3_min.dev_attr.attr,
17515b34dbcd88251508d02e48ad9b0f9b8232a13ee0Jean Delvare	&sensor_dev_attr_temp3_alarm.dev_attr.attr,
17525b34dbcd88251508d02e48ad9b0f9b8232a13ee0Jean Delvare	&sensor_dev_attr_temp3_offset.dev_attr.attr,
17535b34dbcd88251508d02e48ad9b0f9b8232a13ee0Jean Delvare	&sensor_dev_attr_temp3_auto_point1_temp.dev_attr.attr,
17545b34dbcd88251508d02e48ad9b0f9b8232a13ee0Jean Delvare	&sensor_dev_attr_temp3_auto_point1_temp_hyst.dev_attr.attr,
17555b34dbcd88251508d02e48ad9b0f9b8232a13ee0Jean Delvare	&sensor_dev_attr_temp3_auto_point2_temp.dev_attr.attr,
17565b34dbcd88251508d02e48ad9b0f9b8232a13ee0Jean Delvare	&sensor_dev_attr_temp3_crit.dev_attr.attr,
17575b34dbcd88251508d02e48ad9b0f9b8232a13ee0Jean Delvare	&dev_attr_temp3_crit_enable.attr,
17585b34dbcd88251508d02e48ad9b0f9b8232a13ee0Jean Delvare	&dev_attr_temp3_auto_point1_pwm.attr,
17595b34dbcd88251508d02e48ad9b0f9b8232a13ee0Jean Delvare	&dev_attr_temp3_auto_point2_pwm.attr,
17601d5f2c16c6125ae6da1435ac5a190ae08429902aJean Delvare	NULL
17615b34dbcd88251508d02e48ad9b0f9b8232a13ee0Jean Delvare};
17625b34dbcd88251508d02e48ad9b0f9b8232a13ee0Jean Delvare
17635b34dbcd88251508d02e48ad9b0f9b8232a13ee0Jean Delvarestatic const struct attribute_group adm1026_group_temp3 = {
17645b34dbcd88251508d02e48ad9b0f9b8232a13ee0Jean Delvare	.attrs = adm1026_attributes_temp3,
17655b34dbcd88251508d02e48ad9b0f9b8232a13ee0Jean Delvare};
17665b34dbcd88251508d02e48ad9b0f9b8232a13ee0Jean Delvare
17675b34dbcd88251508d02e48ad9b0f9b8232a13ee0Jean Delvarestatic struct attribute *adm1026_attributes_in8_9[] = {
17685b34dbcd88251508d02e48ad9b0f9b8232a13ee0Jean Delvare	&sensor_dev_attr_in8_input.dev_attr.attr,
17695b34dbcd88251508d02e48ad9b0f9b8232a13ee0Jean Delvare	&sensor_dev_attr_in8_max.dev_attr.attr,
17705b34dbcd88251508d02e48ad9b0f9b8232a13ee0Jean Delvare	&sensor_dev_attr_in8_min.dev_attr.attr,
17715b34dbcd88251508d02e48ad9b0f9b8232a13ee0Jean Delvare	&sensor_dev_attr_in8_alarm.dev_attr.attr,
17725b34dbcd88251508d02e48ad9b0f9b8232a13ee0Jean Delvare	&sensor_dev_attr_in9_input.dev_attr.attr,
17735b34dbcd88251508d02e48ad9b0f9b8232a13ee0Jean Delvare	&sensor_dev_attr_in9_max.dev_attr.attr,
17745b34dbcd88251508d02e48ad9b0f9b8232a13ee0Jean Delvare	&sensor_dev_attr_in9_min.dev_attr.attr,
17755b34dbcd88251508d02e48ad9b0f9b8232a13ee0Jean Delvare	&sensor_dev_attr_in9_alarm.dev_attr.attr,
17761d5f2c16c6125ae6da1435ac5a190ae08429902aJean Delvare	NULL
17775b34dbcd88251508d02e48ad9b0f9b8232a13ee0Jean Delvare};
17785b34dbcd88251508d02e48ad9b0f9b8232a13ee0Jean Delvare
17795b34dbcd88251508d02e48ad9b0f9b8232a13ee0Jean Delvarestatic const struct attribute_group adm1026_group_in8_9 = {
17805b34dbcd88251508d02e48ad9b0f9b8232a13ee0Jean Delvare	.attrs = adm1026_attributes_in8_9,
17815b34dbcd88251508d02e48ad9b0f9b8232a13ee0Jean Delvare};
17825b34dbcd88251508d02e48ad9b0f9b8232a13ee0Jean Delvare
178357f7eb0bcb2316dc264cd26f38b33dd2cf3151c1Jean Delvare/* Return 0 if detection is successful, -ENODEV otherwise */
1784310ec79210d754afe51e2e4a983e846b60179abdJean Delvarestatic int adm1026_detect(struct i2c_client *client,
178557f7eb0bcb2316dc264cd26f38b33dd2cf3151c1Jean Delvare			  struct i2c_board_info *info)
17861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
178757f7eb0bcb2316dc264cd26f38b33dd2cf3151c1Jean Delvare	struct i2c_adapter *adapter = client->adapter;
178857f7eb0bcb2316dc264cd26f38b33dd2cf3151c1Jean Delvare	int address = client->addr;
17891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int company, verstep;
17901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
17911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA)) {
17921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		/* We need to be able to do byte I/O */
179357f7eb0bcb2316dc264cd26f38b33dd2cf3151c1Jean Delvare		return -ENODEV;
17941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	};
17951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
17961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* Now, we do the remaining detection. */
17971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1798f67fdabfb94b0bb96623a4b48d22be5329a06277Jean Delvare	company = adm1026_read_value(client, ADM1026_REG_COMPANY);
1799f67fdabfb94b0bb96623a4b48d22be5329a06277Jean Delvare	verstep = adm1026_read_value(client, ADM1026_REG_VERSTEP);
18001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
180157f7eb0bcb2316dc264cd26f38b33dd2cf3151c1Jean Delvare	dev_dbg(&adapter->dev, "Detecting device at %d,0x%02x with"
18021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		" COMPANY: 0x%02x and VERSTEP: 0x%02x\n",
1803f67fdabfb94b0bb96623a4b48d22be5329a06277Jean Delvare		i2c_adapter_id(client->adapter), client->addr,
18041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		company, verstep);
18051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
180652df6440a29123eed912183fe785bbe174ef14b9Jean Delvare	/* Determine the chip type. */
180752df6440a29123eed912183fe785bbe174ef14b9Jean Delvare	dev_dbg(&adapter->dev, "Autodetecting device at %d,0x%02x...\n",
180852df6440a29123eed912183fe785bbe174ef14b9Jean Delvare		i2c_adapter_id(adapter), address);
180952df6440a29123eed912183fe785bbe174ef14b9Jean Delvare	if (company == ADM1026_COMPANY_ANALOG_DEV
181052df6440a29123eed912183fe785bbe174ef14b9Jean Delvare	    && verstep == ADM1026_VERSTEP_ADM1026) {
181152df6440a29123eed912183fe785bbe174ef14b9Jean Delvare		/* Analog Devices ADM1026 */
181252df6440a29123eed912183fe785bbe174ef14b9Jean Delvare	} else if (company == ADM1026_COMPANY_ANALOG_DEV
181352df6440a29123eed912183fe785bbe174ef14b9Jean Delvare		&& (verstep & 0xf0) == ADM1026_VERSTEP_GENERIC) {
181452df6440a29123eed912183fe785bbe174ef14b9Jean Delvare		dev_err(&adapter->dev, "Unrecognized stepping "
181552df6440a29123eed912183fe785bbe174ef14b9Jean Delvare			"0x%02x. Defaulting to ADM1026.\n", verstep);
181652df6440a29123eed912183fe785bbe174ef14b9Jean Delvare	} else if ((verstep & 0xf0) == ADM1026_VERSTEP_GENERIC) {
181752df6440a29123eed912183fe785bbe174ef14b9Jean Delvare		dev_err(&adapter->dev, "Found version/stepping "
181852df6440a29123eed912183fe785bbe174ef14b9Jean Delvare			"0x%02x. Assuming generic ADM1026.\n",
181952df6440a29123eed912183fe785bbe174ef14b9Jean Delvare			verstep);
182052df6440a29123eed912183fe785bbe174ef14b9Jean Delvare	} else {
182152df6440a29123eed912183fe785bbe174ef14b9Jean Delvare		dev_dbg(&adapter->dev, "Autodetection failed\n");
182252df6440a29123eed912183fe785bbe174ef14b9Jean Delvare		/* Not an ADM1026... */
182352df6440a29123eed912183fe785bbe174ef14b9Jean Delvare		return -ENODEV;
18241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
182552df6440a29123eed912183fe785bbe174ef14b9Jean Delvare
182657f7eb0bcb2316dc264cd26f38b33dd2cf3151c1Jean Delvare	strlcpy(info->type, "adm1026", I2C_NAME_SIZE);
18271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
182857f7eb0bcb2316dc264cd26f38b33dd2cf3151c1Jean Delvare	return 0;
182957f7eb0bcb2316dc264cd26f38b33dd2cf3151c1Jean Delvare}
183057f7eb0bcb2316dc264cd26f38b33dd2cf3151c1Jean Delvare
183157f7eb0bcb2316dc264cd26f38b33dd2cf3151c1Jean Delvarestatic int adm1026_probe(struct i2c_client *client,
183257f7eb0bcb2316dc264cd26f38b33dd2cf3151c1Jean Delvare			 const struct i2c_device_id *id)
183357f7eb0bcb2316dc264cd26f38b33dd2cf3151c1Jean Delvare{
183457f7eb0bcb2316dc264cd26f38b33dd2cf3151c1Jean Delvare	struct adm1026_data *data;
183557f7eb0bcb2316dc264cd26f38b33dd2cf3151c1Jean Delvare	int err;
183657f7eb0bcb2316dc264cd26f38b33dd2cf3151c1Jean Delvare
183757f7eb0bcb2316dc264cd26f38b33dd2cf3151c1Jean Delvare	data = kzalloc(sizeof(struct adm1026_data), GFP_KERNEL);
183857f7eb0bcb2316dc264cd26f38b33dd2cf3151c1Jean Delvare	if (!data) {
183957f7eb0bcb2316dc264cd26f38b33dd2cf3151c1Jean Delvare		err = -ENOMEM;
184057f7eb0bcb2316dc264cd26f38b33dd2cf3151c1Jean Delvare		goto exit;
18411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
18421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
184357f7eb0bcb2316dc264cd26f38b33dd2cf3151c1Jean Delvare	i2c_set_clientdata(client, data);
18449a61bf6300533d3b64d7ff29adfec00e596de67dIngo Molnar	mutex_init(&data->update_lock);
18451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
18461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* Set the VRM version */
1847303760b44a7a142cb9f4c9df4609fb63bbda98dbJean Delvare	data->vrm = vid_which_vrm();
18481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
18491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* Initialize the ADM1026 chip */
1850f67fdabfb94b0bb96623a4b48d22be5329a06277Jean Delvare	adm1026_init_client(client);
18511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
18521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* Register sysfs hooks */
185386aa3e22106be3d6338113ff5acd7a87c40056c4Guenter Roeck	err = sysfs_create_group(&client->dev.kobj, &adm1026_group);
185486aa3e22106be3d6338113ff5acd7a87c40056c4Guenter Roeck	if (err)
185557f7eb0bcb2316dc264cd26f38b33dd2cf3151c1Jean Delvare		goto exitfree;
18565b34dbcd88251508d02e48ad9b0f9b8232a13ee0Jean Delvare	if (data->config1 & CFG1_AIN8_9)
18575b34dbcd88251508d02e48ad9b0f9b8232a13ee0Jean Delvare		err = sysfs_create_group(&client->dev.kobj,
18585b34dbcd88251508d02e48ad9b0f9b8232a13ee0Jean Delvare					 &adm1026_group_in8_9);
18595b34dbcd88251508d02e48ad9b0f9b8232a13ee0Jean Delvare	else
18605b34dbcd88251508d02e48ad9b0f9b8232a13ee0Jean Delvare		err = sysfs_create_group(&client->dev.kobj,
18615b34dbcd88251508d02e48ad9b0f9b8232a13ee0Jean Delvare					 &adm1026_group_temp3);
18625b34dbcd88251508d02e48ad9b0f9b8232a13ee0Jean Delvare	if (err)
18635b34dbcd88251508d02e48ad9b0f9b8232a13ee0Jean Delvare		goto exitremove;
1864681c6f7a6702f208d48b501c8829dbc03a2ca238Mark M. Hoffman
1865f67fdabfb94b0bb96623a4b48d22be5329a06277Jean Delvare	data->hwmon_dev = hwmon_device_register(&client->dev);
18661beeffe43311f64df8dd0ab08ff6b1858c58363fTony Jones	if (IS_ERR(data->hwmon_dev)) {
18671beeffe43311f64df8dd0ab08ff6b1858c58363fTony Jones		err = PTR_ERR(data->hwmon_dev);
1868681c6f7a6702f208d48b501c8829dbc03a2ca238Mark M. Hoffman		goto exitremove;
1869943b0830cebe4711354945ed3cb44e84152aaca0Mark M. Hoffman	}
1870943b0830cebe4711354945ed3cb44e84152aaca0Mark M. Hoffman
18711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return 0;
18721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
18731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* Error out and cleanup code */
1874681c6f7a6702f208d48b501c8829dbc03a2ca238Mark M. Hoffmanexitremove:
1875f67fdabfb94b0bb96623a4b48d22be5329a06277Jean Delvare	sysfs_remove_group(&client->dev.kobj, &adm1026_group);
18765b34dbcd88251508d02e48ad9b0f9b8232a13ee0Jean Delvare	if (data->config1 & CFG1_AIN8_9)
18775b34dbcd88251508d02e48ad9b0f9b8232a13ee0Jean Delvare		sysfs_remove_group(&client->dev.kobj, &adm1026_group_in8_9);
18785b34dbcd88251508d02e48ad9b0f9b8232a13ee0Jean Delvare	else
18795b34dbcd88251508d02e48ad9b0f9b8232a13ee0Jean Delvare		sysfs_remove_group(&client->dev.kobj, &adm1026_group_temp3);
18801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsexitfree:
18811f57ff89fee47a317e9e8ca63bf0f139802cc116Alexey Dobriyan	kfree(data);
18821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsexit:
18831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return err;
18841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
1885681c6f7a6702f208d48b501c8829dbc03a2ca238Mark M. Hoffman
188657f7eb0bcb2316dc264cd26f38b33dd2cf3151c1Jean Delvarestatic int adm1026_remove(struct i2c_client *client)
1887681c6f7a6702f208d48b501c8829dbc03a2ca238Mark M. Hoffman{
1888681c6f7a6702f208d48b501c8829dbc03a2ca238Mark M. Hoffman	struct adm1026_data *data = i2c_get_clientdata(client);
18891beeffe43311f64df8dd0ab08ff6b1858c58363fTony Jones	hwmon_device_unregister(data->hwmon_dev);
1890681c6f7a6702f208d48b501c8829dbc03a2ca238Mark M. Hoffman	sysfs_remove_group(&client->dev.kobj, &adm1026_group);
18915b34dbcd88251508d02e48ad9b0f9b8232a13ee0Jean Delvare	if (data->config1 & CFG1_AIN8_9)
18925b34dbcd88251508d02e48ad9b0f9b8232a13ee0Jean Delvare		sysfs_remove_group(&client->dev.kobj, &adm1026_group_in8_9);
18935b34dbcd88251508d02e48ad9b0f9b8232a13ee0Jean Delvare	else
18945b34dbcd88251508d02e48ad9b0f9b8232a13ee0Jean Delvare		sysfs_remove_group(&client->dev.kobj, &adm1026_group_temp3);
1895681c6f7a6702f208d48b501c8829dbc03a2ca238Mark M. Hoffman	kfree(data);
1896681c6f7a6702f208d48b501c8829dbc03a2ca238Mark M. Hoffman	return 0;
1897681c6f7a6702f208d48b501c8829dbc03a2ca238Mark M. Hoffman}
1898681c6f7a6702f208d48b501c8829dbc03a2ca238Mark M. Hoffman
1899f0967eea80ec2a19a4fe1ad27e3ff1b22c79a3c7Axel Linmodule_i2c_driver(adm1026_driver);
19001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
19011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsMODULE_LICENSE("GPL");
19021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsMODULE_AUTHOR("Philip Pokorny <ppokorny@penguincomputing.com>, "
1903cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvare	      "Justin Thiessen <jthiessen@penguincomputing.com>");
19041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsMODULE_DESCRIPTION("ADM1026 driver");
1905