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