adm1026.c revision 25e9c86d5a6d82ea45eb680fc66bf73ac5e50dff
11da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* 21da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds adm1026.c - Part of lm_sensors, Linux kernel modules for hardware 31da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds monitoring 41da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds Copyright (C) 2002, 2003 Philip Pokorny <ppokorny@penguincomputing.com> 51da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds Copyright (C) 2004 Justin Thiessen <jthiessen@penguincomputing.com> 61da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 71da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds Chip details at: 81da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 91da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds <http://www.analog.com/UploadedFiles/Data_Sheets/779263102ADM1026_a.pdf> 101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds This program is free software; you can redistribute it and/or modify 121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds it under the terms of the GNU General Public License as published by 131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds the Free Software Foundation; either version 2 of the License, or 141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds (at your option) any later version. 151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds This program is distributed in the hope that it will be useful, 171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds but WITHOUT ANY WARRANTY; without even the implied warranty of 181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds GNU General Public License for more details. 201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds You should have received a copy of the GNU General Public License 221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds along with this program; if not, write to the Free Software 231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds*/ 251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/module.h> 271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/init.h> 281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/slab.h> 291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/jiffies.h> 301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/i2c.h> 31943b0830cebe4711354945ed3cb44e84152aaca0Mark M. Hoffman#include <linux/hwmon.h> 32303760b44a7a142cb9f4c9df4609fb63bbda98dbJean Delvare#include <linux/hwmon-sysfs.h> 33303760b44a7a142cb9f4c9df4609fb63bbda98dbJean Delvare#include <linux/hwmon-vid.h> 34943b0830cebe4711354945ed3cb44e84152aaca0Mark M. Hoffman#include <linux/err.h> 359a61bf6300533d3b64d7ff29adfec00e596de67dIngo Molnar#include <linux/mutex.h> 361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* Addresses to scan */ 3825e9c86d5a6d82ea45eb680fc66bf73ac5e50dffMark M. Hoffmanstatic const unsigned short normal_i2c[] = { 0x2c, 0x2d, 0x2e, I2C_CLIENT_END }; 391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* Insmod parameters */ 41f4b50261207c987913f076d867c2e154d71fd012Jean DelvareI2C_CLIENT_INSMOD_1(adm1026); 421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 43cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvarestatic int gpio_input[17] = { -1, -1, -1, -1, -1, -1, -1, -1, -1, 44cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvare -1, -1, -1, -1, -1, -1, -1, -1 }; 451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int gpio_output[17] = { -1, -1, -1, -1, -1, -1, -1, -1, -1, 461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds -1, -1, -1, -1, -1, -1, -1, -1 }; 471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int gpio_inverted[17] = { -1, -1, -1, -1, -1, -1, -1, -1, -1, 481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds -1, -1, -1, -1, -1, -1, -1, -1 }; 491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int gpio_normal[17] = { -1, -1, -1, -1, -1, -1, -1, -1, -1, 501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds -1, -1, -1, -1, -1, -1, -1, -1 }; 511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int gpio_fan[8] = { -1, -1, -1, -1, -1, -1, -1, -1 }; 52cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvaremodule_param_array(gpio_input, int, NULL, 0); 53cb01a2312f56c93d2740e827718966b92b7cbb91Jean DelvareMODULE_PARM_DESC(gpio_input, "List of GPIO pins (0-16) to program as inputs"); 54cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvaremodule_param_array(gpio_output, int, NULL, 0); 55cb01a2312f56c93d2740e827718966b92b7cbb91Jean DelvareMODULE_PARM_DESC(gpio_output, "List of GPIO pins (0-16) to program as " 561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "outputs"); 57cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvaremodule_param_array(gpio_inverted, int, NULL, 0); 58cb01a2312f56c93d2740e827718966b92b7cbb91Jean DelvareMODULE_PARM_DESC(gpio_inverted, "List of GPIO pins (0-16) to program as " 591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "inverted"); 60cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvaremodule_param_array(gpio_normal, int, NULL, 0); 61cb01a2312f56c93d2740e827718966b92b7cbb91Jean DelvareMODULE_PARM_DESC(gpio_normal, "List of GPIO pins (0-16) to program as " 621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "normal/non-inverted"); 63cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvaremodule_param_array(gpio_fan, int, NULL, 0); 64cb01a2312f56c93d2740e827718966b92b7cbb91Jean DelvareMODULE_PARM_DESC(gpio_fan, "List of GPIO pins (0-7) to program as fan tachs"); 651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* Many ADM1026 constants specified below */ 671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* The ADM1026 registers */ 69cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvare#define ADM1026_REG_CONFIG1 0x00 70cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvare#define CFG1_MONITOR 0x01 71cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvare#define CFG1_INT_ENABLE 0x02 72cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvare#define CFG1_INT_CLEAR 0x04 73cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvare#define CFG1_AIN8_9 0x08 74cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvare#define CFG1_THERM_HOT 0x10 75cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvare#define CFG1_DAC_AFC 0x20 76cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvare#define CFG1_PWM_AFC 0x40 77cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvare#define CFG1_RESET 0x80 78cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvare 79cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvare#define ADM1026_REG_CONFIG2 0x01 801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* CONFIG2 controls FAN0/GPIO0 through FAN7/GPIO7 */ 81cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvare 82cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvare#define ADM1026_REG_CONFIG3 0x07 83cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvare#define CFG3_GPIO16_ENABLE 0x01 84cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvare#define CFG3_CI_CLEAR 0x02 85cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvare#define CFG3_VREF_250 0x04 86cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvare#define CFG3_GPIO16_DIR 0x40 87cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvare#define CFG3_GPIO16_POL 0x80 88cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvare 89cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvare#define ADM1026_REG_E2CONFIG 0x13 90cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvare#define E2CFG_READ 0x01 91cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvare#define E2CFG_WRITE 0x02 92cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvare#define E2CFG_ERASE 0x04 93cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvare#define E2CFG_ROM 0x08 94cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvare#define E2CFG_CLK_EXT 0x80 951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* There are 10 general analog inputs and 7 dedicated inputs 971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * They are: 981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 0 - 9 = AIN0 - AIN9 991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 10 = Vbat 1001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 11 = 3.3V Standby 1011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 12 = 3.3V Main 1021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 13 = +5V 1031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 14 = Vccp (CPU core voltage) 1041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 15 = +12V 1051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 16 = -12V 1061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 1071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic u16 ADM1026_REG_IN[] = { 1081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 1091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 0x36, 0x37, 0x27, 0x29, 0x26, 0x2a, 1101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 0x2b, 0x2c, 0x2d, 0x2e, 0x2f 1111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds }; 1121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic u16 ADM1026_REG_IN_MIN[] = { 1131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 0x58, 0x59, 0x5a, 0x5b, 0x5c, 0x5d, 1141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 0x5e, 0x5f, 0x6d, 0x49, 0x6b, 0x4a, 1151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 0x4b, 0x4c, 0x4d, 0x4e, 0x4f 1161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds }; 1171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic u16 ADM1026_REG_IN_MAX[] = { 1181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 1191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 0x56, 0x57, 0x6c, 0x41, 0x6a, 0x42, 1201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 0x43, 0x44, 0x45, 0x46, 0x47 1211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds }; 1221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* Temperatures are: 1241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 0 - Internal 1251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 1 - External 1 1261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 2 - External 2 1271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 1281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic u16 ADM1026_REG_TEMP[] = { 0x1f, 0x28, 0x29 }; 1291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic u16 ADM1026_REG_TEMP_MIN[] = { 0x69, 0x48, 0x49 }; 1301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic u16 ADM1026_REG_TEMP_MAX[] = { 0x68, 0x40, 0x41 }; 1311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic u16 ADM1026_REG_TEMP_TMIN[] = { 0x10, 0x11, 0x12 }; 1321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic u16 ADM1026_REG_TEMP_THERM[] = { 0x0d, 0x0e, 0x0f }; 1331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic u16 ADM1026_REG_TEMP_OFFSET[] = { 0x1e, 0x6e, 0x6f }; 1341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 135cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvare#define ADM1026_REG_FAN(nr) (0x38 + (nr)) 136cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvare#define ADM1026_REG_FAN_MIN(nr) (0x60 + (nr)) 137cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvare#define ADM1026_REG_FAN_DIV_0_3 0x02 138cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvare#define ADM1026_REG_FAN_DIV_4_7 0x03 1391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 140cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvare#define ADM1026_REG_DAC 0x04 141cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvare#define ADM1026_REG_PWM 0x05 1421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 143cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvare#define ADM1026_REG_GPIO_CFG_0_3 0x08 144cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvare#define ADM1026_REG_GPIO_CFG_4_7 0x09 145cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvare#define ADM1026_REG_GPIO_CFG_8_11 0x0a 146cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvare#define ADM1026_REG_GPIO_CFG_12_15 0x0b 1471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* CFG_16 in REG_CFG3 */ 148cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvare#define ADM1026_REG_GPIO_STATUS_0_7 0x24 149cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvare#define ADM1026_REG_GPIO_STATUS_8_15 0x25 1501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* STATUS_16 in REG_STATUS4 */ 151cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvare#define ADM1026_REG_GPIO_MASK_0_7 0x1c 152cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvare#define ADM1026_REG_GPIO_MASK_8_15 0x1d 1531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* MASK_16 in REG_MASK4 */ 1541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 155cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvare#define ADM1026_REG_COMPANY 0x16 156cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvare#define ADM1026_REG_VERSTEP 0x17 1571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* These are the recognized values for the above regs */ 158cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvare#define ADM1026_COMPANY_ANALOG_DEV 0x41 159cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvare#define ADM1026_VERSTEP_GENERIC 0x40 160cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvare#define ADM1026_VERSTEP_ADM1026 0x44 1611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 162cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvare#define ADM1026_REG_MASK1 0x18 163cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvare#define ADM1026_REG_MASK2 0x19 164cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvare#define ADM1026_REG_MASK3 0x1a 165cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvare#define ADM1026_REG_MASK4 0x1b 1661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 167cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvare#define ADM1026_REG_STATUS1 0x20 168cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvare#define ADM1026_REG_STATUS2 0x21 169cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvare#define ADM1026_REG_STATUS3 0x22 170cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvare#define ADM1026_REG_STATUS4 0x23 1711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define ADM1026_FAN_ACTIVATION_TEMP_HYST -6 173cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvare#define ADM1026_FAN_CONTROL_TEMP_RANGE 20 174cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvare#define ADM1026_PWM_MAX 255 1751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 176cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvare/* Conversions. Rounding and limit checking is only done on the TO_REG 1771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * variants. Note that you should be a bit careful with which arguments 1781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * these macros are called: arguments may be evaluated more than once. 1791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 1801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* IN are scaled acording to built-in resistors. These are the 1821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * voltages corresponding to 3/4 of full scale (192 or 0xc0) 1831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * NOTE: The -12V input needs an additional factor to account 1841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * for the Vref pullup resistor. 1851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * NEG12_OFFSET = SCALE * Vref / V-192 - Vref 1861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * = 13875 * 2.50 / 1.875 - 2500 1871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * = 16000 1881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 1891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * The values in this table are based on Table II, page 15 of the 1901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * datasheet. 1911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 192cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvarestatic int adm1026_scaling[] = { /* .001 Volts */ 193cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvare 2250, 2250, 2250, 2250, 2250, 2250, 194cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvare 1875, 1875, 1875, 1875, 3000, 3330, 1951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3330, 4995, 2250, 12000, 13875 1961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds }; 1971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define NEG12_OFFSET 16000 198cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvare#define SCALE(val, from, to) (((val)*(to) + ((from)/2))/(from)) 199cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvare#define INS_TO_REG(n, val) (SENSORS_LIMIT(SCALE(val, adm1026_scaling[n], 192),\ 200cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvare 0, 255)) 201cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvare#define INS_FROM_REG(n, val) (SCALE(val, 192, adm1026_scaling[n])) 2021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* FAN speed is measured using 22.5kHz clock and counts for 2 pulses 2041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * and we assume a 2 pulse-per-rev fan tach signal 2051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 22500 kHz * 60 (sec/min) * 2 (pulse) / 2 (pulse/rev) == 1350000 2061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 207cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvare#define FAN_TO_REG(val, div) ((val) <= 0 ? 0xff : \ 208cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvare SENSORS_LIMIT(1350000/((val)*(div)), 1, 254)) 209cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvare#define FAN_FROM_REG(val, div) ((val) == 0 ? -1:(val) == 0xff ? 0 : \ 210cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvare 1350000/((val)*(div))) 2111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define DIV_FROM_REG(val) (1<<(val)) 212cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvare#define DIV_TO_REG(val) ((val) >= 8 ? 3 : (val) >= 4 ? 2 : (val) >= 2 ? 1 : 0) 2131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* Temperature is reported in 1 degC increments */ 2151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define TEMP_TO_REG(val) (SENSORS_LIMIT(((val)+((val)<0 ? -500 : 500))/1000,\ 216cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvare -127, 127)) 2171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define TEMP_FROM_REG(val) ((val) * 1000) 2181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define OFFSET_TO_REG(val) (SENSORS_LIMIT(((val)+((val)<0 ? -500 : 500))/1000,\ 219cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvare -127, 127)) 2201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define OFFSET_FROM_REG(val) ((val) * 1000) 2211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 222cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvare#define PWM_TO_REG(val) (SENSORS_LIMIT(val, 0, 255)) 2231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define PWM_FROM_REG(val) (val) 2241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define PWM_MIN_TO_REG(val) ((val) & 0xf0) 2261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define PWM_MIN_FROM_REG(val) (((val) & 0xf0) + ((val) >> 4)) 2271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 228cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvare/* Analog output is a voltage, and scaled to millivolts. The datasheet 229cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvare * indicates that the DAC could be used to drive the fans, but in our 2301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * example board (Arima HDAMA) it isn't connected to the fans at all. 2311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 232cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvare#define DAC_TO_REG(val) (SENSORS_LIMIT(((((val)*255)+500)/2500), 0, 255)) 2331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define DAC_FROM_REG(val) (((val)*2500)/255) 2341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* Chip sampling rates 2361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 2371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Some sensors are not updated more frequently than once per second 2381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * so it doesn't make sense to read them more often than that. 2391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * We cache the results and return the saved data if the driver 2401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * is called again before a second has elapsed. 2411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 2421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Also, there is significant configuration data for this chip 2431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * So, we keep the config data up to date in the cache 2441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * when it is written and only sample it once every 5 *minutes* 2451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 246cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvare#define ADM1026_DATA_INTERVAL (1 * HZ) 247cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvare#define ADM1026_CONFIG_INTERVAL (5 * 60 * HZ) 2481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* We allow for multiple chips in a single system. 2501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 2511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * For each registered ADM1026, we need to keep state information 2521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * at client->data. The adm1026_data structure is dynamically 2531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * allocated, when a new client structure is allocated. */ 2541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstruct pwm_data { 2561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds u8 pwm; 2571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds u8 enable; 2581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds u8 auto_pwm_min; 2591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}; 2601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstruct adm1026_data { 2621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct i2c_client client; 2631beeffe43311f64df8dd0ab08ff6b1858c58363fTony Jones struct device *hwmon_dev; 2641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2659a61bf6300533d3b64d7ff29adfec00e596de67dIngo Molnar struct mutex update_lock; 2661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int valid; /* !=0 if following fields are valid */ 2671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned long last_reading; /* In jiffies */ 2681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned long last_config; /* In jiffies */ 2691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 270cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvare u8 in[17]; /* Register value */ 271cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvare u8 in_max[17]; /* Register value */ 272cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvare u8 in_min[17]; /* Register value */ 273cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvare s8 temp[3]; /* Register value */ 274cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvare s8 temp_min[3]; /* Register value */ 275cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvare s8 temp_max[3]; /* Register value */ 276cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvare s8 temp_tmin[3]; /* Register value */ 277cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvare s8 temp_crit[3]; /* Register value */ 278cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvare s8 temp_offset[3]; /* Register value */ 279cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvare u8 fan[8]; /* Register value */ 280cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvare u8 fan_min[8]; /* Register value */ 281cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvare u8 fan_div[8]; /* Decoded value */ 282cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvare struct pwm_data pwm1; /* Pwm control values */ 283cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvare int vid; /* Decoded value */ 284cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvare u8 vrm; /* VRM version */ 2851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds u8 analog_out; /* Register value (DAC) */ 286cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvare long alarms; /* Register encoding, combined */ 287cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvare long alarm_mask; /* Register encoding, combined */ 288cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvare long gpio; /* Register encoding, combined */ 289cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvare long gpio_mask; /* Register encoding, combined */ 290cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvare u8 gpio_config[17]; /* Decoded value */ 291cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvare u8 config1; /* Register value */ 292cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvare u8 config2; /* Register value */ 293cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvare u8 config3; /* Register value */ 2941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}; 2951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int adm1026_attach_adapter(struct i2c_adapter *adapter); 2971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int adm1026_detect(struct i2c_adapter *adapter, int address, 2981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int kind); 2991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int adm1026_detach_client(struct i2c_client *client); 300f6c27fc17c5e575c5471fb344bdbd5f5f6072136Darren Jenkinsstatic int adm1026_read_value(struct i2c_client *client, u8 reg); 301f6c27fc17c5e575c5471fb344bdbd5f5f6072136Darren Jenkinsstatic int adm1026_write_value(struct i2c_client *client, u8 reg, int value); 3021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void adm1026_print_gpio(struct i2c_client *client); 303cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvarestatic void adm1026_fixup_gpio(struct i2c_client *client); 3041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic struct adm1026_data *adm1026_update_device(struct device *dev); 3051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void adm1026_init_client(struct i2c_client *client); 3061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic struct i2c_driver adm1026_driver = { 309cdaf79349c7d24e1d33acb6497849c9e956a33eaLaurent Riffard .driver = { 310cdaf79349c7d24e1d33acb6497849c9e956a33eaLaurent Riffard .name = "adm1026", 311cdaf79349c7d24e1d33acb6497849c9e956a33eaLaurent Riffard }, 3121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .attach_adapter = adm1026_attach_adapter, 313cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvare .detach_client = adm1026_detach_client, 3141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}; 3151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 316c49efceffa599299ab3f38b1cdf8c2f1bf9811c4Ben Dooksstatic int adm1026_attach_adapter(struct i2c_adapter *adapter) 3171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 3181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!(adapter->class & I2C_CLASS_HWMON)) { 3191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; 3201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 3212ed2dc3c116d26fc6a9384e83d136b15cc203b6cJean Delvare return i2c_probe(adapter, &addr_data, adm1026_detect); 3221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 3231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 324c49efceffa599299ab3f38b1cdf8c2f1bf9811c4Ben Dooksstatic int adm1026_read_value(struct i2c_client *client, u8 reg) 3251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 3261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int res; 3271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (reg < 0x80) { 3291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* "RAM" locations */ 3301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds res = i2c_smbus_read_byte_data(client, reg) & 0xff; 3311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } else { 3321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* EEPROM, do nothing */ 3331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds res = 0; 3341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 3351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return res; 3361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 3371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 338c49efceffa599299ab3f38b1cdf8c2f1bf9811c4Ben Dooksstatic int adm1026_write_value(struct i2c_client *client, u8 reg, int value) 3391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 3401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int res; 3411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (reg < 0x80) { 3431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* "RAM" locations */ 3441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds res = i2c_smbus_write_byte_data(client, reg, value); 3451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } else { 3461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* EEPROM, do nothing */ 3471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds res = 0; 3481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 3491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return res; 3501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 3511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 352c49efceffa599299ab3f38b1cdf8c2f1bf9811c4Ben Dooksstatic void adm1026_init_client(struct i2c_client *client) 3531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 3541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int value, i; 3551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct adm1026_data *data = i2c_get_clientdata(client); 3561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 357cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvare dev_dbg(&client->dev, "Initializing device\n"); 3581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Read chip config */ 3591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds data->config1 = adm1026_read_value(client, ADM1026_REG_CONFIG1); 3601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds data->config2 = adm1026_read_value(client, ADM1026_REG_CONFIG2); 3611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds data->config3 = adm1026_read_value(client, ADM1026_REG_CONFIG3); 3621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Inform user of chip config */ 3641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dev_dbg(&client->dev, "ADM1026_REG_CONFIG1 is: 0x%02x\n", 3651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds data->config1); 3661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if ((data->config1 & CFG1_MONITOR) == 0) { 3671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dev_dbg(&client->dev, "Monitoring not currently " 3681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "enabled.\n"); 3691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 3701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (data->config1 & CFG1_INT_ENABLE) { 3711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dev_dbg(&client->dev, "SMBALERT interrupts are " 3721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "enabled.\n"); 3731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 3741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (data->config1 & CFG1_AIN8_9) { 3751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dev_dbg(&client->dev, "in8 and in9 enabled. " 3761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "temp3 disabled.\n"); 3771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } else { 3781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dev_dbg(&client->dev, "temp3 enabled. in8 and " 3791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "in9 disabled.\n"); 3801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 3811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (data->config1 & CFG1_THERM_HOT) { 3821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dev_dbg(&client->dev, "Automatic THERM, PWM, " 3831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "and temp limits enabled.\n"); 3841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 3851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (data->config3 & CFG3_GPIO16_ENABLE) { 387368609c5a8bd75b77721e69726ddfd3c6a30f7d4Jean Delvare dev_dbg(&client->dev, "GPIO16 enabled. THERM " 3881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "pin disabled.\n"); 3891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } else { 3901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dev_dbg(&client->dev, "THERM pin enabled. " 3911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "GPIO16 disabled.\n"); 3921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 3931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (data->config3 & CFG3_VREF_250) { 3941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dev_dbg(&client->dev, "Vref is 2.50 Volts.\n"); 3951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } else { 3961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dev_dbg(&client->dev, "Vref is 1.82 Volts.\n"); 3971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 3981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Read and pick apart the existing GPIO configuration */ 3991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds value = 0; 4001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds for (i = 0;i <= 15;++i) { 4011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if ((i & 0x03) == 0) { 4021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds value = adm1026_read_value(client, 4031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ADM1026_REG_GPIO_CFG_0_3 + i/4); 4041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 4051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds data->gpio_config[i] = value & 0x03; 4061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds value >>= 2; 4071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 4081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds data->gpio_config[16] = (data->config3 >> 6) & 0x03; 4091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* ... and then print it */ 4111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds adm1026_print_gpio(client); 4121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* If the user asks us to reprogram the GPIO config, then 4141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * do it now. 4151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 4161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (gpio_input[0] != -1 || gpio_output[0] != -1 4171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds || gpio_inverted[0] != -1 || gpio_normal[0] != -1 4181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds || gpio_fan[0] != -1) { 4191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds adm1026_fixup_gpio(client); 4201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 4211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* WE INTENTIONALLY make no changes to the limits, 4231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * offsets, pwms, fans and zones. If they were 4241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * configured, we don't want to mess with them. 4251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * If they weren't, the default is 100% PWM, no 4261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * control and will suffice until 'sensors -s' 427cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvare * can be run by the user. We DO set the default 4281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * value for pwm1.auto_pwm_min to its maximum 4291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * so that enabling automatic pwm fan control 430cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvare * without first setting a value for pwm1.auto_pwm_min 4311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * will not result in potentially dangerous fan speed decrease. 4321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 4331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds data->pwm1.auto_pwm_min=255; 4341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Start monitoring */ 4351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds value = adm1026_read_value(client, ADM1026_REG_CONFIG1); 4361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Set MONITOR, clear interrupt acknowledge and s/w reset */ 4371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds value = (value | CFG1_MONITOR) & (~CFG1_INT_CLEAR & ~CFG1_RESET); 4381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dev_dbg(&client->dev, "Setting CONFIG to: 0x%02x\n", value); 4391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds data->config1 = value; 4401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds adm1026_write_value(client, ADM1026_REG_CONFIG1, value); 4411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* initialize fan_div[] to hardware defaults */ 4431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds value = adm1026_read_value(client, ADM1026_REG_FAN_DIV_0_3) | 4441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds (adm1026_read_value(client, ADM1026_REG_FAN_DIV_4_7) << 8); 4451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds for (i = 0;i <= 7;++i) { 4461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds data->fan_div[i] = DIV_FROM_REG(value & 0x03); 4471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds value >>= 2; 4481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 4491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 4501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 451c49efceffa599299ab3f38b1cdf8c2f1bf9811c4Ben Dooksstatic void adm1026_print_gpio(struct i2c_client *client) 4521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 4531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct adm1026_data *data = i2c_get_clientdata(client); 454cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvare int i; 4551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dev_dbg(&client->dev, "GPIO config is:"); 4571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds for (i = 0;i <= 7;++i) { 4581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (data->config2 & (1 << i)) { 4591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dev_dbg(&client->dev, "\t%sGP%s%d\n", 4601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds data->gpio_config[i] & 0x02 ? "" : "!", 4611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds data->gpio_config[i] & 0x01 ? "OUT" : "IN", 4621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds i); 4631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } else { 4641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dev_dbg(&client->dev, "\tFAN%d\n", i); 4651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 4661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 4671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds for (i = 8;i <= 15;++i) { 4681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dev_dbg(&client->dev, "\t%sGP%s%d\n", 4691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds data->gpio_config[i] & 0x02 ? "" : "!", 4701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds data->gpio_config[i] & 0x01 ? "OUT" : "IN", 4711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds i); 4721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 4731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (data->config3 & CFG3_GPIO16_ENABLE) { 4741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dev_dbg(&client->dev, "\t%sGP%s16\n", 4751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds data->gpio_config[16] & 0x02 ? "" : "!", 4761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds data->gpio_config[16] & 0x01 ? "OUT" : "IN"); 4771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } else { 478cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvare /* GPIO16 is THERM */ 4791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dev_dbg(&client->dev, "\tTHERM\n"); 4801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 4811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 4821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 483c49efceffa599299ab3f38b1cdf8c2f1bf9811c4Ben Dooksstatic void adm1026_fixup_gpio(struct i2c_client *client) 4841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 4851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct adm1026_data *data = i2c_get_clientdata(client); 486cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvare int i; 487cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvare int value; 4881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Make the changes requested. */ 4901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* We may need to unlock/stop monitoring or soft-reset the 4911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * chip before we can make changes. This hasn't been 4921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * tested much. FIXME 4931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 4941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Make outputs */ 4961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds for (i = 0;i <= 16;++i) { 4971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (gpio_output[i] >= 0 && gpio_output[i] <= 16) { 4981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds data->gpio_config[gpio_output[i]] |= 0x01; 4991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 5001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* if GPIO0-7 is output, it isn't a FAN tach */ 5011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (gpio_output[i] >= 0 && gpio_output[i] <= 7) { 5021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds data->config2 |= 1 << gpio_output[i]; 5031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 5041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 5051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Input overrides output */ 5071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds for (i = 0;i <= 16;++i) { 5081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (gpio_input[i] >= 0 && gpio_input[i] <= 16) { 5091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds data->gpio_config[gpio_input[i]] &= ~ 0x01; 5101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 5111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* if GPIO0-7 is input, it isn't a FAN tach */ 5121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (gpio_input[i] >= 0 && gpio_input[i] <= 7) { 5131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds data->config2 |= 1 << gpio_input[i]; 5141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 5151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 5161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 517cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvare /* Inverted */ 5181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds for (i = 0;i <= 16;++i) { 5191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (gpio_inverted[i] >= 0 && gpio_inverted[i] <= 16) { 5201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds data->gpio_config[gpio_inverted[i]] &= ~ 0x02; 5211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 5221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 5231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 524cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvare /* Normal overrides inverted */ 5251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds for (i = 0;i <= 16;++i) { 5261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (gpio_normal[i] >= 0 && gpio_normal[i] <= 16) { 5271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds data->gpio_config[gpio_normal[i]] |= 0x02; 5281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 5291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 5301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Fan overrides input and output */ 5321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds for (i = 0;i <= 7;++i) { 5331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (gpio_fan[i] >= 0 && gpio_fan[i] <= 7) { 5341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds data->config2 &= ~(1 << gpio_fan[i]); 5351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 5361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 5371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Write new configs to registers */ 5391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds adm1026_write_value(client, ADM1026_REG_CONFIG2, data->config2); 5401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds data->config3 = (data->config3 & 0x3f) 5411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds | ((data->gpio_config[16] & 0x03) << 6); 5421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds adm1026_write_value(client, ADM1026_REG_CONFIG3, data->config3); 5431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds for (i = 15, value = 0;i >= 0;--i) { 5441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds value <<= 2; 5451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds value |= data->gpio_config[i] & 0x03; 5461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if ((i & 0x03) == 0) { 5471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds adm1026_write_value(client, 5481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ADM1026_REG_GPIO_CFG_0_3 + i/4, 5491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds value); 5501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds value = 0; 5511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 5521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 5531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Print the new config */ 5551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds adm1026_print_gpio(client); 5561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 5571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic struct adm1026_data *adm1026_update_device(struct device *dev) 5601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 5611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct i2c_client *client = to_i2c_client(dev); 5621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct adm1026_data *data = i2c_get_clientdata(client); 5631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int i; 5641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds long value, alarms, gpio; 5651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5669a61bf6300533d3b64d7ff29adfec00e596de67dIngo Molnar mutex_lock(&data->update_lock); 5671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!data->valid 5681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds || time_after(jiffies, data->last_reading + ADM1026_DATA_INTERVAL)) { 5691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Things that change quickly */ 570cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvare dev_dbg(&client->dev, "Reading sensor values\n"); 5711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds for (i = 0;i <= 16;++i) { 5721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds data->in[i] = 5731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds adm1026_read_value(client, ADM1026_REG_IN[i]); 5741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 5751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds for (i = 0;i <= 7;++i) { 5771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds data->fan[i] = 5781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds adm1026_read_value(client, ADM1026_REG_FAN(i)); 5791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 5801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds for (i = 0;i <= 2;++i) { 5821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* NOTE: temp[] is s8 and we assume 2's complement 583cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvare * "conversion" in the assignment */ 5841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds data->temp[i] = 5851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds adm1026_read_value(client, ADM1026_REG_TEMP[i]); 5861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 5871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 588cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvare data->pwm1.pwm = adm1026_read_value(client, 5891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ADM1026_REG_PWM); 590cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvare data->analog_out = adm1026_read_value(client, 5911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ADM1026_REG_DAC); 5921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* GPIO16 is MSbit of alarms, move it to gpio */ 5931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds alarms = adm1026_read_value(client, ADM1026_REG_STATUS4); 594cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvare gpio = alarms & 0x80 ? 0x0100 : 0; /* GPIO16 */ 5951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds alarms &= 0x7f; 5961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds alarms <<= 8; 5971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds alarms |= adm1026_read_value(client, ADM1026_REG_STATUS3); 5981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds alarms <<= 8; 5991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds alarms |= adm1026_read_value(client, ADM1026_REG_STATUS2); 6001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds alarms <<= 8; 6011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds alarms |= adm1026_read_value(client, ADM1026_REG_STATUS1); 6021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds data->alarms = alarms; 6031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Read the GPIO values */ 605cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvare gpio |= adm1026_read_value(client, 6061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ADM1026_REG_GPIO_STATUS_8_15); 6071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds gpio <<= 8; 608cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvare gpio |= adm1026_read_value(client, 6091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ADM1026_REG_GPIO_STATUS_0_7); 6101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds data->gpio = gpio; 6111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds data->last_reading = jiffies; 613cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvare }; /* last_reading */ 6141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!data->valid || 6161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds time_after(jiffies, data->last_config + ADM1026_CONFIG_INTERVAL)) { 6171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Things that don't change often */ 6181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dev_dbg(&client->dev, "Reading config values\n"); 6191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds for (i = 0;i <= 16;++i) { 620cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvare data->in_min[i] = adm1026_read_value(client, 6211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ADM1026_REG_IN_MIN[i]); 622cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvare data->in_max[i] = adm1026_read_value(client, 6231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ADM1026_REG_IN_MAX[i]); 6241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 6251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds value = adm1026_read_value(client, ADM1026_REG_FAN_DIV_0_3) 6271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds | (adm1026_read_value(client, ADM1026_REG_FAN_DIV_4_7) 6281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds << 8); 6291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds for (i = 0;i <= 7;++i) { 630cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvare data->fan_min[i] = adm1026_read_value(client, 6311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ADM1026_REG_FAN_MIN(i)); 6321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds data->fan_div[i] = DIV_FROM_REG(value & 0x03); 6331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds value >>= 2; 6341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 6351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds for (i = 0; i <= 2; ++i) { 637cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvare /* NOTE: temp_xxx[] are s8 and we assume 2's 6381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * complement "conversion" in the assignment 6391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 640cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvare data->temp_min[i] = adm1026_read_value(client, 6411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ADM1026_REG_TEMP_MIN[i]); 642cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvare data->temp_max[i] = adm1026_read_value(client, 6431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ADM1026_REG_TEMP_MAX[i]); 644cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvare data->temp_tmin[i] = adm1026_read_value(client, 6451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ADM1026_REG_TEMP_TMIN[i]); 646cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvare data->temp_crit[i] = adm1026_read_value(client, 6471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ADM1026_REG_TEMP_THERM[i]); 648cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvare data->temp_offset[i] = adm1026_read_value(client, 6491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ADM1026_REG_TEMP_OFFSET[i]); 6501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 6511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Read the STATUS/alarm masks */ 653cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvare alarms = adm1026_read_value(client, ADM1026_REG_MASK4); 654cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvare gpio = alarms & 0x80 ? 0x0100 : 0; /* GPIO16 */ 655cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvare alarms = (alarms & 0x7f) << 8; 6561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds alarms |= adm1026_read_value(client, ADM1026_REG_MASK3); 6571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds alarms <<= 8; 6581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds alarms |= adm1026_read_value(client, ADM1026_REG_MASK2); 6591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds alarms <<= 8; 6601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds alarms |= adm1026_read_value(client, ADM1026_REG_MASK1); 6611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds data->alarm_mask = alarms; 6621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Read the GPIO values */ 664cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvare gpio |= adm1026_read_value(client, 6651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ADM1026_REG_GPIO_MASK_8_15); 6661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds gpio <<= 8; 6671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds gpio |= adm1026_read_value(client, ADM1026_REG_GPIO_MASK_0_7); 6681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds data->gpio_mask = gpio; 6691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Read various values from CONFIG1 */ 671cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvare data->config1 = adm1026_read_value(client, 6721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ADM1026_REG_CONFIG1); 6731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (data->config1 & CFG1_PWM_AFC) { 6741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds data->pwm1.enable = 2; 675cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvare data->pwm1.auto_pwm_min = 6761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds PWM_MIN_FROM_REG(data->pwm1.pwm); 6771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 6781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Read the GPIO config */ 679cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvare data->config2 = adm1026_read_value(client, 6801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ADM1026_REG_CONFIG2); 681cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvare data->config3 = adm1026_read_value(client, 6821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ADM1026_REG_CONFIG3); 6831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds data->gpio_config[16] = (data->config3 >> 6) & 0x03; 6841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds value = 0; 6861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds for (i = 0;i <= 15;++i) { 6871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if ((i & 0x03) == 0) { 6881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds value = adm1026_read_value(client, 6891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ADM1026_REG_GPIO_CFG_0_3 + i/4); 6901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 6911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds data->gpio_config[i] = value & 0x03; 6921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds value >>= 2; 6931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 6941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds data->last_config = jiffies; 696cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvare }; /* last_config */ 6971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dev_dbg(&client->dev, "Setting VID from GPIO11-15.\n"); 6991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds data->vid = (data->gpio >> 11) & 0x1f; 7001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds data->valid = 1; 7019a61bf6300533d3b64d7ff29adfec00e596de67dIngo Molnar mutex_unlock(&data->update_lock); 7021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return data; 7031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 7041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 705050480f12aeab62d39a1a07546606a47217ebefaYani Ioannoustatic ssize_t show_in(struct device *dev, struct device_attribute *attr, 706050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou char *buf) 7071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 708050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr); 709050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou int nr = sensor_attr->index; 7101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct adm1026_data *data = adm1026_update_device(dev); 711cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvare return sprintf(buf, "%d\n", INS_FROM_REG(nr, data->in[nr])); 7121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 713050480f12aeab62d39a1a07546606a47217ebefaYani Ioannoustatic ssize_t show_in_min(struct device *dev, struct device_attribute *attr, 714050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou char *buf) 7151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 716050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr); 717050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou int nr = sensor_attr->index; 718cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvare struct adm1026_data *data = adm1026_update_device(dev); 719cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvare return sprintf(buf, "%d\n", INS_FROM_REG(nr, data->in_min[nr])); 7201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 721050480f12aeab62d39a1a07546606a47217ebefaYani Ioannoustatic ssize_t set_in_min(struct device *dev, struct device_attribute *attr, 722050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou const char *buf, size_t count) 7231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 724050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr); 725050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou int nr = sensor_attr->index; 7261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct i2c_client *client = to_i2c_client(dev); 7271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct adm1026_data *data = i2c_get_clientdata(client); 7281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int val = simple_strtol(buf, NULL, 10); 7291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 7309a61bf6300533d3b64d7ff29adfec00e596de67dIngo Molnar mutex_lock(&data->update_lock); 7311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds data->in_min[nr] = INS_TO_REG(nr, val); 7321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds adm1026_write_value(client, ADM1026_REG_IN_MIN[nr], data->in_min[nr]); 7339a61bf6300533d3b64d7ff29adfec00e596de67dIngo Molnar mutex_unlock(&data->update_lock); 734cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvare return count; 7351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 736050480f12aeab62d39a1a07546606a47217ebefaYani Ioannoustatic ssize_t show_in_max(struct device *dev, struct device_attribute *attr, 737050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou char *buf) 7381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 739050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr); 740050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou int nr = sensor_attr->index; 7411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct adm1026_data *data = adm1026_update_device(dev); 742cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvare return sprintf(buf, "%d\n", INS_FROM_REG(nr, data->in_max[nr])); 7431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 744050480f12aeab62d39a1a07546606a47217ebefaYani Ioannoustatic ssize_t set_in_max(struct device *dev, struct device_attribute *attr, 745050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou const char *buf, size_t count) 7461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 747050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr); 748050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou int nr = sensor_attr->index; 7491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct i2c_client *client = to_i2c_client(dev); 7501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct adm1026_data *data = i2c_get_clientdata(client); 7511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int val = simple_strtol(buf, NULL, 10); 7521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 7539a61bf6300533d3b64d7ff29adfec00e596de67dIngo Molnar mutex_lock(&data->update_lock); 7541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds data->in_max[nr] = INS_TO_REG(nr, val); 7551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds adm1026_write_value(client, ADM1026_REG_IN_MAX[nr], data->in_max[nr]); 7569a61bf6300533d3b64d7ff29adfec00e596de67dIngo Molnar mutex_unlock(&data->update_lock); 7571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return count; 7581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 7591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 760050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou#define in_reg(offset) \ 761050480f12aeab62d39a1a07546606a47217ebefaYani Ioannoustatic SENSOR_DEVICE_ATTR(in##offset##_input, S_IRUGO, show_in, \ 762050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou NULL, offset); \ 763050480f12aeab62d39a1a07546606a47217ebefaYani Ioannoustatic SENSOR_DEVICE_ATTR(in##offset##_min, S_IRUGO | S_IWUSR, \ 764050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou show_in_min, set_in_min, offset); \ 765050480f12aeab62d39a1a07546606a47217ebefaYani Ioannoustatic SENSOR_DEVICE_ATTR(in##offset##_max, S_IRUGO | S_IWUSR, \ 766050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou show_in_max, set_in_max, offset); 7671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 7681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 7691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsin_reg(0); 7701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsin_reg(1); 7711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsin_reg(2); 7721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsin_reg(3); 7731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsin_reg(4); 7741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsin_reg(5); 7751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsin_reg(6); 7761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsin_reg(7); 7771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsin_reg(8); 7781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsin_reg(9); 7791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsin_reg(10); 7801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsin_reg(11); 7811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsin_reg(12); 7821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsin_reg(13); 7831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsin_reg(14); 7841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsin_reg(15); 7851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 78674880c063b06efd103c924abfe19d9d8fa4864c4Yani Ioannoustatic ssize_t show_in16(struct device *dev, struct device_attribute *attr, char *buf) 7871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 7881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct adm1026_data *data = adm1026_update_device(dev); 789cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvare return sprintf(buf, "%d\n", INS_FROM_REG(16, data->in[16]) - 7901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds NEG12_OFFSET); 7911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 79274880c063b06efd103c924abfe19d9d8fa4864c4Yani Ioannoustatic ssize_t show_in16_min(struct device *dev, struct device_attribute *attr, char *buf) 7931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 794cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvare struct adm1026_data *data = adm1026_update_device(dev); 795cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvare return sprintf(buf, "%d\n", INS_FROM_REG(16, data->in_min[16]) 7961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds - NEG12_OFFSET); 7971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 79874880c063b06efd103c924abfe19d9d8fa4864c4Yani Ioannoustatic ssize_t set_in16_min(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) 7991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 8001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct i2c_client *client = to_i2c_client(dev); 8011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct adm1026_data *data = i2c_get_clientdata(client); 8021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int val = simple_strtol(buf, NULL, 10); 8031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 8049a61bf6300533d3b64d7ff29adfec00e596de67dIngo Molnar mutex_lock(&data->update_lock); 8051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds data->in_min[16] = INS_TO_REG(16, val + NEG12_OFFSET); 8061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds adm1026_write_value(client, ADM1026_REG_IN_MIN[16], data->in_min[16]); 8079a61bf6300533d3b64d7ff29adfec00e596de67dIngo Molnar mutex_unlock(&data->update_lock); 808cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvare return count; 8091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 81074880c063b06efd103c924abfe19d9d8fa4864c4Yani Ioannoustatic ssize_t show_in16_max(struct device *dev, struct device_attribute *attr, char *buf) 8111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 8121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct adm1026_data *data = adm1026_update_device(dev); 813cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvare return sprintf(buf, "%d\n", INS_FROM_REG(16, data->in_max[16]) 8141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds - NEG12_OFFSET); 8151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 81674880c063b06efd103c924abfe19d9d8fa4864c4Yani Ioannoustatic ssize_t set_in16_max(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) 8171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 8181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct i2c_client *client = to_i2c_client(dev); 8191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct adm1026_data *data = i2c_get_clientdata(client); 8201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int val = simple_strtol(buf, NULL, 10); 8211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 8229a61bf6300533d3b64d7ff29adfec00e596de67dIngo Molnar mutex_lock(&data->update_lock); 8231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds data->in_max[16] = INS_TO_REG(16, val+NEG12_OFFSET); 8241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds adm1026_write_value(client, ADM1026_REG_IN_MAX[16], data->in_max[16]); 8259a61bf6300533d3b64d7ff29adfec00e596de67dIngo Molnar mutex_unlock(&data->update_lock); 8261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return count; 8271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 8281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 829050480f12aeab62d39a1a07546606a47217ebefaYani Ioannoustatic SENSOR_DEVICE_ATTR(in16_input, S_IRUGO, show_in16, NULL, 16); 830050480f12aeab62d39a1a07546606a47217ebefaYani Ioannoustatic SENSOR_DEVICE_ATTR(in16_min, S_IRUGO | S_IWUSR, show_in16_min, set_in16_min, 16); 831050480f12aeab62d39a1a07546606a47217ebefaYani Ioannoustatic SENSOR_DEVICE_ATTR(in16_max, S_IRUGO | S_IWUSR, show_in16_max, set_in16_max, 16); 8321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 8331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 8341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 8351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 8361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* Now add fan read/write functions */ 8371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 838050480f12aeab62d39a1a07546606a47217ebefaYani Ioannoustatic ssize_t show_fan(struct device *dev, struct device_attribute *attr, 839050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou char *buf) 8401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 841050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr); 842050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou int nr = sensor_attr->index; 8431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct adm1026_data *data = adm1026_update_device(dev); 844cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvare return sprintf(buf, "%d\n", FAN_FROM_REG(data->fan[nr], 8451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds data->fan_div[nr])); 8461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 847050480f12aeab62d39a1a07546606a47217ebefaYani Ioannoustatic ssize_t show_fan_min(struct device *dev, struct device_attribute *attr, 848050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou char *buf) 8491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 850050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr); 851050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou int nr = sensor_attr->index; 8521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct adm1026_data *data = adm1026_update_device(dev); 853cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvare return sprintf(buf, "%d\n", FAN_FROM_REG(data->fan_min[nr], 8541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds data->fan_div[nr])); 8551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 856050480f12aeab62d39a1a07546606a47217ebefaYani Ioannoustatic ssize_t set_fan_min(struct device *dev, struct device_attribute *attr, 857050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou const char *buf, size_t count) 8581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 859050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr); 860050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou int nr = sensor_attr->index; 8611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct i2c_client *client = to_i2c_client(dev); 8621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct adm1026_data *data = i2c_get_clientdata(client); 8631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int val = simple_strtol(buf, NULL, 10); 8641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 8659a61bf6300533d3b64d7ff29adfec00e596de67dIngo Molnar mutex_lock(&data->update_lock); 8661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds data->fan_min[nr] = FAN_TO_REG(val, data->fan_div[nr]); 8671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds adm1026_write_value(client, ADM1026_REG_FAN_MIN(nr), 8681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds data->fan_min[nr]); 8699a61bf6300533d3b64d7ff29adfec00e596de67dIngo Molnar mutex_unlock(&data->update_lock); 8701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return count; 8711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 8721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 873cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvare#define fan_offset(offset) \ 874cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvarestatic SENSOR_DEVICE_ATTR(fan##offset##_input, S_IRUGO, show_fan, NULL, \ 875cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvare offset - 1); \ 876cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvarestatic SENSOR_DEVICE_ATTR(fan##offset##_min, S_IRUGO | S_IWUSR, \ 877050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou show_fan_min, set_fan_min, offset - 1); 8781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 8791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsfan_offset(1); 8801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsfan_offset(2); 8811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsfan_offset(3); 8821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsfan_offset(4); 8831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsfan_offset(5); 8841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsfan_offset(6); 8851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsfan_offset(7); 8861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsfan_offset(8); 8871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 8881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* Adjust fan_min to account for new fan divisor */ 8891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void fixup_fan_min(struct device *dev, int fan, int old_div) 8901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 8911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct i2c_client *client = to_i2c_client(dev); 8921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct adm1026_data *data = i2c_get_clientdata(client); 893cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvare int new_min; 894cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvare int new_div = data->fan_div[fan]; 8951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 8961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 0 and 0xff are special. Don't adjust them */ 8971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (data->fan_min[fan] == 0 || data->fan_min[fan] == 0xff) { 8981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return; 8991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 9001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 9011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds new_min = data->fan_min[fan] * old_div / new_div; 9021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds new_min = SENSORS_LIMIT(new_min, 1, 254); 9031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds data->fan_min[fan] = new_min; 9041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds adm1026_write_value(client, ADM1026_REG_FAN_MIN(fan), new_min); 9051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 9061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 9071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* Now add fan_div read/write functions */ 908050480f12aeab62d39a1a07546606a47217ebefaYani Ioannoustatic ssize_t show_fan_div(struct device *dev, struct device_attribute *attr, 909050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou char *buf) 9101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 911050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr); 912050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou int nr = sensor_attr->index; 9131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct adm1026_data *data = adm1026_update_device(dev); 914cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvare return sprintf(buf, "%d\n", data->fan_div[nr]); 9151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 916050480f12aeab62d39a1a07546606a47217ebefaYani Ioannoustatic ssize_t set_fan_div(struct device *dev, struct device_attribute *attr, 917050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou const char *buf, size_t count) 9181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 919050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr); 920050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou int nr = sensor_attr->index; 9211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct i2c_client *client = to_i2c_client(dev); 9221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct adm1026_data *data = i2c_get_clientdata(client); 923cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvare int val, orig_div, new_div, shift; 9241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 9251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds val = simple_strtol(buf, NULL, 10); 926cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvare new_div = DIV_TO_REG(val); 9271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (new_div == 0) { 9281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -EINVAL; 9291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 9309a61bf6300533d3b64d7ff29adfec00e596de67dIngo Molnar mutex_lock(&data->update_lock); 9311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds orig_div = data->fan_div[nr]; 9321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds data->fan_div[nr] = DIV_FROM_REG(new_div); 9331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 9341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (nr < 4) { /* 0 <= nr < 4 */ 9351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds shift = 2 * nr; 9361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds adm1026_write_value(client, ADM1026_REG_FAN_DIV_0_3, 9371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ((DIV_TO_REG(orig_div) & (~(0x03 << shift))) | 9381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds (new_div << shift))); 9391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } else { /* 3 < nr < 8 */ 9401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds shift = 2 * (nr - 4); 9411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds adm1026_write_value(client, ADM1026_REG_FAN_DIV_4_7, 9421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ((DIV_TO_REG(orig_div) & (~(0x03 << (2 * shift)))) | 9431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds (new_div << shift))); 9441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 9451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 9461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (data->fan_div[nr] != orig_div) { 947cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvare fixup_fan_min(dev, nr, orig_div); 9481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 9499a61bf6300533d3b64d7ff29adfec00e596de67dIngo Molnar mutex_unlock(&data->update_lock); 9501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return count; 9511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 9521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 953cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvare#define fan_offset_div(offset) \ 954cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvarestatic SENSOR_DEVICE_ATTR(fan##offset##_div, S_IRUGO | S_IWUSR, \ 955050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou show_fan_div, set_fan_div, offset - 1); 9561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 9571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsfan_offset_div(1); 9581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsfan_offset_div(2); 9591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsfan_offset_div(3); 9601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsfan_offset_div(4); 9611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsfan_offset_div(5); 9621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsfan_offset_div(6); 9631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsfan_offset_div(7); 9641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsfan_offset_div(8); 9651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 9661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* Temps */ 967050480f12aeab62d39a1a07546606a47217ebefaYani Ioannoustatic ssize_t show_temp(struct device *dev, struct device_attribute *attr, 968050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou char *buf) 9691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 970050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr); 971050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou int nr = sensor_attr->index; 9721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct adm1026_data *data = adm1026_update_device(dev); 973cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvare return sprintf(buf, "%d\n", TEMP_FROM_REG(data->temp[nr])); 9741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 975050480f12aeab62d39a1a07546606a47217ebefaYani Ioannoustatic ssize_t show_temp_min(struct device *dev, struct device_attribute *attr, 976050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou char *buf) 9771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 978050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr); 979050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou int nr = sensor_attr->index; 9801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct adm1026_data *data = adm1026_update_device(dev); 981cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvare return sprintf(buf, "%d\n", TEMP_FROM_REG(data->temp_min[nr])); 9821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 983050480f12aeab62d39a1a07546606a47217ebefaYani Ioannoustatic ssize_t set_temp_min(struct device *dev, struct device_attribute *attr, 984050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou const char *buf, size_t count) 9851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 986050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr); 987050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou int nr = sensor_attr->index; 9881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct i2c_client *client = to_i2c_client(dev); 9891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct adm1026_data *data = i2c_get_clientdata(client); 9901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int val = simple_strtol(buf, NULL, 10); 9911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 9929a61bf6300533d3b64d7ff29adfec00e596de67dIngo Molnar mutex_lock(&data->update_lock); 9931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds data->temp_min[nr] = TEMP_TO_REG(val); 9941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds adm1026_write_value(client, ADM1026_REG_TEMP_MIN[nr], 9951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds data->temp_min[nr]); 9969a61bf6300533d3b64d7ff29adfec00e596de67dIngo Molnar mutex_unlock(&data->update_lock); 9971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return count; 9981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 999050480f12aeab62d39a1a07546606a47217ebefaYani Ioannoustatic ssize_t show_temp_max(struct device *dev, struct device_attribute *attr, 1000050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou char *buf) 10011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 1002050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr); 1003050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou int nr = sensor_attr->index; 10041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct adm1026_data *data = adm1026_update_device(dev); 1005cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvare return sprintf(buf, "%d\n", TEMP_FROM_REG(data->temp_max[nr])); 10061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 1007050480f12aeab62d39a1a07546606a47217ebefaYani Ioannoustatic ssize_t set_temp_max(struct device *dev, struct device_attribute *attr, 1008050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou const char *buf, size_t count) 10091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 1010050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr); 1011050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou int nr = sensor_attr->index; 10121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct i2c_client *client = to_i2c_client(dev); 10131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct adm1026_data *data = i2c_get_clientdata(client); 10141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int val = simple_strtol(buf, NULL, 10); 10151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 10169a61bf6300533d3b64d7ff29adfec00e596de67dIngo Molnar mutex_lock(&data->update_lock); 10171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds data->temp_max[nr] = TEMP_TO_REG(val); 10181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds adm1026_write_value(client, ADM1026_REG_TEMP_MAX[nr], 10191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds data->temp_max[nr]); 10209a61bf6300533d3b64d7ff29adfec00e596de67dIngo Molnar mutex_unlock(&data->update_lock); 10211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return count; 10221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 1023050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou 1024050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou#define temp_reg(offset) \ 1025cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvarestatic SENSOR_DEVICE_ATTR(temp##offset##_input, S_IRUGO, show_temp, \ 1026050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou NULL, offset - 1); \ 1027050480f12aeab62d39a1a07546606a47217ebefaYani Ioannoustatic SENSOR_DEVICE_ATTR(temp##offset##_min, S_IRUGO | S_IWUSR, \ 1028050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou show_temp_min, set_temp_min, offset - 1); \ 1029050480f12aeab62d39a1a07546606a47217ebefaYani Ioannoustatic SENSOR_DEVICE_ATTR(temp##offset##_max, S_IRUGO | S_IWUSR, \ 1030050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou show_temp_max, set_temp_max, offset - 1); 10311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 10321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 10331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldstemp_reg(1); 10341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldstemp_reg(2); 10351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldstemp_reg(3); 10361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1037050480f12aeab62d39a1a07546606a47217ebefaYani Ioannoustatic ssize_t show_temp_offset(struct device *dev, 1038050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou struct device_attribute *attr, char *buf) 10391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 1040050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr); 1041050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou int nr = sensor_attr->index; 10421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct adm1026_data *data = adm1026_update_device(dev); 1043cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvare return sprintf(buf, "%d\n", TEMP_FROM_REG(data->temp_offset[nr])); 10441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 1045050480f12aeab62d39a1a07546606a47217ebefaYani Ioannoustatic ssize_t set_temp_offset(struct device *dev, 1046050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou struct device_attribute *attr, const char *buf, 1047050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou size_t count) 10481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 1049050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr); 1050050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou int nr = sensor_attr->index; 10511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct i2c_client *client = to_i2c_client(dev); 10521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct adm1026_data *data = i2c_get_clientdata(client); 10531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int val = simple_strtol(buf, NULL, 10); 10541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 10559a61bf6300533d3b64d7ff29adfec00e596de67dIngo Molnar mutex_lock(&data->update_lock); 10561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds data->temp_offset[nr] = TEMP_TO_REG(val); 10571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds adm1026_write_value(client, ADM1026_REG_TEMP_OFFSET[nr], 10581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds data->temp_offset[nr]); 10599a61bf6300533d3b64d7ff29adfec00e596de67dIngo Molnar mutex_unlock(&data->update_lock); 10601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return count; 10611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 10621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1063050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou#define temp_offset_reg(offset) \ 1064050480f12aeab62d39a1a07546606a47217ebefaYani Ioannoustatic SENSOR_DEVICE_ATTR(temp##offset##_offset, S_IRUGO | S_IWUSR, \ 1065050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou show_temp_offset, set_temp_offset, offset - 1); 10661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 10671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldstemp_offset_reg(1); 10681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldstemp_offset_reg(2); 10691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldstemp_offset_reg(3); 10701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1071050480f12aeab62d39a1a07546606a47217ebefaYani Ioannoustatic ssize_t show_temp_auto_point1_temp_hyst(struct device *dev, 1072050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou struct device_attribute *attr, char *buf) 10731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 1074050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr); 1075050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou int nr = sensor_attr->index; 10761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct adm1026_data *data = adm1026_update_device(dev); 1077cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvare return sprintf(buf, "%d\n", TEMP_FROM_REG( 10781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ADM1026_FAN_ACTIVATION_TEMP_HYST + data->temp_tmin[nr])); 10791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 1080050480f12aeab62d39a1a07546606a47217ebefaYani Ioannoustatic ssize_t show_temp_auto_point2_temp(struct device *dev, 1081050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou struct device_attribute *attr, char *buf) 10821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 1083050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr); 1084050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou int nr = sensor_attr->index; 10851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct adm1026_data *data = adm1026_update_device(dev); 1086cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvare return sprintf(buf, "%d\n", TEMP_FROM_REG(data->temp_tmin[nr] + 10871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ADM1026_FAN_CONTROL_TEMP_RANGE)); 10881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 1089050480f12aeab62d39a1a07546606a47217ebefaYani Ioannoustatic ssize_t show_temp_auto_point1_temp(struct device *dev, 1090050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou struct device_attribute *attr, char *buf) 10911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 1092050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr); 1093050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou int nr = sensor_attr->index; 10941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct adm1026_data *data = adm1026_update_device(dev); 1095cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvare return sprintf(buf, "%d\n", TEMP_FROM_REG(data->temp_tmin[nr])); 10961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 1097050480f12aeab62d39a1a07546606a47217ebefaYani Ioannoustatic ssize_t set_temp_auto_point1_temp(struct device *dev, 1098050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou struct device_attribute *attr, const char *buf, size_t count) 10991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 1100050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr); 1101050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou int nr = sensor_attr->index; 11021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct i2c_client *client = to_i2c_client(dev); 11031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct adm1026_data *data = i2c_get_clientdata(client); 11041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int val = simple_strtol(buf, NULL, 10); 11051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 11069a61bf6300533d3b64d7ff29adfec00e596de67dIngo Molnar mutex_lock(&data->update_lock); 11071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds data->temp_tmin[nr] = TEMP_TO_REG(val); 11081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds adm1026_write_value(client, ADM1026_REG_TEMP_TMIN[nr], 11091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds data->temp_tmin[nr]); 11109a61bf6300533d3b64d7ff29adfec00e596de67dIngo Molnar mutex_unlock(&data->update_lock); 11111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return count; 11121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 11131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1114cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvare#define temp_auto_point(offset) \ 1115cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvarestatic SENSOR_DEVICE_ATTR(temp##offset##_auto_point1_temp, \ 1116cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvare S_IRUGO | S_IWUSR, show_temp_auto_point1_temp, \ 1117cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvare set_temp_auto_point1_temp, offset - 1); \ 1118cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvarestatic SENSOR_DEVICE_ATTR(temp##offset##_auto_point1_temp_hyst, S_IRUGO,\ 1119cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvare show_temp_auto_point1_temp_hyst, NULL, offset - 1); \ 1120cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvarestatic SENSOR_DEVICE_ATTR(temp##offset##_auto_point2_temp, S_IRUGO, \ 1121050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou show_temp_auto_point2_temp, NULL, offset - 1); 11221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 11231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldstemp_auto_point(1); 11241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldstemp_auto_point(2); 11251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldstemp_auto_point(3); 11261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1127050480f12aeab62d39a1a07546606a47217ebefaYani Ioannoustatic ssize_t show_temp_crit_enable(struct device *dev, 1128050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou struct device_attribute *attr, char *buf) 11291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 11301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct adm1026_data *data = adm1026_update_device(dev); 1131cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvare return sprintf(buf, "%d\n", (data->config1 & CFG1_THERM_HOT) >> 4); 11321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 1133050480f12aeab62d39a1a07546606a47217ebefaYani Ioannoustatic ssize_t set_temp_crit_enable(struct device *dev, 1134050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou struct device_attribute *attr, const char *buf, size_t count) 11351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 11361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct i2c_client *client = to_i2c_client(dev); 11371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct adm1026_data *data = i2c_get_clientdata(client); 11381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int val = simple_strtol(buf, NULL, 10); 11391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 11401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if ((val == 1) || (val==0)) { 11419a61bf6300533d3b64d7ff29adfec00e596de67dIngo Molnar mutex_lock(&data->update_lock); 11421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds data->config1 = (data->config1 & ~CFG1_THERM_HOT) | (val << 4); 1143cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvare adm1026_write_value(client, ADM1026_REG_CONFIG1, 11441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds data->config1); 11459a61bf6300533d3b64d7ff29adfec00e596de67dIngo Molnar mutex_unlock(&data->update_lock); 11461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 11471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return count; 11481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 11491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1150050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou#define temp_crit_enable(offset) \ 1151050480f12aeab62d39a1a07546606a47217ebefaYani Ioannoustatic DEVICE_ATTR(temp##offset##_crit_enable, S_IRUGO | S_IWUSR, \ 11521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds show_temp_crit_enable, set_temp_crit_enable); 11531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1154050480f12aeab62d39a1a07546606a47217ebefaYani Ioannoutemp_crit_enable(1); 1155050480f12aeab62d39a1a07546606a47217ebefaYani Ioannoutemp_crit_enable(2); 1156050480f12aeab62d39a1a07546606a47217ebefaYani Ioannoutemp_crit_enable(3); 11571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1158050480f12aeab62d39a1a07546606a47217ebefaYani Ioannoustatic ssize_t show_temp_crit(struct device *dev, 1159050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou struct device_attribute *attr, char *buf) 11601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 1161050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr); 1162050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou int nr = sensor_attr->index; 11631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct adm1026_data *data = adm1026_update_device(dev); 1164cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvare return sprintf(buf, "%d\n", TEMP_FROM_REG(data->temp_crit[nr])); 11651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 1166050480f12aeab62d39a1a07546606a47217ebefaYani Ioannoustatic ssize_t set_temp_crit(struct device *dev, struct device_attribute *attr, 1167050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou const char *buf, size_t count) 11681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 1169050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr); 1170050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou int nr = sensor_attr->index; 11711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct i2c_client *client = to_i2c_client(dev); 11721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct adm1026_data *data = i2c_get_clientdata(client); 11731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int val = simple_strtol(buf, NULL, 10); 11741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 11759a61bf6300533d3b64d7ff29adfec00e596de67dIngo Molnar mutex_lock(&data->update_lock); 11761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds data->temp_crit[nr] = TEMP_TO_REG(val); 11771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds adm1026_write_value(client, ADM1026_REG_TEMP_THERM[nr], 11781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds data->temp_crit[nr]); 11799a61bf6300533d3b64d7ff29adfec00e596de67dIngo Molnar mutex_unlock(&data->update_lock); 11801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return count; 11811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 11821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1183050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou#define temp_crit_reg(offset) \ 1184050480f12aeab62d39a1a07546606a47217ebefaYani Ioannoustatic SENSOR_DEVICE_ATTR(temp##offset##_crit, S_IRUGO | S_IWUSR, \ 1185050480f12aeab62d39a1a07546606a47217ebefaYani Ioannou show_temp_crit, set_temp_crit, offset - 1); 11861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 11871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldstemp_crit_reg(1); 11881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldstemp_crit_reg(2); 11891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldstemp_crit_reg(3); 11901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 119174880c063b06efd103c924abfe19d9d8fa4864c4Yani Ioannoustatic ssize_t show_analog_out_reg(struct device *dev, struct device_attribute *attr, char *buf) 11921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 11931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct adm1026_data *data = adm1026_update_device(dev); 1194cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvare return sprintf(buf, "%d\n", DAC_FROM_REG(data->analog_out)); 11951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 119674880c063b06efd103c924abfe19d9d8fa4864c4Yani Ioannoustatic ssize_t set_analog_out_reg(struct device *dev, struct device_attribute *attr, const char *buf, 11971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds size_t count) 11981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 11991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct i2c_client *client = to_i2c_client(dev); 12001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct adm1026_data *data = i2c_get_clientdata(client); 12011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int val = simple_strtol(buf, NULL, 10); 12021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 12039a61bf6300533d3b64d7ff29adfec00e596de67dIngo Molnar mutex_lock(&data->update_lock); 12041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds data->analog_out = DAC_TO_REG(val); 12051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds adm1026_write_value(client, ADM1026_REG_DAC, data->analog_out); 12069a61bf6300533d3b64d7ff29adfec00e596de67dIngo Molnar mutex_unlock(&data->update_lock); 12071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return count; 12081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 12091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1210cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvarestatic DEVICE_ATTR(analog_out, S_IRUGO | S_IWUSR, show_analog_out_reg, 12111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds set_analog_out_reg); 12121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 121374880c063b06efd103c924abfe19d9d8fa4864c4Yani Ioannoustatic ssize_t show_vid_reg(struct device *dev, struct device_attribute *attr, char *buf) 12141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 12151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct adm1026_data *data = adm1026_update_device(dev); 1216cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvare return sprintf(buf, "%d\n", vid_from_reg(data->vid & 0x3f, data->vrm)); 12171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 1218937df8df907ce63b0f7e19adf6e3cdef1687fac3Grant Coadystatic DEVICE_ATTR(cpu0_vid, S_IRUGO, show_vid_reg, NULL); 12191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 122074880c063b06efd103c924abfe19d9d8fa4864c4Yani Ioannoustatic ssize_t show_vrm_reg(struct device *dev, struct device_attribute *attr, char *buf) 12211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 122290d6619a916062cb75a176aacb318d108758b4a5Jean Delvare struct adm1026_data *data = dev_get_drvdata(dev); 1223cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvare return sprintf(buf, "%d\n", data->vrm); 12241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 122574880c063b06efd103c924abfe19d9d8fa4864c4Yani Ioannoustatic ssize_t store_vrm_reg(struct device *dev, struct device_attribute *attr, const char *buf, 12261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds size_t count) 12271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 1228f67fdabfb94b0bb96623a4b48d22be5329a06277Jean Delvare struct adm1026_data *data = dev_get_drvdata(dev); 12291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 12301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds data->vrm = simple_strtol(buf, NULL, 10); 12311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return count; 12321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 12331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 12341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic DEVICE_ATTR(vrm, S_IRUGO | S_IWUSR, show_vrm_reg, store_vrm_reg); 12351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 123674880c063b06efd103c924abfe19d9d8fa4864c4Yani Ioannoustatic ssize_t show_alarms_reg(struct device *dev, struct device_attribute *attr, char *buf) 12371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 12381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct adm1026_data *data = adm1026_update_device(dev); 1239f67fdabfb94b0bb96623a4b48d22be5329a06277Jean Delvare return sprintf(buf, "%ld\n", data->alarms); 12401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 12411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 12421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic DEVICE_ATTR(alarms, S_IRUGO, show_alarms_reg, NULL); 12431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1244a9273cb8eea503f6b8e28bd5f613962ecba278c5Jean Delvarestatic ssize_t show_alarm(struct device *dev, struct device_attribute *attr, 1245a9273cb8eea503f6b8e28bd5f613962ecba278c5Jean Delvare char *buf) 1246a9273cb8eea503f6b8e28bd5f613962ecba278c5Jean Delvare{ 1247a9273cb8eea503f6b8e28bd5f613962ecba278c5Jean Delvare struct adm1026_data *data = adm1026_update_device(dev); 1248a9273cb8eea503f6b8e28bd5f613962ecba278c5Jean Delvare int bitnr = to_sensor_dev_attr(attr)->index; 1249a9273cb8eea503f6b8e28bd5f613962ecba278c5Jean Delvare return sprintf(buf, "%ld\n", (data->alarms >> bitnr) & 1); 1250a9273cb8eea503f6b8e28bd5f613962ecba278c5Jean Delvare} 1251a9273cb8eea503f6b8e28bd5f613962ecba278c5Jean Delvare 1252a9273cb8eea503f6b8e28bd5f613962ecba278c5Jean Delvarestatic SENSOR_DEVICE_ATTR(temp2_alarm, S_IRUGO, show_alarm, NULL, 0); 1253a9273cb8eea503f6b8e28bd5f613962ecba278c5Jean Delvarestatic SENSOR_DEVICE_ATTR(temp3_alarm, S_IRUGO, show_alarm, NULL, 1); 1254a9273cb8eea503f6b8e28bd5f613962ecba278c5Jean Delvarestatic SENSOR_DEVICE_ATTR(in9_alarm, S_IRUGO, show_alarm, NULL, 1); 1255a9273cb8eea503f6b8e28bd5f613962ecba278c5Jean Delvarestatic SENSOR_DEVICE_ATTR(in11_alarm, S_IRUGO, show_alarm, NULL, 2); 1256a9273cb8eea503f6b8e28bd5f613962ecba278c5Jean Delvarestatic SENSOR_DEVICE_ATTR(in12_alarm, S_IRUGO, show_alarm, NULL, 3); 1257a9273cb8eea503f6b8e28bd5f613962ecba278c5Jean Delvarestatic SENSOR_DEVICE_ATTR(in13_alarm, S_IRUGO, show_alarm, NULL, 4); 1258a9273cb8eea503f6b8e28bd5f613962ecba278c5Jean Delvarestatic SENSOR_DEVICE_ATTR(in14_alarm, S_IRUGO, show_alarm, NULL, 5); 1259a9273cb8eea503f6b8e28bd5f613962ecba278c5Jean Delvarestatic SENSOR_DEVICE_ATTR(in15_alarm, S_IRUGO, show_alarm, NULL, 6); 1260a9273cb8eea503f6b8e28bd5f613962ecba278c5Jean Delvarestatic SENSOR_DEVICE_ATTR(in16_alarm, S_IRUGO, show_alarm, NULL, 7); 1261a9273cb8eea503f6b8e28bd5f613962ecba278c5Jean Delvarestatic SENSOR_DEVICE_ATTR(in0_alarm, S_IRUGO, show_alarm, NULL, 8); 1262a9273cb8eea503f6b8e28bd5f613962ecba278c5Jean Delvarestatic SENSOR_DEVICE_ATTR(in1_alarm, S_IRUGO, show_alarm, NULL, 9); 1263a9273cb8eea503f6b8e28bd5f613962ecba278c5Jean Delvarestatic SENSOR_DEVICE_ATTR(in2_alarm, S_IRUGO, show_alarm, NULL, 10); 1264a9273cb8eea503f6b8e28bd5f613962ecba278c5Jean Delvarestatic SENSOR_DEVICE_ATTR(in3_alarm, S_IRUGO, show_alarm, NULL, 11); 1265a9273cb8eea503f6b8e28bd5f613962ecba278c5Jean Delvarestatic SENSOR_DEVICE_ATTR(in4_alarm, S_IRUGO, show_alarm, NULL, 12); 1266a9273cb8eea503f6b8e28bd5f613962ecba278c5Jean Delvarestatic SENSOR_DEVICE_ATTR(in5_alarm, S_IRUGO, show_alarm, NULL, 13); 1267a9273cb8eea503f6b8e28bd5f613962ecba278c5Jean Delvarestatic SENSOR_DEVICE_ATTR(in6_alarm, S_IRUGO, show_alarm, NULL, 14); 1268a9273cb8eea503f6b8e28bd5f613962ecba278c5Jean Delvarestatic SENSOR_DEVICE_ATTR(in7_alarm, S_IRUGO, show_alarm, NULL, 15); 1269a9273cb8eea503f6b8e28bd5f613962ecba278c5Jean Delvarestatic SENSOR_DEVICE_ATTR(fan1_alarm, S_IRUGO, show_alarm, NULL, 16); 1270a9273cb8eea503f6b8e28bd5f613962ecba278c5Jean Delvarestatic SENSOR_DEVICE_ATTR(fan2_alarm, S_IRUGO, show_alarm, NULL, 17); 1271a9273cb8eea503f6b8e28bd5f613962ecba278c5Jean Delvarestatic SENSOR_DEVICE_ATTR(fan3_alarm, S_IRUGO, show_alarm, NULL, 18); 1272a9273cb8eea503f6b8e28bd5f613962ecba278c5Jean Delvarestatic SENSOR_DEVICE_ATTR(fan4_alarm, S_IRUGO, show_alarm, NULL, 19); 1273a9273cb8eea503f6b8e28bd5f613962ecba278c5Jean Delvarestatic SENSOR_DEVICE_ATTR(fan5_alarm, S_IRUGO, show_alarm, NULL, 20); 1274a9273cb8eea503f6b8e28bd5f613962ecba278c5Jean Delvarestatic SENSOR_DEVICE_ATTR(fan6_alarm, S_IRUGO, show_alarm, NULL, 21); 1275a9273cb8eea503f6b8e28bd5f613962ecba278c5Jean Delvarestatic SENSOR_DEVICE_ATTR(fan7_alarm, S_IRUGO, show_alarm, NULL, 22); 1276a9273cb8eea503f6b8e28bd5f613962ecba278c5Jean Delvarestatic SENSOR_DEVICE_ATTR(fan8_alarm, S_IRUGO, show_alarm, NULL, 23); 1277a9273cb8eea503f6b8e28bd5f613962ecba278c5Jean Delvarestatic SENSOR_DEVICE_ATTR(temp1_alarm, S_IRUGO, show_alarm, NULL, 24); 1278a9273cb8eea503f6b8e28bd5f613962ecba278c5Jean Delvarestatic SENSOR_DEVICE_ATTR(in10_alarm, S_IRUGO, show_alarm, NULL, 25); 1279a9273cb8eea503f6b8e28bd5f613962ecba278c5Jean Delvarestatic SENSOR_DEVICE_ATTR(in8_alarm, S_IRUGO, show_alarm, NULL, 26); 1280a9273cb8eea503f6b8e28bd5f613962ecba278c5Jean Delvare 128174880c063b06efd103c924abfe19d9d8fa4864c4Yani Ioannoustatic ssize_t show_alarm_mask(struct device *dev, struct device_attribute *attr, char *buf) 12821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 12831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct adm1026_data *data = adm1026_update_device(dev); 1284cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvare return sprintf(buf, "%ld\n", data->alarm_mask); 12851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 128674880c063b06efd103c924abfe19d9d8fa4864c4Yani Ioannoustatic ssize_t set_alarm_mask(struct device *dev, struct device_attribute *attr, const char *buf, 12871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds size_t count) 12881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 12891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct i2c_client *client = to_i2c_client(dev); 12901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct adm1026_data *data = i2c_get_clientdata(client); 12911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int val = simple_strtol(buf, NULL, 10); 12921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned long mask; 12931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 12949a61bf6300533d3b64d7ff29adfec00e596de67dIngo Molnar mutex_lock(&data->update_lock); 12951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds data->alarm_mask = val & 0x7fffffff; 12961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds mask = data->alarm_mask 12971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds | (data->gpio_mask & 0x10000 ? 0x80000000 : 0); 12981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds adm1026_write_value(client, ADM1026_REG_MASK1, 12991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds mask & 0xff); 13001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds mask >>= 8; 13011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds adm1026_write_value(client, ADM1026_REG_MASK2, 13021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds mask & 0xff); 13031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds mask >>= 8; 13041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds adm1026_write_value(client, ADM1026_REG_MASK3, 13051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds mask & 0xff); 13061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds mask >>= 8; 13071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds adm1026_write_value(client, ADM1026_REG_MASK4, 13081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds mask & 0xff); 13099a61bf6300533d3b64d7ff29adfec00e596de67dIngo Molnar mutex_unlock(&data->update_lock); 13101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return count; 13111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 13121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 13131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic DEVICE_ATTR(alarm_mask, S_IRUGO | S_IWUSR, show_alarm_mask, 13141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds set_alarm_mask); 13151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 13161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 131774880c063b06efd103c924abfe19d9d8fa4864c4Yani Ioannoustatic ssize_t show_gpio(struct device *dev, struct device_attribute *attr, char *buf) 13181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 13191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct adm1026_data *data = adm1026_update_device(dev); 1320cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvare return sprintf(buf, "%ld\n", data->gpio); 13211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 132274880c063b06efd103c924abfe19d9d8fa4864c4Yani Ioannoustatic ssize_t set_gpio(struct device *dev, struct device_attribute *attr, const char *buf, 13231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds size_t count) 13241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 13251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct i2c_client *client = to_i2c_client(dev); 13261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct adm1026_data *data = i2c_get_clientdata(client); 13271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int val = simple_strtol(buf, NULL, 10); 1328cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvare long gpio; 13291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 13309a61bf6300533d3b64d7ff29adfec00e596de67dIngo Molnar mutex_lock(&data->update_lock); 13311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds data->gpio = val & 0x1ffff; 13321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds gpio = data->gpio; 1333cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvare adm1026_write_value(client, ADM1026_REG_GPIO_STATUS_0_7, gpio & 0xff); 13341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds gpio >>= 8; 1335cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvare adm1026_write_value(client, ADM1026_REG_GPIO_STATUS_8_15, gpio & 0xff); 13361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds gpio = ((gpio >> 1) & 0x80) | (data->alarms >> 24 & 0x7f); 1337cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvare adm1026_write_value(client, ADM1026_REG_STATUS4, gpio & 0xff); 13389a61bf6300533d3b64d7ff29adfec00e596de67dIngo Molnar mutex_unlock(&data->update_lock); 13391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return count; 13401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 13411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 13421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic DEVICE_ATTR(gpio, S_IRUGO | S_IWUSR, show_gpio, set_gpio); 13431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 13441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 134574880c063b06efd103c924abfe19d9d8fa4864c4Yani Ioannoustatic ssize_t show_gpio_mask(struct device *dev, struct device_attribute *attr, char *buf) 13461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 13471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct adm1026_data *data = adm1026_update_device(dev); 1348cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvare return sprintf(buf, "%ld\n", data->gpio_mask); 13491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 135074880c063b06efd103c924abfe19d9d8fa4864c4Yani Ioannoustatic ssize_t set_gpio_mask(struct device *dev, struct device_attribute *attr, const char *buf, 13511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds size_t count) 13521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 13531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct i2c_client *client = to_i2c_client(dev); 13541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct adm1026_data *data = i2c_get_clientdata(client); 13551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int val = simple_strtol(buf, NULL, 10); 1356cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvare long mask; 13571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 13589a61bf6300533d3b64d7ff29adfec00e596de67dIngo Molnar mutex_lock(&data->update_lock); 13591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds data->gpio_mask = val & 0x1ffff; 13601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds mask = data->gpio_mask; 1361cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvare adm1026_write_value(client, ADM1026_REG_GPIO_MASK_0_7, mask & 0xff); 13621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds mask >>= 8; 1363cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvare adm1026_write_value(client, ADM1026_REG_GPIO_MASK_8_15, mask & 0xff); 13641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds mask = ((mask >> 1) & 0x80) | (data->alarm_mask >> 24 & 0x7f); 1365cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvare adm1026_write_value(client, ADM1026_REG_MASK1, mask & 0xff); 13669a61bf6300533d3b64d7ff29adfec00e596de67dIngo Molnar mutex_unlock(&data->update_lock); 13671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return count; 13681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 13691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 13701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic DEVICE_ATTR(gpio_mask, S_IRUGO | S_IWUSR, show_gpio_mask, set_gpio_mask); 13711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 137274880c063b06efd103c924abfe19d9d8fa4864c4Yani Ioannoustatic ssize_t show_pwm_reg(struct device *dev, struct device_attribute *attr, char *buf) 13731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 13741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct adm1026_data *data = adm1026_update_device(dev); 1375cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvare return sprintf(buf, "%d\n", PWM_FROM_REG(data->pwm1.pwm)); 13761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 137774880c063b06efd103c924abfe19d9d8fa4864c4Yani Ioannoustatic ssize_t set_pwm_reg(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 13831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (data->pwm1.enable == 1) { 13841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int val = simple_strtol(buf, NULL, 10); 13851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 13869a61bf6300533d3b64d7ff29adfec00e596de67dIngo Molnar mutex_lock(&data->update_lock); 13871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds data->pwm1.pwm = PWM_TO_REG(val); 13881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds adm1026_write_value(client, ADM1026_REG_PWM, data->pwm1.pwm); 13899a61bf6300533d3b64d7ff29adfec00e596de67dIngo Molnar mutex_unlock(&data->update_lock); 13901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 13911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return count; 13921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 139374880c063b06efd103c924abfe19d9d8fa4864c4Yani Ioannoustatic ssize_t show_auto_pwm_min(struct device *dev, struct device_attribute *attr, char *buf) 13941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 13951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct adm1026_data *data = adm1026_update_device(dev); 1396cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvare return sprintf(buf, "%d\n", data->pwm1.auto_pwm_min); 13971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 139874880c063b06efd103c924abfe19d9d8fa4864c4Yani Ioannoustatic ssize_t set_auto_pwm_min(struct device *dev, struct device_attribute *attr, const char *buf, 13991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds size_t count) 14001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 14011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct i2c_client *client = to_i2c_client(dev); 14021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct adm1026_data *data = i2c_get_clientdata(client); 14031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int val = simple_strtol(buf, NULL, 10); 14041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 14059a61bf6300533d3b64d7ff29adfec00e596de67dIngo Molnar mutex_lock(&data->update_lock); 1406cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvare data->pwm1.auto_pwm_min = SENSORS_LIMIT(val, 0, 255); 14071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (data->pwm1.enable == 2) { /* apply immediately */ 14081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds data->pwm1.pwm = PWM_TO_REG((data->pwm1.pwm & 0x0f) | 1409cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvare PWM_MIN_TO_REG(data->pwm1.auto_pwm_min)); 14101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds adm1026_write_value(client, ADM1026_REG_PWM, data->pwm1.pwm); 14111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 14129a61bf6300533d3b64d7ff29adfec00e596de67dIngo Molnar mutex_unlock(&data->update_lock); 14131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return count; 14141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 141574880c063b06efd103c924abfe19d9d8fa4864c4Yani Ioannoustatic ssize_t show_auto_pwm_max(struct device *dev, struct device_attribute *attr, char *buf) 14161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 1417cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvare return sprintf(buf, "%d\n", ADM1026_PWM_MAX); 14181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 141974880c063b06efd103c924abfe19d9d8fa4864c4Yani Ioannoustatic ssize_t show_pwm_enable(struct device *dev, struct device_attribute *attr, char *buf) 14201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 14211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct adm1026_data *data = adm1026_update_device(dev); 1422cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvare return sprintf(buf, "%d\n", data->pwm1.enable); 14231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 142474880c063b06efd103c924abfe19d9d8fa4864c4Yani Ioannoustatic ssize_t set_pwm_enable(struct device *dev, struct device_attribute *attr, const char *buf, 14251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds size_t count) 14261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 14271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct i2c_client *client = to_i2c_client(dev); 14281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct adm1026_data *data = i2c_get_clientdata(client); 14291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int val = simple_strtol(buf, NULL, 10); 1430cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvare int old_enable; 14311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 14321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if ((val >= 0) && (val < 3)) { 14339a61bf6300533d3b64d7ff29adfec00e596de67dIngo Molnar mutex_lock(&data->update_lock); 14341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds old_enable = data->pwm1.enable; 14351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds data->pwm1.enable = val; 14361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds data->config1 = (data->config1 & ~CFG1_PWM_AFC) 14371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds | ((val == 2) ? CFG1_PWM_AFC : 0); 14381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds adm1026_write_value(client, ADM1026_REG_CONFIG1, 14391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds data->config1); 1440cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvare if (val == 2) { /* apply pwm1_auto_pwm_min to pwm1 */ 14411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds data->pwm1.pwm = PWM_TO_REG((data->pwm1.pwm & 0x0f) | 1442cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvare PWM_MIN_TO_REG(data->pwm1.auto_pwm_min)); 1443cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvare adm1026_write_value(client, ADM1026_REG_PWM, 14441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds data->pwm1.pwm); 14451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } else if (!((old_enable == 1) && (val == 1))) { 14461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* set pwm to safe value */ 14471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds data->pwm1.pwm = 255; 1448cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvare adm1026_write_value(client, ADM1026_REG_PWM, 14491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds data->pwm1.pwm); 14501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 14519a61bf6300533d3b64d7ff29adfec00e596de67dIngo Molnar mutex_unlock(&data->update_lock); 14521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 14531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return count; 14541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 14551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 14561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* enable PWM fan control */ 1457cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvarestatic DEVICE_ATTR(pwm1, S_IRUGO | S_IWUSR, show_pwm_reg, set_pwm_reg); 1458cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvarestatic DEVICE_ATTR(pwm2, S_IRUGO | S_IWUSR, show_pwm_reg, set_pwm_reg); 1459cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvarestatic DEVICE_ATTR(pwm3, S_IRUGO | S_IWUSR, show_pwm_reg, set_pwm_reg); 1460cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvarestatic DEVICE_ATTR(pwm1_enable, S_IRUGO | S_IWUSR, show_pwm_enable, 14611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds set_pwm_enable); 1462cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvarestatic DEVICE_ATTR(pwm2_enable, S_IRUGO | S_IWUSR, show_pwm_enable, 14631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds set_pwm_enable); 1464cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvarestatic DEVICE_ATTR(pwm3_enable, S_IRUGO | S_IWUSR, show_pwm_enable, 14651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds set_pwm_enable); 1466cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvarestatic DEVICE_ATTR(temp1_auto_point1_pwm, S_IRUGO | S_IWUSR, 14671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds show_auto_pwm_min, set_auto_pwm_min); 1468cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvarestatic DEVICE_ATTR(temp2_auto_point1_pwm, S_IRUGO | S_IWUSR, 14691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds show_auto_pwm_min, set_auto_pwm_min); 1470cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvarestatic DEVICE_ATTR(temp3_auto_point1_pwm, S_IRUGO | S_IWUSR, 14711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds show_auto_pwm_min, set_auto_pwm_min); 14721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 14731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic DEVICE_ATTR(temp1_auto_point2_pwm, S_IRUGO, show_auto_pwm_max, NULL); 14741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic DEVICE_ATTR(temp2_auto_point2_pwm, S_IRUGO, show_auto_pwm_max, NULL); 14751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic DEVICE_ATTR(temp3_auto_point2_pwm, S_IRUGO, show_auto_pwm_max, NULL); 14761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1477681c6f7a6702f208d48b501c8829dbc03a2ca238Mark M. Hoffmanstatic struct attribute *adm1026_attributes[] = { 1478681c6f7a6702f208d48b501c8829dbc03a2ca238Mark M. Hoffman &sensor_dev_attr_in0_input.dev_attr.attr, 1479681c6f7a6702f208d48b501c8829dbc03a2ca238Mark M. Hoffman &sensor_dev_attr_in0_max.dev_attr.attr, 1480681c6f7a6702f208d48b501c8829dbc03a2ca238Mark M. Hoffman &sensor_dev_attr_in0_min.dev_attr.attr, 1481a9273cb8eea503f6b8e28bd5f613962ecba278c5Jean Delvare &sensor_dev_attr_in0_alarm.dev_attr.attr, 1482681c6f7a6702f208d48b501c8829dbc03a2ca238Mark M. Hoffman &sensor_dev_attr_in1_input.dev_attr.attr, 1483681c6f7a6702f208d48b501c8829dbc03a2ca238Mark M. Hoffman &sensor_dev_attr_in1_max.dev_attr.attr, 1484681c6f7a6702f208d48b501c8829dbc03a2ca238Mark M. Hoffman &sensor_dev_attr_in1_min.dev_attr.attr, 1485a9273cb8eea503f6b8e28bd5f613962ecba278c5Jean Delvare &sensor_dev_attr_in1_alarm.dev_attr.attr, 1486681c6f7a6702f208d48b501c8829dbc03a2ca238Mark M. Hoffman &sensor_dev_attr_in2_input.dev_attr.attr, 1487681c6f7a6702f208d48b501c8829dbc03a2ca238Mark M. Hoffman &sensor_dev_attr_in2_max.dev_attr.attr, 1488681c6f7a6702f208d48b501c8829dbc03a2ca238Mark M. Hoffman &sensor_dev_attr_in2_min.dev_attr.attr, 1489a9273cb8eea503f6b8e28bd5f613962ecba278c5Jean Delvare &sensor_dev_attr_in2_alarm.dev_attr.attr, 1490681c6f7a6702f208d48b501c8829dbc03a2ca238Mark M. Hoffman &sensor_dev_attr_in3_input.dev_attr.attr, 1491681c6f7a6702f208d48b501c8829dbc03a2ca238Mark M. Hoffman &sensor_dev_attr_in3_max.dev_attr.attr, 1492681c6f7a6702f208d48b501c8829dbc03a2ca238Mark M. Hoffman &sensor_dev_attr_in3_min.dev_attr.attr, 1493a9273cb8eea503f6b8e28bd5f613962ecba278c5Jean Delvare &sensor_dev_attr_in3_alarm.dev_attr.attr, 1494681c6f7a6702f208d48b501c8829dbc03a2ca238Mark M. Hoffman &sensor_dev_attr_in4_input.dev_attr.attr, 1495681c6f7a6702f208d48b501c8829dbc03a2ca238Mark M. Hoffman &sensor_dev_attr_in4_max.dev_attr.attr, 1496681c6f7a6702f208d48b501c8829dbc03a2ca238Mark M. Hoffman &sensor_dev_attr_in4_min.dev_attr.attr, 1497a9273cb8eea503f6b8e28bd5f613962ecba278c5Jean Delvare &sensor_dev_attr_in4_alarm.dev_attr.attr, 1498681c6f7a6702f208d48b501c8829dbc03a2ca238Mark M. Hoffman &sensor_dev_attr_in5_input.dev_attr.attr, 1499681c6f7a6702f208d48b501c8829dbc03a2ca238Mark M. Hoffman &sensor_dev_attr_in5_max.dev_attr.attr, 1500681c6f7a6702f208d48b501c8829dbc03a2ca238Mark M. Hoffman &sensor_dev_attr_in5_min.dev_attr.attr, 1501a9273cb8eea503f6b8e28bd5f613962ecba278c5Jean Delvare &sensor_dev_attr_in5_alarm.dev_attr.attr, 1502681c6f7a6702f208d48b501c8829dbc03a2ca238Mark M. Hoffman &sensor_dev_attr_in6_input.dev_attr.attr, 1503681c6f7a6702f208d48b501c8829dbc03a2ca238Mark M. Hoffman &sensor_dev_attr_in6_max.dev_attr.attr, 1504681c6f7a6702f208d48b501c8829dbc03a2ca238Mark M. Hoffman &sensor_dev_attr_in6_min.dev_attr.attr, 1505a9273cb8eea503f6b8e28bd5f613962ecba278c5Jean Delvare &sensor_dev_attr_in6_alarm.dev_attr.attr, 1506681c6f7a6702f208d48b501c8829dbc03a2ca238Mark M. Hoffman &sensor_dev_attr_in7_input.dev_attr.attr, 1507681c6f7a6702f208d48b501c8829dbc03a2ca238Mark M. Hoffman &sensor_dev_attr_in7_max.dev_attr.attr, 1508681c6f7a6702f208d48b501c8829dbc03a2ca238Mark M. Hoffman &sensor_dev_attr_in7_min.dev_attr.attr, 1509a9273cb8eea503f6b8e28bd5f613962ecba278c5Jean Delvare &sensor_dev_attr_in7_alarm.dev_attr.attr, 1510681c6f7a6702f208d48b501c8829dbc03a2ca238Mark M. Hoffman &sensor_dev_attr_in10_input.dev_attr.attr, 1511681c6f7a6702f208d48b501c8829dbc03a2ca238Mark M. Hoffman &sensor_dev_attr_in10_max.dev_attr.attr, 1512681c6f7a6702f208d48b501c8829dbc03a2ca238Mark M. Hoffman &sensor_dev_attr_in10_min.dev_attr.attr, 1513a9273cb8eea503f6b8e28bd5f613962ecba278c5Jean Delvare &sensor_dev_attr_in10_alarm.dev_attr.attr, 1514681c6f7a6702f208d48b501c8829dbc03a2ca238Mark M. Hoffman &sensor_dev_attr_in11_input.dev_attr.attr, 1515681c6f7a6702f208d48b501c8829dbc03a2ca238Mark M. Hoffman &sensor_dev_attr_in11_max.dev_attr.attr, 1516681c6f7a6702f208d48b501c8829dbc03a2ca238Mark M. Hoffman &sensor_dev_attr_in11_min.dev_attr.attr, 1517a9273cb8eea503f6b8e28bd5f613962ecba278c5Jean Delvare &sensor_dev_attr_in11_alarm.dev_attr.attr, 1518681c6f7a6702f208d48b501c8829dbc03a2ca238Mark M. Hoffman &sensor_dev_attr_in12_input.dev_attr.attr, 1519681c6f7a6702f208d48b501c8829dbc03a2ca238Mark M. Hoffman &sensor_dev_attr_in12_max.dev_attr.attr, 1520681c6f7a6702f208d48b501c8829dbc03a2ca238Mark M. Hoffman &sensor_dev_attr_in12_min.dev_attr.attr, 1521a9273cb8eea503f6b8e28bd5f613962ecba278c5Jean Delvare &sensor_dev_attr_in12_alarm.dev_attr.attr, 1522681c6f7a6702f208d48b501c8829dbc03a2ca238Mark M. Hoffman &sensor_dev_attr_in13_input.dev_attr.attr, 1523681c6f7a6702f208d48b501c8829dbc03a2ca238Mark M. Hoffman &sensor_dev_attr_in13_max.dev_attr.attr, 1524681c6f7a6702f208d48b501c8829dbc03a2ca238Mark M. Hoffman &sensor_dev_attr_in13_min.dev_attr.attr, 1525a9273cb8eea503f6b8e28bd5f613962ecba278c5Jean Delvare &sensor_dev_attr_in13_alarm.dev_attr.attr, 1526681c6f7a6702f208d48b501c8829dbc03a2ca238Mark M. Hoffman &sensor_dev_attr_in14_input.dev_attr.attr, 1527681c6f7a6702f208d48b501c8829dbc03a2ca238Mark M. Hoffman &sensor_dev_attr_in14_max.dev_attr.attr, 1528681c6f7a6702f208d48b501c8829dbc03a2ca238Mark M. Hoffman &sensor_dev_attr_in14_min.dev_attr.attr, 1529a9273cb8eea503f6b8e28bd5f613962ecba278c5Jean Delvare &sensor_dev_attr_in14_alarm.dev_attr.attr, 1530681c6f7a6702f208d48b501c8829dbc03a2ca238Mark M. Hoffman &sensor_dev_attr_in15_input.dev_attr.attr, 1531681c6f7a6702f208d48b501c8829dbc03a2ca238Mark M. Hoffman &sensor_dev_attr_in15_max.dev_attr.attr, 1532681c6f7a6702f208d48b501c8829dbc03a2ca238Mark M. Hoffman &sensor_dev_attr_in15_min.dev_attr.attr, 1533a9273cb8eea503f6b8e28bd5f613962ecba278c5Jean Delvare &sensor_dev_attr_in15_alarm.dev_attr.attr, 1534681c6f7a6702f208d48b501c8829dbc03a2ca238Mark M. Hoffman &sensor_dev_attr_in16_input.dev_attr.attr, 1535681c6f7a6702f208d48b501c8829dbc03a2ca238Mark M. Hoffman &sensor_dev_attr_in16_max.dev_attr.attr, 1536681c6f7a6702f208d48b501c8829dbc03a2ca238Mark M. Hoffman &sensor_dev_attr_in16_min.dev_attr.attr, 1537a9273cb8eea503f6b8e28bd5f613962ecba278c5Jean Delvare &sensor_dev_attr_in16_alarm.dev_attr.attr, 1538681c6f7a6702f208d48b501c8829dbc03a2ca238Mark M. Hoffman &sensor_dev_attr_fan1_input.dev_attr.attr, 1539681c6f7a6702f208d48b501c8829dbc03a2ca238Mark M. Hoffman &sensor_dev_attr_fan1_div.dev_attr.attr, 1540681c6f7a6702f208d48b501c8829dbc03a2ca238Mark M. Hoffman &sensor_dev_attr_fan1_min.dev_attr.attr, 1541a9273cb8eea503f6b8e28bd5f613962ecba278c5Jean Delvare &sensor_dev_attr_fan1_alarm.dev_attr.attr, 1542681c6f7a6702f208d48b501c8829dbc03a2ca238Mark M. Hoffman &sensor_dev_attr_fan2_input.dev_attr.attr, 1543681c6f7a6702f208d48b501c8829dbc03a2ca238Mark M. Hoffman &sensor_dev_attr_fan2_div.dev_attr.attr, 1544681c6f7a6702f208d48b501c8829dbc03a2ca238Mark M. Hoffman &sensor_dev_attr_fan2_min.dev_attr.attr, 1545a9273cb8eea503f6b8e28bd5f613962ecba278c5Jean Delvare &sensor_dev_attr_fan2_alarm.dev_attr.attr, 1546681c6f7a6702f208d48b501c8829dbc03a2ca238Mark M. Hoffman &sensor_dev_attr_fan3_input.dev_attr.attr, 1547681c6f7a6702f208d48b501c8829dbc03a2ca238Mark M. Hoffman &sensor_dev_attr_fan3_div.dev_attr.attr, 1548681c6f7a6702f208d48b501c8829dbc03a2ca238Mark M. Hoffman &sensor_dev_attr_fan3_min.dev_attr.attr, 1549a9273cb8eea503f6b8e28bd5f613962ecba278c5Jean Delvare &sensor_dev_attr_fan3_alarm.dev_attr.attr, 1550681c6f7a6702f208d48b501c8829dbc03a2ca238Mark M. Hoffman &sensor_dev_attr_fan4_input.dev_attr.attr, 1551681c6f7a6702f208d48b501c8829dbc03a2ca238Mark M. Hoffman &sensor_dev_attr_fan4_div.dev_attr.attr, 1552681c6f7a6702f208d48b501c8829dbc03a2ca238Mark M. Hoffman &sensor_dev_attr_fan4_min.dev_attr.attr, 1553a9273cb8eea503f6b8e28bd5f613962ecba278c5Jean Delvare &sensor_dev_attr_fan4_alarm.dev_attr.attr, 1554681c6f7a6702f208d48b501c8829dbc03a2ca238Mark M. Hoffman &sensor_dev_attr_fan5_input.dev_attr.attr, 1555681c6f7a6702f208d48b501c8829dbc03a2ca238Mark M. Hoffman &sensor_dev_attr_fan5_div.dev_attr.attr, 1556681c6f7a6702f208d48b501c8829dbc03a2ca238Mark M. Hoffman &sensor_dev_attr_fan5_min.dev_attr.attr, 1557a9273cb8eea503f6b8e28bd5f613962ecba278c5Jean Delvare &sensor_dev_attr_fan5_alarm.dev_attr.attr, 1558681c6f7a6702f208d48b501c8829dbc03a2ca238Mark M. Hoffman &sensor_dev_attr_fan6_input.dev_attr.attr, 1559681c6f7a6702f208d48b501c8829dbc03a2ca238Mark M. Hoffman &sensor_dev_attr_fan6_div.dev_attr.attr, 1560681c6f7a6702f208d48b501c8829dbc03a2ca238Mark M. Hoffman &sensor_dev_attr_fan6_min.dev_attr.attr, 1561a9273cb8eea503f6b8e28bd5f613962ecba278c5Jean Delvare &sensor_dev_attr_fan6_alarm.dev_attr.attr, 1562681c6f7a6702f208d48b501c8829dbc03a2ca238Mark M. Hoffman &sensor_dev_attr_fan7_input.dev_attr.attr, 1563681c6f7a6702f208d48b501c8829dbc03a2ca238Mark M. Hoffman &sensor_dev_attr_fan7_div.dev_attr.attr, 1564681c6f7a6702f208d48b501c8829dbc03a2ca238Mark M. Hoffman &sensor_dev_attr_fan7_min.dev_attr.attr, 1565a9273cb8eea503f6b8e28bd5f613962ecba278c5Jean Delvare &sensor_dev_attr_fan7_alarm.dev_attr.attr, 1566681c6f7a6702f208d48b501c8829dbc03a2ca238Mark M. Hoffman &sensor_dev_attr_fan8_input.dev_attr.attr, 1567681c6f7a6702f208d48b501c8829dbc03a2ca238Mark M. Hoffman &sensor_dev_attr_fan8_div.dev_attr.attr, 1568681c6f7a6702f208d48b501c8829dbc03a2ca238Mark M. Hoffman &sensor_dev_attr_fan8_min.dev_attr.attr, 1569a9273cb8eea503f6b8e28bd5f613962ecba278c5Jean Delvare &sensor_dev_attr_fan8_alarm.dev_attr.attr, 1570681c6f7a6702f208d48b501c8829dbc03a2ca238Mark M. Hoffman &sensor_dev_attr_temp1_input.dev_attr.attr, 1571681c6f7a6702f208d48b501c8829dbc03a2ca238Mark M. Hoffman &sensor_dev_attr_temp1_max.dev_attr.attr, 1572681c6f7a6702f208d48b501c8829dbc03a2ca238Mark M. Hoffman &sensor_dev_attr_temp1_min.dev_attr.attr, 1573a9273cb8eea503f6b8e28bd5f613962ecba278c5Jean Delvare &sensor_dev_attr_temp1_alarm.dev_attr.attr, 1574681c6f7a6702f208d48b501c8829dbc03a2ca238Mark M. Hoffman &sensor_dev_attr_temp2_input.dev_attr.attr, 1575681c6f7a6702f208d48b501c8829dbc03a2ca238Mark M. Hoffman &sensor_dev_attr_temp2_max.dev_attr.attr, 1576681c6f7a6702f208d48b501c8829dbc03a2ca238Mark M. Hoffman &sensor_dev_attr_temp2_min.dev_attr.attr, 1577a9273cb8eea503f6b8e28bd5f613962ecba278c5Jean Delvare &sensor_dev_attr_temp2_alarm.dev_attr.attr, 1578681c6f7a6702f208d48b501c8829dbc03a2ca238Mark M. Hoffman &sensor_dev_attr_temp1_offset.dev_attr.attr, 1579681c6f7a6702f208d48b501c8829dbc03a2ca238Mark M. Hoffman &sensor_dev_attr_temp2_offset.dev_attr.attr, 1580681c6f7a6702f208d48b501c8829dbc03a2ca238Mark M. Hoffman &sensor_dev_attr_temp1_auto_point1_temp.dev_attr.attr, 1581681c6f7a6702f208d48b501c8829dbc03a2ca238Mark M. Hoffman &sensor_dev_attr_temp2_auto_point1_temp.dev_attr.attr, 1582681c6f7a6702f208d48b501c8829dbc03a2ca238Mark M. Hoffman &sensor_dev_attr_temp1_auto_point1_temp_hyst.dev_attr.attr, 1583681c6f7a6702f208d48b501c8829dbc03a2ca238Mark M. Hoffman &sensor_dev_attr_temp2_auto_point1_temp_hyst.dev_attr.attr, 1584681c6f7a6702f208d48b501c8829dbc03a2ca238Mark M. Hoffman &sensor_dev_attr_temp1_auto_point2_temp.dev_attr.attr, 1585681c6f7a6702f208d48b501c8829dbc03a2ca238Mark M. Hoffman &sensor_dev_attr_temp2_auto_point2_temp.dev_attr.attr, 1586681c6f7a6702f208d48b501c8829dbc03a2ca238Mark M. Hoffman &sensor_dev_attr_temp1_crit.dev_attr.attr, 1587681c6f7a6702f208d48b501c8829dbc03a2ca238Mark M. Hoffman &sensor_dev_attr_temp2_crit.dev_attr.attr, 1588681c6f7a6702f208d48b501c8829dbc03a2ca238Mark M. Hoffman &dev_attr_temp1_crit_enable.attr, 1589681c6f7a6702f208d48b501c8829dbc03a2ca238Mark M. Hoffman &dev_attr_temp2_crit_enable.attr, 1590681c6f7a6702f208d48b501c8829dbc03a2ca238Mark M. Hoffman &dev_attr_cpu0_vid.attr, 1591681c6f7a6702f208d48b501c8829dbc03a2ca238Mark M. Hoffman &dev_attr_vrm.attr, 1592681c6f7a6702f208d48b501c8829dbc03a2ca238Mark M. Hoffman &dev_attr_alarms.attr, 1593681c6f7a6702f208d48b501c8829dbc03a2ca238Mark M. Hoffman &dev_attr_alarm_mask.attr, 1594681c6f7a6702f208d48b501c8829dbc03a2ca238Mark M. Hoffman &dev_attr_gpio.attr, 1595681c6f7a6702f208d48b501c8829dbc03a2ca238Mark M. Hoffman &dev_attr_gpio_mask.attr, 1596681c6f7a6702f208d48b501c8829dbc03a2ca238Mark M. Hoffman &dev_attr_pwm1.attr, 1597681c6f7a6702f208d48b501c8829dbc03a2ca238Mark M. Hoffman &dev_attr_pwm2.attr, 1598681c6f7a6702f208d48b501c8829dbc03a2ca238Mark M. Hoffman &dev_attr_pwm3.attr, 1599681c6f7a6702f208d48b501c8829dbc03a2ca238Mark M. Hoffman &dev_attr_pwm1_enable.attr, 1600681c6f7a6702f208d48b501c8829dbc03a2ca238Mark M. Hoffman &dev_attr_pwm2_enable.attr, 1601681c6f7a6702f208d48b501c8829dbc03a2ca238Mark M. Hoffman &dev_attr_pwm3_enable.attr, 1602681c6f7a6702f208d48b501c8829dbc03a2ca238Mark M. Hoffman &dev_attr_temp1_auto_point1_pwm.attr, 1603681c6f7a6702f208d48b501c8829dbc03a2ca238Mark M. Hoffman &dev_attr_temp2_auto_point1_pwm.attr, 1604681c6f7a6702f208d48b501c8829dbc03a2ca238Mark M. Hoffman &dev_attr_temp1_auto_point2_pwm.attr, 1605681c6f7a6702f208d48b501c8829dbc03a2ca238Mark M. Hoffman &dev_attr_temp2_auto_point2_pwm.attr, 1606681c6f7a6702f208d48b501c8829dbc03a2ca238Mark M. Hoffman &dev_attr_analog_out.attr, 1607681c6f7a6702f208d48b501c8829dbc03a2ca238Mark M. Hoffman NULL 1608681c6f7a6702f208d48b501c8829dbc03a2ca238Mark M. Hoffman}; 1609681c6f7a6702f208d48b501c8829dbc03a2ca238Mark M. Hoffman 1610681c6f7a6702f208d48b501c8829dbc03a2ca238Mark M. Hoffmanstatic const struct attribute_group adm1026_group = { 1611681c6f7a6702f208d48b501c8829dbc03a2ca238Mark M. Hoffman .attrs = adm1026_attributes, 1612681c6f7a6702f208d48b501c8829dbc03a2ca238Mark M. Hoffman}; 1613681c6f7a6702f208d48b501c8829dbc03a2ca238Mark M. Hoffman 16145b34dbcd88251508d02e48ad9b0f9b8232a13ee0Jean Delvarestatic struct attribute *adm1026_attributes_temp3[] = { 16155b34dbcd88251508d02e48ad9b0f9b8232a13ee0Jean Delvare &sensor_dev_attr_temp3_input.dev_attr.attr, 16165b34dbcd88251508d02e48ad9b0f9b8232a13ee0Jean Delvare &sensor_dev_attr_temp3_max.dev_attr.attr, 16175b34dbcd88251508d02e48ad9b0f9b8232a13ee0Jean Delvare &sensor_dev_attr_temp3_min.dev_attr.attr, 16185b34dbcd88251508d02e48ad9b0f9b8232a13ee0Jean Delvare &sensor_dev_attr_temp3_alarm.dev_attr.attr, 16195b34dbcd88251508d02e48ad9b0f9b8232a13ee0Jean Delvare &sensor_dev_attr_temp3_offset.dev_attr.attr, 16205b34dbcd88251508d02e48ad9b0f9b8232a13ee0Jean Delvare &sensor_dev_attr_temp3_auto_point1_temp.dev_attr.attr, 16215b34dbcd88251508d02e48ad9b0f9b8232a13ee0Jean Delvare &sensor_dev_attr_temp3_auto_point1_temp_hyst.dev_attr.attr, 16225b34dbcd88251508d02e48ad9b0f9b8232a13ee0Jean Delvare &sensor_dev_attr_temp3_auto_point2_temp.dev_attr.attr, 16235b34dbcd88251508d02e48ad9b0f9b8232a13ee0Jean Delvare &sensor_dev_attr_temp3_crit.dev_attr.attr, 16245b34dbcd88251508d02e48ad9b0f9b8232a13ee0Jean Delvare &dev_attr_temp3_crit_enable.attr, 16255b34dbcd88251508d02e48ad9b0f9b8232a13ee0Jean Delvare &dev_attr_temp3_auto_point1_pwm.attr, 16265b34dbcd88251508d02e48ad9b0f9b8232a13ee0Jean Delvare &dev_attr_temp3_auto_point2_pwm.attr, 16271d5f2c16c6125ae6da1435ac5a190ae08429902aJean Delvare NULL 16285b34dbcd88251508d02e48ad9b0f9b8232a13ee0Jean Delvare}; 16295b34dbcd88251508d02e48ad9b0f9b8232a13ee0Jean Delvare 16305b34dbcd88251508d02e48ad9b0f9b8232a13ee0Jean Delvarestatic const struct attribute_group adm1026_group_temp3 = { 16315b34dbcd88251508d02e48ad9b0f9b8232a13ee0Jean Delvare .attrs = adm1026_attributes_temp3, 16325b34dbcd88251508d02e48ad9b0f9b8232a13ee0Jean Delvare}; 16335b34dbcd88251508d02e48ad9b0f9b8232a13ee0Jean Delvare 16345b34dbcd88251508d02e48ad9b0f9b8232a13ee0Jean Delvarestatic struct attribute *adm1026_attributes_in8_9[] = { 16355b34dbcd88251508d02e48ad9b0f9b8232a13ee0Jean Delvare &sensor_dev_attr_in8_input.dev_attr.attr, 16365b34dbcd88251508d02e48ad9b0f9b8232a13ee0Jean Delvare &sensor_dev_attr_in8_max.dev_attr.attr, 16375b34dbcd88251508d02e48ad9b0f9b8232a13ee0Jean Delvare &sensor_dev_attr_in8_min.dev_attr.attr, 16385b34dbcd88251508d02e48ad9b0f9b8232a13ee0Jean Delvare &sensor_dev_attr_in8_alarm.dev_attr.attr, 16395b34dbcd88251508d02e48ad9b0f9b8232a13ee0Jean Delvare &sensor_dev_attr_in9_input.dev_attr.attr, 16405b34dbcd88251508d02e48ad9b0f9b8232a13ee0Jean Delvare &sensor_dev_attr_in9_max.dev_attr.attr, 16415b34dbcd88251508d02e48ad9b0f9b8232a13ee0Jean Delvare &sensor_dev_attr_in9_min.dev_attr.attr, 16425b34dbcd88251508d02e48ad9b0f9b8232a13ee0Jean Delvare &sensor_dev_attr_in9_alarm.dev_attr.attr, 16431d5f2c16c6125ae6da1435ac5a190ae08429902aJean Delvare NULL 16445b34dbcd88251508d02e48ad9b0f9b8232a13ee0Jean Delvare}; 16455b34dbcd88251508d02e48ad9b0f9b8232a13ee0Jean Delvare 16465b34dbcd88251508d02e48ad9b0f9b8232a13ee0Jean Delvarestatic const struct attribute_group adm1026_group_in8_9 = { 16475b34dbcd88251508d02e48ad9b0f9b8232a13ee0Jean Delvare .attrs = adm1026_attributes_in8_9, 16485b34dbcd88251508d02e48ad9b0f9b8232a13ee0Jean Delvare}; 16495b34dbcd88251508d02e48ad9b0f9b8232a13ee0Jean Delvare 1650c49efceffa599299ab3f38b1cdf8c2f1bf9811c4Ben Dooksstatic int adm1026_detect(struct i2c_adapter *adapter, int address, 1651c49efceffa599299ab3f38b1cdf8c2f1bf9811c4Ben Dooks int kind) 16521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 16531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int company, verstep; 1654f67fdabfb94b0bb96623a4b48d22be5329a06277Jean Delvare struct i2c_client *client; 16551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct adm1026_data *data; 16561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int err = 0; 16571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds const char *type_name = ""; 16581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 16591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA)) { 16601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* We need to be able to do byte I/O */ 16611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto exit; 16621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds }; 16631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 16641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* OK. For now, we presume we have a valid client. We now create the 16651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds client structure, even though we cannot fill it completely yet. 16661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds But it allows us to access adm1026_{read,write}_value. */ 16671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1668ba9c2e8d15da029ea3051c95e446b2d638ef02e2Deepak Saxena if (!(data = kzalloc(sizeof(struct adm1026_data), GFP_KERNEL))) { 16691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds err = -ENOMEM; 16701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto exit; 16711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 16721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1673f67fdabfb94b0bb96623a4b48d22be5329a06277Jean Delvare client = &data->client; 1674f67fdabfb94b0bb96623a4b48d22be5329a06277Jean Delvare i2c_set_clientdata(client, data); 1675f67fdabfb94b0bb96623a4b48d22be5329a06277Jean Delvare client->addr = address; 1676f67fdabfb94b0bb96623a4b48d22be5329a06277Jean Delvare client->adapter = adapter; 1677f67fdabfb94b0bb96623a4b48d22be5329a06277Jean Delvare client->driver = &adm1026_driver; 16781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 16791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Now, we do the remaining detection. */ 16801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1681f67fdabfb94b0bb96623a4b48d22be5329a06277Jean Delvare company = adm1026_read_value(client, ADM1026_REG_COMPANY); 1682f67fdabfb94b0bb96623a4b48d22be5329a06277Jean Delvare verstep = adm1026_read_value(client, ADM1026_REG_VERSTEP); 16831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1684f67fdabfb94b0bb96623a4b48d22be5329a06277Jean Delvare dev_dbg(&client->dev, "Detecting device at %d,0x%02x with" 16851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds " COMPANY: 0x%02x and VERSTEP: 0x%02x\n", 1686f67fdabfb94b0bb96623a4b48d22be5329a06277Jean Delvare i2c_adapter_id(client->adapter), client->addr, 16871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds company, verstep); 16881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 16891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* If auto-detecting, Determine the chip type. */ 16901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (kind <= 0) { 1691f67fdabfb94b0bb96623a4b48d22be5329a06277Jean Delvare dev_dbg(&client->dev, "Autodetecting device at %d,0x%02x " 16921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "...\n", i2c_adapter_id(adapter), address); 16931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (company == ADM1026_COMPANY_ANALOG_DEV 16941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds && verstep == ADM1026_VERSTEP_ADM1026) { 16951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds kind = adm1026; 16961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } else if (company == ADM1026_COMPANY_ANALOG_DEV 16971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds && (verstep & 0xf0) == ADM1026_VERSTEP_GENERIC) { 16981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dev_err(&adapter->dev, ": Unrecognized stepping " 16991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "0x%02x. Defaulting to ADM1026.\n", verstep); 17001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds kind = adm1026; 17011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } else if ((verstep & 0xf0) == ADM1026_VERSTEP_GENERIC) { 17021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dev_err(&adapter->dev, ": Found version/stepping " 17031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "0x%02x. Assuming generic ADM1026.\n", 17041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds verstep); 17051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds kind = any_chip; 17061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } else { 1707f67fdabfb94b0bb96623a4b48d22be5329a06277Jean Delvare dev_dbg(&client->dev, ": Autodetection " 17081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "failed\n"); 17091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Not an ADM1026 ... */ 1710cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvare if (kind == 0) { /* User used force=x,y */ 17111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dev_err(&adapter->dev, "Generic ADM1026 not " 17121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "found at %d,0x%02x. Try " 17131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "force_adm1026.\n", 17141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds i2c_adapter_id(adapter), address); 17151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 17161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto exitfree; 17171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 17181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 17191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 17201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Fill in the chip specific driver values */ 17211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds switch (kind) { 17221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case any_chip : 17231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds type_name = "adm1026"; 17241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 17251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case adm1026 : 17261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds type_name = "adm1026"; 17271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 17281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds default : 17291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dev_err(&adapter->dev, ": Internal error, invalid " 1730898eb71cb17644964c5895fb190e79e3d0c49679Joe Perches "kind (%d)!\n", kind); 17311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds err = -EFAULT; 17321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto exitfree; 17331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 1734f67fdabfb94b0bb96623a4b48d22be5329a06277Jean Delvare strlcpy(client->name, type_name, I2C_NAME_SIZE); 17351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 17361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Fill in the remaining client fields */ 17379a61bf6300533d3b64d7ff29adfec00e596de67dIngo Molnar mutex_init(&data->update_lock); 17381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 17391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Tell the I2C layer a new client has arrived */ 1740f67fdabfb94b0bb96623a4b48d22be5329a06277Jean Delvare if ((err = i2c_attach_client(client))) 17411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto exitfree; 17421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 17431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Set the VRM version */ 1744303760b44a7a142cb9f4c9df4609fb63bbda98dbJean Delvare data->vrm = vid_which_vrm(); 17451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 17461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Initialize the ADM1026 chip */ 1747f67fdabfb94b0bb96623a4b48d22be5329a06277Jean Delvare adm1026_init_client(client); 17481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 17491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Register sysfs hooks */ 1750f67fdabfb94b0bb96623a4b48d22be5329a06277Jean Delvare if ((err = sysfs_create_group(&client->dev.kobj, &adm1026_group))) 1751681c6f7a6702f208d48b501c8829dbc03a2ca238Mark M. Hoffman goto exitdetach; 17525b34dbcd88251508d02e48ad9b0f9b8232a13ee0Jean Delvare if (data->config1 & CFG1_AIN8_9) 17535b34dbcd88251508d02e48ad9b0f9b8232a13ee0Jean Delvare err = sysfs_create_group(&client->dev.kobj, 17545b34dbcd88251508d02e48ad9b0f9b8232a13ee0Jean Delvare &adm1026_group_in8_9); 17555b34dbcd88251508d02e48ad9b0f9b8232a13ee0Jean Delvare else 17565b34dbcd88251508d02e48ad9b0f9b8232a13ee0Jean Delvare err = sysfs_create_group(&client->dev.kobj, 17575b34dbcd88251508d02e48ad9b0f9b8232a13ee0Jean Delvare &adm1026_group_temp3); 17585b34dbcd88251508d02e48ad9b0f9b8232a13ee0Jean Delvare if (err) 17595b34dbcd88251508d02e48ad9b0f9b8232a13ee0Jean Delvare goto exitremove; 1760681c6f7a6702f208d48b501c8829dbc03a2ca238Mark M. Hoffman 1761f67fdabfb94b0bb96623a4b48d22be5329a06277Jean Delvare data->hwmon_dev = hwmon_device_register(&client->dev); 17621beeffe43311f64df8dd0ab08ff6b1858c58363fTony Jones if (IS_ERR(data->hwmon_dev)) { 17631beeffe43311f64df8dd0ab08ff6b1858c58363fTony Jones err = PTR_ERR(data->hwmon_dev); 1764681c6f7a6702f208d48b501c8829dbc03a2ca238Mark M. Hoffman goto exitremove; 1765943b0830cebe4711354945ed3cb44e84152aaca0Mark M. Hoffman } 1766943b0830cebe4711354945ed3cb44e84152aaca0Mark M. Hoffman 17671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; 17681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 17691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Error out and cleanup code */ 1770681c6f7a6702f208d48b501c8829dbc03a2ca238Mark M. Hoffmanexitremove: 1771f67fdabfb94b0bb96623a4b48d22be5329a06277Jean Delvare sysfs_remove_group(&client->dev.kobj, &adm1026_group); 17725b34dbcd88251508d02e48ad9b0f9b8232a13ee0Jean Delvare if (data->config1 & CFG1_AIN8_9) 17735b34dbcd88251508d02e48ad9b0f9b8232a13ee0Jean Delvare sysfs_remove_group(&client->dev.kobj, &adm1026_group_in8_9); 17745b34dbcd88251508d02e48ad9b0f9b8232a13ee0Jean Delvare else 17755b34dbcd88251508d02e48ad9b0f9b8232a13ee0Jean Delvare sysfs_remove_group(&client->dev.kobj, &adm1026_group_temp3); 1776943b0830cebe4711354945ed3cb44e84152aaca0Mark M. Hoffmanexitdetach: 1777f67fdabfb94b0bb96623a4b48d22be5329a06277Jean Delvare i2c_detach_client(client); 17781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsexitfree: 17791f57ff89fee47a317e9e8ca63bf0f139802cc116Alexey Dobriyan kfree(data); 17801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsexit: 17811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return err; 17821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 1783681c6f7a6702f208d48b501c8829dbc03a2ca238Mark M. Hoffman 1784681c6f7a6702f208d48b501c8829dbc03a2ca238Mark M. Hoffmanstatic int adm1026_detach_client(struct i2c_client *client) 1785681c6f7a6702f208d48b501c8829dbc03a2ca238Mark M. Hoffman{ 1786681c6f7a6702f208d48b501c8829dbc03a2ca238Mark M. Hoffman struct adm1026_data *data = i2c_get_clientdata(client); 17871beeffe43311f64df8dd0ab08ff6b1858c58363fTony Jones hwmon_device_unregister(data->hwmon_dev); 1788681c6f7a6702f208d48b501c8829dbc03a2ca238Mark M. Hoffman sysfs_remove_group(&client->dev.kobj, &adm1026_group); 17895b34dbcd88251508d02e48ad9b0f9b8232a13ee0Jean Delvare if (data->config1 & CFG1_AIN8_9) 17905b34dbcd88251508d02e48ad9b0f9b8232a13ee0Jean Delvare sysfs_remove_group(&client->dev.kobj, &adm1026_group_in8_9); 17915b34dbcd88251508d02e48ad9b0f9b8232a13ee0Jean Delvare else 17925b34dbcd88251508d02e48ad9b0f9b8232a13ee0Jean Delvare sysfs_remove_group(&client->dev.kobj, &adm1026_group_temp3); 1793681c6f7a6702f208d48b501c8829dbc03a2ca238Mark M. Hoffman i2c_detach_client(client); 1794681c6f7a6702f208d48b501c8829dbc03a2ca238Mark M. Hoffman kfree(data); 1795681c6f7a6702f208d48b501c8829dbc03a2ca238Mark M. Hoffman return 0; 1796681c6f7a6702f208d48b501c8829dbc03a2ca238Mark M. Hoffman} 1797681c6f7a6702f208d48b501c8829dbc03a2ca238Mark M. Hoffman 17981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int __init sm_adm1026_init(void) 17991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 18001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return i2c_add_driver(&adm1026_driver); 18011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 18021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1803cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvarestatic void __exit sm_adm1026_exit(void) 18041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 18051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds i2c_del_driver(&adm1026_driver); 18061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 18071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 18081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsMODULE_LICENSE("GPL"); 18091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsMODULE_AUTHOR("Philip Pokorny <ppokorny@penguincomputing.com>, " 1810cb01a2312f56c93d2740e827718966b92b7cbb91Jean Delvare "Justin Thiessen <jthiessen@penguincomputing.com>"); 18111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsMODULE_DESCRIPTION("ADM1026 driver"); 18121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 18131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsmodule_init(sm_adm1026_init); 18141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsmodule_exit(sm_adm1026_exit); 1815