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