adm1026.c revision 52df6440a29123eed912183fe785bbe174ef14b9
11da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*
21da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds    adm1026.c - Part of lm_sensors, Linux kernel modules for hardware
31da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	     monitoring
41da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds    Copyright (C) 2002, 2003  Philip Pokorny <ppokorny@penguincomputing.com>
51da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds    Copyright (C) 2004 Justin Thiessen <jthiessen@penguincomputing.com>
61da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
71da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds    Chip details at:
81da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
91da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds    <http://www.analog.com/UploadedFiles/Data_Sheets/779263102ADM1026_a.pdf>
101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds    This program is free software; you can redistribute it and/or modify
121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds    it under the terms of the GNU General Public License as published by
131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds    the Free Software Foundation; either version 2 of the License, or
141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds    (at your option) any later version.
151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds    This program is distributed in the hope that it will be useful,
171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds    but WITHOUT ANY WARRANTY; without even the implied warranty of
181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds    GNU General Public License for more details.
201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds    You should have received a copy of the GNU General Public License
221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds    along with this program; if not, write to the Free Software
231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds*/
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
401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* Insmod parameters */
41f4b50261207c987913f076d867c2e154d71fd012Jean DelvareI2C_CLIENT_INSMOD_1(adm1026);
421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
43cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvarestatic int gpio_input[17] = { -1, -1, -1, -1, -1, -1, -1, -1, -1,
44cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvare				-1, -1, -1, -1, -1, -1, -1, -1 };
451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int gpio_output[17] = { -1, -1, -1, -1, -1, -1, -1, -1, -1,
461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				-1, -1, -1, -1, -1, -1, -1, -1 };
471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int gpio_inverted[17] = { -1, -1, -1, -1, -1, -1, -1, -1, -1,
481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				-1, -1, -1, -1, -1, -1, -1, -1 };
491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int gpio_normal[17] = { -1, -1, -1, -1, -1, -1, -1, -1, -1,
501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				-1, -1, -1, -1, -1, -1, -1, -1 };
511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int gpio_fan[8] = { -1, -1, -1, -1, -1, -1, -1, -1 };
52cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvaremodule_param_array(gpio_input, int, NULL, 0);
53cb01a2312f56c93d2740e827718966b92b7cbb91Jean DelvareMODULE_PARM_DESC(gpio_input, "List of GPIO pins (0-16) to program as inputs");
54cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvaremodule_param_array(gpio_output, int, NULL, 0);
55cb01a2312f56c93d2740e827718966b92b7cbb91Jean DelvareMODULE_PARM_DESC(gpio_output, "List of GPIO pins (0-16) to program as "
561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	"outputs");
57cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvaremodule_param_array(gpio_inverted, int, NULL, 0);
58cb01a2312f56c93d2740e827718966b92b7cbb91Jean DelvareMODULE_PARM_DESC(gpio_inverted, "List of GPIO pins (0-16) to program as "
591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	"inverted");
60cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvaremodule_param_array(gpio_normal, int, NULL, 0);
61cb01a2312f56c93d2740e827718966b92b7cbb91Jean DelvareMODULE_PARM_DESC(gpio_normal, "List of GPIO pins (0-16) to program as "
621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	"normal/non-inverted");
63cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvaremodule_param_array(gpio_fan, int, NULL, 0);
64cb01a2312f56c93d2740e827718966b92b7cbb91Jean DelvareMODULE_PARM_DESC(gpio_fan, "List of GPIO pins (0-7) to program as fan tachs");
651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* Many ADM1026 constants specified below */
671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* The ADM1026 registers */
69cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvare#define ADM1026_REG_CONFIG1	0x00
70cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvare#define CFG1_MONITOR		0x01
71cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvare#define CFG1_INT_ENABLE		0x02
72cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvare#define CFG1_INT_CLEAR		0x04
73cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvare#define CFG1_AIN8_9		0x08
74cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvare#define CFG1_THERM_HOT		0x10
75cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvare#define CFG1_DAC_AFC		0x20
76cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvare#define CFG1_PWM_AFC		0x40
77cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvare#define CFG1_RESET		0x80
78cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvare
79cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvare#define ADM1026_REG_CONFIG2	0x01
801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* CONFIG2 controls FAN0/GPIO0 through FAN7/GPIO7 */
81cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvare
82cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvare#define ADM1026_REG_CONFIG3	0x07
83cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvare#define CFG3_GPIO16_ENABLE	0x01
84cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvare#define CFG3_CI_CLEAR		0x02
85cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvare#define CFG3_VREF_250		0x04
86cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvare#define CFG3_GPIO16_DIR		0x40
87cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvare#define CFG3_GPIO16_POL		0x80
88cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvare
89cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvare#define ADM1026_REG_E2CONFIG	0x13
90cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvare#define E2CFG_READ		0x01
91cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvare#define E2CFG_WRITE		0x02
92cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvare#define E2CFG_ERASE		0x04
93cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvare#define E2CFG_ROM		0x08
94cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvare#define E2CFG_CLK_EXT		0x80
951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* There are 10 general analog inputs and 7 dedicated inputs
971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * They are:
981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *    0 - 9  =  AIN0 - AIN9
991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *       10  =  Vbat
1001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *       11  =  3.3V Standby
1011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *       12  =  3.3V Main
1021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *       13  =  +5V
1031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *       14  =  Vccp (CPU core voltage)
1041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *       15  =  +12V
1051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *       16  =  -12V
1061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
1071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic u16 ADM1026_REG_IN[] = {
1081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		0x30, 0x31, 0x32, 0x33, 0x34, 0x35,
1091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		0x36, 0x37, 0x27, 0x29, 0x26, 0x2a,
1101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		0x2b, 0x2c, 0x2d, 0x2e, 0x2f
1111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	};
1121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic u16 ADM1026_REG_IN_MIN[] = {
1131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		0x58, 0x59, 0x5a, 0x5b, 0x5c, 0x5d,
1141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		0x5e, 0x5f, 0x6d, 0x49, 0x6b, 0x4a,
1151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		0x4b, 0x4c, 0x4d, 0x4e, 0x4f
1161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	};
1171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic u16 ADM1026_REG_IN_MAX[] = {
1181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		0x50, 0x51, 0x52, 0x53, 0x54, 0x55,
1191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		0x56, 0x57, 0x6c, 0x41, 0x6a, 0x42,
1201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		0x43, 0x44, 0x45, 0x46, 0x47
1211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	};
1221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* Temperatures are:
1241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *    0 - Internal
1251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *    1 - External 1
1261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *    2 - External 2
1271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
1281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic u16 ADM1026_REG_TEMP[] = { 0x1f, 0x28, 0x29 };
1291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic u16 ADM1026_REG_TEMP_MIN[] = { 0x69, 0x48, 0x49 };
1301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic u16 ADM1026_REG_TEMP_MAX[] = { 0x68, 0x40, 0x41 };
1311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic u16 ADM1026_REG_TEMP_TMIN[] = { 0x10, 0x11, 0x12 };
1321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic u16 ADM1026_REG_TEMP_THERM[] = { 0x0d, 0x0e, 0x0f };
1331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic u16 ADM1026_REG_TEMP_OFFSET[] = { 0x1e, 0x6e, 0x6f };
1341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
135cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvare#define ADM1026_REG_FAN(nr)		(0x38 + (nr))
136cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvare#define ADM1026_REG_FAN_MIN(nr)		(0x60 + (nr))
137cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvare#define ADM1026_REG_FAN_DIV_0_3		0x02
138cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvare#define ADM1026_REG_FAN_DIV_4_7		0x03
1391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
140cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvare#define ADM1026_REG_DAC			0x04
141cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvare#define ADM1026_REG_PWM			0x05
1421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
143cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvare#define ADM1026_REG_GPIO_CFG_0_3	0x08
144cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvare#define ADM1026_REG_GPIO_CFG_4_7	0x09
145cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvare#define ADM1026_REG_GPIO_CFG_8_11	0x0a
146cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvare#define ADM1026_REG_GPIO_CFG_12_15	0x0b
1471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* CFG_16 in REG_CFG3 */
148cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvare#define ADM1026_REG_GPIO_STATUS_0_7	0x24
149cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvare#define ADM1026_REG_GPIO_STATUS_8_15	0x25
1501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* STATUS_16 in REG_STATUS4 */
151cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvare#define ADM1026_REG_GPIO_MASK_0_7	0x1c
152cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvare#define ADM1026_REG_GPIO_MASK_8_15	0x1d
1531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* MASK_16 in REG_MASK4 */
1541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
155cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvare#define ADM1026_REG_COMPANY		0x16
156cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvare#define ADM1026_REG_VERSTEP		0x17
1571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* These are the recognized values for the above regs */
158cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvare#define ADM1026_COMPANY_ANALOG_DEV	0x41
159cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvare#define ADM1026_VERSTEP_GENERIC		0x40
160cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvare#define ADM1026_VERSTEP_ADM1026		0x44
1611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
162cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvare#define ADM1026_REG_MASK1		0x18
163cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvare#define ADM1026_REG_MASK2		0x19
164cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvare#define ADM1026_REG_MASK3		0x1a
165cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvare#define ADM1026_REG_MASK4		0x1b
1661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
167cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvare#define ADM1026_REG_STATUS1		0x20
168cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvare#define ADM1026_REG_STATUS2		0x21
169cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvare#define ADM1026_REG_STATUS3		0x22
170cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvare#define ADM1026_REG_STATUS4		0x23
1711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define ADM1026_FAN_ACTIVATION_TEMP_HYST -6
173cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvare#define ADM1026_FAN_CONTROL_TEMP_RANGE	20
174cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvare#define ADM1026_PWM_MAX			255
1751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
176cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvare/* 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
1811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* IN are scaled acording to built-in resistors.  These are the
1821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *   voltages corresponding to 3/4 of full scale (192 or 0xc0)
1831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *   NOTE: The -12V input needs an additional factor to account
1841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *      for the Vref pullup resistor.
1851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *      NEG12_OFFSET = SCALE * Vref / V-192 - Vref
1861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *                   = 13875 * 2.50 / 1.875 - 2500
1871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *                   = 16000
1881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
1891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * The values in this table are based on Table II, page 15 of the
1901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *    datasheet.
1911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
192cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvarestatic int adm1026_scaling[] = { /* .001 Volts */
193cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvare		2250, 2250, 2250, 2250, 2250, 2250,
194cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvare		1875, 1875, 1875, 1875, 3000, 3330,
1951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		3330, 4995, 2250, 12000, 13875
1961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	};
1971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define NEG12_OFFSET  16000
198cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvare#define SCALE(val, from, to) (((val)*(to) + ((from)/2))/(from))
199cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvare#define INS_TO_REG(n, val)  (SENSORS_LIMIT(SCALE(val, adm1026_scaling[n], 192),\
200cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvare	0, 255))
201cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvare#define INS_FROM_REG(n, val) (SCALE(val, 192, adm1026_scaling[n]))
2021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* FAN speed is measured using 22.5kHz clock and counts for 2 pulses
2041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *   and we assume a 2 pulse-per-rev fan tach signal
2051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *      22500 kHz * 60 (sec/min) * 2 (pulse) / 2 (pulse/rev) == 1350000
2061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
207cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvare#define FAN_TO_REG(val, div)  ((val) <= 0 ? 0xff : \
208cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvare				SENSORS_LIMIT(1350000/((val)*(div)), 1, 254))
209cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvare#define FAN_FROM_REG(val, div) ((val) == 0 ? -1:(val) == 0xff ? 0 : \
210cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvare				1350000/((val)*(div)))
2111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define DIV_FROM_REG(val) (1<<(val))
212cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvare#define DIV_TO_REG(val) ((val) >= 8 ? 3 : (val) >= 4 ? 2 : (val) >= 2 ? 1 : 0)
2131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* Temperature is reported in 1 degC increments */
2151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define TEMP_TO_REG(val) (SENSORS_LIMIT(((val)+((val)<0 ? -500 : 500))/1000,\
216cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvare	-127, 127))
2171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define TEMP_FROM_REG(val) ((val) * 1000)
2181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define OFFSET_TO_REG(val) (SENSORS_LIMIT(((val)+((val)<0 ? -500 : 500))/1000,\
219cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvare	-127, 127))
2201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define OFFSET_FROM_REG(val) ((val) * 1000)
2211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
222cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvare#define PWM_TO_REG(val) (SENSORS_LIMIT(val, 0, 255))
2231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define PWM_FROM_REG(val) (val)
2241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define PWM_MIN_TO_REG(val) ((val) & 0xf0)
2261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define PWM_MIN_FROM_REG(val) (((val) & 0xf0) + ((val) >> 4))
2271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
228cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvare/* Analog output is a voltage, and scaled to millivolts.  The datasheet
229cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvare *   indicates that the DAC could be used to drive the fans, but in our
2301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *   example board (Arima HDAMA) it isn't connected to the fans at all.
2311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
232cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvare#define DAC_TO_REG(val) (SENSORS_LIMIT(((((val)*255)+500)/2500), 0, 255))
2331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define DAC_FROM_REG(val) (((val)*2500)/255)
2341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* Chip sampling rates
2361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
2371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Some sensors are not updated more frequently than once per second
2381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *    so it doesn't make sense to read them more often than that.
2391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *    We cache the results and return the saved data if the driver
2401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *    is called again before a second has elapsed.
2411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
2421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Also, there is significant configuration data for this chip
2431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *    So, we keep the config data up to date in the cache
2441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *    when it is written and only sample it once every 5 *minutes*
2451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
246cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvare#define ADM1026_DATA_INTERVAL		(1 * HZ)
247cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvare#define ADM1026_CONFIG_INTERVAL		(5 * 60 * HZ)
2481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* We allow for multiple chips in a single system.
2501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
2511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * For each registered ADM1026, we need to keep state information
2521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * at client->data. The adm1026_data structure is dynamically
2531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * allocated, when a new client structure is allocated. */
2541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstruct pwm_data {
2561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	u8 pwm;
2571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	u8 enable;
2581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	u8 auto_pwm_min;
2591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds};
2601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstruct adm1026_data {
2621beeffe43311f64df8dd0ab08ff6b1858c58363fTony Jones	struct device *hwmon_dev;
2631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2649a61bf6300533d3b64d7ff29adfec00e596de67dIngo Molnar	struct mutex update_lock;
2651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int valid;		/* !=0 if following fields are valid */
2661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	unsigned long last_reading;	/* In jiffies */
2671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	unsigned long last_config;	/* In jiffies */
2681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
269cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvare	u8 in[17];		/* Register value */
270cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvare	u8 in_max[17];		/* Register value */
271cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvare	u8 in_min[17];		/* Register value */
272cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvare	s8 temp[3];		/* Register value */
273cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvare	s8 temp_min[3];		/* Register value */
274cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvare	s8 temp_max[3];		/* Register value */
275cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvare	s8 temp_tmin[3];	/* Register value */
276cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvare	s8 temp_crit[3];	/* Register value */
277cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvare	s8 temp_offset[3];	/* Register value */
278cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvare	u8 fan[8];		/* Register value */
279cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvare	u8 fan_min[8];		/* Register value */
280cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvare	u8 fan_div[8];		/* Decoded value */
281cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvare	struct pwm_data pwm1;	/* Pwm control values */
282cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvare	u8 vrm;			/* VRM version */
2831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	u8 analog_out;		/* Register value (DAC) */
284cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvare	long alarms;		/* Register encoding, combined */
285cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvare	long alarm_mask;	/* Register encoding, combined */
286cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvare	long gpio;		/* Register encoding, combined */
287cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvare	long gpio_mask;		/* Register encoding, combined */
288cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvare	u8 gpio_config[17];	/* Decoded value */
289cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvare	u8 config1;		/* Register value */
290cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvare	u8 config2;		/* Register value */
291cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvare	u8 config3;		/* Register value */
2921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds};
2931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
29457f7eb0bcb2316dc264cd26f38b33dd2cf3151c1Jean Delvarestatic int adm1026_probe(struct i2c_client *client,
29557f7eb0bcb2316dc264cd26f38b33dd2cf3151c1Jean Delvare			 const struct i2c_device_id *id);
29657f7eb0bcb2316dc264cd26f38b33dd2cf3151c1Jean Delvarestatic int adm1026_detect(struct i2c_client *client, int kind,
29757f7eb0bcb2316dc264cd26f38b33dd2cf3151c1Jean Delvare			  struct i2c_board_info *info);
29857f7eb0bcb2316dc264cd26f38b33dd2cf3151c1Jean Delvarestatic int adm1026_remove(struct i2c_client *client);
299f6c27fc17c5e575c5471fb344bdbd5f5f6072136Darren Jenkinsstatic int adm1026_read_value(struct i2c_client *client, u8 reg);
300f6c27fc17c5e575c5471fb344bdbd5f5f6072136Darren Jenkinsstatic int adm1026_write_value(struct i2c_client *client, u8 reg, int value);
3011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void adm1026_print_gpio(struct i2c_client *client);
302cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvarestatic void adm1026_fixup_gpio(struct i2c_client *client);
3031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic struct adm1026_data *adm1026_update_device(struct device *dev);
3041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void adm1026_init_client(struct i2c_client *client);
3051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
30757f7eb0bcb2316dc264cd26f38b33dd2cf3151c1Jean Delvarestatic const struct i2c_device_id adm1026_id[] = {
30857f7eb0bcb2316dc264cd26f38b33dd2cf3151c1Jean Delvare	{ "adm1026", adm1026 },
30957f7eb0bcb2316dc264cd26f38b33dd2cf3151c1Jean Delvare	{ }
31057f7eb0bcb2316dc264cd26f38b33dd2cf3151c1Jean Delvare};
31157f7eb0bcb2316dc264cd26f38b33dd2cf3151c1Jean DelvareMODULE_DEVICE_TABLE(i2c, adm1026_id);
31257f7eb0bcb2316dc264cd26f38b33dd2cf3151c1Jean Delvare
3131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic struct i2c_driver adm1026_driver = {
31457f7eb0bcb2316dc264cd26f38b33dd2cf3151c1Jean Delvare	.class		= I2C_CLASS_HWMON,
315cdaf79349c7d24e1d33acb6497849c9e956a33eaLaurent Riffard	.driver = {
316cdaf79349c7d24e1d33acb6497849c9e956a33eaLaurent Riffard		.name	= "adm1026",
317cdaf79349c7d24e1d33acb6497849c9e956a33eaLaurent Riffard	},
31857f7eb0bcb2316dc264cd26f38b33dd2cf3151c1Jean Delvare	.probe		= adm1026_probe,
31957f7eb0bcb2316dc264cd26f38b33dd2cf3151c1Jean Delvare	.remove		= adm1026_remove,
32057f7eb0bcb2316dc264cd26f38b33dd2cf3151c1Jean Delvare	.id_table	= adm1026_id,
32157f7eb0bcb2316dc264cd26f38b33dd2cf3151c1Jean Delvare	.detect		= adm1026_detect,
32257f7eb0bcb2316dc264cd26f38b33dd2cf3151c1Jean Delvare	.address_data	= &addr_data,
3231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds};
3241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
325c49efceffa599299ab3f38b1cdf8c2f1bf9811c4Ben Dooksstatic int adm1026_read_value(struct i2c_client *client, u8 reg)
3261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
3271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int res;
3281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (reg < 0x80) {
3301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		/* "RAM" locations */
3311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		res = i2c_smbus_read_byte_data(client, reg) & 0xff;
3321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	} else {
3331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		/* EEPROM, do nothing */
3341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		res = 0;
3351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
3361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return res;
3371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
3381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
339c49efceffa599299ab3f38b1cdf8c2f1bf9811c4Ben Dooksstatic int adm1026_write_value(struct i2c_client *client, u8 reg, int value)
3401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
3411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int res;
3421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (reg < 0x80) {
3441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		/* "RAM" locations */
3451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		res = i2c_smbus_write_byte_data(client, reg, value);
3461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	} else {
3471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		/* EEPROM, do nothing */
3481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		res = 0;
3491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
3501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return res;
3511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
3521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
353c49efceffa599299ab3f38b1cdf8c2f1bf9811c4Ben Dooksstatic void adm1026_init_client(struct i2c_client *client)
3541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
3551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int value, i;
3561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct adm1026_data *data = i2c_get_clientdata(client);
3571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
358cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvare	dev_dbg(&client->dev, "Initializing device\n");
3591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* Read chip config */
3601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	data->config1 = adm1026_read_value(client, ADM1026_REG_CONFIG1);
3611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	data->config2 = adm1026_read_value(client, ADM1026_REG_CONFIG2);
3621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	data->config3 = adm1026_read_value(client, ADM1026_REG_CONFIG3);
3631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* Inform user of chip config */
3651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	dev_dbg(&client->dev, "ADM1026_REG_CONFIG1 is: 0x%02x\n",
3661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		data->config1);
3671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if ((data->config1 & CFG1_MONITOR) == 0) {
3681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		dev_dbg(&client->dev, "Monitoring not currently "
3691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			"enabled.\n");
3701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
3711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (data->config1 & CFG1_INT_ENABLE) {
3721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		dev_dbg(&client->dev, "SMBALERT interrupts are "
3731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			"enabled.\n");
3741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
3751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (data->config1 & CFG1_AIN8_9) {
3761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		dev_dbg(&client->dev, "in8 and in9 enabled. "
3771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			"temp3 disabled.\n");
3781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	} else {
3791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		dev_dbg(&client->dev, "temp3 enabled.  in8 and "
3801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			"in9 disabled.\n");
3811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
3821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (data->config1 & CFG1_THERM_HOT) {
3831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		dev_dbg(&client->dev, "Automatic THERM, PWM, "
3841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			"and temp limits enabled.\n");
3851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
3861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (data->config3 & CFG3_GPIO16_ENABLE) {
388368609c5a8bd75b77721e69726ddfd3c6a30f7d4Jean Delvare		dev_dbg(&client->dev, "GPIO16 enabled.  THERM "
3891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			"pin disabled.\n");
3901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	} else {
3911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		dev_dbg(&client->dev, "THERM pin enabled.  "
3921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			"GPIO16 disabled.\n");
3931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
3941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (data->config3 & CFG3_VREF_250) {
3951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		dev_dbg(&client->dev, "Vref is 2.50 Volts.\n");
3961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	} else {
3971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		dev_dbg(&client->dev, "Vref is 1.82 Volts.\n");
3981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
3991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* Read and pick apart the existing GPIO configuration */
4001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	value = 0;
4011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	for (i = 0;i <= 15;++i) {
4021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if ((i & 0x03) == 0) {
4031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			value = adm1026_read_value(client,
4041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds					ADM1026_REG_GPIO_CFG_0_3 + i/4);
4051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
4061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		data->gpio_config[i] = value & 0x03;
4071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		value >>= 2;
4081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
4091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	data->gpio_config[16] = (data->config3 >> 6) & 0x03;
4101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* ... and then print it */
4121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	adm1026_print_gpio(client);
4131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* If the user asks us to reprogram the GPIO config, then
4151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * do it now.
4161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 */
4171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (gpio_input[0] != -1 || gpio_output[0] != -1
4181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		|| gpio_inverted[0] != -1 || gpio_normal[0] != -1
4191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		|| gpio_fan[0] != -1) {
4201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		adm1026_fixup_gpio(client);
4211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
4221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* WE INTENTIONALLY make no changes to the limits,
4241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 *   offsets, pwms, fans and zones.  If they were
4251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 *   configured, we don't want to mess with them.
4261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 *   If they weren't, the default is 100% PWM, no
4271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 *   control and will suffice until 'sensors -s'
428cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvare	 *   can be run by the user.  We DO set the default
4291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 *   value for pwm1.auto_pwm_min to its maximum
4301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 *   so that enabling automatic pwm fan control
431cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvare	 *   without first setting a value for pwm1.auto_pwm_min
4321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 *   will not result in potentially dangerous fan speed decrease.
4331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 */
4341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	data->pwm1.auto_pwm_min=255;
4351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* Start monitoring */
4361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	value = adm1026_read_value(client, ADM1026_REG_CONFIG1);
4371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* Set MONITOR, clear interrupt acknowledge and s/w reset */
4381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	value = (value | CFG1_MONITOR) & (~CFG1_INT_CLEAR & ~CFG1_RESET);
4391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	dev_dbg(&client->dev, "Setting CONFIG to: 0x%02x\n", value);
4401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	data->config1 = value;
4411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	adm1026_write_value(client, ADM1026_REG_CONFIG1, value);
4421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* initialize fan_div[] to hardware defaults */
4441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	value = adm1026_read_value(client, ADM1026_REG_FAN_DIV_0_3) |
4451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		(adm1026_read_value(client, ADM1026_REG_FAN_DIV_4_7) << 8);
4461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	for (i = 0;i <= 7;++i) {
4471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		data->fan_div[i] = DIV_FROM_REG(value & 0x03);
4481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		value >>= 2;
4491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
4501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
4511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
452c49efceffa599299ab3f38b1cdf8c2f1bf9811c4Ben Dooksstatic void adm1026_print_gpio(struct i2c_client *client)
4531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
4541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct adm1026_data *data = i2c_get_clientdata(client);
455cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvare	int i;
4561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
457885fe4b1f621fa2c8499e222059b59dbc98583e2Jean Delvare	dev_dbg(&client->dev, "GPIO config is:\n");
4581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	for (i = 0;i <= 7;++i) {
4591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (data->config2 & (1 << i)) {
4601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			dev_dbg(&client->dev, "\t%sGP%s%d\n",
4611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				data->gpio_config[i] & 0x02 ? "" : "!",
4621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				data->gpio_config[i] & 0x01 ? "OUT" : "IN",
4631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				i);
4641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		} else {
4651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			dev_dbg(&client->dev, "\tFAN%d\n", i);
4661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
4671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
4681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	for (i = 8;i <= 15;++i) {
4691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		dev_dbg(&client->dev, "\t%sGP%s%d\n",
4701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			data->gpio_config[i] & 0x02 ? "" : "!",
4711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			data->gpio_config[i] & 0x01 ? "OUT" : "IN",
4721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			i);
4731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
4741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (data->config3 & CFG3_GPIO16_ENABLE) {
4751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		dev_dbg(&client->dev, "\t%sGP%s16\n",
4761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			data->gpio_config[16] & 0x02 ? "" : "!",
4771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			data->gpio_config[16] & 0x01 ? "OUT" : "IN");
4781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	} else {
479cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvare		/* GPIO16 is THERM */
4801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		dev_dbg(&client->dev, "\tTHERM\n");
4811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
4821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
4831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
484c49efceffa599299ab3f38b1cdf8c2f1bf9811c4Ben Dooksstatic void adm1026_fixup_gpio(struct i2c_client *client)
4851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
4861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct adm1026_data *data = i2c_get_clientdata(client);
487cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvare	int i;
488cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvare	int value;
4891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* Make the changes requested. */
4911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* We may need to unlock/stop monitoring or soft-reset the
4921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 *    chip before we can make changes.  This hasn't been
4931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 *    tested much.  FIXME
4941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 */
4951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* Make outputs */
4971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	for (i = 0;i <= 16;++i) {
4981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (gpio_output[i] >= 0 && gpio_output[i] <= 16) {
4991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			data->gpio_config[gpio_output[i]] |= 0x01;
5001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
5011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		/* if GPIO0-7 is output, it isn't a FAN tach */
5021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (gpio_output[i] >= 0 && gpio_output[i] <= 7) {
5031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			data->config2 |= 1 << gpio_output[i];
5041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
5051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
5061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* Input overrides output */
5081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	for (i = 0;i <= 16;++i) {
5091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (gpio_input[i] >= 0 && gpio_input[i] <= 16) {
5101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			data->gpio_config[gpio_input[i]] &= ~ 0x01;
5111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
5121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		/* if GPIO0-7 is input, it isn't a FAN tach */
5131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (gpio_input[i] >= 0 && gpio_input[i] <= 7) {
5141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			data->config2 |= 1 << gpio_input[i];
5151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
5161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
5171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
518cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvare	/* Inverted */
5191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	for (i = 0;i <= 16;++i) {
5201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (gpio_inverted[i] >= 0 && gpio_inverted[i] <= 16) {
5211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			data->gpio_config[gpio_inverted[i]] &= ~ 0x02;
5221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
5231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
5241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
525cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvare	/* Normal overrides inverted */
5261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	for (i = 0;i <= 16;++i) {
5271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (gpio_normal[i] >= 0 && gpio_normal[i] <= 16) {
5281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			data->gpio_config[gpio_normal[i]] |= 0x02;
5291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
5301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
5311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* Fan overrides input and output */
5331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	for (i = 0;i <= 7;++i) {
5341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (gpio_fan[i] >= 0 && gpio_fan[i] <= 7) {
5351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			data->config2 &= ~(1 << gpio_fan[i]);
5361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
5371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
5381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* Write new configs to registers */
5401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	adm1026_write_value(client, ADM1026_REG_CONFIG2, data->config2);
5411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	data->config3 = (data->config3 & 0x3f)
5421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			| ((data->gpio_config[16] & 0x03) << 6);
5431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	adm1026_write_value(client, ADM1026_REG_CONFIG3, data->config3);
5441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	for (i = 15, value = 0;i >= 0;--i) {
5451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		value <<= 2;
5461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		value |= data->gpio_config[i] & 0x03;
5471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if ((i & 0x03) == 0) {
5481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			adm1026_write_value(client,
5491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds					ADM1026_REG_GPIO_CFG_0_3 + i/4,
5501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds					value);
5511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			value = 0;
5521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
5531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
5541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* Print the new config */
5561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	adm1026_print_gpio(client);
5571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
5581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic struct adm1026_data *adm1026_update_device(struct device *dev)
5611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
5621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct i2c_client *client = to_i2c_client(dev);
5631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct adm1026_data *data = i2c_get_clientdata(client);
5641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int i;
5651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	long value, alarms, gpio;
5661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5679a61bf6300533d3b64d7ff29adfec00e596de67dIngo Molnar	mutex_lock(&data->update_lock);
5681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (!data->valid
5691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	    || time_after(jiffies, data->last_reading + ADM1026_DATA_INTERVAL)) {
5701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		/* Things that change quickly */
571cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvare		dev_dbg(&client->dev, "Reading sensor values\n");
5721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		for (i = 0;i <= 16;++i) {
5731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			data->in[i] =
5741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			    adm1026_read_value(client, ADM1026_REG_IN[i]);
5751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
5761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		for (i = 0;i <= 7;++i) {
5781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			data->fan[i] =
5791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			    adm1026_read_value(client, ADM1026_REG_FAN(i));
5801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
5811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		for (i = 0;i <= 2;++i) {
5831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			/* NOTE: temp[] is s8 and we assume 2's complement
584cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvare			 *   "conversion" in the assignment */
5851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			data->temp[i] =
5861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			    adm1026_read_value(client, ADM1026_REG_TEMP[i]);
5871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
5881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
589cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvare		data->pwm1.pwm = adm1026_read_value(client,
5901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			ADM1026_REG_PWM);
591cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvare		data->analog_out = adm1026_read_value(client,
5921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			ADM1026_REG_DAC);
5931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		/* GPIO16 is MSbit of alarms, move it to gpio */
5941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		alarms = adm1026_read_value(client, ADM1026_REG_STATUS4);
595cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvare		gpio = alarms & 0x80 ? 0x0100 : 0; /* GPIO16 */
5961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		alarms &= 0x7f;
5971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		alarms <<= 8;
5981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		alarms |= adm1026_read_value(client, ADM1026_REG_STATUS3);
5991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		alarms <<= 8;
6001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		alarms |= adm1026_read_value(client, ADM1026_REG_STATUS2);
6011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		alarms <<= 8;
6021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		alarms |= adm1026_read_value(client, ADM1026_REG_STATUS1);
6031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		data->alarms = alarms;
6041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
6051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		/* Read the GPIO values */
606cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvare		gpio |= adm1026_read_value(client,
6071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			ADM1026_REG_GPIO_STATUS_8_15);
6081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		gpio <<= 8;
609cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvare		gpio |= adm1026_read_value(client,
6101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			ADM1026_REG_GPIO_STATUS_0_7);
6111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		data->gpio = gpio;
6121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
6131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		data->last_reading = jiffies;
614cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvare	}; /* last_reading */
6151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
6161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (!data->valid ||
6171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	    time_after(jiffies, data->last_config + ADM1026_CONFIG_INTERVAL)) {
6181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		/* Things that don't change often */
6191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		dev_dbg(&client->dev, "Reading config values\n");
6201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		for (i = 0;i <= 16;++i) {
621cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvare			data->in_min[i] = adm1026_read_value(client,
6221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				ADM1026_REG_IN_MIN[i]);
623cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvare			data->in_max[i] = adm1026_read_value(client,
6241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				ADM1026_REG_IN_MAX[i]);
6251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
6261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
6271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		value = adm1026_read_value(client, ADM1026_REG_FAN_DIV_0_3)
6281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			| (adm1026_read_value(client, ADM1026_REG_FAN_DIV_4_7)
6291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			<< 8);
6301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		for (i = 0;i <= 7;++i) {
631cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvare			data->fan_min[i] = adm1026_read_value(client,
6321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				ADM1026_REG_FAN_MIN(i));
6331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			data->fan_div[i] = DIV_FROM_REG(value & 0x03);
6341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			value >>= 2;
6351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
6361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
6371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		for (i = 0; i <= 2; ++i) {
638cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvare			/* NOTE: temp_xxx[] are s8 and we assume 2's
6391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			 *    complement "conversion" in the assignment
6401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			 */
641cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvare			data->temp_min[i] = adm1026_read_value(client,
6421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				ADM1026_REG_TEMP_MIN[i]);
643cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvare			data->temp_max[i] = adm1026_read_value(client,
6441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				ADM1026_REG_TEMP_MAX[i]);
645cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvare			data->temp_tmin[i] = adm1026_read_value(client,
6461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				ADM1026_REG_TEMP_TMIN[i]);
647cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvare			data->temp_crit[i] = adm1026_read_value(client,
6481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				ADM1026_REG_TEMP_THERM[i]);
649cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvare			data->temp_offset[i] = adm1026_read_value(client,
6501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				ADM1026_REG_TEMP_OFFSET[i]);
6511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
6521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
6531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		/* Read the STATUS/alarm masks */
654cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvare		alarms = adm1026_read_value(client, ADM1026_REG_MASK4);
655cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvare		gpio = alarms & 0x80 ? 0x0100 : 0; /* GPIO16 */
656cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvare		alarms = (alarms & 0x7f) << 8;
6571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		alarms |= adm1026_read_value(client, ADM1026_REG_MASK3);
6581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		alarms <<= 8;
6591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		alarms |= adm1026_read_value(client, ADM1026_REG_MASK2);
6601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		alarms <<= 8;
6611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		alarms |= adm1026_read_value(client, ADM1026_REG_MASK1);
6621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		data->alarm_mask = alarms;
6631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
6641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		/* Read the GPIO values */
665cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvare		gpio |= adm1026_read_value(client,
6661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			ADM1026_REG_GPIO_MASK_8_15);
6671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		gpio <<= 8;
6681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		gpio |= adm1026_read_value(client, ADM1026_REG_GPIO_MASK_0_7);
6691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		data->gpio_mask = gpio;
6701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
6711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		/* Read various values from CONFIG1 */
672cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvare		data->config1 = adm1026_read_value(client,
6731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			ADM1026_REG_CONFIG1);
6741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (data->config1 & CFG1_PWM_AFC) {
6751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			data->pwm1.enable = 2;
676cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvare			data->pwm1.auto_pwm_min =
6771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				PWM_MIN_FROM_REG(data->pwm1.pwm);
6781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
6791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		/* Read the GPIO config */
680cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvare		data->config2 = adm1026_read_value(client,
6811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			ADM1026_REG_CONFIG2);
682cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvare		data->config3 = adm1026_read_value(client,
6831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			ADM1026_REG_CONFIG3);
6841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		data->gpio_config[16] = (data->config3 >> 6) & 0x03;
6851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
6861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		value = 0;
6871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		for (i = 0;i <= 15;++i) {
6881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			if ((i & 0x03) == 0) {
6891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				value = adm1026_read_value(client,
6901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds					    ADM1026_REG_GPIO_CFG_0_3 + i/4);
6911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			}
6921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			data->gpio_config[i] = value & 0x03;
6931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			value >>= 2;
6941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
6951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
6961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		data->last_config = jiffies;
697cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvare	}; /* last_config */
6981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
6991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	data->valid = 1;
7009a61bf6300533d3b64d7ff29adfec00e596de67dIngo Molnar	mutex_unlock(&data->update_lock);
7011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return data;
7021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
7031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
704050480f12aeab62d39a1a07546606a47217ebefaYani Ioannoustatic ssize_t show_in(struct device *dev, struct device_attribute *attr,
705050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou		char *buf)
7061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
707050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou	struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr);
708050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou	int nr = sensor_attr->index;
7091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct adm1026_data *data = adm1026_update_device(dev);
710cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvare	return sprintf(buf, "%d\n", INS_FROM_REG(nr, data->in[nr]));
7111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
712050480f12aeab62d39a1a07546606a47217ebefaYani Ioannoustatic ssize_t show_in_min(struct device *dev, struct device_attribute *attr,
713050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou		char *buf)
7141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
715050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou	struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr);
716050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou	int nr = sensor_attr->index;
717cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvare	struct adm1026_data *data = adm1026_update_device(dev);
718cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvare	return sprintf(buf, "%d\n", INS_FROM_REG(nr, data->in_min[nr]));
7191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
720050480f12aeab62d39a1a07546606a47217ebefaYani Ioannoustatic ssize_t set_in_min(struct device *dev, struct device_attribute *attr,
721050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou		const char *buf, size_t count)
7221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
723050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou	struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr);
724050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou	int nr = sensor_attr->index;
7251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct i2c_client *client = to_i2c_client(dev);
7261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct adm1026_data *data = i2c_get_clientdata(client);
7271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int val = simple_strtol(buf, NULL, 10);
7281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
7299a61bf6300533d3b64d7ff29adfec00e596de67dIngo Molnar	mutex_lock(&data->update_lock);
7301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	data->in_min[nr] = INS_TO_REG(nr, val);
7311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	adm1026_write_value(client, ADM1026_REG_IN_MIN[nr], data->in_min[nr]);
7329a61bf6300533d3b64d7ff29adfec00e596de67dIngo Molnar	mutex_unlock(&data->update_lock);
733cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvare	return count;
7341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
735050480f12aeab62d39a1a07546606a47217ebefaYani Ioannoustatic ssize_t show_in_max(struct device *dev, struct device_attribute *attr,
736050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou		char *buf)
7371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
738050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou	struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr);
739050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou	int nr = sensor_attr->index;
7401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct adm1026_data *data = adm1026_update_device(dev);
741cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvare	return sprintf(buf, "%d\n", INS_FROM_REG(nr, data->in_max[nr]));
7421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
743050480f12aeab62d39a1a07546606a47217ebefaYani Ioannoustatic ssize_t set_in_max(struct device *dev, struct device_attribute *attr,
744050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou		const char *buf, size_t count)
7451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
746050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou	struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr);
747050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou	int nr = sensor_attr->index;
7481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct i2c_client *client = to_i2c_client(dev);
7491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct adm1026_data *data = i2c_get_clientdata(client);
7501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int val = simple_strtol(buf, NULL, 10);
7511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
7529a61bf6300533d3b64d7ff29adfec00e596de67dIngo Molnar	mutex_lock(&data->update_lock);
7531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	data->in_max[nr] = INS_TO_REG(nr, val);
7541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	adm1026_write_value(client, ADM1026_REG_IN_MAX[nr], data->in_max[nr]);
7559a61bf6300533d3b64d7ff29adfec00e596de67dIngo Molnar	mutex_unlock(&data->update_lock);
7561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return count;
7571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
7581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
759050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou#define in_reg(offset)						\
760050480f12aeab62d39a1a07546606a47217ebefaYani Ioannoustatic SENSOR_DEVICE_ATTR(in##offset##_input, S_IRUGO, show_in,	\
761050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou		NULL, offset);					\
762050480f12aeab62d39a1a07546606a47217ebefaYani Ioannoustatic SENSOR_DEVICE_ATTR(in##offset##_min, S_IRUGO | S_IWUSR,	\
763050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou		show_in_min, set_in_min, offset);		\
764050480f12aeab62d39a1a07546606a47217ebefaYani Ioannoustatic SENSOR_DEVICE_ATTR(in##offset##_max, S_IRUGO | S_IWUSR,	\
765050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou		show_in_max, set_in_max, offset);
7661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
7671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
7681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsin_reg(0);
7691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsin_reg(1);
7701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsin_reg(2);
7711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsin_reg(3);
7721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsin_reg(4);
7731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsin_reg(5);
7741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsin_reg(6);
7751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsin_reg(7);
7761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsin_reg(8);
7771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsin_reg(9);
7781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsin_reg(10);
7791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsin_reg(11);
7801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsin_reg(12);
7811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsin_reg(13);
7821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsin_reg(14);
7831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsin_reg(15);
7841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
78574880c063b06efd103c924abfe19d9d8fa4864c4Yani Ioannoustatic ssize_t show_in16(struct device *dev, struct device_attribute *attr, char *buf)
7861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
7871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct adm1026_data *data = adm1026_update_device(dev);
788cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvare	return sprintf(buf, "%d\n", INS_FROM_REG(16, data->in[16]) -
7891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		NEG12_OFFSET);
7901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
79174880c063b06efd103c924abfe19d9d8fa4864c4Yani Ioannoustatic ssize_t show_in16_min(struct device *dev, struct device_attribute *attr, char *buf)
7921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
793cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvare	struct adm1026_data *data = adm1026_update_device(dev);
794cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvare	return sprintf(buf, "%d\n", INS_FROM_REG(16, data->in_min[16])
7951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		- NEG12_OFFSET);
7961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
79774880c063b06efd103c924abfe19d9d8fa4864c4Yani Ioannoustatic ssize_t set_in16_min(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
7981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
7991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct i2c_client *client = to_i2c_client(dev);
8001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct adm1026_data *data = i2c_get_clientdata(client);
8011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int val = simple_strtol(buf, NULL, 10);
8021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
8039a61bf6300533d3b64d7ff29adfec00e596de67dIngo Molnar	mutex_lock(&data->update_lock);
8041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	data->in_min[16] = INS_TO_REG(16, val + NEG12_OFFSET);
8051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	adm1026_write_value(client, ADM1026_REG_IN_MIN[16], data->in_min[16]);
8069a61bf6300533d3b64d7ff29adfec00e596de67dIngo Molnar	mutex_unlock(&data->update_lock);
807cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvare	return count;
8081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
80974880c063b06efd103c924abfe19d9d8fa4864c4Yani Ioannoustatic ssize_t show_in16_max(struct device *dev, struct device_attribute *attr, char *buf)
8101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
8111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct adm1026_data *data = adm1026_update_device(dev);
812cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvare	return sprintf(buf, "%d\n", INS_FROM_REG(16, data->in_max[16])
8131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			- NEG12_OFFSET);
8141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
81574880c063b06efd103c924abfe19d9d8fa4864c4Yani Ioannoustatic ssize_t set_in16_max(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
8161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
8171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct i2c_client *client = to_i2c_client(dev);
8181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct adm1026_data *data = i2c_get_clientdata(client);
8191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int val = simple_strtol(buf, NULL, 10);
8201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
8219a61bf6300533d3b64d7ff29adfec00e596de67dIngo Molnar	mutex_lock(&data->update_lock);
8221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	data->in_max[16] = INS_TO_REG(16, val+NEG12_OFFSET);
8231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	adm1026_write_value(client, ADM1026_REG_IN_MAX[16], data->in_max[16]);
8249a61bf6300533d3b64d7ff29adfec00e596de67dIngo Molnar	mutex_unlock(&data->update_lock);
8251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return count;
8261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
8271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
828050480f12aeab62d39a1a07546606a47217ebefaYani Ioannoustatic SENSOR_DEVICE_ATTR(in16_input, S_IRUGO, show_in16, NULL, 16);
829050480f12aeab62d39a1a07546606a47217ebefaYani Ioannoustatic SENSOR_DEVICE_ATTR(in16_min, S_IRUGO | S_IWUSR, show_in16_min, set_in16_min, 16);
830050480f12aeab62d39a1a07546606a47217ebefaYani Ioannoustatic SENSOR_DEVICE_ATTR(in16_max, S_IRUGO | S_IWUSR, show_in16_max, set_in16_max, 16);
8311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
8321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
8331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
8341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
8351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* Now add fan read/write functions */
8361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
837050480f12aeab62d39a1a07546606a47217ebefaYani Ioannoustatic ssize_t show_fan(struct device *dev, struct device_attribute *attr,
838050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou		char *buf)
8391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
840050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou	struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr);
841050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou	int nr = sensor_attr->index;
8421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct adm1026_data *data = adm1026_update_device(dev);
843cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvare	return sprintf(buf, "%d\n", FAN_FROM_REG(data->fan[nr],
8441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		data->fan_div[nr]));
8451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
846050480f12aeab62d39a1a07546606a47217ebefaYani Ioannoustatic ssize_t show_fan_min(struct device *dev, struct device_attribute *attr,
847050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou		char *buf)
8481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
849050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou	struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr);
850050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou	int nr = sensor_attr->index;
8511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct adm1026_data *data = adm1026_update_device(dev);
852cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvare	return sprintf(buf, "%d\n", FAN_FROM_REG(data->fan_min[nr],
8531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		data->fan_div[nr]));
8541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
855050480f12aeab62d39a1a07546606a47217ebefaYani Ioannoustatic ssize_t set_fan_min(struct device *dev, struct device_attribute *attr,
856050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou		const char *buf, size_t count)
8571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
858050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou	struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr);
859050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou	int nr = sensor_attr->index;
8601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct i2c_client *client = to_i2c_client(dev);
8611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct adm1026_data *data = i2c_get_clientdata(client);
8621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int val = simple_strtol(buf, NULL, 10);
8631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
8649a61bf6300533d3b64d7ff29adfec00e596de67dIngo Molnar	mutex_lock(&data->update_lock);
8651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	data->fan_min[nr] = FAN_TO_REG(val, data->fan_div[nr]);
8661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	adm1026_write_value(client, ADM1026_REG_FAN_MIN(nr),
8671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		data->fan_min[nr]);
8689a61bf6300533d3b64d7ff29adfec00e596de67dIngo Molnar	mutex_unlock(&data->update_lock);
8691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return count;
8701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
8711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
872cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvare#define fan_offset(offset)						\
873cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvarestatic SENSOR_DEVICE_ATTR(fan##offset##_input, S_IRUGO, show_fan, NULL,	\
874cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvare		offset - 1);						\
875cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvarestatic SENSOR_DEVICE_ATTR(fan##offset##_min, S_IRUGO | S_IWUSR,		\
876050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou		show_fan_min, set_fan_min, offset - 1);
8771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
8781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsfan_offset(1);
8791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsfan_offset(2);
8801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsfan_offset(3);
8811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsfan_offset(4);
8821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsfan_offset(5);
8831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsfan_offset(6);
8841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsfan_offset(7);
8851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsfan_offset(8);
8861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
8871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* Adjust fan_min to account for new fan divisor */
8881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void fixup_fan_min(struct device *dev, int fan, int old_div)
8891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
8901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct i2c_client *client = to_i2c_client(dev);
8911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct adm1026_data *data = i2c_get_clientdata(client);
892cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvare	int new_min;
893cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvare	int new_div = data->fan_div[fan];
8941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
8951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* 0 and 0xff are special.  Don't adjust them */
8961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (data->fan_min[fan] == 0 || data->fan_min[fan] == 0xff) {
8971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return;
8981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
8991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
9001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	new_min = data->fan_min[fan] * old_div / new_div;
9011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	new_min = SENSORS_LIMIT(new_min, 1, 254);
9021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	data->fan_min[fan] = new_min;
9031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	adm1026_write_value(client, ADM1026_REG_FAN_MIN(fan), new_min);
9041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
9051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
9061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* Now add fan_div read/write functions */
907050480f12aeab62d39a1a07546606a47217ebefaYani Ioannoustatic ssize_t show_fan_div(struct device *dev, struct device_attribute *attr,
908050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou		char *buf)
9091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
910050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou	struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr);
911050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou	int nr = sensor_attr->index;
9121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct adm1026_data *data = adm1026_update_device(dev);
913cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvare	return sprintf(buf, "%d\n", data->fan_div[nr]);
9141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
915050480f12aeab62d39a1a07546606a47217ebefaYani Ioannoustatic ssize_t set_fan_div(struct device *dev, struct device_attribute *attr,
916050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou		const char *buf, size_t count)
9171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
918050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou	struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr);
919050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou	int nr = sensor_attr->index;
9201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct i2c_client *client = to_i2c_client(dev);
9211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct adm1026_data *data = i2c_get_clientdata(client);
922cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvare	int val, orig_div, new_div, shift;
9231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
9241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	val = simple_strtol(buf, NULL, 10);
925cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvare	new_div = DIV_TO_REG(val);
9261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (new_div == 0) {
9271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return -EINVAL;
9281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
9299a61bf6300533d3b64d7ff29adfec00e596de67dIngo Molnar	mutex_lock(&data->update_lock);
9301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	orig_div = data->fan_div[nr];
9311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	data->fan_div[nr] = DIV_FROM_REG(new_div);
9321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
9331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (nr < 4) { /* 0 <= nr < 4 */
9341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		shift = 2 * nr;
9351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		adm1026_write_value(client, ADM1026_REG_FAN_DIV_0_3,
9361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			((DIV_TO_REG(orig_div) & (~(0x03 << shift))) |
9371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			(new_div << shift)));
9381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	} else { /* 3 < nr < 8 */
9391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		shift = 2 * (nr - 4);
9401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		adm1026_write_value(client, ADM1026_REG_FAN_DIV_4_7,
9411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			((DIV_TO_REG(orig_div) & (~(0x03 << (2 * shift)))) |
9421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			(new_div << shift)));
9431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
9441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
9451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (data->fan_div[nr] != orig_div) {
946cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvare		fixup_fan_min(dev, nr, orig_div);
9471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
9489a61bf6300533d3b64d7ff29adfec00e596de67dIngo Molnar	mutex_unlock(&data->update_lock);
9491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return count;
9501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
9511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
952cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvare#define fan_offset_div(offset)						\
953cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvarestatic SENSOR_DEVICE_ATTR(fan##offset##_div, S_IRUGO | S_IWUSR,		\
954050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou		show_fan_div, set_fan_div, offset - 1);
9551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
9561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsfan_offset_div(1);
9571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsfan_offset_div(2);
9581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsfan_offset_div(3);
9591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsfan_offset_div(4);
9601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsfan_offset_div(5);
9611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsfan_offset_div(6);
9621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsfan_offset_div(7);
9631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsfan_offset_div(8);
9641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
9651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* Temps */
966050480f12aeab62d39a1a07546606a47217ebefaYani Ioannoustatic ssize_t show_temp(struct device *dev, struct device_attribute *attr,
967050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou		char *buf)
9681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
969050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou	struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr);
970050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou	int nr = sensor_attr->index;
9711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct adm1026_data *data = adm1026_update_device(dev);
972cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvare	return sprintf(buf, "%d\n", TEMP_FROM_REG(data->temp[nr]));
9731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
974050480f12aeab62d39a1a07546606a47217ebefaYani Ioannoustatic ssize_t show_temp_min(struct device *dev, struct device_attribute *attr,
975050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou		char *buf)
9761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
977050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou	struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr);
978050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou	int nr = sensor_attr->index;
9791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct adm1026_data *data = adm1026_update_device(dev);
980cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvare	return sprintf(buf, "%d\n", TEMP_FROM_REG(data->temp_min[nr]));
9811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
982050480f12aeab62d39a1a07546606a47217ebefaYani Ioannoustatic ssize_t set_temp_min(struct device *dev, struct device_attribute *attr,
983050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou		const char *buf, size_t count)
9841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
985050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou	struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr);
986050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou	int nr = sensor_attr->index;
9871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct i2c_client *client = to_i2c_client(dev);
9881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct adm1026_data *data = i2c_get_clientdata(client);
9891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int val = simple_strtol(buf, NULL, 10);
9901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
9919a61bf6300533d3b64d7ff29adfec00e596de67dIngo Molnar	mutex_lock(&data->update_lock);
9921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	data->temp_min[nr] = TEMP_TO_REG(val);
9931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	adm1026_write_value(client, ADM1026_REG_TEMP_MIN[nr],
9941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		data->temp_min[nr]);
9959a61bf6300533d3b64d7ff29adfec00e596de67dIngo Molnar	mutex_unlock(&data->update_lock);
9961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return count;
9971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
998050480f12aeab62d39a1a07546606a47217ebefaYani Ioannoustatic ssize_t show_temp_max(struct device *dev, struct device_attribute *attr,
999050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou		char *buf)
10001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
1001050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou	struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr);
1002050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou	int nr = sensor_attr->index;
10031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct adm1026_data *data = adm1026_update_device(dev);
1004cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvare	return sprintf(buf, "%d\n", TEMP_FROM_REG(data->temp_max[nr]));
10051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
1006050480f12aeab62d39a1a07546606a47217ebefaYani Ioannoustatic ssize_t set_temp_max(struct device *dev, struct device_attribute *attr,
1007050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou		const char *buf, size_t count)
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 i2c_client *client = to_i2c_client(dev);
10121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct adm1026_data *data = i2c_get_clientdata(client);
10131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int val = simple_strtol(buf, NULL, 10);
10141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
10159a61bf6300533d3b64d7ff29adfec00e596de67dIngo Molnar	mutex_lock(&data->update_lock);
10161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	data->temp_max[nr] = TEMP_TO_REG(val);
10171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	adm1026_write_value(client, ADM1026_REG_TEMP_MAX[nr],
10181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		data->temp_max[nr]);
10199a61bf6300533d3b64d7ff29adfec00e596de67dIngo Molnar	mutex_unlock(&data->update_lock);
10201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return count;
10211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
1022050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou
1023050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou#define temp_reg(offset)						\
1024cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvarestatic SENSOR_DEVICE_ATTR(temp##offset##_input, S_IRUGO, show_temp,	\
1025050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou		NULL, offset - 1);					\
1026050480f12aeab62d39a1a07546606a47217ebefaYani Ioannoustatic SENSOR_DEVICE_ATTR(temp##offset##_min, S_IRUGO | S_IWUSR,	\
1027050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou		show_temp_min, set_temp_min, offset - 1);		\
1028050480f12aeab62d39a1a07546606a47217ebefaYani Ioannoustatic SENSOR_DEVICE_ATTR(temp##offset##_max, S_IRUGO | S_IWUSR,	\
1029050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou		show_temp_max, set_temp_max, offset - 1);
10301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
10311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
10321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldstemp_reg(1);
10331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldstemp_reg(2);
10341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldstemp_reg(3);
10351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1036050480f12aeab62d39a1a07546606a47217ebefaYani Ioannoustatic ssize_t show_temp_offset(struct device *dev,
1037050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou		struct device_attribute *attr, char *buf)
10381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
1039050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou	struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr);
1040050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou	int nr = sensor_attr->index;
10411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct adm1026_data *data = adm1026_update_device(dev);
1042cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvare	return sprintf(buf, "%d\n", TEMP_FROM_REG(data->temp_offset[nr]));
10431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
1044050480f12aeab62d39a1a07546606a47217ebefaYani Ioannoustatic ssize_t set_temp_offset(struct device *dev,
1045050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou		struct device_attribute *attr, const char *buf,
1046050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou		size_t count)
10471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
1048050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou	struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr);
1049050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou	int nr = sensor_attr->index;
10501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct i2c_client *client = to_i2c_client(dev);
10511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct adm1026_data *data = i2c_get_clientdata(client);
10521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int val = simple_strtol(buf, NULL, 10);
10531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
10549a61bf6300533d3b64d7ff29adfec00e596de67dIngo Molnar	mutex_lock(&data->update_lock);
10551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	data->temp_offset[nr] = TEMP_TO_REG(val);
10561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	adm1026_write_value(client, ADM1026_REG_TEMP_OFFSET[nr],
10571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		data->temp_offset[nr]);
10589a61bf6300533d3b64d7ff29adfec00e596de67dIngo Molnar	mutex_unlock(&data->update_lock);
10591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return count;
10601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
10611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1062050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou#define temp_offset_reg(offset)							\
1063050480f12aeab62d39a1a07546606a47217ebefaYani Ioannoustatic SENSOR_DEVICE_ATTR(temp##offset##_offset, S_IRUGO | S_IWUSR,		\
1064050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou		show_temp_offset, set_temp_offset, offset - 1);
10651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
10661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldstemp_offset_reg(1);
10671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldstemp_offset_reg(2);
10681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldstemp_offset_reg(3);
10691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1070050480f12aeab62d39a1a07546606a47217ebefaYani Ioannoustatic ssize_t show_temp_auto_point1_temp_hyst(struct device *dev,
1071050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou		struct device_attribute *attr, char *buf)
10721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
1073050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou	struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr);
1074050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou	int nr = sensor_attr->index;
10751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct adm1026_data *data = adm1026_update_device(dev);
1076cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvare	return sprintf(buf, "%d\n", TEMP_FROM_REG(
10771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		ADM1026_FAN_ACTIVATION_TEMP_HYST + data->temp_tmin[nr]));
10781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
1079050480f12aeab62d39a1a07546606a47217ebefaYani Ioannoustatic ssize_t show_temp_auto_point2_temp(struct device *dev,
1080050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou		struct device_attribute *attr, char *buf)
10811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
1082050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou	struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr);
1083050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou	int nr = sensor_attr->index;
10841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct adm1026_data *data = adm1026_update_device(dev);
1085cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvare	return sprintf(buf, "%d\n", TEMP_FROM_REG(data->temp_tmin[nr] +
10861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		ADM1026_FAN_CONTROL_TEMP_RANGE));
10871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
1088050480f12aeab62d39a1a07546606a47217ebefaYani Ioannoustatic ssize_t show_temp_auto_point1_temp(struct device *dev,
1089050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou		struct device_attribute *attr, char *buf)
10901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
1091050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou	struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr);
1092050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou	int nr = sensor_attr->index;
10931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct adm1026_data *data = adm1026_update_device(dev);
1094cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvare	return sprintf(buf, "%d\n", TEMP_FROM_REG(data->temp_tmin[nr]));
10951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
1096050480f12aeab62d39a1a07546606a47217ebefaYani Ioannoustatic ssize_t set_temp_auto_point1_temp(struct device *dev,
1097050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou		struct device_attribute *attr, const char *buf, size_t count)
10981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
1099050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou	struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr);
1100050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou	int nr = sensor_attr->index;
11011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct i2c_client *client = to_i2c_client(dev);
11021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct adm1026_data *data = i2c_get_clientdata(client);
11031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int val = simple_strtol(buf, NULL, 10);
11041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
11059a61bf6300533d3b64d7ff29adfec00e596de67dIngo Molnar	mutex_lock(&data->update_lock);
11061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	data->temp_tmin[nr] = TEMP_TO_REG(val);
11071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	adm1026_write_value(client, ADM1026_REG_TEMP_TMIN[nr],
11081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		data->temp_tmin[nr]);
11099a61bf6300533d3b64d7ff29adfec00e596de67dIngo Molnar	mutex_unlock(&data->update_lock);
11101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return count;
11111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
11121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1113cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvare#define temp_auto_point(offset)						\
1114cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvarestatic SENSOR_DEVICE_ATTR(temp##offset##_auto_point1_temp,		\
1115cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvare		S_IRUGO | S_IWUSR, show_temp_auto_point1_temp,		\
1116cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvare		set_temp_auto_point1_temp, offset - 1);			\
1117cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvarestatic SENSOR_DEVICE_ATTR(temp##offset##_auto_point1_temp_hyst, S_IRUGO,\
1118cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvare		show_temp_auto_point1_temp_hyst, NULL, offset - 1);	\
1119cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvarestatic SENSOR_DEVICE_ATTR(temp##offset##_auto_point2_temp, S_IRUGO,	\
1120050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou		show_temp_auto_point2_temp, NULL, offset - 1);
11211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
11221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldstemp_auto_point(1);
11231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldstemp_auto_point(2);
11241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldstemp_auto_point(3);
11251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1126050480f12aeab62d39a1a07546606a47217ebefaYani Ioannoustatic ssize_t show_temp_crit_enable(struct device *dev,
1127050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou		struct device_attribute *attr, char *buf)
11281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
11291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct adm1026_data *data = adm1026_update_device(dev);
1130cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvare	return sprintf(buf, "%d\n", (data->config1 & CFG1_THERM_HOT) >> 4);
11311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
1132050480f12aeab62d39a1a07546606a47217ebefaYani Ioannoustatic ssize_t set_temp_crit_enable(struct device *dev,
1133050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou		struct device_attribute *attr, const char *buf, size_t count)
11341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
11351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct i2c_client *client = to_i2c_client(dev);
11361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct adm1026_data *data = i2c_get_clientdata(client);
11371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int val = simple_strtol(buf, NULL, 10);
11381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
11391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if ((val == 1) || (val==0)) {
11409a61bf6300533d3b64d7ff29adfec00e596de67dIngo Molnar		mutex_lock(&data->update_lock);
11411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		data->config1 = (data->config1 & ~CFG1_THERM_HOT) | (val << 4);
1142cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvare		adm1026_write_value(client, ADM1026_REG_CONFIG1,
11431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			data->config1);
11449a61bf6300533d3b64d7ff29adfec00e596de67dIngo Molnar		mutex_unlock(&data->update_lock);
11451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
11461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return count;
11471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
11481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1149050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou#define temp_crit_enable(offset)				\
1150050480f12aeab62d39a1a07546606a47217ebefaYani Ioannoustatic DEVICE_ATTR(temp##offset##_crit_enable, S_IRUGO | S_IWUSR, \
11511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	show_temp_crit_enable, set_temp_crit_enable);
11521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1153050480f12aeab62d39a1a07546606a47217ebefaYani Ioannoutemp_crit_enable(1);
1154050480f12aeab62d39a1a07546606a47217ebefaYani Ioannoutemp_crit_enable(2);
1155050480f12aeab62d39a1a07546606a47217ebefaYani Ioannoutemp_crit_enable(3);
11561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1157050480f12aeab62d39a1a07546606a47217ebefaYani Ioannoustatic ssize_t show_temp_crit(struct device *dev,
1158050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou		struct device_attribute *attr, char *buf)
11591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
1160050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou	struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr);
1161050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou	int nr = sensor_attr->index;
11621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct adm1026_data *data = adm1026_update_device(dev);
1163cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvare	return sprintf(buf, "%d\n", TEMP_FROM_REG(data->temp_crit[nr]));
11641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
1165050480f12aeab62d39a1a07546606a47217ebefaYani Ioannoustatic ssize_t set_temp_crit(struct device *dev, struct device_attribute *attr,
1166050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou		const char *buf, size_t count)
11671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
1168050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou	struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr);
1169050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou	int nr = sensor_attr->index;
11701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct i2c_client *client = to_i2c_client(dev);
11711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct adm1026_data *data = i2c_get_clientdata(client);
11721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int val = simple_strtol(buf, NULL, 10);
11731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
11749a61bf6300533d3b64d7ff29adfec00e596de67dIngo Molnar	mutex_lock(&data->update_lock);
11751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	data->temp_crit[nr] = TEMP_TO_REG(val);
11761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	adm1026_write_value(client, ADM1026_REG_TEMP_THERM[nr],
11771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		data->temp_crit[nr]);
11789a61bf6300533d3b64d7ff29adfec00e596de67dIngo Molnar	mutex_unlock(&data->update_lock);
11791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return count;
11801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
11811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1182050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou#define temp_crit_reg(offset)						\
1183050480f12aeab62d39a1a07546606a47217ebefaYani Ioannoustatic SENSOR_DEVICE_ATTR(temp##offset##_crit, S_IRUGO | S_IWUSR,	\
1184050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou		show_temp_crit, set_temp_crit, offset - 1);
11851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
11861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldstemp_crit_reg(1);
11871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldstemp_crit_reg(2);
11881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldstemp_crit_reg(3);
11891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
119074880c063b06efd103c924abfe19d9d8fa4864c4Yani Ioannoustatic ssize_t show_analog_out_reg(struct device *dev, struct device_attribute *attr, char *buf)
11911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
11921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct adm1026_data *data = adm1026_update_device(dev);
1193cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvare	return sprintf(buf, "%d\n", DAC_FROM_REG(data->analog_out));
11941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
119574880c063b06efd103c924abfe19d9d8fa4864c4Yani Ioannoustatic ssize_t set_analog_out_reg(struct device *dev, struct device_attribute *attr, const char *buf,
11961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		size_t count)
11971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
11981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct i2c_client *client = to_i2c_client(dev);
11991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct adm1026_data *data = i2c_get_clientdata(client);
12001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int val = simple_strtol(buf, NULL, 10);
12011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
12029a61bf6300533d3b64d7ff29adfec00e596de67dIngo Molnar	mutex_lock(&data->update_lock);
12031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	data->analog_out = DAC_TO_REG(val);
12041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	adm1026_write_value(client, ADM1026_REG_DAC, data->analog_out);
12059a61bf6300533d3b64d7ff29adfec00e596de67dIngo Molnar	mutex_unlock(&data->update_lock);
12061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return count;
12071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
12081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1209cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvarestatic DEVICE_ATTR(analog_out, S_IRUGO | S_IWUSR, show_analog_out_reg,
12101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	set_analog_out_reg);
12111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
121274880c063b06efd103c924abfe19d9d8fa4864c4Yani Ioannoustatic ssize_t show_vid_reg(struct device *dev, struct device_attribute *attr, char *buf)
12131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
12141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct adm1026_data *data = adm1026_update_device(dev);
1215a0cf354a71bd2969b2f1868530d3fecaebd6dc3dJean Delvare	int vid = (data->gpio >> 11) & 0x1f;
1216a0cf354a71bd2969b2f1868530d3fecaebd6dc3dJean Delvare
1217a0cf354a71bd2969b2f1868530d3fecaebd6dc3dJean Delvare	dev_dbg(dev, "Setting VID from GPIO11-15.\n");
1218a0cf354a71bd2969b2f1868530d3fecaebd6dc3dJean Delvare	return sprintf(buf, "%d\n", vid_from_reg(vid, data->vrm));
12191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
1220937df8df907ce63b0f7e19adf6e3cdef1687fac3Grant Coadystatic DEVICE_ATTR(cpu0_vid, S_IRUGO, show_vid_reg, NULL);
12211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
122274880c063b06efd103c924abfe19d9d8fa4864c4Yani Ioannoustatic ssize_t show_vrm_reg(struct device *dev, struct device_attribute *attr, char *buf)
12231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
122490d6619a916062cb75a176aacb318d108758b4a5Jean Delvare	struct adm1026_data *data = dev_get_drvdata(dev);
1225cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvare	return sprintf(buf, "%d\n", data->vrm);
12261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
122774880c063b06efd103c924abfe19d9d8fa4864c4Yani Ioannoustatic ssize_t store_vrm_reg(struct device *dev, struct device_attribute *attr, const char *buf,
12281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		size_t count)
12291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
1230f67fdabfb94b0bb96623a4b48d22be5329a06277Jean Delvare	struct adm1026_data *data = dev_get_drvdata(dev);
12311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
12321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	data->vrm = simple_strtol(buf, NULL, 10);
12331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return count;
12341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
12351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
12361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic DEVICE_ATTR(vrm, S_IRUGO | S_IWUSR, show_vrm_reg, store_vrm_reg);
12371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
123874880c063b06efd103c924abfe19d9d8fa4864c4Yani Ioannoustatic ssize_t show_alarms_reg(struct device *dev, struct device_attribute *attr, char *buf)
12391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
12401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct adm1026_data *data = adm1026_update_device(dev);
1241f67fdabfb94b0bb96623a4b48d22be5329a06277Jean Delvare	return sprintf(buf, "%ld\n", data->alarms);
12421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
12431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
12441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic DEVICE_ATTR(alarms, S_IRUGO, show_alarms_reg, NULL);
12451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1246a9273cb8eea503f6b8e28bd5f613962ecba278c5Jean Delvarestatic ssize_t show_alarm(struct device *dev, struct device_attribute *attr,
1247a9273cb8eea503f6b8e28bd5f613962ecba278c5Jean Delvare			  char *buf)
1248a9273cb8eea503f6b8e28bd5f613962ecba278c5Jean Delvare{
1249a9273cb8eea503f6b8e28bd5f613962ecba278c5Jean Delvare	struct adm1026_data *data = adm1026_update_device(dev);
1250a9273cb8eea503f6b8e28bd5f613962ecba278c5Jean Delvare	int bitnr = to_sensor_dev_attr(attr)->index;
1251a9273cb8eea503f6b8e28bd5f613962ecba278c5Jean Delvare	return sprintf(buf, "%ld\n", (data->alarms >> bitnr) & 1);
1252a9273cb8eea503f6b8e28bd5f613962ecba278c5Jean Delvare}
1253a9273cb8eea503f6b8e28bd5f613962ecba278c5Jean Delvare
1254a9273cb8eea503f6b8e28bd5f613962ecba278c5Jean Delvarestatic SENSOR_DEVICE_ATTR(temp2_alarm, S_IRUGO, show_alarm, NULL, 0);
1255a9273cb8eea503f6b8e28bd5f613962ecba278c5Jean Delvarestatic SENSOR_DEVICE_ATTR(temp3_alarm, S_IRUGO, show_alarm, NULL, 1);
1256a9273cb8eea503f6b8e28bd5f613962ecba278c5Jean Delvarestatic SENSOR_DEVICE_ATTR(in9_alarm, S_IRUGO, show_alarm, NULL, 1);
1257a9273cb8eea503f6b8e28bd5f613962ecba278c5Jean Delvarestatic SENSOR_DEVICE_ATTR(in11_alarm, S_IRUGO, show_alarm, NULL, 2);
1258a9273cb8eea503f6b8e28bd5f613962ecba278c5Jean Delvarestatic SENSOR_DEVICE_ATTR(in12_alarm, S_IRUGO, show_alarm, NULL, 3);
1259a9273cb8eea503f6b8e28bd5f613962ecba278c5Jean Delvarestatic SENSOR_DEVICE_ATTR(in13_alarm, S_IRUGO, show_alarm, NULL, 4);
1260a9273cb8eea503f6b8e28bd5f613962ecba278c5Jean Delvarestatic SENSOR_DEVICE_ATTR(in14_alarm, S_IRUGO, show_alarm, NULL, 5);
1261a9273cb8eea503f6b8e28bd5f613962ecba278c5Jean Delvarestatic SENSOR_DEVICE_ATTR(in15_alarm, S_IRUGO, show_alarm, NULL, 6);
1262a9273cb8eea503f6b8e28bd5f613962ecba278c5Jean Delvarestatic SENSOR_DEVICE_ATTR(in16_alarm, S_IRUGO, show_alarm, NULL, 7);
1263a9273cb8eea503f6b8e28bd5f613962ecba278c5Jean Delvarestatic SENSOR_DEVICE_ATTR(in0_alarm, S_IRUGO, show_alarm, NULL, 8);
1264a9273cb8eea503f6b8e28bd5f613962ecba278c5Jean Delvarestatic SENSOR_DEVICE_ATTR(in1_alarm, S_IRUGO, show_alarm, NULL, 9);
1265a9273cb8eea503f6b8e28bd5f613962ecba278c5Jean Delvarestatic SENSOR_DEVICE_ATTR(in2_alarm, S_IRUGO, show_alarm, NULL, 10);
1266a9273cb8eea503f6b8e28bd5f613962ecba278c5Jean Delvarestatic SENSOR_DEVICE_ATTR(in3_alarm, S_IRUGO, show_alarm, NULL, 11);
1267a9273cb8eea503f6b8e28bd5f613962ecba278c5Jean Delvarestatic SENSOR_DEVICE_ATTR(in4_alarm, S_IRUGO, show_alarm, NULL, 12);
1268a9273cb8eea503f6b8e28bd5f613962ecba278c5Jean Delvarestatic SENSOR_DEVICE_ATTR(in5_alarm, S_IRUGO, show_alarm, NULL, 13);
1269a9273cb8eea503f6b8e28bd5f613962ecba278c5Jean Delvarestatic SENSOR_DEVICE_ATTR(in6_alarm, S_IRUGO, show_alarm, NULL, 14);
1270a9273cb8eea503f6b8e28bd5f613962ecba278c5Jean Delvarestatic SENSOR_DEVICE_ATTR(in7_alarm, S_IRUGO, show_alarm, NULL, 15);
1271a9273cb8eea503f6b8e28bd5f613962ecba278c5Jean Delvarestatic SENSOR_DEVICE_ATTR(fan1_alarm, S_IRUGO, show_alarm, NULL, 16);
1272a9273cb8eea503f6b8e28bd5f613962ecba278c5Jean Delvarestatic SENSOR_DEVICE_ATTR(fan2_alarm, S_IRUGO, show_alarm, NULL, 17);
1273a9273cb8eea503f6b8e28bd5f613962ecba278c5Jean Delvarestatic SENSOR_DEVICE_ATTR(fan3_alarm, S_IRUGO, show_alarm, NULL, 18);
1274a9273cb8eea503f6b8e28bd5f613962ecba278c5Jean Delvarestatic SENSOR_DEVICE_ATTR(fan4_alarm, S_IRUGO, show_alarm, NULL, 19);
1275a9273cb8eea503f6b8e28bd5f613962ecba278c5Jean Delvarestatic SENSOR_DEVICE_ATTR(fan5_alarm, S_IRUGO, show_alarm, NULL, 20);
1276a9273cb8eea503f6b8e28bd5f613962ecba278c5Jean Delvarestatic SENSOR_DEVICE_ATTR(fan6_alarm, S_IRUGO, show_alarm, NULL, 21);
1277a9273cb8eea503f6b8e28bd5f613962ecba278c5Jean Delvarestatic SENSOR_DEVICE_ATTR(fan7_alarm, S_IRUGO, show_alarm, NULL, 22);
1278a9273cb8eea503f6b8e28bd5f613962ecba278c5Jean Delvarestatic SENSOR_DEVICE_ATTR(fan8_alarm, S_IRUGO, show_alarm, NULL, 23);
1279a9273cb8eea503f6b8e28bd5f613962ecba278c5Jean Delvarestatic SENSOR_DEVICE_ATTR(temp1_alarm, S_IRUGO, show_alarm, NULL, 24);
1280a9273cb8eea503f6b8e28bd5f613962ecba278c5Jean Delvarestatic SENSOR_DEVICE_ATTR(in10_alarm, S_IRUGO, show_alarm, NULL, 25);
1281a9273cb8eea503f6b8e28bd5f613962ecba278c5Jean Delvarestatic SENSOR_DEVICE_ATTR(in8_alarm, S_IRUGO, show_alarm, NULL, 26);
1282a9273cb8eea503f6b8e28bd5f613962ecba278c5Jean Delvare
128374880c063b06efd103c924abfe19d9d8fa4864c4Yani Ioannoustatic ssize_t show_alarm_mask(struct device *dev, struct device_attribute *attr, char *buf)
12841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
12851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct adm1026_data *data = adm1026_update_device(dev);
1286cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvare	return sprintf(buf, "%ld\n", data->alarm_mask);
12871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
128874880c063b06efd103c924abfe19d9d8fa4864c4Yani Ioannoustatic ssize_t set_alarm_mask(struct device *dev, struct device_attribute *attr, const char *buf,
12891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		size_t count)
12901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
12911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct i2c_client *client = to_i2c_client(dev);
12921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct adm1026_data *data = i2c_get_clientdata(client);
12931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int val = simple_strtol(buf, NULL, 10);
12941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	unsigned long mask;
12951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
12969a61bf6300533d3b64d7ff29adfec00e596de67dIngo Molnar	mutex_lock(&data->update_lock);
12971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	data->alarm_mask = val & 0x7fffffff;
12981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	mask = data->alarm_mask
12991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		| (data->gpio_mask & 0x10000 ? 0x80000000 : 0);
13001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	adm1026_write_value(client, ADM1026_REG_MASK1,
13011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		mask & 0xff);
13021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	mask >>= 8;
13031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	adm1026_write_value(client, ADM1026_REG_MASK2,
13041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		mask & 0xff);
13051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	mask >>= 8;
13061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	adm1026_write_value(client, ADM1026_REG_MASK3,
13071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		mask & 0xff);
13081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	mask >>= 8;
13091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	adm1026_write_value(client, ADM1026_REG_MASK4,
13101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		mask & 0xff);
13119a61bf6300533d3b64d7ff29adfec00e596de67dIngo Molnar	mutex_unlock(&data->update_lock);
13121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return count;
13131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
13141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
13151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic DEVICE_ATTR(alarm_mask, S_IRUGO | S_IWUSR, show_alarm_mask,
13161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	set_alarm_mask);
13171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
13181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
131974880c063b06efd103c924abfe19d9d8fa4864c4Yani Ioannoustatic ssize_t show_gpio(struct device *dev, struct device_attribute *attr, char *buf)
13201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
13211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct adm1026_data *data = adm1026_update_device(dev);
1322cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvare	return sprintf(buf, "%ld\n", data->gpio);
13231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
132474880c063b06efd103c924abfe19d9d8fa4864c4Yani Ioannoustatic ssize_t set_gpio(struct device *dev, struct device_attribute *attr, const char *buf,
13251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		size_t count)
13261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
13271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct i2c_client *client = to_i2c_client(dev);
13281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct adm1026_data *data = i2c_get_clientdata(client);
13291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int val = simple_strtol(buf, NULL, 10);
1330cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvare	long gpio;
13311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
13329a61bf6300533d3b64d7ff29adfec00e596de67dIngo Molnar	mutex_lock(&data->update_lock);
13331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	data->gpio = val & 0x1ffff;
13341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	gpio = data->gpio;
1335cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvare	adm1026_write_value(client, ADM1026_REG_GPIO_STATUS_0_7, gpio & 0xff);
13361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	gpio >>= 8;
1337cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvare	adm1026_write_value(client, ADM1026_REG_GPIO_STATUS_8_15, gpio & 0xff);
13381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	gpio = ((gpio >> 1) & 0x80) | (data->alarms >> 24 & 0x7f);
1339cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvare	adm1026_write_value(client, ADM1026_REG_STATUS4, gpio & 0xff);
13409a61bf6300533d3b64d7ff29adfec00e596de67dIngo Molnar	mutex_unlock(&data->update_lock);
13411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return count;
13421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
13431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
13441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic DEVICE_ATTR(gpio, S_IRUGO | S_IWUSR, show_gpio, set_gpio);
13451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
13461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
134774880c063b06efd103c924abfe19d9d8fa4864c4Yani Ioannoustatic ssize_t show_gpio_mask(struct device *dev, struct device_attribute *attr, char *buf)
13481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
13491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct adm1026_data *data = adm1026_update_device(dev);
1350cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvare	return sprintf(buf, "%ld\n", data->gpio_mask);
13511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
135274880c063b06efd103c924abfe19d9d8fa4864c4Yani Ioannoustatic ssize_t set_gpio_mask(struct device *dev, struct device_attribute *attr, const char *buf,
13531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		size_t count)
13541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
13551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct i2c_client *client = to_i2c_client(dev);
13561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct adm1026_data *data = i2c_get_clientdata(client);
13571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int val = simple_strtol(buf, NULL, 10);
1358cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvare	long mask;
13591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
13609a61bf6300533d3b64d7ff29adfec00e596de67dIngo Molnar	mutex_lock(&data->update_lock);
13611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	data->gpio_mask = val & 0x1ffff;
13621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	mask = data->gpio_mask;
1363cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvare	adm1026_write_value(client, ADM1026_REG_GPIO_MASK_0_7, mask & 0xff);
13641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	mask >>= 8;
1365cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvare	adm1026_write_value(client, ADM1026_REG_GPIO_MASK_8_15, mask & 0xff);
13661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	mask = ((mask >> 1) & 0x80) | (data->alarm_mask >> 24 & 0x7f);
1367cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvare	adm1026_write_value(client, ADM1026_REG_MASK1, mask & 0xff);
13689a61bf6300533d3b64d7ff29adfec00e596de67dIngo Molnar	mutex_unlock(&data->update_lock);
13691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return count;
13701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
13711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
13721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic DEVICE_ATTR(gpio_mask, S_IRUGO | S_IWUSR, show_gpio_mask, set_gpio_mask);
13731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
137474880c063b06efd103c924abfe19d9d8fa4864c4Yani Ioannoustatic ssize_t show_pwm_reg(struct device *dev, struct device_attribute *attr, char *buf)
13751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
13761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct adm1026_data *data = adm1026_update_device(dev);
1377cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvare	return sprintf(buf, "%d\n", PWM_FROM_REG(data->pwm1.pwm));
13781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
137974880c063b06efd103c924abfe19d9d8fa4864c4Yani Ioannoustatic ssize_t set_pwm_reg(struct device *dev, struct device_attribute *attr, const char *buf,
13801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		size_t count)
13811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
13821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct i2c_client *client = to_i2c_client(dev);
13831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct adm1026_data *data = i2c_get_clientdata(client);
13841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
13851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (data->pwm1.enable == 1) {
13861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		int val = simple_strtol(buf, NULL, 10);
13871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
13889a61bf6300533d3b64d7ff29adfec00e596de67dIngo Molnar		mutex_lock(&data->update_lock);
13891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		data->pwm1.pwm = PWM_TO_REG(val);
13901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		adm1026_write_value(client, ADM1026_REG_PWM, data->pwm1.pwm);
13919a61bf6300533d3b64d7ff29adfec00e596de67dIngo Molnar		mutex_unlock(&data->update_lock);
13921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
13931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return count;
13941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
139574880c063b06efd103c924abfe19d9d8fa4864c4Yani Ioannoustatic ssize_t show_auto_pwm_min(struct device *dev, struct device_attribute *attr, char *buf)
13961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
13971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct adm1026_data *data = adm1026_update_device(dev);
1398cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvare	return sprintf(buf, "%d\n", data->pwm1.auto_pwm_min);
13991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
140074880c063b06efd103c924abfe19d9d8fa4864c4Yani Ioannoustatic ssize_t set_auto_pwm_min(struct device *dev, struct device_attribute *attr, const char *buf,
14011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		size_t count)
14021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
14031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct i2c_client *client = to_i2c_client(dev);
14041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct adm1026_data *data = i2c_get_clientdata(client);
14051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int val = simple_strtol(buf, NULL, 10);
14061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
14079a61bf6300533d3b64d7ff29adfec00e596de67dIngo Molnar	mutex_lock(&data->update_lock);
1408cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvare	data->pwm1.auto_pwm_min = SENSORS_LIMIT(val, 0, 255);
14091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (data->pwm1.enable == 2) { /* apply immediately */
14101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		data->pwm1.pwm = PWM_TO_REG((data->pwm1.pwm & 0x0f) |
1411cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvare			PWM_MIN_TO_REG(data->pwm1.auto_pwm_min));
14121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		adm1026_write_value(client, ADM1026_REG_PWM, data->pwm1.pwm);
14131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
14149a61bf6300533d3b64d7ff29adfec00e596de67dIngo Molnar	mutex_unlock(&data->update_lock);
14151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return count;
14161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
141774880c063b06efd103c924abfe19d9d8fa4864c4Yani Ioannoustatic ssize_t show_auto_pwm_max(struct device *dev, struct device_attribute *attr, char *buf)
14181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
1419cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvare	return sprintf(buf, "%d\n", ADM1026_PWM_MAX);
14201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
142174880c063b06efd103c924abfe19d9d8fa4864c4Yani Ioannoustatic ssize_t show_pwm_enable(struct device *dev, struct device_attribute *attr, char *buf)
14221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
14231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct adm1026_data *data = adm1026_update_device(dev);
1424cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvare	return sprintf(buf, "%d\n", data->pwm1.enable);
14251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
142674880c063b06efd103c924abfe19d9d8fa4864c4Yani Ioannoustatic ssize_t set_pwm_enable(struct device *dev, struct device_attribute *attr, const char *buf,
14271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		size_t count)
14281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
14291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct i2c_client *client = to_i2c_client(dev);
14301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct adm1026_data *data = i2c_get_clientdata(client);
14311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int val = simple_strtol(buf, NULL, 10);
1432cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvare	int old_enable;
14331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
14341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if ((val >= 0) && (val < 3)) {
14359a61bf6300533d3b64d7ff29adfec00e596de67dIngo Molnar		mutex_lock(&data->update_lock);
14361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		old_enable = data->pwm1.enable;
14371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		data->pwm1.enable = val;
14381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		data->config1 = (data->config1 & ~CFG1_PWM_AFC)
14391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				| ((val == 2) ? CFG1_PWM_AFC : 0);
14401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		adm1026_write_value(client, ADM1026_REG_CONFIG1,
14411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			data->config1);
1442cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvare		if (val == 2) { /* apply pwm1_auto_pwm_min to pwm1 */
14431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			data->pwm1.pwm = PWM_TO_REG((data->pwm1.pwm & 0x0f) |
1444cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvare				PWM_MIN_TO_REG(data->pwm1.auto_pwm_min));
1445cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvare			adm1026_write_value(client, ADM1026_REG_PWM,
14461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				data->pwm1.pwm);
14471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		} else if (!((old_enable == 1) && (val == 1))) {
14481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			/* set pwm to safe value */
14491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			data->pwm1.pwm = 255;
1450cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvare			adm1026_write_value(client, ADM1026_REG_PWM,
14511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				data->pwm1.pwm);
14521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
14539a61bf6300533d3b64d7ff29adfec00e596de67dIngo Molnar		mutex_unlock(&data->update_lock);
14541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
14551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return count;
14561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
14571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
14581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* enable PWM fan control */
1459cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvarestatic DEVICE_ATTR(pwm1, S_IRUGO | S_IWUSR, show_pwm_reg, set_pwm_reg);
1460cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvarestatic DEVICE_ATTR(pwm2, S_IRUGO | S_IWUSR, show_pwm_reg, set_pwm_reg);
1461cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvarestatic DEVICE_ATTR(pwm3, S_IRUGO | S_IWUSR, show_pwm_reg, set_pwm_reg);
1462cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvarestatic DEVICE_ATTR(pwm1_enable, S_IRUGO | S_IWUSR, show_pwm_enable,
14631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	set_pwm_enable);
1464cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvarestatic DEVICE_ATTR(pwm2_enable, S_IRUGO | S_IWUSR, show_pwm_enable,
14651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	set_pwm_enable);
1466cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvarestatic DEVICE_ATTR(pwm3_enable, S_IRUGO | S_IWUSR, show_pwm_enable,
14671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	set_pwm_enable);
1468cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvarestatic DEVICE_ATTR(temp1_auto_point1_pwm, S_IRUGO | S_IWUSR,
14691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	show_auto_pwm_min, set_auto_pwm_min);
1470cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvarestatic DEVICE_ATTR(temp2_auto_point1_pwm, S_IRUGO | S_IWUSR,
14711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	show_auto_pwm_min, set_auto_pwm_min);
1472cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvarestatic DEVICE_ATTR(temp3_auto_point1_pwm, S_IRUGO | S_IWUSR,
14731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	show_auto_pwm_min, set_auto_pwm_min);
14741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
14751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic DEVICE_ATTR(temp1_auto_point2_pwm, S_IRUGO, show_auto_pwm_max, NULL);
14761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic DEVICE_ATTR(temp2_auto_point2_pwm, S_IRUGO, show_auto_pwm_max, NULL);
14771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic DEVICE_ATTR(temp3_auto_point2_pwm, S_IRUGO, show_auto_pwm_max, NULL);
14781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1479681c6f7a6702f208d48b501c8829dbc03a2ca238Mark M. Hoffmanstatic struct attribute *adm1026_attributes[] = {
1480681c6f7a6702f208d48b501c8829dbc03a2ca238Mark M. Hoffman	&sensor_dev_attr_in0_input.dev_attr.attr,
1481681c6f7a6702f208d48b501c8829dbc03a2ca238Mark M. Hoffman	&sensor_dev_attr_in0_max.dev_attr.attr,
1482681c6f7a6702f208d48b501c8829dbc03a2ca238Mark M. Hoffman	&sensor_dev_attr_in0_min.dev_attr.attr,
1483a9273cb8eea503f6b8e28bd5f613962ecba278c5Jean Delvare	&sensor_dev_attr_in0_alarm.dev_attr.attr,
1484681c6f7a6702f208d48b501c8829dbc03a2ca238Mark M. Hoffman	&sensor_dev_attr_in1_input.dev_attr.attr,
1485681c6f7a6702f208d48b501c8829dbc03a2ca238Mark M. Hoffman	&sensor_dev_attr_in1_max.dev_attr.attr,
1486681c6f7a6702f208d48b501c8829dbc03a2ca238Mark M. Hoffman	&sensor_dev_attr_in1_min.dev_attr.attr,
1487a9273cb8eea503f6b8e28bd5f613962ecba278c5Jean Delvare	&sensor_dev_attr_in1_alarm.dev_attr.attr,
1488681c6f7a6702f208d48b501c8829dbc03a2ca238Mark M. Hoffman	&sensor_dev_attr_in2_input.dev_attr.attr,
1489681c6f7a6702f208d48b501c8829dbc03a2ca238Mark M. Hoffman	&sensor_dev_attr_in2_max.dev_attr.attr,
1490681c6f7a6702f208d48b501c8829dbc03a2ca238Mark M. Hoffman	&sensor_dev_attr_in2_min.dev_attr.attr,
1491a9273cb8eea503f6b8e28bd5f613962ecba278c5Jean Delvare	&sensor_dev_attr_in2_alarm.dev_attr.attr,
1492681c6f7a6702f208d48b501c8829dbc03a2ca238Mark M. Hoffman	&sensor_dev_attr_in3_input.dev_attr.attr,
1493681c6f7a6702f208d48b501c8829dbc03a2ca238Mark M. Hoffman	&sensor_dev_attr_in3_max.dev_attr.attr,
1494681c6f7a6702f208d48b501c8829dbc03a2ca238Mark M. Hoffman	&sensor_dev_attr_in3_min.dev_attr.attr,
1495a9273cb8eea503f6b8e28bd5f613962ecba278c5Jean Delvare	&sensor_dev_attr_in3_alarm.dev_attr.attr,
1496681c6f7a6702f208d48b501c8829dbc03a2ca238Mark M. Hoffman	&sensor_dev_attr_in4_input.dev_attr.attr,
1497681c6f7a6702f208d48b501c8829dbc03a2ca238Mark M. Hoffman	&sensor_dev_attr_in4_max.dev_attr.attr,
1498681c6f7a6702f208d48b501c8829dbc03a2ca238Mark M. Hoffman	&sensor_dev_attr_in4_min.dev_attr.attr,
1499a9273cb8eea503f6b8e28bd5f613962ecba278c5Jean Delvare	&sensor_dev_attr_in4_alarm.dev_attr.attr,
1500681c6f7a6702f208d48b501c8829dbc03a2ca238Mark M. Hoffman	&sensor_dev_attr_in5_input.dev_attr.attr,
1501681c6f7a6702f208d48b501c8829dbc03a2ca238Mark M. Hoffman	&sensor_dev_attr_in5_max.dev_attr.attr,
1502681c6f7a6702f208d48b501c8829dbc03a2ca238Mark M. Hoffman	&sensor_dev_attr_in5_min.dev_attr.attr,
1503a9273cb8eea503f6b8e28bd5f613962ecba278c5Jean Delvare	&sensor_dev_attr_in5_alarm.dev_attr.attr,
1504681c6f7a6702f208d48b501c8829dbc03a2ca238Mark M. Hoffman	&sensor_dev_attr_in6_input.dev_attr.attr,
1505681c6f7a6702f208d48b501c8829dbc03a2ca238Mark M. Hoffman	&sensor_dev_attr_in6_max.dev_attr.attr,
1506681c6f7a6702f208d48b501c8829dbc03a2ca238Mark M. Hoffman	&sensor_dev_attr_in6_min.dev_attr.attr,
1507a9273cb8eea503f6b8e28bd5f613962ecba278c5Jean Delvare	&sensor_dev_attr_in6_alarm.dev_attr.attr,
1508681c6f7a6702f208d48b501c8829dbc03a2ca238Mark M. Hoffman	&sensor_dev_attr_in7_input.dev_attr.attr,
1509681c6f7a6702f208d48b501c8829dbc03a2ca238Mark M. Hoffman	&sensor_dev_attr_in7_max.dev_attr.attr,
1510681c6f7a6702f208d48b501c8829dbc03a2ca238Mark M. Hoffman	&sensor_dev_attr_in7_min.dev_attr.attr,
1511a9273cb8eea503f6b8e28bd5f613962ecba278c5Jean Delvare	&sensor_dev_attr_in7_alarm.dev_attr.attr,
1512681c6f7a6702f208d48b501c8829dbc03a2ca238Mark M. Hoffman	&sensor_dev_attr_in10_input.dev_attr.attr,
1513681c6f7a6702f208d48b501c8829dbc03a2ca238Mark M. Hoffman	&sensor_dev_attr_in10_max.dev_attr.attr,
1514681c6f7a6702f208d48b501c8829dbc03a2ca238Mark M. Hoffman	&sensor_dev_attr_in10_min.dev_attr.attr,
1515a9273cb8eea503f6b8e28bd5f613962ecba278c5Jean Delvare	&sensor_dev_attr_in10_alarm.dev_attr.attr,
1516681c6f7a6702f208d48b501c8829dbc03a2ca238Mark M. Hoffman	&sensor_dev_attr_in11_input.dev_attr.attr,
1517681c6f7a6702f208d48b501c8829dbc03a2ca238Mark M. Hoffman	&sensor_dev_attr_in11_max.dev_attr.attr,
1518681c6f7a6702f208d48b501c8829dbc03a2ca238Mark M. Hoffman	&sensor_dev_attr_in11_min.dev_attr.attr,
1519a9273cb8eea503f6b8e28bd5f613962ecba278c5Jean Delvare	&sensor_dev_attr_in11_alarm.dev_attr.attr,
1520681c6f7a6702f208d48b501c8829dbc03a2ca238Mark M. Hoffman	&sensor_dev_attr_in12_input.dev_attr.attr,
1521681c6f7a6702f208d48b501c8829dbc03a2ca238Mark M. Hoffman	&sensor_dev_attr_in12_max.dev_attr.attr,
1522681c6f7a6702f208d48b501c8829dbc03a2ca238Mark M. Hoffman	&sensor_dev_attr_in12_min.dev_attr.attr,
1523a9273cb8eea503f6b8e28bd5f613962ecba278c5Jean Delvare	&sensor_dev_attr_in12_alarm.dev_attr.attr,
1524681c6f7a6702f208d48b501c8829dbc03a2ca238Mark M. Hoffman	&sensor_dev_attr_in13_input.dev_attr.attr,
1525681c6f7a6702f208d48b501c8829dbc03a2ca238Mark M. Hoffman	&sensor_dev_attr_in13_max.dev_attr.attr,
1526681c6f7a6702f208d48b501c8829dbc03a2ca238Mark M. Hoffman	&sensor_dev_attr_in13_min.dev_attr.attr,
1527a9273cb8eea503f6b8e28bd5f613962ecba278c5Jean Delvare	&sensor_dev_attr_in13_alarm.dev_attr.attr,
1528681c6f7a6702f208d48b501c8829dbc03a2ca238Mark M. Hoffman	&sensor_dev_attr_in14_input.dev_attr.attr,
1529681c6f7a6702f208d48b501c8829dbc03a2ca238Mark M. Hoffman	&sensor_dev_attr_in14_max.dev_attr.attr,
1530681c6f7a6702f208d48b501c8829dbc03a2ca238Mark M. Hoffman	&sensor_dev_attr_in14_min.dev_attr.attr,
1531a9273cb8eea503f6b8e28bd5f613962ecba278c5Jean Delvare	&sensor_dev_attr_in14_alarm.dev_attr.attr,
1532681c6f7a6702f208d48b501c8829dbc03a2ca238Mark M. Hoffman	&sensor_dev_attr_in15_input.dev_attr.attr,
1533681c6f7a6702f208d48b501c8829dbc03a2ca238Mark M. Hoffman	&sensor_dev_attr_in15_max.dev_attr.attr,
1534681c6f7a6702f208d48b501c8829dbc03a2ca238Mark M. Hoffman	&sensor_dev_attr_in15_min.dev_attr.attr,
1535a9273cb8eea503f6b8e28bd5f613962ecba278c5Jean Delvare	&sensor_dev_attr_in15_alarm.dev_attr.attr,
1536681c6f7a6702f208d48b501c8829dbc03a2ca238Mark M. Hoffman	&sensor_dev_attr_in16_input.dev_attr.attr,
1537681c6f7a6702f208d48b501c8829dbc03a2ca238Mark M. Hoffman	&sensor_dev_attr_in16_max.dev_attr.attr,
1538681c6f7a6702f208d48b501c8829dbc03a2ca238Mark M. Hoffman	&sensor_dev_attr_in16_min.dev_attr.attr,
1539a9273cb8eea503f6b8e28bd5f613962ecba278c5Jean Delvare	&sensor_dev_attr_in16_alarm.dev_attr.attr,
1540681c6f7a6702f208d48b501c8829dbc03a2ca238Mark M. Hoffman	&sensor_dev_attr_fan1_input.dev_attr.attr,
1541681c6f7a6702f208d48b501c8829dbc03a2ca238Mark M. Hoffman	&sensor_dev_attr_fan1_div.dev_attr.attr,
1542681c6f7a6702f208d48b501c8829dbc03a2ca238Mark M. Hoffman	&sensor_dev_attr_fan1_min.dev_attr.attr,
1543a9273cb8eea503f6b8e28bd5f613962ecba278c5Jean Delvare	&sensor_dev_attr_fan1_alarm.dev_attr.attr,
1544681c6f7a6702f208d48b501c8829dbc03a2ca238Mark M. Hoffman	&sensor_dev_attr_fan2_input.dev_attr.attr,
1545681c6f7a6702f208d48b501c8829dbc03a2ca238Mark M. Hoffman	&sensor_dev_attr_fan2_div.dev_attr.attr,
1546681c6f7a6702f208d48b501c8829dbc03a2ca238Mark M. Hoffman	&sensor_dev_attr_fan2_min.dev_attr.attr,
1547a9273cb8eea503f6b8e28bd5f613962ecba278c5Jean Delvare	&sensor_dev_attr_fan2_alarm.dev_attr.attr,
1548681c6f7a6702f208d48b501c8829dbc03a2ca238Mark M. Hoffman	&sensor_dev_attr_fan3_input.dev_attr.attr,
1549681c6f7a6702f208d48b501c8829dbc03a2ca238Mark M. Hoffman	&sensor_dev_attr_fan3_div.dev_attr.attr,
1550681c6f7a6702f208d48b501c8829dbc03a2ca238Mark M. Hoffman	&sensor_dev_attr_fan3_min.dev_attr.attr,
1551a9273cb8eea503f6b8e28bd5f613962ecba278c5Jean Delvare	&sensor_dev_attr_fan3_alarm.dev_attr.attr,
1552681c6f7a6702f208d48b501c8829dbc03a2ca238Mark M. Hoffman	&sensor_dev_attr_fan4_input.dev_attr.attr,
1553681c6f7a6702f208d48b501c8829dbc03a2ca238Mark M. Hoffman	&sensor_dev_attr_fan4_div.dev_attr.attr,
1554681c6f7a6702f208d48b501c8829dbc03a2ca238Mark M. Hoffman	&sensor_dev_attr_fan4_min.dev_attr.attr,
1555a9273cb8eea503f6b8e28bd5f613962ecba278c5Jean Delvare	&sensor_dev_attr_fan4_alarm.dev_attr.attr,
1556681c6f7a6702f208d48b501c8829dbc03a2ca238Mark M. Hoffman	&sensor_dev_attr_fan5_input.dev_attr.attr,
1557681c6f7a6702f208d48b501c8829dbc03a2ca238Mark M. Hoffman	&sensor_dev_attr_fan5_div.dev_attr.attr,
1558681c6f7a6702f208d48b501c8829dbc03a2ca238Mark M. Hoffman	&sensor_dev_attr_fan5_min.dev_attr.attr,
1559a9273cb8eea503f6b8e28bd5f613962ecba278c5Jean Delvare	&sensor_dev_attr_fan5_alarm.dev_attr.attr,
1560681c6f7a6702f208d48b501c8829dbc03a2ca238Mark M. Hoffman	&sensor_dev_attr_fan6_input.dev_attr.attr,
1561681c6f7a6702f208d48b501c8829dbc03a2ca238Mark M. Hoffman	&sensor_dev_attr_fan6_div.dev_attr.attr,
1562681c6f7a6702f208d48b501c8829dbc03a2ca238Mark M. Hoffman	&sensor_dev_attr_fan6_min.dev_attr.attr,
1563a9273cb8eea503f6b8e28bd5f613962ecba278c5Jean Delvare	&sensor_dev_attr_fan6_alarm.dev_attr.attr,
1564681c6f7a6702f208d48b501c8829dbc03a2ca238Mark M. Hoffman	&sensor_dev_attr_fan7_input.dev_attr.attr,
1565681c6f7a6702f208d48b501c8829dbc03a2ca238Mark M. Hoffman	&sensor_dev_attr_fan7_div.dev_attr.attr,
1566681c6f7a6702f208d48b501c8829dbc03a2ca238Mark M. Hoffman	&sensor_dev_attr_fan7_min.dev_attr.attr,
1567a9273cb8eea503f6b8e28bd5f613962ecba278c5Jean Delvare	&sensor_dev_attr_fan7_alarm.dev_attr.attr,
1568681c6f7a6702f208d48b501c8829dbc03a2ca238Mark M. Hoffman	&sensor_dev_attr_fan8_input.dev_attr.attr,
1569681c6f7a6702f208d48b501c8829dbc03a2ca238Mark M. Hoffman	&sensor_dev_attr_fan8_div.dev_attr.attr,
1570681c6f7a6702f208d48b501c8829dbc03a2ca238Mark M. Hoffman	&sensor_dev_attr_fan8_min.dev_attr.attr,
1571a9273cb8eea503f6b8e28bd5f613962ecba278c5Jean Delvare	&sensor_dev_attr_fan8_alarm.dev_attr.attr,
1572681c6f7a6702f208d48b501c8829dbc03a2ca238Mark M. Hoffman	&sensor_dev_attr_temp1_input.dev_attr.attr,
1573681c6f7a6702f208d48b501c8829dbc03a2ca238Mark M. Hoffman	&sensor_dev_attr_temp1_max.dev_attr.attr,
1574681c6f7a6702f208d48b501c8829dbc03a2ca238Mark M. Hoffman	&sensor_dev_attr_temp1_min.dev_attr.attr,
1575a9273cb8eea503f6b8e28bd5f613962ecba278c5Jean Delvare	&sensor_dev_attr_temp1_alarm.dev_attr.attr,
1576681c6f7a6702f208d48b501c8829dbc03a2ca238Mark M. Hoffman	&sensor_dev_attr_temp2_input.dev_attr.attr,
1577681c6f7a6702f208d48b501c8829dbc03a2ca238Mark M. Hoffman	&sensor_dev_attr_temp2_max.dev_attr.attr,
1578681c6f7a6702f208d48b501c8829dbc03a2ca238Mark M. Hoffman	&sensor_dev_attr_temp2_min.dev_attr.attr,
1579a9273cb8eea503f6b8e28bd5f613962ecba278c5Jean Delvare	&sensor_dev_attr_temp2_alarm.dev_attr.attr,
1580681c6f7a6702f208d48b501c8829dbc03a2ca238Mark M. Hoffman	&sensor_dev_attr_temp1_offset.dev_attr.attr,
1581681c6f7a6702f208d48b501c8829dbc03a2ca238Mark M. Hoffman	&sensor_dev_attr_temp2_offset.dev_attr.attr,
1582681c6f7a6702f208d48b501c8829dbc03a2ca238Mark M. Hoffman	&sensor_dev_attr_temp1_auto_point1_temp.dev_attr.attr,
1583681c6f7a6702f208d48b501c8829dbc03a2ca238Mark M. Hoffman	&sensor_dev_attr_temp2_auto_point1_temp.dev_attr.attr,
1584681c6f7a6702f208d48b501c8829dbc03a2ca238Mark M. Hoffman	&sensor_dev_attr_temp1_auto_point1_temp_hyst.dev_attr.attr,
1585681c6f7a6702f208d48b501c8829dbc03a2ca238Mark M. Hoffman	&sensor_dev_attr_temp2_auto_point1_temp_hyst.dev_attr.attr,
1586681c6f7a6702f208d48b501c8829dbc03a2ca238Mark M. Hoffman	&sensor_dev_attr_temp1_auto_point2_temp.dev_attr.attr,
1587681c6f7a6702f208d48b501c8829dbc03a2ca238Mark M. Hoffman	&sensor_dev_attr_temp2_auto_point2_temp.dev_attr.attr,
1588681c6f7a6702f208d48b501c8829dbc03a2ca238Mark M. Hoffman	&sensor_dev_attr_temp1_crit.dev_attr.attr,
1589681c6f7a6702f208d48b501c8829dbc03a2ca238Mark M. Hoffman	&sensor_dev_attr_temp2_crit.dev_attr.attr,
1590681c6f7a6702f208d48b501c8829dbc03a2ca238Mark M. Hoffman	&dev_attr_temp1_crit_enable.attr,
1591681c6f7a6702f208d48b501c8829dbc03a2ca238Mark M. Hoffman	&dev_attr_temp2_crit_enable.attr,
1592681c6f7a6702f208d48b501c8829dbc03a2ca238Mark M. Hoffman	&dev_attr_cpu0_vid.attr,
1593681c6f7a6702f208d48b501c8829dbc03a2ca238Mark M. Hoffman	&dev_attr_vrm.attr,
1594681c6f7a6702f208d48b501c8829dbc03a2ca238Mark M. Hoffman	&dev_attr_alarms.attr,
1595681c6f7a6702f208d48b501c8829dbc03a2ca238Mark M. Hoffman	&dev_attr_alarm_mask.attr,
1596681c6f7a6702f208d48b501c8829dbc03a2ca238Mark M. Hoffman	&dev_attr_gpio.attr,
1597681c6f7a6702f208d48b501c8829dbc03a2ca238Mark M. Hoffman	&dev_attr_gpio_mask.attr,
1598681c6f7a6702f208d48b501c8829dbc03a2ca238Mark M. Hoffman	&dev_attr_pwm1.attr,
1599681c6f7a6702f208d48b501c8829dbc03a2ca238Mark M. Hoffman	&dev_attr_pwm2.attr,
1600681c6f7a6702f208d48b501c8829dbc03a2ca238Mark M. Hoffman	&dev_attr_pwm3.attr,
1601681c6f7a6702f208d48b501c8829dbc03a2ca238Mark M. Hoffman	&dev_attr_pwm1_enable.attr,
1602681c6f7a6702f208d48b501c8829dbc03a2ca238Mark M. Hoffman	&dev_attr_pwm2_enable.attr,
1603681c6f7a6702f208d48b501c8829dbc03a2ca238Mark M. Hoffman	&dev_attr_pwm3_enable.attr,
1604681c6f7a6702f208d48b501c8829dbc03a2ca238Mark M. Hoffman	&dev_attr_temp1_auto_point1_pwm.attr,
1605681c6f7a6702f208d48b501c8829dbc03a2ca238Mark M. Hoffman	&dev_attr_temp2_auto_point1_pwm.attr,
1606681c6f7a6702f208d48b501c8829dbc03a2ca238Mark M. Hoffman	&dev_attr_temp1_auto_point2_pwm.attr,
1607681c6f7a6702f208d48b501c8829dbc03a2ca238Mark M. Hoffman	&dev_attr_temp2_auto_point2_pwm.attr,
1608681c6f7a6702f208d48b501c8829dbc03a2ca238Mark M. Hoffman	&dev_attr_analog_out.attr,
1609681c6f7a6702f208d48b501c8829dbc03a2ca238Mark M. Hoffman	NULL
1610681c6f7a6702f208d48b501c8829dbc03a2ca238Mark M. Hoffman};
1611681c6f7a6702f208d48b501c8829dbc03a2ca238Mark M. Hoffman
1612681c6f7a6702f208d48b501c8829dbc03a2ca238Mark M. Hoffmanstatic const struct attribute_group adm1026_group = {
1613681c6f7a6702f208d48b501c8829dbc03a2ca238Mark M. Hoffman	.attrs = adm1026_attributes,
1614681c6f7a6702f208d48b501c8829dbc03a2ca238Mark M. Hoffman};
1615681c6f7a6702f208d48b501c8829dbc03a2ca238Mark M. Hoffman
16165b34dbcd88251508d02e48ad9b0f9b8232a13ee0Jean Delvarestatic struct attribute *adm1026_attributes_temp3[] = {
16175b34dbcd88251508d02e48ad9b0f9b8232a13ee0Jean Delvare	&sensor_dev_attr_temp3_input.dev_attr.attr,
16185b34dbcd88251508d02e48ad9b0f9b8232a13ee0Jean Delvare	&sensor_dev_attr_temp3_max.dev_attr.attr,
16195b34dbcd88251508d02e48ad9b0f9b8232a13ee0Jean Delvare	&sensor_dev_attr_temp3_min.dev_attr.attr,
16205b34dbcd88251508d02e48ad9b0f9b8232a13ee0Jean Delvare	&sensor_dev_attr_temp3_alarm.dev_attr.attr,
16215b34dbcd88251508d02e48ad9b0f9b8232a13ee0Jean Delvare	&sensor_dev_attr_temp3_offset.dev_attr.attr,
16225b34dbcd88251508d02e48ad9b0f9b8232a13ee0Jean Delvare	&sensor_dev_attr_temp3_auto_point1_temp.dev_attr.attr,
16235b34dbcd88251508d02e48ad9b0f9b8232a13ee0Jean Delvare	&sensor_dev_attr_temp3_auto_point1_temp_hyst.dev_attr.attr,
16245b34dbcd88251508d02e48ad9b0f9b8232a13ee0Jean Delvare	&sensor_dev_attr_temp3_auto_point2_temp.dev_attr.attr,
16255b34dbcd88251508d02e48ad9b0f9b8232a13ee0Jean Delvare	&sensor_dev_attr_temp3_crit.dev_attr.attr,
16265b34dbcd88251508d02e48ad9b0f9b8232a13ee0Jean Delvare	&dev_attr_temp3_crit_enable.attr,
16275b34dbcd88251508d02e48ad9b0f9b8232a13ee0Jean Delvare	&dev_attr_temp3_auto_point1_pwm.attr,
16285b34dbcd88251508d02e48ad9b0f9b8232a13ee0Jean Delvare	&dev_attr_temp3_auto_point2_pwm.attr,
16291d5f2c16c6125ae6da1435ac5a190ae08429902aJean Delvare	NULL
16305b34dbcd88251508d02e48ad9b0f9b8232a13ee0Jean Delvare};
16315b34dbcd88251508d02e48ad9b0f9b8232a13ee0Jean Delvare
16325b34dbcd88251508d02e48ad9b0f9b8232a13ee0Jean Delvarestatic const struct attribute_group adm1026_group_temp3 = {
16335b34dbcd88251508d02e48ad9b0f9b8232a13ee0Jean Delvare	.attrs = adm1026_attributes_temp3,
16345b34dbcd88251508d02e48ad9b0f9b8232a13ee0Jean Delvare};
16355b34dbcd88251508d02e48ad9b0f9b8232a13ee0Jean Delvare
16365b34dbcd88251508d02e48ad9b0f9b8232a13ee0Jean Delvarestatic struct attribute *adm1026_attributes_in8_9[] = {
16375b34dbcd88251508d02e48ad9b0f9b8232a13ee0Jean Delvare	&sensor_dev_attr_in8_input.dev_attr.attr,
16385b34dbcd88251508d02e48ad9b0f9b8232a13ee0Jean Delvare	&sensor_dev_attr_in8_max.dev_attr.attr,
16395b34dbcd88251508d02e48ad9b0f9b8232a13ee0Jean Delvare	&sensor_dev_attr_in8_min.dev_attr.attr,
16405b34dbcd88251508d02e48ad9b0f9b8232a13ee0Jean Delvare	&sensor_dev_attr_in8_alarm.dev_attr.attr,
16415b34dbcd88251508d02e48ad9b0f9b8232a13ee0Jean Delvare	&sensor_dev_attr_in9_input.dev_attr.attr,
16425b34dbcd88251508d02e48ad9b0f9b8232a13ee0Jean Delvare	&sensor_dev_attr_in9_max.dev_attr.attr,
16435b34dbcd88251508d02e48ad9b0f9b8232a13ee0Jean Delvare	&sensor_dev_attr_in9_min.dev_attr.attr,
16445b34dbcd88251508d02e48ad9b0f9b8232a13ee0Jean Delvare	&sensor_dev_attr_in9_alarm.dev_attr.attr,
16451d5f2c16c6125ae6da1435ac5a190ae08429902aJean Delvare	NULL
16465b34dbcd88251508d02e48ad9b0f9b8232a13ee0Jean Delvare};
16475b34dbcd88251508d02e48ad9b0f9b8232a13ee0Jean Delvare
16485b34dbcd88251508d02e48ad9b0f9b8232a13ee0Jean Delvarestatic const struct attribute_group adm1026_group_in8_9 = {
16495b34dbcd88251508d02e48ad9b0f9b8232a13ee0Jean Delvare	.attrs = adm1026_attributes_in8_9,
16505b34dbcd88251508d02e48ad9b0f9b8232a13ee0Jean Delvare};
16515b34dbcd88251508d02e48ad9b0f9b8232a13ee0Jean Delvare
165257f7eb0bcb2316dc264cd26f38b33dd2cf3151c1Jean Delvare/* Return 0 if detection is successful, -ENODEV otherwise */
165357f7eb0bcb2316dc264cd26f38b33dd2cf3151c1Jean Delvarestatic int adm1026_detect(struct i2c_client *client, int kind,
165457f7eb0bcb2316dc264cd26f38b33dd2cf3151c1Jean Delvare			  struct i2c_board_info *info)
16551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
165657f7eb0bcb2316dc264cd26f38b33dd2cf3151c1Jean Delvare	struct i2c_adapter *adapter = client->adapter;
165757f7eb0bcb2316dc264cd26f38b33dd2cf3151c1Jean Delvare	int address = client->addr;
16581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int company, verstep;
16591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
16601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA)) {
16611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		/* We need to be able to do byte I/O */
166257f7eb0bcb2316dc264cd26f38b33dd2cf3151c1Jean Delvare		return -ENODEV;
16631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	};
16641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
16651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* Now, we do the remaining detection. */
16661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1667f67fdabfb94b0bb96623a4b48d22be5329a06277Jean Delvare	company = adm1026_read_value(client, ADM1026_REG_COMPANY);
1668f67fdabfb94b0bb96623a4b48d22be5329a06277Jean Delvare	verstep = adm1026_read_value(client, ADM1026_REG_VERSTEP);
16691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
167057f7eb0bcb2316dc264cd26f38b33dd2cf3151c1Jean Delvare	dev_dbg(&adapter->dev, "Detecting device at %d,0x%02x with"
16711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		" COMPANY: 0x%02x and VERSTEP: 0x%02x\n",
1672f67fdabfb94b0bb96623a4b48d22be5329a06277Jean Delvare		i2c_adapter_id(client->adapter), client->addr,
16731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		company, verstep);
16741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
167552df6440a29123eed912183fe785bbe174ef14b9Jean Delvare	/* Determine the chip type. */
167652df6440a29123eed912183fe785bbe174ef14b9Jean Delvare	dev_dbg(&adapter->dev, "Autodetecting device at %d,0x%02x...\n",
167752df6440a29123eed912183fe785bbe174ef14b9Jean Delvare		i2c_adapter_id(adapter), address);
167852df6440a29123eed912183fe785bbe174ef14b9Jean Delvare	if (company == ADM1026_COMPANY_ANALOG_DEV
167952df6440a29123eed912183fe785bbe174ef14b9Jean Delvare	    && verstep == ADM1026_VERSTEP_ADM1026) {
168052df6440a29123eed912183fe785bbe174ef14b9Jean Delvare		/* Analog Devices ADM1026 */
168152df6440a29123eed912183fe785bbe174ef14b9Jean Delvare	} else if (company == ADM1026_COMPANY_ANALOG_DEV
168252df6440a29123eed912183fe785bbe174ef14b9Jean Delvare		&& (verstep & 0xf0) == ADM1026_VERSTEP_GENERIC) {
168352df6440a29123eed912183fe785bbe174ef14b9Jean Delvare		dev_err(&adapter->dev, "Unrecognized stepping "
168452df6440a29123eed912183fe785bbe174ef14b9Jean Delvare			"0x%02x. Defaulting to ADM1026.\n", verstep);
168552df6440a29123eed912183fe785bbe174ef14b9Jean Delvare	} else if ((verstep & 0xf0) == ADM1026_VERSTEP_GENERIC) {
168652df6440a29123eed912183fe785bbe174ef14b9Jean Delvare		dev_err(&adapter->dev, "Found version/stepping "
168752df6440a29123eed912183fe785bbe174ef14b9Jean Delvare			"0x%02x. Assuming generic ADM1026.\n",
168852df6440a29123eed912183fe785bbe174ef14b9Jean Delvare			verstep);
168952df6440a29123eed912183fe785bbe174ef14b9Jean Delvare	} else {
169052df6440a29123eed912183fe785bbe174ef14b9Jean Delvare		dev_dbg(&adapter->dev, "Autodetection failed\n");
169152df6440a29123eed912183fe785bbe174ef14b9Jean Delvare		/* Not an ADM1026... */
169252df6440a29123eed912183fe785bbe174ef14b9Jean Delvare		return -ENODEV;
16931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
169452df6440a29123eed912183fe785bbe174ef14b9Jean Delvare
169557f7eb0bcb2316dc264cd26f38b33dd2cf3151c1Jean Delvare	strlcpy(info->type, "adm1026", I2C_NAME_SIZE);
16961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
169757f7eb0bcb2316dc264cd26f38b33dd2cf3151c1Jean Delvare	return 0;
169857f7eb0bcb2316dc264cd26f38b33dd2cf3151c1Jean Delvare}
169957f7eb0bcb2316dc264cd26f38b33dd2cf3151c1Jean Delvare
170057f7eb0bcb2316dc264cd26f38b33dd2cf3151c1Jean Delvarestatic int adm1026_probe(struct i2c_client *client,
170157f7eb0bcb2316dc264cd26f38b33dd2cf3151c1Jean Delvare			 const struct i2c_device_id *id)
170257f7eb0bcb2316dc264cd26f38b33dd2cf3151c1Jean Delvare{
170357f7eb0bcb2316dc264cd26f38b33dd2cf3151c1Jean Delvare	struct adm1026_data *data;
170457f7eb0bcb2316dc264cd26f38b33dd2cf3151c1Jean Delvare	int err;
170557f7eb0bcb2316dc264cd26f38b33dd2cf3151c1Jean Delvare
170657f7eb0bcb2316dc264cd26f38b33dd2cf3151c1Jean Delvare	data = kzalloc(sizeof(struct adm1026_data), GFP_KERNEL);
170757f7eb0bcb2316dc264cd26f38b33dd2cf3151c1Jean Delvare	if (!data) {
170857f7eb0bcb2316dc264cd26f38b33dd2cf3151c1Jean Delvare		err = -ENOMEM;
170957f7eb0bcb2316dc264cd26f38b33dd2cf3151c1Jean Delvare		goto exit;
17101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
17111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
171257f7eb0bcb2316dc264cd26f38b33dd2cf3151c1Jean Delvare	i2c_set_clientdata(client, data);
17139a61bf6300533d3b64d7ff29adfec00e596de67dIngo Molnar	mutex_init(&data->update_lock);
17141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
17151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* Set the VRM version */
1716303760b44a7a142cb9f4c9df4609fb63bbda98dbJean Delvare	data->vrm = vid_which_vrm();
17171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
17181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* Initialize the ADM1026 chip */
1719f67fdabfb94b0bb96623a4b48d22be5329a06277Jean Delvare	adm1026_init_client(client);
17201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
17211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* Register sysfs hooks */
1722f67fdabfb94b0bb96623a4b48d22be5329a06277Jean Delvare	if ((err = sysfs_create_group(&client->dev.kobj, &adm1026_group)))
172357f7eb0bcb2316dc264cd26f38b33dd2cf3151c1Jean Delvare		goto exitfree;
17245b34dbcd88251508d02e48ad9b0f9b8232a13ee0Jean Delvare	if (data->config1 & CFG1_AIN8_9)
17255b34dbcd88251508d02e48ad9b0f9b8232a13ee0Jean Delvare		err = sysfs_create_group(&client->dev.kobj,
17265b34dbcd88251508d02e48ad9b0f9b8232a13ee0Jean Delvare					 &adm1026_group_in8_9);
17275b34dbcd88251508d02e48ad9b0f9b8232a13ee0Jean Delvare	else
17285b34dbcd88251508d02e48ad9b0f9b8232a13ee0Jean Delvare		err = sysfs_create_group(&client->dev.kobj,
17295b34dbcd88251508d02e48ad9b0f9b8232a13ee0Jean Delvare					 &adm1026_group_temp3);
17305b34dbcd88251508d02e48ad9b0f9b8232a13ee0Jean Delvare	if (err)
17315b34dbcd88251508d02e48ad9b0f9b8232a13ee0Jean Delvare		goto exitremove;
1732681c6f7a6702f208d48b501c8829dbc03a2ca238Mark M. Hoffman
1733f67fdabfb94b0bb96623a4b48d22be5329a06277Jean Delvare	data->hwmon_dev = hwmon_device_register(&client->dev);
17341beeffe43311f64df8dd0ab08ff6b1858c58363fTony Jones	if (IS_ERR(data->hwmon_dev)) {
17351beeffe43311f64df8dd0ab08ff6b1858c58363fTony Jones		err = PTR_ERR(data->hwmon_dev);
1736681c6f7a6702f208d48b501c8829dbc03a2ca238Mark M. Hoffman		goto exitremove;
1737943b0830cebe4711354945ed3cb44e84152aaca0Mark M. Hoffman	}
1738943b0830cebe4711354945ed3cb44e84152aaca0Mark M. Hoffman
17391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return 0;
17401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
17411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* Error out and cleanup code */
1742681c6f7a6702f208d48b501c8829dbc03a2ca238Mark M. Hoffmanexitremove:
1743f67fdabfb94b0bb96623a4b48d22be5329a06277Jean Delvare	sysfs_remove_group(&client->dev.kobj, &adm1026_group);
17445b34dbcd88251508d02e48ad9b0f9b8232a13ee0Jean Delvare	if (data->config1 & CFG1_AIN8_9)
17455b34dbcd88251508d02e48ad9b0f9b8232a13ee0Jean Delvare		sysfs_remove_group(&client->dev.kobj, &adm1026_group_in8_9);
17465b34dbcd88251508d02e48ad9b0f9b8232a13ee0Jean Delvare	else
17475b34dbcd88251508d02e48ad9b0f9b8232a13ee0Jean Delvare		sysfs_remove_group(&client->dev.kobj, &adm1026_group_temp3);
17481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsexitfree:
17491f57ff89fee47a317e9e8ca63bf0f139802cc116Alexey Dobriyan	kfree(data);
17501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsexit:
17511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return err;
17521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
1753681c6f7a6702f208d48b501c8829dbc03a2ca238Mark M. Hoffman
175457f7eb0bcb2316dc264cd26f38b33dd2cf3151c1Jean Delvarestatic int adm1026_remove(struct i2c_client *client)
1755681c6f7a6702f208d48b501c8829dbc03a2ca238Mark M. Hoffman{
1756681c6f7a6702f208d48b501c8829dbc03a2ca238Mark M. Hoffman	struct adm1026_data *data = i2c_get_clientdata(client);
17571beeffe43311f64df8dd0ab08ff6b1858c58363fTony Jones	hwmon_device_unregister(data->hwmon_dev);
1758681c6f7a6702f208d48b501c8829dbc03a2ca238Mark M. Hoffman	sysfs_remove_group(&client->dev.kobj, &adm1026_group);
17595b34dbcd88251508d02e48ad9b0f9b8232a13ee0Jean Delvare	if (data->config1 & CFG1_AIN8_9)
17605b34dbcd88251508d02e48ad9b0f9b8232a13ee0Jean Delvare		sysfs_remove_group(&client->dev.kobj, &adm1026_group_in8_9);
17615b34dbcd88251508d02e48ad9b0f9b8232a13ee0Jean Delvare	else
17625b34dbcd88251508d02e48ad9b0f9b8232a13ee0Jean Delvare		sysfs_remove_group(&client->dev.kobj, &adm1026_group_temp3);
1763681c6f7a6702f208d48b501c8829dbc03a2ca238Mark M. Hoffman	kfree(data);
1764681c6f7a6702f208d48b501c8829dbc03a2ca238Mark M. Hoffman	return 0;
1765681c6f7a6702f208d48b501c8829dbc03a2ca238Mark M. Hoffman}
1766681c6f7a6702f208d48b501c8829dbc03a2ca238Mark M. Hoffman
17671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int __init sm_adm1026_init(void)
17681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
17691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return i2c_add_driver(&adm1026_driver);
17701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
17711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1772cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvarestatic void __exit sm_adm1026_exit(void)
17731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
17741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	i2c_del_driver(&adm1026_driver);
17751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
17761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
17771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsMODULE_LICENSE("GPL");
17781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsMODULE_AUTHOR("Philip Pokorny <ppokorny@penguincomputing.com>, "
1779cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvare	      "Justin Thiessen <jthiessen@penguincomputing.com>");
17801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsMODULE_DESCRIPTION("ADM1026 driver");
17811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
17821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsmodule_init(sm_adm1026_init);
17831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsmodule_exit(sm_adm1026_exit);
1784