1c0b4e3abSDarrick J. Wong /* 2c0b4e3abSDarrick J. Wong * A hwmon driver for the Analog Devices ADT7462 3c0b4e3abSDarrick J. Wong * Copyright (C) 2008 IBM 4c0b4e3abSDarrick J. Wong * 5c0b4e3abSDarrick J. Wong * Author: Darrick J. Wong <djwong@us.ibm.com> 6c0b4e3abSDarrick J. Wong * 7c0b4e3abSDarrick J. Wong * This program is free software; you can redistribute it and/or modify 8c0b4e3abSDarrick J. Wong * it under the terms of the GNU General Public License as published by 9c0b4e3abSDarrick J. Wong * the Free Software Foundation; either version 2 of the License, or 10c0b4e3abSDarrick J. Wong * (at your option) any later version. 11c0b4e3abSDarrick J. Wong * 12c0b4e3abSDarrick J. Wong * This program is distributed in the hope that it will be useful, 13c0b4e3abSDarrick J. Wong * but WITHOUT ANY WARRANTY; without even the implied warranty of 14c0b4e3abSDarrick J. Wong * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15c0b4e3abSDarrick J. Wong * GNU General Public License for more details. 16c0b4e3abSDarrick J. Wong * 17c0b4e3abSDarrick J. Wong * You should have received a copy of the GNU General Public License 18c0b4e3abSDarrick J. Wong * along with this program; if not, write to the Free Software 19c0b4e3abSDarrick J. Wong * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 20c0b4e3abSDarrick J. Wong */ 21c0b4e3abSDarrick J. Wong 22c0b4e3abSDarrick J. Wong #include <linux/module.h> 23c0b4e3abSDarrick J. Wong #include <linux/jiffies.h> 24c0b4e3abSDarrick J. Wong #include <linux/i2c.h> 25c0b4e3abSDarrick J. Wong #include <linux/hwmon.h> 26c0b4e3abSDarrick J. Wong #include <linux/hwmon-sysfs.h> 27c0b4e3abSDarrick J. Wong #include <linux/err.h> 28c0b4e3abSDarrick J. Wong #include <linux/mutex.h> 29c0b4e3abSDarrick J. Wong #include <linux/delay.h> 30c0b4e3abSDarrick J. Wong #include <linux/log2.h> 315a0e3ad6STejun Heo #include <linux/slab.h> 32c0b4e3abSDarrick J. Wong 33c0b4e3abSDarrick J. Wong /* Addresses to scan */ 34c0b4e3abSDarrick J. Wong static const unsigned short normal_i2c[] = { 0x58, 0x5C, I2C_CLIENT_END }; 35c0b4e3abSDarrick J. Wong 36c0b4e3abSDarrick J. Wong /* ADT7462 registers */ 37c0b4e3abSDarrick J. Wong #define ADT7462_REG_DEVICE 0x3D 38c0b4e3abSDarrick J. Wong #define ADT7462_REG_VENDOR 0x3E 39c0b4e3abSDarrick J. Wong #define ADT7462_REG_REVISION 0x3F 40c0b4e3abSDarrick J. Wong 41c0b4e3abSDarrick J. Wong #define ADT7462_REG_MIN_TEMP_BASE_ADDR 0x44 42c0b4e3abSDarrick J. Wong #define ADT7462_REG_MIN_TEMP_MAX_ADDR 0x47 43c0b4e3abSDarrick J. Wong #define ADT7462_REG_MAX_TEMP_BASE_ADDR 0x48 44c0b4e3abSDarrick J. Wong #define ADT7462_REG_MAX_TEMP_MAX_ADDR 0x4B 45c0b4e3abSDarrick J. Wong #define ADT7462_REG_TEMP_BASE_ADDR 0x88 46c0b4e3abSDarrick J. Wong #define ADT7462_REG_TEMP_MAX_ADDR 0x8F 47c0b4e3abSDarrick J. Wong 48c0b4e3abSDarrick J. Wong #define ADT7462_REG_FAN_BASE_ADDR 0x98 49c0b4e3abSDarrick J. Wong #define ADT7462_REG_FAN_MAX_ADDR 0x9F 50c0b4e3abSDarrick J. Wong #define ADT7462_REG_FAN2_BASE_ADDR 0xA2 51c0b4e3abSDarrick J. Wong #define ADT7462_REG_FAN2_MAX_ADDR 0xA9 52c0b4e3abSDarrick J. Wong #define ADT7462_REG_FAN_ENABLE 0x07 53c0b4e3abSDarrick J. Wong #define ADT7462_REG_FAN_MIN_BASE_ADDR 0x78 54c0b4e3abSDarrick J. Wong #define ADT7462_REG_FAN_MIN_MAX_ADDR 0x7F 55c0b4e3abSDarrick J. Wong 56c0b4e3abSDarrick J. Wong #define ADT7462_REG_CFG2 0x02 57c0b4e3abSDarrick J. Wong #define ADT7462_FSPD_MASK 0x20 58c0b4e3abSDarrick J. Wong 59c0b4e3abSDarrick J. Wong #define ADT7462_REG_PWM_BASE_ADDR 0xAA 60c0b4e3abSDarrick J. Wong #define ADT7462_REG_PWM_MAX_ADDR 0xAD 61c0b4e3abSDarrick J. Wong #define ADT7462_REG_PWM_MIN_BASE_ADDR 0x28 62c0b4e3abSDarrick J. Wong #define ADT7462_REG_PWM_MIN_MAX_ADDR 0x2B 63c0b4e3abSDarrick J. Wong #define ADT7462_REG_PWM_MAX 0x2C 64c0b4e3abSDarrick J. Wong #define ADT7462_REG_PWM_TEMP_MIN_BASE_ADDR 0x5C 65c0b4e3abSDarrick J. Wong #define ADT7462_REG_PWM_TEMP_MIN_MAX_ADDR 0x5F 66c0b4e3abSDarrick J. Wong #define ADT7462_REG_PWM_TEMP_RANGE_BASE_ADDR 0x60 67c0b4e3abSDarrick J. Wong #define ADT7462_REG_PWM_TEMP_RANGE_MAX_ADDR 0x63 68c0b4e3abSDarrick J. Wong #define ADT7462_PWM_HYST_MASK 0x0F 69c0b4e3abSDarrick J. Wong #define ADT7462_PWM_RANGE_MASK 0xF0 70c0b4e3abSDarrick J. Wong #define ADT7462_PWM_RANGE_SHIFT 4 71c0b4e3abSDarrick J. Wong #define ADT7462_REG_PWM_CFG_BASE_ADDR 0x21 72c0b4e3abSDarrick J. Wong #define ADT7462_REG_PWM_CFG_MAX_ADDR 0x24 73c0b4e3abSDarrick J. Wong #define ADT7462_PWM_CHANNEL_MASK 0xE0 74c0b4e3abSDarrick J. Wong #define ADT7462_PWM_CHANNEL_SHIFT 5 75c0b4e3abSDarrick J. Wong 76c0b4e3abSDarrick J. Wong #define ADT7462_REG_PIN_CFG_BASE_ADDR 0x10 77c0b4e3abSDarrick J. Wong #define ADT7462_REG_PIN_CFG_MAX_ADDR 0x13 78c0b4e3abSDarrick J. Wong #define ADT7462_PIN7_INPUT 0x01 /* cfg0 */ 79c0b4e3abSDarrick J. Wong #define ADT7462_DIODE3_INPUT 0x20 80c0b4e3abSDarrick J. Wong #define ADT7462_DIODE1_INPUT 0x40 81c0b4e3abSDarrick J. Wong #define ADT7462_VID_INPUT 0x80 82c0b4e3abSDarrick J. Wong #define ADT7462_PIN22_INPUT 0x04 /* cfg1 */ 83c0b4e3abSDarrick J. Wong #define ADT7462_PIN21_INPUT 0x08 84c0b4e3abSDarrick J. Wong #define ADT7462_PIN19_INPUT 0x10 85c0b4e3abSDarrick J. Wong #define ADT7462_PIN15_INPUT 0x20 86c0b4e3abSDarrick J. Wong #define ADT7462_PIN13_INPUT 0x40 87c0b4e3abSDarrick J. Wong #define ADT7462_PIN8_INPUT 0x80 88c0b4e3abSDarrick J. Wong #define ADT7462_PIN23_MASK 0x03 89c0b4e3abSDarrick J. Wong #define ADT7462_PIN23_SHIFT 0 90c0b4e3abSDarrick J. Wong #define ADT7462_PIN26_MASK 0x0C /* cfg2 */ 91c0b4e3abSDarrick J. Wong #define ADT7462_PIN26_SHIFT 2 92c0b4e3abSDarrick J. Wong #define ADT7462_PIN25_MASK 0x30 93c0b4e3abSDarrick J. Wong #define ADT7462_PIN25_SHIFT 4 94c0b4e3abSDarrick J. Wong #define ADT7462_PIN24_MASK 0xC0 95c0b4e3abSDarrick J. Wong #define ADT7462_PIN24_SHIFT 6 96c0b4e3abSDarrick J. Wong #define ADT7462_PIN26_VOLT_INPUT 0x08 97c0b4e3abSDarrick J. Wong #define ADT7462_PIN25_VOLT_INPUT 0x20 98bb595c92SRoger Blofeld #define ADT7462_PIN28_SHIFT 4 /* cfg3 */ 99c0b4e3abSDarrick J. Wong #define ADT7462_PIN28_VOLT 0x5 100c0b4e3abSDarrick J. Wong 101c0b4e3abSDarrick J. Wong #define ADT7462_REG_ALARM1 0xB8 102c0b4e3abSDarrick J. Wong #define ADT7462_LT_ALARM 0x02 103c0b4e3abSDarrick J. Wong #define ADT7462_R1T_ALARM 0x04 104c0b4e3abSDarrick J. Wong #define ADT7462_R2T_ALARM 0x08 105c0b4e3abSDarrick J. Wong #define ADT7462_R3T_ALARM 0x10 106c0b4e3abSDarrick J. Wong #define ADT7462_REG_ALARM2 0xBB 107c0b4e3abSDarrick J. Wong #define ADT7462_V0_ALARM 0x01 108c0b4e3abSDarrick J. Wong #define ADT7462_V1_ALARM 0x02 109c0b4e3abSDarrick J. Wong #define ADT7462_V2_ALARM 0x04 110c0b4e3abSDarrick J. Wong #define ADT7462_V3_ALARM 0x08 111c0b4e3abSDarrick J. Wong #define ADT7462_V4_ALARM 0x10 112c0b4e3abSDarrick J. Wong #define ADT7462_V5_ALARM 0x20 113c0b4e3abSDarrick J. Wong #define ADT7462_V6_ALARM 0x40 114c0b4e3abSDarrick J. Wong #define ADT7462_V7_ALARM 0x80 115c0b4e3abSDarrick J. Wong #define ADT7462_REG_ALARM3 0xBC 116c0b4e3abSDarrick J. Wong #define ADT7462_V8_ALARM 0x08 117c0b4e3abSDarrick J. Wong #define ADT7462_V9_ALARM 0x10 118c0b4e3abSDarrick J. Wong #define ADT7462_V10_ALARM 0x20 119c0b4e3abSDarrick J. Wong #define ADT7462_V11_ALARM 0x40 120c0b4e3abSDarrick J. Wong #define ADT7462_V12_ALARM 0x80 121c0b4e3abSDarrick J. Wong #define ADT7462_REG_ALARM4 0xBD 122c0b4e3abSDarrick J. Wong #define ADT7462_F0_ALARM 0x01 123c0b4e3abSDarrick J. Wong #define ADT7462_F1_ALARM 0x02 124c0b4e3abSDarrick J. Wong #define ADT7462_F2_ALARM 0x04 125c0b4e3abSDarrick J. Wong #define ADT7462_F3_ALARM 0x08 126c0b4e3abSDarrick J. Wong #define ADT7462_F4_ALARM 0x10 127c0b4e3abSDarrick J. Wong #define ADT7462_F5_ALARM 0x20 128c0b4e3abSDarrick J. Wong #define ADT7462_F6_ALARM 0x40 129c0b4e3abSDarrick J. Wong #define ADT7462_F7_ALARM 0x80 130c0b4e3abSDarrick J. Wong #define ADT7462_ALARM1 0x0000 131c0b4e3abSDarrick J. Wong #define ADT7462_ALARM2 0x0100 132c0b4e3abSDarrick J. Wong #define ADT7462_ALARM3 0x0200 133c0b4e3abSDarrick J. Wong #define ADT7462_ALARM4 0x0300 134c0b4e3abSDarrick J. Wong #define ADT7462_ALARM_REG_SHIFT 8 135c0b4e3abSDarrick J. Wong #define ADT7462_ALARM_FLAG_MASK 0x0F 136c0b4e3abSDarrick J. Wong 137c0b4e3abSDarrick J. Wong #define ADT7462_TEMP_COUNT 4 138724cc331SGuenter Roeck #define ADT7462_TEMP_REG(x) (ADT7462_REG_TEMP_BASE_ADDR + ((x) * 2)) 139c0b4e3abSDarrick J. Wong #define ADT7462_TEMP_MIN_REG(x) (ADT7462_REG_MIN_TEMP_BASE_ADDR + (x)) 140c0b4e3abSDarrick J. Wong #define ADT7462_TEMP_MAX_REG(x) (ADT7462_REG_MAX_TEMP_BASE_ADDR + (x)) 141c0b4e3abSDarrick J. Wong #define TEMP_FRAC_OFFSET 6 142c0b4e3abSDarrick J. Wong 143c0b4e3abSDarrick J. Wong #define ADT7462_FAN_COUNT 8 144c0b4e3abSDarrick J. Wong #define ADT7462_REG_FAN_MIN(x) (ADT7462_REG_FAN_MIN_BASE_ADDR + (x)) 145c0b4e3abSDarrick J. Wong 146c0b4e3abSDarrick J. Wong #define ADT7462_PWM_COUNT 4 147c0b4e3abSDarrick J. Wong #define ADT7462_REG_PWM(x) (ADT7462_REG_PWM_BASE_ADDR + (x)) 148c0b4e3abSDarrick J. Wong #define ADT7462_REG_PWM_MIN(x) (ADT7462_REG_PWM_MIN_BASE_ADDR + (x)) 149c0b4e3abSDarrick J. Wong #define ADT7462_REG_PWM_TMIN(x) \ 150c0b4e3abSDarrick J. Wong (ADT7462_REG_PWM_TEMP_MIN_BASE_ADDR + (x)) 151c0b4e3abSDarrick J. Wong #define ADT7462_REG_PWM_TRANGE(x) \ 152c0b4e3abSDarrick J. Wong (ADT7462_REG_PWM_TEMP_RANGE_BASE_ADDR + (x)) 153c0b4e3abSDarrick J. Wong 154c0b4e3abSDarrick J. Wong #define ADT7462_PIN_CFG_REG_COUNT 4 155c0b4e3abSDarrick J. Wong #define ADT7462_REG_PIN_CFG(x) (ADT7462_REG_PIN_CFG_BASE_ADDR + (x)) 156c0b4e3abSDarrick J. Wong #define ADT7462_REG_PWM_CFG(x) (ADT7462_REG_PWM_CFG_BASE_ADDR + (x)) 157c0b4e3abSDarrick J. Wong 158c0b4e3abSDarrick J. Wong #define ADT7462_ALARM_REG_COUNT 4 159c0b4e3abSDarrick J. Wong 160c0b4e3abSDarrick J. Wong /* 161c0b4e3abSDarrick J. Wong * The chip can measure 13 different voltage sources: 162c0b4e3abSDarrick J. Wong * 163c0b4e3abSDarrick J. Wong * 1. +12V1 (pin 7) 164c0b4e3abSDarrick J. Wong * 2. Vccp1/+2.5V/+1.8V/+1.5V (pin 23) 165c0b4e3abSDarrick J. Wong * 3. +12V3 (pin 22) 166c0b4e3abSDarrick J. Wong * 4. +5V (pin 21) 167c0b4e3abSDarrick J. Wong * 5. +1.25V/+0.9V (pin 19) 168c0b4e3abSDarrick J. Wong * 6. +2.5V/+1.8V (pin 15) 169c0b4e3abSDarrick J. Wong * 7. +3.3v (pin 13) 170c0b4e3abSDarrick J. Wong * 8. +12V2 (pin 8) 171c0b4e3abSDarrick J. Wong * 9. Vbatt/FSB_Vtt (pin 26) 172c0b4e3abSDarrick J. Wong * A. +3.3V/+1.2V1 (pin 25) 173c0b4e3abSDarrick J. Wong * B. Vccp2/+2.5V/+1.8V/+1.5V (pin 24) 174c0b4e3abSDarrick J. Wong * C. +1.5V ICH (only if BOTH pin 28/29 are set to +1.5V) 175c0b4e3abSDarrick J. Wong * D. +1.5V 3GPIO (only if BOTH pin 28/29 are set to +1.5V) 176c0b4e3abSDarrick J. Wong * 177c0b4e3abSDarrick J. Wong * Each of these 13 has a factor to convert raw to voltage. Even better, 178c0b4e3abSDarrick J. Wong * the pins can be connected to other sensors (tach/gpio/hot/etc), which 179c0b4e3abSDarrick J. Wong * makes the bookkeeping tricky. 180c0b4e3abSDarrick J. Wong * 181c0b4e3abSDarrick J. Wong * Some, but not all, of these voltages have low/high limits. 182c0b4e3abSDarrick J. Wong */ 18385f8d3e5SRay Copeland #define ADT7462_VOLT_COUNT 13 184c0b4e3abSDarrick J. Wong 185c0b4e3abSDarrick J. Wong #define ADT7462_VENDOR 0x41 186c0b4e3abSDarrick J. Wong #define ADT7462_DEVICE 0x62 187c0b4e3abSDarrick J. Wong /* datasheet only mentions a revision 4 */ 188c0b4e3abSDarrick J. Wong #define ADT7462_REVISION 0x04 189c0b4e3abSDarrick J. Wong 190c0b4e3abSDarrick J. Wong /* How often do we reread sensors values? (In jiffies) */ 191c0b4e3abSDarrick J. Wong #define SENSOR_REFRESH_INTERVAL (2 * HZ) 192c0b4e3abSDarrick J. Wong 193c0b4e3abSDarrick J. Wong /* How often do we reread sensor limit values? (In jiffies) */ 194c0b4e3abSDarrick J. Wong #define LIMIT_REFRESH_INTERVAL (60 * HZ) 195c0b4e3abSDarrick J. Wong 196c0b4e3abSDarrick J. Wong /* datasheet says to divide this number by the fan reading to get fan rpm */ 197c0b4e3abSDarrick J. Wong #define FAN_PERIOD_TO_RPM(x) ((90000 * 60) / (x)) 198c0b4e3abSDarrick J. Wong #define FAN_RPM_TO_PERIOD FAN_PERIOD_TO_RPM 199c0b4e3abSDarrick J. Wong #define FAN_PERIOD_INVALID 65535 200c0b4e3abSDarrick J. Wong #define FAN_DATA_VALID(x) ((x) && (x) != FAN_PERIOD_INVALID) 201c0b4e3abSDarrick J. Wong 202c0b4e3abSDarrick J. Wong #define MASK_AND_SHIFT(value, prefix) \ 203c0b4e3abSDarrick J. Wong (((value) & prefix##_MASK) >> prefix##_SHIFT) 204c0b4e3abSDarrick J. Wong 205c0b4e3abSDarrick J. Wong struct adt7462_data { 206c0b4e3abSDarrick J. Wong struct device *hwmon_dev; 207c0b4e3abSDarrick J. Wong struct attribute_group attrs; 208c0b4e3abSDarrick J. Wong struct mutex lock; 209c0b4e3abSDarrick J. Wong char sensors_valid; 210c0b4e3abSDarrick J. Wong char limits_valid; 211c0b4e3abSDarrick J. Wong unsigned long sensors_last_updated; /* In jiffies */ 212c0b4e3abSDarrick J. Wong unsigned long limits_last_updated; /* In jiffies */ 213c0b4e3abSDarrick J. Wong 214c0b4e3abSDarrick J. Wong u8 temp[ADT7462_TEMP_COUNT]; 215c0b4e3abSDarrick J. Wong /* bits 6-7 are quarter pieces of temp */ 216c0b4e3abSDarrick J. Wong u8 temp_frac[ADT7462_TEMP_COUNT]; 217c0b4e3abSDarrick J. Wong u8 temp_min[ADT7462_TEMP_COUNT]; 218c0b4e3abSDarrick J. Wong u8 temp_max[ADT7462_TEMP_COUNT]; 219c0b4e3abSDarrick J. Wong u16 fan[ADT7462_FAN_COUNT]; 220c0b4e3abSDarrick J. Wong u8 fan_enabled; 221c0b4e3abSDarrick J. Wong u8 fan_min[ADT7462_FAN_COUNT]; 222c0b4e3abSDarrick J. Wong u8 cfg2; 223c0b4e3abSDarrick J. Wong u8 pwm[ADT7462_PWM_COUNT]; 224c0b4e3abSDarrick J. Wong u8 pin_cfg[ADT7462_PIN_CFG_REG_COUNT]; 225c0b4e3abSDarrick J. Wong u8 voltages[ADT7462_VOLT_COUNT]; 226c0b4e3abSDarrick J. Wong u8 volt_max[ADT7462_VOLT_COUNT]; 227c0b4e3abSDarrick J. Wong u8 volt_min[ADT7462_VOLT_COUNT]; 228c0b4e3abSDarrick J. Wong u8 pwm_min[ADT7462_PWM_COUNT]; 229c0b4e3abSDarrick J. Wong u8 pwm_tmin[ADT7462_PWM_COUNT]; 230c0b4e3abSDarrick J. Wong u8 pwm_trange[ADT7462_PWM_COUNT]; 231c0b4e3abSDarrick J. Wong u8 pwm_max; /* only one per chip */ 232c0b4e3abSDarrick J. Wong u8 pwm_cfg[ADT7462_PWM_COUNT]; 233c0b4e3abSDarrick J. Wong u8 alarms[ADT7462_ALARM_REG_COUNT]; 234c0b4e3abSDarrick J. Wong }; 235c0b4e3abSDarrick J. Wong 236c0b4e3abSDarrick J. Wong static int adt7462_probe(struct i2c_client *client, 237c0b4e3abSDarrick J. Wong const struct i2c_device_id *id); 238310ec792SJean Delvare static int adt7462_detect(struct i2c_client *client, 239c0b4e3abSDarrick J. Wong struct i2c_board_info *info); 240c0b4e3abSDarrick J. Wong static int adt7462_remove(struct i2c_client *client); 241c0b4e3abSDarrick J. Wong 242c0b4e3abSDarrick J. Wong static const struct i2c_device_id adt7462_id[] = { 2431f86df49SJean Delvare { "adt7462", 0 }, 244c0b4e3abSDarrick J. Wong { } 245c0b4e3abSDarrick J. Wong }; 246c0b4e3abSDarrick J. Wong MODULE_DEVICE_TABLE(i2c, adt7462_id); 247c0b4e3abSDarrick J. Wong 248c0b4e3abSDarrick J. Wong static struct i2c_driver adt7462_driver = { 249c0b4e3abSDarrick J. Wong .class = I2C_CLASS_HWMON, 250c0b4e3abSDarrick J. Wong .driver = { 251c0b4e3abSDarrick J. Wong .name = "adt7462", 252c0b4e3abSDarrick J. Wong }, 253c0b4e3abSDarrick J. Wong .probe = adt7462_probe, 254c0b4e3abSDarrick J. Wong .remove = adt7462_remove, 255c0b4e3abSDarrick J. Wong .id_table = adt7462_id, 256c0b4e3abSDarrick J. Wong .detect = adt7462_detect, 257c3813d6aSJean Delvare .address_list = normal_i2c, 258c0b4e3abSDarrick J. Wong }; 259c0b4e3abSDarrick J. Wong 260c0b4e3abSDarrick J. Wong /* 261c0b4e3abSDarrick J. Wong * 16-bit registers on the ADT7462 are low-byte first. The data sheet says 262c0b4e3abSDarrick J. Wong * that the low byte must be read before the high byte. 263c0b4e3abSDarrick J. Wong */ 264c0b4e3abSDarrick J. Wong static inline int adt7462_read_word_data(struct i2c_client *client, u8 reg) 265c0b4e3abSDarrick J. Wong { 266c0b4e3abSDarrick J. Wong u16 foo; 267c0b4e3abSDarrick J. Wong foo = i2c_smbus_read_byte_data(client, reg); 268c0b4e3abSDarrick J. Wong foo |= ((u16)i2c_smbus_read_byte_data(client, reg + 1) << 8); 269c0b4e3abSDarrick J. Wong return foo; 270c0b4e3abSDarrick J. Wong } 271c0b4e3abSDarrick J. Wong 272c0b4e3abSDarrick J. Wong /* For some reason these registers are not contiguous. */ 273c0b4e3abSDarrick J. Wong static int ADT7462_REG_FAN(int fan) 274c0b4e3abSDarrick J. Wong { 275c0b4e3abSDarrick J. Wong if (fan < 4) 276c0b4e3abSDarrick J. Wong return ADT7462_REG_FAN_BASE_ADDR + (2 * fan); 277c0b4e3abSDarrick J. Wong return ADT7462_REG_FAN2_BASE_ADDR + (2 * (fan - 4)); 278c0b4e3abSDarrick J. Wong } 279c0b4e3abSDarrick J. Wong 280c0b4e3abSDarrick J. Wong /* Voltage registers are scattered everywhere */ 281c0b4e3abSDarrick J. Wong static int ADT7462_REG_VOLT_MAX(struct adt7462_data *data, int which) 282c0b4e3abSDarrick J. Wong { 283c0b4e3abSDarrick J. Wong switch (which) { 284c0b4e3abSDarrick J. Wong case 0: 285c0b4e3abSDarrick J. Wong if (!(data->pin_cfg[0] & ADT7462_PIN7_INPUT)) 286c0b4e3abSDarrick J. Wong return 0x7C; 287c0b4e3abSDarrick J. Wong break; 288c0b4e3abSDarrick J. Wong case 1: 289c0b4e3abSDarrick J. Wong return 0x69; 290c0b4e3abSDarrick J. Wong case 2: 291c0b4e3abSDarrick J. Wong if (!(data->pin_cfg[1] & ADT7462_PIN22_INPUT)) 292c0b4e3abSDarrick J. Wong return 0x7F; 293c0b4e3abSDarrick J. Wong break; 294c0b4e3abSDarrick J. Wong case 3: 295c0b4e3abSDarrick J. Wong if (!(data->pin_cfg[1] & ADT7462_PIN21_INPUT)) 296c0b4e3abSDarrick J. Wong return 0x7E; 297c0b4e3abSDarrick J. Wong break; 298c0b4e3abSDarrick J. Wong case 4: 299c0b4e3abSDarrick J. Wong if (!(data->pin_cfg[0] & ADT7462_DIODE3_INPUT)) 300c0b4e3abSDarrick J. Wong return 0x4B; 301c0b4e3abSDarrick J. Wong break; 302c0b4e3abSDarrick J. Wong case 5: 303c0b4e3abSDarrick J. Wong if (!(data->pin_cfg[0] & ADT7462_DIODE1_INPUT)) 304c0b4e3abSDarrick J. Wong return 0x49; 305c0b4e3abSDarrick J. Wong break; 306c0b4e3abSDarrick J. Wong case 6: 307c0b4e3abSDarrick J. Wong if (!(data->pin_cfg[1] & ADT7462_PIN13_INPUT)) 308c0b4e3abSDarrick J. Wong return 0x68; 309c0b4e3abSDarrick J. Wong break; 310c0b4e3abSDarrick J. Wong case 7: 311c0b4e3abSDarrick J. Wong if (!(data->pin_cfg[1] & ADT7462_PIN8_INPUT)) 312c0b4e3abSDarrick J. Wong return 0x7D; 313c0b4e3abSDarrick J. Wong break; 314c0b4e3abSDarrick J. Wong case 8: 315c0b4e3abSDarrick J. Wong if (!(data->pin_cfg[2] & ADT7462_PIN26_VOLT_INPUT)) 316c0b4e3abSDarrick J. Wong return 0x6C; 317c0b4e3abSDarrick J. Wong break; 318c0b4e3abSDarrick J. Wong case 9: 319c0b4e3abSDarrick J. Wong if (!(data->pin_cfg[2] & ADT7462_PIN25_VOLT_INPUT)) 320c0b4e3abSDarrick J. Wong return 0x6B; 321c0b4e3abSDarrick J. Wong break; 322c0b4e3abSDarrick J. Wong case 10: 323c0b4e3abSDarrick J. Wong return 0x6A; 324c0b4e3abSDarrick J. Wong case 11: 325c0b4e3abSDarrick J. Wong if (data->pin_cfg[3] >> ADT7462_PIN28_SHIFT == 326c0b4e3abSDarrick J. Wong ADT7462_PIN28_VOLT && 327c0b4e3abSDarrick J. Wong !(data->pin_cfg[0] & ADT7462_VID_INPUT)) 328c0b4e3abSDarrick J. Wong return 0x50; 329c0b4e3abSDarrick J. Wong break; 330c0b4e3abSDarrick J. Wong case 12: 331c0b4e3abSDarrick J. Wong if (data->pin_cfg[3] >> ADT7462_PIN28_SHIFT == 332c0b4e3abSDarrick J. Wong ADT7462_PIN28_VOLT && 333c0b4e3abSDarrick J. Wong !(data->pin_cfg[0] & ADT7462_VID_INPUT)) 334c0b4e3abSDarrick J. Wong return 0x4C; 335c0b4e3abSDarrick J. Wong break; 336c0b4e3abSDarrick J. Wong } 337c0b4e3abSDarrick J. Wong return -ENODEV; 338c0b4e3abSDarrick J. Wong } 339c0b4e3abSDarrick J. Wong 340c0b4e3abSDarrick J. Wong static int ADT7462_REG_VOLT_MIN(struct adt7462_data *data, int which) 341c0b4e3abSDarrick J. Wong { 342c0b4e3abSDarrick J. Wong switch (which) { 343c0b4e3abSDarrick J. Wong case 0: 344c0b4e3abSDarrick J. Wong if (!(data->pin_cfg[0] & ADT7462_PIN7_INPUT)) 345c0b4e3abSDarrick J. Wong return 0x6D; 346c0b4e3abSDarrick J. Wong break; 347c0b4e3abSDarrick J. Wong case 1: 348c0b4e3abSDarrick J. Wong return 0x72; 349c0b4e3abSDarrick J. Wong case 2: 350c0b4e3abSDarrick J. Wong if (!(data->pin_cfg[1] & ADT7462_PIN22_INPUT)) 351c0b4e3abSDarrick J. Wong return 0x6F; 352c0b4e3abSDarrick J. Wong break; 353c0b4e3abSDarrick J. Wong case 3: 354c0b4e3abSDarrick J. Wong if (!(data->pin_cfg[1] & ADT7462_PIN21_INPUT)) 355c0b4e3abSDarrick J. Wong return 0x71; 356c0b4e3abSDarrick J. Wong break; 357c0b4e3abSDarrick J. Wong case 4: 358c0b4e3abSDarrick J. Wong if (!(data->pin_cfg[0] & ADT7462_DIODE3_INPUT)) 359c0b4e3abSDarrick J. Wong return 0x47; 360c0b4e3abSDarrick J. Wong break; 361c0b4e3abSDarrick J. Wong case 5: 362c0b4e3abSDarrick J. Wong if (!(data->pin_cfg[0] & ADT7462_DIODE1_INPUT)) 363c0b4e3abSDarrick J. Wong return 0x45; 364c0b4e3abSDarrick J. Wong break; 365c0b4e3abSDarrick J. Wong case 6: 366c0b4e3abSDarrick J. Wong if (!(data->pin_cfg[1] & ADT7462_PIN13_INPUT)) 367c0b4e3abSDarrick J. Wong return 0x70; 368c0b4e3abSDarrick J. Wong break; 369c0b4e3abSDarrick J. Wong case 7: 370c0b4e3abSDarrick J. Wong if (!(data->pin_cfg[1] & ADT7462_PIN8_INPUT)) 371c0b4e3abSDarrick J. Wong return 0x6E; 372c0b4e3abSDarrick J. Wong break; 373c0b4e3abSDarrick J. Wong case 8: 374c0b4e3abSDarrick J. Wong if (!(data->pin_cfg[2] & ADT7462_PIN26_VOLT_INPUT)) 375c0b4e3abSDarrick J. Wong return 0x75; 376c0b4e3abSDarrick J. Wong break; 377c0b4e3abSDarrick J. Wong case 9: 378c0b4e3abSDarrick J. Wong if (!(data->pin_cfg[2] & ADT7462_PIN25_VOLT_INPUT)) 379c0b4e3abSDarrick J. Wong return 0x74; 380c0b4e3abSDarrick J. Wong break; 381c0b4e3abSDarrick J. Wong case 10: 382c0b4e3abSDarrick J. Wong return 0x73; 383c0b4e3abSDarrick J. Wong case 11: 384c0b4e3abSDarrick J. Wong if (data->pin_cfg[3] >> ADT7462_PIN28_SHIFT == 385c0b4e3abSDarrick J. Wong ADT7462_PIN28_VOLT && 386c0b4e3abSDarrick J. Wong !(data->pin_cfg[0] & ADT7462_VID_INPUT)) 387c0b4e3abSDarrick J. Wong return 0x76; 388c0b4e3abSDarrick J. Wong break; 389c0b4e3abSDarrick J. Wong case 12: 390c0b4e3abSDarrick J. Wong if (data->pin_cfg[3] >> ADT7462_PIN28_SHIFT == 391c0b4e3abSDarrick J. Wong ADT7462_PIN28_VOLT && 392c0b4e3abSDarrick J. Wong !(data->pin_cfg[0] & ADT7462_VID_INPUT)) 393c0b4e3abSDarrick J. Wong return 0x77; 394c0b4e3abSDarrick J. Wong break; 395c0b4e3abSDarrick J. Wong } 396c0b4e3abSDarrick J. Wong return -ENODEV; 397c0b4e3abSDarrick J. Wong } 398c0b4e3abSDarrick J. Wong 399c0b4e3abSDarrick J. Wong static int ADT7462_REG_VOLT(struct adt7462_data *data, int which) 400c0b4e3abSDarrick J. Wong { 401c0b4e3abSDarrick J. Wong switch (which) { 402c0b4e3abSDarrick J. Wong case 0: 403c0b4e3abSDarrick J. Wong if (!(data->pin_cfg[0] & ADT7462_PIN7_INPUT)) 404c0b4e3abSDarrick J. Wong return 0xA3; 405c0b4e3abSDarrick J. Wong break; 406c0b4e3abSDarrick J. Wong case 1: 407c0b4e3abSDarrick J. Wong return 0x90; 408c0b4e3abSDarrick J. Wong case 2: 409c0b4e3abSDarrick J. Wong if (!(data->pin_cfg[1] & ADT7462_PIN22_INPUT)) 410c0b4e3abSDarrick J. Wong return 0xA9; 411c0b4e3abSDarrick J. Wong break; 412c0b4e3abSDarrick J. Wong case 3: 413c0b4e3abSDarrick J. Wong if (!(data->pin_cfg[1] & ADT7462_PIN21_INPUT)) 414c0b4e3abSDarrick J. Wong return 0xA7; 415c0b4e3abSDarrick J. Wong break; 416c0b4e3abSDarrick J. Wong case 4: 417c0b4e3abSDarrick J. Wong if (!(data->pin_cfg[0] & ADT7462_DIODE3_INPUT)) 418c0b4e3abSDarrick J. Wong return 0x8F; 419c0b4e3abSDarrick J. Wong break; 420c0b4e3abSDarrick J. Wong case 5: 421c0b4e3abSDarrick J. Wong if (!(data->pin_cfg[0] & ADT7462_DIODE1_INPUT)) 422c0b4e3abSDarrick J. Wong return 0x8B; 423c0b4e3abSDarrick J. Wong break; 424c0b4e3abSDarrick J. Wong case 6: 425c0b4e3abSDarrick J. Wong if (!(data->pin_cfg[1] & ADT7462_PIN13_INPUT)) 426c0b4e3abSDarrick J. Wong return 0x96; 427c0b4e3abSDarrick J. Wong break; 428c0b4e3abSDarrick J. Wong case 7: 429c0b4e3abSDarrick J. Wong if (!(data->pin_cfg[1] & ADT7462_PIN8_INPUT)) 430c0b4e3abSDarrick J. Wong return 0xA5; 431c0b4e3abSDarrick J. Wong break; 432c0b4e3abSDarrick J. Wong case 8: 433c0b4e3abSDarrick J. Wong if (!(data->pin_cfg[2] & ADT7462_PIN26_VOLT_INPUT)) 434c0b4e3abSDarrick J. Wong return 0x93; 435c0b4e3abSDarrick J. Wong break; 436c0b4e3abSDarrick J. Wong case 9: 437c0b4e3abSDarrick J. Wong if (!(data->pin_cfg[2] & ADT7462_PIN25_VOLT_INPUT)) 438c0b4e3abSDarrick J. Wong return 0x92; 439c0b4e3abSDarrick J. Wong break; 440c0b4e3abSDarrick J. Wong case 10: 441c0b4e3abSDarrick J. Wong return 0x91; 442c0b4e3abSDarrick J. Wong case 11: 443c0b4e3abSDarrick J. Wong if (data->pin_cfg[3] >> ADT7462_PIN28_SHIFT == 444c0b4e3abSDarrick J. Wong ADT7462_PIN28_VOLT && 445c0b4e3abSDarrick J. Wong !(data->pin_cfg[0] & ADT7462_VID_INPUT)) 446c0b4e3abSDarrick J. Wong return 0x94; 447c0b4e3abSDarrick J. Wong break; 448c0b4e3abSDarrick J. Wong case 12: 449c0b4e3abSDarrick J. Wong if (data->pin_cfg[3] >> ADT7462_PIN28_SHIFT == 450c0b4e3abSDarrick J. Wong ADT7462_PIN28_VOLT && 451c0b4e3abSDarrick J. Wong !(data->pin_cfg[0] & ADT7462_VID_INPUT)) 452c0b4e3abSDarrick J. Wong return 0x95; 453c0b4e3abSDarrick J. Wong break; 454c0b4e3abSDarrick J. Wong } 455c0b4e3abSDarrick J. Wong return -ENODEV; 456c0b4e3abSDarrick J. Wong } 457c0b4e3abSDarrick J. Wong 458c0b4e3abSDarrick J. Wong /* Provide labels for sysfs */ 459c0b4e3abSDarrick J. Wong static const char *voltage_label(struct adt7462_data *data, int which) 460c0b4e3abSDarrick J. Wong { 461c0b4e3abSDarrick J. Wong switch (which) { 462c0b4e3abSDarrick J. Wong case 0: 463c0b4e3abSDarrick J. Wong if (!(data->pin_cfg[0] & ADT7462_PIN7_INPUT)) 464c0b4e3abSDarrick J. Wong return "+12V1"; 465c0b4e3abSDarrick J. Wong break; 466c0b4e3abSDarrick J. Wong case 1: 467c0b4e3abSDarrick J. Wong switch (MASK_AND_SHIFT(data->pin_cfg[1], ADT7462_PIN23)) { 468c0b4e3abSDarrick J. Wong case 0: 469c0b4e3abSDarrick J. Wong return "Vccp1"; 470c0b4e3abSDarrick J. Wong case 1: 471c0b4e3abSDarrick J. Wong return "+2.5V"; 472c0b4e3abSDarrick J. Wong case 2: 473c0b4e3abSDarrick J. Wong return "+1.8V"; 474c0b4e3abSDarrick J. Wong case 3: 475c0b4e3abSDarrick J. Wong return "+1.5V"; 476c0b4e3abSDarrick J. Wong } 477c0b4e3abSDarrick J. Wong case 2: 478c0b4e3abSDarrick J. Wong if (!(data->pin_cfg[1] & ADT7462_PIN22_INPUT)) 479c0b4e3abSDarrick J. Wong return "+12V3"; 480c0b4e3abSDarrick J. Wong break; 481c0b4e3abSDarrick J. Wong case 3: 482c0b4e3abSDarrick J. Wong if (!(data->pin_cfg[1] & ADT7462_PIN21_INPUT)) 483c0b4e3abSDarrick J. Wong return "+5V"; 484c0b4e3abSDarrick J. Wong break; 485c0b4e3abSDarrick J. Wong case 4: 486c0b4e3abSDarrick J. Wong if (!(data->pin_cfg[0] & ADT7462_DIODE3_INPUT)) { 487c0b4e3abSDarrick J. Wong if (data->pin_cfg[1] & ADT7462_PIN19_INPUT) 488c0b4e3abSDarrick J. Wong return "+0.9V"; 489c0b4e3abSDarrick J. Wong return "+1.25V"; 490c0b4e3abSDarrick J. Wong } 491c0b4e3abSDarrick J. Wong break; 492c0b4e3abSDarrick J. Wong case 5: 493c0b4e3abSDarrick J. Wong if (!(data->pin_cfg[0] & ADT7462_DIODE1_INPUT)) { 494c0b4e3abSDarrick J. Wong if (data->pin_cfg[1] & ADT7462_PIN19_INPUT) 495c0b4e3abSDarrick J. Wong return "+1.8V"; 496c0b4e3abSDarrick J. Wong return "+2.5V"; 497c0b4e3abSDarrick J. Wong } 498c0b4e3abSDarrick J. Wong break; 499c0b4e3abSDarrick J. Wong case 6: 500c0b4e3abSDarrick J. Wong if (!(data->pin_cfg[1] & ADT7462_PIN13_INPUT)) 501c0b4e3abSDarrick J. Wong return "+3.3V"; 502c0b4e3abSDarrick J. Wong break; 503c0b4e3abSDarrick J. Wong case 7: 504c0b4e3abSDarrick J. Wong if (!(data->pin_cfg[1] & ADT7462_PIN8_INPUT)) 505c0b4e3abSDarrick J. Wong return "+12V2"; 506c0b4e3abSDarrick J. Wong break; 507c0b4e3abSDarrick J. Wong case 8: 508c0b4e3abSDarrick J. Wong switch (MASK_AND_SHIFT(data->pin_cfg[2], ADT7462_PIN26)) { 509c0b4e3abSDarrick J. Wong case 0: 510c0b4e3abSDarrick J. Wong return "Vbatt"; 511c0b4e3abSDarrick J. Wong case 1: 512c0b4e3abSDarrick J. Wong return "FSB_Vtt"; 513c0b4e3abSDarrick J. Wong } 514c0b4e3abSDarrick J. Wong break; 515c0b4e3abSDarrick J. Wong case 9: 516c0b4e3abSDarrick J. Wong switch (MASK_AND_SHIFT(data->pin_cfg[2], ADT7462_PIN25)) { 517c0b4e3abSDarrick J. Wong case 0: 518c0b4e3abSDarrick J. Wong return "+3.3V"; 519c0b4e3abSDarrick J. Wong case 1: 520c0b4e3abSDarrick J. Wong return "+1.2V1"; 521c0b4e3abSDarrick J. Wong } 522c0b4e3abSDarrick J. Wong break; 523c0b4e3abSDarrick J. Wong case 10: 524c0b4e3abSDarrick J. Wong switch (MASK_AND_SHIFT(data->pin_cfg[2], ADT7462_PIN24)) { 525c0b4e3abSDarrick J. Wong case 0: 526c0b4e3abSDarrick J. Wong return "Vccp2"; 527c0b4e3abSDarrick J. Wong case 1: 528c0b4e3abSDarrick J. Wong return "+2.5V"; 529c0b4e3abSDarrick J. Wong case 2: 530c0b4e3abSDarrick J. Wong return "+1.8V"; 531c0b4e3abSDarrick J. Wong case 3: 532c0b4e3abSDarrick J. Wong return "+1.5"; 533c0b4e3abSDarrick J. Wong } 534c0b4e3abSDarrick J. Wong case 11: 535c0b4e3abSDarrick J. Wong if (data->pin_cfg[3] >> ADT7462_PIN28_SHIFT == 536c0b4e3abSDarrick J. Wong ADT7462_PIN28_VOLT && 537c0b4e3abSDarrick J. Wong !(data->pin_cfg[0] & ADT7462_VID_INPUT)) 538c0b4e3abSDarrick J. Wong return "+1.5V ICH"; 539c0b4e3abSDarrick J. Wong break; 540c0b4e3abSDarrick J. Wong case 12: 541c0b4e3abSDarrick J. Wong if (data->pin_cfg[3] >> ADT7462_PIN28_SHIFT == 542c0b4e3abSDarrick J. Wong ADT7462_PIN28_VOLT && 543c0b4e3abSDarrick J. Wong !(data->pin_cfg[0] & ADT7462_VID_INPUT)) 544c0b4e3abSDarrick J. Wong return "+1.5V 3GPIO"; 545c0b4e3abSDarrick J. Wong break; 546c0b4e3abSDarrick J. Wong } 547c0b4e3abSDarrick J. Wong return "N/A"; 548c0b4e3abSDarrick J. Wong } 549c0b4e3abSDarrick J. Wong 550c0b4e3abSDarrick J. Wong /* Multipliers are actually in uV, not mV. */ 551c0b4e3abSDarrick J. Wong static int voltage_multiplier(struct adt7462_data *data, int which) 552c0b4e3abSDarrick J. Wong { 553c0b4e3abSDarrick J. Wong switch (which) { 554c0b4e3abSDarrick J. Wong case 0: 555c0b4e3abSDarrick J. Wong if (!(data->pin_cfg[0] & ADT7462_PIN7_INPUT)) 556c0b4e3abSDarrick J. Wong return 62500; 557c0b4e3abSDarrick J. Wong break; 558c0b4e3abSDarrick J. Wong case 1: 559c0b4e3abSDarrick J. Wong switch (MASK_AND_SHIFT(data->pin_cfg[1], ADT7462_PIN23)) { 560c0b4e3abSDarrick J. Wong case 0: 561c0b4e3abSDarrick J. Wong if (data->pin_cfg[0] & ADT7462_VID_INPUT) 562c0b4e3abSDarrick J. Wong return 12500; 563c0b4e3abSDarrick J. Wong return 6250; 564c0b4e3abSDarrick J. Wong case 1: 565c0b4e3abSDarrick J. Wong return 13000; 566c0b4e3abSDarrick J. Wong case 2: 567c0b4e3abSDarrick J. Wong return 9400; 568c0b4e3abSDarrick J. Wong case 3: 569c0b4e3abSDarrick J. Wong return 7800; 570c0b4e3abSDarrick J. Wong } 571c0b4e3abSDarrick J. Wong case 2: 572c0b4e3abSDarrick J. Wong if (!(data->pin_cfg[1] & ADT7462_PIN22_INPUT)) 573c0b4e3abSDarrick J. Wong return 62500; 574c0b4e3abSDarrick J. Wong break; 575c0b4e3abSDarrick J. Wong case 3: 576c0b4e3abSDarrick J. Wong if (!(data->pin_cfg[1] & ADT7462_PIN21_INPUT)) 577c0b4e3abSDarrick J. Wong return 26000; 578c0b4e3abSDarrick J. Wong break; 579c0b4e3abSDarrick J. Wong case 4: 580c0b4e3abSDarrick J. Wong if (!(data->pin_cfg[0] & ADT7462_DIODE3_INPUT)) { 581c0b4e3abSDarrick J. Wong if (data->pin_cfg[1] & ADT7462_PIN19_INPUT) 582c0b4e3abSDarrick J. Wong return 4690; 583c0b4e3abSDarrick J. Wong return 6500; 584c0b4e3abSDarrick J. Wong } 585c0b4e3abSDarrick J. Wong break; 586c0b4e3abSDarrick J. Wong case 5: 587c0b4e3abSDarrick J. Wong if (!(data->pin_cfg[0] & ADT7462_DIODE1_INPUT)) { 588c0b4e3abSDarrick J. Wong if (data->pin_cfg[1] & ADT7462_PIN15_INPUT) 589c0b4e3abSDarrick J. Wong return 9400; 590c0b4e3abSDarrick J. Wong return 13000; 591c0b4e3abSDarrick J. Wong } 592c0b4e3abSDarrick J. Wong break; 593c0b4e3abSDarrick J. Wong case 6: 594c0b4e3abSDarrick J. Wong if (!(data->pin_cfg[1] & ADT7462_PIN13_INPUT)) 595c0b4e3abSDarrick J. Wong return 17200; 596c0b4e3abSDarrick J. Wong break; 597c0b4e3abSDarrick J. Wong case 7: 598c0b4e3abSDarrick J. Wong if (!(data->pin_cfg[1] & ADT7462_PIN8_INPUT)) 599c0b4e3abSDarrick J. Wong return 62500; 600c0b4e3abSDarrick J. Wong break; 601c0b4e3abSDarrick J. Wong case 8: 602c0b4e3abSDarrick J. Wong switch (MASK_AND_SHIFT(data->pin_cfg[2], ADT7462_PIN26)) { 603c0b4e3abSDarrick J. Wong case 0: 604c0b4e3abSDarrick J. Wong return 15600; 605c0b4e3abSDarrick J. Wong case 1: 606c0b4e3abSDarrick J. Wong return 6250; 607c0b4e3abSDarrick J. Wong } 608c0b4e3abSDarrick J. Wong break; 609c0b4e3abSDarrick J. Wong case 9: 610c0b4e3abSDarrick J. Wong switch (MASK_AND_SHIFT(data->pin_cfg[2], ADT7462_PIN25)) { 611c0b4e3abSDarrick J. Wong case 0: 612c0b4e3abSDarrick J. Wong return 17200; 613c0b4e3abSDarrick J. Wong case 1: 614c0b4e3abSDarrick J. Wong return 6250; 615c0b4e3abSDarrick J. Wong } 616c0b4e3abSDarrick J. Wong break; 617c0b4e3abSDarrick J. Wong case 10: 618c0b4e3abSDarrick J. Wong switch (MASK_AND_SHIFT(data->pin_cfg[2], ADT7462_PIN24)) { 619c0b4e3abSDarrick J. Wong case 0: 620c0b4e3abSDarrick J. Wong return 6250; 621c0b4e3abSDarrick J. Wong case 1: 622c0b4e3abSDarrick J. Wong return 13000; 623c0b4e3abSDarrick J. Wong case 2: 624c0b4e3abSDarrick J. Wong return 9400; 625c0b4e3abSDarrick J. Wong case 3: 626c0b4e3abSDarrick J. Wong return 7800; 627c0b4e3abSDarrick J. Wong } 628c0b4e3abSDarrick J. Wong case 11: 629c0b4e3abSDarrick J. Wong case 12: 630c0b4e3abSDarrick J. Wong if (data->pin_cfg[3] >> ADT7462_PIN28_SHIFT == 631c0b4e3abSDarrick J. Wong ADT7462_PIN28_VOLT && 632c0b4e3abSDarrick J. Wong !(data->pin_cfg[0] & ADT7462_VID_INPUT)) 633c0b4e3abSDarrick J. Wong return 7800; 634c0b4e3abSDarrick J. Wong } 635c0b4e3abSDarrick J. Wong return 0; 636c0b4e3abSDarrick J. Wong } 637c0b4e3abSDarrick J. Wong 638c0b4e3abSDarrick J. Wong static int temp_enabled(struct adt7462_data *data, int which) 639c0b4e3abSDarrick J. Wong { 640c0b4e3abSDarrick J. Wong switch (which) { 641c0b4e3abSDarrick J. Wong case 0: 642c0b4e3abSDarrick J. Wong case 2: 643c0b4e3abSDarrick J. Wong return 1; 644c0b4e3abSDarrick J. Wong case 1: 645c0b4e3abSDarrick J. Wong if (data->pin_cfg[0] & ADT7462_DIODE1_INPUT) 646c0b4e3abSDarrick J. Wong return 1; 647c0b4e3abSDarrick J. Wong break; 648c0b4e3abSDarrick J. Wong case 3: 649c0b4e3abSDarrick J. Wong if (data->pin_cfg[0] & ADT7462_DIODE3_INPUT) 650c0b4e3abSDarrick J. Wong return 1; 651c0b4e3abSDarrick J. Wong break; 652c0b4e3abSDarrick J. Wong } 653c0b4e3abSDarrick J. Wong return 0; 654c0b4e3abSDarrick J. Wong } 655c0b4e3abSDarrick J. Wong 656c0b4e3abSDarrick J. Wong static const char *temp_label(struct adt7462_data *data, int which) 657c0b4e3abSDarrick J. Wong { 658c0b4e3abSDarrick J. Wong switch (which) { 659c0b4e3abSDarrick J. Wong case 0: 660c0b4e3abSDarrick J. Wong return "local"; 661c0b4e3abSDarrick J. Wong case 1: 662c0b4e3abSDarrick J. Wong if (data->pin_cfg[0] & ADT7462_DIODE1_INPUT) 663c0b4e3abSDarrick J. Wong return "remote1"; 664c0b4e3abSDarrick J. Wong break; 665c0b4e3abSDarrick J. Wong case 2: 666c0b4e3abSDarrick J. Wong return "remote2"; 667c0b4e3abSDarrick J. Wong case 3: 668c0b4e3abSDarrick J. Wong if (data->pin_cfg[0] & ADT7462_DIODE3_INPUT) 669c0b4e3abSDarrick J. Wong return "remote3"; 670c0b4e3abSDarrick J. Wong break; 671c0b4e3abSDarrick J. Wong } 672c0b4e3abSDarrick J. Wong return "N/A"; 673c0b4e3abSDarrick J. Wong } 674c0b4e3abSDarrick J. Wong 675c0b4e3abSDarrick J. Wong /* Map Trange register values to mC */ 676c0b4e3abSDarrick J. Wong #define NUM_TRANGE_VALUES 16 677c0b4e3abSDarrick J. Wong static const int trange_values[NUM_TRANGE_VALUES] = { 678c0b4e3abSDarrick J. Wong 2000, 679c0b4e3abSDarrick J. Wong 2500, 680c0b4e3abSDarrick J. Wong 3300, 681c0b4e3abSDarrick J. Wong 4000, 682c0b4e3abSDarrick J. Wong 5000, 683c0b4e3abSDarrick J. Wong 6700, 684c0b4e3abSDarrick J. Wong 8000, 685c0b4e3abSDarrick J. Wong 10000, 686c0b4e3abSDarrick J. Wong 13300, 687c0b4e3abSDarrick J. Wong 16000, 688c0b4e3abSDarrick J. Wong 20000, 689c0b4e3abSDarrick J. Wong 26700, 690c0b4e3abSDarrick J. Wong 32000, 691c0b4e3abSDarrick J. Wong 40000, 692c0b4e3abSDarrick J. Wong 53300, 693c0b4e3abSDarrick J. Wong 80000 694c0b4e3abSDarrick J. Wong }; 695c0b4e3abSDarrick J. Wong 696c0b4e3abSDarrick J. Wong static int find_trange_value(int trange) 697c0b4e3abSDarrick J. Wong { 698c0b4e3abSDarrick J. Wong int i; 699c0b4e3abSDarrick J. Wong 700c0b4e3abSDarrick J. Wong for (i = 0; i < NUM_TRANGE_VALUES; i++) 701c0b4e3abSDarrick J. Wong if (trange_values[i] == trange) 702c0b4e3abSDarrick J. Wong return i; 703c0b4e3abSDarrick J. Wong 704c0b4e3abSDarrick J. Wong return -ENODEV; 705c0b4e3abSDarrick J. Wong } 706c0b4e3abSDarrick J. Wong 707c0b4e3abSDarrick J. Wong static struct adt7462_data *adt7462_update_device(struct device *dev) 708c0b4e3abSDarrick J. Wong { 709c0b4e3abSDarrick J. Wong struct i2c_client *client = to_i2c_client(dev); 710c0b4e3abSDarrick J. Wong struct adt7462_data *data = i2c_get_clientdata(client); 711c0b4e3abSDarrick J. Wong unsigned long local_jiffies = jiffies; 712c0b4e3abSDarrick J. Wong int i; 713c0b4e3abSDarrick J. Wong 714c0b4e3abSDarrick J. Wong mutex_lock(&data->lock); 715c0b4e3abSDarrick J. Wong if (time_before(local_jiffies, data->sensors_last_updated + 716c0b4e3abSDarrick J. Wong SENSOR_REFRESH_INTERVAL) 717c0b4e3abSDarrick J. Wong && data->sensors_valid) 718c0b4e3abSDarrick J. Wong goto no_sensor_update; 719c0b4e3abSDarrick J. Wong 720c0b4e3abSDarrick J. Wong for (i = 0; i < ADT7462_TEMP_COUNT; i++) { 721c0b4e3abSDarrick J. Wong /* 722c0b4e3abSDarrick J. Wong * Reading the fractional register locks the integral 723c0b4e3abSDarrick J. Wong * register until both have been read. 724c0b4e3abSDarrick J. Wong */ 725c0b4e3abSDarrick J. Wong data->temp_frac[i] = i2c_smbus_read_byte_data(client, 726c0b4e3abSDarrick J. Wong ADT7462_TEMP_REG(i)); 727c0b4e3abSDarrick J. Wong data->temp[i] = i2c_smbus_read_byte_data(client, 728c0b4e3abSDarrick J. Wong ADT7462_TEMP_REG(i) + 1); 729c0b4e3abSDarrick J. Wong } 730c0b4e3abSDarrick J. Wong 731c0b4e3abSDarrick J. Wong for (i = 0; i < ADT7462_FAN_COUNT; i++) 732c0b4e3abSDarrick J. Wong data->fan[i] = adt7462_read_word_data(client, 733c0b4e3abSDarrick J. Wong ADT7462_REG_FAN(i)); 734c0b4e3abSDarrick J. Wong 735c0b4e3abSDarrick J. Wong data->fan_enabled = i2c_smbus_read_byte_data(client, 736c0b4e3abSDarrick J. Wong ADT7462_REG_FAN_ENABLE); 737c0b4e3abSDarrick J. Wong 738c0b4e3abSDarrick J. Wong for (i = 0; i < ADT7462_PWM_COUNT; i++) 739c0b4e3abSDarrick J. Wong data->pwm[i] = i2c_smbus_read_byte_data(client, 740c0b4e3abSDarrick J. Wong ADT7462_REG_PWM(i)); 741c0b4e3abSDarrick J. Wong 742c0b4e3abSDarrick J. Wong for (i = 0; i < ADT7462_PIN_CFG_REG_COUNT; i++) 743c0b4e3abSDarrick J. Wong data->pin_cfg[i] = i2c_smbus_read_byte_data(client, 744c0b4e3abSDarrick J. Wong ADT7462_REG_PIN_CFG(i)); 745c0b4e3abSDarrick J. Wong 746c0b4e3abSDarrick J. Wong for (i = 0; i < ADT7462_VOLT_COUNT; i++) { 747c0b4e3abSDarrick J. Wong int reg = ADT7462_REG_VOLT(data, i); 748c0b4e3abSDarrick J. Wong if (!reg) 749c0b4e3abSDarrick J. Wong data->voltages[i] = 0; 750c0b4e3abSDarrick J. Wong else 751c0b4e3abSDarrick J. Wong data->voltages[i] = i2c_smbus_read_byte_data(client, 752c0b4e3abSDarrick J. Wong reg); 753c0b4e3abSDarrick J. Wong } 754c0b4e3abSDarrick J. Wong 755c0b4e3abSDarrick J. Wong data->alarms[0] = i2c_smbus_read_byte_data(client, ADT7462_REG_ALARM1); 756c0b4e3abSDarrick J. Wong data->alarms[1] = i2c_smbus_read_byte_data(client, ADT7462_REG_ALARM2); 757c0b4e3abSDarrick J. Wong data->alarms[2] = i2c_smbus_read_byte_data(client, ADT7462_REG_ALARM3); 758c0b4e3abSDarrick J. Wong data->alarms[3] = i2c_smbus_read_byte_data(client, ADT7462_REG_ALARM4); 759c0b4e3abSDarrick J. Wong 760c0b4e3abSDarrick J. Wong data->sensors_last_updated = local_jiffies; 761c0b4e3abSDarrick J. Wong data->sensors_valid = 1; 762c0b4e3abSDarrick J. Wong 763c0b4e3abSDarrick J. Wong no_sensor_update: 764c0b4e3abSDarrick J. Wong if (time_before(local_jiffies, data->limits_last_updated + 765c0b4e3abSDarrick J. Wong LIMIT_REFRESH_INTERVAL) 766c0b4e3abSDarrick J. Wong && data->limits_valid) 767c0b4e3abSDarrick J. Wong goto out; 768c0b4e3abSDarrick J. Wong 769c0b4e3abSDarrick J. Wong for (i = 0; i < ADT7462_TEMP_COUNT; i++) { 770c0b4e3abSDarrick J. Wong data->temp_min[i] = i2c_smbus_read_byte_data(client, 771c0b4e3abSDarrick J. Wong ADT7462_TEMP_MIN_REG(i)); 772c0b4e3abSDarrick J. Wong data->temp_max[i] = i2c_smbus_read_byte_data(client, 773c0b4e3abSDarrick J. Wong ADT7462_TEMP_MAX_REG(i)); 774c0b4e3abSDarrick J. Wong } 775c0b4e3abSDarrick J. Wong 776c0b4e3abSDarrick J. Wong for (i = 0; i < ADT7462_FAN_COUNT; i++) 777c0b4e3abSDarrick J. Wong data->fan_min[i] = i2c_smbus_read_byte_data(client, 778c0b4e3abSDarrick J. Wong ADT7462_REG_FAN_MIN(i)); 779c0b4e3abSDarrick J. Wong 780c0b4e3abSDarrick J. Wong for (i = 0; i < ADT7462_VOLT_COUNT; i++) { 781c0b4e3abSDarrick J. Wong int reg = ADT7462_REG_VOLT_MAX(data, i); 782c0b4e3abSDarrick J. Wong data->volt_max[i] = 783c0b4e3abSDarrick J. Wong (reg ? i2c_smbus_read_byte_data(client, reg) : 0); 784c0b4e3abSDarrick J. Wong 785c0b4e3abSDarrick J. Wong reg = ADT7462_REG_VOLT_MIN(data, i); 786c0b4e3abSDarrick J. Wong data->volt_min[i] = 787c0b4e3abSDarrick J. Wong (reg ? i2c_smbus_read_byte_data(client, reg) : 0); 788c0b4e3abSDarrick J. Wong } 789c0b4e3abSDarrick J. Wong 790c0b4e3abSDarrick J. Wong for (i = 0; i < ADT7462_PWM_COUNT; i++) { 791c0b4e3abSDarrick J. Wong data->pwm_min[i] = i2c_smbus_read_byte_data(client, 792c0b4e3abSDarrick J. Wong ADT7462_REG_PWM_MIN(i)); 793c0b4e3abSDarrick J. Wong data->pwm_tmin[i] = i2c_smbus_read_byte_data(client, 794c0b4e3abSDarrick J. Wong ADT7462_REG_PWM_TMIN(i)); 795c0b4e3abSDarrick J. Wong data->pwm_trange[i] = i2c_smbus_read_byte_data(client, 796c0b4e3abSDarrick J. Wong ADT7462_REG_PWM_TRANGE(i)); 797c0b4e3abSDarrick J. Wong data->pwm_cfg[i] = i2c_smbus_read_byte_data(client, 798c0b4e3abSDarrick J. Wong ADT7462_REG_PWM_CFG(i)); 799c0b4e3abSDarrick J. Wong } 800c0b4e3abSDarrick J. Wong 801c0b4e3abSDarrick J. Wong data->pwm_max = i2c_smbus_read_byte_data(client, ADT7462_REG_PWM_MAX); 802c0b4e3abSDarrick J. Wong 803c0b4e3abSDarrick J. Wong data->cfg2 = i2c_smbus_read_byte_data(client, ADT7462_REG_CFG2); 804c0b4e3abSDarrick J. Wong 805c0b4e3abSDarrick J. Wong data->limits_last_updated = local_jiffies; 806c0b4e3abSDarrick J. Wong data->limits_valid = 1; 807c0b4e3abSDarrick J. Wong 808c0b4e3abSDarrick J. Wong out: 809c0b4e3abSDarrick J. Wong mutex_unlock(&data->lock); 810c0b4e3abSDarrick J. Wong return data; 811c0b4e3abSDarrick J. Wong } 812c0b4e3abSDarrick J. Wong 813c0b4e3abSDarrick J. Wong static ssize_t show_temp_min(struct device *dev, 814c0b4e3abSDarrick J. Wong struct device_attribute *devattr, 815c0b4e3abSDarrick J. Wong char *buf) 816c0b4e3abSDarrick J. Wong { 817c0b4e3abSDarrick J. Wong struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); 818c0b4e3abSDarrick J. Wong struct adt7462_data *data = adt7462_update_device(dev); 819c0b4e3abSDarrick J. Wong 820c0b4e3abSDarrick J. Wong if (!temp_enabled(data, attr->index)) 821c0b4e3abSDarrick J. Wong return sprintf(buf, "0\n"); 822c0b4e3abSDarrick J. Wong 823c0b4e3abSDarrick J. Wong return sprintf(buf, "%d\n", 1000 * (data->temp_min[attr->index] - 64)); 824c0b4e3abSDarrick J. Wong } 825c0b4e3abSDarrick J. Wong 826c0b4e3abSDarrick J. Wong static ssize_t set_temp_min(struct device *dev, 827c0b4e3abSDarrick J. Wong struct device_attribute *devattr, 828c0b4e3abSDarrick J. Wong const char *buf, 829c0b4e3abSDarrick J. Wong size_t count) 830c0b4e3abSDarrick J. Wong { 831c0b4e3abSDarrick J. Wong struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); 832c0b4e3abSDarrick J. Wong struct i2c_client *client = to_i2c_client(dev); 833c0b4e3abSDarrick J. Wong struct adt7462_data *data = i2c_get_clientdata(client); 834c0b4e3abSDarrick J. Wong long temp; 835c0b4e3abSDarrick J. Wong 836179c4fdbSFrans Meulenbroeks if (kstrtol(buf, 10, &temp) || !temp_enabled(data, attr->index)) 837c0b4e3abSDarrick J. Wong return -EINVAL; 838c0b4e3abSDarrick J. Wong 8398f8c1fb0SDarrick J. Wong temp = DIV_ROUND_CLOSEST(temp, 1000) + 64; 840c0b4e3abSDarrick J. Wong temp = SENSORS_LIMIT(temp, 0, 255); 841c0b4e3abSDarrick J. Wong 842c0b4e3abSDarrick J. Wong mutex_lock(&data->lock); 843c0b4e3abSDarrick J. Wong data->temp_min[attr->index] = temp; 844c0b4e3abSDarrick J. Wong i2c_smbus_write_byte_data(client, ADT7462_TEMP_MIN_REG(attr->index), 845c0b4e3abSDarrick J. Wong temp); 846c0b4e3abSDarrick J. Wong mutex_unlock(&data->lock); 847c0b4e3abSDarrick J. Wong 848c0b4e3abSDarrick J. Wong return count; 849c0b4e3abSDarrick J. Wong } 850c0b4e3abSDarrick J. Wong 851c0b4e3abSDarrick J. Wong static ssize_t show_temp_max(struct device *dev, 852c0b4e3abSDarrick J. Wong struct device_attribute *devattr, 853c0b4e3abSDarrick J. Wong char *buf) 854c0b4e3abSDarrick J. Wong { 855c0b4e3abSDarrick J. Wong struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); 856c0b4e3abSDarrick J. Wong struct adt7462_data *data = adt7462_update_device(dev); 857c0b4e3abSDarrick J. Wong 858c0b4e3abSDarrick J. Wong if (!temp_enabled(data, attr->index)) 859c0b4e3abSDarrick J. Wong return sprintf(buf, "0\n"); 860c0b4e3abSDarrick J. Wong 861c0b4e3abSDarrick J. Wong return sprintf(buf, "%d\n", 1000 * (data->temp_max[attr->index] - 64)); 862c0b4e3abSDarrick J. Wong } 863c0b4e3abSDarrick J. Wong 864c0b4e3abSDarrick J. Wong static ssize_t set_temp_max(struct device *dev, 865c0b4e3abSDarrick J. Wong struct device_attribute *devattr, 866c0b4e3abSDarrick J. Wong const char *buf, 867c0b4e3abSDarrick J. Wong size_t count) 868c0b4e3abSDarrick J. Wong { 869c0b4e3abSDarrick J. Wong struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); 870c0b4e3abSDarrick J. Wong struct i2c_client *client = to_i2c_client(dev); 871c0b4e3abSDarrick J. Wong struct adt7462_data *data = i2c_get_clientdata(client); 872c0b4e3abSDarrick J. Wong long temp; 873c0b4e3abSDarrick J. Wong 874179c4fdbSFrans Meulenbroeks if (kstrtol(buf, 10, &temp) || !temp_enabled(data, attr->index)) 875c0b4e3abSDarrick J. Wong return -EINVAL; 876c0b4e3abSDarrick J. Wong 8778f8c1fb0SDarrick J. Wong temp = DIV_ROUND_CLOSEST(temp, 1000) + 64; 878c0b4e3abSDarrick J. Wong temp = SENSORS_LIMIT(temp, 0, 255); 879c0b4e3abSDarrick J. Wong 880c0b4e3abSDarrick J. Wong mutex_lock(&data->lock); 881c0b4e3abSDarrick J. Wong data->temp_max[attr->index] = temp; 882c0b4e3abSDarrick J. Wong i2c_smbus_write_byte_data(client, ADT7462_TEMP_MAX_REG(attr->index), 883c0b4e3abSDarrick J. Wong temp); 884c0b4e3abSDarrick J. Wong mutex_unlock(&data->lock); 885c0b4e3abSDarrick J. Wong 886c0b4e3abSDarrick J. Wong return count; 887c0b4e3abSDarrick J. Wong } 888c0b4e3abSDarrick J. Wong 889c0b4e3abSDarrick J. Wong static ssize_t show_temp(struct device *dev, struct device_attribute *devattr, 890c0b4e3abSDarrick J. Wong char *buf) 891c0b4e3abSDarrick J. Wong { 892c0b4e3abSDarrick J. Wong struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); 893c0b4e3abSDarrick J. Wong struct adt7462_data *data = adt7462_update_device(dev); 894c0b4e3abSDarrick J. Wong u8 frac = data->temp_frac[attr->index] >> TEMP_FRAC_OFFSET; 895c0b4e3abSDarrick J. Wong 896c0b4e3abSDarrick J. Wong if (!temp_enabled(data, attr->index)) 897c0b4e3abSDarrick J. Wong return sprintf(buf, "0\n"); 898c0b4e3abSDarrick J. Wong 899c0b4e3abSDarrick J. Wong return sprintf(buf, "%d\n", 1000 * (data->temp[attr->index] - 64) + 900c0b4e3abSDarrick J. Wong 250 * frac); 901c0b4e3abSDarrick J. Wong } 902c0b4e3abSDarrick J. Wong 903c0b4e3abSDarrick J. Wong static ssize_t show_temp_label(struct device *dev, 904c0b4e3abSDarrick J. Wong struct device_attribute *devattr, 905c0b4e3abSDarrick J. Wong char *buf) 906c0b4e3abSDarrick J. Wong { 907c0b4e3abSDarrick J. Wong struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); 908c0b4e3abSDarrick J. Wong struct adt7462_data *data = adt7462_update_device(dev); 909c0b4e3abSDarrick J. Wong 910c0b4e3abSDarrick J. Wong return sprintf(buf, "%s\n", temp_label(data, attr->index)); 911c0b4e3abSDarrick J. Wong } 912c0b4e3abSDarrick J. Wong 913c0b4e3abSDarrick J. Wong static ssize_t show_volt_max(struct device *dev, 914c0b4e3abSDarrick J. Wong struct device_attribute *devattr, 915c0b4e3abSDarrick J. Wong char *buf) 916c0b4e3abSDarrick J. Wong { 917c0b4e3abSDarrick J. Wong struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); 918c0b4e3abSDarrick J. Wong struct adt7462_data *data = adt7462_update_device(dev); 919c0b4e3abSDarrick J. Wong int x = voltage_multiplier(data, attr->index); 920c0b4e3abSDarrick J. Wong 921c0b4e3abSDarrick J. Wong x *= data->volt_max[attr->index]; 922c0b4e3abSDarrick J. Wong x /= 1000; /* convert from uV to mV */ 923c0b4e3abSDarrick J. Wong 924c0b4e3abSDarrick J. Wong return sprintf(buf, "%d\n", x); 925c0b4e3abSDarrick J. Wong } 926c0b4e3abSDarrick J. Wong 927c0b4e3abSDarrick J. Wong static ssize_t set_volt_max(struct device *dev, 928c0b4e3abSDarrick J. Wong struct device_attribute *devattr, 929c0b4e3abSDarrick J. Wong const char *buf, 930c0b4e3abSDarrick J. Wong size_t count) 931c0b4e3abSDarrick J. Wong { 932c0b4e3abSDarrick J. Wong struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); 933c0b4e3abSDarrick J. Wong struct i2c_client *client = to_i2c_client(dev); 934c0b4e3abSDarrick J. Wong struct adt7462_data *data = i2c_get_clientdata(client); 935c0b4e3abSDarrick J. Wong int x = voltage_multiplier(data, attr->index); 936c0b4e3abSDarrick J. Wong long temp; 937c0b4e3abSDarrick J. Wong 938179c4fdbSFrans Meulenbroeks if (kstrtol(buf, 10, &temp) || !x) 939c0b4e3abSDarrick J. Wong return -EINVAL; 940c0b4e3abSDarrick J. Wong 941c0b4e3abSDarrick J. Wong temp *= 1000; /* convert mV to uV */ 9428f8c1fb0SDarrick J. Wong temp = DIV_ROUND_CLOSEST(temp, x); 943c0b4e3abSDarrick J. Wong temp = SENSORS_LIMIT(temp, 0, 255); 944c0b4e3abSDarrick J. Wong 945c0b4e3abSDarrick J. Wong mutex_lock(&data->lock); 946c0b4e3abSDarrick J. Wong data->volt_max[attr->index] = temp; 947c0b4e3abSDarrick J. Wong i2c_smbus_write_byte_data(client, 948c0b4e3abSDarrick J. Wong ADT7462_REG_VOLT_MAX(data, attr->index), 949c0b4e3abSDarrick J. Wong temp); 950c0b4e3abSDarrick J. Wong mutex_unlock(&data->lock); 951c0b4e3abSDarrick J. Wong 952c0b4e3abSDarrick J. Wong return count; 953c0b4e3abSDarrick J. Wong } 954c0b4e3abSDarrick J. Wong 955c0b4e3abSDarrick J. Wong static ssize_t show_volt_min(struct device *dev, 956c0b4e3abSDarrick J. Wong struct device_attribute *devattr, 957c0b4e3abSDarrick J. Wong char *buf) 958c0b4e3abSDarrick J. Wong { 959c0b4e3abSDarrick J. Wong struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); 960c0b4e3abSDarrick J. Wong struct adt7462_data *data = adt7462_update_device(dev); 961c0b4e3abSDarrick J. Wong int x = voltage_multiplier(data, attr->index); 962c0b4e3abSDarrick J. Wong 963c0b4e3abSDarrick J. Wong x *= data->volt_min[attr->index]; 964c0b4e3abSDarrick J. Wong x /= 1000; /* convert from uV to mV */ 965c0b4e3abSDarrick J. Wong 966c0b4e3abSDarrick J. Wong return sprintf(buf, "%d\n", x); 967c0b4e3abSDarrick J. Wong } 968c0b4e3abSDarrick J. Wong 969c0b4e3abSDarrick J. Wong static ssize_t set_volt_min(struct device *dev, 970c0b4e3abSDarrick J. Wong struct device_attribute *devattr, 971c0b4e3abSDarrick J. Wong const char *buf, 972c0b4e3abSDarrick J. Wong size_t count) 973c0b4e3abSDarrick J. Wong { 974c0b4e3abSDarrick J. Wong struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); 975c0b4e3abSDarrick J. Wong struct i2c_client *client = to_i2c_client(dev); 976c0b4e3abSDarrick J. Wong struct adt7462_data *data = i2c_get_clientdata(client); 977c0b4e3abSDarrick J. Wong int x = voltage_multiplier(data, attr->index); 978c0b4e3abSDarrick J. Wong long temp; 979c0b4e3abSDarrick J. Wong 980179c4fdbSFrans Meulenbroeks if (kstrtol(buf, 10, &temp) || !x) 981c0b4e3abSDarrick J. Wong return -EINVAL; 982c0b4e3abSDarrick J. Wong 983c0b4e3abSDarrick J. Wong temp *= 1000; /* convert mV to uV */ 9848f8c1fb0SDarrick J. Wong temp = DIV_ROUND_CLOSEST(temp, x); 985c0b4e3abSDarrick J. Wong temp = SENSORS_LIMIT(temp, 0, 255); 986c0b4e3abSDarrick J. Wong 987c0b4e3abSDarrick J. Wong mutex_lock(&data->lock); 988c0b4e3abSDarrick J. Wong data->volt_min[attr->index] = temp; 989c0b4e3abSDarrick J. Wong i2c_smbus_write_byte_data(client, 990c0b4e3abSDarrick J. Wong ADT7462_REG_VOLT_MIN(data, attr->index), 991c0b4e3abSDarrick J. Wong temp); 992c0b4e3abSDarrick J. Wong mutex_unlock(&data->lock); 993c0b4e3abSDarrick J. Wong 994c0b4e3abSDarrick J. Wong return count; 995c0b4e3abSDarrick J. Wong } 996c0b4e3abSDarrick J. Wong 997c0b4e3abSDarrick J. Wong static ssize_t show_voltage(struct device *dev, 998c0b4e3abSDarrick J. Wong struct device_attribute *devattr, 999c0b4e3abSDarrick J. Wong char *buf) 1000c0b4e3abSDarrick J. Wong { 1001c0b4e3abSDarrick J. Wong struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); 1002c0b4e3abSDarrick J. Wong struct adt7462_data *data = adt7462_update_device(dev); 1003c0b4e3abSDarrick J. Wong int x = voltage_multiplier(data, attr->index); 1004c0b4e3abSDarrick J. Wong 1005c0b4e3abSDarrick J. Wong x *= data->voltages[attr->index]; 1006c0b4e3abSDarrick J. Wong x /= 1000; /* convert from uV to mV */ 1007c0b4e3abSDarrick J. Wong 1008c0b4e3abSDarrick J. Wong return sprintf(buf, "%d\n", x); 1009c0b4e3abSDarrick J. Wong } 1010c0b4e3abSDarrick J. Wong 1011c0b4e3abSDarrick J. Wong static ssize_t show_voltage_label(struct device *dev, 1012c0b4e3abSDarrick J. Wong struct device_attribute *devattr, 1013c0b4e3abSDarrick J. Wong char *buf) 1014c0b4e3abSDarrick J. Wong { 1015c0b4e3abSDarrick J. Wong struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); 1016c0b4e3abSDarrick J. Wong struct adt7462_data *data = adt7462_update_device(dev); 1017c0b4e3abSDarrick J. Wong 1018c0b4e3abSDarrick J. Wong return sprintf(buf, "%s\n", voltage_label(data, attr->index)); 1019c0b4e3abSDarrick J. Wong } 1020c0b4e3abSDarrick J. Wong 1021c0b4e3abSDarrick J. Wong static ssize_t show_alarm(struct device *dev, 1022c0b4e3abSDarrick J. Wong struct device_attribute *devattr, 1023c0b4e3abSDarrick J. Wong char *buf) 1024c0b4e3abSDarrick J. Wong { 1025c0b4e3abSDarrick J. Wong struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); 1026c0b4e3abSDarrick J. Wong struct adt7462_data *data = adt7462_update_device(dev); 1027c0b4e3abSDarrick J. Wong int reg = attr->index >> ADT7462_ALARM_REG_SHIFT; 1028c0b4e3abSDarrick J. Wong int mask = attr->index & ADT7462_ALARM_FLAG_MASK; 1029c0b4e3abSDarrick J. Wong 1030c0b4e3abSDarrick J. Wong if (data->alarms[reg] & mask) 1031c0b4e3abSDarrick J. Wong return sprintf(buf, "1\n"); 1032c0b4e3abSDarrick J. Wong else 1033c0b4e3abSDarrick J. Wong return sprintf(buf, "0\n"); 1034c0b4e3abSDarrick J. Wong } 1035c0b4e3abSDarrick J. Wong 1036c0b4e3abSDarrick J. Wong static int fan_enabled(struct adt7462_data *data, int fan) 1037c0b4e3abSDarrick J. Wong { 1038c0b4e3abSDarrick J. Wong return data->fan_enabled & (1 << fan); 1039c0b4e3abSDarrick J. Wong } 1040c0b4e3abSDarrick J. Wong 1041c0b4e3abSDarrick J. Wong static ssize_t show_fan_min(struct device *dev, 1042c0b4e3abSDarrick J. Wong struct device_attribute *devattr, 1043c0b4e3abSDarrick J. Wong char *buf) 1044c0b4e3abSDarrick J. Wong { 1045c0b4e3abSDarrick J. Wong struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); 1046c0b4e3abSDarrick J. Wong struct adt7462_data *data = adt7462_update_device(dev); 1047c0b4e3abSDarrick J. Wong u16 temp; 1048c0b4e3abSDarrick J. Wong 1049c0b4e3abSDarrick J. Wong /* Only the MSB of the min fan period is stored... */ 1050c0b4e3abSDarrick J. Wong temp = data->fan_min[attr->index]; 1051c0b4e3abSDarrick J. Wong temp <<= 8; 1052c0b4e3abSDarrick J. Wong 1053c0b4e3abSDarrick J. Wong if (!fan_enabled(data, attr->index) || 1054c0b4e3abSDarrick J. Wong !FAN_DATA_VALID(temp)) 1055c0b4e3abSDarrick J. Wong return sprintf(buf, "0\n"); 1056c0b4e3abSDarrick J. Wong 1057c0b4e3abSDarrick J. Wong return sprintf(buf, "%d\n", FAN_PERIOD_TO_RPM(temp)); 1058c0b4e3abSDarrick J. Wong } 1059c0b4e3abSDarrick J. Wong 1060c0b4e3abSDarrick J. Wong static ssize_t set_fan_min(struct device *dev, 1061c0b4e3abSDarrick J. Wong struct device_attribute *devattr, 1062c0b4e3abSDarrick J. Wong const char *buf, size_t count) 1063c0b4e3abSDarrick J. Wong { 1064c0b4e3abSDarrick J. Wong struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); 1065c0b4e3abSDarrick J. Wong struct i2c_client *client = to_i2c_client(dev); 1066c0b4e3abSDarrick J. Wong struct adt7462_data *data = i2c_get_clientdata(client); 1067c0b4e3abSDarrick J. Wong long temp; 1068c0b4e3abSDarrick J. Wong 1069179c4fdbSFrans Meulenbroeks if (kstrtol(buf, 10, &temp) || !temp || 1070c0b4e3abSDarrick J. Wong !fan_enabled(data, attr->index)) 1071c0b4e3abSDarrick J. Wong return -EINVAL; 1072c0b4e3abSDarrick J. Wong 1073c0b4e3abSDarrick J. Wong temp = FAN_RPM_TO_PERIOD(temp); 1074c0b4e3abSDarrick J. Wong temp >>= 8; 1075c0b4e3abSDarrick J. Wong temp = SENSORS_LIMIT(temp, 1, 255); 1076c0b4e3abSDarrick J. Wong 1077c0b4e3abSDarrick J. Wong mutex_lock(&data->lock); 1078c0b4e3abSDarrick J. Wong data->fan_min[attr->index] = temp; 1079c0b4e3abSDarrick J. Wong i2c_smbus_write_byte_data(client, ADT7462_REG_FAN_MIN(attr->index), 1080c0b4e3abSDarrick J. Wong temp); 1081c0b4e3abSDarrick J. Wong mutex_unlock(&data->lock); 1082c0b4e3abSDarrick J. Wong 1083c0b4e3abSDarrick J. Wong return count; 1084c0b4e3abSDarrick J. Wong } 1085c0b4e3abSDarrick J. Wong 1086c0b4e3abSDarrick J. Wong static ssize_t show_fan(struct device *dev, struct device_attribute *devattr, 1087c0b4e3abSDarrick J. Wong char *buf) 1088c0b4e3abSDarrick J. Wong { 1089c0b4e3abSDarrick J. Wong struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); 1090c0b4e3abSDarrick J. Wong struct adt7462_data *data = adt7462_update_device(dev); 1091c0b4e3abSDarrick J. Wong 1092c0b4e3abSDarrick J. Wong if (!fan_enabled(data, attr->index) || 1093c0b4e3abSDarrick J. Wong !FAN_DATA_VALID(data->fan[attr->index])) 1094c0b4e3abSDarrick J. Wong return sprintf(buf, "0\n"); 1095c0b4e3abSDarrick J. Wong 1096c0b4e3abSDarrick J. Wong return sprintf(buf, "%d\n", 1097c0b4e3abSDarrick J. Wong FAN_PERIOD_TO_RPM(data->fan[attr->index])); 1098c0b4e3abSDarrick J. Wong } 1099c0b4e3abSDarrick J. Wong 1100c0b4e3abSDarrick J. Wong static ssize_t show_force_pwm_max(struct device *dev, 1101c0b4e3abSDarrick J. Wong struct device_attribute *devattr, 1102c0b4e3abSDarrick J. Wong char *buf) 1103c0b4e3abSDarrick J. Wong { 1104c0b4e3abSDarrick J. Wong struct adt7462_data *data = adt7462_update_device(dev); 1105c0b4e3abSDarrick J. Wong return sprintf(buf, "%d\n", (data->cfg2 & ADT7462_FSPD_MASK ? 1 : 0)); 1106c0b4e3abSDarrick J. Wong } 1107c0b4e3abSDarrick J. Wong 1108c0b4e3abSDarrick J. Wong static ssize_t set_force_pwm_max(struct device *dev, 1109c0b4e3abSDarrick J. Wong struct device_attribute *devattr, 1110c0b4e3abSDarrick J. Wong const char *buf, 1111c0b4e3abSDarrick J. Wong size_t count) 1112c0b4e3abSDarrick J. Wong { 1113c0b4e3abSDarrick J. Wong struct i2c_client *client = to_i2c_client(dev); 1114c0b4e3abSDarrick J. Wong struct adt7462_data *data = i2c_get_clientdata(client); 1115c0b4e3abSDarrick J. Wong long temp; 1116c0b4e3abSDarrick J. Wong u8 reg; 1117c0b4e3abSDarrick J. Wong 1118179c4fdbSFrans Meulenbroeks if (kstrtol(buf, 10, &temp)) 1119c0b4e3abSDarrick J. Wong return -EINVAL; 1120c0b4e3abSDarrick J. Wong 1121c0b4e3abSDarrick J. Wong mutex_lock(&data->lock); 1122c0b4e3abSDarrick J. Wong reg = i2c_smbus_read_byte_data(client, ADT7462_REG_CFG2); 1123c0b4e3abSDarrick J. Wong if (temp) 1124c0b4e3abSDarrick J. Wong reg |= ADT7462_FSPD_MASK; 1125c0b4e3abSDarrick J. Wong else 1126c0b4e3abSDarrick J. Wong reg &= ~ADT7462_FSPD_MASK; 1127c0b4e3abSDarrick J. Wong data->cfg2 = reg; 1128c0b4e3abSDarrick J. Wong i2c_smbus_write_byte_data(client, ADT7462_REG_CFG2, reg); 1129c0b4e3abSDarrick J. Wong mutex_unlock(&data->lock); 1130c0b4e3abSDarrick J. Wong 1131c0b4e3abSDarrick J. Wong return count; 1132c0b4e3abSDarrick J. Wong } 1133c0b4e3abSDarrick J. Wong 1134c0b4e3abSDarrick J. Wong static ssize_t show_pwm(struct device *dev, struct device_attribute *devattr, 1135c0b4e3abSDarrick J. Wong char *buf) 1136c0b4e3abSDarrick J. Wong { 1137c0b4e3abSDarrick J. Wong struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); 1138c0b4e3abSDarrick J. Wong struct adt7462_data *data = adt7462_update_device(dev); 1139c0b4e3abSDarrick J. Wong return sprintf(buf, "%d\n", data->pwm[attr->index]); 1140c0b4e3abSDarrick J. Wong } 1141c0b4e3abSDarrick J. Wong 1142c0b4e3abSDarrick J. Wong static ssize_t set_pwm(struct device *dev, struct device_attribute *devattr, 1143c0b4e3abSDarrick J. Wong const char *buf, size_t count) 1144c0b4e3abSDarrick J. Wong { 1145c0b4e3abSDarrick J. Wong struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); 1146c0b4e3abSDarrick J. Wong struct i2c_client *client = to_i2c_client(dev); 1147c0b4e3abSDarrick J. Wong struct adt7462_data *data = i2c_get_clientdata(client); 1148c0b4e3abSDarrick J. Wong long temp; 1149c0b4e3abSDarrick J. Wong 1150179c4fdbSFrans Meulenbroeks if (kstrtol(buf, 10, &temp)) 1151c0b4e3abSDarrick J. Wong return -EINVAL; 1152c0b4e3abSDarrick J. Wong 1153c0b4e3abSDarrick J. Wong temp = SENSORS_LIMIT(temp, 0, 255); 1154c0b4e3abSDarrick J. Wong 1155c0b4e3abSDarrick J. Wong mutex_lock(&data->lock); 1156c0b4e3abSDarrick J. Wong data->pwm[attr->index] = temp; 1157c0b4e3abSDarrick J. Wong i2c_smbus_write_byte_data(client, ADT7462_REG_PWM(attr->index), temp); 1158c0b4e3abSDarrick J. Wong mutex_unlock(&data->lock); 1159c0b4e3abSDarrick J. Wong 1160c0b4e3abSDarrick J. Wong return count; 1161c0b4e3abSDarrick J. Wong } 1162c0b4e3abSDarrick J. Wong 1163c0b4e3abSDarrick J. Wong static ssize_t show_pwm_max(struct device *dev, 1164c0b4e3abSDarrick J. Wong struct device_attribute *devattr, 1165c0b4e3abSDarrick J. Wong char *buf) 1166c0b4e3abSDarrick J. Wong { 1167c0b4e3abSDarrick J. Wong struct adt7462_data *data = adt7462_update_device(dev); 1168c0b4e3abSDarrick J. Wong return sprintf(buf, "%d\n", data->pwm_max); 1169c0b4e3abSDarrick J. Wong } 1170c0b4e3abSDarrick J. Wong 1171c0b4e3abSDarrick J. Wong static ssize_t set_pwm_max(struct device *dev, 1172c0b4e3abSDarrick J. Wong struct device_attribute *devattr, 1173c0b4e3abSDarrick J. Wong const char *buf, 1174c0b4e3abSDarrick J. Wong size_t count) 1175c0b4e3abSDarrick J. Wong { 1176c0b4e3abSDarrick J. Wong struct i2c_client *client = to_i2c_client(dev); 1177c0b4e3abSDarrick J. Wong struct adt7462_data *data = i2c_get_clientdata(client); 1178c0b4e3abSDarrick J. Wong long temp; 1179c0b4e3abSDarrick J. Wong 1180179c4fdbSFrans Meulenbroeks if (kstrtol(buf, 10, &temp)) 1181c0b4e3abSDarrick J. Wong return -EINVAL; 1182c0b4e3abSDarrick J. Wong 1183c0b4e3abSDarrick J. Wong temp = SENSORS_LIMIT(temp, 0, 255); 1184c0b4e3abSDarrick J. Wong 1185c0b4e3abSDarrick J. Wong mutex_lock(&data->lock); 1186c0b4e3abSDarrick J. Wong data->pwm_max = temp; 1187c0b4e3abSDarrick J. Wong i2c_smbus_write_byte_data(client, ADT7462_REG_PWM_MAX, temp); 1188c0b4e3abSDarrick J. Wong mutex_unlock(&data->lock); 1189c0b4e3abSDarrick J. Wong 1190c0b4e3abSDarrick J. Wong return count; 1191c0b4e3abSDarrick J. Wong } 1192c0b4e3abSDarrick J. Wong 1193c0b4e3abSDarrick J. Wong static ssize_t show_pwm_min(struct device *dev, 1194c0b4e3abSDarrick J. Wong struct device_attribute *devattr, 1195c0b4e3abSDarrick J. Wong char *buf) 1196c0b4e3abSDarrick J. Wong { 1197c0b4e3abSDarrick J. Wong struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); 1198c0b4e3abSDarrick J. Wong struct adt7462_data *data = adt7462_update_device(dev); 1199c0b4e3abSDarrick J. Wong return sprintf(buf, "%d\n", data->pwm_min[attr->index]); 1200c0b4e3abSDarrick J. Wong } 1201c0b4e3abSDarrick J. Wong 1202c0b4e3abSDarrick J. Wong static ssize_t set_pwm_min(struct device *dev, 1203c0b4e3abSDarrick J. Wong struct device_attribute *devattr, 1204c0b4e3abSDarrick J. Wong const char *buf, 1205c0b4e3abSDarrick J. Wong size_t count) 1206c0b4e3abSDarrick J. Wong { 1207c0b4e3abSDarrick J. Wong struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); 1208c0b4e3abSDarrick J. Wong struct i2c_client *client = to_i2c_client(dev); 1209c0b4e3abSDarrick J. Wong struct adt7462_data *data = i2c_get_clientdata(client); 1210c0b4e3abSDarrick J. Wong long temp; 1211c0b4e3abSDarrick J. Wong 1212179c4fdbSFrans Meulenbroeks if (kstrtol(buf, 10, &temp)) 1213c0b4e3abSDarrick J. Wong return -EINVAL; 1214c0b4e3abSDarrick J. Wong 1215c0b4e3abSDarrick J. Wong temp = SENSORS_LIMIT(temp, 0, 255); 1216c0b4e3abSDarrick J. Wong 1217c0b4e3abSDarrick J. Wong mutex_lock(&data->lock); 1218c0b4e3abSDarrick J. Wong data->pwm_min[attr->index] = temp; 1219c0b4e3abSDarrick J. Wong i2c_smbus_write_byte_data(client, ADT7462_REG_PWM_MIN(attr->index), 1220c0b4e3abSDarrick J. Wong temp); 1221c0b4e3abSDarrick J. Wong mutex_unlock(&data->lock); 1222c0b4e3abSDarrick J. Wong 1223c0b4e3abSDarrick J. Wong return count; 1224c0b4e3abSDarrick J. Wong } 1225c0b4e3abSDarrick J. Wong 1226c0b4e3abSDarrick J. Wong static ssize_t show_pwm_hyst(struct device *dev, 1227c0b4e3abSDarrick J. Wong struct device_attribute *devattr, 1228c0b4e3abSDarrick J. Wong char *buf) 1229c0b4e3abSDarrick J. Wong { 1230c0b4e3abSDarrick J. Wong struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); 1231c0b4e3abSDarrick J. Wong struct adt7462_data *data = adt7462_update_device(dev); 1232c0b4e3abSDarrick J. Wong return sprintf(buf, "%d\n", 1000 * 1233c0b4e3abSDarrick J. Wong (data->pwm_trange[attr->index] & ADT7462_PWM_HYST_MASK)); 1234c0b4e3abSDarrick J. Wong } 1235c0b4e3abSDarrick J. Wong 1236c0b4e3abSDarrick J. Wong static ssize_t set_pwm_hyst(struct device *dev, 1237c0b4e3abSDarrick J. Wong struct device_attribute *devattr, 1238c0b4e3abSDarrick J. Wong const char *buf, 1239c0b4e3abSDarrick J. Wong size_t count) 1240c0b4e3abSDarrick J. Wong { 1241c0b4e3abSDarrick J. Wong struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); 1242c0b4e3abSDarrick J. Wong struct i2c_client *client = to_i2c_client(dev); 1243c0b4e3abSDarrick J. Wong struct adt7462_data *data = i2c_get_clientdata(client); 1244c0b4e3abSDarrick J. Wong long temp; 1245c0b4e3abSDarrick J. Wong 1246179c4fdbSFrans Meulenbroeks if (kstrtol(buf, 10, &temp)) 1247c0b4e3abSDarrick J. Wong return -EINVAL; 1248c0b4e3abSDarrick J. Wong 12498f8c1fb0SDarrick J. Wong temp = DIV_ROUND_CLOSEST(temp, 1000); 1250c0b4e3abSDarrick J. Wong temp = SENSORS_LIMIT(temp, 0, 15); 1251c0b4e3abSDarrick J. Wong 1252c0b4e3abSDarrick J. Wong /* package things up */ 1253c0b4e3abSDarrick J. Wong temp &= ADT7462_PWM_HYST_MASK; 1254c0b4e3abSDarrick J. Wong temp |= data->pwm_trange[attr->index] & ADT7462_PWM_RANGE_MASK; 1255c0b4e3abSDarrick J. Wong 1256c0b4e3abSDarrick J. Wong mutex_lock(&data->lock); 1257c0b4e3abSDarrick J. Wong data->pwm_trange[attr->index] = temp; 1258c0b4e3abSDarrick J. Wong i2c_smbus_write_byte_data(client, ADT7462_REG_PWM_TRANGE(attr->index), 1259c0b4e3abSDarrick J. Wong temp); 1260c0b4e3abSDarrick J. Wong mutex_unlock(&data->lock); 1261c0b4e3abSDarrick J. Wong 1262c0b4e3abSDarrick J. Wong return count; 1263c0b4e3abSDarrick J. Wong } 1264c0b4e3abSDarrick J. Wong 1265c0b4e3abSDarrick J. Wong static ssize_t show_pwm_tmax(struct device *dev, 1266c0b4e3abSDarrick J. Wong struct device_attribute *devattr, 1267c0b4e3abSDarrick J. Wong char *buf) 1268c0b4e3abSDarrick J. Wong { 1269c0b4e3abSDarrick J. Wong struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); 1270c0b4e3abSDarrick J. Wong struct adt7462_data *data = adt7462_update_device(dev); 1271c0b4e3abSDarrick J. Wong 1272c0b4e3abSDarrick J. Wong /* tmax = tmin + trange */ 1273c0b4e3abSDarrick J. Wong int trange = trange_values[data->pwm_trange[attr->index] >> 1274c0b4e3abSDarrick J. Wong ADT7462_PWM_RANGE_SHIFT]; 1275c0b4e3abSDarrick J. Wong int tmin = (data->pwm_tmin[attr->index] - 64) * 1000; 1276c0b4e3abSDarrick J. Wong 1277c0b4e3abSDarrick J. Wong return sprintf(buf, "%d\n", tmin + trange); 1278c0b4e3abSDarrick J. Wong } 1279c0b4e3abSDarrick J. Wong 1280c0b4e3abSDarrick J. Wong static ssize_t set_pwm_tmax(struct device *dev, 1281c0b4e3abSDarrick J. Wong struct device_attribute *devattr, 1282c0b4e3abSDarrick J. Wong const char *buf, 1283c0b4e3abSDarrick J. Wong size_t count) 1284c0b4e3abSDarrick J. Wong { 1285c0b4e3abSDarrick J. Wong int temp; 1286c0b4e3abSDarrick J. Wong struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); 1287c0b4e3abSDarrick J. Wong struct i2c_client *client = to_i2c_client(dev); 1288c0b4e3abSDarrick J. Wong struct adt7462_data *data = i2c_get_clientdata(client); 1289c0b4e3abSDarrick J. Wong int tmin, trange_value; 1290c0b4e3abSDarrick J. Wong long trange; 1291c0b4e3abSDarrick J. Wong 1292179c4fdbSFrans Meulenbroeks if (kstrtol(buf, 10, &trange)) 1293c0b4e3abSDarrick J. Wong return -EINVAL; 1294c0b4e3abSDarrick J. Wong 1295c0b4e3abSDarrick J. Wong /* trange = tmax - tmin */ 1296c0b4e3abSDarrick J. Wong tmin = (data->pwm_tmin[attr->index] - 64) * 1000; 1297c0b4e3abSDarrick J. Wong trange_value = find_trange_value(trange - tmin); 1298c0b4e3abSDarrick J. Wong 1299c0b4e3abSDarrick J. Wong if (trange_value < 0) 1300c0b4e3abSDarrick J. Wong return -EINVAL; 1301c0b4e3abSDarrick J. Wong 1302c0b4e3abSDarrick J. Wong temp = trange_value << ADT7462_PWM_RANGE_SHIFT; 1303c0b4e3abSDarrick J. Wong temp |= data->pwm_trange[attr->index] & ADT7462_PWM_HYST_MASK; 1304c0b4e3abSDarrick J. Wong 1305c0b4e3abSDarrick J. Wong mutex_lock(&data->lock); 1306c0b4e3abSDarrick J. Wong data->pwm_trange[attr->index] = temp; 1307c0b4e3abSDarrick J. Wong i2c_smbus_write_byte_data(client, ADT7462_REG_PWM_TRANGE(attr->index), 1308c0b4e3abSDarrick J. Wong temp); 1309c0b4e3abSDarrick J. Wong mutex_unlock(&data->lock); 1310c0b4e3abSDarrick J. Wong 1311c0b4e3abSDarrick J. Wong return count; 1312c0b4e3abSDarrick J. Wong } 1313c0b4e3abSDarrick J. Wong 1314c0b4e3abSDarrick J. Wong static ssize_t show_pwm_tmin(struct device *dev, 1315c0b4e3abSDarrick J. Wong struct device_attribute *devattr, 1316c0b4e3abSDarrick J. Wong char *buf) 1317c0b4e3abSDarrick J. Wong { 1318c0b4e3abSDarrick J. Wong struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); 1319c0b4e3abSDarrick J. Wong struct adt7462_data *data = adt7462_update_device(dev); 1320c0b4e3abSDarrick J. Wong return sprintf(buf, "%d\n", 1000 * (data->pwm_tmin[attr->index] - 64)); 1321c0b4e3abSDarrick J. Wong } 1322c0b4e3abSDarrick J. Wong 1323c0b4e3abSDarrick J. Wong static ssize_t set_pwm_tmin(struct device *dev, 1324c0b4e3abSDarrick J. Wong struct device_attribute *devattr, 1325c0b4e3abSDarrick J. Wong const char *buf, 1326c0b4e3abSDarrick J. Wong size_t count) 1327c0b4e3abSDarrick J. Wong { 1328c0b4e3abSDarrick J. Wong struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); 1329c0b4e3abSDarrick J. Wong struct i2c_client *client = to_i2c_client(dev); 1330c0b4e3abSDarrick J. Wong struct adt7462_data *data = i2c_get_clientdata(client); 1331c0b4e3abSDarrick J. Wong long temp; 1332c0b4e3abSDarrick J. Wong 1333179c4fdbSFrans Meulenbroeks if (kstrtol(buf, 10, &temp)) 1334c0b4e3abSDarrick J. Wong return -EINVAL; 1335c0b4e3abSDarrick J. Wong 13368f8c1fb0SDarrick J. Wong temp = DIV_ROUND_CLOSEST(temp, 1000) + 64; 1337c0b4e3abSDarrick J. Wong temp = SENSORS_LIMIT(temp, 0, 255); 1338c0b4e3abSDarrick J. Wong 1339c0b4e3abSDarrick J. Wong mutex_lock(&data->lock); 1340c0b4e3abSDarrick J. Wong data->pwm_tmin[attr->index] = temp; 1341c0b4e3abSDarrick J. Wong i2c_smbus_write_byte_data(client, ADT7462_REG_PWM_TMIN(attr->index), 1342c0b4e3abSDarrick J. Wong temp); 1343c0b4e3abSDarrick J. Wong mutex_unlock(&data->lock); 1344c0b4e3abSDarrick J. Wong 1345c0b4e3abSDarrick J. Wong return count; 1346c0b4e3abSDarrick J. Wong } 1347c0b4e3abSDarrick J. Wong 1348c0b4e3abSDarrick J. Wong static ssize_t show_pwm_auto(struct device *dev, 1349c0b4e3abSDarrick J. Wong struct device_attribute *devattr, 1350c0b4e3abSDarrick J. Wong char *buf) 1351c0b4e3abSDarrick J. Wong { 1352c0b4e3abSDarrick J. Wong struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); 1353c0b4e3abSDarrick J. Wong struct adt7462_data *data = adt7462_update_device(dev); 1354c0b4e3abSDarrick J. Wong int cfg = data->pwm_cfg[attr->index] >> ADT7462_PWM_CHANNEL_SHIFT; 1355c0b4e3abSDarrick J. Wong 1356c0b4e3abSDarrick J. Wong switch (cfg) { 1357c0b4e3abSDarrick J. Wong case 4: /* off */ 1358c0b4e3abSDarrick J. Wong return sprintf(buf, "0\n"); 1359c0b4e3abSDarrick J. Wong case 7: /* manual */ 1360c0b4e3abSDarrick J. Wong return sprintf(buf, "1\n"); 1361c0b4e3abSDarrick J. Wong default: /* automatic */ 1362c0b4e3abSDarrick J. Wong return sprintf(buf, "2\n"); 1363c0b4e3abSDarrick J. Wong } 1364c0b4e3abSDarrick J. Wong } 1365c0b4e3abSDarrick J. Wong 1366c0b4e3abSDarrick J. Wong static void set_pwm_channel(struct i2c_client *client, 1367c0b4e3abSDarrick J. Wong struct adt7462_data *data, 1368c0b4e3abSDarrick J. Wong int which, 1369c0b4e3abSDarrick J. Wong int value) 1370c0b4e3abSDarrick J. Wong { 1371c0b4e3abSDarrick J. Wong int temp = data->pwm_cfg[which] & ~ADT7462_PWM_CHANNEL_MASK; 1372c0b4e3abSDarrick J. Wong temp |= value << ADT7462_PWM_CHANNEL_SHIFT; 1373c0b4e3abSDarrick J. Wong 1374c0b4e3abSDarrick J. Wong mutex_lock(&data->lock); 1375c0b4e3abSDarrick J. Wong data->pwm_cfg[which] = temp; 1376c0b4e3abSDarrick J. Wong i2c_smbus_write_byte_data(client, ADT7462_REG_PWM_CFG(which), temp); 1377c0b4e3abSDarrick J. Wong mutex_unlock(&data->lock); 1378c0b4e3abSDarrick J. Wong } 1379c0b4e3abSDarrick J. Wong 1380c0b4e3abSDarrick J. Wong static ssize_t set_pwm_auto(struct device *dev, 1381c0b4e3abSDarrick J. Wong struct device_attribute *devattr, 1382c0b4e3abSDarrick J. Wong const char *buf, 1383c0b4e3abSDarrick J. Wong size_t count) 1384c0b4e3abSDarrick J. Wong { 1385c0b4e3abSDarrick J. Wong struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); 1386c0b4e3abSDarrick J. Wong struct i2c_client *client = to_i2c_client(dev); 1387c0b4e3abSDarrick J. Wong struct adt7462_data *data = i2c_get_clientdata(client); 1388c0b4e3abSDarrick J. Wong long temp; 1389c0b4e3abSDarrick J. Wong 1390179c4fdbSFrans Meulenbroeks if (kstrtol(buf, 10, &temp)) 1391c0b4e3abSDarrick J. Wong return -EINVAL; 1392c0b4e3abSDarrick J. Wong 1393c0b4e3abSDarrick J. Wong switch (temp) { 1394c0b4e3abSDarrick J. Wong case 0: /* off */ 1395c0b4e3abSDarrick J. Wong set_pwm_channel(client, data, attr->index, 4); 1396c0b4e3abSDarrick J. Wong return count; 1397c0b4e3abSDarrick J. Wong case 1: /* manual */ 1398c0b4e3abSDarrick J. Wong set_pwm_channel(client, data, attr->index, 7); 1399c0b4e3abSDarrick J. Wong return count; 1400c0b4e3abSDarrick J. Wong default: 1401c0b4e3abSDarrick J. Wong return -EINVAL; 1402c0b4e3abSDarrick J. Wong } 1403c0b4e3abSDarrick J. Wong } 1404c0b4e3abSDarrick J. Wong 1405c0b4e3abSDarrick J. Wong static ssize_t show_pwm_auto_temp(struct device *dev, 1406c0b4e3abSDarrick J. Wong struct device_attribute *devattr, 1407c0b4e3abSDarrick J. Wong char *buf) 1408c0b4e3abSDarrick J. Wong { 1409c0b4e3abSDarrick J. Wong struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); 1410c0b4e3abSDarrick J. Wong struct adt7462_data *data = adt7462_update_device(dev); 1411c0b4e3abSDarrick J. Wong int channel = data->pwm_cfg[attr->index] >> ADT7462_PWM_CHANNEL_SHIFT; 1412c0b4e3abSDarrick J. Wong 1413c0b4e3abSDarrick J. Wong switch (channel) { 1414c0b4e3abSDarrick J. Wong case 0: /* temp[1234] only */ 1415c0b4e3abSDarrick J. Wong case 1: 1416c0b4e3abSDarrick J. Wong case 2: 1417c0b4e3abSDarrick J. Wong case 3: 1418c0b4e3abSDarrick J. Wong return sprintf(buf, "%d\n", (1 << channel)); 1419c0b4e3abSDarrick J. Wong case 5: /* temp1 & temp4 */ 1420c0b4e3abSDarrick J. Wong return sprintf(buf, "9\n"); 1421c0b4e3abSDarrick J. Wong case 6: 1422c0b4e3abSDarrick J. Wong return sprintf(buf, "15\n"); 1423c0b4e3abSDarrick J. Wong default: 1424c0b4e3abSDarrick J. Wong return sprintf(buf, "0\n"); 1425c0b4e3abSDarrick J. Wong } 1426c0b4e3abSDarrick J. Wong } 1427c0b4e3abSDarrick J. Wong 1428c0b4e3abSDarrick J. Wong static int cvt_auto_temp(int input) 1429c0b4e3abSDarrick J. Wong { 1430c0b4e3abSDarrick J. Wong if (input == 0xF) 1431c0b4e3abSDarrick J. Wong return 6; 1432c0b4e3abSDarrick J. Wong if (input == 0x9) 1433c0b4e3abSDarrick J. Wong return 5; 1434c0b4e3abSDarrick J. Wong if (input < 1 || !is_power_of_2(input)) 1435c0b4e3abSDarrick J. Wong return -EINVAL; 1436c0b4e3abSDarrick J. Wong return ilog2(input); 1437c0b4e3abSDarrick J. Wong } 1438c0b4e3abSDarrick J. Wong 1439c0b4e3abSDarrick J. Wong static ssize_t set_pwm_auto_temp(struct device *dev, 1440c0b4e3abSDarrick J. Wong struct device_attribute *devattr, 1441c0b4e3abSDarrick J. Wong const char *buf, 1442c0b4e3abSDarrick J. Wong size_t count) 1443c0b4e3abSDarrick J. Wong { 1444c0b4e3abSDarrick J. Wong struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); 1445c0b4e3abSDarrick J. Wong struct i2c_client *client = to_i2c_client(dev); 1446c0b4e3abSDarrick J. Wong struct adt7462_data *data = i2c_get_clientdata(client); 1447c0b4e3abSDarrick J. Wong long temp; 1448c0b4e3abSDarrick J. Wong 1449179c4fdbSFrans Meulenbroeks if (kstrtol(buf, 10, &temp)) 1450c0b4e3abSDarrick J. Wong return -EINVAL; 1451c0b4e3abSDarrick J. Wong 1452c0b4e3abSDarrick J. Wong temp = cvt_auto_temp(temp); 1453c0b4e3abSDarrick J. Wong if (temp < 0) 1454c0b4e3abSDarrick J. Wong return temp; 1455c0b4e3abSDarrick J. Wong 1456c0b4e3abSDarrick J. Wong set_pwm_channel(client, data, attr->index, temp); 1457c0b4e3abSDarrick J. Wong 1458c0b4e3abSDarrick J. Wong return count; 1459c0b4e3abSDarrick J. Wong } 1460c0b4e3abSDarrick J. Wong 1461c0b4e3abSDarrick J. Wong static SENSOR_DEVICE_ATTR(temp1_max, S_IWUSR | S_IRUGO, show_temp_max, 1462c0b4e3abSDarrick J. Wong set_temp_max, 0); 1463c0b4e3abSDarrick J. Wong static SENSOR_DEVICE_ATTR(temp2_max, S_IWUSR | S_IRUGO, show_temp_max, 1464c0b4e3abSDarrick J. Wong set_temp_max, 1); 1465c0b4e3abSDarrick J. Wong static SENSOR_DEVICE_ATTR(temp3_max, S_IWUSR | S_IRUGO, show_temp_max, 1466c0b4e3abSDarrick J. Wong set_temp_max, 2); 1467c0b4e3abSDarrick J. Wong static SENSOR_DEVICE_ATTR(temp4_max, S_IWUSR | S_IRUGO, show_temp_max, 1468c0b4e3abSDarrick J. Wong set_temp_max, 3); 1469c0b4e3abSDarrick J. Wong 1470c0b4e3abSDarrick J. Wong static SENSOR_DEVICE_ATTR(temp1_min, S_IWUSR | S_IRUGO, show_temp_min, 1471c0b4e3abSDarrick J. Wong set_temp_min, 0); 1472c0b4e3abSDarrick J. Wong static SENSOR_DEVICE_ATTR(temp2_min, S_IWUSR | S_IRUGO, show_temp_min, 1473c0b4e3abSDarrick J. Wong set_temp_min, 1); 1474c0b4e3abSDarrick J. Wong static SENSOR_DEVICE_ATTR(temp3_min, S_IWUSR | S_IRUGO, show_temp_min, 1475c0b4e3abSDarrick J. Wong set_temp_min, 2); 1476c0b4e3abSDarrick J. Wong static SENSOR_DEVICE_ATTR(temp4_min, S_IWUSR | S_IRUGO, show_temp_min, 1477c0b4e3abSDarrick J. Wong set_temp_min, 3); 1478c0b4e3abSDarrick J. Wong 1479c0b4e3abSDarrick J. Wong static SENSOR_DEVICE_ATTR(temp1_input, S_IRUGO, show_temp, NULL, 0); 1480c0b4e3abSDarrick J. Wong static SENSOR_DEVICE_ATTR(temp2_input, S_IRUGO, show_temp, NULL, 1); 1481c0b4e3abSDarrick J. Wong static SENSOR_DEVICE_ATTR(temp3_input, S_IRUGO, show_temp, NULL, 2); 1482c0b4e3abSDarrick J. Wong static SENSOR_DEVICE_ATTR(temp4_input, S_IRUGO, show_temp, NULL, 3); 1483c0b4e3abSDarrick J. Wong 1484c0b4e3abSDarrick J. Wong static SENSOR_DEVICE_ATTR(temp1_label, S_IRUGO, show_temp_label, NULL, 0); 1485c0b4e3abSDarrick J. Wong static SENSOR_DEVICE_ATTR(temp2_label, S_IRUGO, show_temp_label, NULL, 1); 1486c0b4e3abSDarrick J. Wong static SENSOR_DEVICE_ATTR(temp3_label, S_IRUGO, show_temp_label, NULL, 2); 1487c0b4e3abSDarrick J. Wong static SENSOR_DEVICE_ATTR(temp4_label, S_IRUGO, show_temp_label, NULL, 3); 1488c0b4e3abSDarrick J. Wong 1489c0b4e3abSDarrick J. Wong static SENSOR_DEVICE_ATTR(temp1_alarm, S_IRUGO, show_alarm, NULL, 1490c0b4e3abSDarrick J. Wong ADT7462_ALARM1 | ADT7462_LT_ALARM); 1491c0b4e3abSDarrick J. Wong static SENSOR_DEVICE_ATTR(temp2_alarm, S_IRUGO, show_alarm, NULL, 1492c0b4e3abSDarrick J. Wong ADT7462_ALARM1 | ADT7462_R1T_ALARM); 1493c0b4e3abSDarrick J. Wong static SENSOR_DEVICE_ATTR(temp3_alarm, S_IRUGO, show_alarm, NULL, 1494c0b4e3abSDarrick J. Wong ADT7462_ALARM1 | ADT7462_R2T_ALARM); 1495c0b4e3abSDarrick J. Wong static SENSOR_DEVICE_ATTR(temp4_alarm, S_IRUGO, show_alarm, NULL, 1496c0b4e3abSDarrick J. Wong ADT7462_ALARM1 | ADT7462_R3T_ALARM); 1497c0b4e3abSDarrick J. Wong 1498c0b4e3abSDarrick J. Wong static SENSOR_DEVICE_ATTR(in1_max, S_IWUSR | S_IRUGO, show_volt_max, 1499c0b4e3abSDarrick J. Wong set_volt_max, 0); 1500c0b4e3abSDarrick J. Wong static SENSOR_DEVICE_ATTR(in2_max, S_IWUSR | S_IRUGO, show_volt_max, 1501c0b4e3abSDarrick J. Wong set_volt_max, 1); 1502c0b4e3abSDarrick J. Wong static SENSOR_DEVICE_ATTR(in3_max, S_IWUSR | S_IRUGO, show_volt_max, 1503c0b4e3abSDarrick J. Wong set_volt_max, 2); 1504c0b4e3abSDarrick J. Wong static SENSOR_DEVICE_ATTR(in4_max, S_IWUSR | S_IRUGO, show_volt_max, 1505c0b4e3abSDarrick J. Wong set_volt_max, 3); 1506c0b4e3abSDarrick J. Wong static SENSOR_DEVICE_ATTR(in5_max, S_IWUSR | S_IRUGO, show_volt_max, 1507c0b4e3abSDarrick J. Wong set_volt_max, 4); 1508c0b4e3abSDarrick J. Wong static SENSOR_DEVICE_ATTR(in6_max, S_IWUSR | S_IRUGO, show_volt_max, 1509c0b4e3abSDarrick J. Wong set_volt_max, 5); 1510c0b4e3abSDarrick J. Wong static SENSOR_DEVICE_ATTR(in7_max, S_IWUSR | S_IRUGO, show_volt_max, 1511c0b4e3abSDarrick J. Wong set_volt_max, 6); 1512c0b4e3abSDarrick J. Wong static SENSOR_DEVICE_ATTR(in8_max, S_IWUSR | S_IRUGO, show_volt_max, 1513c0b4e3abSDarrick J. Wong set_volt_max, 7); 1514c0b4e3abSDarrick J. Wong static SENSOR_DEVICE_ATTR(in9_max, S_IWUSR | S_IRUGO, show_volt_max, 1515c0b4e3abSDarrick J. Wong set_volt_max, 8); 1516c0b4e3abSDarrick J. Wong static SENSOR_DEVICE_ATTR(in10_max, S_IWUSR | S_IRUGO, show_volt_max, 1517c0b4e3abSDarrick J. Wong set_volt_max, 9); 1518c0b4e3abSDarrick J. Wong static SENSOR_DEVICE_ATTR(in11_max, S_IWUSR | S_IRUGO, show_volt_max, 1519c0b4e3abSDarrick J. Wong set_volt_max, 10); 1520c0b4e3abSDarrick J. Wong static SENSOR_DEVICE_ATTR(in12_max, S_IWUSR | S_IRUGO, show_volt_max, 1521c0b4e3abSDarrick J. Wong set_volt_max, 11); 1522c0b4e3abSDarrick J. Wong static SENSOR_DEVICE_ATTR(in13_max, S_IWUSR | S_IRUGO, show_volt_max, 1523c0b4e3abSDarrick J. Wong set_volt_max, 12); 1524c0b4e3abSDarrick J. Wong 1525c0b4e3abSDarrick J. Wong static SENSOR_DEVICE_ATTR(in1_min, S_IWUSR | S_IRUGO, show_volt_min, 1526c0b4e3abSDarrick J. Wong set_volt_min, 0); 1527c0b4e3abSDarrick J. Wong static SENSOR_DEVICE_ATTR(in2_min, S_IWUSR | S_IRUGO, show_volt_min, 1528c0b4e3abSDarrick J. Wong set_volt_min, 1); 1529c0b4e3abSDarrick J. Wong static SENSOR_DEVICE_ATTR(in3_min, S_IWUSR | S_IRUGO, show_volt_min, 1530c0b4e3abSDarrick J. Wong set_volt_min, 2); 1531c0b4e3abSDarrick J. Wong static SENSOR_DEVICE_ATTR(in4_min, S_IWUSR | S_IRUGO, show_volt_min, 1532c0b4e3abSDarrick J. Wong set_volt_min, 3); 1533c0b4e3abSDarrick J. Wong static SENSOR_DEVICE_ATTR(in5_min, S_IWUSR | S_IRUGO, show_volt_min, 1534c0b4e3abSDarrick J. Wong set_volt_min, 4); 1535c0b4e3abSDarrick J. Wong static SENSOR_DEVICE_ATTR(in6_min, S_IWUSR | S_IRUGO, show_volt_min, 1536c0b4e3abSDarrick J. Wong set_volt_min, 5); 1537c0b4e3abSDarrick J. Wong static SENSOR_DEVICE_ATTR(in7_min, S_IWUSR | S_IRUGO, show_volt_min, 1538c0b4e3abSDarrick J. Wong set_volt_min, 6); 1539c0b4e3abSDarrick J. Wong static SENSOR_DEVICE_ATTR(in8_min, S_IWUSR | S_IRUGO, show_volt_min, 1540c0b4e3abSDarrick J. Wong set_volt_min, 7); 1541c0b4e3abSDarrick J. Wong static SENSOR_DEVICE_ATTR(in9_min, S_IWUSR | S_IRUGO, show_volt_min, 1542c0b4e3abSDarrick J. Wong set_volt_min, 8); 1543c0b4e3abSDarrick J. Wong static SENSOR_DEVICE_ATTR(in10_min, S_IWUSR | S_IRUGO, show_volt_min, 1544c0b4e3abSDarrick J. Wong set_volt_min, 9); 1545c0b4e3abSDarrick J. Wong static SENSOR_DEVICE_ATTR(in11_min, S_IWUSR | S_IRUGO, show_volt_min, 1546c0b4e3abSDarrick J. Wong set_volt_min, 10); 1547c0b4e3abSDarrick J. Wong static SENSOR_DEVICE_ATTR(in12_min, S_IWUSR | S_IRUGO, show_volt_min, 1548c0b4e3abSDarrick J. Wong set_volt_min, 11); 1549c0b4e3abSDarrick J. Wong static SENSOR_DEVICE_ATTR(in13_min, S_IWUSR | S_IRUGO, show_volt_min, 1550c0b4e3abSDarrick J. Wong set_volt_min, 12); 1551c0b4e3abSDarrick J. Wong 1552c0b4e3abSDarrick J. Wong static SENSOR_DEVICE_ATTR(in1_input, S_IRUGO, show_voltage, NULL, 0); 1553c0b4e3abSDarrick J. Wong static SENSOR_DEVICE_ATTR(in2_input, S_IRUGO, show_voltage, NULL, 1); 1554c0b4e3abSDarrick J. Wong static SENSOR_DEVICE_ATTR(in3_input, S_IRUGO, show_voltage, NULL, 2); 1555c0b4e3abSDarrick J. Wong static SENSOR_DEVICE_ATTR(in4_input, S_IRUGO, show_voltage, NULL, 3); 1556c0b4e3abSDarrick J. Wong static SENSOR_DEVICE_ATTR(in5_input, S_IRUGO, show_voltage, NULL, 4); 1557c0b4e3abSDarrick J. Wong static SENSOR_DEVICE_ATTR(in6_input, S_IRUGO, show_voltage, NULL, 5); 1558c0b4e3abSDarrick J. Wong static SENSOR_DEVICE_ATTR(in7_input, S_IRUGO, show_voltage, NULL, 6); 1559c0b4e3abSDarrick J. Wong static SENSOR_DEVICE_ATTR(in8_input, S_IRUGO, show_voltage, NULL, 7); 1560c0b4e3abSDarrick J. Wong static SENSOR_DEVICE_ATTR(in9_input, S_IRUGO, show_voltage, NULL, 8); 1561c0b4e3abSDarrick J. Wong static SENSOR_DEVICE_ATTR(in10_input, S_IRUGO, show_voltage, NULL, 9); 1562c0b4e3abSDarrick J. Wong static SENSOR_DEVICE_ATTR(in11_input, S_IRUGO, show_voltage, NULL, 10); 1563c0b4e3abSDarrick J. Wong static SENSOR_DEVICE_ATTR(in12_input, S_IRUGO, show_voltage, NULL, 11); 1564c0b4e3abSDarrick J. Wong static SENSOR_DEVICE_ATTR(in13_input, S_IRUGO, show_voltage, NULL, 12); 1565c0b4e3abSDarrick J. Wong 1566c0b4e3abSDarrick J. Wong static SENSOR_DEVICE_ATTR(in1_label, S_IRUGO, show_voltage_label, NULL, 0); 1567c0b4e3abSDarrick J. Wong static SENSOR_DEVICE_ATTR(in2_label, S_IRUGO, show_voltage_label, NULL, 1); 1568c0b4e3abSDarrick J. Wong static SENSOR_DEVICE_ATTR(in3_label, S_IRUGO, show_voltage_label, NULL, 2); 1569c0b4e3abSDarrick J. Wong static SENSOR_DEVICE_ATTR(in4_label, S_IRUGO, show_voltage_label, NULL, 3); 1570c0b4e3abSDarrick J. Wong static SENSOR_DEVICE_ATTR(in5_label, S_IRUGO, show_voltage_label, NULL, 4); 1571c0b4e3abSDarrick J. Wong static SENSOR_DEVICE_ATTR(in6_label, S_IRUGO, show_voltage_label, NULL, 5); 1572c0b4e3abSDarrick J. Wong static SENSOR_DEVICE_ATTR(in7_label, S_IRUGO, show_voltage_label, NULL, 6); 1573c0b4e3abSDarrick J. Wong static SENSOR_DEVICE_ATTR(in8_label, S_IRUGO, show_voltage_label, NULL, 7); 1574c0b4e3abSDarrick J. Wong static SENSOR_DEVICE_ATTR(in9_label, S_IRUGO, show_voltage_label, NULL, 8); 1575c0b4e3abSDarrick J. Wong static SENSOR_DEVICE_ATTR(in10_label, S_IRUGO, show_voltage_label, NULL, 9); 1576c0b4e3abSDarrick J. Wong static SENSOR_DEVICE_ATTR(in11_label, S_IRUGO, show_voltage_label, NULL, 10); 1577c0b4e3abSDarrick J. Wong static SENSOR_DEVICE_ATTR(in12_label, S_IRUGO, show_voltage_label, NULL, 11); 1578c0b4e3abSDarrick J. Wong static SENSOR_DEVICE_ATTR(in13_label, S_IRUGO, show_voltage_label, NULL, 12); 1579c0b4e3abSDarrick J. Wong 1580c0b4e3abSDarrick J. Wong static SENSOR_DEVICE_ATTR(in1_alarm, S_IRUGO, show_alarm, NULL, 1581c0b4e3abSDarrick J. Wong ADT7462_ALARM2 | ADT7462_V0_ALARM); 1582c0b4e3abSDarrick J. Wong static SENSOR_DEVICE_ATTR(in2_alarm, S_IRUGO, show_alarm, NULL, 1583c0b4e3abSDarrick J. Wong ADT7462_ALARM2 | ADT7462_V7_ALARM); 1584c0b4e3abSDarrick J. Wong static SENSOR_DEVICE_ATTR(in3_alarm, S_IRUGO, show_alarm, NULL, 1585c0b4e3abSDarrick J. Wong ADT7462_ALARM2 | ADT7462_V2_ALARM); 1586c0b4e3abSDarrick J. Wong static SENSOR_DEVICE_ATTR(in4_alarm, S_IRUGO, show_alarm, NULL, 1587c0b4e3abSDarrick J. Wong ADT7462_ALARM2 | ADT7462_V6_ALARM); 1588c0b4e3abSDarrick J. Wong static SENSOR_DEVICE_ATTR(in5_alarm, S_IRUGO, show_alarm, NULL, 1589c0b4e3abSDarrick J. Wong ADT7462_ALARM2 | ADT7462_V5_ALARM); 1590c0b4e3abSDarrick J. Wong static SENSOR_DEVICE_ATTR(in6_alarm, S_IRUGO, show_alarm, NULL, 1591c0b4e3abSDarrick J. Wong ADT7462_ALARM2 | ADT7462_V4_ALARM); 1592c0b4e3abSDarrick J. Wong static SENSOR_DEVICE_ATTR(in7_alarm, S_IRUGO, show_alarm, NULL, 1593c0b4e3abSDarrick J. Wong ADT7462_ALARM2 | ADT7462_V3_ALARM); 1594c0b4e3abSDarrick J. Wong static SENSOR_DEVICE_ATTR(in8_alarm, S_IRUGO, show_alarm, NULL, 1595c0b4e3abSDarrick J. Wong ADT7462_ALARM2 | ADT7462_V1_ALARM); 1596c0b4e3abSDarrick J. Wong static SENSOR_DEVICE_ATTR(in9_alarm, S_IRUGO, show_alarm, NULL, 1597c0b4e3abSDarrick J. Wong ADT7462_ALARM3 | ADT7462_V10_ALARM); 1598c0b4e3abSDarrick J. Wong static SENSOR_DEVICE_ATTR(in10_alarm, S_IRUGO, show_alarm, NULL, 1599c0b4e3abSDarrick J. Wong ADT7462_ALARM3 | ADT7462_V9_ALARM); 1600c0b4e3abSDarrick J. Wong static SENSOR_DEVICE_ATTR(in11_alarm, S_IRUGO, show_alarm, NULL, 1601c0b4e3abSDarrick J. Wong ADT7462_ALARM3 | ADT7462_V8_ALARM); 1602c0b4e3abSDarrick J. Wong static SENSOR_DEVICE_ATTR(in12_alarm, S_IRUGO, show_alarm, NULL, 1603c0b4e3abSDarrick J. Wong ADT7462_ALARM3 | ADT7462_V11_ALARM); 1604c0b4e3abSDarrick J. Wong static SENSOR_DEVICE_ATTR(in13_alarm, S_IRUGO, show_alarm, NULL, 1605c0b4e3abSDarrick J. Wong ADT7462_ALARM3 | ADT7462_V12_ALARM); 1606c0b4e3abSDarrick J. Wong 1607c0b4e3abSDarrick J. Wong static SENSOR_DEVICE_ATTR(fan1_min, S_IWUSR | S_IRUGO, show_fan_min, 1608c0b4e3abSDarrick J. Wong set_fan_min, 0); 1609c0b4e3abSDarrick J. Wong static SENSOR_DEVICE_ATTR(fan2_min, S_IWUSR | S_IRUGO, show_fan_min, 1610c0b4e3abSDarrick J. Wong set_fan_min, 1); 1611c0b4e3abSDarrick J. Wong static SENSOR_DEVICE_ATTR(fan3_min, S_IWUSR | S_IRUGO, show_fan_min, 1612c0b4e3abSDarrick J. Wong set_fan_min, 2); 1613c0b4e3abSDarrick J. Wong static SENSOR_DEVICE_ATTR(fan4_min, S_IWUSR | S_IRUGO, show_fan_min, 1614c0b4e3abSDarrick J. Wong set_fan_min, 3); 1615c0b4e3abSDarrick J. Wong static SENSOR_DEVICE_ATTR(fan5_min, S_IWUSR | S_IRUGO, show_fan_min, 1616c0b4e3abSDarrick J. Wong set_fan_min, 4); 1617c0b4e3abSDarrick J. Wong static SENSOR_DEVICE_ATTR(fan6_min, S_IWUSR | S_IRUGO, show_fan_min, 1618c0b4e3abSDarrick J. Wong set_fan_min, 5); 1619c0b4e3abSDarrick J. Wong static SENSOR_DEVICE_ATTR(fan7_min, S_IWUSR | S_IRUGO, show_fan_min, 1620c0b4e3abSDarrick J. Wong set_fan_min, 6); 1621c0b4e3abSDarrick J. Wong static SENSOR_DEVICE_ATTR(fan8_min, S_IWUSR | S_IRUGO, show_fan_min, 1622c0b4e3abSDarrick J. Wong set_fan_min, 7); 1623c0b4e3abSDarrick J. Wong 1624c0b4e3abSDarrick J. Wong static SENSOR_DEVICE_ATTR(fan1_input, S_IRUGO, show_fan, NULL, 0); 1625c0b4e3abSDarrick J. Wong static SENSOR_DEVICE_ATTR(fan2_input, S_IRUGO, show_fan, NULL, 1); 1626c0b4e3abSDarrick J. Wong static SENSOR_DEVICE_ATTR(fan3_input, S_IRUGO, show_fan, NULL, 2); 1627c0b4e3abSDarrick J. Wong static SENSOR_DEVICE_ATTR(fan4_input, S_IRUGO, show_fan, NULL, 3); 1628c0b4e3abSDarrick J. Wong static SENSOR_DEVICE_ATTR(fan5_input, S_IRUGO, show_fan, NULL, 4); 1629c0b4e3abSDarrick J. Wong static SENSOR_DEVICE_ATTR(fan6_input, S_IRUGO, show_fan, NULL, 5); 1630c0b4e3abSDarrick J. Wong static SENSOR_DEVICE_ATTR(fan7_input, S_IRUGO, show_fan, NULL, 6); 1631c0b4e3abSDarrick J. Wong static SENSOR_DEVICE_ATTR(fan8_input, S_IRUGO, show_fan, NULL, 7); 1632c0b4e3abSDarrick J. Wong 1633c0b4e3abSDarrick J. Wong static SENSOR_DEVICE_ATTR(fan1_alarm, S_IRUGO, show_alarm, NULL, 1634c0b4e3abSDarrick J. Wong ADT7462_ALARM4 | ADT7462_F0_ALARM); 1635c0b4e3abSDarrick J. Wong static SENSOR_DEVICE_ATTR(fan2_alarm, S_IRUGO, show_alarm, NULL, 1636c0b4e3abSDarrick J. Wong ADT7462_ALARM4 | ADT7462_F1_ALARM); 1637c0b4e3abSDarrick J. Wong static SENSOR_DEVICE_ATTR(fan3_alarm, S_IRUGO, show_alarm, NULL, 1638c0b4e3abSDarrick J. Wong ADT7462_ALARM4 | ADT7462_F2_ALARM); 1639c0b4e3abSDarrick J. Wong static SENSOR_DEVICE_ATTR(fan4_alarm, S_IRUGO, show_alarm, NULL, 1640c0b4e3abSDarrick J. Wong ADT7462_ALARM4 | ADT7462_F3_ALARM); 1641c0b4e3abSDarrick J. Wong static SENSOR_DEVICE_ATTR(fan5_alarm, S_IRUGO, show_alarm, NULL, 1642c0b4e3abSDarrick J. Wong ADT7462_ALARM4 | ADT7462_F4_ALARM); 1643c0b4e3abSDarrick J. Wong static SENSOR_DEVICE_ATTR(fan6_alarm, S_IRUGO, show_alarm, NULL, 1644c0b4e3abSDarrick J. Wong ADT7462_ALARM4 | ADT7462_F5_ALARM); 1645c0b4e3abSDarrick J. Wong static SENSOR_DEVICE_ATTR(fan7_alarm, S_IRUGO, show_alarm, NULL, 1646c0b4e3abSDarrick J. Wong ADT7462_ALARM4 | ADT7462_F6_ALARM); 1647c0b4e3abSDarrick J. Wong static SENSOR_DEVICE_ATTR(fan8_alarm, S_IRUGO, show_alarm, NULL, 1648c0b4e3abSDarrick J. Wong ADT7462_ALARM4 | ADT7462_F7_ALARM); 1649c0b4e3abSDarrick J. Wong 1650c0b4e3abSDarrick J. Wong static SENSOR_DEVICE_ATTR(force_pwm_max, S_IWUSR | S_IRUGO, 1651c0b4e3abSDarrick J. Wong show_force_pwm_max, set_force_pwm_max, 0); 1652c0b4e3abSDarrick J. Wong 1653c0b4e3abSDarrick J. Wong static SENSOR_DEVICE_ATTR(pwm1, S_IWUSR | S_IRUGO, show_pwm, set_pwm, 0); 1654c0b4e3abSDarrick J. Wong static SENSOR_DEVICE_ATTR(pwm2, S_IWUSR | S_IRUGO, show_pwm, set_pwm, 1); 1655c0b4e3abSDarrick J. Wong static SENSOR_DEVICE_ATTR(pwm3, S_IWUSR | S_IRUGO, show_pwm, set_pwm, 2); 1656c0b4e3abSDarrick J. Wong static SENSOR_DEVICE_ATTR(pwm4, S_IWUSR | S_IRUGO, show_pwm, set_pwm, 3); 1657c0b4e3abSDarrick J. Wong 1658c0b4e3abSDarrick J. Wong static SENSOR_DEVICE_ATTR(pwm1_auto_point1_pwm, S_IWUSR | S_IRUGO, 1659c0b4e3abSDarrick J. Wong show_pwm_min, set_pwm_min, 0); 1660c0b4e3abSDarrick J. Wong static SENSOR_DEVICE_ATTR(pwm2_auto_point1_pwm, S_IWUSR | S_IRUGO, 1661c0b4e3abSDarrick J. Wong show_pwm_min, set_pwm_min, 1); 1662c0b4e3abSDarrick J. Wong static SENSOR_DEVICE_ATTR(pwm3_auto_point1_pwm, S_IWUSR | S_IRUGO, 1663c0b4e3abSDarrick J. Wong show_pwm_min, set_pwm_min, 2); 1664c0b4e3abSDarrick J. Wong static SENSOR_DEVICE_ATTR(pwm4_auto_point1_pwm, S_IWUSR | S_IRUGO, 1665c0b4e3abSDarrick J. Wong show_pwm_min, set_pwm_min, 3); 1666c0b4e3abSDarrick J. Wong 1667c0b4e3abSDarrick J. Wong static SENSOR_DEVICE_ATTR(pwm1_auto_point2_pwm, S_IWUSR | S_IRUGO, 1668c0b4e3abSDarrick J. Wong show_pwm_max, set_pwm_max, 0); 1669c0b4e3abSDarrick J. Wong static SENSOR_DEVICE_ATTR(pwm2_auto_point2_pwm, S_IWUSR | S_IRUGO, 1670c0b4e3abSDarrick J. Wong show_pwm_max, set_pwm_max, 1); 1671c0b4e3abSDarrick J. Wong static SENSOR_DEVICE_ATTR(pwm3_auto_point2_pwm, S_IWUSR | S_IRUGO, 1672c0b4e3abSDarrick J. Wong show_pwm_max, set_pwm_max, 2); 1673c0b4e3abSDarrick J. Wong static SENSOR_DEVICE_ATTR(pwm4_auto_point2_pwm, S_IWUSR | S_IRUGO, 1674c0b4e3abSDarrick J. Wong show_pwm_max, set_pwm_max, 3); 1675c0b4e3abSDarrick J. Wong 1676c0b4e3abSDarrick J. Wong static SENSOR_DEVICE_ATTR(temp1_auto_point1_hyst, S_IWUSR | S_IRUGO, 1677c0b4e3abSDarrick J. Wong show_pwm_hyst, set_pwm_hyst, 0); 1678c0b4e3abSDarrick J. Wong static SENSOR_DEVICE_ATTR(temp2_auto_point1_hyst, S_IWUSR | S_IRUGO, 1679c0b4e3abSDarrick J. Wong show_pwm_hyst, set_pwm_hyst, 1); 1680c0b4e3abSDarrick J. Wong static SENSOR_DEVICE_ATTR(temp3_auto_point1_hyst, S_IWUSR | S_IRUGO, 1681c0b4e3abSDarrick J. Wong show_pwm_hyst, set_pwm_hyst, 2); 1682c0b4e3abSDarrick J. Wong static SENSOR_DEVICE_ATTR(temp4_auto_point1_hyst, S_IWUSR | S_IRUGO, 1683c0b4e3abSDarrick J. Wong show_pwm_hyst, set_pwm_hyst, 3); 1684c0b4e3abSDarrick J. Wong 1685c0b4e3abSDarrick J. Wong static SENSOR_DEVICE_ATTR(temp1_auto_point2_hyst, S_IWUSR | S_IRUGO, 1686c0b4e3abSDarrick J. Wong show_pwm_hyst, set_pwm_hyst, 0); 1687c0b4e3abSDarrick J. Wong static SENSOR_DEVICE_ATTR(temp2_auto_point2_hyst, S_IWUSR | S_IRUGO, 1688c0b4e3abSDarrick J. Wong show_pwm_hyst, set_pwm_hyst, 1); 1689c0b4e3abSDarrick J. Wong static SENSOR_DEVICE_ATTR(temp3_auto_point2_hyst, S_IWUSR | S_IRUGO, 1690c0b4e3abSDarrick J. Wong show_pwm_hyst, set_pwm_hyst, 2); 1691c0b4e3abSDarrick J. Wong static SENSOR_DEVICE_ATTR(temp4_auto_point2_hyst, S_IWUSR | S_IRUGO, 1692c0b4e3abSDarrick J. Wong show_pwm_hyst, set_pwm_hyst, 3); 1693c0b4e3abSDarrick J. Wong 1694c0b4e3abSDarrick J. Wong static SENSOR_DEVICE_ATTR(temp1_auto_point1_temp, S_IWUSR | S_IRUGO, 1695c0b4e3abSDarrick J. Wong show_pwm_tmin, set_pwm_tmin, 0); 1696c0b4e3abSDarrick J. Wong static SENSOR_DEVICE_ATTR(temp2_auto_point1_temp, S_IWUSR | S_IRUGO, 1697c0b4e3abSDarrick J. Wong show_pwm_tmin, set_pwm_tmin, 1); 1698c0b4e3abSDarrick J. Wong static SENSOR_DEVICE_ATTR(temp3_auto_point1_temp, S_IWUSR | S_IRUGO, 1699c0b4e3abSDarrick J. Wong show_pwm_tmin, set_pwm_tmin, 2); 1700c0b4e3abSDarrick J. Wong static SENSOR_DEVICE_ATTR(temp4_auto_point1_temp, S_IWUSR | S_IRUGO, 1701c0b4e3abSDarrick J. Wong show_pwm_tmin, set_pwm_tmin, 3); 1702c0b4e3abSDarrick J. Wong 1703c0b4e3abSDarrick J. Wong static SENSOR_DEVICE_ATTR(temp1_auto_point2_temp, S_IWUSR | S_IRUGO, 1704c0b4e3abSDarrick J. Wong show_pwm_tmax, set_pwm_tmax, 0); 1705c0b4e3abSDarrick J. Wong static SENSOR_DEVICE_ATTR(temp2_auto_point2_temp, S_IWUSR | S_IRUGO, 1706c0b4e3abSDarrick J. Wong show_pwm_tmax, set_pwm_tmax, 1); 1707c0b4e3abSDarrick J. Wong static SENSOR_DEVICE_ATTR(temp3_auto_point2_temp, S_IWUSR | S_IRUGO, 1708c0b4e3abSDarrick J. Wong show_pwm_tmax, set_pwm_tmax, 2); 1709c0b4e3abSDarrick J. Wong static SENSOR_DEVICE_ATTR(temp4_auto_point2_temp, S_IWUSR | S_IRUGO, 1710c0b4e3abSDarrick J. Wong show_pwm_tmax, set_pwm_tmax, 3); 1711c0b4e3abSDarrick J. Wong 1712c0b4e3abSDarrick J. Wong static SENSOR_DEVICE_ATTR(pwm1_enable, S_IWUSR | S_IRUGO, show_pwm_auto, 1713c0b4e3abSDarrick J. Wong set_pwm_auto, 0); 1714c0b4e3abSDarrick J. Wong static SENSOR_DEVICE_ATTR(pwm2_enable, S_IWUSR | S_IRUGO, show_pwm_auto, 1715c0b4e3abSDarrick J. Wong set_pwm_auto, 1); 1716c0b4e3abSDarrick J. Wong static SENSOR_DEVICE_ATTR(pwm3_enable, S_IWUSR | S_IRUGO, show_pwm_auto, 1717c0b4e3abSDarrick J. Wong set_pwm_auto, 2); 1718c0b4e3abSDarrick J. Wong static SENSOR_DEVICE_ATTR(pwm4_enable, S_IWUSR | S_IRUGO, show_pwm_auto, 1719c0b4e3abSDarrick J. Wong set_pwm_auto, 3); 1720c0b4e3abSDarrick J. Wong 1721c0b4e3abSDarrick J. Wong static SENSOR_DEVICE_ATTR(pwm1_auto_channels_temp, S_IWUSR | S_IRUGO, 1722c0b4e3abSDarrick J. Wong show_pwm_auto_temp, set_pwm_auto_temp, 0); 1723c0b4e3abSDarrick J. Wong static SENSOR_DEVICE_ATTR(pwm2_auto_channels_temp, S_IWUSR | S_IRUGO, 1724c0b4e3abSDarrick J. Wong show_pwm_auto_temp, set_pwm_auto_temp, 1); 1725c0b4e3abSDarrick J. Wong static SENSOR_DEVICE_ATTR(pwm3_auto_channels_temp, S_IWUSR | S_IRUGO, 1726c0b4e3abSDarrick J. Wong show_pwm_auto_temp, set_pwm_auto_temp, 2); 1727c0b4e3abSDarrick J. Wong static SENSOR_DEVICE_ATTR(pwm4_auto_channels_temp, S_IWUSR | S_IRUGO, 1728c0b4e3abSDarrick J. Wong show_pwm_auto_temp, set_pwm_auto_temp, 3); 1729c0b4e3abSDarrick J. Wong 1730724cc331SGuenter Roeck static struct attribute *adt7462_attr[] = { 1731c0b4e3abSDarrick J. Wong &sensor_dev_attr_temp1_max.dev_attr.attr, 1732c0b4e3abSDarrick J. Wong &sensor_dev_attr_temp2_max.dev_attr.attr, 1733c0b4e3abSDarrick J. Wong &sensor_dev_attr_temp3_max.dev_attr.attr, 1734c0b4e3abSDarrick J. Wong &sensor_dev_attr_temp4_max.dev_attr.attr, 1735c0b4e3abSDarrick J. Wong 1736c0b4e3abSDarrick J. Wong &sensor_dev_attr_temp1_min.dev_attr.attr, 1737c0b4e3abSDarrick J. Wong &sensor_dev_attr_temp2_min.dev_attr.attr, 1738c0b4e3abSDarrick J. Wong &sensor_dev_attr_temp3_min.dev_attr.attr, 1739c0b4e3abSDarrick J. Wong &sensor_dev_attr_temp4_min.dev_attr.attr, 1740c0b4e3abSDarrick J. Wong 1741c0b4e3abSDarrick J. Wong &sensor_dev_attr_temp1_input.dev_attr.attr, 1742c0b4e3abSDarrick J. Wong &sensor_dev_attr_temp2_input.dev_attr.attr, 1743c0b4e3abSDarrick J. Wong &sensor_dev_attr_temp3_input.dev_attr.attr, 1744c0b4e3abSDarrick J. Wong &sensor_dev_attr_temp4_input.dev_attr.attr, 1745c0b4e3abSDarrick J. Wong 1746c0b4e3abSDarrick J. Wong &sensor_dev_attr_temp1_label.dev_attr.attr, 1747c0b4e3abSDarrick J. Wong &sensor_dev_attr_temp2_label.dev_attr.attr, 1748c0b4e3abSDarrick J. Wong &sensor_dev_attr_temp3_label.dev_attr.attr, 1749c0b4e3abSDarrick J. Wong &sensor_dev_attr_temp4_label.dev_attr.attr, 1750c0b4e3abSDarrick J. Wong 1751c0b4e3abSDarrick J. Wong &sensor_dev_attr_temp1_alarm.dev_attr.attr, 1752c0b4e3abSDarrick J. Wong &sensor_dev_attr_temp2_alarm.dev_attr.attr, 1753c0b4e3abSDarrick J. Wong &sensor_dev_attr_temp3_alarm.dev_attr.attr, 1754c0b4e3abSDarrick J. Wong &sensor_dev_attr_temp4_alarm.dev_attr.attr, 1755c0b4e3abSDarrick J. Wong 1756c0b4e3abSDarrick J. Wong &sensor_dev_attr_in1_max.dev_attr.attr, 1757c0b4e3abSDarrick J. Wong &sensor_dev_attr_in2_max.dev_attr.attr, 1758c0b4e3abSDarrick J. Wong &sensor_dev_attr_in3_max.dev_attr.attr, 1759c0b4e3abSDarrick J. Wong &sensor_dev_attr_in4_max.dev_attr.attr, 1760c0b4e3abSDarrick J. Wong &sensor_dev_attr_in5_max.dev_attr.attr, 1761c0b4e3abSDarrick J. Wong &sensor_dev_attr_in6_max.dev_attr.attr, 1762c0b4e3abSDarrick J. Wong &sensor_dev_attr_in7_max.dev_attr.attr, 1763c0b4e3abSDarrick J. Wong &sensor_dev_attr_in8_max.dev_attr.attr, 1764c0b4e3abSDarrick J. Wong &sensor_dev_attr_in9_max.dev_attr.attr, 1765c0b4e3abSDarrick J. Wong &sensor_dev_attr_in10_max.dev_attr.attr, 1766c0b4e3abSDarrick J. Wong &sensor_dev_attr_in11_max.dev_attr.attr, 1767c0b4e3abSDarrick J. Wong &sensor_dev_attr_in12_max.dev_attr.attr, 1768c0b4e3abSDarrick J. Wong &sensor_dev_attr_in13_max.dev_attr.attr, 1769c0b4e3abSDarrick J. Wong 1770c0b4e3abSDarrick J. Wong &sensor_dev_attr_in1_min.dev_attr.attr, 1771c0b4e3abSDarrick J. Wong &sensor_dev_attr_in2_min.dev_attr.attr, 1772c0b4e3abSDarrick J. Wong &sensor_dev_attr_in3_min.dev_attr.attr, 1773c0b4e3abSDarrick J. Wong &sensor_dev_attr_in4_min.dev_attr.attr, 1774c0b4e3abSDarrick J. Wong &sensor_dev_attr_in5_min.dev_attr.attr, 1775c0b4e3abSDarrick J. Wong &sensor_dev_attr_in6_min.dev_attr.attr, 1776c0b4e3abSDarrick J. Wong &sensor_dev_attr_in7_min.dev_attr.attr, 1777c0b4e3abSDarrick J. Wong &sensor_dev_attr_in8_min.dev_attr.attr, 1778c0b4e3abSDarrick J. Wong &sensor_dev_attr_in9_min.dev_attr.attr, 1779c0b4e3abSDarrick J. Wong &sensor_dev_attr_in10_min.dev_attr.attr, 1780c0b4e3abSDarrick J. Wong &sensor_dev_attr_in11_min.dev_attr.attr, 1781c0b4e3abSDarrick J. Wong &sensor_dev_attr_in12_min.dev_attr.attr, 1782c0b4e3abSDarrick J. Wong &sensor_dev_attr_in13_min.dev_attr.attr, 1783c0b4e3abSDarrick J. Wong 1784c0b4e3abSDarrick J. Wong &sensor_dev_attr_in1_input.dev_attr.attr, 1785c0b4e3abSDarrick J. Wong &sensor_dev_attr_in2_input.dev_attr.attr, 1786c0b4e3abSDarrick J. Wong &sensor_dev_attr_in3_input.dev_attr.attr, 1787c0b4e3abSDarrick J. Wong &sensor_dev_attr_in4_input.dev_attr.attr, 1788c0b4e3abSDarrick J. Wong &sensor_dev_attr_in5_input.dev_attr.attr, 1789c0b4e3abSDarrick J. Wong &sensor_dev_attr_in6_input.dev_attr.attr, 1790c0b4e3abSDarrick J. Wong &sensor_dev_attr_in7_input.dev_attr.attr, 1791c0b4e3abSDarrick J. Wong &sensor_dev_attr_in8_input.dev_attr.attr, 1792c0b4e3abSDarrick J. Wong &sensor_dev_attr_in9_input.dev_attr.attr, 1793c0b4e3abSDarrick J. Wong &sensor_dev_attr_in10_input.dev_attr.attr, 1794c0b4e3abSDarrick J. Wong &sensor_dev_attr_in11_input.dev_attr.attr, 1795c0b4e3abSDarrick J. Wong &sensor_dev_attr_in12_input.dev_attr.attr, 1796c0b4e3abSDarrick J. Wong &sensor_dev_attr_in13_input.dev_attr.attr, 1797c0b4e3abSDarrick J. Wong 1798c0b4e3abSDarrick J. Wong &sensor_dev_attr_in1_label.dev_attr.attr, 1799c0b4e3abSDarrick J. Wong &sensor_dev_attr_in2_label.dev_attr.attr, 1800c0b4e3abSDarrick J. Wong &sensor_dev_attr_in3_label.dev_attr.attr, 1801c0b4e3abSDarrick J. Wong &sensor_dev_attr_in4_label.dev_attr.attr, 1802c0b4e3abSDarrick J. Wong &sensor_dev_attr_in5_label.dev_attr.attr, 1803c0b4e3abSDarrick J. Wong &sensor_dev_attr_in6_label.dev_attr.attr, 1804c0b4e3abSDarrick J. Wong &sensor_dev_attr_in7_label.dev_attr.attr, 1805c0b4e3abSDarrick J. Wong &sensor_dev_attr_in8_label.dev_attr.attr, 1806c0b4e3abSDarrick J. Wong &sensor_dev_attr_in9_label.dev_attr.attr, 1807c0b4e3abSDarrick J. Wong &sensor_dev_attr_in10_label.dev_attr.attr, 1808c0b4e3abSDarrick J. Wong &sensor_dev_attr_in11_label.dev_attr.attr, 1809c0b4e3abSDarrick J. Wong &sensor_dev_attr_in12_label.dev_attr.attr, 1810c0b4e3abSDarrick J. Wong &sensor_dev_attr_in13_label.dev_attr.attr, 1811c0b4e3abSDarrick J. Wong 1812c0b4e3abSDarrick J. Wong &sensor_dev_attr_in1_alarm.dev_attr.attr, 1813c0b4e3abSDarrick J. Wong &sensor_dev_attr_in2_alarm.dev_attr.attr, 1814c0b4e3abSDarrick J. Wong &sensor_dev_attr_in3_alarm.dev_attr.attr, 1815c0b4e3abSDarrick J. Wong &sensor_dev_attr_in4_alarm.dev_attr.attr, 1816c0b4e3abSDarrick J. Wong &sensor_dev_attr_in5_alarm.dev_attr.attr, 1817c0b4e3abSDarrick J. Wong &sensor_dev_attr_in6_alarm.dev_attr.attr, 1818c0b4e3abSDarrick J. Wong &sensor_dev_attr_in7_alarm.dev_attr.attr, 1819c0b4e3abSDarrick J. Wong &sensor_dev_attr_in8_alarm.dev_attr.attr, 1820c0b4e3abSDarrick J. Wong &sensor_dev_attr_in9_alarm.dev_attr.attr, 1821c0b4e3abSDarrick J. Wong &sensor_dev_attr_in10_alarm.dev_attr.attr, 1822c0b4e3abSDarrick J. Wong &sensor_dev_attr_in11_alarm.dev_attr.attr, 1823c0b4e3abSDarrick J. Wong &sensor_dev_attr_in12_alarm.dev_attr.attr, 1824c0b4e3abSDarrick J. Wong &sensor_dev_attr_in13_alarm.dev_attr.attr, 1825c0b4e3abSDarrick J. Wong 1826c0b4e3abSDarrick J. Wong &sensor_dev_attr_fan1_min.dev_attr.attr, 1827c0b4e3abSDarrick J. Wong &sensor_dev_attr_fan2_min.dev_attr.attr, 1828c0b4e3abSDarrick J. Wong &sensor_dev_attr_fan3_min.dev_attr.attr, 1829c0b4e3abSDarrick J. Wong &sensor_dev_attr_fan4_min.dev_attr.attr, 1830c0b4e3abSDarrick J. Wong &sensor_dev_attr_fan5_min.dev_attr.attr, 1831c0b4e3abSDarrick J. Wong &sensor_dev_attr_fan6_min.dev_attr.attr, 1832c0b4e3abSDarrick J. Wong &sensor_dev_attr_fan7_min.dev_attr.attr, 1833c0b4e3abSDarrick J. Wong &sensor_dev_attr_fan8_min.dev_attr.attr, 1834c0b4e3abSDarrick J. Wong 1835c0b4e3abSDarrick J. Wong &sensor_dev_attr_fan1_input.dev_attr.attr, 1836c0b4e3abSDarrick J. Wong &sensor_dev_attr_fan2_input.dev_attr.attr, 1837c0b4e3abSDarrick J. Wong &sensor_dev_attr_fan3_input.dev_attr.attr, 1838c0b4e3abSDarrick J. Wong &sensor_dev_attr_fan4_input.dev_attr.attr, 1839c0b4e3abSDarrick J. Wong &sensor_dev_attr_fan5_input.dev_attr.attr, 1840c0b4e3abSDarrick J. Wong &sensor_dev_attr_fan6_input.dev_attr.attr, 1841c0b4e3abSDarrick J. Wong &sensor_dev_attr_fan7_input.dev_attr.attr, 1842c0b4e3abSDarrick J. Wong &sensor_dev_attr_fan8_input.dev_attr.attr, 1843c0b4e3abSDarrick J. Wong 1844c0b4e3abSDarrick J. Wong &sensor_dev_attr_fan1_alarm.dev_attr.attr, 1845c0b4e3abSDarrick J. Wong &sensor_dev_attr_fan2_alarm.dev_attr.attr, 1846c0b4e3abSDarrick J. Wong &sensor_dev_attr_fan3_alarm.dev_attr.attr, 1847c0b4e3abSDarrick J. Wong &sensor_dev_attr_fan4_alarm.dev_attr.attr, 1848c0b4e3abSDarrick J. Wong &sensor_dev_attr_fan5_alarm.dev_attr.attr, 1849c0b4e3abSDarrick J. Wong &sensor_dev_attr_fan6_alarm.dev_attr.attr, 1850c0b4e3abSDarrick J. Wong &sensor_dev_attr_fan7_alarm.dev_attr.attr, 1851c0b4e3abSDarrick J. Wong &sensor_dev_attr_fan8_alarm.dev_attr.attr, 1852c0b4e3abSDarrick J. Wong 1853c0b4e3abSDarrick J. Wong &sensor_dev_attr_force_pwm_max.dev_attr.attr, 1854c0b4e3abSDarrick J. Wong &sensor_dev_attr_pwm1.dev_attr.attr, 1855c0b4e3abSDarrick J. Wong &sensor_dev_attr_pwm2.dev_attr.attr, 1856c0b4e3abSDarrick J. Wong &sensor_dev_attr_pwm3.dev_attr.attr, 1857c0b4e3abSDarrick J. Wong &sensor_dev_attr_pwm4.dev_attr.attr, 1858c0b4e3abSDarrick J. Wong 1859c0b4e3abSDarrick J. Wong &sensor_dev_attr_pwm1_auto_point1_pwm.dev_attr.attr, 1860c0b4e3abSDarrick J. Wong &sensor_dev_attr_pwm2_auto_point1_pwm.dev_attr.attr, 1861c0b4e3abSDarrick J. Wong &sensor_dev_attr_pwm3_auto_point1_pwm.dev_attr.attr, 1862c0b4e3abSDarrick J. Wong &sensor_dev_attr_pwm4_auto_point1_pwm.dev_attr.attr, 1863c0b4e3abSDarrick J. Wong 1864c0b4e3abSDarrick J. Wong &sensor_dev_attr_pwm1_auto_point2_pwm.dev_attr.attr, 1865c0b4e3abSDarrick J. Wong &sensor_dev_attr_pwm2_auto_point2_pwm.dev_attr.attr, 1866c0b4e3abSDarrick J. Wong &sensor_dev_attr_pwm3_auto_point2_pwm.dev_attr.attr, 1867c0b4e3abSDarrick J. Wong &sensor_dev_attr_pwm4_auto_point2_pwm.dev_attr.attr, 1868c0b4e3abSDarrick J. Wong 1869c0b4e3abSDarrick J. Wong &sensor_dev_attr_temp1_auto_point1_hyst.dev_attr.attr, 1870c0b4e3abSDarrick J. Wong &sensor_dev_attr_temp2_auto_point1_hyst.dev_attr.attr, 1871c0b4e3abSDarrick J. Wong &sensor_dev_attr_temp3_auto_point1_hyst.dev_attr.attr, 1872c0b4e3abSDarrick J. Wong &sensor_dev_attr_temp4_auto_point1_hyst.dev_attr.attr, 1873c0b4e3abSDarrick J. Wong 1874c0b4e3abSDarrick J. Wong &sensor_dev_attr_temp1_auto_point2_hyst.dev_attr.attr, 1875c0b4e3abSDarrick J. Wong &sensor_dev_attr_temp2_auto_point2_hyst.dev_attr.attr, 1876c0b4e3abSDarrick J. Wong &sensor_dev_attr_temp3_auto_point2_hyst.dev_attr.attr, 1877c0b4e3abSDarrick J. Wong &sensor_dev_attr_temp4_auto_point2_hyst.dev_attr.attr, 1878c0b4e3abSDarrick J. Wong 1879c0b4e3abSDarrick J. Wong &sensor_dev_attr_temp1_auto_point1_temp.dev_attr.attr, 1880c0b4e3abSDarrick J. Wong &sensor_dev_attr_temp2_auto_point1_temp.dev_attr.attr, 1881c0b4e3abSDarrick J. Wong &sensor_dev_attr_temp3_auto_point1_temp.dev_attr.attr, 1882c0b4e3abSDarrick J. Wong &sensor_dev_attr_temp4_auto_point1_temp.dev_attr.attr, 1883c0b4e3abSDarrick J. Wong 1884c0b4e3abSDarrick J. Wong &sensor_dev_attr_temp1_auto_point2_temp.dev_attr.attr, 1885c0b4e3abSDarrick J. Wong &sensor_dev_attr_temp2_auto_point2_temp.dev_attr.attr, 1886c0b4e3abSDarrick J. Wong &sensor_dev_attr_temp3_auto_point2_temp.dev_attr.attr, 1887c0b4e3abSDarrick J. Wong &sensor_dev_attr_temp4_auto_point2_temp.dev_attr.attr, 1888c0b4e3abSDarrick J. Wong 1889c0b4e3abSDarrick J. Wong &sensor_dev_attr_pwm1_enable.dev_attr.attr, 1890c0b4e3abSDarrick J. Wong &sensor_dev_attr_pwm2_enable.dev_attr.attr, 1891c0b4e3abSDarrick J. Wong &sensor_dev_attr_pwm3_enable.dev_attr.attr, 1892c0b4e3abSDarrick J. Wong &sensor_dev_attr_pwm4_enable.dev_attr.attr, 1893c0b4e3abSDarrick J. Wong 1894c0b4e3abSDarrick J. Wong &sensor_dev_attr_pwm1_auto_channels_temp.dev_attr.attr, 1895c0b4e3abSDarrick J. Wong &sensor_dev_attr_pwm2_auto_channels_temp.dev_attr.attr, 1896c0b4e3abSDarrick J. Wong &sensor_dev_attr_pwm3_auto_channels_temp.dev_attr.attr, 1897c0b4e3abSDarrick J. Wong &sensor_dev_attr_pwm4_auto_channels_temp.dev_attr.attr, 1898c0b4e3abSDarrick J. Wong NULL 1899c0b4e3abSDarrick J. Wong }; 1900c0b4e3abSDarrick J. Wong 1901c0b4e3abSDarrick J. Wong /* Return 0 if detection is successful, -ENODEV otherwise */ 1902310ec792SJean Delvare static int adt7462_detect(struct i2c_client *client, 1903c0b4e3abSDarrick J. Wong struct i2c_board_info *info) 1904c0b4e3abSDarrick J. Wong { 1905c0b4e3abSDarrick J. Wong struct i2c_adapter *adapter = client->adapter; 190652df6440SJean Delvare int vendor, device, revision; 1907c0b4e3abSDarrick J. Wong 1908c0b4e3abSDarrick J. Wong if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA)) 1909c0b4e3abSDarrick J. Wong return -ENODEV; 1910c0b4e3abSDarrick J. Wong 1911c0b4e3abSDarrick J. Wong vendor = i2c_smbus_read_byte_data(client, ADT7462_REG_VENDOR); 1912c0b4e3abSDarrick J. Wong if (vendor != ADT7462_VENDOR) 1913c0b4e3abSDarrick J. Wong return -ENODEV; 1914c0b4e3abSDarrick J. Wong 1915c0b4e3abSDarrick J. Wong device = i2c_smbus_read_byte_data(client, ADT7462_REG_DEVICE); 1916c0b4e3abSDarrick J. Wong if (device != ADT7462_DEVICE) 1917c0b4e3abSDarrick J. Wong return -ENODEV; 1918c0b4e3abSDarrick J. Wong 191952df6440SJean Delvare revision = i2c_smbus_read_byte_data(client, ADT7462_REG_REVISION); 1920c0b4e3abSDarrick J. Wong if (revision != ADT7462_REVISION) 1921c0b4e3abSDarrick J. Wong return -ENODEV; 1922c0b4e3abSDarrick J. Wong 1923c0b4e3abSDarrick J. Wong strlcpy(info->type, "adt7462", I2C_NAME_SIZE); 1924c0b4e3abSDarrick J. Wong 1925c0b4e3abSDarrick J. Wong return 0; 1926c0b4e3abSDarrick J. Wong } 1927c0b4e3abSDarrick J. Wong 1928c0b4e3abSDarrick J. Wong static int adt7462_probe(struct i2c_client *client, 1929c0b4e3abSDarrick J. Wong const struct i2c_device_id *id) 1930c0b4e3abSDarrick J. Wong { 1931c0b4e3abSDarrick J. Wong struct adt7462_data *data; 1932c0b4e3abSDarrick J. Wong int err; 1933c0b4e3abSDarrick J. Wong 1934*08808300SGuenter Roeck data = devm_kzalloc(&client->dev, sizeof(struct adt7462_data), 1935*08808300SGuenter Roeck GFP_KERNEL); 1936*08808300SGuenter Roeck if (!data) 1937*08808300SGuenter Roeck return -ENOMEM; 1938c0b4e3abSDarrick J. Wong 1939c0b4e3abSDarrick J. Wong i2c_set_clientdata(client, data); 1940c0b4e3abSDarrick J. Wong mutex_init(&data->lock); 1941c0b4e3abSDarrick J. Wong 1942c0b4e3abSDarrick J. Wong dev_info(&client->dev, "%s chip found\n", client->name); 1943c0b4e3abSDarrick J. Wong 1944c0b4e3abSDarrick J. Wong /* Register sysfs hooks */ 1945c0b4e3abSDarrick J. Wong data->attrs.attrs = adt7462_attr; 1946c0b4e3abSDarrick J. Wong err = sysfs_create_group(&client->dev.kobj, &data->attrs); 1947c0b4e3abSDarrick J. Wong if (err) 1948*08808300SGuenter Roeck return err; 1949c0b4e3abSDarrick J. Wong 1950c0b4e3abSDarrick J. Wong data->hwmon_dev = hwmon_device_register(&client->dev); 1951c0b4e3abSDarrick J. Wong if (IS_ERR(data->hwmon_dev)) { 1952c0b4e3abSDarrick J. Wong err = PTR_ERR(data->hwmon_dev); 1953c0b4e3abSDarrick J. Wong goto exit_remove; 1954c0b4e3abSDarrick J. Wong } 1955c0b4e3abSDarrick J. Wong 1956c0b4e3abSDarrick J. Wong return 0; 1957c0b4e3abSDarrick J. Wong 1958c0b4e3abSDarrick J. Wong exit_remove: 1959c0b4e3abSDarrick J. Wong sysfs_remove_group(&client->dev.kobj, &data->attrs); 1960c0b4e3abSDarrick J. Wong return err; 1961c0b4e3abSDarrick J. Wong } 1962c0b4e3abSDarrick J. Wong 1963c0b4e3abSDarrick J. Wong static int adt7462_remove(struct i2c_client *client) 1964c0b4e3abSDarrick J. Wong { 1965c0b4e3abSDarrick J. Wong struct adt7462_data *data = i2c_get_clientdata(client); 1966c0b4e3abSDarrick J. Wong 1967c0b4e3abSDarrick J. Wong hwmon_device_unregister(data->hwmon_dev); 1968c0b4e3abSDarrick J. Wong sysfs_remove_group(&client->dev.kobj, &data->attrs); 1969c0b4e3abSDarrick J. Wong return 0; 1970c0b4e3abSDarrick J. Wong } 1971c0b4e3abSDarrick J. Wong 1972f0967eeaSAxel Lin module_i2c_driver(adt7462_driver); 1973c0b4e3abSDarrick J. Wong 1974c0b4e3abSDarrick J. Wong MODULE_AUTHOR("Darrick J. Wong <djwong@us.ibm.com>"); 1975c0b4e3abSDarrick J. Wong MODULE_DESCRIPTION("ADT7462 driver"); 1976c0b4e3abSDarrick J. Wong MODULE_LICENSE("GPL"); 1977