1b886d83cSThomas Gleixner // SPDX-License-Identifier: GPL-2.0-only 2f7c2fe38SFelten, Lothar /* 3f7c2fe38SFelten, Lothar * Driver for Texas Instruments INA219, INA226 power monitor chips 4f7c2fe38SFelten, Lothar * 5f7c2fe38SFelten, Lothar * INA219: 6f7c2fe38SFelten, Lothar * Zero Drift Bi-Directional Current/Power Monitor with I2C Interface 749dc2fb0SAlexander A. Klimov * Datasheet: https://www.ti.com/product/ina219 8f7c2fe38SFelten, Lothar * 9dc92cd0cSGuenter Roeck * INA220: 10dc92cd0cSGuenter Roeck * Bi-Directional Current/Power Monitor with I2C Interface 1149dc2fb0SAlexander A. Klimov * Datasheet: https://www.ti.com/product/ina220 12dc92cd0cSGuenter Roeck * 13f7c2fe38SFelten, Lothar * INA226: 14f7c2fe38SFelten, Lothar * Bi-Directional Current/Power Monitor with I2C Interface 1549dc2fb0SAlexander A. Klimov * Datasheet: https://www.ti.com/product/ina226 16f7c2fe38SFelten, Lothar * 17dc92cd0cSGuenter Roeck * INA230: 18dc92cd0cSGuenter Roeck * Bi-directional Current/Power Monitor with I2C Interface 1949dc2fb0SAlexander A. Klimov * Datasheet: https://www.ti.com/product/ina230 20dc92cd0cSGuenter Roeck * 213ad86700SLothar Felten * Copyright (C) 2012 Lothar Felten <lothar.felten@gmail.com> 22f7c2fe38SFelten, Lothar * Thanks to Jan Volkering 23f7c2fe38SFelten, Lothar */ 24f7c2fe38SFelten, Lothar 25232177a3SGuenter Roeck #include <linux/bitfield.h> 26232177a3SGuenter Roeck #include <linux/bits.h> 279e60bb81SGuenter Roeck #include <linux/delay.h> 28f7c2fe38SFelten, Lothar #include <linux/err.h> 29f7c2fe38SFelten, Lothar #include <linux/hwmon.h> 30f7c2fe38SFelten, Lothar #include <linux/hwmon-sysfs.h> 319e60bb81SGuenter Roeck #include <linux/i2c.h> 329e60bb81SGuenter Roeck #include <linux/init.h> 339e60bb81SGuenter Roeck #include <linux/kernel.h> 349e60bb81SGuenter Roeck #include <linux/module.h> 3561a4a841SGuenter Roeck #include <linux/property.h> 36a0de56c8SMarc Titinger #include <linux/regmap.h> 379e60bb81SGuenter Roeck #include <linux/slab.h> 389e60bb81SGuenter Roeck #include <linux/util_macros.h> 39f7c2fe38SFelten, Lothar 40f7c2fe38SFelten, Lothar /* common register definitions */ 41f7c2fe38SFelten, Lothar #define INA2XX_CONFIG 0x00 42f7c2fe38SFelten, Lothar #define INA2XX_SHUNT_VOLTAGE 0x01 /* readonly */ 43f7c2fe38SFelten, Lothar #define INA2XX_BUS_VOLTAGE 0x02 /* readonly */ 44f7c2fe38SFelten, Lothar #define INA2XX_POWER 0x03 /* readonly */ 45f7c2fe38SFelten, Lothar #define INA2XX_CURRENT 0x04 /* readonly */ 46f7c2fe38SFelten, Lothar #define INA2XX_CALIBRATION 0x05 47f7c2fe38SFelten, Lothar 48f7c2fe38SFelten, Lothar /* INA226 register definitions */ 49f7c2fe38SFelten, Lothar #define INA226_MASK_ENABLE 0x06 50f7c2fe38SFelten, Lothar #define INA226_ALERT_LIMIT 0x07 51f7c2fe38SFelten, Lothar #define INA226_DIE_ID 0xFF 52f7c2fe38SFelten, Lothar 53f7c2fe38SFelten, Lothar #define INA2XX_MAX_REGISTERS 8 54f7c2fe38SFelten, Lothar 55f7c2fe38SFelten, Lothar /* settings - depend on use case */ 56f7c2fe38SFelten, Lothar #define INA219_CONFIG_DEFAULT 0x399F /* PGA=8 */ 57f7c2fe38SFelten, Lothar #define INA226_CONFIG_DEFAULT 0x4527 /* averages=16 */ 58f7c2fe38SFelten, Lothar 59f7c2fe38SFelten, Lothar /* worst case is 68.10 ms (~14.6Hz, ina219) */ 60f7c2fe38SFelten, Lothar #define INA2XX_CONVERSION_RATE 15 61509416a8SBartosz Golaszewski #define INA2XX_MAX_DELAY 69 /* worst case delay in ms */ 62509416a8SBartosz Golaszewski 63509416a8SBartosz Golaszewski #define INA2XX_RSHUNT_DEFAULT 10000 64f7c2fe38SFelten, Lothar 6572a87a47SBartosz Golaszewski /* bit mask for reading the averaging setting in the configuration register */ 66232177a3SGuenter Roeck #define INA226_AVG_RD_MASK GENMASK(11, 9) 6772a87a47SBartosz Golaszewski 68232177a3SGuenter Roeck #define INA226_READ_AVG(reg) FIELD_GET(INA226_AVG_RD_MASK, reg) 6972a87a47SBartosz Golaszewski 70232177a3SGuenter Roeck #define INA226_ALERT_POLARITY_MASK BIT(1) 71ec5d234fSAmna Waseem #define INA226_ALERT_POL_LOW 0 72ec5d234fSAmna Waseem #define INA226_ALERT_POL_HIGH 1 73ec5d234fSAmna Waseem 745a56a39bSAlex Qiu /* bit number of alert functions in Mask/Enable Register */ 75232177a3SGuenter Roeck #define INA226_SHUNT_OVER_VOLTAGE_MASK BIT(15) 76232177a3SGuenter Roeck #define INA226_SHUNT_UNDER_VOLTAGE_MASK BIT(14) 77232177a3SGuenter Roeck #define INA226_BUS_OVER_VOLTAGE_MASK BIT(13) 78232177a3SGuenter Roeck #define INA226_BUS_UNDER_VOLTAGE_MASK BIT(12) 79232177a3SGuenter Roeck #define INA226_POWER_OVER_LIMIT_MASK BIT(11) 805a56a39bSAlex Qiu 815a56a39bSAlex Qiu /* bit mask for alert config bits of Mask/Enable Register */ 82232177a3SGuenter Roeck #define INA226_ALERT_CONFIG_MASK GENMASK(15, 10) 835a56a39bSAlex Qiu #define INA226_ALERT_FUNCTION_FLAG BIT(4) 845a56a39bSAlex Qiu 8572a87a47SBartosz Golaszewski /* common attrs, ina226 attrs and NULL */ 8672a87a47SBartosz Golaszewski #define INA2XX_MAX_ATTRIBUTE_GROUPS 3 8772a87a47SBartosz Golaszewski 8872a87a47SBartosz Golaszewski /* 8972a87a47SBartosz Golaszewski * Both bus voltage and shunt voltage conversion times for ina226 are set 9072a87a47SBartosz Golaszewski * to 0b0100 on POR, which translates to 2200 microseconds in total. 9172a87a47SBartosz Golaszewski */ 9272a87a47SBartosz Golaszewski #define INA226_TOTAL_CONV_TIME_DEFAULT 2200 9372a87a47SBartosz Golaszewski 94bb25cdc2SGuenter Roeck static bool ina2xx_writeable_reg(struct device *dev, unsigned int reg) 95bb25cdc2SGuenter Roeck { 96bb25cdc2SGuenter Roeck switch (reg) { 97bb25cdc2SGuenter Roeck case INA2XX_CONFIG: 98bb25cdc2SGuenter Roeck case INA2XX_CALIBRATION: 99bb25cdc2SGuenter Roeck case INA226_MASK_ENABLE: 100bb25cdc2SGuenter Roeck case INA226_ALERT_LIMIT: 101bb25cdc2SGuenter Roeck return true; 102bb25cdc2SGuenter Roeck default: 103bb25cdc2SGuenter Roeck return false; 104bb25cdc2SGuenter Roeck } 105bb25cdc2SGuenter Roeck } 106bb25cdc2SGuenter Roeck 107bb25cdc2SGuenter Roeck static bool ina2xx_volatile_reg(struct device *dev, unsigned int reg) 108bb25cdc2SGuenter Roeck { 109bb25cdc2SGuenter Roeck switch (reg) { 110bb25cdc2SGuenter Roeck case INA2XX_SHUNT_VOLTAGE: 111bb25cdc2SGuenter Roeck case INA2XX_BUS_VOLTAGE: 112bb25cdc2SGuenter Roeck case INA2XX_POWER: 113bb25cdc2SGuenter Roeck case INA2XX_CURRENT: 114bb25cdc2SGuenter Roeck return true; 115bb25cdc2SGuenter Roeck default: 116bb25cdc2SGuenter Roeck return false; 117bb25cdc2SGuenter Roeck } 118bb25cdc2SGuenter Roeck } 119bb25cdc2SGuenter Roeck 1202bb47652SGuenter Roeck static const struct regmap_config ina2xx_regmap_config = { 121a0de56c8SMarc Titinger .reg_bits = 8, 122a0de56c8SMarc Titinger .val_bits = 16, 123bb25cdc2SGuenter Roeck .use_single_write = true, 124bb25cdc2SGuenter Roeck .use_single_read = true, 1252bb47652SGuenter Roeck .max_register = INA2XX_MAX_REGISTERS, 126bb25cdc2SGuenter Roeck .cache_type = REGCACHE_MAPLE, 127bb25cdc2SGuenter Roeck .volatile_reg = ina2xx_volatile_reg, 128bb25cdc2SGuenter Roeck .writeable_reg = ina2xx_writeable_reg, 129a0de56c8SMarc Titinger }; 130a0de56c8SMarc Titinger 131f7c2fe38SFelten, Lothar enum ina2xx_ids { ina219, ina226 }; 132f7c2fe38SFelten, Lothar 1336106db25SGuenter Roeck struct ina2xx_config { 1346106db25SGuenter Roeck u16 config_default; 1355d389b12SMaciej Purski int calibration_value; 1366106db25SGuenter Roeck int shunt_div; 1376106db25SGuenter Roeck int bus_voltage_shift; 1386106db25SGuenter Roeck int bus_voltage_lsb; /* uV */ 1395d389b12SMaciej Purski int power_lsb_factor; 1406106db25SGuenter Roeck }; 1416106db25SGuenter Roeck 142f7c2fe38SFelten, Lothar struct ina2xx_data { 1436106db25SGuenter Roeck const struct ina2xx_config *config; 144f7c2fe38SFelten, Lothar 145509416a8SBartosz Golaszewski long rshunt; 1465d389b12SMaciej Purski long current_lsb_uA; 1475d389b12SMaciej Purski long power_lsb_uW; 148a0de56c8SMarc Titinger struct mutex config_lock; 149a0de56c8SMarc Titinger struct regmap *regmap; 150f7c2fe38SFelten, Lothar 15172a87a47SBartosz Golaszewski const struct attribute_group *groups[INA2XX_MAX_ATTRIBUTE_GROUPS]; 152f7c2fe38SFelten, Lothar }; 153f7c2fe38SFelten, Lothar 1546106db25SGuenter Roeck static const struct ina2xx_config ina2xx_config[] = { 1556106db25SGuenter Roeck [ina219] = { 1566106db25SGuenter Roeck .config_default = INA219_CONFIG_DEFAULT, 1575d389b12SMaciej Purski .calibration_value = 4096, 1586106db25SGuenter Roeck .shunt_div = 100, 1596106db25SGuenter Roeck .bus_voltage_shift = 3, 1606106db25SGuenter Roeck .bus_voltage_lsb = 4000, 1615d389b12SMaciej Purski .power_lsb_factor = 20, 1626106db25SGuenter Roeck }, 1636106db25SGuenter Roeck [ina226] = { 1646106db25SGuenter Roeck .config_default = INA226_CONFIG_DEFAULT, 1655d389b12SMaciej Purski .calibration_value = 2048, 1666106db25SGuenter Roeck .shunt_div = 400, 1676106db25SGuenter Roeck .bus_voltage_shift = 0, 1686106db25SGuenter Roeck .bus_voltage_lsb = 1250, 1695d389b12SMaciej Purski .power_lsb_factor = 25, 1706106db25SGuenter Roeck }, 1716106db25SGuenter Roeck }; 1726106db25SGuenter Roeck 17372a87a47SBartosz Golaszewski /* 17472a87a47SBartosz Golaszewski * Available averaging rates for ina226. The indices correspond with 17572a87a47SBartosz Golaszewski * the bit values expected by the chip (according to the ina226 datasheet, 17672a87a47SBartosz Golaszewski * table 3 AVG bit settings, found at 17749dc2fb0SAlexander A. Klimov * https://www.ti.com/lit/ds/symlink/ina226.pdf. 17872a87a47SBartosz Golaszewski */ 17972a87a47SBartosz Golaszewski static const int ina226_avg_tab[] = { 1, 4, 16, 64, 128, 256, 512, 1024 }; 18072a87a47SBartosz Golaszewski 18172a87a47SBartosz Golaszewski static int ina226_reg_to_interval(u16 config) 18272a87a47SBartosz Golaszewski { 18372a87a47SBartosz Golaszewski int avg = ina226_avg_tab[INA226_READ_AVG(config)]; 18472a87a47SBartosz Golaszewski 18572a87a47SBartosz Golaszewski /* 18672a87a47SBartosz Golaszewski * Multiply the total conversion time by the number of averages. 18772a87a47SBartosz Golaszewski * Return the result in milliseconds. 18872a87a47SBartosz Golaszewski */ 18972a87a47SBartosz Golaszewski return DIV_ROUND_CLOSEST(avg * INA226_TOTAL_CONV_TIME_DEFAULT, 1000); 19072a87a47SBartosz Golaszewski } 19172a87a47SBartosz Golaszewski 192a0de56c8SMarc Titinger /* 193a0de56c8SMarc Titinger * Return the new, shifted AVG field value of CONFIG register, 194a0de56c8SMarc Titinger * to use with regmap_update_bits 195a0de56c8SMarc Titinger */ 196*ab7fbee4SGuenter Roeck static u16 ina226_interval_to_reg(unsigned long interval) 19772a87a47SBartosz Golaszewski { 19872a87a47SBartosz Golaszewski int avg, avg_bits; 19972a87a47SBartosz Golaszewski 200*ab7fbee4SGuenter Roeck /* 201*ab7fbee4SGuenter Roeck * The maximum supported interval is 1,024 * (2 * 8.244ms) ~= 16.8s. 202*ab7fbee4SGuenter Roeck * Clamp to 32 seconds before calculations to avoid overflows. 203*ab7fbee4SGuenter Roeck */ 204*ab7fbee4SGuenter Roeck interval = clamp_val(interval, 0, 32000); 205*ab7fbee4SGuenter Roeck 20672a87a47SBartosz Golaszewski avg = DIV_ROUND_CLOSEST(interval * 1000, 20772a87a47SBartosz Golaszewski INA226_TOTAL_CONV_TIME_DEFAULT); 208d38df34eSBartosz Golaszewski avg_bits = find_closest(avg, ina226_avg_tab, 209d38df34eSBartosz Golaszewski ARRAY_SIZE(ina226_avg_tab)); 21072a87a47SBartosz Golaszewski 211232177a3SGuenter Roeck return FIELD_PREP(INA226_AVG_RD_MASK, avg_bits); 21272a87a47SBartosz Golaszewski } 21372a87a47SBartosz Golaszewski 214ec5d234fSAmna Waseem static int ina2xx_set_alert_polarity(struct ina2xx_data *data, 215ec5d234fSAmna Waseem unsigned long val) 216ec5d234fSAmna Waseem { 217ec5d234fSAmna Waseem return regmap_update_bits(data->regmap, INA226_MASK_ENABLE, 218ec5d234fSAmna Waseem INA226_ALERT_POLARITY_MASK, 219232177a3SGuenter Roeck FIELD_PREP(INA226_ALERT_POLARITY_MASK, val)); 220ec5d234fSAmna Waseem } 221ec5d234fSAmna Waseem 2225d389b12SMaciej Purski /* 2235d389b12SMaciej Purski * Calibration register is set to the best value, which eliminates 2245d389b12SMaciej Purski * truncation errors on calculating current register in hardware. 2255d389b12SMaciej Purski * According to datasheet (eq. 3) the best values are 2048 for 2265d389b12SMaciej Purski * ina226 and 4096 for ina219. They are hardcoded as calibration_value. 2275d389b12SMaciej Purski */ 2288a5fc795SBartosz Golaszewski static int ina2xx_calibrate(struct ina2xx_data *data) 2298a5fc795SBartosz Golaszewski { 2305d389b12SMaciej Purski return regmap_write(data->regmap, INA2XX_CALIBRATION, 2315d389b12SMaciej Purski data->config->calibration_value); 2328a5fc795SBartosz Golaszewski } 2338a5fc795SBartosz Golaszewski 234509416a8SBartosz Golaszewski /* 235509416a8SBartosz Golaszewski * Initialize the configuration and calibration registers. 236509416a8SBartosz Golaszewski */ 237509416a8SBartosz Golaszewski static int ina2xx_init(struct ina2xx_data *data) 238509416a8SBartosz Golaszewski { 239a0de56c8SMarc Titinger int ret = regmap_write(data->regmap, INA2XX_CONFIG, 240a0de56c8SMarc Titinger data->config->config_default); 241509416a8SBartosz Golaszewski if (ret < 0) 242509416a8SBartosz Golaszewski return ret; 243509416a8SBartosz Golaszewski 2448a5fc795SBartosz Golaszewski return ina2xx_calibrate(data); 245509416a8SBartosz Golaszewski } 246509416a8SBartosz Golaszewski 247a0de56c8SMarc Titinger static int ina2xx_read_reg(struct device *dev, int reg, unsigned int *regval) 248f7c2fe38SFelten, Lothar { 249468bf0e3SGuenter Roeck struct ina2xx_data *data = dev_get_drvdata(dev); 250d491e781SGuenter Roeck struct regmap *regmap = data->regmap; 251a0de56c8SMarc Titinger int ret, retry; 252509416a8SBartosz Golaszewski 253509416a8SBartosz Golaszewski for (retry = 5; retry; retry--) { 254d491e781SGuenter Roeck ret = regmap_read(regmap, reg, regval); 255a0de56c8SMarc Titinger if (ret < 0) 256a0de56c8SMarc Titinger return ret; 257a0de56c8SMarc Titinger 258509416a8SBartosz Golaszewski /* 259509416a8SBartosz Golaszewski * If the current value in the calibration register is 0, the 260509416a8SBartosz Golaszewski * power and current registers will also remain at 0. In case 261509416a8SBartosz Golaszewski * the chip has been reset let's check the calibration 262509416a8SBartosz Golaszewski * register and reinitialize if needed. 263a0de56c8SMarc Titinger * We do that extra read of the calibration register if there 264a0de56c8SMarc Titinger * is some hint of a chip reset. 265509416a8SBartosz Golaszewski */ 266a0de56c8SMarc Titinger if (*regval == 0) { 267a0de56c8SMarc Titinger unsigned int cal; 268a0de56c8SMarc Titinger 269bb25cdc2SGuenter Roeck ret = regmap_read_bypassed(regmap, INA2XX_CALIBRATION, &cal); 270a0de56c8SMarc Titinger if (ret < 0) 271a0de56c8SMarc Titinger return ret; 272a0de56c8SMarc Titinger 273a0de56c8SMarc Titinger if (cal == 0) { 274509416a8SBartosz Golaszewski dev_warn(dev, "chip not calibrated, reinitializing\n"); 275509416a8SBartosz Golaszewski 276bb25cdc2SGuenter Roeck regcache_mark_dirty(regmap); 277bb25cdc2SGuenter Roeck regcache_sync(regmap); 278bb25cdc2SGuenter Roeck 279509416a8SBartosz Golaszewski /* 280a0de56c8SMarc Titinger * Let's make sure the power and current 281a0de56c8SMarc Titinger * registers have been updated before trying 282a0de56c8SMarc Titinger * again. 283509416a8SBartosz Golaszewski */ 284509416a8SBartosz Golaszewski msleep(INA2XX_MAX_DELAY); 285509416a8SBartosz Golaszewski continue; 286509416a8SBartosz Golaszewski } 287a0de56c8SMarc Titinger } 288509416a8SBartosz Golaszewski return 0; 289509416a8SBartosz Golaszewski } 290509416a8SBartosz Golaszewski 291509416a8SBartosz Golaszewski /* 292509416a8SBartosz Golaszewski * If we're here then although all write operations succeeded, the 293509416a8SBartosz Golaszewski * chip still returns 0 in the calibration register. Nothing more we 294509416a8SBartosz Golaszewski * can do here. 295509416a8SBartosz Golaszewski */ 296509416a8SBartosz Golaszewski dev_err(dev, "unable to reinitialize the chip\n"); 297509416a8SBartosz Golaszewski return -ENODEV; 298509416a8SBartosz Golaszewski } 299509416a8SBartosz Golaszewski 300a0de56c8SMarc Titinger static int ina2xx_get_value(struct ina2xx_data *data, u8 reg, 301a0de56c8SMarc Titinger unsigned int regval) 302f7c2fe38SFelten, Lothar { 3036106db25SGuenter Roeck int val; 304f7c2fe38SFelten, Lothar 305f7c2fe38SFelten, Lothar switch (reg) { 306f7c2fe38SFelten, Lothar case INA2XX_SHUNT_VOLTAGE: 307c0214f98SFabio Baltieri /* signed register */ 308a0de56c8SMarc Titinger val = DIV_ROUND_CLOSEST((s16)regval, data->config->shunt_div); 309f7c2fe38SFelten, Lothar break; 310f7c2fe38SFelten, Lothar case INA2XX_BUS_VOLTAGE: 311a0de56c8SMarc Titinger val = (regval >> data->config->bus_voltage_shift) 3126106db25SGuenter Roeck * data->config->bus_voltage_lsb; 3136106db25SGuenter Roeck val = DIV_ROUND_CLOSEST(val, 1000); 314f7c2fe38SFelten, Lothar break; 315f7c2fe38SFelten, Lothar case INA2XX_POWER: 3165d389b12SMaciej Purski val = regval * data->power_lsb_uW; 317f7c2fe38SFelten, Lothar break; 318f7c2fe38SFelten, Lothar case INA2XX_CURRENT: 3195d389b12SMaciej Purski /* signed register, result in mA */ 32038cd989eSNicolin Chen val = (s16)regval * data->current_lsb_uA; 3215d389b12SMaciej Purski val = DIV_ROUND_CLOSEST(val, 1000); 322f7c2fe38SFelten, Lothar break; 3238a5fc795SBartosz Golaszewski case INA2XX_CALIBRATION: 3245d389b12SMaciej Purski val = regval; 3258a5fc795SBartosz Golaszewski break; 326f7c2fe38SFelten, Lothar default: 327f7c2fe38SFelten, Lothar /* programmer goofed */ 328f7c2fe38SFelten, Lothar WARN_ON_ONCE(1); 329f7c2fe38SFelten, Lothar val = 0; 330f7c2fe38SFelten, Lothar break; 331f7c2fe38SFelten, Lothar } 332f7c2fe38SFelten, Lothar 333f7c2fe38SFelten, Lothar return val; 334f7c2fe38SFelten, Lothar } 335f7c2fe38SFelten, Lothar 3366a0f234fSGuenter Roeck static ssize_t ina2xx_value_show(struct device *dev, 337f7c2fe38SFelten, Lothar struct device_attribute *da, char *buf) 338f7c2fe38SFelten, Lothar { 339f7c2fe38SFelten, Lothar struct sensor_device_attribute *attr = to_sensor_dev_attr(da); 340a0de56c8SMarc Titinger struct ina2xx_data *data = dev_get_drvdata(dev); 341a0de56c8SMarc Titinger unsigned int regval; 342f7c2fe38SFelten, Lothar 343a0de56c8SMarc Titinger int err = ina2xx_read_reg(dev, attr->index, ®val); 344a0de56c8SMarc Titinger 345a0de56c8SMarc Titinger if (err < 0) 346a0de56c8SMarc Titinger return err; 347f7c2fe38SFelten, Lothar 348af9a9730SZihao Tang return sysfs_emit(buf, "%d\n", ina2xx_get_value(data, attr->index, regval)); 349f7c2fe38SFelten, Lothar } 350f7c2fe38SFelten, Lothar 351232177a3SGuenter Roeck static int ina226_reg_to_alert(struct ina2xx_data *data, u32 mask, u16 regval) 3525a56a39bSAlex Qiu { 3535a56a39bSAlex Qiu int reg; 3545a56a39bSAlex Qiu 355232177a3SGuenter Roeck switch (mask) { 356232177a3SGuenter Roeck case INA226_SHUNT_OVER_VOLTAGE_MASK: 357232177a3SGuenter Roeck case INA226_SHUNT_UNDER_VOLTAGE_MASK: 3585a56a39bSAlex Qiu reg = INA2XX_SHUNT_VOLTAGE; 3595a56a39bSAlex Qiu break; 360232177a3SGuenter Roeck case INA226_BUS_OVER_VOLTAGE_MASK: 361232177a3SGuenter Roeck case INA226_BUS_UNDER_VOLTAGE_MASK: 3625a56a39bSAlex Qiu reg = INA2XX_BUS_VOLTAGE; 3635a56a39bSAlex Qiu break; 364232177a3SGuenter Roeck case INA226_POWER_OVER_LIMIT_MASK: 3655a56a39bSAlex Qiu reg = INA2XX_POWER; 3665a56a39bSAlex Qiu break; 3675a56a39bSAlex Qiu default: 3685a56a39bSAlex Qiu /* programmer goofed */ 3695a56a39bSAlex Qiu WARN_ON_ONCE(1); 3705a56a39bSAlex Qiu return 0; 3715a56a39bSAlex Qiu } 3725a56a39bSAlex Qiu 3735a56a39bSAlex Qiu return ina2xx_get_value(data, reg, regval); 3745a56a39bSAlex Qiu } 3755a56a39bSAlex Qiu 3765a56a39bSAlex Qiu /* 3775a56a39bSAlex Qiu * Turns alert limit values into register values. 3785a56a39bSAlex Qiu * Opposite of the formula in ina2xx_get_value(). 3795a56a39bSAlex Qiu */ 380*ab7fbee4SGuenter Roeck static u16 ina226_alert_to_reg(struct ina2xx_data *data, u32 mask, unsigned long val) 3815a56a39bSAlex Qiu { 382232177a3SGuenter Roeck switch (mask) { 383232177a3SGuenter Roeck case INA226_SHUNT_OVER_VOLTAGE_MASK: 384232177a3SGuenter Roeck case INA226_SHUNT_UNDER_VOLTAGE_MASK: 385*ab7fbee4SGuenter Roeck val = clamp_val(val, 0, SHRT_MAX * data->config->shunt_div); 3865a56a39bSAlex Qiu val *= data->config->shunt_div; 387*ab7fbee4SGuenter Roeck return clamp_val(val, 0, SHRT_MAX); 388232177a3SGuenter Roeck case INA226_BUS_OVER_VOLTAGE_MASK: 389232177a3SGuenter Roeck case INA226_BUS_UNDER_VOLTAGE_MASK: 390*ab7fbee4SGuenter Roeck val = clamp_val(val, 0, 200000); 3915a56a39bSAlex Qiu val = (val * 1000) << data->config->bus_voltage_shift; 3925a56a39bSAlex Qiu val = DIV_ROUND_CLOSEST(val, data->config->bus_voltage_lsb); 393*ab7fbee4SGuenter Roeck return clamp_val(val, 0, USHRT_MAX); 394232177a3SGuenter Roeck case INA226_POWER_OVER_LIMIT_MASK: 395*ab7fbee4SGuenter Roeck val = clamp_val(val, 0, UINT_MAX - data->power_lsb_uW); 3965a56a39bSAlex Qiu val = DIV_ROUND_CLOSEST(val, data->power_lsb_uW); 3975a56a39bSAlex Qiu return clamp_val(val, 0, USHRT_MAX); 3985a56a39bSAlex Qiu default: 3995a56a39bSAlex Qiu /* programmer goofed */ 4005a56a39bSAlex Qiu WARN_ON_ONCE(1); 4015a56a39bSAlex Qiu return 0; 4025a56a39bSAlex Qiu } 4035a56a39bSAlex Qiu } 4045a56a39bSAlex Qiu 4055a56a39bSAlex Qiu static ssize_t ina226_alert_show(struct device *dev, 4065a56a39bSAlex Qiu struct device_attribute *da, char *buf) 4075a56a39bSAlex Qiu { 4085a56a39bSAlex Qiu struct sensor_device_attribute *attr = to_sensor_dev_attr(da); 4095a56a39bSAlex Qiu struct ina2xx_data *data = dev_get_drvdata(dev); 410d491e781SGuenter Roeck struct regmap *regmap = data->regmap; 4115a56a39bSAlex Qiu int regval; 4125a56a39bSAlex Qiu int val = 0; 4135a56a39bSAlex Qiu int ret; 4145a56a39bSAlex Qiu 4155a56a39bSAlex Qiu mutex_lock(&data->config_lock); 416d491e781SGuenter Roeck ret = regmap_read(regmap, INA226_MASK_ENABLE, ®val); 4175a56a39bSAlex Qiu if (ret) 4185a56a39bSAlex Qiu goto abort; 4195a56a39bSAlex Qiu 420232177a3SGuenter Roeck if (regval & attr->index) { 421d491e781SGuenter Roeck ret = regmap_read(regmap, INA226_ALERT_LIMIT, ®val); 4225a56a39bSAlex Qiu if (ret) 4235a56a39bSAlex Qiu goto abort; 4245a56a39bSAlex Qiu val = ina226_reg_to_alert(data, attr->index, regval); 4255a56a39bSAlex Qiu } 4265a56a39bSAlex Qiu 4271f4d4af4SGuenter Roeck ret = sysfs_emit(buf, "%d\n", val); 4285a56a39bSAlex Qiu abort: 4295a56a39bSAlex Qiu mutex_unlock(&data->config_lock); 4305a56a39bSAlex Qiu return ret; 4315a56a39bSAlex Qiu } 4325a56a39bSAlex Qiu 4335a56a39bSAlex Qiu static ssize_t ina226_alert_store(struct device *dev, 4345a56a39bSAlex Qiu struct device_attribute *da, 4355a56a39bSAlex Qiu const char *buf, size_t count) 4365a56a39bSAlex Qiu { 4375a56a39bSAlex Qiu struct sensor_device_attribute *attr = to_sensor_dev_attr(da); 4385a56a39bSAlex Qiu struct ina2xx_data *data = dev_get_drvdata(dev); 439d491e781SGuenter Roeck struct regmap *regmap = data->regmap; 4405a56a39bSAlex Qiu unsigned long val; 4415a56a39bSAlex Qiu int ret; 4425a56a39bSAlex Qiu 4435a56a39bSAlex Qiu ret = kstrtoul(buf, 10, &val); 4445a56a39bSAlex Qiu if (ret < 0) 4455a56a39bSAlex Qiu return ret; 4465a56a39bSAlex Qiu 4475a56a39bSAlex Qiu /* 4485a56a39bSAlex Qiu * Clear all alerts first to avoid accidentally triggering ALERT pin 4495a56a39bSAlex Qiu * due to register write sequence. Then, only enable the alert 4505a56a39bSAlex Qiu * if the value is non-zero. 4515a56a39bSAlex Qiu */ 4525a56a39bSAlex Qiu mutex_lock(&data->config_lock); 453d491e781SGuenter Roeck ret = regmap_update_bits(regmap, INA226_MASK_ENABLE, 4545a56a39bSAlex Qiu INA226_ALERT_CONFIG_MASK, 0); 4555a56a39bSAlex Qiu if (ret < 0) 4565a56a39bSAlex Qiu goto abort; 4575a56a39bSAlex Qiu 458d491e781SGuenter Roeck ret = regmap_write(regmap, INA226_ALERT_LIMIT, 4595a56a39bSAlex Qiu ina226_alert_to_reg(data, attr->index, val)); 4605a56a39bSAlex Qiu if (ret < 0) 4615a56a39bSAlex Qiu goto abort; 4625a56a39bSAlex Qiu 4635a56a39bSAlex Qiu if (val != 0) { 464d491e781SGuenter Roeck ret = regmap_update_bits(regmap, INA226_MASK_ENABLE, 4655a56a39bSAlex Qiu INA226_ALERT_CONFIG_MASK, 466232177a3SGuenter Roeck attr->index); 4675a56a39bSAlex Qiu if (ret < 0) 4685a56a39bSAlex Qiu goto abort; 4695a56a39bSAlex Qiu } 4705a56a39bSAlex Qiu 4715a56a39bSAlex Qiu ret = count; 4725a56a39bSAlex Qiu abort: 4735a56a39bSAlex Qiu mutex_unlock(&data->config_lock); 4745a56a39bSAlex Qiu return ret; 4755a56a39bSAlex Qiu } 4765a56a39bSAlex Qiu 4775a56a39bSAlex Qiu static ssize_t ina226_alarm_show(struct device *dev, 4785a56a39bSAlex Qiu struct device_attribute *da, char *buf) 4795a56a39bSAlex Qiu { 4805a56a39bSAlex Qiu struct sensor_device_attribute *attr = to_sensor_dev_attr(da); 4815a56a39bSAlex Qiu struct ina2xx_data *data = dev_get_drvdata(dev); 482bb25cdc2SGuenter Roeck unsigned int mask; 4835a56a39bSAlex Qiu int alarm = 0; 4845a56a39bSAlex Qiu int ret; 4855a56a39bSAlex Qiu 486bb25cdc2SGuenter Roeck ret = regmap_read_bypassed(data->regmap, INA226_MASK_ENABLE, &mask); 4875a56a39bSAlex Qiu if (ret) 4885a56a39bSAlex Qiu return ret; 4895a56a39bSAlex Qiu 490bb25cdc2SGuenter Roeck alarm = (mask & attr->index) && 491bb25cdc2SGuenter Roeck (mask & INA226_ALERT_FUNCTION_FLAG); 492bb25cdc2SGuenter Roeck 493af9a9730SZihao Tang return sysfs_emit(buf, "%d\n", alarm); 4945a56a39bSAlex Qiu } 4955a56a39bSAlex Qiu 4965d389b12SMaciej Purski /* 4975d389b12SMaciej Purski * In order to keep calibration register value fixed, the product 4985d389b12SMaciej Purski * of current_lsb and shunt_resistor should also be fixed and equal 4995d389b12SMaciej Purski * to shunt_voltage_lsb = 1 / shunt_div multiplied by 10^9 in order 5005d389b12SMaciej Purski * to keep the scale. 5015d389b12SMaciej Purski */ 502*ab7fbee4SGuenter Roeck static int ina2xx_set_shunt(struct ina2xx_data *data, unsigned long val) 5035d389b12SMaciej Purski { 5045d389b12SMaciej Purski unsigned int dividend = DIV_ROUND_CLOSEST(1000000000, 5055d389b12SMaciej Purski data->config->shunt_div); 506*ab7fbee4SGuenter Roeck if (!val || val > dividend) 5075d389b12SMaciej Purski return -EINVAL; 5085d389b12SMaciej Purski 5095d389b12SMaciej Purski data->rshunt = val; 5105d389b12SMaciej Purski data->current_lsb_uA = DIV_ROUND_CLOSEST(dividend, val); 5115d389b12SMaciej Purski data->power_lsb_uW = data->config->power_lsb_factor * 5125d389b12SMaciej Purski data->current_lsb_uA; 5135d389b12SMaciej Purski 5145d389b12SMaciej Purski return 0; 5155d389b12SMaciej Purski } 5165d389b12SMaciej Purski 5176a0f234fSGuenter Roeck static ssize_t ina2xx_shunt_show(struct device *dev, 5186a0f234fSGuenter Roeck struct device_attribute *da, char *buf) 5193ad86700SLothar Felten { 5203ad86700SLothar Felten struct ina2xx_data *data = dev_get_drvdata(dev); 5213ad86700SLothar Felten 522af9a9730SZihao Tang return sysfs_emit(buf, "%li\n", data->rshunt); 5233ad86700SLothar Felten } 5243ad86700SLothar Felten 5256a0f234fSGuenter Roeck static ssize_t ina2xx_shunt_store(struct device *dev, 5268a5fc795SBartosz Golaszewski struct device_attribute *da, 5278a5fc795SBartosz Golaszewski const char *buf, size_t count) 5288a5fc795SBartosz Golaszewski { 5298a5fc795SBartosz Golaszewski unsigned long val; 5308a5fc795SBartosz Golaszewski int status; 531a0de56c8SMarc Titinger struct ina2xx_data *data = dev_get_drvdata(dev); 5328a5fc795SBartosz Golaszewski 5338a5fc795SBartosz Golaszewski status = kstrtoul(buf, 10, &val); 5348a5fc795SBartosz Golaszewski if (status < 0) 5358a5fc795SBartosz Golaszewski return status; 5368a5fc795SBartosz Golaszewski 537*ab7fbee4SGuenter Roeck mutex_lock(&data->config_lock); 5385d389b12SMaciej Purski status = ina2xx_set_shunt(data, val); 539*ab7fbee4SGuenter Roeck mutex_unlock(&data->config_lock); 5408a5fc795SBartosz Golaszewski if (status < 0) 5418a5fc795SBartosz Golaszewski return status; 5428a5fc795SBartosz Golaszewski return count; 5438a5fc795SBartosz Golaszewski } 5448a5fc795SBartosz Golaszewski 5456a0f234fSGuenter Roeck static ssize_t ina226_interval_store(struct device *dev, 54672a87a47SBartosz Golaszewski struct device_attribute *da, 54772a87a47SBartosz Golaszewski const char *buf, size_t count) 54872a87a47SBartosz Golaszewski { 54972a87a47SBartosz Golaszewski struct ina2xx_data *data = dev_get_drvdata(dev); 55072a87a47SBartosz Golaszewski unsigned long val; 55172a87a47SBartosz Golaszewski int status; 55272a87a47SBartosz Golaszewski 55372a87a47SBartosz Golaszewski status = kstrtoul(buf, 10, &val); 55472a87a47SBartosz Golaszewski if (status < 0) 55572a87a47SBartosz Golaszewski return status; 55672a87a47SBartosz Golaszewski 557a0de56c8SMarc Titinger status = regmap_update_bits(data->regmap, INA2XX_CONFIG, 558a0de56c8SMarc Titinger INA226_AVG_RD_MASK, 559a0de56c8SMarc Titinger ina226_interval_to_reg(val)); 56072a87a47SBartosz Golaszewski if (status < 0) 56172a87a47SBartosz Golaszewski return status; 56272a87a47SBartosz Golaszewski 56372a87a47SBartosz Golaszewski return count; 56472a87a47SBartosz Golaszewski } 56572a87a47SBartosz Golaszewski 5666a0f234fSGuenter Roeck static ssize_t ina226_interval_show(struct device *dev, 56772a87a47SBartosz Golaszewski struct device_attribute *da, char *buf) 56872a87a47SBartosz Golaszewski { 569a0de56c8SMarc Titinger struct ina2xx_data *data = dev_get_drvdata(dev); 570a0de56c8SMarc Titinger int status; 571a0de56c8SMarc Titinger unsigned int regval; 57272a87a47SBartosz Golaszewski 573a0de56c8SMarc Titinger status = regmap_read(data->regmap, INA2XX_CONFIG, ®val); 574a0de56c8SMarc Titinger if (status) 575a0de56c8SMarc Titinger return status; 57672a87a47SBartosz Golaszewski 577af9a9730SZihao Tang return sysfs_emit(buf, "%d\n", ina226_reg_to_interval(regval)); 57872a87a47SBartosz Golaszewski } 57972a87a47SBartosz Golaszewski 580f7c2fe38SFelten, Lothar /* shunt voltage */ 5816a0f234fSGuenter Roeck static SENSOR_DEVICE_ATTR_RO(in0_input, ina2xx_value, INA2XX_SHUNT_VOLTAGE); 5825a56a39bSAlex Qiu /* shunt voltage over/under voltage alert setting and alarm */ 5835a56a39bSAlex Qiu static SENSOR_DEVICE_ATTR_RW(in0_crit, ina226_alert, 584232177a3SGuenter Roeck INA226_SHUNT_OVER_VOLTAGE_MASK); 5855a56a39bSAlex Qiu static SENSOR_DEVICE_ATTR_RW(in0_lcrit, ina226_alert, 586232177a3SGuenter Roeck INA226_SHUNT_UNDER_VOLTAGE_MASK); 5875a56a39bSAlex Qiu static SENSOR_DEVICE_ATTR_RO(in0_crit_alarm, ina226_alarm, 588232177a3SGuenter Roeck INA226_SHUNT_OVER_VOLTAGE_MASK); 5895a56a39bSAlex Qiu static SENSOR_DEVICE_ATTR_RO(in0_lcrit_alarm, ina226_alarm, 590232177a3SGuenter Roeck INA226_SHUNT_UNDER_VOLTAGE_MASK); 591f7c2fe38SFelten, Lothar 592f7c2fe38SFelten, Lothar /* bus voltage */ 5936a0f234fSGuenter Roeck static SENSOR_DEVICE_ATTR_RO(in1_input, ina2xx_value, INA2XX_BUS_VOLTAGE); 5945a56a39bSAlex Qiu /* bus voltage over/under voltage alert setting and alarm */ 5955a56a39bSAlex Qiu static SENSOR_DEVICE_ATTR_RW(in1_crit, ina226_alert, 596232177a3SGuenter Roeck INA226_BUS_OVER_VOLTAGE_MASK); 5975a56a39bSAlex Qiu static SENSOR_DEVICE_ATTR_RW(in1_lcrit, ina226_alert, 598232177a3SGuenter Roeck INA226_BUS_UNDER_VOLTAGE_MASK); 5995a56a39bSAlex Qiu static SENSOR_DEVICE_ATTR_RO(in1_crit_alarm, ina226_alarm, 600232177a3SGuenter Roeck INA226_BUS_OVER_VOLTAGE_MASK); 6015a56a39bSAlex Qiu static SENSOR_DEVICE_ATTR_RO(in1_lcrit_alarm, ina226_alarm, 602232177a3SGuenter Roeck INA226_BUS_UNDER_VOLTAGE_MASK); 603f7c2fe38SFelten, Lothar 604f7c2fe38SFelten, Lothar /* calculated current */ 6056a0f234fSGuenter Roeck static SENSOR_DEVICE_ATTR_RO(curr1_input, ina2xx_value, INA2XX_CURRENT); 606f7c2fe38SFelten, Lothar 607f7c2fe38SFelten, Lothar /* calculated power */ 6086a0f234fSGuenter Roeck static SENSOR_DEVICE_ATTR_RO(power1_input, ina2xx_value, INA2XX_POWER); 6095a56a39bSAlex Qiu /* over-limit power alert setting and alarm */ 6105a56a39bSAlex Qiu static SENSOR_DEVICE_ATTR_RW(power1_crit, ina226_alert, 611232177a3SGuenter Roeck INA226_POWER_OVER_LIMIT_MASK); 6125a56a39bSAlex Qiu static SENSOR_DEVICE_ATTR_RO(power1_crit_alarm, ina226_alarm, 613232177a3SGuenter Roeck INA226_POWER_OVER_LIMIT_MASK); 614f7c2fe38SFelten, Lothar 6158a5fc795SBartosz Golaszewski /* shunt resistance */ 6166a0f234fSGuenter Roeck static SENSOR_DEVICE_ATTR_RW(shunt_resistor, ina2xx_shunt, INA2XX_CALIBRATION); 6178a5fc795SBartosz Golaszewski 61872a87a47SBartosz Golaszewski /* update interval (ina226 only) */ 6196a0f234fSGuenter Roeck static SENSOR_DEVICE_ATTR_RW(update_interval, ina226_interval, 0); 62072a87a47SBartosz Golaszewski 621f7c2fe38SFelten, Lothar /* pointers to created device attributes */ 622468bf0e3SGuenter Roeck static struct attribute *ina2xx_attrs[] = { 623f7c2fe38SFelten, Lothar &sensor_dev_attr_in0_input.dev_attr.attr, 624f7c2fe38SFelten, Lothar &sensor_dev_attr_in1_input.dev_attr.attr, 625f7c2fe38SFelten, Lothar &sensor_dev_attr_curr1_input.dev_attr.attr, 626f7c2fe38SFelten, Lothar &sensor_dev_attr_power1_input.dev_attr.attr, 6278a5fc795SBartosz Golaszewski &sensor_dev_attr_shunt_resistor.dev_attr.attr, 628f7c2fe38SFelten, Lothar NULL, 629f7c2fe38SFelten, Lothar }; 63072a87a47SBartosz Golaszewski 63172a87a47SBartosz Golaszewski static const struct attribute_group ina2xx_group = { 63272a87a47SBartosz Golaszewski .attrs = ina2xx_attrs, 63372a87a47SBartosz Golaszewski }; 63472a87a47SBartosz Golaszewski 63572a87a47SBartosz Golaszewski static struct attribute *ina226_attrs[] = { 6365a56a39bSAlex Qiu &sensor_dev_attr_in0_crit.dev_attr.attr, 6375a56a39bSAlex Qiu &sensor_dev_attr_in0_lcrit.dev_attr.attr, 6385a56a39bSAlex Qiu &sensor_dev_attr_in0_crit_alarm.dev_attr.attr, 6395a56a39bSAlex Qiu &sensor_dev_attr_in0_lcrit_alarm.dev_attr.attr, 6405a56a39bSAlex Qiu &sensor_dev_attr_in1_crit.dev_attr.attr, 6415a56a39bSAlex Qiu &sensor_dev_attr_in1_lcrit.dev_attr.attr, 6425a56a39bSAlex Qiu &sensor_dev_attr_in1_crit_alarm.dev_attr.attr, 6435a56a39bSAlex Qiu &sensor_dev_attr_in1_lcrit_alarm.dev_attr.attr, 6445a56a39bSAlex Qiu &sensor_dev_attr_power1_crit.dev_attr.attr, 6455a56a39bSAlex Qiu &sensor_dev_attr_power1_crit_alarm.dev_attr.attr, 64672a87a47SBartosz Golaszewski &sensor_dev_attr_update_interval.dev_attr.attr, 64772a87a47SBartosz Golaszewski NULL, 64872a87a47SBartosz Golaszewski }; 64972a87a47SBartosz Golaszewski 65072a87a47SBartosz Golaszewski static const struct attribute_group ina226_group = { 65172a87a47SBartosz Golaszewski .attrs = ina226_attrs, 65272a87a47SBartosz Golaszewski }; 653f7c2fe38SFelten, Lothar 65467487038SStephen Kitt static int ina2xx_probe(struct i2c_client *client) 655f7c2fe38SFelten, Lothar { 656468bf0e3SGuenter Roeck struct device *dev = &client->dev; 657468bf0e3SGuenter Roeck struct ina2xx_data *data; 658468bf0e3SGuenter Roeck struct device *hwmon_dev; 659468bf0e3SGuenter Roeck u32 val; 66072a87a47SBartosz Golaszewski int ret, group = 0; 661bd0ddd4dSJavier Martinez Canillas enum ina2xx_ids chip; 662bd0ddd4dSJavier Martinez Canillas 6638b839699SAndrew Davis chip = (uintptr_t)i2c_get_match_data(client); 664f7c2fe38SFelten, Lothar 665468bf0e3SGuenter Roeck data = devm_kzalloc(dev, sizeof(*data), GFP_KERNEL); 666f7c2fe38SFelten, Lothar if (!data) 667f7c2fe38SFelten, Lothar return -ENOMEM; 668f7c2fe38SFelten, Lothar 669f7c2fe38SFelten, Lothar /* set the device type */ 670bd0ddd4dSJavier Martinez Canillas data->config = &ina2xx_config[chip]; 6710c4c5860SMarek Szyprowski mutex_init(&data->config_lock); 67272a87a47SBartosz Golaszewski 67361a4a841SGuenter Roeck if (device_property_read_u32(dev, "shunt-resistor", &val) < 0) 674001e2e73SMarc Titinger val = INA2XX_RSHUNT_DEFAULT; 675001e2e73SMarc Titinger 676*ab7fbee4SGuenter Roeck ret = ina2xx_set_shunt(data, val); 677*ab7fbee4SGuenter Roeck if (ret < 0) 678*ab7fbee4SGuenter Roeck return dev_err_probe(dev, ret, "Invalid shunt resistor value\n"); 679001e2e73SMarc Titinger 680a0de56c8SMarc Titinger data->regmap = devm_regmap_init_i2c(client, &ina2xx_regmap_config); 681a0de56c8SMarc Titinger if (IS_ERR(data->regmap)) { 682a0de56c8SMarc Titinger dev_err(dev, "failed to allocate register map\n"); 683a0de56c8SMarc Titinger return PTR_ERR(data->regmap); 684a0de56c8SMarc Titinger } 685a0de56c8SMarc Titinger 686ad20248aSSvyatoslav Ryhel ret = devm_regulator_get_enable(dev, "vs"); 687ad20248aSSvyatoslav Ryhel if (ret) 688ad20248aSSvyatoslav Ryhel return dev_err_probe(dev, ret, "failed to enable vs regulator\n"); 689ad20248aSSvyatoslav Ryhel 690ec5d234fSAmna Waseem if (chip == ina226) { 69161a4a841SGuenter Roeck if (device_property_read_bool(dev, "ti,alert-polarity-active-high")) { 692ec5d234fSAmna Waseem ret = ina2xx_set_alert_polarity(data, 693ec5d234fSAmna Waseem INA226_ALERT_POL_HIGH); 694ec5d234fSAmna Waseem if (ret < 0) { 695ec5d234fSAmna Waseem return dev_err_probe(dev, ret, 696ec5d234fSAmna Waseem "failed to set alert polarity active high\n"); 697ec5d234fSAmna Waseem } 698ec5d234fSAmna Waseem } else { 699ec5d234fSAmna Waseem /* Set default value i.e active low */ 700ec5d234fSAmna Waseem ret = ina2xx_set_alert_polarity(data, 701ec5d234fSAmna Waseem INA226_ALERT_POL_LOW); 702ec5d234fSAmna Waseem if (ret < 0) { 703ec5d234fSAmna Waseem return dev_err_probe(dev, ret, 704ec5d234fSAmna Waseem "failed to set alert polarity active low\n"); 705ec5d234fSAmna Waseem } 706ec5d234fSAmna Waseem } 707ec5d234fSAmna Waseem } 708ec5d234fSAmna Waseem 709509416a8SBartosz Golaszewski ret = ina2xx_init(data); 710509416a8SBartosz Golaszewski if (ret < 0) { 711509416a8SBartosz Golaszewski dev_err(dev, "error configuring the device: %d\n", ret); 712509416a8SBartosz Golaszewski return -ENODEV; 713509416a8SBartosz Golaszewski } 714509416a8SBartosz Golaszewski 71572a87a47SBartosz Golaszewski data->groups[group++] = &ina2xx_group; 71670df9ebbSNicolin Chen if (chip == ina226) 71772a87a47SBartosz Golaszewski data->groups[group++] = &ina226_group; 71872a87a47SBartosz Golaszewski 719468bf0e3SGuenter Roeck hwmon_dev = devm_hwmon_device_register_with_groups(dev, client->name, 72072a87a47SBartosz Golaszewski data, data->groups); 721468bf0e3SGuenter Roeck if (IS_ERR(hwmon_dev)) 722468bf0e3SGuenter Roeck return PTR_ERR(hwmon_dev); 723f7c2fe38SFelten, Lothar 724468bf0e3SGuenter Roeck dev_info(dev, "power monitor %s (Rshunt = %li uOhm)\n", 72570df9ebbSNicolin Chen client->name, data->rshunt); 7266106db25SGuenter Roeck 727f7c2fe38SFelten, Lothar return 0; 728f7c2fe38SFelten, Lothar } 729f7c2fe38SFelten, Lothar 730f7c2fe38SFelten, Lothar static const struct i2c_device_id ina2xx_id[] = { 731f7c2fe38SFelten, Lothar { "ina219", ina219 }, 732dc92cd0cSGuenter Roeck { "ina220", ina219 }, 733f7c2fe38SFelten, Lothar { "ina226", ina226 }, 734dc92cd0cSGuenter Roeck { "ina230", ina226 }, 735add513beSKevin Hilman { "ina231", ina226 }, 736f7c2fe38SFelten, Lothar { } 737f7c2fe38SFelten, Lothar }; 738f7c2fe38SFelten, Lothar MODULE_DEVICE_TABLE(i2c, ina2xx_id); 739f7c2fe38SFelten, Lothar 740df6b8c70SGuenter Roeck static const struct of_device_id __maybe_unused ina2xx_of_match[] = { 741bd0ddd4dSJavier Martinez Canillas { 742bd0ddd4dSJavier Martinez Canillas .compatible = "ti,ina219", 743bd0ddd4dSJavier Martinez Canillas .data = (void *)ina219 744bd0ddd4dSJavier Martinez Canillas }, 745bd0ddd4dSJavier Martinez Canillas { 746bd0ddd4dSJavier Martinez Canillas .compatible = "ti,ina220", 747bd0ddd4dSJavier Martinez Canillas .data = (void *)ina219 748bd0ddd4dSJavier Martinez Canillas }, 749bd0ddd4dSJavier Martinez Canillas { 750bd0ddd4dSJavier Martinez Canillas .compatible = "ti,ina226", 751bd0ddd4dSJavier Martinez Canillas .data = (void *)ina226 752bd0ddd4dSJavier Martinez Canillas }, 753bd0ddd4dSJavier Martinez Canillas { 754bd0ddd4dSJavier Martinez Canillas .compatible = "ti,ina230", 755bd0ddd4dSJavier Martinez Canillas .data = (void *)ina226 756bd0ddd4dSJavier Martinez Canillas }, 757bd0ddd4dSJavier Martinez Canillas { 758bd0ddd4dSJavier Martinez Canillas .compatible = "ti,ina231", 759bd0ddd4dSJavier Martinez Canillas .data = (void *)ina226 760bd0ddd4dSJavier Martinez Canillas }, 761bd0ddd4dSJavier Martinez Canillas { }, 762bd0ddd4dSJavier Martinez Canillas }; 763bd0ddd4dSJavier Martinez Canillas MODULE_DEVICE_TABLE(of, ina2xx_of_match); 764bd0ddd4dSJavier Martinez Canillas 765f7c2fe38SFelten, Lothar static struct i2c_driver ina2xx_driver = { 766f7c2fe38SFelten, Lothar .driver = { 767f7c2fe38SFelten, Lothar .name = "ina2xx", 768bd0ddd4dSJavier Martinez Canillas .of_match_table = of_match_ptr(ina2xx_of_match), 769f7c2fe38SFelten, Lothar }, 7701975d167SUwe Kleine-König .probe = ina2xx_probe, 771f7c2fe38SFelten, Lothar .id_table = ina2xx_id, 772f7c2fe38SFelten, Lothar }; 773f7c2fe38SFelten, Lothar 774d835ca0fSWei Yongjun module_i2c_driver(ina2xx_driver); 775f7c2fe38SFelten, Lothar 776f7c2fe38SFelten, Lothar MODULE_AUTHOR("Lothar Felten <l-felten@ti.com>"); 777f7c2fe38SFelten, Lothar MODULE_DESCRIPTION("ina2xx driver"); 778f7c2fe38SFelten, Lothar MODULE_LICENSE("GPL"); 779