adm1026.c revision 2ed2dc3c116d26fc6a9384e83d136b15cc203b6c
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>
311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/i2c-sensor.h>
321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/i2c-vid.h>
3310c08f8100ee2c4d27b862635574cdf4ef439e67Jean Delvare#include <linux/hwmon-sysfs.h>
34943b0830cebe4711354945ed3cb44e84152aaca0Mark M. Hoffman#include <linux/hwmon.h>
35943b0830cebe4711354945ed3cb44e84152aaca0Mark M. Hoffman#include <linux/err.h>
361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* Addresses to scan */
381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic unsigned short normal_i2c[] = { 0x2c, 0x2d, 0x2e, I2C_CLIENT_END };
391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* Insmod parameters */
411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsSENSORS_INSMOD_1(adm1026);
421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int gpio_input[17]  = { -1, -1, -1, -1, -1, -1, -1, -1, -1,
441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				-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 };
521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsmodule_param_array(gpio_input,int,NULL,0);
531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsMODULE_PARM_DESC(gpio_input,"List of GPIO pins (0-16) to program as inputs");
541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsmodule_param_array(gpio_output,int,NULL,0);
551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsMODULE_PARM_DESC(gpio_output,"List of GPIO pins (0-16) to program as "
561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	"outputs");
571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsmodule_param_array(gpio_inverted,int,NULL,0);
581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsMODULE_PARM_DESC(gpio_inverted,"List of GPIO pins (0-16) to program as "
591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	"inverted");
601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsmodule_param_array(gpio_normal,int,NULL,0);
611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsMODULE_PARM_DESC(gpio_normal,"List of GPIO pins (0-16) to program as "
621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	"normal/non-inverted");
631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsmodule_param_array(gpio_fan,int,NULL,0);
641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsMODULE_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 */
691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define ADM1026_REG_CONFIG1  0x00
701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define CFG1_MONITOR     0x01
711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define CFG1_INT_ENABLE  0x02
721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define CFG1_INT_CLEAR   0x04
731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define CFG1_AIN8_9      0x08
741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define CFG1_THERM_HOT   0x10
751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define CFG1_DAC_AFC     0x20
761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define CFG1_PWM_AFC     0x40
771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define CFG1_RESET       0x80
781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define ADM1026_REG_CONFIG2  0x01
791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* CONFIG2 controls FAN0/GPIO0 through FAN7/GPIO7 */
801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define ADM1026_REG_CONFIG3  0x07
811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define CFG3_GPIO16_ENABLE  0x01
821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define CFG3_CI_CLEAR  0x02
831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define CFG3_VREF_250  0x04
841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define CFG3_GPIO16_DIR  0x40
851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define CFG3_GPIO16_POL  0x80
861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define ADM1026_REG_E2CONFIG  0x13
871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define E2CFG_READ  0x01
881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define E2CFG_WRITE  0x02
891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define E2CFG_ERASE  0x04
901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define E2CFG_ROM  0x08
911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define E2CFG_CLK_EXT  0x80
921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* There are 10 general analog inputs and 7 dedicated inputs
941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * They are:
951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *    0 - 9  =  AIN0 - AIN9
961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *       10  =  Vbat
971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *       11  =  3.3V Standby
981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *       12  =  3.3V Main
991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *       13  =  +5V
1001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *       14  =  Vccp (CPU core voltage)
1011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *       15  =  +12V
1021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *       16  =  -12V
1031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
1041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic u16 ADM1026_REG_IN[] = {
1051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		0x30, 0x31, 0x32, 0x33, 0x34, 0x35,
1061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		0x36, 0x37, 0x27, 0x29, 0x26, 0x2a,
1071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		0x2b, 0x2c, 0x2d, 0x2e, 0x2f
1081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	};
1091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic u16 ADM1026_REG_IN_MIN[] = {
1101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		0x58, 0x59, 0x5a, 0x5b, 0x5c, 0x5d,
1111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		0x5e, 0x5f, 0x6d, 0x49, 0x6b, 0x4a,
1121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		0x4b, 0x4c, 0x4d, 0x4e, 0x4f
1131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	};
1141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic u16 ADM1026_REG_IN_MAX[] = {
1151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		0x50, 0x51, 0x52, 0x53, 0x54, 0x55,
1161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		0x56, 0x57, 0x6c, 0x41, 0x6a, 0x42,
1171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		0x43, 0x44, 0x45, 0x46, 0x47
1181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	};
1191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* Temperatures are:
1211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *    0 - Internal
1221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *    1 - External 1
1231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *    2 - External 2
1241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
1251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic u16 ADM1026_REG_TEMP[] = { 0x1f, 0x28, 0x29 };
1261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic u16 ADM1026_REG_TEMP_MIN[] = { 0x69, 0x48, 0x49 };
1271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic u16 ADM1026_REG_TEMP_MAX[] = { 0x68, 0x40, 0x41 };
1281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic u16 ADM1026_REG_TEMP_TMIN[] = { 0x10, 0x11, 0x12 };
1291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic u16 ADM1026_REG_TEMP_THERM[] = { 0x0d, 0x0e, 0x0f };
1301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic u16 ADM1026_REG_TEMP_OFFSET[] = { 0x1e, 0x6e, 0x6f };
1311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define ADM1026_REG_FAN(nr) (0x38 + (nr))
1331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define ADM1026_REG_FAN_MIN(nr) (0x60 + (nr))
1341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define ADM1026_REG_FAN_DIV_0_3 0x02
1351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define ADM1026_REG_FAN_DIV_4_7 0x03
1361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define ADM1026_REG_DAC  0x04
1381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define ADM1026_REG_PWM  0x05
1391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define ADM1026_REG_GPIO_CFG_0_3 0x08
1411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define ADM1026_REG_GPIO_CFG_4_7 0x09
1421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define ADM1026_REG_GPIO_CFG_8_11 0x0a
1431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define ADM1026_REG_GPIO_CFG_12_15 0x0b
1441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* CFG_16 in REG_CFG3 */
1451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define ADM1026_REG_GPIO_STATUS_0_7 0x24
1461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define ADM1026_REG_GPIO_STATUS_8_15 0x25
1471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* STATUS_16 in REG_STATUS4 */
1481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define ADM1026_REG_GPIO_MASK_0_7 0x1c
1491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define ADM1026_REG_GPIO_MASK_8_15 0x1d
1501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* MASK_16 in REG_MASK4 */
1511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define ADM1026_REG_COMPANY 0x16
1531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define ADM1026_REG_VERSTEP 0x17
1541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* These are the recognized values for the above regs */
1551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define ADM1026_COMPANY_ANALOG_DEV 0x41
1561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define ADM1026_VERSTEP_GENERIC 0x40
1571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define ADM1026_VERSTEP_ADM1026 0x44
1581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define ADM1026_REG_MASK1 0x18
1601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define ADM1026_REG_MASK2 0x19
1611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define ADM1026_REG_MASK3 0x1a
1621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define ADM1026_REG_MASK4 0x1b
1631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define ADM1026_REG_STATUS1 0x20
1651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define ADM1026_REG_STATUS2 0x21
1661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define ADM1026_REG_STATUS3 0x22
1671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define ADM1026_REG_STATUS4 0x23
1681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define ADM1026_FAN_ACTIVATION_TEMP_HYST -6
1701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define ADM1026_FAN_CONTROL_TEMP_RANGE 20
1711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define ADM1026_PWM_MAX 255
1721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* Conversions. Rounding and limit checking is only done on the TO_REG
1741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * variants. Note that you should be a bit careful with which arguments
1751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * these macros are called: arguments may be evaluated more than once.
1761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
1771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* IN are scaled acording to built-in resistors.  These are the
1791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *   voltages corresponding to 3/4 of full scale (192 or 0xc0)
1801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *   NOTE: The -12V input needs an additional factor to account
1811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *      for the Vref pullup resistor.
1821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *      NEG12_OFFSET = SCALE * Vref / V-192 - Vref
1831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *                   = 13875 * 2.50 / 1.875 - 2500
1841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *                   = 16000
1851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
1861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * The values in this table are based on Table II, page 15 of the
1871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *    datasheet.
1881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
1891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int adm1026_scaling[] = {  /* .001 Volts */
1901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		2250, 2250, 2250, 2250, 2250, 2250,
1911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		1875, 1875, 1875, 1875, 3000, 3330,
1921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		3330, 4995, 2250, 12000, 13875
1931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	};
1941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define NEG12_OFFSET  16000
1951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define SCALE(val,from,to) (((val)*(to) + ((from)/2))/(from))
1961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define INS_TO_REG(n,val)  (SENSORS_LIMIT(SCALE(val,adm1026_scaling[n],192),\
1971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	0,255))
1981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define INS_FROM_REG(n,val) (SCALE(val,192,adm1026_scaling[n]))
1991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* FAN speed is measured using 22.5kHz clock and counts for 2 pulses
2011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *   and we assume a 2 pulse-per-rev fan tach signal
2021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *      22500 kHz * 60 (sec/min) * 2 (pulse) / 2 (pulse/rev) == 1350000
2031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
2041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define FAN_TO_REG(val,div)  ((val)<=0 ? 0xff : SENSORS_LIMIT(1350000/((val)*\
2051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	(div)),1,254))
2061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define FAN_FROM_REG(val,div) ((val)==0?-1:(val)==0xff ? 0 : 1350000/((val)*\
2071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	(div)))
2081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define DIV_FROM_REG(val) (1<<(val))
2091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define DIV_TO_REG(val) ((val)>=8 ? 3 : (val)>=4 ? 2 : (val)>=2 ? 1 : 0)
2101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* Temperature is reported in 1 degC increments */
2121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define TEMP_TO_REG(val) (SENSORS_LIMIT(((val)+((val)<0 ? -500 : 500))/1000,\
2131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	-127,127))
2141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define TEMP_FROM_REG(val) ((val) * 1000)
2151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define OFFSET_TO_REG(val) (SENSORS_LIMIT(((val)+((val)<0 ? -500 : 500))/1000,\
2161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	-127,127))
2171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define OFFSET_FROM_REG(val) ((val) * 1000)
2181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define PWM_TO_REG(val) (SENSORS_LIMIT(val,0,255))
2201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define PWM_FROM_REG(val) (val)
2211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define PWM_MIN_TO_REG(val) ((val) & 0xf0)
2231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define PWM_MIN_FROM_REG(val) (((val) & 0xf0) + ((val) >> 4))
2241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* Analog output is a voltage, and scaled to millivolts.  The datasheet
2261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *   indicates that the DAC could be used to drive the fans, but in our
2271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *   example board (Arima HDAMA) it isn't connected to the fans at all.
2281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
2291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define DAC_TO_REG(val) (SENSORS_LIMIT(((((val)*255)+500)/2500),0,255))
2301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define DAC_FROM_REG(val) (((val)*2500)/255)
2311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* Typically used with systems using a v9.1 VRM spec ? */
2331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define ADM1026_INIT_VRM  91
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 */
2461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define ADM1026_DATA_INTERVAL  (1 * HZ)
2471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#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 {
2621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct i2c_client client;
263943b0830cebe4711354945ed3cb44e84152aaca0Mark M. Hoffman	struct class_device *class_dev;
2641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct semaphore lock;
2651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	enum chips type;
2661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct semaphore update_lock;
2681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int valid;		/* !=0 if following fields are valid */
2691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	unsigned long last_reading;	/* In jiffies */
2701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	unsigned long last_config;	/* In jiffies */
2711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	u8 in[17];              /* Register value */
2731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	u8 in_max[17];          /* Register value */
2741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	u8 in_min[17];          /* Register value */
2751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	s8 temp[3];             /* Register value */
2761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	s8 temp_min[3];         /* Register value */
2771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	s8 temp_max[3];         /* Register value */
2781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	s8 temp_tmin[3];        /* Register value */
2791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	s8 temp_crit[3];        /* Register value */
2801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	s8 temp_offset[3];      /* Register value */
2811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	u8 fan[8];              /* Register value */
2821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	u8 fan_min[8];          /* Register value */
2831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	u8 fan_div[8];          /* Decoded value */
2841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct pwm_data pwm1;   /* Pwm control values */
2851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int vid;                /* Decoded value */
2861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	u8 vrm;                 /* VRM version */
2871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	u8 analog_out;		/* Register value (DAC) */
2881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	long alarms;            /* Register encoding, combined */
2891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	long alarm_mask;        /* Register encoding, combined */
2901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	long gpio;              /* Register encoding, combined */
2911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	long gpio_mask;         /* Register encoding, combined */
2921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	u8 gpio_config[17];     /* Decoded value */
2931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	u8 config1;             /* Register value */
2941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	u8 config2;             /* Register value */
2951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	u8 config3;             /* Register value */
2961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds};
2971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int adm1026_attach_adapter(struct i2c_adapter *adapter);
2991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int adm1026_detect(struct i2c_adapter *adapter, int address,
3001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int kind);
3011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int adm1026_detach_client(struct i2c_client *client);
3021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int adm1026_read_value(struct i2c_client *client, u8 register);
3031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int adm1026_write_value(struct i2c_client *client, u8 register,
3041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int value);
3051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void adm1026_print_gpio(struct i2c_client *client);
3061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void adm1026_fixup_gpio(struct i2c_client *client);
3071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic struct adm1026_data *adm1026_update_device(struct device *dev);
3081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void adm1026_init_client(struct i2c_client *client);
3091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic struct i2c_driver adm1026_driver = {
3121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	.owner          = THIS_MODULE,
3131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	.name           = "adm1026",
3141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	.flags          = I2C_DF_NOTIFY,
3151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	.attach_adapter = adm1026_attach_adapter,
3161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	.detach_client  = adm1026_detach_client,
3171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds};
3181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsint adm1026_attach_adapter(struct i2c_adapter *adapter)
3201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
3211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (!(adapter->class & I2C_CLASS_HWMON)) {
3221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return 0;
3231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
3242ed2dc3c116d26fc6a9384e83d136b15cc203b6cJean Delvare	return i2c_probe(adapter, &addr_data, adm1026_detect);
3251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
3261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsint adm1026_detach_client(struct i2c_client *client)
3281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
329943b0830cebe4711354945ed3cb44e84152aaca0Mark M. Hoffman	struct adm1026_data *data = i2c_get_clientdata(client);
330943b0830cebe4711354945ed3cb44e84152aaca0Mark M. Hoffman	hwmon_device_unregister(data->class_dev);
3311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	i2c_detach_client(client);
332943b0830cebe4711354945ed3cb44e84152aaca0Mark M. Hoffman	kfree(data);
3331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return 0;
3341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
3351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsint adm1026_read_value(struct i2c_client *client, u8 reg)
3371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
3381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int res;
3391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (reg < 0x80) {
3411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		/* "RAM" locations */
3421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		res = i2c_smbus_read_byte_data(client, reg) & 0xff;
3431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	} else {
3441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		/* EEPROM, do nothing */
3451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		res = 0;
3461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
3471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return res;
3481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
3491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsint adm1026_write_value(struct i2c_client *client, u8 reg, int value)
3511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
3521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int res;
3531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (reg < 0x80) {
3551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		/* "RAM" locations */
3561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		res = i2c_smbus_write_byte_data(client, reg, value);
3571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	} else {
3581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		/* EEPROM, do nothing */
3591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		res = 0;
3601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
3611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return res;
3621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
3631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsvoid adm1026_init_client(struct i2c_client *client)
3651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
3661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int value, i;
3671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct adm1026_data *data = i2c_get_clientdata(client);
3681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        dev_dbg(&client->dev, "Initializing device\n");
3701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* Read chip config */
3711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	data->config1 = adm1026_read_value(client, ADM1026_REG_CONFIG1);
3721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	data->config2 = adm1026_read_value(client, ADM1026_REG_CONFIG2);
3731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	data->config3 = adm1026_read_value(client, ADM1026_REG_CONFIG3);
3741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* Inform user of chip config */
3761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	dev_dbg(&client->dev, "ADM1026_REG_CONFIG1 is: 0x%02x\n",
3771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		data->config1);
3781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if ((data->config1 & CFG1_MONITOR) == 0) {
3791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		dev_dbg(&client->dev, "Monitoring not currently "
3801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			"enabled.\n");
3811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
3821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (data->config1 & CFG1_INT_ENABLE) {
3831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		dev_dbg(&client->dev, "SMBALERT interrupts are "
3841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			"enabled.\n");
3851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
3861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (data->config1 & CFG1_AIN8_9) {
3871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		dev_dbg(&client->dev, "in8 and in9 enabled. "
3881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			"temp3 disabled.\n");
3891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	} else {
3901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		dev_dbg(&client->dev, "temp3 enabled.  in8 and "
3911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			"in9 disabled.\n");
3921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
3931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (data->config1 & CFG1_THERM_HOT) {
3941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		dev_dbg(&client->dev, "Automatic THERM, PWM, "
3951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			"and temp limits enabled.\n");
3961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
3971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	value = data->config3;
3991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (data->config3 & CFG3_GPIO16_ENABLE) {
400368609c5a8bd75b77721e69726ddfd3c6a30f7d4Jean Delvare		dev_dbg(&client->dev, "GPIO16 enabled.  THERM "
4011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			"pin disabled.\n");
4021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	} else {
4031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		dev_dbg(&client->dev, "THERM pin enabled.  "
4041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			"GPIO16 disabled.\n");
4051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
4061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (data->config3 & CFG3_VREF_250) {
4071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		dev_dbg(&client->dev, "Vref is 2.50 Volts.\n");
4081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	} else {
4091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		dev_dbg(&client->dev, "Vref is 1.82 Volts.\n");
4101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
4111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* Read and pick apart the existing GPIO configuration */
4121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	value = 0;
4131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	for (i = 0;i <= 15;++i) {
4141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if ((i & 0x03) == 0) {
4151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			value = adm1026_read_value(client,
4161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds					ADM1026_REG_GPIO_CFG_0_3 + i/4);
4171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
4181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		data->gpio_config[i] = value & 0x03;
4191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		value >>= 2;
4201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
4211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	data->gpio_config[16] = (data->config3 >> 6) & 0x03;
4221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* ... and then print it */
4241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	adm1026_print_gpio(client);
4251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* If the user asks us to reprogram the GPIO config, then
4271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * do it now.
4281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 */
4291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (gpio_input[0] != -1 || gpio_output[0] != -1
4301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		|| gpio_inverted[0] != -1 || gpio_normal[0] != -1
4311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		|| gpio_fan[0] != -1) {
4321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		adm1026_fixup_gpio(client);
4331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
4341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* WE INTENTIONALLY make no changes to the limits,
4361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 *   offsets, pwms, fans and zones.  If they were
4371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 *   configured, we don't want to mess with them.
4381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 *   If they weren't, the default is 100% PWM, no
4391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 *   control and will suffice until 'sensors -s'
4401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 *   can be run by the user.  We DO set the default
4411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 *   value for pwm1.auto_pwm_min to its maximum
4421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 *   so that enabling automatic pwm fan control
4431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 *   without first setting a value for pwm1.auto_pwm_min
4441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 *   will not result in potentially dangerous fan speed decrease.
4451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 */
4461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	data->pwm1.auto_pwm_min=255;
4471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* Start monitoring */
4481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	value = adm1026_read_value(client, ADM1026_REG_CONFIG1);
4491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* Set MONITOR, clear interrupt acknowledge and s/w reset */
4501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	value = (value | CFG1_MONITOR) & (~CFG1_INT_CLEAR & ~CFG1_RESET);
4511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	dev_dbg(&client->dev, "Setting CONFIG to: 0x%02x\n", value);
4521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	data->config1 = value;
4531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	adm1026_write_value(client, ADM1026_REG_CONFIG1, value);
4541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* initialize fan_div[] to hardware defaults */
4561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	value = adm1026_read_value(client, ADM1026_REG_FAN_DIV_0_3) |
4571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		(adm1026_read_value(client, ADM1026_REG_FAN_DIV_4_7) << 8);
4581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	for (i = 0;i <= 7;++i) {
4591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		data->fan_div[i] = DIV_FROM_REG(value & 0x03);
4601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		value >>= 2;
4611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
4621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
4631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsvoid adm1026_print_gpio(struct i2c_client *client)
4651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
4661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct adm1026_data *data = i2c_get_clientdata(client);
4671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int  i;
4681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	dev_dbg(&client->dev, "GPIO config is:");
4701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	for (i = 0;i <= 7;++i) {
4711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (data->config2 & (1 << i)) {
4721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			dev_dbg(&client->dev, "\t%sGP%s%d\n",
4731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				data->gpio_config[i] & 0x02 ? "" : "!",
4741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				data->gpio_config[i] & 0x01 ? "OUT" : "IN",
4751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				i);
4761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		} else {
4771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			dev_dbg(&client->dev, "\tFAN%d\n", i);
4781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
4791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
4801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	for (i = 8;i <= 15;++i) {
4811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		dev_dbg(&client->dev, "\t%sGP%s%d\n",
4821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			data->gpio_config[i] & 0x02 ? "" : "!",
4831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			data->gpio_config[i] & 0x01 ? "OUT" : "IN",
4841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			i);
4851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
4861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (data->config3 & CFG3_GPIO16_ENABLE) {
4871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		dev_dbg(&client->dev, "\t%sGP%s16\n",
4881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			data->gpio_config[16] & 0x02 ? "" : "!",
4891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			data->gpio_config[16] & 0x01 ? "OUT" : "IN");
4901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	} else {
4911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		/* GPIO16 is THERM  */
4921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		dev_dbg(&client->dev, "\tTHERM\n");
4931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
4941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
4951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsvoid adm1026_fixup_gpio(struct i2c_client *client)
4971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
4981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct adm1026_data *data = i2c_get_clientdata(client);
4991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int  i;
5001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int  value;
5011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* Make the changes requested. */
5031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* We may need to unlock/stop monitoring or soft-reset the
5041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 *    chip before we can make changes.  This hasn't been
5051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 *    tested much.  FIXME
5061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 */
5071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* Make outputs */
5091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	for (i = 0;i <= 16;++i) {
5101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (gpio_output[i] >= 0 && gpio_output[i] <= 16) {
5111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			data->gpio_config[gpio_output[i]] |= 0x01;
5121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
5131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		/* if GPIO0-7 is output, it isn't a FAN tach */
5141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (gpio_output[i] >= 0 && gpio_output[i] <= 7) {
5151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			data->config2 |= 1 << gpio_output[i];
5161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
5171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
5181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* Input overrides output */
5201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	for (i = 0;i <= 16;++i) {
5211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (gpio_input[i] >= 0 && gpio_input[i] <= 16) {
5221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			data->gpio_config[gpio_input[i]] &= ~ 0x01;
5231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
5241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		/* if GPIO0-7 is input, it isn't a FAN tach */
5251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (gpio_input[i] >= 0 && gpio_input[i] <= 7) {
5261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			data->config2 |= 1 << gpio_input[i];
5271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
5281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
5291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* Inverted  */
5311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	for (i = 0;i <= 16;++i) {
5321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (gpio_inverted[i] >= 0 && gpio_inverted[i] <= 16) {
5331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			data->gpio_config[gpio_inverted[i]] &= ~ 0x02;
5341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
5351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
5361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* Normal overrides inverted  */
5381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	for (i = 0;i <= 16;++i) {
5391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (gpio_normal[i] >= 0 && gpio_normal[i] <= 16) {
5401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			data->gpio_config[gpio_normal[i]] |= 0x02;
5411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
5421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
5431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* Fan overrides input and output */
5451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	for (i = 0;i <= 7;++i) {
5461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (gpio_fan[i] >= 0 && gpio_fan[i] <= 7) {
5471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			data->config2 &= ~(1 << gpio_fan[i]);
5481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
5491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
5501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* Write new configs to registers */
5521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	adm1026_write_value(client, ADM1026_REG_CONFIG2, data->config2);
5531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	data->config3 = (data->config3 & 0x3f)
5541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			| ((data->gpio_config[16] & 0x03) << 6);
5551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	adm1026_write_value(client, ADM1026_REG_CONFIG3, data->config3);
5561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	for (i = 15, value = 0;i >= 0;--i) {
5571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		value <<= 2;
5581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		value |= data->gpio_config[i] & 0x03;
5591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if ((i & 0x03) == 0) {
5601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			adm1026_write_value(client,
5611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds					ADM1026_REG_GPIO_CFG_0_3 + i/4,
5621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds					value);
5631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			value = 0;
5641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
5651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
5661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* Print the new config */
5681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	adm1026_print_gpio(client);
5691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
5701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic struct adm1026_data *adm1026_update_device(struct device *dev)
5731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
5741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct i2c_client *client = to_i2c_client(dev);
5751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct adm1026_data *data = i2c_get_clientdata(client);
5761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int i;
5771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	long value, alarms, gpio;
5781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	down(&data->update_lock);
5801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (!data->valid
5811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	    || time_after(jiffies, data->last_reading + ADM1026_DATA_INTERVAL)) {
5821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		/* Things that change quickly */
5831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		dev_dbg(&client->dev,"Reading sensor values\n");
5841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		for (i = 0;i <= 16;++i) {
5851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			data->in[i] =
5861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			    adm1026_read_value(client, ADM1026_REG_IN[i]);
5871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
5881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		for (i = 0;i <= 7;++i) {
5901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			data->fan[i] =
5911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			    adm1026_read_value(client, ADM1026_REG_FAN(i));
5921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
5931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		for (i = 0;i <= 2;++i) {
5951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			/* NOTE: temp[] is s8 and we assume 2's complement
5961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			 *   "conversion" in the assignment   */
5971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			data->temp[i] =
5981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			    adm1026_read_value(client, ADM1026_REG_TEMP[i]);
5991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
6001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
6011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		data->pwm1.pwm = adm1026_read_value(client,
6021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			ADM1026_REG_PWM);
6031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		data->analog_out = adm1026_read_value(client,
6041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			ADM1026_REG_DAC);
6051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		/* GPIO16 is MSbit of alarms, move it to gpio */
6061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		alarms = adm1026_read_value(client, ADM1026_REG_STATUS4);
6071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		gpio = alarms & 0x80 ? 0x0100 : 0;  /* GPIO16 */
6081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		alarms &= 0x7f;
6091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		alarms <<= 8;
6101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		alarms |= adm1026_read_value(client, ADM1026_REG_STATUS3);
6111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		alarms <<= 8;
6121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		alarms |= adm1026_read_value(client, ADM1026_REG_STATUS2);
6131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		alarms <<= 8;
6141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		alarms |= adm1026_read_value(client, ADM1026_REG_STATUS1);
6151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		data->alarms = alarms;
6161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
6171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		/* Read the GPIO values */
6181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		gpio |= adm1026_read_value(client,
6191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			ADM1026_REG_GPIO_STATUS_8_15);
6201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		gpio <<= 8;
6211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		gpio |= adm1026_read_value(client,
6221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			ADM1026_REG_GPIO_STATUS_0_7);
6231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		data->gpio = gpio;
6241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
6251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		data->last_reading = jiffies;
6261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	};  /* last_reading */
6271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
6281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (!data->valid ||
6291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	    time_after(jiffies, data->last_config + ADM1026_CONFIG_INTERVAL)) {
6301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		/* Things that don't change often */
6311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		dev_dbg(&client->dev, "Reading config values\n");
6321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		for (i = 0;i <= 16;++i) {
6331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			data->in_min[i] = adm1026_read_value(client,
6341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				ADM1026_REG_IN_MIN[i]);
6351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			data->in_max[i] = adm1026_read_value(client,
6361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				ADM1026_REG_IN_MAX[i]);
6371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
6381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
6391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		value = adm1026_read_value(client, ADM1026_REG_FAN_DIV_0_3)
6401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			| (adm1026_read_value(client, ADM1026_REG_FAN_DIV_4_7)
6411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			<< 8);
6421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		for (i = 0;i <= 7;++i) {
6431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			data->fan_min[i] = adm1026_read_value(client,
6441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				ADM1026_REG_FAN_MIN(i));
6451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			data->fan_div[i] = DIV_FROM_REG(value & 0x03);
6461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			value >>= 2;
6471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
6481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
6491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		for (i = 0; i <= 2; ++i) {
6501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			/* NOTE: temp_xxx[] are s8 and we assume 2's
6511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			 *    complement "conversion" in the assignment
6521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			 */
6531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			data->temp_min[i] = adm1026_read_value(client,
6541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				ADM1026_REG_TEMP_MIN[i]);
6551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			data->temp_max[i] = adm1026_read_value(client,
6561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				ADM1026_REG_TEMP_MAX[i]);
6571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			data->temp_tmin[i] = adm1026_read_value(client,
6581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				ADM1026_REG_TEMP_TMIN[i]);
6591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			data->temp_crit[i] = adm1026_read_value(client,
6601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				ADM1026_REG_TEMP_THERM[i]);
6611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			data->temp_offset[i] = adm1026_read_value(client,
6621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				ADM1026_REG_TEMP_OFFSET[i]);
6631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
6641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
6651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		/* Read the STATUS/alarm masks */
6661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		alarms  = adm1026_read_value(client, ADM1026_REG_MASK4);
6671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		gpio    = alarms & 0x80 ? 0x0100 : 0;  /* GPIO16 */
6681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		alarms  = (alarms & 0x7f) << 8;
6691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		alarms |= adm1026_read_value(client, ADM1026_REG_MASK3);
6701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		alarms <<= 8;
6711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		alarms |= adm1026_read_value(client, ADM1026_REG_MASK2);
6721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		alarms <<= 8;
6731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		alarms |= adm1026_read_value(client, ADM1026_REG_MASK1);
6741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		data->alarm_mask = alarms;
6751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
6761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		/* Read the GPIO values */
6771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		gpio |= adm1026_read_value(client,
6781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			ADM1026_REG_GPIO_MASK_8_15);
6791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		gpio <<= 8;
6801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		gpio |= adm1026_read_value(client, ADM1026_REG_GPIO_MASK_0_7);
6811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		data->gpio_mask = gpio;
6821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
6831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		/* Read various values from CONFIG1 */
6841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		data->config1 = adm1026_read_value(client,
6851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			ADM1026_REG_CONFIG1);
6861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (data->config1 & CFG1_PWM_AFC) {
6871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			data->pwm1.enable = 2;
6881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			data->pwm1.auto_pwm_min =
6891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				PWM_MIN_FROM_REG(data->pwm1.pwm);
6901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
6911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		/* Read the GPIO config */
6921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		data->config2 = adm1026_read_value(client,
6931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			ADM1026_REG_CONFIG2);
6941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		data->config3 = adm1026_read_value(client,
6951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			ADM1026_REG_CONFIG3);
6961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		data->gpio_config[16] = (data->config3 >> 6) & 0x03;
6971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
6981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		value = 0;
6991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		for (i = 0;i <= 15;++i) {
7001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			if ((i & 0x03) == 0) {
7011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				value = adm1026_read_value(client,
7021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds					    ADM1026_REG_GPIO_CFG_0_3 + i/4);
7031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			}
7041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			data->gpio_config[i] = value & 0x03;
7051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			value >>= 2;
7061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
7071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
7081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		data->last_config = jiffies;
7091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	};  /* last_config */
7101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
7111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	dev_dbg(&client->dev, "Setting VID from GPIO11-15.\n");
7121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	data->vid = (data->gpio >> 11) & 0x1f;
7131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	data->valid = 1;
7141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	up(&data->update_lock);
7151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return data;
7161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
7171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
718050480f12aeab62d39a1a07546606a47217ebefaYani Ioannoustatic ssize_t show_in(struct device *dev, struct device_attribute *attr,
719050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou		char *buf)
7201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
721050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou	struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr);
722050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou	int nr = sensor_attr->index;
7231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct adm1026_data *data = adm1026_update_device(dev);
7241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return sprintf(buf,"%d\n", INS_FROM_REG(nr, data->in[nr]));
7251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
726050480f12aeab62d39a1a07546606a47217ebefaYani Ioannoustatic ssize_t show_in_min(struct device *dev, struct device_attribute *attr,
727050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou		char *buf)
7281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
729050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou	struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr);
730050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou	int nr = sensor_attr->index;
7311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct adm1026_data *data = adm1026_update_device(dev);
7321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return sprintf(buf,"%d\n", INS_FROM_REG(nr, data->in_min[nr]));
7331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
734050480f12aeab62d39a1a07546606a47217ebefaYani Ioannoustatic ssize_t set_in_min(struct device *dev, struct device_attribute *attr,
735050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou		const char *buf, size_t count)
7361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
737050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou	struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr);
738050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou	int nr = sensor_attr->index;
7391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct i2c_client *client = to_i2c_client(dev);
7401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct adm1026_data *data = i2c_get_clientdata(client);
7411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int val = simple_strtol(buf, NULL, 10);
7421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
7431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	down(&data->update_lock);
7441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	data->in_min[nr] = INS_TO_REG(nr, val);
7451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	adm1026_write_value(client, ADM1026_REG_IN_MIN[nr], data->in_min[nr]);
7461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	up(&data->update_lock);
7471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return count;
7481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
749050480f12aeab62d39a1a07546606a47217ebefaYani Ioannoustatic ssize_t show_in_max(struct device *dev, struct device_attribute *attr,
750050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou		char *buf)
7511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
752050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou	struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr);
753050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou	int nr = sensor_attr->index;
7541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct adm1026_data *data = adm1026_update_device(dev);
7551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return sprintf(buf,"%d\n", INS_FROM_REG(nr, data->in_max[nr]));
7561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
757050480f12aeab62d39a1a07546606a47217ebefaYani Ioannoustatic ssize_t set_in_max(struct device *dev, struct device_attribute *attr,
758050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou		const char *buf, size_t count)
7591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
760050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou	struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr);
761050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou	int nr = sensor_attr->index;
7621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct i2c_client *client = to_i2c_client(dev);
7631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct adm1026_data *data = i2c_get_clientdata(client);
7641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int val = simple_strtol(buf, NULL, 10);
7651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
7661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	down(&data->update_lock);
7671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	data->in_max[nr] = INS_TO_REG(nr, val);
7681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	adm1026_write_value(client, ADM1026_REG_IN_MAX[nr], data->in_max[nr]);
7691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	up(&data->update_lock);
7701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return count;
7711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
7721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
773050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou#define in_reg(offset)						\
774050480f12aeab62d39a1a07546606a47217ebefaYani Ioannoustatic SENSOR_DEVICE_ATTR(in##offset##_input, S_IRUGO, show_in,	\
775050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou		NULL, offset);					\
776050480f12aeab62d39a1a07546606a47217ebefaYani Ioannoustatic SENSOR_DEVICE_ATTR(in##offset##_min, S_IRUGO | S_IWUSR,	\
777050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou		show_in_min, set_in_min, offset);		\
778050480f12aeab62d39a1a07546606a47217ebefaYani Ioannoustatic SENSOR_DEVICE_ATTR(in##offset##_max, S_IRUGO | S_IWUSR,	\
779050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou		show_in_max, set_in_max, offset);
7801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
7811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
7821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsin_reg(0);
7831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsin_reg(1);
7841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsin_reg(2);
7851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsin_reg(3);
7861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsin_reg(4);
7871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsin_reg(5);
7881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsin_reg(6);
7891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsin_reg(7);
7901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsin_reg(8);
7911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsin_reg(9);
7921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsin_reg(10);
7931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsin_reg(11);
7941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsin_reg(12);
7951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsin_reg(13);
7961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsin_reg(14);
7971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsin_reg(15);
7981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
79974880c063b06efd103c924abfe19d9d8fa4864c4Yani Ioannoustatic ssize_t show_in16(struct device *dev, struct device_attribute *attr, char *buf)
8001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
8011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct adm1026_data *data = adm1026_update_device(dev);
8021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return sprintf(buf,"%d\n", INS_FROM_REG(16, data->in[16]) -
8031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		NEG12_OFFSET);
8041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
80574880c063b06efd103c924abfe19d9d8fa4864c4Yani Ioannoustatic ssize_t show_in16_min(struct device *dev, struct device_attribute *attr, char *buf)
8061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
8071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct adm1026_data *data = adm1026_update_device(dev);
8081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return sprintf(buf,"%d\n", INS_FROM_REG(16, data->in_min[16])
8091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		- NEG12_OFFSET);
8101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
81174880c063b06efd103c924abfe19d9d8fa4864c4Yani Ioannoustatic ssize_t set_in16_min(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
8121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
8131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct i2c_client *client = to_i2c_client(dev);
8141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct adm1026_data *data = i2c_get_clientdata(client);
8151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int val = simple_strtol(buf, NULL, 10);
8161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
8171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	down(&data->update_lock);
8181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	data->in_min[16] = INS_TO_REG(16, val + NEG12_OFFSET);
8191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	adm1026_write_value(client, ADM1026_REG_IN_MIN[16], data->in_min[16]);
8201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	up(&data->update_lock);
8211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return count;
8221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
82374880c063b06efd103c924abfe19d9d8fa4864c4Yani Ioannoustatic ssize_t show_in16_max(struct device *dev, struct device_attribute *attr, char *buf)
8241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
8251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct adm1026_data *data = adm1026_update_device(dev);
8261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return sprintf(buf,"%d\n", INS_FROM_REG(16, data->in_max[16])
8271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			- NEG12_OFFSET);
8281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
82974880c063b06efd103c924abfe19d9d8fa4864c4Yani Ioannoustatic ssize_t set_in16_max(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
8301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
8311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct i2c_client *client = to_i2c_client(dev);
8321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct adm1026_data *data = i2c_get_clientdata(client);
8331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int val = simple_strtol(buf, NULL, 10);
8341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
8351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	down(&data->update_lock);
8361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	data->in_max[16] = INS_TO_REG(16, val+NEG12_OFFSET);
8371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	adm1026_write_value(client, ADM1026_REG_IN_MAX[16], data->in_max[16]);
8381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	up(&data->update_lock);
8391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return count;
8401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
8411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
842050480f12aeab62d39a1a07546606a47217ebefaYani Ioannoustatic SENSOR_DEVICE_ATTR(in16_input, S_IRUGO, show_in16, NULL, 16);
843050480f12aeab62d39a1a07546606a47217ebefaYani Ioannoustatic SENSOR_DEVICE_ATTR(in16_min, S_IRUGO | S_IWUSR, show_in16_min, set_in16_min, 16);
844050480f12aeab62d39a1a07546606a47217ebefaYani Ioannoustatic SENSOR_DEVICE_ATTR(in16_max, S_IRUGO | S_IWUSR, show_in16_max, set_in16_max, 16);
8451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
8461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
8471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
8481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
8491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* Now add fan read/write functions */
8501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
851050480f12aeab62d39a1a07546606a47217ebefaYani Ioannoustatic ssize_t show_fan(struct device *dev, struct device_attribute *attr,
852050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou		char *buf)
8531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
854050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou	struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr);
855050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou	int nr = sensor_attr->index;
8561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct adm1026_data *data = adm1026_update_device(dev);
8571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return sprintf(buf,"%d\n", FAN_FROM_REG(data->fan[nr],
8581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		data->fan_div[nr]));
8591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
860050480f12aeab62d39a1a07546606a47217ebefaYani Ioannoustatic ssize_t show_fan_min(struct device *dev, struct device_attribute *attr,
861050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou		char *buf)
8621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
863050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou	struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr);
864050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou	int nr = sensor_attr->index;
8651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct adm1026_data *data = adm1026_update_device(dev);
8661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return sprintf(buf,"%d\n", FAN_FROM_REG(data->fan_min[nr],
8671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		data->fan_div[nr]));
8681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
869050480f12aeab62d39a1a07546606a47217ebefaYani Ioannoustatic ssize_t set_fan_min(struct device *dev, struct device_attribute *attr,
870050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou		const char *buf, size_t count)
8711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
872050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou	struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr);
873050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou	int nr = sensor_attr->index;
8741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct i2c_client *client = to_i2c_client(dev);
8751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct adm1026_data *data = i2c_get_clientdata(client);
8761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int val = simple_strtol(buf, NULL, 10);
8771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
8781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	down(&data->update_lock);
8791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	data->fan_min[nr] = FAN_TO_REG(val, data->fan_div[nr]);
8801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	adm1026_write_value(client, ADM1026_REG_FAN_MIN(nr),
8811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		data->fan_min[nr]);
8821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	up(&data->update_lock);
8831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return count;
8841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
8851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
886050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou#define fan_offset(offset)                                         		\
887050480f12aeab62d39a1a07546606a47217ebefaYani Ioannoustatic SENSOR_DEVICE_ATTR(fan##offset##_input, S_IRUGO, show_fan, NULL, 	\
888050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou		offset - 1);							\
889050480f12aeab62d39a1a07546606a47217ebefaYani Ioannoustatic SENSOR_DEVICE_ATTR(fan##offset##_min, S_IRUGO | S_IWUSR,           	\
890050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou		show_fan_min, set_fan_min, offset - 1);
8911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
8921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsfan_offset(1);
8931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsfan_offset(2);
8941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsfan_offset(3);
8951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsfan_offset(4);
8961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsfan_offset(5);
8971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsfan_offset(6);
8981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsfan_offset(7);
8991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsfan_offset(8);
9001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
9011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* Adjust fan_min to account for new fan divisor */
9021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void fixup_fan_min(struct device *dev, int fan, int old_div)
9031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
9041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct i2c_client *client = to_i2c_client(dev);
9051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct adm1026_data *data = i2c_get_clientdata(client);
9061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int    new_min;
9071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int    new_div = data->fan_div[fan];
9081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
9091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* 0 and 0xff are special.  Don't adjust them */
9101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (data->fan_min[fan] == 0 || data->fan_min[fan] == 0xff) {
9111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return;
9121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
9131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
9141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	new_min = data->fan_min[fan] * old_div / new_div;
9151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	new_min = SENSORS_LIMIT(new_min, 1, 254);
9161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	data->fan_min[fan] = new_min;
9171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	adm1026_write_value(client, ADM1026_REG_FAN_MIN(fan), new_min);
9181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
9191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
9201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* Now add fan_div read/write functions */
921050480f12aeab62d39a1a07546606a47217ebefaYani Ioannoustatic ssize_t show_fan_div(struct device *dev, struct device_attribute *attr,
922050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou		char *buf)
9231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
924050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou	struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr);
925050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou	int nr = sensor_attr->index;
9261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct adm1026_data *data = adm1026_update_device(dev);
9271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return sprintf(buf,"%d\n", data->fan_div[nr]);
9281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
929050480f12aeab62d39a1a07546606a47217ebefaYani Ioannoustatic ssize_t set_fan_div(struct device *dev, struct device_attribute *attr,
930050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou		const char *buf, size_t count)
9311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
932050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou	struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr);
933050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou	int nr = sensor_attr->index;
9341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct i2c_client *client = to_i2c_client(dev);
9351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct adm1026_data *data = i2c_get_clientdata(client);
9361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int    val,orig_div,new_div,shift;
9371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
9381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	val = simple_strtol(buf, NULL, 10);
9391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	new_div = DIV_TO_REG(val);
9401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (new_div == 0) {
9411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return -EINVAL;
9421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
9431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	down(&data->update_lock);
9441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	orig_div = data->fan_div[nr];
9451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	data->fan_div[nr] = DIV_FROM_REG(new_div);
9461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
9471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (nr < 4) { /* 0 <= nr < 4 */
9481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		shift = 2 * nr;
9491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		adm1026_write_value(client, ADM1026_REG_FAN_DIV_0_3,
9501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			((DIV_TO_REG(orig_div) & (~(0x03 << shift))) |
9511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			(new_div << shift)));
9521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	} else { /* 3 < nr < 8 */
9531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		shift = 2 * (nr - 4);
9541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		adm1026_write_value(client, ADM1026_REG_FAN_DIV_4_7,
9551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			((DIV_TO_REG(orig_div) & (~(0x03 << (2 * shift)))) |
9561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			(new_div << shift)));
9571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
9581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
9591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (data->fan_div[nr] != orig_div) {
9601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		fixup_fan_min(dev,nr,orig_div);
9611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
9621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	up(&data->update_lock);
9631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return count;
9641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
9651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
9661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define fan_offset_div(offset)                                          \
967050480f12aeab62d39a1a07546606a47217ebefaYani Ioannoustatic SENSOR_DEVICE_ATTR(fan##offset##_div, S_IRUGO | S_IWUSR,         \
968050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou		show_fan_div, set_fan_div, offset - 1);
9691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
9701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsfan_offset_div(1);
9711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsfan_offset_div(2);
9721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsfan_offset_div(3);
9731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsfan_offset_div(4);
9741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsfan_offset_div(5);
9751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsfan_offset_div(6);
9761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsfan_offset_div(7);
9771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsfan_offset_div(8);
9781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
9791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* Temps */
980050480f12aeab62d39a1a07546606a47217ebefaYani Ioannoustatic ssize_t show_temp(struct device *dev, struct device_attribute *attr,
981050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou		char *buf)
9821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
983050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou	struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr);
984050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou	int nr = sensor_attr->index;
9851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct adm1026_data *data = adm1026_update_device(dev);
9861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return sprintf(buf,"%d\n", TEMP_FROM_REG(data->temp[nr]));
9871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
988050480f12aeab62d39a1a07546606a47217ebefaYani Ioannoustatic ssize_t show_temp_min(struct device *dev, struct device_attribute *attr,
989050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou		char *buf)
9901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
991050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou	struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr);
992050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou	int nr = sensor_attr->index;
9931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct adm1026_data *data = adm1026_update_device(dev);
9941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return sprintf(buf,"%d\n", TEMP_FROM_REG(data->temp_min[nr]));
9951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
996050480f12aeab62d39a1a07546606a47217ebefaYani Ioannoustatic ssize_t set_temp_min(struct device *dev, struct device_attribute *attr,
997050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou		const char *buf, size_t count)
9981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
999050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou	struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr);
1000050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou	int nr = sensor_attr->index;
10011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct i2c_client *client = to_i2c_client(dev);
10021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct adm1026_data *data = i2c_get_clientdata(client);
10031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int val = simple_strtol(buf, NULL, 10);
10041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
10051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	down(&data->update_lock);
10061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	data->temp_min[nr] = TEMP_TO_REG(val);
10071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	adm1026_write_value(client, ADM1026_REG_TEMP_MIN[nr],
10081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		data->temp_min[nr]);
10091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	up(&data->update_lock);
10101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return count;
10111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
1012050480f12aeab62d39a1a07546606a47217ebefaYani Ioannoustatic ssize_t show_temp_max(struct device *dev, struct device_attribute *attr,
1013050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou		char *buf)
10141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
1015050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou	struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr);
1016050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou	int nr = sensor_attr->index;
10171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct adm1026_data *data = adm1026_update_device(dev);
10181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return sprintf(buf,"%d\n", TEMP_FROM_REG(data->temp_max[nr]));
10191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
1020050480f12aeab62d39a1a07546606a47217ebefaYani Ioannoustatic ssize_t set_temp_max(struct device *dev, struct device_attribute *attr,
1021050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou		const char *buf, size_t count)
10221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
1023050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou	struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr);
1024050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou	int nr = sensor_attr->index;
10251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct i2c_client *client = to_i2c_client(dev);
10261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct adm1026_data *data = i2c_get_clientdata(client);
10271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int val = simple_strtol(buf, NULL, 10);
10281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
10291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	down(&data->update_lock);
10301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	data->temp_max[nr] = TEMP_TO_REG(val);
10311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	adm1026_write_value(client, ADM1026_REG_TEMP_MAX[nr],
10321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		data->temp_max[nr]);
10331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	up(&data->update_lock);
10341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return count;
10351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
1036050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou
1037050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou#define temp_reg(offset)						\
1038050480f12aeab62d39a1a07546606a47217ebefaYani Ioannoustatic SENSOR_DEVICE_ATTR(temp##offset##_input, S_IRUGO, show_temp, 	\
1039050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou		NULL, offset - 1);					\
1040050480f12aeab62d39a1a07546606a47217ebefaYani Ioannoustatic SENSOR_DEVICE_ATTR(temp##offset##_min, S_IRUGO | S_IWUSR,	\
1041050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou		show_temp_min, set_temp_min, offset - 1);		\
1042050480f12aeab62d39a1a07546606a47217ebefaYani Ioannoustatic SENSOR_DEVICE_ATTR(temp##offset##_max, S_IRUGO | S_IWUSR,	\
1043050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou		show_temp_max, set_temp_max, offset - 1);
10441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
10451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
10461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldstemp_reg(1);
10471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldstemp_reg(2);
10481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldstemp_reg(3);
10491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1050050480f12aeab62d39a1a07546606a47217ebefaYani Ioannoustatic ssize_t show_temp_offset(struct device *dev,
1051050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou		struct device_attribute *attr, char *buf)
10521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
1053050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou	struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr);
1054050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou	int nr = sensor_attr->index;
10551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct adm1026_data *data = adm1026_update_device(dev);
10561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return sprintf(buf,"%d\n", TEMP_FROM_REG(data->temp_offset[nr]));
10571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
1058050480f12aeab62d39a1a07546606a47217ebefaYani Ioannoustatic ssize_t set_temp_offset(struct device *dev,
1059050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou		struct device_attribute *attr, const char *buf,
1060050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou		size_t count)
10611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
1062050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou	struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr);
1063050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou	int nr = sensor_attr->index;
10641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct i2c_client *client = to_i2c_client(dev);
10651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct adm1026_data *data = i2c_get_clientdata(client);
10661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int val = simple_strtol(buf, NULL, 10);
10671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
10681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	down(&data->update_lock);
10691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	data->temp_offset[nr] = TEMP_TO_REG(val);
10701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	adm1026_write_value(client, ADM1026_REG_TEMP_OFFSET[nr],
10711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		data->temp_offset[nr]);
10721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	up(&data->update_lock);
10731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return count;
10741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
10751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1076050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou#define temp_offset_reg(offset)							\
1077050480f12aeab62d39a1a07546606a47217ebefaYani Ioannoustatic SENSOR_DEVICE_ATTR(temp##offset##_offset, S_IRUGO | S_IWUSR,		\
1078050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou		show_temp_offset, set_temp_offset, offset - 1);
10791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
10801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldstemp_offset_reg(1);
10811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldstemp_offset_reg(2);
10821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldstemp_offset_reg(3);
10831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1084050480f12aeab62d39a1a07546606a47217ebefaYani Ioannoustatic ssize_t show_temp_auto_point1_temp_hyst(struct device *dev,
1085050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou		struct device_attribute *attr, char *buf)
10861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
1087050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou	struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr);
1088050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou	int nr = sensor_attr->index;
10891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct adm1026_data *data = adm1026_update_device(dev);
10901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return sprintf(buf,"%d\n", TEMP_FROM_REG(
10911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		ADM1026_FAN_ACTIVATION_TEMP_HYST + data->temp_tmin[nr]));
10921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
1093050480f12aeab62d39a1a07546606a47217ebefaYani Ioannoustatic ssize_t show_temp_auto_point2_temp(struct device *dev,
1094050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou		struct device_attribute *attr, char *buf)
10951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
1096050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou	struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr);
1097050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou	int nr = sensor_attr->index;
10981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct adm1026_data *data = adm1026_update_device(dev);
10991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return sprintf(buf,"%d\n", TEMP_FROM_REG(data->temp_tmin[nr] +
11001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		ADM1026_FAN_CONTROL_TEMP_RANGE));
11011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
1102050480f12aeab62d39a1a07546606a47217ebefaYani Ioannoustatic ssize_t show_temp_auto_point1_temp(struct device *dev,
1103050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou		struct device_attribute *attr, char *buf)
11041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
1105050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou	struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr);
1106050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou	int nr = sensor_attr->index;
11071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct adm1026_data *data = adm1026_update_device(dev);
11081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return sprintf(buf,"%d\n", TEMP_FROM_REG(data->temp_tmin[nr]));
11091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
1110050480f12aeab62d39a1a07546606a47217ebefaYani Ioannoustatic ssize_t set_temp_auto_point1_temp(struct device *dev,
1111050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou		struct device_attribute *attr, const char *buf, size_t count)
11121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
1113050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou	struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr);
1114050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou	int nr = sensor_attr->index;
11151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct i2c_client *client = to_i2c_client(dev);
11161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct adm1026_data *data = i2c_get_clientdata(client);
11171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int val = simple_strtol(buf, NULL, 10);
11181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
11191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	down(&data->update_lock);
11201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	data->temp_tmin[nr] = TEMP_TO_REG(val);
11211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	adm1026_write_value(client, ADM1026_REG_TEMP_TMIN[nr],
11221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		data->temp_tmin[nr]);
11231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	up(&data->update_lock);
11241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return count;
11251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
11261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1127050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou#define temp_auto_point(offset)							\
1128050480f12aeab62d39a1a07546606a47217ebefaYani Ioannoustatic SENSOR_DEVICE_ATTR(temp##offset##_auto_point1_temp, S_IRUGO | S_IWUSR,	\
1129050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou		show_temp_auto_point1_temp, set_temp_auto_point1_temp, 		\
1130050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou		offset - 1);							\
1131050480f12aeab62d39a1a07546606a47217ebefaYani Ioannoustatic SENSOR_DEVICE_ATTR(temp##offset##_auto_point1_temp_hyst, S_IRUGO,	\
1132050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou		show_temp_auto_point1_temp_hyst, NULL, offset - 1);		\
1133050480f12aeab62d39a1a07546606a47217ebefaYani Ioannoustatic SENSOR_DEVICE_ATTR(temp##offset##_auto_point2_temp, S_IRUGO,		\
1134050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou		show_temp_auto_point2_temp, NULL, offset - 1);
11351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
11361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldstemp_auto_point(1);
11371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldstemp_auto_point(2);
11381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldstemp_auto_point(3);
11391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1140050480f12aeab62d39a1a07546606a47217ebefaYani Ioannoustatic ssize_t show_temp_crit_enable(struct device *dev,
1141050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou		struct device_attribute *attr, char *buf)
11421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
11431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct adm1026_data *data = adm1026_update_device(dev);
11441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return sprintf(buf,"%d\n", (data->config1 & CFG1_THERM_HOT) >> 4);
11451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
1146050480f12aeab62d39a1a07546606a47217ebefaYani Ioannoustatic ssize_t set_temp_crit_enable(struct device *dev,
1147050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou		struct device_attribute *attr, const char *buf, size_t count)
11481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
11491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct i2c_client *client = to_i2c_client(dev);
11501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct adm1026_data *data = i2c_get_clientdata(client);
11511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int val = simple_strtol(buf, NULL, 10);
11521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
11531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if ((val == 1) || (val==0)) {
11541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		down(&data->update_lock);
11551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		data->config1 = (data->config1 & ~CFG1_THERM_HOT) | (val << 4);
11561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		adm1026_write_value(client, ADM1026_REG_CONFIG1,
11571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			data->config1);
11581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		up(&data->update_lock);
11591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
11601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return count;
11611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
11621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1163050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou#define temp_crit_enable(offset)				\
1164050480f12aeab62d39a1a07546606a47217ebefaYani Ioannoustatic DEVICE_ATTR(temp##offset##_crit_enable, S_IRUGO | S_IWUSR, \
11651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	show_temp_crit_enable, set_temp_crit_enable);
11661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1167050480f12aeab62d39a1a07546606a47217ebefaYani Ioannoutemp_crit_enable(1);
1168050480f12aeab62d39a1a07546606a47217ebefaYani Ioannoutemp_crit_enable(2);
1169050480f12aeab62d39a1a07546606a47217ebefaYani Ioannoutemp_crit_enable(3);
11701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1171050480f12aeab62d39a1a07546606a47217ebefaYani Ioannoustatic ssize_t show_temp_crit(struct device *dev,
1172050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou		struct device_attribute *attr, char *buf)
11731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
1174050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou	struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr);
1175050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou	int nr = sensor_attr->index;
11761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct adm1026_data *data = adm1026_update_device(dev);
11771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return sprintf(buf,"%d\n", TEMP_FROM_REG(data->temp_crit[nr]));
11781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
1179050480f12aeab62d39a1a07546606a47217ebefaYani Ioannoustatic ssize_t set_temp_crit(struct device *dev, struct device_attribute *attr,
1180050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou		const char *buf, size_t count)
11811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
1182050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou	struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr);
1183050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou	int nr = sensor_attr->index;
11841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct i2c_client *client = to_i2c_client(dev);
11851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct adm1026_data *data = i2c_get_clientdata(client);
11861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int val = simple_strtol(buf, NULL, 10);
11871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
11881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	down(&data->update_lock);
11891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	data->temp_crit[nr] = TEMP_TO_REG(val);
11901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	adm1026_write_value(client, ADM1026_REG_TEMP_THERM[nr],
11911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		data->temp_crit[nr]);
11921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	up(&data->update_lock);
11931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return count;
11941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
11951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1196050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou#define temp_crit_reg(offset)						\
1197050480f12aeab62d39a1a07546606a47217ebefaYani Ioannoustatic SENSOR_DEVICE_ATTR(temp##offset##_crit, S_IRUGO | S_IWUSR,	\
1198050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou		show_temp_crit, set_temp_crit, offset - 1);
11991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
12001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldstemp_crit_reg(1);
12011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldstemp_crit_reg(2);
12021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldstemp_crit_reg(3);
12031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
120474880c063b06efd103c924abfe19d9d8fa4864c4Yani Ioannoustatic ssize_t show_analog_out_reg(struct device *dev, struct device_attribute *attr, char *buf)
12051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
12061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct adm1026_data *data = adm1026_update_device(dev);
12071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return sprintf(buf,"%d\n", DAC_FROM_REG(data->analog_out));
12081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
120974880c063b06efd103c924abfe19d9d8fa4864c4Yani Ioannoustatic ssize_t set_analog_out_reg(struct device *dev, struct device_attribute *attr, const char *buf,
12101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		size_t count)
12111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
12121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct i2c_client *client = to_i2c_client(dev);
12131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct adm1026_data *data = i2c_get_clientdata(client);
12141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int val = simple_strtol(buf, NULL, 10);
12151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
12161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	down(&data->update_lock);
12171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	data->analog_out = DAC_TO_REG(val);
12181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	adm1026_write_value(client, ADM1026_REG_DAC, data->analog_out);
12191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	up(&data->update_lock);
12201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return count;
12211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
12221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
12231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic DEVICE_ATTR(analog_out, S_IRUGO | S_IWUSR, show_analog_out_reg,
12241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	set_analog_out_reg);
12251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
122674880c063b06efd103c924abfe19d9d8fa4864c4Yani Ioannoustatic ssize_t show_vid_reg(struct device *dev, struct device_attribute *attr, char *buf)
12271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
12281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct adm1026_data *data = adm1026_update_device(dev);
12291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return sprintf(buf,"%d\n", vid_from_reg(data->vid & 0x3f, data->vrm));
12301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
1231937df8df907ce63b0f7e19adf6e3cdef1687fac3Grant Coady/* vid deprecated in favour of cpu0_vid, remove after 2005-11-11 */
12321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic DEVICE_ATTR(vid, S_IRUGO, show_vid_reg, NULL);
1233937df8df907ce63b0f7e19adf6e3cdef1687fac3Grant Coadystatic DEVICE_ATTR(cpu0_vid, S_IRUGO, show_vid_reg, NULL);
12341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
123574880c063b06efd103c924abfe19d9d8fa4864c4Yani Ioannoustatic ssize_t show_vrm_reg(struct device *dev, struct device_attribute *attr, char *buf)
12361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
12371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct adm1026_data *data = adm1026_update_device(dev);
12381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return sprintf(buf,"%d\n", data->vrm);
12391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
124074880c063b06efd103c924abfe19d9d8fa4864c4Yani Ioannoustatic ssize_t store_vrm_reg(struct device *dev, struct device_attribute *attr, const char *buf,
12411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		size_t count)
12421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
12431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct i2c_client *client = to_i2c_client(dev);
12441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct adm1026_data *data = i2c_get_clientdata(client);
12451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
12461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	data->vrm = simple_strtol(buf, NULL, 10);
12471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return count;
12481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
12491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
12501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic DEVICE_ATTR(vrm, S_IRUGO | S_IWUSR, show_vrm_reg, store_vrm_reg);
12511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
125274880c063b06efd103c924abfe19d9d8fa4864c4Yani Ioannoustatic ssize_t show_alarms_reg(struct device *dev, struct device_attribute *attr, char *buf)
12531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
12541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct adm1026_data *data = adm1026_update_device(dev);
12551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return sprintf(buf, "%ld\n", (long) (data->alarms));
12561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
12571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
12581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic DEVICE_ATTR(alarms, S_IRUGO, show_alarms_reg, NULL);
12591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
126074880c063b06efd103c924abfe19d9d8fa4864c4Yani Ioannoustatic ssize_t show_alarm_mask(struct device *dev, struct device_attribute *attr, char *buf)
12611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
12621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct adm1026_data *data = adm1026_update_device(dev);
12631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return sprintf(buf,"%ld\n", data->alarm_mask);
12641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
126574880c063b06efd103c924abfe19d9d8fa4864c4Yani Ioannoustatic ssize_t set_alarm_mask(struct device *dev, struct device_attribute *attr, const char *buf,
12661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		size_t count)
12671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
12681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct i2c_client *client = to_i2c_client(dev);
12691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct adm1026_data *data = i2c_get_clientdata(client);
12701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int val = simple_strtol(buf, NULL, 10);
12711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	unsigned long mask;
12721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
12731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	down(&data->update_lock);
12741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	data->alarm_mask = val & 0x7fffffff;
12751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	mask = data->alarm_mask
12761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		| (data->gpio_mask & 0x10000 ? 0x80000000 : 0);
12771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	adm1026_write_value(client, ADM1026_REG_MASK1,
12781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		mask & 0xff);
12791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	mask >>= 8;
12801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	adm1026_write_value(client, ADM1026_REG_MASK2,
12811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		mask & 0xff);
12821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	mask >>= 8;
12831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	adm1026_write_value(client, ADM1026_REG_MASK3,
12841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		mask & 0xff);
12851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	mask >>= 8;
12861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	adm1026_write_value(client, ADM1026_REG_MASK4,
12871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		mask & 0xff);
12881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	up(&data->update_lock);
12891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return count;
12901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
12911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
12921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic DEVICE_ATTR(alarm_mask, S_IRUGO | S_IWUSR, show_alarm_mask,
12931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	set_alarm_mask);
12941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
12951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
129674880c063b06efd103c924abfe19d9d8fa4864c4Yani Ioannoustatic ssize_t show_gpio(struct device *dev, struct device_attribute *attr, char *buf)
12971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
12981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct adm1026_data *data = adm1026_update_device(dev);
12991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return sprintf(buf,"%ld\n", data->gpio);
13001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
130174880c063b06efd103c924abfe19d9d8fa4864c4Yani Ioannoustatic ssize_t set_gpio(struct device *dev, struct device_attribute *attr, const char *buf,
13021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		size_t count)
13031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
13041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct i2c_client *client = to_i2c_client(dev);
13051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct adm1026_data *data = i2c_get_clientdata(client);
13061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int val = simple_strtol(buf, NULL, 10);
13071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	long   gpio;
13081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
13091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	down(&data->update_lock);
13101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	data->gpio = val & 0x1ffff;
13111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	gpio = data->gpio;
13121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	adm1026_write_value(client, ADM1026_REG_GPIO_STATUS_0_7,gpio & 0xff);
13131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	gpio >>= 8;
13141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	adm1026_write_value(client, ADM1026_REG_GPIO_STATUS_8_15,gpio & 0xff);
13151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	gpio = ((gpio >> 1) & 0x80) | (data->alarms >> 24 & 0x7f);
13161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	adm1026_write_value(client, ADM1026_REG_STATUS4,gpio & 0xff);
13171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	up(&data->update_lock);
13181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return count;
13191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
13201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
13211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic DEVICE_ATTR(gpio, S_IRUGO | S_IWUSR, show_gpio, set_gpio);
13221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
13231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
132474880c063b06efd103c924abfe19d9d8fa4864c4Yani Ioannoustatic ssize_t show_gpio_mask(struct device *dev, struct device_attribute *attr, char *buf)
13251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
13261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct adm1026_data *data = adm1026_update_device(dev);
13271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return sprintf(buf,"%ld\n", data->gpio_mask);
13281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
132974880c063b06efd103c924abfe19d9d8fa4864c4Yani Ioannoustatic ssize_t set_gpio_mask(struct device *dev, struct device_attribute *attr, const char *buf,
13301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		size_t count)
13311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
13321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct i2c_client *client = to_i2c_client(dev);
13331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct adm1026_data *data = i2c_get_clientdata(client);
13341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int val = simple_strtol(buf, NULL, 10);
13351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	long   mask;
13361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
13371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	down(&data->update_lock);
13381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	data->gpio_mask = val & 0x1ffff;
13391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	mask = data->gpio_mask;
13401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	adm1026_write_value(client, ADM1026_REG_GPIO_MASK_0_7,mask & 0xff);
13411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	mask >>= 8;
13421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	adm1026_write_value(client, ADM1026_REG_GPIO_MASK_8_15,mask & 0xff);
13431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	mask = ((mask >> 1) & 0x80) | (data->alarm_mask >> 24 & 0x7f);
13441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	adm1026_write_value(client, ADM1026_REG_MASK1,mask & 0xff);
13451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	up(&data->update_lock);
13461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return count;
13471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
13481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
13491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic DEVICE_ATTR(gpio_mask, S_IRUGO | S_IWUSR, show_gpio_mask, set_gpio_mask);
13501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
135174880c063b06efd103c924abfe19d9d8fa4864c4Yani Ioannoustatic ssize_t show_pwm_reg(struct device *dev, struct device_attribute *attr, char *buf)
13521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
13531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct adm1026_data *data = adm1026_update_device(dev);
13541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return sprintf(buf,"%d\n", PWM_FROM_REG(data->pwm1.pwm));
13551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
135674880c063b06efd103c924abfe19d9d8fa4864c4Yani Ioannoustatic ssize_t set_pwm_reg(struct device *dev, struct device_attribute *attr, const char *buf,
13571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		size_t count)
13581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
13591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct i2c_client *client = to_i2c_client(dev);
13601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct adm1026_data *data = i2c_get_clientdata(client);
13611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
13621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (data->pwm1.enable == 1) {
13631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		int val = simple_strtol(buf, NULL, 10);
13641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
13651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		down(&data->update_lock);
13661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		data->pwm1.pwm = PWM_TO_REG(val);
13671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		adm1026_write_value(client, ADM1026_REG_PWM, data->pwm1.pwm);
13681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		up(&data->update_lock);
13691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
13701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return count;
13711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
137274880c063b06efd103c924abfe19d9d8fa4864c4Yani Ioannoustatic ssize_t show_auto_pwm_min(struct device *dev, struct device_attribute *attr, char *buf)
13731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
13741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct adm1026_data *data = adm1026_update_device(dev);
13751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return sprintf(buf,"%d\n", data->pwm1.auto_pwm_min);
13761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
137774880c063b06efd103c924abfe19d9d8fa4864c4Yani Ioannoustatic ssize_t set_auto_pwm_min(struct device *dev, struct device_attribute *attr, const char *buf,
13781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		size_t count)
13791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
13801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct i2c_client *client = to_i2c_client(dev);
13811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct adm1026_data *data = i2c_get_clientdata(client);
13821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int val = simple_strtol(buf, NULL, 10);
13831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
13841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	down(&data->update_lock);
13851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	data->pwm1.auto_pwm_min = SENSORS_LIMIT(val,0,255);
13861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (data->pwm1.enable == 2) { /* apply immediately */
13871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		data->pwm1.pwm = PWM_TO_REG((data->pwm1.pwm & 0x0f) |
13881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			PWM_MIN_TO_REG(data->pwm1.auto_pwm_min));
13891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		adm1026_write_value(client, ADM1026_REG_PWM, data->pwm1.pwm);
13901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
13911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	up(&data->update_lock);
13921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return count;
13931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
139474880c063b06efd103c924abfe19d9d8fa4864c4Yani Ioannoustatic ssize_t show_auto_pwm_max(struct device *dev, struct device_attribute *attr, char *buf)
13951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
13961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return sprintf(buf,"%d\n", ADM1026_PWM_MAX);
13971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
139874880c063b06efd103c924abfe19d9d8fa4864c4Yani Ioannoustatic ssize_t show_pwm_enable(struct device *dev, struct device_attribute *attr, char *buf)
13991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
14001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct adm1026_data *data = adm1026_update_device(dev);
14011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return sprintf(buf,"%d\n", data->pwm1.enable);
14021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
140374880c063b06efd103c924abfe19d9d8fa4864c4Yani Ioannoustatic ssize_t set_pwm_enable(struct device *dev, struct device_attribute *attr, const char *buf,
14041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		size_t count)
14051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
14061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct i2c_client *client = to_i2c_client(dev);
14071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct adm1026_data *data = i2c_get_clientdata(client);
14081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int val = simple_strtol(buf, NULL, 10);
14091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int     old_enable;
14101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
14111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if ((val >= 0) && (val < 3)) {
14121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		down(&data->update_lock);
14131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		old_enable = data->pwm1.enable;
14141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		data->pwm1.enable = val;
14151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		data->config1 = (data->config1 & ~CFG1_PWM_AFC)
14161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				| ((val == 2) ? CFG1_PWM_AFC : 0);
14171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		adm1026_write_value(client, ADM1026_REG_CONFIG1,
14181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			data->config1);
14191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (val == 2) {  /* apply pwm1_auto_pwm_min to pwm1 */
14201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			data->pwm1.pwm = PWM_TO_REG((data->pwm1.pwm & 0x0f) |
14211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				PWM_MIN_TO_REG(data->pwm1.auto_pwm_min));
14221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			adm1026_write_value(client, ADM1026_REG_PWM,
14231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				data->pwm1.pwm);
14241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		} else if (!((old_enable == 1) && (val == 1))) {
14251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			/* set pwm to safe value */
14261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			data->pwm1.pwm = 255;
14271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			adm1026_write_value(client, ADM1026_REG_PWM,
14281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				data->pwm1.pwm);
14291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
14301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		up(&data->update_lock);
14311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
14321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return count;
14331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
14341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
14351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* enable PWM fan control */
14361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic DEVICE_ATTR(pwm1, S_IRUGO | S_IWUSR, show_pwm_reg, set_pwm_reg);
14371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic DEVICE_ATTR(pwm2, S_IRUGO | S_IWUSR, show_pwm_reg, set_pwm_reg);
14381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic DEVICE_ATTR(pwm3, S_IRUGO | S_IWUSR, show_pwm_reg, set_pwm_reg);
14391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic DEVICE_ATTR(pwm1_enable, S_IRUGO | S_IWUSR, show_pwm_enable,
14401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	set_pwm_enable);
14411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic DEVICE_ATTR(pwm2_enable, S_IRUGO | S_IWUSR, show_pwm_enable,
14421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	set_pwm_enable);
14431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic DEVICE_ATTR(pwm3_enable, S_IRUGO | S_IWUSR, show_pwm_enable,
14441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	set_pwm_enable);
14451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic DEVICE_ATTR(temp1_auto_point1_pwm, S_IRUGO | S_IWUSR,
14461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	show_auto_pwm_min, set_auto_pwm_min);
14471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic DEVICE_ATTR(temp2_auto_point1_pwm, S_IRUGO | S_IWUSR,
14481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	show_auto_pwm_min, set_auto_pwm_min);
14491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic DEVICE_ATTR(temp3_auto_point1_pwm, S_IRUGO | S_IWUSR,
14501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	show_auto_pwm_min, set_auto_pwm_min);
14511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
14521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic DEVICE_ATTR(temp1_auto_point2_pwm, S_IRUGO, show_auto_pwm_max, NULL);
14531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic DEVICE_ATTR(temp2_auto_point2_pwm, S_IRUGO, show_auto_pwm_max, NULL);
14541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic DEVICE_ATTR(temp3_auto_point2_pwm, S_IRUGO, show_auto_pwm_max, NULL);
14551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
14561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsint adm1026_detect(struct i2c_adapter *adapter, int address,
14571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		int kind)
14581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
14591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int company, verstep;
14601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct i2c_client *new_client;
14611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct adm1026_data *data;
14621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int err = 0;
14631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	const char *type_name = "";
14641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
14651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA)) {
14661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		/* We need to be able to do byte I/O */
14671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		goto exit;
14681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	};
14691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
14701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* OK. For now, we presume we have a valid client. We now create the
14711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	   client structure, even though we cannot fill it completely yet.
14721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	   But it allows us to access adm1026_{read,write}_value. */
14731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
14741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (!(data = kmalloc(sizeof(struct adm1026_data), GFP_KERNEL))) {
14751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		err = -ENOMEM;
14761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		goto exit;
14771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
14781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
14791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	memset(data, 0, sizeof(struct adm1026_data));
14801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
14811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	new_client = &data->client;
14821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	i2c_set_clientdata(new_client, data);
14831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	new_client->addr = address;
14841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	new_client->adapter = adapter;
14851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	new_client->driver = &adm1026_driver;
14861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	new_client->flags = 0;
14871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
14881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* Now, we do the remaining detection. */
14891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
14901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	company = adm1026_read_value(new_client, ADM1026_REG_COMPANY);
14911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	verstep = adm1026_read_value(new_client, ADM1026_REG_VERSTEP);
14921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
14931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	dev_dbg(&new_client->dev, "Detecting device at %d,0x%02x with"
14941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		" COMPANY: 0x%02x and VERSTEP: 0x%02x\n",
14951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		i2c_adapter_id(new_client->adapter), new_client->addr,
14961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		company, verstep);
14971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
14981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* If auto-detecting, Determine the chip type. */
14991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (kind <= 0) {
15001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		dev_dbg(&new_client->dev, "Autodetecting device at %d,0x%02x "
15011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			"...\n", i2c_adapter_id(adapter), address);
15021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (company == ADM1026_COMPANY_ANALOG_DEV
15031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		    && verstep == ADM1026_VERSTEP_ADM1026) {
15041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			kind = adm1026;
15051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		} else if (company == ADM1026_COMPANY_ANALOG_DEV
15061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			&& (verstep & 0xf0) == ADM1026_VERSTEP_GENERIC) {
15071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			dev_err(&adapter->dev, ": Unrecognized stepping "
15081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				"0x%02x. Defaulting to ADM1026.\n", verstep);
15091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			kind = adm1026;
15101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		} else if ((verstep & 0xf0) == ADM1026_VERSTEP_GENERIC) {
15111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			dev_err(&adapter->dev, ": Found version/stepping "
15121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				"0x%02x. Assuming generic ADM1026.\n",
15131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				verstep);
15141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			kind = any_chip;
15151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		} else {
15161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			dev_dbg(&new_client->dev, ": Autodetection "
15171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				"failed\n");
15181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			/* Not an ADM1026 ... */
15191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			if (kind == 0)  { /* User used force=x,y */
15201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				dev_err(&adapter->dev, "Generic ADM1026 not "
15211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds					"found at %d,0x%02x.  Try "
15221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds					"force_adm1026.\n",
15231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds					i2c_adapter_id(adapter), address);
15241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			}
15251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			err = 0;
15261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			goto exitfree;
15271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
15281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
15291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
15301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* Fill in the chip specific driver values */
15311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	switch (kind) {
15321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case any_chip :
15331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		type_name = "adm1026";
15341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		break;
15351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case adm1026 :
15361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		type_name = "adm1026";
15371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		break;
15381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	default :
15391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		dev_err(&adapter->dev, ": Internal error, invalid "
15401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			"kind (%d)!", kind);
15411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		err = -EFAULT;
15421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		goto exitfree;
15431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
15441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	strlcpy(new_client->name, type_name, I2C_NAME_SIZE);
15451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
15461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* Fill in the remaining client fields */
15471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	data->type = kind;
15481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	data->valid = 0;
15491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	init_MUTEX(&data->update_lock);
15501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
15511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* Tell the I2C layer a new client has arrived */
15521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if ((err = i2c_attach_client(new_client)))
15531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		goto exitfree;
15541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
15551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* Set the VRM version */
15561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	data->vrm = i2c_which_vrm();
15571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
15581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* Initialize the ADM1026 chip */
15591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	adm1026_init_client(new_client);
15601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
15611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* Register sysfs hooks */
1562943b0830cebe4711354945ed3cb44e84152aaca0Mark M. Hoffman	data->class_dev = hwmon_device_register(&new_client->dev);
1563943b0830cebe4711354945ed3cb44e84152aaca0Mark M. Hoffman	if (IS_ERR(data->class_dev)) {
1564943b0830cebe4711354945ed3cb44e84152aaca0Mark M. Hoffman		err = PTR_ERR(data->class_dev);
1565943b0830cebe4711354945ed3cb44e84152aaca0Mark M. Hoffman		goto exitdetach;
1566943b0830cebe4711354945ed3cb44e84152aaca0Mark M. Hoffman	}
1567943b0830cebe4711354945ed3cb44e84152aaca0Mark M. Hoffman
1568050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou	device_create_file(&new_client->dev, &sensor_dev_attr_in0_input.dev_attr);
1569050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou	device_create_file(&new_client->dev, &sensor_dev_attr_in0_max.dev_attr);
1570050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou	device_create_file(&new_client->dev, &sensor_dev_attr_in0_min.dev_attr);
1571050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou	device_create_file(&new_client->dev, &sensor_dev_attr_in1_input.dev_attr);
1572050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou	device_create_file(&new_client->dev, &sensor_dev_attr_in1_max.dev_attr);
1573050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou	device_create_file(&new_client->dev, &sensor_dev_attr_in1_min.dev_attr);
1574050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou	device_create_file(&new_client->dev, &sensor_dev_attr_in2_input.dev_attr);
1575050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou	device_create_file(&new_client->dev, &sensor_dev_attr_in2_max.dev_attr);
1576050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou	device_create_file(&new_client->dev, &sensor_dev_attr_in2_min.dev_attr);
1577050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou	device_create_file(&new_client->dev, &sensor_dev_attr_in3_input.dev_attr);
1578050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou	device_create_file(&new_client->dev, &sensor_dev_attr_in3_max.dev_attr);
1579050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou	device_create_file(&new_client->dev, &sensor_dev_attr_in3_min.dev_attr);
1580050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou	device_create_file(&new_client->dev, &sensor_dev_attr_in4_input.dev_attr);
1581050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou	device_create_file(&new_client->dev, &sensor_dev_attr_in4_max.dev_attr);
1582050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou	device_create_file(&new_client->dev, &sensor_dev_attr_in4_min.dev_attr);
1583050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou	device_create_file(&new_client->dev, &sensor_dev_attr_in5_input.dev_attr);
1584050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou	device_create_file(&new_client->dev, &sensor_dev_attr_in5_max.dev_attr);
1585050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou	device_create_file(&new_client->dev, &sensor_dev_attr_in5_min.dev_attr);
1586050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou	device_create_file(&new_client->dev, &sensor_dev_attr_in6_input.dev_attr);
1587050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou	device_create_file(&new_client->dev, &sensor_dev_attr_in6_max.dev_attr);
1588050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou	device_create_file(&new_client->dev, &sensor_dev_attr_in6_min.dev_attr);
1589050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou	device_create_file(&new_client->dev, &sensor_dev_attr_in7_input.dev_attr);
1590050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou	device_create_file(&new_client->dev, &sensor_dev_attr_in7_max.dev_attr);
1591050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou	device_create_file(&new_client->dev, &sensor_dev_attr_in7_min.dev_attr);
1592050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou	device_create_file(&new_client->dev, &sensor_dev_attr_in8_input.dev_attr);
1593050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou	device_create_file(&new_client->dev, &sensor_dev_attr_in8_max.dev_attr);
1594050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou	device_create_file(&new_client->dev, &sensor_dev_attr_in8_min.dev_attr);
1595050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou	device_create_file(&new_client->dev, &sensor_dev_attr_in9_input.dev_attr);
1596050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou	device_create_file(&new_client->dev, &sensor_dev_attr_in9_max.dev_attr);
1597050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou	device_create_file(&new_client->dev, &sensor_dev_attr_in9_min.dev_attr);
1598050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou	device_create_file(&new_client->dev, &sensor_dev_attr_in10_input.dev_attr);
1599050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou	device_create_file(&new_client->dev, &sensor_dev_attr_in10_max.dev_attr);
1600050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou	device_create_file(&new_client->dev, &sensor_dev_attr_in10_min.dev_attr);
1601050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou	device_create_file(&new_client->dev, &sensor_dev_attr_in11_input.dev_attr);
1602050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou	device_create_file(&new_client->dev, &sensor_dev_attr_in11_max.dev_attr);
1603050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou	device_create_file(&new_client->dev, &sensor_dev_attr_in11_min.dev_attr);
1604050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou	device_create_file(&new_client->dev, &sensor_dev_attr_in12_input.dev_attr);
1605050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou	device_create_file(&new_client->dev, &sensor_dev_attr_in12_max.dev_attr);
1606050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou	device_create_file(&new_client->dev, &sensor_dev_attr_in12_min.dev_attr);
1607050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou	device_create_file(&new_client->dev, &sensor_dev_attr_in13_input.dev_attr);
1608050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou	device_create_file(&new_client->dev, &sensor_dev_attr_in13_max.dev_attr);
1609050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou	device_create_file(&new_client->dev, &sensor_dev_attr_in13_min.dev_attr);
1610050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou	device_create_file(&new_client->dev, &sensor_dev_attr_in14_input.dev_attr);
1611050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou	device_create_file(&new_client->dev, &sensor_dev_attr_in14_max.dev_attr);
1612050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou	device_create_file(&new_client->dev, &sensor_dev_attr_in14_min.dev_attr);
1613050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou	device_create_file(&new_client->dev, &sensor_dev_attr_in15_input.dev_attr);
1614050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou	device_create_file(&new_client->dev, &sensor_dev_attr_in15_max.dev_attr);
1615050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou	device_create_file(&new_client->dev, &sensor_dev_attr_in15_min.dev_attr);
1616050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou	device_create_file(&new_client->dev, &sensor_dev_attr_in16_input.dev_attr);
1617050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou	device_create_file(&new_client->dev, &sensor_dev_attr_in16_max.dev_attr);
1618050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou	device_create_file(&new_client->dev, &sensor_dev_attr_in16_min.dev_attr);
1619050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou	device_create_file(&new_client->dev, &sensor_dev_attr_fan1_input.dev_attr);
1620050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou	device_create_file(&new_client->dev, &sensor_dev_attr_fan1_div.dev_attr);
1621050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou	device_create_file(&new_client->dev, &sensor_dev_attr_fan1_min.dev_attr);
1622050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou	device_create_file(&new_client->dev, &sensor_dev_attr_fan2_input.dev_attr);
1623050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou	device_create_file(&new_client->dev, &sensor_dev_attr_fan2_div.dev_attr);
1624050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou	device_create_file(&new_client->dev, &sensor_dev_attr_fan2_min.dev_attr);
1625050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou	device_create_file(&new_client->dev, &sensor_dev_attr_fan3_input.dev_attr);
1626050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou	device_create_file(&new_client->dev, &sensor_dev_attr_fan3_div.dev_attr);
1627050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou	device_create_file(&new_client->dev, &sensor_dev_attr_fan3_min.dev_attr);
1628050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou	device_create_file(&new_client->dev, &sensor_dev_attr_fan4_input.dev_attr);
1629050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou	device_create_file(&new_client->dev, &sensor_dev_attr_fan4_div.dev_attr);
1630050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou	device_create_file(&new_client->dev, &sensor_dev_attr_fan4_min.dev_attr);
1631050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou	device_create_file(&new_client->dev, &sensor_dev_attr_fan5_input.dev_attr);
1632050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou	device_create_file(&new_client->dev, &sensor_dev_attr_fan5_div.dev_attr);
1633050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou	device_create_file(&new_client->dev, &sensor_dev_attr_fan5_min.dev_attr);
1634050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou	device_create_file(&new_client->dev, &sensor_dev_attr_fan6_input.dev_attr);
1635050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou	device_create_file(&new_client->dev, &sensor_dev_attr_fan6_div.dev_attr);
1636050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou	device_create_file(&new_client->dev, &sensor_dev_attr_fan6_min.dev_attr);
1637050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou	device_create_file(&new_client->dev, &sensor_dev_attr_fan7_input.dev_attr);
1638050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou	device_create_file(&new_client->dev, &sensor_dev_attr_fan7_div.dev_attr);
1639050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou	device_create_file(&new_client->dev, &sensor_dev_attr_fan7_min.dev_attr);
1640050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou	device_create_file(&new_client->dev, &sensor_dev_attr_fan8_input.dev_attr);
1641050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou	device_create_file(&new_client->dev, &sensor_dev_attr_fan8_div.dev_attr);
1642050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou	device_create_file(&new_client->dev, &sensor_dev_attr_fan8_min.dev_attr);
1643050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou	device_create_file(&new_client->dev, &sensor_dev_attr_temp1_input.dev_attr);
1644050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou	device_create_file(&new_client->dev, &sensor_dev_attr_temp1_max.dev_attr);
1645050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou	device_create_file(&new_client->dev, &sensor_dev_attr_temp1_min.dev_attr);
1646050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou	device_create_file(&new_client->dev, &sensor_dev_attr_temp2_input.dev_attr);
1647050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou	device_create_file(&new_client->dev, &sensor_dev_attr_temp2_max.dev_attr);
1648050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou	device_create_file(&new_client->dev, &sensor_dev_attr_temp2_min.dev_attr);
1649050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou	device_create_file(&new_client->dev, &sensor_dev_attr_temp3_input.dev_attr);
1650050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou	device_create_file(&new_client->dev, &sensor_dev_attr_temp3_max.dev_attr);
1651050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou	device_create_file(&new_client->dev, &sensor_dev_attr_temp3_min.dev_attr);
1652050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou	device_create_file(&new_client->dev, &sensor_dev_attr_temp1_offset.dev_attr);
1653050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou	device_create_file(&new_client->dev, &sensor_dev_attr_temp2_offset.dev_attr);
1654050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou	device_create_file(&new_client->dev, &sensor_dev_attr_temp3_offset.dev_attr);
16551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	device_create_file(&new_client->dev,
1656050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou		&sensor_dev_attr_temp1_auto_point1_temp.dev_attr);
16571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	device_create_file(&new_client->dev,
1658050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou		&sensor_dev_attr_temp2_auto_point1_temp.dev_attr);
16591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	device_create_file(&new_client->dev,
1660050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou		&sensor_dev_attr_temp3_auto_point1_temp.dev_attr);
16611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	device_create_file(&new_client->dev,
1662050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou		&sensor_dev_attr_temp1_auto_point1_temp_hyst.dev_attr);
16631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	device_create_file(&new_client->dev,
1664050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou		&sensor_dev_attr_temp2_auto_point1_temp_hyst.dev_attr);
16651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	device_create_file(&new_client->dev,
1666050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou		&sensor_dev_attr_temp3_auto_point1_temp_hyst.dev_attr);
16671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	device_create_file(&new_client->dev,
1668050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou		&sensor_dev_attr_temp1_auto_point2_temp.dev_attr);
16691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	device_create_file(&new_client->dev,
1670050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou		&sensor_dev_attr_temp2_auto_point2_temp.dev_attr);
16711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	device_create_file(&new_client->dev,
1672050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou		&sensor_dev_attr_temp3_auto_point2_temp.dev_attr);
1673050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou	device_create_file(&new_client->dev, &sensor_dev_attr_temp1_crit.dev_attr);
1674050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou	device_create_file(&new_client->dev, &sensor_dev_attr_temp2_crit.dev_attr);
1675050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou	device_create_file(&new_client->dev, &sensor_dev_attr_temp3_crit.dev_attr);
16761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	device_create_file(&new_client->dev, &dev_attr_temp1_crit_enable);
16771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	device_create_file(&new_client->dev, &dev_attr_temp2_crit_enable);
16781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	device_create_file(&new_client->dev, &dev_attr_temp3_crit_enable);
1679937df8df907ce63b0f7e19adf6e3cdef1687fac3Grant Coady	/* vid deprecated in favour of cpu0_vid, remove after 2005-11-11 */
16801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	device_create_file(&new_client->dev, &dev_attr_vid);
1681937df8df907ce63b0f7e19adf6e3cdef1687fac3Grant Coady	device_create_file(&new_client->dev, &dev_attr_cpu0_vid);
16821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	device_create_file(&new_client->dev, &dev_attr_vrm);
16831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	device_create_file(&new_client->dev, &dev_attr_alarms);
16841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	device_create_file(&new_client->dev, &dev_attr_alarm_mask);
16851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	device_create_file(&new_client->dev, &dev_attr_gpio);
16861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	device_create_file(&new_client->dev, &dev_attr_gpio_mask);
16871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	device_create_file(&new_client->dev, &dev_attr_pwm1);
16881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	device_create_file(&new_client->dev, &dev_attr_pwm2);
16891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	device_create_file(&new_client->dev, &dev_attr_pwm3);
16901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	device_create_file(&new_client->dev, &dev_attr_pwm1_enable);
16911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	device_create_file(&new_client->dev, &dev_attr_pwm2_enable);
16921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	device_create_file(&new_client->dev, &dev_attr_pwm3_enable);
16931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	device_create_file(&new_client->dev, &dev_attr_temp1_auto_point1_pwm);
16941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	device_create_file(&new_client->dev, &dev_attr_temp2_auto_point1_pwm);
16951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	device_create_file(&new_client->dev, &dev_attr_temp3_auto_point1_pwm);
16961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	device_create_file(&new_client->dev, &dev_attr_temp1_auto_point2_pwm);
16971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	device_create_file(&new_client->dev, &dev_attr_temp2_auto_point2_pwm);
16981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	device_create_file(&new_client->dev, &dev_attr_temp3_auto_point2_pwm);
16991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	device_create_file(&new_client->dev, &dev_attr_analog_out);
17001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return 0;
17011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
17021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* Error out and cleanup code */
1703943b0830cebe4711354945ed3cb44e84152aaca0Mark M. Hoffmanexitdetach:
1704943b0830cebe4711354945ed3cb44e84152aaca0Mark M. Hoffman	i2c_detach_client(new_client);
17051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsexitfree:
17061f57ff89fee47a317e9e8ca63bf0f139802cc116Alexey Dobriyan	kfree(data);
17071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsexit:
17081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return err;
17091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
17101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int __init sm_adm1026_init(void)
17111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
17121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return i2c_add_driver(&adm1026_driver);
17131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
17141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
17151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void  __exit sm_adm1026_exit(void)
17161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
17171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	i2c_del_driver(&adm1026_driver);
17181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
17191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
17201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsMODULE_LICENSE("GPL");
17211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsMODULE_AUTHOR("Philip Pokorny <ppokorny@penguincomputing.com>, "
17221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds              "Justin Thiessen <jthiessen@penguincomputing.com>");
17231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsMODULE_DESCRIPTION("ADM1026 driver");
17241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
17251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsmodule_init(sm_adm1026_init);
17261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsmodule_exit(sm_adm1026_exit);
1727