1*0c7d530aSIgor Reznichenko // SPDX-License-Identifier: GPL-2.0 2*0c7d530aSIgor Reznichenko /* 3*0c7d530aSIgor Reznichenko * Driver for ST Microelectronics TSC1641 I2C power monitor 4*0c7d530aSIgor Reznichenko * 5*0c7d530aSIgor Reznichenko * 60 V, 16-bit high-precision power monitor with I2C and MIPI I3C interface 6*0c7d530aSIgor Reznichenko * Datasheet: https://www.st.com/resource/en/datasheet/tsc1641.pdf 7*0c7d530aSIgor Reznichenko * 8*0c7d530aSIgor Reznichenko * Copyright (C) 2025 Igor Reznichenko <igor@reznichenko.net> 9*0c7d530aSIgor Reznichenko */ 10*0c7d530aSIgor Reznichenko 11*0c7d530aSIgor Reznichenko #include <linux/bitfield.h> 12*0c7d530aSIgor Reznichenko #include <linux/bits.h> 13*0c7d530aSIgor Reznichenko #include <linux/device.h> 14*0c7d530aSIgor Reznichenko #include <linux/err.h> 15*0c7d530aSIgor Reznichenko #include <linux/hwmon.h> 16*0c7d530aSIgor Reznichenko #include <linux/i2c.h> 17*0c7d530aSIgor Reznichenko #include <linux/module.h> 18*0c7d530aSIgor Reznichenko #include <linux/regmap.h> 19*0c7d530aSIgor Reznichenko #include <linux/sysfs.h> 20*0c7d530aSIgor Reznichenko #include <linux/util_macros.h> 21*0c7d530aSIgor Reznichenko 22*0c7d530aSIgor Reznichenko /* I2C registers */ 23*0c7d530aSIgor Reznichenko #define TSC1641_CONFIG 0x00 24*0c7d530aSIgor Reznichenko #define TSC1641_SHUNT_VOLTAGE 0x01 25*0c7d530aSIgor Reznichenko #define TSC1641_LOAD_VOLTAGE 0x02 26*0c7d530aSIgor Reznichenko #define TSC1641_POWER 0x03 27*0c7d530aSIgor Reznichenko #define TSC1641_CURRENT 0x04 28*0c7d530aSIgor Reznichenko #define TSC1641_TEMP 0x05 29*0c7d530aSIgor Reznichenko #define TSC1641_MASK 0x06 30*0c7d530aSIgor Reznichenko #define TSC1641_FLAG 0x07 31*0c7d530aSIgor Reznichenko #define TSC1641_RSHUNT 0x08 /* Shunt resistance */ 32*0c7d530aSIgor Reznichenko #define TSC1641_SOL 0x09 33*0c7d530aSIgor Reznichenko #define TSC1641_SUL 0x0A 34*0c7d530aSIgor Reznichenko #define TSC1641_LOL 0x0B 35*0c7d530aSIgor Reznichenko #define TSC1641_LUL 0x0C 36*0c7d530aSIgor Reznichenko #define TSC1641_POL 0x0D 37*0c7d530aSIgor Reznichenko #define TSC1641_TOL 0x0E 38*0c7d530aSIgor Reznichenko #define TSC1641_MANUF_ID 0xFE /* 0x0006 */ 39*0c7d530aSIgor Reznichenko #define TSC1641_DIE_ID 0xFF /* 0x1000 */ 40*0c7d530aSIgor Reznichenko #define TSC1641_MAX_REG 0xFF 41*0c7d530aSIgor Reznichenko 42*0c7d530aSIgor Reznichenko #define TSC1641_RSHUNT_DEFAULT 1000 /* 1mOhm */ 43*0c7d530aSIgor Reznichenko #define TSC1641_CONFIG_DEFAULT 0x003F /* Default mode and temperature sensor */ 44*0c7d530aSIgor Reznichenko #define TSC1641_MASK_DEFAULT 0xFC00 /* Unmask all alerts */ 45*0c7d530aSIgor Reznichenko 46*0c7d530aSIgor Reznichenko /* Bit mask for conversion time in the configuration register */ 47*0c7d530aSIgor Reznichenko #define TSC1641_CONV_TIME_MASK GENMASK(7, 4) 48*0c7d530aSIgor Reznichenko 49*0c7d530aSIgor Reznichenko #define TSC1641_CONV_TIME_DEFAULT 1024 50*0c7d530aSIgor Reznichenko #define TSC1641_MIN_UPDATE_INTERVAL 1024 51*0c7d530aSIgor Reznichenko 52*0c7d530aSIgor Reznichenko /* LSB value of different registers */ 53*0c7d530aSIgor Reznichenko #define TSC1641_VLOAD_LSB_MVOLT 2 54*0c7d530aSIgor Reznichenko #define TSC1641_POWER_LSB_UWATT 25000 55*0c7d530aSIgor Reznichenko #define TSC1641_VSHUNT_LSB_NVOLT 2500 /* Use nanovolts to make it integer */ 56*0c7d530aSIgor Reznichenko #define TSC1641_RSHUNT_LSB_UOHM 10 57*0c7d530aSIgor Reznichenko #define TSC1641_TEMP_LSB_MDEGC 500 58*0c7d530aSIgor Reznichenko 59*0c7d530aSIgor Reznichenko /* Limits based on datasheet */ 60*0c7d530aSIgor Reznichenko #define TSC1641_RSHUNT_MIN_UOHM 100 61*0c7d530aSIgor Reznichenko #define TSC1641_RSHUNT_MAX_UOHM 655350 62*0c7d530aSIgor Reznichenko #define TSC1641_CURR_ABS_MAX_MAMP 819200 /* Max current at 100uOhm*/ 63*0c7d530aSIgor Reznichenko 64*0c7d530aSIgor Reznichenko #define TSC1641_ALERT_POL_MASK BIT(1) 65*0c7d530aSIgor Reznichenko #define TSC1641_ALERT_LATCH_EN_MASK BIT(0) 66*0c7d530aSIgor Reznichenko 67*0c7d530aSIgor Reznichenko /* Flags indicating alerts in TSC1641_FLAG register*/ 68*0c7d530aSIgor Reznichenko #define TSC1641_SAT_FLAG BIT(13) 69*0c7d530aSIgor Reznichenko #define TSC1641_SHUNT_OV_FLAG BIT(6) 70*0c7d530aSIgor Reznichenko #define TSC1641_SHUNT_UV_FLAG BIT(5) 71*0c7d530aSIgor Reznichenko #define TSC1641_LOAD_OV_FLAG BIT(4) 72*0c7d530aSIgor Reznichenko #define TSC1641_LOAD_UV_FLAG BIT(3) 73*0c7d530aSIgor Reznichenko #define TSC1641_POWER_OVER_FLAG BIT(2) 74*0c7d530aSIgor Reznichenko #define TSC1641_TEMP_OVER_FLAG BIT(1) 75*0c7d530aSIgor Reznichenko 76*0c7d530aSIgor Reznichenko static bool tsc1641_writeable_reg(struct device *dev, unsigned int reg) 77*0c7d530aSIgor Reznichenko { 78*0c7d530aSIgor Reznichenko switch (reg) { 79*0c7d530aSIgor Reznichenko case TSC1641_CONFIG: 80*0c7d530aSIgor Reznichenko case TSC1641_MASK: 81*0c7d530aSIgor Reznichenko case TSC1641_RSHUNT: 82*0c7d530aSIgor Reznichenko case TSC1641_SOL: 83*0c7d530aSIgor Reznichenko case TSC1641_SUL: 84*0c7d530aSIgor Reznichenko case TSC1641_LOL: 85*0c7d530aSIgor Reznichenko case TSC1641_LUL: 86*0c7d530aSIgor Reznichenko case TSC1641_POL: 87*0c7d530aSIgor Reznichenko case TSC1641_TOL: 88*0c7d530aSIgor Reznichenko return true; 89*0c7d530aSIgor Reznichenko default: 90*0c7d530aSIgor Reznichenko return false; 91*0c7d530aSIgor Reznichenko } 92*0c7d530aSIgor Reznichenko } 93*0c7d530aSIgor Reznichenko 94*0c7d530aSIgor Reznichenko static bool tsc1641_volatile_reg(struct device *dev, unsigned int reg) 95*0c7d530aSIgor Reznichenko { 96*0c7d530aSIgor Reznichenko switch (reg) { 97*0c7d530aSIgor Reznichenko case TSC1641_SHUNT_VOLTAGE: 98*0c7d530aSIgor Reznichenko case TSC1641_LOAD_VOLTAGE: 99*0c7d530aSIgor Reznichenko case TSC1641_POWER: 100*0c7d530aSIgor Reznichenko case TSC1641_CURRENT: 101*0c7d530aSIgor Reznichenko case TSC1641_TEMP: 102*0c7d530aSIgor Reznichenko case TSC1641_FLAG: 103*0c7d530aSIgor Reznichenko case TSC1641_MANUF_ID: 104*0c7d530aSIgor Reznichenko case TSC1641_DIE_ID: 105*0c7d530aSIgor Reznichenko return true; 106*0c7d530aSIgor Reznichenko default: 107*0c7d530aSIgor Reznichenko return false; 108*0c7d530aSIgor Reznichenko } 109*0c7d530aSIgor Reznichenko } 110*0c7d530aSIgor Reznichenko 111*0c7d530aSIgor Reznichenko static const struct regmap_config tsc1641_regmap_config = { 112*0c7d530aSIgor Reznichenko .reg_bits = 8, 113*0c7d530aSIgor Reznichenko .val_bits = 16, 114*0c7d530aSIgor Reznichenko .use_single_write = true, 115*0c7d530aSIgor Reznichenko .use_single_read = true, 116*0c7d530aSIgor Reznichenko .max_register = TSC1641_MAX_REG, 117*0c7d530aSIgor Reznichenko .cache_type = REGCACHE_MAPLE, 118*0c7d530aSIgor Reznichenko .volatile_reg = tsc1641_volatile_reg, 119*0c7d530aSIgor Reznichenko .writeable_reg = tsc1641_writeable_reg, 120*0c7d530aSIgor Reznichenko }; 121*0c7d530aSIgor Reznichenko 122*0c7d530aSIgor Reznichenko struct tsc1641_data { 123*0c7d530aSIgor Reznichenko long rshunt_uohm; 124*0c7d530aSIgor Reznichenko long current_lsb_ua; 125*0c7d530aSIgor Reznichenko struct regmap *regmap; 126*0c7d530aSIgor Reznichenko }; 127*0c7d530aSIgor Reznichenko 128*0c7d530aSIgor Reznichenko /* 129*0c7d530aSIgor Reznichenko * Upper limit due to chip 16-bit shunt register, lower limit to 130*0c7d530aSIgor Reznichenko * prevent current and power registers overflow 131*0c7d530aSIgor Reznichenko */ 132*0c7d530aSIgor Reznichenko static inline int tsc1641_validate_shunt(u32 val) 133*0c7d530aSIgor Reznichenko { 134*0c7d530aSIgor Reznichenko if (val < TSC1641_RSHUNT_MIN_UOHM || val > TSC1641_RSHUNT_MAX_UOHM) 135*0c7d530aSIgor Reznichenko return -EINVAL; 136*0c7d530aSIgor Reznichenko return 0; 137*0c7d530aSIgor Reznichenko } 138*0c7d530aSIgor Reznichenko 139*0c7d530aSIgor Reznichenko static int tsc1641_set_shunt(struct tsc1641_data *data, u32 val) 140*0c7d530aSIgor Reznichenko { 141*0c7d530aSIgor Reznichenko struct regmap *regmap = data->regmap; 142*0c7d530aSIgor Reznichenko long rshunt_reg; 143*0c7d530aSIgor Reznichenko 144*0c7d530aSIgor Reznichenko /* RSHUNT register LSB is 10uOhm so need to divide further */ 145*0c7d530aSIgor Reznichenko rshunt_reg = DIV_ROUND_CLOSEST(val, TSC1641_RSHUNT_LSB_UOHM); 146*0c7d530aSIgor Reznichenko /* 147*0c7d530aSIgor Reznichenko * Clamp value to the nearest multiple of TSC1641_RSHUNT_LSB_UOHM 148*0c7d530aSIgor Reznichenko * in case shunt value provided was not a multiple 149*0c7d530aSIgor Reznichenko */ 150*0c7d530aSIgor Reznichenko data->rshunt_uohm = rshunt_reg * TSC1641_RSHUNT_LSB_UOHM; 151*0c7d530aSIgor Reznichenko data->current_lsb_ua = DIV_ROUND_CLOSEST(TSC1641_VSHUNT_LSB_NVOLT * 1000, 152*0c7d530aSIgor Reznichenko data->rshunt_uohm); 153*0c7d530aSIgor Reznichenko 154*0c7d530aSIgor Reznichenko return regmap_write(regmap, TSC1641_RSHUNT, rshunt_reg); 155*0c7d530aSIgor Reznichenko } 156*0c7d530aSIgor Reznichenko 157*0c7d530aSIgor Reznichenko /* 158*0c7d530aSIgor Reznichenko * Conversion times in uS, value in CONFIG[CT3:CT0] corresponds to index in this array 159*0c7d530aSIgor Reznichenko * See "Table 14. CT3 to CT0: conversion time" in: 160*0c7d530aSIgor Reznichenko * https://www.st.com/resource/en/datasheet/tsc1641.pdf 161*0c7d530aSIgor Reznichenko */ 162*0c7d530aSIgor Reznichenko static const int tsc1641_conv_times[] = { 128, 256, 512, 1024, 2048, 4096, 8192, 16384, 32768 }; 163*0c7d530aSIgor Reznichenko 164*0c7d530aSIgor Reznichenko static int tsc1641_reg_to_upd_interval(u16 config) 165*0c7d530aSIgor Reznichenko { 166*0c7d530aSIgor Reznichenko int idx = FIELD_GET(TSC1641_CONV_TIME_MASK, config); 167*0c7d530aSIgor Reznichenko 168*0c7d530aSIgor Reznichenko idx = clamp_val(idx, 0, ARRAY_SIZE(tsc1641_conv_times) - 1); 169*0c7d530aSIgor Reznichenko int conv_time = tsc1641_conv_times[idx]; 170*0c7d530aSIgor Reznichenko 171*0c7d530aSIgor Reznichenko /* Don't support sub-millisecond update interval as it's not supported in hwmon */ 172*0c7d530aSIgor Reznichenko conv_time = max(conv_time, TSC1641_MIN_UPDATE_INTERVAL); 173*0c7d530aSIgor Reznichenko /* Return nearest value in milliseconds */ 174*0c7d530aSIgor Reznichenko return DIV_ROUND_CLOSEST(conv_time, 1000); 175*0c7d530aSIgor Reznichenko } 176*0c7d530aSIgor Reznichenko 177*0c7d530aSIgor Reznichenko static u16 tsc1641_upd_interval_to_reg(long interval) 178*0c7d530aSIgor Reznichenko { 179*0c7d530aSIgor Reznichenko /* Supported interval is 1ms - 33ms */ 180*0c7d530aSIgor Reznichenko interval = clamp_val(interval, 1, 33); 181*0c7d530aSIgor Reznichenko 182*0c7d530aSIgor Reznichenko int conv = interval * 1000; 183*0c7d530aSIgor Reznichenko int conv_bits = find_closest(conv, tsc1641_conv_times, 184*0c7d530aSIgor Reznichenko ARRAY_SIZE(tsc1641_conv_times)); 185*0c7d530aSIgor Reznichenko 186*0c7d530aSIgor Reznichenko return FIELD_PREP(TSC1641_CONV_TIME_MASK, conv_bits); 187*0c7d530aSIgor Reznichenko } 188*0c7d530aSIgor Reznichenko 189*0c7d530aSIgor Reznichenko static int tsc1641_chip_write(struct device *dev, u32 attr, long val) 190*0c7d530aSIgor Reznichenko { 191*0c7d530aSIgor Reznichenko struct tsc1641_data *data = dev_get_drvdata(dev); 192*0c7d530aSIgor Reznichenko 193*0c7d530aSIgor Reznichenko switch (attr) { 194*0c7d530aSIgor Reznichenko case hwmon_chip_update_interval: 195*0c7d530aSIgor Reznichenko return regmap_update_bits(data->regmap, TSC1641_CONFIG, 196*0c7d530aSIgor Reznichenko TSC1641_CONV_TIME_MASK, 197*0c7d530aSIgor Reznichenko tsc1641_upd_interval_to_reg(val)); 198*0c7d530aSIgor Reznichenko default: 199*0c7d530aSIgor Reznichenko return -EOPNOTSUPP; 200*0c7d530aSIgor Reznichenko } 201*0c7d530aSIgor Reznichenko } 202*0c7d530aSIgor Reznichenko 203*0c7d530aSIgor Reznichenko static int tsc1641_chip_read(struct device *dev, u32 attr, long *val) 204*0c7d530aSIgor Reznichenko { 205*0c7d530aSIgor Reznichenko struct tsc1641_data *data = dev_get_drvdata(dev); 206*0c7d530aSIgor Reznichenko u32 regval; 207*0c7d530aSIgor Reznichenko int ret; 208*0c7d530aSIgor Reznichenko 209*0c7d530aSIgor Reznichenko switch (attr) { 210*0c7d530aSIgor Reznichenko case hwmon_chip_update_interval: 211*0c7d530aSIgor Reznichenko ret = regmap_read(data->regmap, TSC1641_CONFIG, ®val); 212*0c7d530aSIgor Reznichenko if (ret) 213*0c7d530aSIgor Reznichenko return ret; 214*0c7d530aSIgor Reznichenko 215*0c7d530aSIgor Reznichenko *val = tsc1641_reg_to_upd_interval(regval); 216*0c7d530aSIgor Reznichenko return 0; 217*0c7d530aSIgor Reznichenko default: 218*0c7d530aSIgor Reznichenko return -EOPNOTSUPP; 219*0c7d530aSIgor Reznichenko } 220*0c7d530aSIgor Reznichenko } 221*0c7d530aSIgor Reznichenko 222*0c7d530aSIgor Reznichenko static int tsc1641_flag_read(struct regmap *regmap, u32 flag, long *val) 223*0c7d530aSIgor Reznichenko { 224*0c7d530aSIgor Reznichenko unsigned int regval; 225*0c7d530aSIgor Reznichenko int ret; 226*0c7d530aSIgor Reznichenko 227*0c7d530aSIgor Reznichenko ret = regmap_read_bypassed(regmap, TSC1641_FLAG, ®val); 228*0c7d530aSIgor Reznichenko if (ret) 229*0c7d530aSIgor Reznichenko return ret; 230*0c7d530aSIgor Reznichenko 231*0c7d530aSIgor Reznichenko *val = !!(regval & flag); 232*0c7d530aSIgor Reznichenko return 0; 233*0c7d530aSIgor Reznichenko } 234*0c7d530aSIgor Reznichenko 235*0c7d530aSIgor Reznichenko static int tsc1641_in_read(struct device *dev, u32 attr, long *val) 236*0c7d530aSIgor Reznichenko { 237*0c7d530aSIgor Reznichenko struct tsc1641_data *data = dev_get_drvdata(dev); 238*0c7d530aSIgor Reznichenko struct regmap *regmap = data->regmap; 239*0c7d530aSIgor Reznichenko unsigned int regval; 240*0c7d530aSIgor Reznichenko int ret, reg; 241*0c7d530aSIgor Reznichenko long sat_flag; 242*0c7d530aSIgor Reznichenko 243*0c7d530aSIgor Reznichenko switch (attr) { 244*0c7d530aSIgor Reznichenko case hwmon_in_input: 245*0c7d530aSIgor Reznichenko reg = TSC1641_LOAD_VOLTAGE; 246*0c7d530aSIgor Reznichenko break; 247*0c7d530aSIgor Reznichenko case hwmon_in_min: 248*0c7d530aSIgor Reznichenko reg = TSC1641_LUL; 249*0c7d530aSIgor Reznichenko break; 250*0c7d530aSIgor Reznichenko case hwmon_in_max: 251*0c7d530aSIgor Reznichenko reg = TSC1641_LOL; 252*0c7d530aSIgor Reznichenko break; 253*0c7d530aSIgor Reznichenko case hwmon_in_min_alarm: 254*0c7d530aSIgor Reznichenko return tsc1641_flag_read(regmap, TSC1641_LOAD_UV_FLAG, val); 255*0c7d530aSIgor Reznichenko case hwmon_in_max_alarm: 256*0c7d530aSIgor Reznichenko return tsc1641_flag_read(regmap, TSC1641_LOAD_OV_FLAG, val); 257*0c7d530aSIgor Reznichenko default: 258*0c7d530aSIgor Reznichenko return -EOPNOTSUPP; 259*0c7d530aSIgor Reznichenko } 260*0c7d530aSIgor Reznichenko 261*0c7d530aSIgor Reznichenko ret = regmap_read(regmap, reg, ®val); 262*0c7d530aSIgor Reznichenko if (ret) 263*0c7d530aSIgor Reznichenko return ret; 264*0c7d530aSIgor Reznichenko 265*0c7d530aSIgor Reznichenko /* Check if load voltage is out of range */ 266*0c7d530aSIgor Reznichenko if (reg == TSC1641_LOAD_VOLTAGE) { 267*0c7d530aSIgor Reznichenko /* Register is 15-bit max */ 268*0c7d530aSIgor Reznichenko if (regval & 0x8000) 269*0c7d530aSIgor Reznichenko return -ENODATA; 270*0c7d530aSIgor Reznichenko 271*0c7d530aSIgor Reznichenko ret = tsc1641_flag_read(regmap, TSC1641_SAT_FLAG, &sat_flag); 272*0c7d530aSIgor Reznichenko if (ret) 273*0c7d530aSIgor Reznichenko return ret; 274*0c7d530aSIgor Reznichenko /* Out of range conditions per datasheet */ 275*0c7d530aSIgor Reznichenko if (sat_flag && (regval == 0x7FFF || !regval)) 276*0c7d530aSIgor Reznichenko return -ENODATA; 277*0c7d530aSIgor Reznichenko } 278*0c7d530aSIgor Reznichenko 279*0c7d530aSIgor Reznichenko *val = regval * TSC1641_VLOAD_LSB_MVOLT; 280*0c7d530aSIgor Reznichenko return 0; 281*0c7d530aSIgor Reznichenko } 282*0c7d530aSIgor Reznichenko 283*0c7d530aSIgor Reznichenko /* Chip supports bidirectional (positive or negative) current */ 284*0c7d530aSIgor Reznichenko static int tsc1641_curr_read(struct device *dev, u32 attr, long *val) 285*0c7d530aSIgor Reznichenko { 286*0c7d530aSIgor Reznichenko struct tsc1641_data *data = dev_get_drvdata(dev); 287*0c7d530aSIgor Reznichenko struct regmap *regmap = data->regmap; 288*0c7d530aSIgor Reznichenko int regval; 289*0c7d530aSIgor Reznichenko int ret, reg; 290*0c7d530aSIgor Reznichenko long sat_flag; 291*0c7d530aSIgor Reznichenko 292*0c7d530aSIgor Reznichenko /* Current limits are the shunt under/over voltage limits */ 293*0c7d530aSIgor Reznichenko switch (attr) { 294*0c7d530aSIgor Reznichenko case hwmon_curr_input: 295*0c7d530aSIgor Reznichenko reg = TSC1641_CURRENT; 296*0c7d530aSIgor Reznichenko break; 297*0c7d530aSIgor Reznichenko case hwmon_curr_min: 298*0c7d530aSIgor Reznichenko reg = TSC1641_SUL; 299*0c7d530aSIgor Reznichenko break; 300*0c7d530aSIgor Reznichenko case hwmon_curr_max: 301*0c7d530aSIgor Reznichenko reg = TSC1641_SOL; 302*0c7d530aSIgor Reznichenko break; 303*0c7d530aSIgor Reznichenko case hwmon_curr_min_alarm: 304*0c7d530aSIgor Reznichenko return tsc1641_flag_read(regmap, TSC1641_SHUNT_UV_FLAG, val); 305*0c7d530aSIgor Reznichenko case hwmon_curr_max_alarm: 306*0c7d530aSIgor Reznichenko return tsc1641_flag_read(regmap, TSC1641_SHUNT_OV_FLAG, val); 307*0c7d530aSIgor Reznichenko default: 308*0c7d530aSIgor Reznichenko return -EOPNOTSUPP; 309*0c7d530aSIgor Reznichenko } 310*0c7d530aSIgor Reznichenko /* 311*0c7d530aSIgor Reznichenko * Current uses shunt voltage, so check if it's out of range. 312*0c7d530aSIgor Reznichenko * We report current register in sysfs to stay consistent with internal 313*0c7d530aSIgor Reznichenko * power calculations which use current register values 314*0c7d530aSIgor Reznichenko */ 315*0c7d530aSIgor Reznichenko if (reg == TSC1641_CURRENT) { 316*0c7d530aSIgor Reznichenko ret = regmap_read(regmap, TSC1641_SHUNT_VOLTAGE, ®val); 317*0c7d530aSIgor Reznichenko if (ret) 318*0c7d530aSIgor Reznichenko return ret; 319*0c7d530aSIgor Reznichenko 320*0c7d530aSIgor Reznichenko ret = tsc1641_flag_read(regmap, TSC1641_SAT_FLAG, &sat_flag); 321*0c7d530aSIgor Reznichenko if (ret) 322*0c7d530aSIgor Reznichenko return ret; 323*0c7d530aSIgor Reznichenko 324*0c7d530aSIgor Reznichenko if (sat_flag && (regval == 0x7FFF || regval == 0x8000)) 325*0c7d530aSIgor Reznichenko return -ENODATA; 326*0c7d530aSIgor Reznichenko } 327*0c7d530aSIgor Reznichenko 328*0c7d530aSIgor Reznichenko ret = regmap_read(regmap, reg, ®val); 329*0c7d530aSIgor Reznichenko if (ret) 330*0c7d530aSIgor Reznichenko return ret; 331*0c7d530aSIgor Reznichenko 332*0c7d530aSIgor Reznichenko /* Current in milliamps, signed */ 333*0c7d530aSIgor Reznichenko *val = DIV_ROUND_CLOSEST((s16)regval * data->current_lsb_ua, 1000); 334*0c7d530aSIgor Reznichenko return 0; 335*0c7d530aSIgor Reznichenko } 336*0c7d530aSIgor Reznichenko 337*0c7d530aSIgor Reznichenko static int tsc1641_power_read(struct device *dev, u32 attr, long *val) 338*0c7d530aSIgor Reznichenko { 339*0c7d530aSIgor Reznichenko struct tsc1641_data *data = dev_get_drvdata(dev); 340*0c7d530aSIgor Reznichenko struct regmap *regmap = data->regmap; 341*0c7d530aSIgor Reznichenko unsigned int regval; 342*0c7d530aSIgor Reznichenko int ret, reg; 343*0c7d530aSIgor Reznichenko 344*0c7d530aSIgor Reznichenko switch (attr) { 345*0c7d530aSIgor Reznichenko case hwmon_power_input: 346*0c7d530aSIgor Reznichenko reg = TSC1641_POWER; 347*0c7d530aSIgor Reznichenko break; 348*0c7d530aSIgor Reznichenko case hwmon_power_max: 349*0c7d530aSIgor Reznichenko reg = TSC1641_POL; 350*0c7d530aSIgor Reznichenko break; 351*0c7d530aSIgor Reznichenko case hwmon_power_max_alarm: 352*0c7d530aSIgor Reznichenko return tsc1641_flag_read(regmap, TSC1641_POWER_OVER_FLAG, val); 353*0c7d530aSIgor Reznichenko default: 354*0c7d530aSIgor Reznichenko return -EOPNOTSUPP; 355*0c7d530aSIgor Reznichenko } 356*0c7d530aSIgor Reznichenko 357*0c7d530aSIgor Reznichenko ret = regmap_read(regmap, reg, ®val); 358*0c7d530aSIgor Reznichenko if (ret) 359*0c7d530aSIgor Reznichenko return ret; 360*0c7d530aSIgor Reznichenko 361*0c7d530aSIgor Reznichenko *val = regval * TSC1641_POWER_LSB_UWATT; 362*0c7d530aSIgor Reznichenko return 0; 363*0c7d530aSIgor Reznichenko } 364*0c7d530aSIgor Reznichenko 365*0c7d530aSIgor Reznichenko static int tsc1641_temp_read(struct device *dev, u32 attr, long *val) 366*0c7d530aSIgor Reznichenko { 367*0c7d530aSIgor Reznichenko struct tsc1641_data *data = dev_get_drvdata(dev); 368*0c7d530aSIgor Reznichenko struct regmap *regmap = data->regmap; 369*0c7d530aSIgor Reznichenko unsigned int regval; 370*0c7d530aSIgor Reznichenko int ret, reg; 371*0c7d530aSIgor Reznichenko 372*0c7d530aSIgor Reznichenko switch (attr) { 373*0c7d530aSIgor Reznichenko case hwmon_temp_input: 374*0c7d530aSIgor Reznichenko reg = TSC1641_TEMP; 375*0c7d530aSIgor Reznichenko break; 376*0c7d530aSIgor Reznichenko case hwmon_temp_max: 377*0c7d530aSIgor Reznichenko reg = TSC1641_TOL; 378*0c7d530aSIgor Reznichenko break; 379*0c7d530aSIgor Reznichenko case hwmon_temp_max_alarm: 380*0c7d530aSIgor Reznichenko return tsc1641_flag_read(regmap, TSC1641_TEMP_OVER_FLAG, val); 381*0c7d530aSIgor Reznichenko default: 382*0c7d530aSIgor Reznichenko return -EOPNOTSUPP; 383*0c7d530aSIgor Reznichenko } 384*0c7d530aSIgor Reznichenko 385*0c7d530aSIgor Reznichenko ret = regmap_read(regmap, reg, ®val); 386*0c7d530aSIgor Reznichenko if (ret) 387*0c7d530aSIgor Reznichenko return ret; 388*0c7d530aSIgor Reznichenko 389*0c7d530aSIgor Reznichenko /* 0x8000 means that TEMP measurement not enabled */ 390*0c7d530aSIgor Reznichenko if (reg == TSC1641_TEMP && regval == 0x8000) 391*0c7d530aSIgor Reznichenko return -ENODATA; 392*0c7d530aSIgor Reznichenko 393*0c7d530aSIgor Reznichenko /* Both temperature and limit registers are signed */ 394*0c7d530aSIgor Reznichenko *val = (s16)regval * TSC1641_TEMP_LSB_MDEGC; 395*0c7d530aSIgor Reznichenko return 0; 396*0c7d530aSIgor Reznichenko } 397*0c7d530aSIgor Reznichenko 398*0c7d530aSIgor Reznichenko static int tsc1641_in_write(struct device *dev, u32 attr, long val) 399*0c7d530aSIgor Reznichenko { 400*0c7d530aSIgor Reznichenko struct tsc1641_data *data = dev_get_drvdata(dev); 401*0c7d530aSIgor Reznichenko struct regmap *regmap = data->regmap; 402*0c7d530aSIgor Reznichenko unsigned int regval; 403*0c7d530aSIgor Reznichenko int reg; 404*0c7d530aSIgor Reznichenko 405*0c7d530aSIgor Reznichenko switch (attr) { 406*0c7d530aSIgor Reznichenko case hwmon_in_min: 407*0c7d530aSIgor Reznichenko reg = TSC1641_LUL; 408*0c7d530aSIgor Reznichenko break; 409*0c7d530aSIgor Reznichenko case hwmon_in_max: 410*0c7d530aSIgor Reznichenko reg = TSC1641_LOL; 411*0c7d530aSIgor Reznichenko break; 412*0c7d530aSIgor Reznichenko default: 413*0c7d530aSIgor Reznichenko return -EOPNOTSUPP; 414*0c7d530aSIgor Reznichenko } 415*0c7d530aSIgor Reznichenko /* Clamp to full register range */ 416*0c7d530aSIgor Reznichenko val = clamp_val(val, 0, TSC1641_VLOAD_LSB_MVOLT * USHRT_MAX); 417*0c7d530aSIgor Reznichenko regval = DIV_ROUND_CLOSEST(val, TSC1641_VLOAD_LSB_MVOLT); 418*0c7d530aSIgor Reznichenko 419*0c7d530aSIgor Reznichenko return regmap_write(regmap, reg, regval); 420*0c7d530aSIgor Reznichenko } 421*0c7d530aSIgor Reznichenko 422*0c7d530aSIgor Reznichenko static int tsc1641_curr_write(struct device *dev, u32 attr, long val) 423*0c7d530aSIgor Reznichenko { 424*0c7d530aSIgor Reznichenko struct tsc1641_data *data = dev_get_drvdata(dev); 425*0c7d530aSIgor Reznichenko struct regmap *regmap = data->regmap; 426*0c7d530aSIgor Reznichenko int reg, regval; 427*0c7d530aSIgor Reznichenko 428*0c7d530aSIgor Reznichenko switch (attr) { 429*0c7d530aSIgor Reznichenko case hwmon_curr_min: 430*0c7d530aSIgor Reznichenko reg = TSC1641_SUL; 431*0c7d530aSIgor Reznichenko break; 432*0c7d530aSIgor Reznichenko case hwmon_curr_max: 433*0c7d530aSIgor Reznichenko reg = TSC1641_SOL; 434*0c7d530aSIgor Reznichenko break; 435*0c7d530aSIgor Reznichenko default: 436*0c7d530aSIgor Reznichenko return -EOPNOTSUPP; 437*0c7d530aSIgor Reznichenko } 438*0c7d530aSIgor Reznichenko 439*0c7d530aSIgor Reznichenko /* Clamp to prevent over/underflow below */ 440*0c7d530aSIgor Reznichenko val = clamp_val(val, -TSC1641_CURR_ABS_MAX_MAMP, TSC1641_CURR_ABS_MAX_MAMP); 441*0c7d530aSIgor Reznichenko /* Convert val in milliamps to register */ 442*0c7d530aSIgor Reznichenko regval = DIV_ROUND_CLOSEST(val * 1000, data->current_lsb_ua); 443*0c7d530aSIgor Reznichenko /* 444*0c7d530aSIgor Reznichenko * Prevent signed 16-bit overflow. 445*0c7d530aSIgor Reznichenko * Integer arithmetic and shunt scaling can quantize values near 0x7FFF/0x8000, 446*0c7d530aSIgor Reznichenko * so reading and writing back may not preserve the exact original register value. 447*0c7d530aSIgor Reznichenko */ 448*0c7d530aSIgor Reznichenko regval = clamp_val(regval, SHRT_MIN, SHRT_MAX); 449*0c7d530aSIgor Reznichenko /* SUL and SOL registers are signed */ 450*0c7d530aSIgor Reznichenko return regmap_write(regmap, reg, regval & 0xFFFF); 451*0c7d530aSIgor Reznichenko } 452*0c7d530aSIgor Reznichenko 453*0c7d530aSIgor Reznichenko static int tsc1641_power_write(struct device *dev, u32 attr, long val) 454*0c7d530aSIgor Reznichenko { 455*0c7d530aSIgor Reznichenko struct tsc1641_data *data = dev_get_drvdata(dev); 456*0c7d530aSIgor Reznichenko struct regmap *regmap = data->regmap; 457*0c7d530aSIgor Reznichenko unsigned int regval; 458*0c7d530aSIgor Reznichenko 459*0c7d530aSIgor Reznichenko switch (attr) { 460*0c7d530aSIgor Reznichenko case hwmon_power_max: 461*0c7d530aSIgor Reznichenko /* Clamp to full register range */ 462*0c7d530aSIgor Reznichenko val = clamp_val(val, 0, TSC1641_POWER_LSB_UWATT * USHRT_MAX); 463*0c7d530aSIgor Reznichenko regval = DIV_ROUND_CLOSEST(val, TSC1641_POWER_LSB_UWATT); 464*0c7d530aSIgor Reznichenko return regmap_write(regmap, TSC1641_POL, regval); 465*0c7d530aSIgor Reznichenko default: 466*0c7d530aSIgor Reznichenko return -EOPNOTSUPP; 467*0c7d530aSIgor Reznichenko } 468*0c7d530aSIgor Reznichenko } 469*0c7d530aSIgor Reznichenko 470*0c7d530aSIgor Reznichenko static int tsc1641_temp_write(struct device *dev, u32 attr, long val) 471*0c7d530aSIgor Reznichenko { 472*0c7d530aSIgor Reznichenko struct tsc1641_data *data = dev_get_drvdata(dev); 473*0c7d530aSIgor Reznichenko struct regmap *regmap = data->regmap; 474*0c7d530aSIgor Reznichenko int regval; 475*0c7d530aSIgor Reznichenko 476*0c7d530aSIgor Reznichenko switch (attr) { 477*0c7d530aSIgor Reznichenko case hwmon_temp_max: 478*0c7d530aSIgor Reznichenko /* Clamp to full register range */ 479*0c7d530aSIgor Reznichenko val = clamp_val(val, TSC1641_TEMP_LSB_MDEGC * SHRT_MIN, 480*0c7d530aSIgor Reznichenko TSC1641_TEMP_LSB_MDEGC * SHRT_MAX); 481*0c7d530aSIgor Reznichenko regval = DIV_ROUND_CLOSEST(val, TSC1641_TEMP_LSB_MDEGC); 482*0c7d530aSIgor Reznichenko /* TOL register is signed */ 483*0c7d530aSIgor Reznichenko return regmap_write(regmap, TSC1641_TOL, regval & 0xFFFF); 484*0c7d530aSIgor Reznichenko default: 485*0c7d530aSIgor Reznichenko return -EOPNOTSUPP; 486*0c7d530aSIgor Reznichenko } 487*0c7d530aSIgor Reznichenko } 488*0c7d530aSIgor Reznichenko 489*0c7d530aSIgor Reznichenko static umode_t tsc1641_is_visible(const void *data, enum hwmon_sensor_types type, 490*0c7d530aSIgor Reznichenko u32 attr, int channel) 491*0c7d530aSIgor Reznichenko { 492*0c7d530aSIgor Reznichenko switch (type) { 493*0c7d530aSIgor Reznichenko case hwmon_chip: 494*0c7d530aSIgor Reznichenko switch (attr) { 495*0c7d530aSIgor Reznichenko case hwmon_chip_update_interval: 496*0c7d530aSIgor Reznichenko return 0644; 497*0c7d530aSIgor Reznichenko default: 498*0c7d530aSIgor Reznichenko break; 499*0c7d530aSIgor Reznichenko } 500*0c7d530aSIgor Reznichenko break; 501*0c7d530aSIgor Reznichenko case hwmon_in: 502*0c7d530aSIgor Reznichenko switch (attr) { 503*0c7d530aSIgor Reznichenko case hwmon_in_input: 504*0c7d530aSIgor Reznichenko return 0444; 505*0c7d530aSIgor Reznichenko case hwmon_in_min: 506*0c7d530aSIgor Reznichenko case hwmon_in_max: 507*0c7d530aSIgor Reznichenko return 0644; 508*0c7d530aSIgor Reznichenko case hwmon_in_min_alarm: 509*0c7d530aSIgor Reznichenko case hwmon_in_max_alarm: 510*0c7d530aSIgor Reznichenko return 0444; 511*0c7d530aSIgor Reznichenko default: 512*0c7d530aSIgor Reznichenko break; 513*0c7d530aSIgor Reznichenko } 514*0c7d530aSIgor Reznichenko break; 515*0c7d530aSIgor Reznichenko case hwmon_curr: 516*0c7d530aSIgor Reznichenko switch (attr) { 517*0c7d530aSIgor Reznichenko case hwmon_curr_input: 518*0c7d530aSIgor Reznichenko return 0444; 519*0c7d530aSIgor Reznichenko case hwmon_curr_min: 520*0c7d530aSIgor Reznichenko case hwmon_curr_max: 521*0c7d530aSIgor Reznichenko return 0644; 522*0c7d530aSIgor Reznichenko case hwmon_curr_min_alarm: 523*0c7d530aSIgor Reznichenko case hwmon_curr_max_alarm: 524*0c7d530aSIgor Reznichenko return 0444; 525*0c7d530aSIgor Reznichenko default: 526*0c7d530aSIgor Reznichenko break; 527*0c7d530aSIgor Reznichenko } 528*0c7d530aSIgor Reznichenko break; 529*0c7d530aSIgor Reznichenko case hwmon_power: 530*0c7d530aSIgor Reznichenko switch (attr) { 531*0c7d530aSIgor Reznichenko case hwmon_power_input: 532*0c7d530aSIgor Reznichenko return 0444; 533*0c7d530aSIgor Reznichenko case hwmon_power_max: 534*0c7d530aSIgor Reznichenko return 0644; 535*0c7d530aSIgor Reznichenko case hwmon_power_max_alarm: 536*0c7d530aSIgor Reznichenko return 0444; 537*0c7d530aSIgor Reznichenko default: 538*0c7d530aSIgor Reznichenko break; 539*0c7d530aSIgor Reznichenko } 540*0c7d530aSIgor Reznichenko break; 541*0c7d530aSIgor Reznichenko case hwmon_temp: 542*0c7d530aSIgor Reznichenko switch (attr) { 543*0c7d530aSIgor Reznichenko case hwmon_temp_input: 544*0c7d530aSIgor Reznichenko return 0444; 545*0c7d530aSIgor Reznichenko case hwmon_temp_max: 546*0c7d530aSIgor Reznichenko return 0644; 547*0c7d530aSIgor Reznichenko case hwmon_temp_max_alarm: 548*0c7d530aSIgor Reznichenko return 0444; 549*0c7d530aSIgor Reznichenko default: 550*0c7d530aSIgor Reznichenko break; 551*0c7d530aSIgor Reznichenko } 552*0c7d530aSIgor Reznichenko break; 553*0c7d530aSIgor Reznichenko default: 554*0c7d530aSIgor Reznichenko break; 555*0c7d530aSIgor Reznichenko } 556*0c7d530aSIgor Reznichenko return 0; 557*0c7d530aSIgor Reznichenko } 558*0c7d530aSIgor Reznichenko 559*0c7d530aSIgor Reznichenko static int tsc1641_read(struct device *dev, enum hwmon_sensor_types type, 560*0c7d530aSIgor Reznichenko u32 attr, int channel, long *val) 561*0c7d530aSIgor Reznichenko { 562*0c7d530aSIgor Reznichenko switch (type) { 563*0c7d530aSIgor Reznichenko case hwmon_chip: 564*0c7d530aSIgor Reznichenko return tsc1641_chip_read(dev, attr, val); 565*0c7d530aSIgor Reznichenko case hwmon_in: 566*0c7d530aSIgor Reznichenko return tsc1641_in_read(dev, attr, val); 567*0c7d530aSIgor Reznichenko case hwmon_curr: 568*0c7d530aSIgor Reznichenko return tsc1641_curr_read(dev, attr, val); 569*0c7d530aSIgor Reznichenko case hwmon_power: 570*0c7d530aSIgor Reznichenko return tsc1641_power_read(dev, attr, val); 571*0c7d530aSIgor Reznichenko case hwmon_temp: 572*0c7d530aSIgor Reznichenko return tsc1641_temp_read(dev, attr, val); 573*0c7d530aSIgor Reznichenko default: 574*0c7d530aSIgor Reznichenko return -EOPNOTSUPP; 575*0c7d530aSIgor Reznichenko } 576*0c7d530aSIgor Reznichenko } 577*0c7d530aSIgor Reznichenko 578*0c7d530aSIgor Reznichenko static int tsc1641_write(struct device *dev, enum hwmon_sensor_types type, 579*0c7d530aSIgor Reznichenko u32 attr, int channel, long val) 580*0c7d530aSIgor Reznichenko { 581*0c7d530aSIgor Reznichenko switch (type) { 582*0c7d530aSIgor Reznichenko case hwmon_chip: 583*0c7d530aSIgor Reznichenko return tsc1641_chip_write(dev, attr, val); 584*0c7d530aSIgor Reznichenko case hwmon_in: 585*0c7d530aSIgor Reznichenko return tsc1641_in_write(dev, attr, val); 586*0c7d530aSIgor Reznichenko case hwmon_curr: 587*0c7d530aSIgor Reznichenko return tsc1641_curr_write(dev, attr, val); 588*0c7d530aSIgor Reznichenko case hwmon_power: 589*0c7d530aSIgor Reznichenko return tsc1641_power_write(dev, attr, val); 590*0c7d530aSIgor Reznichenko case hwmon_temp: 591*0c7d530aSIgor Reznichenko return tsc1641_temp_write(dev, attr, val); 592*0c7d530aSIgor Reznichenko default: 593*0c7d530aSIgor Reznichenko return -EOPNOTSUPP; 594*0c7d530aSIgor Reznichenko } 595*0c7d530aSIgor Reznichenko } 596*0c7d530aSIgor Reznichenko 597*0c7d530aSIgor Reznichenko static const struct hwmon_channel_info * const tsc1641_info[] = { 598*0c7d530aSIgor Reznichenko HWMON_CHANNEL_INFO(chip, 599*0c7d530aSIgor Reznichenko HWMON_C_UPDATE_INTERVAL), 600*0c7d530aSIgor Reznichenko HWMON_CHANNEL_INFO(in, 601*0c7d530aSIgor Reznichenko HWMON_I_INPUT | HWMON_I_MAX | HWMON_I_MAX_ALARM | 602*0c7d530aSIgor Reznichenko HWMON_I_MIN | HWMON_I_MIN_ALARM), 603*0c7d530aSIgor Reznichenko HWMON_CHANNEL_INFO(curr, 604*0c7d530aSIgor Reznichenko HWMON_C_INPUT | HWMON_C_MAX | HWMON_C_MAX_ALARM | 605*0c7d530aSIgor Reznichenko HWMON_C_MIN | HWMON_C_MIN_ALARM), 606*0c7d530aSIgor Reznichenko HWMON_CHANNEL_INFO(power, 607*0c7d530aSIgor Reznichenko HWMON_P_INPUT | HWMON_P_MAX | HWMON_P_MAX_ALARM), 608*0c7d530aSIgor Reznichenko HWMON_CHANNEL_INFO(temp, 609*0c7d530aSIgor Reznichenko HWMON_T_INPUT | HWMON_T_MAX | HWMON_T_MAX_ALARM), 610*0c7d530aSIgor Reznichenko NULL 611*0c7d530aSIgor Reznichenko }; 612*0c7d530aSIgor Reznichenko 613*0c7d530aSIgor Reznichenko static ssize_t shunt_resistor_show(struct device *dev, 614*0c7d530aSIgor Reznichenko struct device_attribute *da, char *buf) 615*0c7d530aSIgor Reznichenko { 616*0c7d530aSIgor Reznichenko struct tsc1641_data *data = dev_get_drvdata(dev); 617*0c7d530aSIgor Reznichenko 618*0c7d530aSIgor Reznichenko return sysfs_emit(buf, "%li\n", data->rshunt_uohm); 619*0c7d530aSIgor Reznichenko } 620*0c7d530aSIgor Reznichenko 621*0c7d530aSIgor Reznichenko static ssize_t shunt_resistor_store(struct device *dev, 622*0c7d530aSIgor Reznichenko struct device_attribute *da, 623*0c7d530aSIgor Reznichenko const char *buf, size_t count) 624*0c7d530aSIgor Reznichenko { 625*0c7d530aSIgor Reznichenko struct tsc1641_data *data = dev_get_drvdata(dev); 626*0c7d530aSIgor Reznichenko unsigned int val; 627*0c7d530aSIgor Reznichenko int ret; 628*0c7d530aSIgor Reznichenko 629*0c7d530aSIgor Reznichenko ret = kstrtouint(buf, 10, &val); 630*0c7d530aSIgor Reznichenko if (ret < 0) 631*0c7d530aSIgor Reznichenko return ret; 632*0c7d530aSIgor Reznichenko 633*0c7d530aSIgor Reznichenko ret = tsc1641_validate_shunt(val); 634*0c7d530aSIgor Reznichenko if (ret < 0) 635*0c7d530aSIgor Reznichenko return ret; 636*0c7d530aSIgor Reznichenko 637*0c7d530aSIgor Reznichenko ret = tsc1641_set_shunt(data, val); 638*0c7d530aSIgor Reznichenko if (ret < 0) 639*0c7d530aSIgor Reznichenko return ret; 640*0c7d530aSIgor Reznichenko return count; 641*0c7d530aSIgor Reznichenko } 642*0c7d530aSIgor Reznichenko 643*0c7d530aSIgor Reznichenko static const struct hwmon_ops tsc1641_hwmon_ops = { 644*0c7d530aSIgor Reznichenko .is_visible = tsc1641_is_visible, 645*0c7d530aSIgor Reznichenko .read = tsc1641_read, 646*0c7d530aSIgor Reznichenko .write = tsc1641_write, 647*0c7d530aSIgor Reznichenko }; 648*0c7d530aSIgor Reznichenko 649*0c7d530aSIgor Reznichenko static const struct hwmon_chip_info tsc1641_chip_info = { 650*0c7d530aSIgor Reznichenko .ops = &tsc1641_hwmon_ops, 651*0c7d530aSIgor Reznichenko .info = tsc1641_info, 652*0c7d530aSIgor Reznichenko }; 653*0c7d530aSIgor Reznichenko 654*0c7d530aSIgor Reznichenko static DEVICE_ATTR_RW(shunt_resistor); 655*0c7d530aSIgor Reznichenko 656*0c7d530aSIgor Reznichenko /* Shunt resistor value is exposed via sysfs attribute */ 657*0c7d530aSIgor Reznichenko static struct attribute *tsc1641_attrs[] = { 658*0c7d530aSIgor Reznichenko &dev_attr_shunt_resistor.attr, 659*0c7d530aSIgor Reznichenko NULL, 660*0c7d530aSIgor Reznichenko }; 661*0c7d530aSIgor Reznichenko ATTRIBUTE_GROUPS(tsc1641); 662*0c7d530aSIgor Reznichenko 663*0c7d530aSIgor Reznichenko static int tsc1641_init(struct device *dev, struct tsc1641_data *data) 664*0c7d530aSIgor Reznichenko { 665*0c7d530aSIgor Reznichenko struct regmap *regmap = data->regmap; 666*0c7d530aSIgor Reznichenko bool active_high; 667*0c7d530aSIgor Reznichenko u32 shunt; 668*0c7d530aSIgor Reznichenko int ret; 669*0c7d530aSIgor Reznichenko 670*0c7d530aSIgor Reznichenko if (device_property_read_u32(dev, "shunt-resistor-micro-ohms", &shunt) < 0) 671*0c7d530aSIgor Reznichenko shunt = TSC1641_RSHUNT_DEFAULT; 672*0c7d530aSIgor Reznichenko 673*0c7d530aSIgor Reznichenko if (tsc1641_validate_shunt(shunt) < 0) { 674*0c7d530aSIgor Reznichenko dev_err(dev, "invalid shunt resistor value %u\n", shunt); 675*0c7d530aSIgor Reznichenko return -EINVAL; 676*0c7d530aSIgor Reznichenko } 677*0c7d530aSIgor Reznichenko 678*0c7d530aSIgor Reznichenko ret = tsc1641_set_shunt(data, shunt); 679*0c7d530aSIgor Reznichenko if (ret < 0) 680*0c7d530aSIgor Reznichenko return ret; 681*0c7d530aSIgor Reznichenko 682*0c7d530aSIgor Reznichenko ret = regmap_write(regmap, TSC1641_CONFIG, TSC1641_CONFIG_DEFAULT); 683*0c7d530aSIgor Reznichenko if (ret < 0) 684*0c7d530aSIgor Reznichenko return ret; 685*0c7d530aSIgor Reznichenko 686*0c7d530aSIgor Reznichenko active_high = device_property_read_bool(dev, "st,alert-polarity-active-high"); 687*0c7d530aSIgor Reznichenko 688*0c7d530aSIgor Reznichenko return regmap_write(regmap, TSC1641_MASK, TSC1641_MASK_DEFAULT | 689*0c7d530aSIgor Reznichenko FIELD_PREP(TSC1641_ALERT_POL_MASK, active_high)); 690*0c7d530aSIgor Reznichenko } 691*0c7d530aSIgor Reznichenko 692*0c7d530aSIgor Reznichenko static int tsc1641_probe(struct i2c_client *client) 693*0c7d530aSIgor Reznichenko { 694*0c7d530aSIgor Reznichenko struct device *dev = &client->dev; 695*0c7d530aSIgor Reznichenko struct tsc1641_data *data; 696*0c7d530aSIgor Reznichenko struct device *hwmon_dev; 697*0c7d530aSIgor Reznichenko int ret; 698*0c7d530aSIgor Reznichenko 699*0c7d530aSIgor Reznichenko data = devm_kzalloc(dev, sizeof(*data), GFP_KERNEL); 700*0c7d530aSIgor Reznichenko if (!data) 701*0c7d530aSIgor Reznichenko return -ENOMEM; 702*0c7d530aSIgor Reznichenko 703*0c7d530aSIgor Reznichenko data->regmap = devm_regmap_init_i2c(client, &tsc1641_regmap_config); 704*0c7d530aSIgor Reznichenko if (IS_ERR(data->regmap)) 705*0c7d530aSIgor Reznichenko return dev_err_probe(dev, PTR_ERR(data->regmap), 706*0c7d530aSIgor Reznichenko "failed to allocate register map\n"); 707*0c7d530aSIgor Reznichenko 708*0c7d530aSIgor Reznichenko ret = tsc1641_init(dev, data); 709*0c7d530aSIgor Reznichenko if (ret < 0) 710*0c7d530aSIgor Reznichenko return dev_err_probe(dev, ret, "failed to configure device\n"); 711*0c7d530aSIgor Reznichenko 712*0c7d530aSIgor Reznichenko hwmon_dev = devm_hwmon_device_register_with_info(dev, client->name, 713*0c7d530aSIgor Reznichenko data, &tsc1641_chip_info, tsc1641_groups); 714*0c7d530aSIgor Reznichenko if (IS_ERR(hwmon_dev)) 715*0c7d530aSIgor Reznichenko return PTR_ERR(hwmon_dev); 716*0c7d530aSIgor Reznichenko 717*0c7d530aSIgor Reznichenko dev_info(dev, "power monitor %s (Rshunt = %li uOhm)\n", 718*0c7d530aSIgor Reznichenko client->name, data->rshunt_uohm); 719*0c7d530aSIgor Reznichenko 720*0c7d530aSIgor Reznichenko return 0; 721*0c7d530aSIgor Reznichenko } 722*0c7d530aSIgor Reznichenko 723*0c7d530aSIgor Reznichenko static const struct i2c_device_id tsc1641_id[] = { 724*0c7d530aSIgor Reznichenko { "tsc1641", 0 }, 725*0c7d530aSIgor Reznichenko { } 726*0c7d530aSIgor Reznichenko }; 727*0c7d530aSIgor Reznichenko MODULE_DEVICE_TABLE(i2c, tsc1641_id); 728*0c7d530aSIgor Reznichenko 729*0c7d530aSIgor Reznichenko static const struct of_device_id __maybe_unused tsc1641_of_match[] = { 730*0c7d530aSIgor Reznichenko { .compatible = "st,tsc1641" }, 731*0c7d530aSIgor Reznichenko { }, 732*0c7d530aSIgor Reznichenko }; 733*0c7d530aSIgor Reznichenko MODULE_DEVICE_TABLE(of, tsc1641_of_match); 734*0c7d530aSIgor Reznichenko 735*0c7d530aSIgor Reznichenko static struct i2c_driver tsc1641_driver = { 736*0c7d530aSIgor Reznichenko .driver = { 737*0c7d530aSIgor Reznichenko .name = "tsc1641", 738*0c7d530aSIgor Reznichenko .of_match_table = of_match_ptr(tsc1641_of_match), 739*0c7d530aSIgor Reznichenko }, 740*0c7d530aSIgor Reznichenko .probe = tsc1641_probe, 741*0c7d530aSIgor Reznichenko .id_table = tsc1641_id, 742*0c7d530aSIgor Reznichenko }; 743*0c7d530aSIgor Reznichenko 744*0c7d530aSIgor Reznichenko module_i2c_driver(tsc1641_driver); 745*0c7d530aSIgor Reznichenko 746*0c7d530aSIgor Reznichenko MODULE_AUTHOR("Igor Reznichenko <igor@reznichenko.net>"); 747*0c7d530aSIgor Reznichenko MODULE_DESCRIPTION("tsc1641 driver"); 748*0c7d530aSIgor Reznichenko MODULE_LICENSE("GPL"); 749