1c942fddfSThomas Gleixner // SPDX-License-Identifier: GPL-2.0-or-later 26700ce03SGuenter Roeck /* 36700ce03SGuenter Roeck * Driver for Linear Technology LTC2945 I2C Power Monitor 46700ce03SGuenter Roeck * 56700ce03SGuenter Roeck * Copyright (c) 2014 Guenter Roeck 66700ce03SGuenter Roeck */ 76700ce03SGuenter Roeck 86700ce03SGuenter Roeck #include <linux/kernel.h> 96700ce03SGuenter Roeck #include <linux/module.h> 106700ce03SGuenter Roeck #include <linux/err.h> 116700ce03SGuenter Roeck #include <linux/slab.h> 126700ce03SGuenter Roeck #include <linux/i2c.h> 136700ce03SGuenter Roeck #include <linux/hwmon.h> 146700ce03SGuenter Roeck #include <linux/hwmon-sysfs.h> 156700ce03SGuenter Roeck #include <linux/jiffies.h> 166700ce03SGuenter Roeck #include <linux/regmap.h> 176700ce03SGuenter Roeck 186700ce03SGuenter Roeck /* chip registers */ 196700ce03SGuenter Roeck #define LTC2945_CONTROL 0x00 206700ce03SGuenter Roeck #define LTC2945_ALERT 0x01 216700ce03SGuenter Roeck #define LTC2945_STATUS 0x02 226700ce03SGuenter Roeck #define LTC2945_FAULT 0x03 236700ce03SGuenter Roeck #define LTC2945_POWER_H 0x05 246700ce03SGuenter Roeck #define LTC2945_MAX_POWER_H 0x08 256700ce03SGuenter Roeck #define LTC2945_MIN_POWER_H 0x0b 266700ce03SGuenter Roeck #define LTC2945_MAX_POWER_THRES_H 0x0e 276700ce03SGuenter Roeck #define LTC2945_MIN_POWER_THRES_H 0x11 286700ce03SGuenter Roeck #define LTC2945_SENSE_H 0x14 296700ce03SGuenter Roeck #define LTC2945_MAX_SENSE_H 0x16 306700ce03SGuenter Roeck #define LTC2945_MIN_SENSE_H 0x18 316700ce03SGuenter Roeck #define LTC2945_MAX_SENSE_THRES_H 0x1a 326700ce03SGuenter Roeck #define LTC2945_MIN_SENSE_THRES_H 0x1c 336700ce03SGuenter Roeck #define LTC2945_VIN_H 0x1e 346700ce03SGuenter Roeck #define LTC2945_MAX_VIN_H 0x20 356700ce03SGuenter Roeck #define LTC2945_MIN_VIN_H 0x22 366700ce03SGuenter Roeck #define LTC2945_MAX_VIN_THRES_H 0x24 376700ce03SGuenter Roeck #define LTC2945_MIN_VIN_THRES_H 0x26 386700ce03SGuenter Roeck #define LTC2945_ADIN_H 0x28 396700ce03SGuenter Roeck #define LTC2945_MAX_ADIN_H 0x2a 406700ce03SGuenter Roeck #define LTC2945_MIN_ADIN_H 0x2c 416700ce03SGuenter Roeck #define LTC2945_MAX_ADIN_THRES_H 0x2e 426700ce03SGuenter Roeck #define LTC2945_MIN_ADIN_THRES_H 0x30 436700ce03SGuenter Roeck #define LTC2945_MIN_ADIN_THRES_L 0x31 446700ce03SGuenter Roeck 456700ce03SGuenter Roeck /* Fault register bits */ 466700ce03SGuenter Roeck 476700ce03SGuenter Roeck #define FAULT_ADIN_UV (1 << 0) 486700ce03SGuenter Roeck #define FAULT_ADIN_OV (1 << 1) 496700ce03SGuenter Roeck #define FAULT_VIN_UV (1 << 2) 506700ce03SGuenter Roeck #define FAULT_VIN_OV (1 << 3) 516700ce03SGuenter Roeck #define FAULT_SENSE_UV (1 << 4) 526700ce03SGuenter Roeck #define FAULT_SENSE_OV (1 << 5) 536700ce03SGuenter Roeck #define FAULT_POWER_UV (1 << 6) 546700ce03SGuenter Roeck #define FAULT_POWER_OV (1 << 7) 556700ce03SGuenter Roeck 566700ce03SGuenter Roeck /* Control register bits */ 576700ce03SGuenter Roeck 586700ce03SGuenter Roeck #define CONTROL_MULT_SELECT (1 << 0) 596700ce03SGuenter Roeck #define CONTROL_TEST_MODE (1 << 4) 606700ce03SGuenter Roeck 616700ce03SGuenter Roeck static inline bool is_power_reg(u8 reg) 626700ce03SGuenter Roeck { 636700ce03SGuenter Roeck return reg < LTC2945_SENSE_H; 646700ce03SGuenter Roeck } 656700ce03SGuenter Roeck 666700ce03SGuenter Roeck /* Return the value from the given register in uW, mV, or mA */ 676700ce03SGuenter Roeck static long long ltc2945_reg_to_val(struct device *dev, u8 reg) 686700ce03SGuenter Roeck { 696700ce03SGuenter Roeck struct regmap *regmap = dev_get_drvdata(dev); 706700ce03SGuenter Roeck unsigned int control; 716700ce03SGuenter Roeck u8 buf[3]; 726700ce03SGuenter Roeck long long val; 736700ce03SGuenter Roeck int ret; 746700ce03SGuenter Roeck 756700ce03SGuenter Roeck ret = regmap_bulk_read(regmap, reg, buf, 766700ce03SGuenter Roeck is_power_reg(reg) ? 3 : 2); 776700ce03SGuenter Roeck if (ret < 0) 786700ce03SGuenter Roeck return ret; 796700ce03SGuenter Roeck 806700ce03SGuenter Roeck if (is_power_reg(reg)) { 816700ce03SGuenter Roeck /* power */ 826700ce03SGuenter Roeck val = (buf[0] << 16) + (buf[1] << 8) + buf[2]; 836700ce03SGuenter Roeck } else { 846700ce03SGuenter Roeck /* current, voltage */ 856700ce03SGuenter Roeck val = (buf[0] << 4) + (buf[1] >> 4); 866700ce03SGuenter Roeck } 876700ce03SGuenter Roeck 886700ce03SGuenter Roeck switch (reg) { 896700ce03SGuenter Roeck case LTC2945_POWER_H: 906700ce03SGuenter Roeck case LTC2945_MAX_POWER_H: 916700ce03SGuenter Roeck case LTC2945_MIN_POWER_H: 926700ce03SGuenter Roeck case LTC2945_MAX_POWER_THRES_H: 936700ce03SGuenter Roeck case LTC2945_MIN_POWER_THRES_H: 946700ce03SGuenter Roeck /* 956700ce03SGuenter Roeck * Convert to uW by assuming current is measured with 966700ce03SGuenter Roeck * an 1mOhm sense resistor, similar to current 976700ce03SGuenter Roeck * measurements. 986700ce03SGuenter Roeck * Control register bit 0 selects if voltage at SENSE+/VDD 996700ce03SGuenter Roeck * or voltage at ADIN is used to measure power. 1006700ce03SGuenter Roeck */ 1016700ce03SGuenter Roeck ret = regmap_read(regmap, LTC2945_CONTROL, &control); 1026700ce03SGuenter Roeck if (ret < 0) 1036700ce03SGuenter Roeck return ret; 1046700ce03SGuenter Roeck if (control & CONTROL_MULT_SELECT) { 1056700ce03SGuenter Roeck /* 25 mV * 25 uV = 0.625 uV resolution. */ 1066700ce03SGuenter Roeck val *= 625LL; 1076700ce03SGuenter Roeck } else { 1086700ce03SGuenter Roeck /* 0.5 mV * 25 uV = 0.0125 uV resolution. */ 1096700ce03SGuenter Roeck val = (val * 25LL) >> 1; 1106700ce03SGuenter Roeck } 1116700ce03SGuenter Roeck break; 1126700ce03SGuenter Roeck case LTC2945_VIN_H: 1136700ce03SGuenter Roeck case LTC2945_MAX_VIN_H: 1146700ce03SGuenter Roeck case LTC2945_MIN_VIN_H: 1156700ce03SGuenter Roeck case LTC2945_MAX_VIN_THRES_H: 1166700ce03SGuenter Roeck case LTC2945_MIN_VIN_THRES_H: 1176700ce03SGuenter Roeck /* 25 mV resolution. Convert to mV. */ 1186700ce03SGuenter Roeck val *= 25; 1196700ce03SGuenter Roeck break; 1206700ce03SGuenter Roeck case LTC2945_ADIN_H: 1216700ce03SGuenter Roeck case LTC2945_MAX_ADIN_H: 1226700ce03SGuenter Roeck case LTC2945_MIN_ADIN_THRES_H: 1236700ce03SGuenter Roeck case LTC2945_MAX_ADIN_THRES_H: 1246700ce03SGuenter Roeck case LTC2945_MIN_ADIN_H: 1256700ce03SGuenter Roeck /* 0.5mV resolution. Convert to mV. */ 1266700ce03SGuenter Roeck val = val >> 1; 1276700ce03SGuenter Roeck break; 1286700ce03SGuenter Roeck case LTC2945_SENSE_H: 1296700ce03SGuenter Roeck case LTC2945_MAX_SENSE_H: 1306700ce03SGuenter Roeck case LTC2945_MIN_SENSE_H: 1316700ce03SGuenter Roeck case LTC2945_MAX_SENSE_THRES_H: 1326700ce03SGuenter Roeck case LTC2945_MIN_SENSE_THRES_H: 1336700ce03SGuenter Roeck /* 1346700ce03SGuenter Roeck * 25 uV resolution. Convert to current as measured with 1356700ce03SGuenter Roeck * an 1 mOhm sense resistor, in mA. If a different sense 1366700ce03SGuenter Roeck * resistor is installed, calculate the actual current by 1376700ce03SGuenter Roeck * dividing the reported current by the sense resistor value 1386700ce03SGuenter Roeck * in mOhm. 1396700ce03SGuenter Roeck */ 1406700ce03SGuenter Roeck val *= 25; 1416700ce03SGuenter Roeck break; 1426700ce03SGuenter Roeck default: 1436700ce03SGuenter Roeck return -EINVAL; 1446700ce03SGuenter Roeck } 1456700ce03SGuenter Roeck return val; 1466700ce03SGuenter Roeck } 1476700ce03SGuenter Roeck 1486700ce03SGuenter Roeck static int ltc2945_val_to_reg(struct device *dev, u8 reg, 1496700ce03SGuenter Roeck unsigned long val) 1506700ce03SGuenter Roeck { 1516700ce03SGuenter Roeck struct regmap *regmap = dev_get_drvdata(dev); 1526700ce03SGuenter Roeck unsigned int control; 1536700ce03SGuenter Roeck int ret; 1546700ce03SGuenter Roeck 1556700ce03SGuenter Roeck switch (reg) { 1566700ce03SGuenter Roeck case LTC2945_POWER_H: 1576700ce03SGuenter Roeck case LTC2945_MAX_POWER_H: 1586700ce03SGuenter Roeck case LTC2945_MIN_POWER_H: 1596700ce03SGuenter Roeck case LTC2945_MAX_POWER_THRES_H: 1606700ce03SGuenter Roeck case LTC2945_MIN_POWER_THRES_H: 1616700ce03SGuenter Roeck /* 1626700ce03SGuenter Roeck * Convert to register value by assuming current is measured 1636700ce03SGuenter Roeck * with an 1mOhm sense resistor, similar to current 1646700ce03SGuenter Roeck * measurements. 1656700ce03SGuenter Roeck * Control register bit 0 selects if voltage at SENSE+/VDD 1666700ce03SGuenter Roeck * or voltage at ADIN is used to measure power, which in turn 1676700ce03SGuenter Roeck * determines register calculations. 1686700ce03SGuenter Roeck */ 1696700ce03SGuenter Roeck ret = regmap_read(regmap, LTC2945_CONTROL, &control); 1706700ce03SGuenter Roeck if (ret < 0) 1716700ce03SGuenter Roeck return ret; 1726700ce03SGuenter Roeck if (control & CONTROL_MULT_SELECT) { 1736700ce03SGuenter Roeck /* 25 mV * 25 uV = 0.625 uV resolution. */ 1746700ce03SGuenter Roeck val = DIV_ROUND_CLOSEST(val, 625); 1756700ce03SGuenter Roeck } else { 1766700ce03SGuenter Roeck /* 1776700ce03SGuenter Roeck * 0.5 mV * 25 uV = 0.0125 uV resolution. 1786700ce03SGuenter Roeck * Divide first to avoid overflow; 1796700ce03SGuenter Roeck * accept loss of accuracy. 1806700ce03SGuenter Roeck */ 1816700ce03SGuenter Roeck val = DIV_ROUND_CLOSEST(val, 25) * 2; 1826700ce03SGuenter Roeck } 1836700ce03SGuenter Roeck break; 1846700ce03SGuenter Roeck case LTC2945_VIN_H: 1856700ce03SGuenter Roeck case LTC2945_MAX_VIN_H: 1866700ce03SGuenter Roeck case LTC2945_MIN_VIN_H: 1876700ce03SGuenter Roeck case LTC2945_MAX_VIN_THRES_H: 1886700ce03SGuenter Roeck case LTC2945_MIN_VIN_THRES_H: 1896700ce03SGuenter Roeck /* 25 mV resolution. */ 1906700ce03SGuenter Roeck val /= 25; 1916700ce03SGuenter Roeck break; 1926700ce03SGuenter Roeck case LTC2945_ADIN_H: 1936700ce03SGuenter Roeck case LTC2945_MAX_ADIN_H: 1946700ce03SGuenter Roeck case LTC2945_MIN_ADIN_THRES_H: 1956700ce03SGuenter Roeck case LTC2945_MAX_ADIN_THRES_H: 1966700ce03SGuenter Roeck case LTC2945_MIN_ADIN_H: 1976700ce03SGuenter Roeck /* 0.5mV resolution. */ 1986700ce03SGuenter Roeck val *= 2; 1996700ce03SGuenter Roeck break; 2006700ce03SGuenter Roeck case LTC2945_SENSE_H: 2016700ce03SGuenter Roeck case LTC2945_MAX_SENSE_H: 2026700ce03SGuenter Roeck case LTC2945_MIN_SENSE_H: 2036700ce03SGuenter Roeck case LTC2945_MAX_SENSE_THRES_H: 2046700ce03SGuenter Roeck case LTC2945_MIN_SENSE_THRES_H: 2056700ce03SGuenter Roeck /* 2066700ce03SGuenter Roeck * 25 uV resolution. Convert to current as measured with 2076700ce03SGuenter Roeck * an 1 mOhm sense resistor, in mA. If a different sense 2086700ce03SGuenter Roeck * resistor is installed, calculate the actual current by 2096700ce03SGuenter Roeck * dividing the reported current by the sense resistor value 2106700ce03SGuenter Roeck * in mOhm. 2116700ce03SGuenter Roeck */ 2126700ce03SGuenter Roeck val = DIV_ROUND_CLOSEST(val, 25); 2136700ce03SGuenter Roeck break; 2146700ce03SGuenter Roeck default: 2156700ce03SGuenter Roeck return -EINVAL; 2166700ce03SGuenter Roeck } 2176700ce03SGuenter Roeck return val; 2186700ce03SGuenter Roeck } 2196700ce03SGuenter Roeck 2205614e26dSGuenter Roeck static ssize_t ltc2945_value_show(struct device *dev, 2216700ce03SGuenter Roeck struct device_attribute *da, char *buf) 2226700ce03SGuenter Roeck { 2236700ce03SGuenter Roeck struct sensor_device_attribute *attr = to_sensor_dev_attr(da); 2246700ce03SGuenter Roeck long long value; 2256700ce03SGuenter Roeck 2266700ce03SGuenter Roeck value = ltc2945_reg_to_val(dev, attr->index); 2276700ce03SGuenter Roeck if (value < 0) 2286700ce03SGuenter Roeck return value; 2296700ce03SGuenter Roeck return snprintf(buf, PAGE_SIZE, "%lld\n", value); 2306700ce03SGuenter Roeck } 2316700ce03SGuenter Roeck 2325614e26dSGuenter Roeck static ssize_t ltc2945_value_store(struct device *dev, 2336700ce03SGuenter Roeck struct device_attribute *da, 2346700ce03SGuenter Roeck const char *buf, size_t count) 2356700ce03SGuenter Roeck { 2366700ce03SGuenter Roeck struct sensor_device_attribute *attr = to_sensor_dev_attr(da); 2376700ce03SGuenter Roeck struct regmap *regmap = dev_get_drvdata(dev); 2386700ce03SGuenter Roeck u8 reg = attr->index; 2396700ce03SGuenter Roeck unsigned long val; 2406700ce03SGuenter Roeck u8 regbuf[3]; 2416700ce03SGuenter Roeck int num_regs; 2426700ce03SGuenter Roeck int regval; 2436700ce03SGuenter Roeck int ret; 2446700ce03SGuenter Roeck 2456700ce03SGuenter Roeck ret = kstrtoul(buf, 10, &val); 2466700ce03SGuenter Roeck if (ret) 2476700ce03SGuenter Roeck return ret; 2486700ce03SGuenter Roeck 2496700ce03SGuenter Roeck /* convert to register value, then clamp and write result */ 2506700ce03SGuenter Roeck regval = ltc2945_val_to_reg(dev, reg, val); 2516700ce03SGuenter Roeck if (is_power_reg(reg)) { 2526700ce03SGuenter Roeck regval = clamp_val(regval, 0, 0xffffff); 2536700ce03SGuenter Roeck regbuf[0] = regval >> 16; 2546700ce03SGuenter Roeck regbuf[1] = (regval >> 8) & 0xff; 2556700ce03SGuenter Roeck regbuf[2] = regval; 2566700ce03SGuenter Roeck num_regs = 3; 2576700ce03SGuenter Roeck } else { 2586700ce03SGuenter Roeck regval = clamp_val(regval, 0, 0xfff) << 4; 2596700ce03SGuenter Roeck regbuf[0] = regval >> 8; 2606700ce03SGuenter Roeck regbuf[1] = regval & 0xff; 2616700ce03SGuenter Roeck num_regs = 2; 2626700ce03SGuenter Roeck } 2636700ce03SGuenter Roeck ret = regmap_bulk_write(regmap, reg, regbuf, num_regs); 2646700ce03SGuenter Roeck return ret < 0 ? ret : count; 2656700ce03SGuenter Roeck } 2666700ce03SGuenter Roeck 2675614e26dSGuenter Roeck static ssize_t ltc2945_history_store(struct device *dev, 2686700ce03SGuenter Roeck struct device_attribute *da, 2696700ce03SGuenter Roeck const char *buf, size_t count) 2706700ce03SGuenter Roeck { 2716700ce03SGuenter Roeck struct sensor_device_attribute *attr = to_sensor_dev_attr(da); 2726700ce03SGuenter Roeck struct regmap *regmap = dev_get_drvdata(dev); 2736700ce03SGuenter Roeck u8 reg = attr->index; 2746700ce03SGuenter Roeck int num_regs = is_power_reg(reg) ? 3 : 2; 2756700ce03SGuenter Roeck u8 buf_min[3] = { 0xff, 0xff, 0xff }; 2766700ce03SGuenter Roeck u8 buf_max[3] = { 0, 0, 0 }; 2776700ce03SGuenter Roeck unsigned long val; 2786700ce03SGuenter Roeck int ret; 2796700ce03SGuenter Roeck 2806700ce03SGuenter Roeck ret = kstrtoul(buf, 10, &val); 2816700ce03SGuenter Roeck if (ret) 2826700ce03SGuenter Roeck return ret; 2836700ce03SGuenter Roeck if (val != 1) 2846700ce03SGuenter Roeck return -EINVAL; 2856700ce03SGuenter Roeck 2866700ce03SGuenter Roeck ret = regmap_update_bits(regmap, LTC2945_CONTROL, CONTROL_TEST_MODE, 2876700ce03SGuenter Roeck CONTROL_TEST_MODE); 2886700ce03SGuenter Roeck 2896700ce03SGuenter Roeck /* Reset minimum */ 2906700ce03SGuenter Roeck ret = regmap_bulk_write(regmap, reg, buf_min, num_regs); 2916700ce03SGuenter Roeck if (ret) 2926700ce03SGuenter Roeck return ret; 2936700ce03SGuenter Roeck 2946700ce03SGuenter Roeck switch (reg) { 2956700ce03SGuenter Roeck case LTC2945_MIN_POWER_H: 2966700ce03SGuenter Roeck reg = LTC2945_MAX_POWER_H; 2976700ce03SGuenter Roeck break; 2986700ce03SGuenter Roeck case LTC2945_MIN_SENSE_H: 2996700ce03SGuenter Roeck reg = LTC2945_MAX_SENSE_H; 3006700ce03SGuenter Roeck break; 3016700ce03SGuenter Roeck case LTC2945_MIN_VIN_H: 3026700ce03SGuenter Roeck reg = LTC2945_MAX_VIN_H; 3036700ce03SGuenter Roeck break; 3046700ce03SGuenter Roeck case LTC2945_MIN_ADIN_H: 3056700ce03SGuenter Roeck reg = LTC2945_MAX_ADIN_H; 3066700ce03SGuenter Roeck break; 3076700ce03SGuenter Roeck default: 308f75d7230SGuenter Roeck WARN_ONCE(1, "Bad register: 0x%x\n", reg); 309f75d7230SGuenter Roeck return -EINVAL; 3106700ce03SGuenter Roeck } 3116700ce03SGuenter Roeck /* Reset maximum */ 3126700ce03SGuenter Roeck ret = regmap_bulk_write(regmap, reg, buf_max, num_regs); 3136700ce03SGuenter Roeck 3146700ce03SGuenter Roeck /* Try resetting test mode even if there was an error */ 3156700ce03SGuenter Roeck regmap_update_bits(regmap, LTC2945_CONTROL, CONTROL_TEST_MODE, 0); 3166700ce03SGuenter Roeck 3176700ce03SGuenter Roeck return ret ? : count; 3186700ce03SGuenter Roeck } 3196700ce03SGuenter Roeck 3205614e26dSGuenter Roeck static ssize_t ltc2945_bool_show(struct device *dev, 3216700ce03SGuenter Roeck struct device_attribute *da, char *buf) 3226700ce03SGuenter Roeck { 3236700ce03SGuenter Roeck struct sensor_device_attribute *attr = to_sensor_dev_attr(da); 3246700ce03SGuenter Roeck struct regmap *regmap = dev_get_drvdata(dev); 3256700ce03SGuenter Roeck unsigned int fault; 3266700ce03SGuenter Roeck int ret; 3276700ce03SGuenter Roeck 3286700ce03SGuenter Roeck ret = regmap_read(regmap, LTC2945_FAULT, &fault); 3296700ce03SGuenter Roeck if (ret < 0) 3306700ce03SGuenter Roeck return ret; 3316700ce03SGuenter Roeck 3326700ce03SGuenter Roeck fault &= attr->index; 3336700ce03SGuenter Roeck if (fault) /* Clear reported faults in chip register */ 3346700ce03SGuenter Roeck regmap_update_bits(regmap, LTC2945_FAULT, attr->index, 0); 3356700ce03SGuenter Roeck 3366700ce03SGuenter Roeck return snprintf(buf, PAGE_SIZE, "%d\n", !!fault); 3376700ce03SGuenter Roeck } 3386700ce03SGuenter Roeck 3396700ce03SGuenter Roeck /* Input voltages */ 3406700ce03SGuenter Roeck 3415614e26dSGuenter Roeck static SENSOR_DEVICE_ATTR_RO(in1_input, ltc2945_value, LTC2945_VIN_H); 3425614e26dSGuenter Roeck static SENSOR_DEVICE_ATTR_RW(in1_min, ltc2945_value, LTC2945_MIN_VIN_THRES_H); 3435614e26dSGuenter Roeck static SENSOR_DEVICE_ATTR_RW(in1_max, ltc2945_value, LTC2945_MAX_VIN_THRES_H); 3445614e26dSGuenter Roeck static SENSOR_DEVICE_ATTR_RO(in1_lowest, ltc2945_value, LTC2945_MIN_VIN_H); 3455614e26dSGuenter Roeck static SENSOR_DEVICE_ATTR_RO(in1_highest, ltc2945_value, LTC2945_MAX_VIN_H); 3465614e26dSGuenter Roeck static SENSOR_DEVICE_ATTR_WO(in1_reset_history, ltc2945_history, 3476700ce03SGuenter Roeck LTC2945_MIN_VIN_H); 3486700ce03SGuenter Roeck 3495614e26dSGuenter Roeck static SENSOR_DEVICE_ATTR_RO(in2_input, ltc2945_value, LTC2945_ADIN_H); 3505614e26dSGuenter Roeck static SENSOR_DEVICE_ATTR_RW(in2_min, ltc2945_value, LTC2945_MIN_ADIN_THRES_H); 3515614e26dSGuenter Roeck static SENSOR_DEVICE_ATTR_RW(in2_max, ltc2945_value, LTC2945_MAX_ADIN_THRES_H); 3525614e26dSGuenter Roeck static SENSOR_DEVICE_ATTR_RO(in2_lowest, ltc2945_value, LTC2945_MIN_ADIN_H); 3535614e26dSGuenter Roeck static SENSOR_DEVICE_ATTR_RO(in2_highest, ltc2945_value, LTC2945_MAX_ADIN_H); 3545614e26dSGuenter Roeck static SENSOR_DEVICE_ATTR_WO(in2_reset_history, ltc2945_history, 3556700ce03SGuenter Roeck LTC2945_MIN_ADIN_H); 3566700ce03SGuenter Roeck 3576700ce03SGuenter Roeck /* Voltage alarms */ 3586700ce03SGuenter Roeck 3595614e26dSGuenter Roeck static SENSOR_DEVICE_ATTR_RO(in1_min_alarm, ltc2945_bool, FAULT_VIN_UV); 3605614e26dSGuenter Roeck static SENSOR_DEVICE_ATTR_RO(in1_max_alarm, ltc2945_bool, FAULT_VIN_OV); 3615614e26dSGuenter Roeck static SENSOR_DEVICE_ATTR_RO(in2_min_alarm, ltc2945_bool, FAULT_ADIN_UV); 3625614e26dSGuenter Roeck static SENSOR_DEVICE_ATTR_RO(in2_max_alarm, ltc2945_bool, FAULT_ADIN_OV); 3636700ce03SGuenter Roeck 3646700ce03SGuenter Roeck /* Currents (via sense resistor) */ 3656700ce03SGuenter Roeck 3665614e26dSGuenter Roeck static SENSOR_DEVICE_ATTR_RO(curr1_input, ltc2945_value, LTC2945_SENSE_H); 3675614e26dSGuenter Roeck static SENSOR_DEVICE_ATTR_RW(curr1_min, ltc2945_value, 3685614e26dSGuenter Roeck LTC2945_MIN_SENSE_THRES_H); 3695614e26dSGuenter Roeck static SENSOR_DEVICE_ATTR_RW(curr1_max, ltc2945_value, 3705614e26dSGuenter Roeck LTC2945_MAX_SENSE_THRES_H); 3715614e26dSGuenter Roeck static SENSOR_DEVICE_ATTR_RO(curr1_lowest, ltc2945_value, LTC2945_MIN_SENSE_H); 3725614e26dSGuenter Roeck static SENSOR_DEVICE_ATTR_RO(curr1_highest, ltc2945_value, 3736700ce03SGuenter Roeck LTC2945_MAX_SENSE_H); 3745614e26dSGuenter Roeck static SENSOR_DEVICE_ATTR_WO(curr1_reset_history, ltc2945_history, 3755614e26dSGuenter Roeck LTC2945_MIN_SENSE_H); 3766700ce03SGuenter Roeck 3776700ce03SGuenter Roeck /* Current alarms */ 3786700ce03SGuenter Roeck 3795614e26dSGuenter Roeck static SENSOR_DEVICE_ATTR_RO(curr1_min_alarm, ltc2945_bool, FAULT_SENSE_UV); 3805614e26dSGuenter Roeck static SENSOR_DEVICE_ATTR_RO(curr1_max_alarm, ltc2945_bool, FAULT_SENSE_OV); 3816700ce03SGuenter Roeck 3826700ce03SGuenter Roeck /* Power */ 3836700ce03SGuenter Roeck 3845614e26dSGuenter Roeck static SENSOR_DEVICE_ATTR_RO(power1_input, ltc2945_value, LTC2945_POWER_H); 3855614e26dSGuenter Roeck static SENSOR_DEVICE_ATTR_RW(power1_min, ltc2945_value, 3865614e26dSGuenter Roeck LTC2945_MIN_POWER_THRES_H); 3875614e26dSGuenter Roeck static SENSOR_DEVICE_ATTR_RW(power1_max, ltc2945_value, 3885614e26dSGuenter Roeck LTC2945_MAX_POWER_THRES_H); 3895614e26dSGuenter Roeck static SENSOR_DEVICE_ATTR_RO(power1_input_lowest, ltc2945_value, 3905614e26dSGuenter Roeck LTC2945_MIN_POWER_H); 3915614e26dSGuenter Roeck static SENSOR_DEVICE_ATTR_RO(power1_input_highest, ltc2945_value, 3925614e26dSGuenter Roeck LTC2945_MAX_POWER_H); 3935614e26dSGuenter Roeck static SENSOR_DEVICE_ATTR_WO(power1_reset_history, ltc2945_history, 3945614e26dSGuenter Roeck LTC2945_MIN_POWER_H); 3956700ce03SGuenter Roeck 3966700ce03SGuenter Roeck /* Power alarms */ 3976700ce03SGuenter Roeck 3985614e26dSGuenter Roeck static SENSOR_DEVICE_ATTR_RO(power1_min_alarm, ltc2945_bool, FAULT_POWER_UV); 3995614e26dSGuenter Roeck static SENSOR_DEVICE_ATTR_RO(power1_max_alarm, ltc2945_bool, FAULT_POWER_OV); 4006700ce03SGuenter Roeck 4016700ce03SGuenter Roeck static struct attribute *ltc2945_attrs[] = { 4026700ce03SGuenter Roeck &sensor_dev_attr_in1_input.dev_attr.attr, 4036700ce03SGuenter Roeck &sensor_dev_attr_in1_min.dev_attr.attr, 4046700ce03SGuenter Roeck &sensor_dev_attr_in1_max.dev_attr.attr, 4056700ce03SGuenter Roeck &sensor_dev_attr_in1_lowest.dev_attr.attr, 4066700ce03SGuenter Roeck &sensor_dev_attr_in1_highest.dev_attr.attr, 4076700ce03SGuenter Roeck &sensor_dev_attr_in1_reset_history.dev_attr.attr, 4086700ce03SGuenter Roeck &sensor_dev_attr_in1_min_alarm.dev_attr.attr, 4096700ce03SGuenter Roeck &sensor_dev_attr_in1_max_alarm.dev_attr.attr, 4106700ce03SGuenter Roeck 4116700ce03SGuenter Roeck &sensor_dev_attr_in2_input.dev_attr.attr, 4126700ce03SGuenter Roeck &sensor_dev_attr_in2_min.dev_attr.attr, 4136700ce03SGuenter Roeck &sensor_dev_attr_in2_max.dev_attr.attr, 4146700ce03SGuenter Roeck &sensor_dev_attr_in2_lowest.dev_attr.attr, 4156700ce03SGuenter Roeck &sensor_dev_attr_in2_highest.dev_attr.attr, 4166700ce03SGuenter Roeck &sensor_dev_attr_in2_reset_history.dev_attr.attr, 4176700ce03SGuenter Roeck &sensor_dev_attr_in2_min_alarm.dev_attr.attr, 4186700ce03SGuenter Roeck &sensor_dev_attr_in2_max_alarm.dev_attr.attr, 4196700ce03SGuenter Roeck 4206700ce03SGuenter Roeck &sensor_dev_attr_curr1_input.dev_attr.attr, 4216700ce03SGuenter Roeck &sensor_dev_attr_curr1_min.dev_attr.attr, 4226700ce03SGuenter Roeck &sensor_dev_attr_curr1_max.dev_attr.attr, 4236700ce03SGuenter Roeck &sensor_dev_attr_curr1_lowest.dev_attr.attr, 4246700ce03SGuenter Roeck &sensor_dev_attr_curr1_highest.dev_attr.attr, 4256700ce03SGuenter Roeck &sensor_dev_attr_curr1_reset_history.dev_attr.attr, 4266700ce03SGuenter Roeck &sensor_dev_attr_curr1_min_alarm.dev_attr.attr, 4276700ce03SGuenter Roeck &sensor_dev_attr_curr1_max_alarm.dev_attr.attr, 4286700ce03SGuenter Roeck 4296700ce03SGuenter Roeck &sensor_dev_attr_power1_input.dev_attr.attr, 4306700ce03SGuenter Roeck &sensor_dev_attr_power1_min.dev_attr.attr, 4316700ce03SGuenter Roeck &sensor_dev_attr_power1_max.dev_attr.attr, 4326700ce03SGuenter Roeck &sensor_dev_attr_power1_input_lowest.dev_attr.attr, 4336700ce03SGuenter Roeck &sensor_dev_attr_power1_input_highest.dev_attr.attr, 4346700ce03SGuenter Roeck &sensor_dev_attr_power1_reset_history.dev_attr.attr, 4356700ce03SGuenter Roeck &sensor_dev_attr_power1_min_alarm.dev_attr.attr, 4366700ce03SGuenter Roeck &sensor_dev_attr_power1_max_alarm.dev_attr.attr, 4376700ce03SGuenter Roeck 4386700ce03SGuenter Roeck NULL, 4396700ce03SGuenter Roeck }; 4406700ce03SGuenter Roeck ATTRIBUTE_GROUPS(ltc2945); 4416700ce03SGuenter Roeck 442034b44b4SAxel Lin static const struct regmap_config ltc2945_regmap_config = { 4436700ce03SGuenter Roeck .reg_bits = 8, 4446700ce03SGuenter Roeck .val_bits = 8, 4456700ce03SGuenter Roeck .max_register = LTC2945_MIN_ADIN_THRES_L, 4466700ce03SGuenter Roeck }; 4476700ce03SGuenter Roeck 448*67487038SStephen Kitt static int ltc2945_probe(struct i2c_client *client) 4496700ce03SGuenter Roeck { 4506700ce03SGuenter Roeck struct device *dev = &client->dev; 4516700ce03SGuenter Roeck struct device *hwmon_dev; 4526700ce03SGuenter Roeck struct regmap *regmap; 4536700ce03SGuenter Roeck 4546700ce03SGuenter Roeck regmap = devm_regmap_init_i2c(client, <c2945_regmap_config); 4556700ce03SGuenter Roeck if (IS_ERR(regmap)) { 4566700ce03SGuenter Roeck dev_err(dev, "failed to allocate register map\n"); 4576700ce03SGuenter Roeck return PTR_ERR(regmap); 4586700ce03SGuenter Roeck } 4596700ce03SGuenter Roeck 4606700ce03SGuenter Roeck /* Clear faults */ 4616700ce03SGuenter Roeck regmap_write(regmap, LTC2945_FAULT, 0x00); 4626700ce03SGuenter Roeck 4636700ce03SGuenter Roeck hwmon_dev = devm_hwmon_device_register_with_groups(dev, client->name, 4646700ce03SGuenter Roeck regmap, 4656700ce03SGuenter Roeck ltc2945_groups); 4666700ce03SGuenter Roeck return PTR_ERR_OR_ZERO(hwmon_dev); 4676700ce03SGuenter Roeck } 4686700ce03SGuenter Roeck 4696700ce03SGuenter Roeck static const struct i2c_device_id ltc2945_id[] = { 4706700ce03SGuenter Roeck {"ltc2945", 0}, 4716700ce03SGuenter Roeck { } 4726700ce03SGuenter Roeck }; 4736700ce03SGuenter Roeck 4746700ce03SGuenter Roeck MODULE_DEVICE_TABLE(i2c, ltc2945_id); 4756700ce03SGuenter Roeck 4766700ce03SGuenter Roeck static struct i2c_driver ltc2945_driver = { 4776700ce03SGuenter Roeck .driver = { 4786700ce03SGuenter Roeck .name = "ltc2945", 4796700ce03SGuenter Roeck }, 480*67487038SStephen Kitt .probe_new = ltc2945_probe, 4816700ce03SGuenter Roeck .id_table = ltc2945_id, 4826700ce03SGuenter Roeck }; 4836700ce03SGuenter Roeck 4846700ce03SGuenter Roeck module_i2c_driver(ltc2945_driver); 4856700ce03SGuenter Roeck 4866700ce03SGuenter Roeck MODULE_AUTHOR("Guenter Roeck <linux@roeck-us.net>"); 4876700ce03SGuenter Roeck MODULE_DESCRIPTION("LTC2945 driver"); 4886700ce03SGuenter Roeck MODULE_LICENSE("GPL"); 489