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 614b0654e2SJonathan Cormier static const struct of_device_id __maybe_unused ltc2945_of_match[] = { 624b0654e2SJonathan Cormier { .compatible = "adi,ltc2945" }, 634b0654e2SJonathan Cormier { } 644b0654e2SJonathan Cormier }; 654b0654e2SJonathan Cormier MODULE_DEVICE_TABLE(of, ltc2945_of_match); 664b0654e2SJonathan Cormier 676700ce03SGuenter Roeck static inline bool is_power_reg(u8 reg) 686700ce03SGuenter Roeck { 696700ce03SGuenter Roeck return reg < LTC2945_SENSE_H; 706700ce03SGuenter Roeck } 716700ce03SGuenter Roeck 726700ce03SGuenter Roeck /* Return the value from the given register in uW, mV, or mA */ 736700ce03SGuenter Roeck static long long ltc2945_reg_to_val(struct device *dev, u8 reg) 746700ce03SGuenter Roeck { 756700ce03SGuenter Roeck struct regmap *regmap = dev_get_drvdata(dev); 766700ce03SGuenter Roeck unsigned int control; 776700ce03SGuenter Roeck u8 buf[3]; 786700ce03SGuenter Roeck long long val; 796700ce03SGuenter Roeck int ret; 806700ce03SGuenter Roeck 816700ce03SGuenter Roeck ret = regmap_bulk_read(regmap, reg, buf, 826700ce03SGuenter Roeck is_power_reg(reg) ? 3 : 2); 836700ce03SGuenter Roeck if (ret < 0) 846700ce03SGuenter Roeck return ret; 856700ce03SGuenter Roeck 866700ce03SGuenter Roeck if (is_power_reg(reg)) { 876700ce03SGuenter Roeck /* power */ 886700ce03SGuenter Roeck val = (buf[0] << 16) + (buf[1] << 8) + buf[2]; 896700ce03SGuenter Roeck } else { 906700ce03SGuenter Roeck /* current, voltage */ 916700ce03SGuenter Roeck val = (buf[0] << 4) + (buf[1] >> 4); 926700ce03SGuenter Roeck } 936700ce03SGuenter Roeck 946700ce03SGuenter Roeck switch (reg) { 956700ce03SGuenter Roeck case LTC2945_POWER_H: 966700ce03SGuenter Roeck case LTC2945_MAX_POWER_H: 976700ce03SGuenter Roeck case LTC2945_MIN_POWER_H: 986700ce03SGuenter Roeck case LTC2945_MAX_POWER_THRES_H: 996700ce03SGuenter Roeck case LTC2945_MIN_POWER_THRES_H: 1006700ce03SGuenter Roeck /* 1016700ce03SGuenter Roeck * Convert to uW by assuming current is measured with 1026700ce03SGuenter Roeck * an 1mOhm sense resistor, similar to current 1036700ce03SGuenter Roeck * measurements. 1046700ce03SGuenter Roeck * Control register bit 0 selects if voltage at SENSE+/VDD 1056700ce03SGuenter Roeck * or voltage at ADIN is used to measure power. 1066700ce03SGuenter Roeck */ 1076700ce03SGuenter Roeck ret = regmap_read(regmap, LTC2945_CONTROL, &control); 1086700ce03SGuenter Roeck if (ret < 0) 1096700ce03SGuenter Roeck return ret; 1106700ce03SGuenter Roeck if (control & CONTROL_MULT_SELECT) { 1116700ce03SGuenter Roeck /* 25 mV * 25 uV = 0.625 uV resolution. */ 1126700ce03SGuenter Roeck val *= 625LL; 1136700ce03SGuenter Roeck } else { 1146700ce03SGuenter Roeck /* 0.5 mV * 25 uV = 0.0125 uV resolution. */ 1156700ce03SGuenter Roeck val = (val * 25LL) >> 1; 1166700ce03SGuenter Roeck } 1176700ce03SGuenter Roeck break; 1186700ce03SGuenter Roeck case LTC2945_VIN_H: 1196700ce03SGuenter Roeck case LTC2945_MAX_VIN_H: 1206700ce03SGuenter Roeck case LTC2945_MIN_VIN_H: 1216700ce03SGuenter Roeck case LTC2945_MAX_VIN_THRES_H: 1226700ce03SGuenter Roeck case LTC2945_MIN_VIN_THRES_H: 1236700ce03SGuenter Roeck /* 25 mV resolution. Convert to mV. */ 1246700ce03SGuenter Roeck val *= 25; 1256700ce03SGuenter Roeck break; 1266700ce03SGuenter Roeck case LTC2945_ADIN_H: 1276700ce03SGuenter Roeck case LTC2945_MAX_ADIN_H: 1286700ce03SGuenter Roeck case LTC2945_MIN_ADIN_THRES_H: 1296700ce03SGuenter Roeck case LTC2945_MAX_ADIN_THRES_H: 1306700ce03SGuenter Roeck case LTC2945_MIN_ADIN_H: 1316700ce03SGuenter Roeck /* 0.5mV resolution. Convert to mV. */ 1326700ce03SGuenter Roeck val = val >> 1; 1336700ce03SGuenter Roeck break; 1346700ce03SGuenter Roeck case LTC2945_SENSE_H: 1356700ce03SGuenter Roeck case LTC2945_MAX_SENSE_H: 1366700ce03SGuenter Roeck case LTC2945_MIN_SENSE_H: 1376700ce03SGuenter Roeck case LTC2945_MAX_SENSE_THRES_H: 1386700ce03SGuenter Roeck case LTC2945_MIN_SENSE_THRES_H: 1396700ce03SGuenter Roeck /* 1406700ce03SGuenter Roeck * 25 uV resolution. Convert to current as measured with 1416700ce03SGuenter Roeck * an 1 mOhm sense resistor, in mA. If a different sense 1426700ce03SGuenter Roeck * resistor is installed, calculate the actual current by 1436700ce03SGuenter Roeck * dividing the reported current by the sense resistor value 1446700ce03SGuenter Roeck * in mOhm. 1456700ce03SGuenter Roeck */ 1466700ce03SGuenter Roeck val *= 25; 1476700ce03SGuenter Roeck break; 1486700ce03SGuenter Roeck default: 1496700ce03SGuenter Roeck return -EINVAL; 1506700ce03SGuenter Roeck } 1516700ce03SGuenter Roeck return val; 1526700ce03SGuenter Roeck } 1536700ce03SGuenter Roeck 1546700ce03SGuenter Roeck static int ltc2945_val_to_reg(struct device *dev, u8 reg, 1556700ce03SGuenter Roeck unsigned long val) 1566700ce03SGuenter Roeck { 1576700ce03SGuenter Roeck struct regmap *regmap = dev_get_drvdata(dev); 1586700ce03SGuenter Roeck unsigned int control; 1596700ce03SGuenter Roeck int ret; 1606700ce03SGuenter Roeck 1616700ce03SGuenter Roeck switch (reg) { 1626700ce03SGuenter Roeck case LTC2945_POWER_H: 1636700ce03SGuenter Roeck case LTC2945_MAX_POWER_H: 1646700ce03SGuenter Roeck case LTC2945_MIN_POWER_H: 1656700ce03SGuenter Roeck case LTC2945_MAX_POWER_THRES_H: 1666700ce03SGuenter Roeck case LTC2945_MIN_POWER_THRES_H: 1676700ce03SGuenter Roeck /* 1686700ce03SGuenter Roeck * Convert to register value by assuming current is measured 1696700ce03SGuenter Roeck * with an 1mOhm sense resistor, similar to current 1706700ce03SGuenter Roeck * measurements. 1716700ce03SGuenter Roeck * Control register bit 0 selects if voltage at SENSE+/VDD 1726700ce03SGuenter Roeck * or voltage at ADIN is used to measure power, which in turn 1736700ce03SGuenter Roeck * determines register calculations. 1746700ce03SGuenter Roeck */ 1756700ce03SGuenter Roeck ret = regmap_read(regmap, LTC2945_CONTROL, &control); 1766700ce03SGuenter Roeck if (ret < 0) 1776700ce03SGuenter Roeck return ret; 1786700ce03SGuenter Roeck if (control & CONTROL_MULT_SELECT) { 1796700ce03SGuenter Roeck /* 25 mV * 25 uV = 0.625 uV resolution. */ 1806700ce03SGuenter Roeck val = DIV_ROUND_CLOSEST(val, 625); 1816700ce03SGuenter Roeck } else { 1826700ce03SGuenter Roeck /* 1836700ce03SGuenter Roeck * 0.5 mV * 25 uV = 0.0125 uV resolution. 1846700ce03SGuenter Roeck * Divide first to avoid overflow; 1856700ce03SGuenter Roeck * accept loss of accuracy. 1866700ce03SGuenter Roeck */ 1876700ce03SGuenter Roeck val = DIV_ROUND_CLOSEST(val, 25) * 2; 1886700ce03SGuenter Roeck } 1896700ce03SGuenter Roeck break; 1906700ce03SGuenter Roeck case LTC2945_VIN_H: 1916700ce03SGuenter Roeck case LTC2945_MAX_VIN_H: 1926700ce03SGuenter Roeck case LTC2945_MIN_VIN_H: 1936700ce03SGuenter Roeck case LTC2945_MAX_VIN_THRES_H: 1946700ce03SGuenter Roeck case LTC2945_MIN_VIN_THRES_H: 1956700ce03SGuenter Roeck /* 25 mV resolution. */ 1966700ce03SGuenter Roeck val /= 25; 1976700ce03SGuenter Roeck break; 1986700ce03SGuenter Roeck case LTC2945_ADIN_H: 1996700ce03SGuenter Roeck case LTC2945_MAX_ADIN_H: 2006700ce03SGuenter Roeck case LTC2945_MIN_ADIN_THRES_H: 2016700ce03SGuenter Roeck case LTC2945_MAX_ADIN_THRES_H: 2026700ce03SGuenter Roeck case LTC2945_MIN_ADIN_H: 2036700ce03SGuenter Roeck /* 0.5mV resolution. */ 2046700ce03SGuenter Roeck val *= 2; 2056700ce03SGuenter Roeck break; 2066700ce03SGuenter Roeck case LTC2945_SENSE_H: 2076700ce03SGuenter Roeck case LTC2945_MAX_SENSE_H: 2086700ce03SGuenter Roeck case LTC2945_MIN_SENSE_H: 2096700ce03SGuenter Roeck case LTC2945_MAX_SENSE_THRES_H: 2106700ce03SGuenter Roeck case LTC2945_MIN_SENSE_THRES_H: 2116700ce03SGuenter Roeck /* 2126700ce03SGuenter Roeck * 25 uV resolution. Convert to current as measured with 2136700ce03SGuenter Roeck * an 1 mOhm sense resistor, in mA. If a different sense 2146700ce03SGuenter Roeck * resistor is installed, calculate the actual current by 2156700ce03SGuenter Roeck * dividing the reported current by the sense resistor value 2166700ce03SGuenter Roeck * in mOhm. 2176700ce03SGuenter Roeck */ 2186700ce03SGuenter Roeck val = DIV_ROUND_CLOSEST(val, 25); 2196700ce03SGuenter Roeck break; 2206700ce03SGuenter Roeck default: 2216700ce03SGuenter Roeck return -EINVAL; 2226700ce03SGuenter Roeck } 2236700ce03SGuenter Roeck return val; 2246700ce03SGuenter Roeck } 2256700ce03SGuenter Roeck 2265614e26dSGuenter Roeck static ssize_t ltc2945_value_show(struct device *dev, 2276700ce03SGuenter Roeck struct device_attribute *da, char *buf) 2286700ce03SGuenter Roeck { 2296700ce03SGuenter Roeck struct sensor_device_attribute *attr = to_sensor_dev_attr(da); 2306700ce03SGuenter Roeck long long value; 2316700ce03SGuenter Roeck 2326700ce03SGuenter Roeck value = ltc2945_reg_to_val(dev, attr->index); 2336700ce03SGuenter Roeck if (value < 0) 2346700ce03SGuenter Roeck return value; 2351f4d4af4SGuenter Roeck return sysfs_emit(buf, "%lld\n", value); 2366700ce03SGuenter Roeck } 2376700ce03SGuenter Roeck 2385614e26dSGuenter Roeck static ssize_t ltc2945_value_store(struct device *dev, 2396700ce03SGuenter Roeck struct device_attribute *da, 2406700ce03SGuenter Roeck const char *buf, size_t count) 2416700ce03SGuenter Roeck { 2426700ce03SGuenter Roeck struct sensor_device_attribute *attr = to_sensor_dev_attr(da); 2436700ce03SGuenter Roeck struct regmap *regmap = dev_get_drvdata(dev); 2446700ce03SGuenter Roeck u8 reg = attr->index; 2456700ce03SGuenter Roeck unsigned long val; 2466700ce03SGuenter Roeck u8 regbuf[3]; 2476700ce03SGuenter Roeck int num_regs; 2486700ce03SGuenter Roeck int regval; 2496700ce03SGuenter Roeck int ret; 2506700ce03SGuenter Roeck 2516700ce03SGuenter Roeck ret = kstrtoul(buf, 10, &val); 2526700ce03SGuenter Roeck if (ret) 2536700ce03SGuenter Roeck return ret; 2546700ce03SGuenter Roeck 2556700ce03SGuenter Roeck /* convert to register value, then clamp and write result */ 2566700ce03SGuenter Roeck regval = ltc2945_val_to_reg(dev, reg, val); 257*178b01ecSJonathan Cormier if (regval < 0) 258*178b01ecSJonathan Cormier return regval; 2596700ce03SGuenter Roeck if (is_power_reg(reg)) { 2606700ce03SGuenter Roeck regval = clamp_val(regval, 0, 0xffffff); 2616700ce03SGuenter Roeck regbuf[0] = regval >> 16; 2626700ce03SGuenter Roeck regbuf[1] = (regval >> 8) & 0xff; 2636700ce03SGuenter Roeck regbuf[2] = regval; 2646700ce03SGuenter Roeck num_regs = 3; 2656700ce03SGuenter Roeck } else { 2666700ce03SGuenter Roeck regval = clamp_val(regval, 0, 0xfff) << 4; 2676700ce03SGuenter Roeck regbuf[0] = regval >> 8; 2686700ce03SGuenter Roeck regbuf[1] = regval & 0xff; 2696700ce03SGuenter Roeck num_regs = 2; 2706700ce03SGuenter Roeck } 2716700ce03SGuenter Roeck ret = regmap_bulk_write(regmap, reg, regbuf, num_regs); 2726700ce03SGuenter Roeck return ret < 0 ? ret : count; 2736700ce03SGuenter Roeck } 2746700ce03SGuenter Roeck 2755614e26dSGuenter Roeck static ssize_t ltc2945_history_store(struct device *dev, 2766700ce03SGuenter Roeck struct device_attribute *da, 2776700ce03SGuenter Roeck const char *buf, size_t count) 2786700ce03SGuenter Roeck { 2796700ce03SGuenter Roeck struct sensor_device_attribute *attr = to_sensor_dev_attr(da); 2806700ce03SGuenter Roeck struct regmap *regmap = dev_get_drvdata(dev); 2816700ce03SGuenter Roeck u8 reg = attr->index; 2826700ce03SGuenter Roeck int num_regs = is_power_reg(reg) ? 3 : 2; 2836700ce03SGuenter Roeck u8 buf_min[3] = { 0xff, 0xff, 0xff }; 2846700ce03SGuenter Roeck u8 buf_max[3] = { 0, 0, 0 }; 2856700ce03SGuenter Roeck unsigned long val; 2866700ce03SGuenter Roeck int ret; 2876700ce03SGuenter Roeck 2886700ce03SGuenter Roeck ret = kstrtoul(buf, 10, &val); 2896700ce03SGuenter Roeck if (ret) 2906700ce03SGuenter Roeck return ret; 2916700ce03SGuenter Roeck if (val != 1) 2926700ce03SGuenter Roeck return -EINVAL; 2936700ce03SGuenter Roeck 2946700ce03SGuenter Roeck ret = regmap_update_bits(regmap, LTC2945_CONTROL, CONTROL_TEST_MODE, 2956700ce03SGuenter Roeck CONTROL_TEST_MODE); 2966700ce03SGuenter Roeck 2976700ce03SGuenter Roeck /* Reset minimum */ 2986700ce03SGuenter Roeck ret = regmap_bulk_write(regmap, reg, buf_min, num_regs); 2996700ce03SGuenter Roeck if (ret) 3006700ce03SGuenter Roeck return ret; 3016700ce03SGuenter Roeck 3026700ce03SGuenter Roeck switch (reg) { 3036700ce03SGuenter Roeck case LTC2945_MIN_POWER_H: 3046700ce03SGuenter Roeck reg = LTC2945_MAX_POWER_H; 3056700ce03SGuenter Roeck break; 3066700ce03SGuenter Roeck case LTC2945_MIN_SENSE_H: 3076700ce03SGuenter Roeck reg = LTC2945_MAX_SENSE_H; 3086700ce03SGuenter Roeck break; 3096700ce03SGuenter Roeck case LTC2945_MIN_VIN_H: 3106700ce03SGuenter Roeck reg = LTC2945_MAX_VIN_H; 3116700ce03SGuenter Roeck break; 3126700ce03SGuenter Roeck case LTC2945_MIN_ADIN_H: 3136700ce03SGuenter Roeck reg = LTC2945_MAX_ADIN_H; 3146700ce03SGuenter Roeck break; 3156700ce03SGuenter Roeck default: 316f75d7230SGuenter Roeck WARN_ONCE(1, "Bad register: 0x%x\n", reg); 317f75d7230SGuenter Roeck return -EINVAL; 3186700ce03SGuenter Roeck } 3196700ce03SGuenter Roeck /* Reset maximum */ 3206700ce03SGuenter Roeck ret = regmap_bulk_write(regmap, reg, buf_max, num_regs); 3216700ce03SGuenter Roeck 3226700ce03SGuenter Roeck /* Try resetting test mode even if there was an error */ 3236700ce03SGuenter Roeck regmap_update_bits(regmap, LTC2945_CONTROL, CONTROL_TEST_MODE, 0); 3246700ce03SGuenter Roeck 3256700ce03SGuenter Roeck return ret ? : count; 3266700ce03SGuenter Roeck } 3276700ce03SGuenter Roeck 3285614e26dSGuenter Roeck static ssize_t ltc2945_bool_show(struct device *dev, 3296700ce03SGuenter Roeck struct device_attribute *da, char *buf) 3306700ce03SGuenter Roeck { 3316700ce03SGuenter Roeck struct sensor_device_attribute *attr = to_sensor_dev_attr(da); 3326700ce03SGuenter Roeck struct regmap *regmap = dev_get_drvdata(dev); 3336700ce03SGuenter Roeck unsigned int fault; 3346700ce03SGuenter Roeck int ret; 3356700ce03SGuenter Roeck 3366700ce03SGuenter Roeck ret = regmap_read(regmap, LTC2945_FAULT, &fault); 3376700ce03SGuenter Roeck if (ret < 0) 3386700ce03SGuenter Roeck return ret; 3396700ce03SGuenter Roeck 3406700ce03SGuenter Roeck fault &= attr->index; 3416700ce03SGuenter Roeck if (fault) /* Clear reported faults in chip register */ 3426700ce03SGuenter Roeck regmap_update_bits(regmap, LTC2945_FAULT, attr->index, 0); 3436700ce03SGuenter Roeck 3441f4d4af4SGuenter Roeck return sysfs_emit(buf, "%d\n", !!fault); 3456700ce03SGuenter Roeck } 3466700ce03SGuenter Roeck 3476700ce03SGuenter Roeck /* Input voltages */ 3486700ce03SGuenter Roeck 3495614e26dSGuenter Roeck static SENSOR_DEVICE_ATTR_RO(in1_input, ltc2945_value, LTC2945_VIN_H); 3505614e26dSGuenter Roeck static SENSOR_DEVICE_ATTR_RW(in1_min, ltc2945_value, LTC2945_MIN_VIN_THRES_H); 3515614e26dSGuenter Roeck static SENSOR_DEVICE_ATTR_RW(in1_max, ltc2945_value, LTC2945_MAX_VIN_THRES_H); 3525614e26dSGuenter Roeck static SENSOR_DEVICE_ATTR_RO(in1_lowest, ltc2945_value, LTC2945_MIN_VIN_H); 3535614e26dSGuenter Roeck static SENSOR_DEVICE_ATTR_RO(in1_highest, ltc2945_value, LTC2945_MAX_VIN_H); 3545614e26dSGuenter Roeck static SENSOR_DEVICE_ATTR_WO(in1_reset_history, ltc2945_history, 3556700ce03SGuenter Roeck LTC2945_MIN_VIN_H); 3566700ce03SGuenter Roeck 3575614e26dSGuenter Roeck static SENSOR_DEVICE_ATTR_RO(in2_input, ltc2945_value, LTC2945_ADIN_H); 3585614e26dSGuenter Roeck static SENSOR_DEVICE_ATTR_RW(in2_min, ltc2945_value, LTC2945_MIN_ADIN_THRES_H); 3595614e26dSGuenter Roeck static SENSOR_DEVICE_ATTR_RW(in2_max, ltc2945_value, LTC2945_MAX_ADIN_THRES_H); 3605614e26dSGuenter Roeck static SENSOR_DEVICE_ATTR_RO(in2_lowest, ltc2945_value, LTC2945_MIN_ADIN_H); 3615614e26dSGuenter Roeck static SENSOR_DEVICE_ATTR_RO(in2_highest, ltc2945_value, LTC2945_MAX_ADIN_H); 3625614e26dSGuenter Roeck static SENSOR_DEVICE_ATTR_WO(in2_reset_history, ltc2945_history, 3636700ce03SGuenter Roeck LTC2945_MIN_ADIN_H); 3646700ce03SGuenter Roeck 3656700ce03SGuenter Roeck /* Voltage alarms */ 3666700ce03SGuenter Roeck 3675614e26dSGuenter Roeck static SENSOR_DEVICE_ATTR_RO(in1_min_alarm, ltc2945_bool, FAULT_VIN_UV); 3685614e26dSGuenter Roeck static SENSOR_DEVICE_ATTR_RO(in1_max_alarm, ltc2945_bool, FAULT_VIN_OV); 3695614e26dSGuenter Roeck static SENSOR_DEVICE_ATTR_RO(in2_min_alarm, ltc2945_bool, FAULT_ADIN_UV); 3705614e26dSGuenter Roeck static SENSOR_DEVICE_ATTR_RO(in2_max_alarm, ltc2945_bool, FAULT_ADIN_OV); 3716700ce03SGuenter Roeck 3726700ce03SGuenter Roeck /* Currents (via sense resistor) */ 3736700ce03SGuenter Roeck 3745614e26dSGuenter Roeck static SENSOR_DEVICE_ATTR_RO(curr1_input, ltc2945_value, LTC2945_SENSE_H); 3755614e26dSGuenter Roeck static SENSOR_DEVICE_ATTR_RW(curr1_min, ltc2945_value, 3765614e26dSGuenter Roeck LTC2945_MIN_SENSE_THRES_H); 3775614e26dSGuenter Roeck static SENSOR_DEVICE_ATTR_RW(curr1_max, ltc2945_value, 3785614e26dSGuenter Roeck LTC2945_MAX_SENSE_THRES_H); 3795614e26dSGuenter Roeck static SENSOR_DEVICE_ATTR_RO(curr1_lowest, ltc2945_value, LTC2945_MIN_SENSE_H); 3805614e26dSGuenter Roeck static SENSOR_DEVICE_ATTR_RO(curr1_highest, ltc2945_value, 3816700ce03SGuenter Roeck LTC2945_MAX_SENSE_H); 3825614e26dSGuenter Roeck static SENSOR_DEVICE_ATTR_WO(curr1_reset_history, ltc2945_history, 3835614e26dSGuenter Roeck LTC2945_MIN_SENSE_H); 3846700ce03SGuenter Roeck 3856700ce03SGuenter Roeck /* Current alarms */ 3866700ce03SGuenter Roeck 3875614e26dSGuenter Roeck static SENSOR_DEVICE_ATTR_RO(curr1_min_alarm, ltc2945_bool, FAULT_SENSE_UV); 3885614e26dSGuenter Roeck static SENSOR_DEVICE_ATTR_RO(curr1_max_alarm, ltc2945_bool, FAULT_SENSE_OV); 3896700ce03SGuenter Roeck 3906700ce03SGuenter Roeck /* Power */ 3916700ce03SGuenter Roeck 3925614e26dSGuenter Roeck static SENSOR_DEVICE_ATTR_RO(power1_input, ltc2945_value, LTC2945_POWER_H); 3935614e26dSGuenter Roeck static SENSOR_DEVICE_ATTR_RW(power1_min, ltc2945_value, 3945614e26dSGuenter Roeck LTC2945_MIN_POWER_THRES_H); 3955614e26dSGuenter Roeck static SENSOR_DEVICE_ATTR_RW(power1_max, ltc2945_value, 3965614e26dSGuenter Roeck LTC2945_MAX_POWER_THRES_H); 3975614e26dSGuenter Roeck static SENSOR_DEVICE_ATTR_RO(power1_input_lowest, ltc2945_value, 3985614e26dSGuenter Roeck LTC2945_MIN_POWER_H); 3995614e26dSGuenter Roeck static SENSOR_DEVICE_ATTR_RO(power1_input_highest, ltc2945_value, 4005614e26dSGuenter Roeck LTC2945_MAX_POWER_H); 4015614e26dSGuenter Roeck static SENSOR_DEVICE_ATTR_WO(power1_reset_history, ltc2945_history, 4025614e26dSGuenter Roeck LTC2945_MIN_POWER_H); 4036700ce03SGuenter Roeck 4046700ce03SGuenter Roeck /* Power alarms */ 4056700ce03SGuenter Roeck 4065614e26dSGuenter Roeck static SENSOR_DEVICE_ATTR_RO(power1_min_alarm, ltc2945_bool, FAULT_POWER_UV); 4075614e26dSGuenter Roeck static SENSOR_DEVICE_ATTR_RO(power1_max_alarm, ltc2945_bool, FAULT_POWER_OV); 4086700ce03SGuenter Roeck 4096700ce03SGuenter Roeck static struct attribute *ltc2945_attrs[] = { 4106700ce03SGuenter Roeck &sensor_dev_attr_in1_input.dev_attr.attr, 4116700ce03SGuenter Roeck &sensor_dev_attr_in1_min.dev_attr.attr, 4126700ce03SGuenter Roeck &sensor_dev_attr_in1_max.dev_attr.attr, 4136700ce03SGuenter Roeck &sensor_dev_attr_in1_lowest.dev_attr.attr, 4146700ce03SGuenter Roeck &sensor_dev_attr_in1_highest.dev_attr.attr, 4156700ce03SGuenter Roeck &sensor_dev_attr_in1_reset_history.dev_attr.attr, 4166700ce03SGuenter Roeck &sensor_dev_attr_in1_min_alarm.dev_attr.attr, 4176700ce03SGuenter Roeck &sensor_dev_attr_in1_max_alarm.dev_attr.attr, 4186700ce03SGuenter Roeck 4196700ce03SGuenter Roeck &sensor_dev_attr_in2_input.dev_attr.attr, 4206700ce03SGuenter Roeck &sensor_dev_attr_in2_min.dev_attr.attr, 4216700ce03SGuenter Roeck &sensor_dev_attr_in2_max.dev_attr.attr, 4226700ce03SGuenter Roeck &sensor_dev_attr_in2_lowest.dev_attr.attr, 4236700ce03SGuenter Roeck &sensor_dev_attr_in2_highest.dev_attr.attr, 4246700ce03SGuenter Roeck &sensor_dev_attr_in2_reset_history.dev_attr.attr, 4256700ce03SGuenter Roeck &sensor_dev_attr_in2_min_alarm.dev_attr.attr, 4266700ce03SGuenter Roeck &sensor_dev_attr_in2_max_alarm.dev_attr.attr, 4276700ce03SGuenter Roeck 4286700ce03SGuenter Roeck &sensor_dev_attr_curr1_input.dev_attr.attr, 4296700ce03SGuenter Roeck &sensor_dev_attr_curr1_min.dev_attr.attr, 4306700ce03SGuenter Roeck &sensor_dev_attr_curr1_max.dev_attr.attr, 4316700ce03SGuenter Roeck &sensor_dev_attr_curr1_lowest.dev_attr.attr, 4326700ce03SGuenter Roeck &sensor_dev_attr_curr1_highest.dev_attr.attr, 4336700ce03SGuenter Roeck &sensor_dev_attr_curr1_reset_history.dev_attr.attr, 4346700ce03SGuenter Roeck &sensor_dev_attr_curr1_min_alarm.dev_attr.attr, 4356700ce03SGuenter Roeck &sensor_dev_attr_curr1_max_alarm.dev_attr.attr, 4366700ce03SGuenter Roeck 4376700ce03SGuenter Roeck &sensor_dev_attr_power1_input.dev_attr.attr, 4386700ce03SGuenter Roeck &sensor_dev_attr_power1_min.dev_attr.attr, 4396700ce03SGuenter Roeck &sensor_dev_attr_power1_max.dev_attr.attr, 4406700ce03SGuenter Roeck &sensor_dev_attr_power1_input_lowest.dev_attr.attr, 4416700ce03SGuenter Roeck &sensor_dev_attr_power1_input_highest.dev_attr.attr, 4426700ce03SGuenter Roeck &sensor_dev_attr_power1_reset_history.dev_attr.attr, 4436700ce03SGuenter Roeck &sensor_dev_attr_power1_min_alarm.dev_attr.attr, 4446700ce03SGuenter Roeck &sensor_dev_attr_power1_max_alarm.dev_attr.attr, 4456700ce03SGuenter Roeck 4466700ce03SGuenter Roeck NULL, 4476700ce03SGuenter Roeck }; 4486700ce03SGuenter Roeck ATTRIBUTE_GROUPS(ltc2945); 4496700ce03SGuenter Roeck 450034b44b4SAxel Lin static const struct regmap_config ltc2945_regmap_config = { 4516700ce03SGuenter Roeck .reg_bits = 8, 4526700ce03SGuenter Roeck .val_bits = 8, 4536700ce03SGuenter Roeck .max_register = LTC2945_MIN_ADIN_THRES_L, 4546700ce03SGuenter Roeck }; 4556700ce03SGuenter Roeck 45667487038SStephen Kitt static int ltc2945_probe(struct i2c_client *client) 4576700ce03SGuenter Roeck { 4586700ce03SGuenter Roeck struct device *dev = &client->dev; 4596700ce03SGuenter Roeck struct device *hwmon_dev; 4606700ce03SGuenter Roeck struct regmap *regmap; 4616700ce03SGuenter Roeck 4626700ce03SGuenter Roeck regmap = devm_regmap_init_i2c(client, <c2945_regmap_config); 4636700ce03SGuenter Roeck if (IS_ERR(regmap)) { 4646700ce03SGuenter Roeck dev_err(dev, "failed to allocate register map\n"); 4656700ce03SGuenter Roeck return PTR_ERR(regmap); 4666700ce03SGuenter Roeck } 4676700ce03SGuenter Roeck 4686700ce03SGuenter Roeck /* Clear faults */ 4696700ce03SGuenter Roeck regmap_write(regmap, LTC2945_FAULT, 0x00); 4706700ce03SGuenter Roeck 4716700ce03SGuenter Roeck hwmon_dev = devm_hwmon_device_register_with_groups(dev, client->name, 4726700ce03SGuenter Roeck regmap, 4736700ce03SGuenter Roeck ltc2945_groups); 4746700ce03SGuenter Roeck return PTR_ERR_OR_ZERO(hwmon_dev); 4756700ce03SGuenter Roeck } 4766700ce03SGuenter Roeck 4776700ce03SGuenter Roeck static const struct i2c_device_id ltc2945_id[] = { 4786700ce03SGuenter Roeck {"ltc2945", 0}, 4796700ce03SGuenter Roeck { } 4806700ce03SGuenter Roeck }; 4816700ce03SGuenter Roeck 4826700ce03SGuenter Roeck MODULE_DEVICE_TABLE(i2c, ltc2945_id); 4836700ce03SGuenter Roeck 4846700ce03SGuenter Roeck static struct i2c_driver ltc2945_driver = { 4856700ce03SGuenter Roeck .driver = { 4866700ce03SGuenter Roeck .name = "ltc2945", 4874b0654e2SJonathan Cormier .of_match_table = of_match_ptr(ltc2945_of_match), 4886700ce03SGuenter Roeck }, 48967487038SStephen Kitt .probe_new = ltc2945_probe, 4906700ce03SGuenter Roeck .id_table = ltc2945_id, 4916700ce03SGuenter Roeck }; 4926700ce03SGuenter Roeck 4936700ce03SGuenter Roeck module_i2c_driver(ltc2945_driver); 4946700ce03SGuenter Roeck 4956700ce03SGuenter Roeck MODULE_AUTHOR("Guenter Roeck <linux@roeck-us.net>"); 4966700ce03SGuenter Roeck MODULE_DESCRIPTION("LTC2945 driver"); 4976700ce03SGuenter Roeck MODULE_LICENSE("GPL"); 498