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 25f7c2fe38SFelten, Lothar #include <linux/kernel.h> 26f7c2fe38SFelten, Lothar #include <linux/module.h> 27f7c2fe38SFelten, Lothar #include <linux/init.h> 28f7c2fe38SFelten, Lothar #include <linux/err.h> 29f7c2fe38SFelten, Lothar #include <linux/slab.h> 30f7c2fe38SFelten, Lothar #include <linux/i2c.h> 31f7c2fe38SFelten, Lothar #include <linux/hwmon.h> 32f7c2fe38SFelten, Lothar #include <linux/hwmon-sysfs.h> 33dcd8f392SJean Delvare #include <linux/jiffies.h> 34bd0ddd4dSJavier Martinez Canillas #include <linux/of_device.h> 3531e7ad74STang Yuantian #include <linux/of.h> 36509416a8SBartosz Golaszewski #include <linux/delay.h> 37d38df34eSBartosz Golaszewski #include <linux/util_macros.h> 38a0de56c8SMarc Titinger #include <linux/regmap.h> 39f7c2fe38SFelten, Lothar 40f7c2fe38SFelten, Lothar #include <linux/platform_data/ina2xx.h> 41f7c2fe38SFelten, Lothar 42f7c2fe38SFelten, Lothar /* common register definitions */ 43f7c2fe38SFelten, Lothar #define INA2XX_CONFIG 0x00 44f7c2fe38SFelten, Lothar #define INA2XX_SHUNT_VOLTAGE 0x01 /* readonly */ 45f7c2fe38SFelten, Lothar #define INA2XX_BUS_VOLTAGE 0x02 /* readonly */ 46f7c2fe38SFelten, Lothar #define INA2XX_POWER 0x03 /* readonly */ 47f7c2fe38SFelten, Lothar #define INA2XX_CURRENT 0x04 /* readonly */ 48f7c2fe38SFelten, Lothar #define INA2XX_CALIBRATION 0x05 49f7c2fe38SFelten, Lothar 50f7c2fe38SFelten, Lothar /* INA226 register definitions */ 51f7c2fe38SFelten, Lothar #define INA226_MASK_ENABLE 0x06 52f7c2fe38SFelten, Lothar #define INA226_ALERT_LIMIT 0x07 53f7c2fe38SFelten, Lothar #define INA226_DIE_ID 0xFF 54f7c2fe38SFelten, Lothar 55f7c2fe38SFelten, Lothar /* register count */ 56f7c2fe38SFelten, Lothar #define INA219_REGISTERS 6 57f7c2fe38SFelten, Lothar #define INA226_REGISTERS 8 58f7c2fe38SFelten, Lothar 59f7c2fe38SFelten, Lothar #define INA2XX_MAX_REGISTERS 8 60f7c2fe38SFelten, Lothar 61f7c2fe38SFelten, Lothar /* settings - depend on use case */ 62f7c2fe38SFelten, Lothar #define INA219_CONFIG_DEFAULT 0x399F /* PGA=8 */ 63f7c2fe38SFelten, Lothar #define INA226_CONFIG_DEFAULT 0x4527 /* averages=16 */ 64f7c2fe38SFelten, Lothar 65f7c2fe38SFelten, Lothar /* worst case is 68.10 ms (~14.6Hz, ina219) */ 66f7c2fe38SFelten, Lothar #define INA2XX_CONVERSION_RATE 15 67509416a8SBartosz Golaszewski #define INA2XX_MAX_DELAY 69 /* worst case delay in ms */ 68509416a8SBartosz Golaszewski 69509416a8SBartosz Golaszewski #define INA2XX_RSHUNT_DEFAULT 10000 70f7c2fe38SFelten, Lothar 7172a87a47SBartosz Golaszewski /* bit mask for reading the averaging setting in the configuration register */ 7272a87a47SBartosz Golaszewski #define INA226_AVG_RD_MASK 0x0E00 7372a87a47SBartosz Golaszewski 7472a87a47SBartosz Golaszewski #define INA226_READ_AVG(reg) (((reg) & INA226_AVG_RD_MASK) >> 9) 7572a87a47SBartosz Golaszewski #define INA226_SHIFT_AVG(val) ((val) << 9) 7672a87a47SBartosz Golaszewski 775a56a39bSAlex Qiu /* bit number of alert functions in Mask/Enable Register */ 785a56a39bSAlex Qiu #define INA226_SHUNT_OVER_VOLTAGE_BIT 15 795a56a39bSAlex Qiu #define INA226_SHUNT_UNDER_VOLTAGE_BIT 14 805a56a39bSAlex Qiu #define INA226_BUS_OVER_VOLTAGE_BIT 13 815a56a39bSAlex Qiu #define INA226_BUS_UNDER_VOLTAGE_BIT 12 825a56a39bSAlex Qiu #define INA226_POWER_OVER_LIMIT_BIT 11 835a56a39bSAlex Qiu 845a56a39bSAlex Qiu /* bit mask for alert config bits of Mask/Enable Register */ 855a56a39bSAlex Qiu #define INA226_ALERT_CONFIG_MASK 0xFC00 865a56a39bSAlex Qiu #define INA226_ALERT_FUNCTION_FLAG BIT(4) 875a56a39bSAlex Qiu 8872a87a47SBartosz Golaszewski /* common attrs, ina226 attrs and NULL */ 8972a87a47SBartosz Golaszewski #define INA2XX_MAX_ATTRIBUTE_GROUPS 3 9072a87a47SBartosz Golaszewski 9172a87a47SBartosz Golaszewski /* 9272a87a47SBartosz Golaszewski * Both bus voltage and shunt voltage conversion times for ina226 are set 9372a87a47SBartosz Golaszewski * to 0b0100 on POR, which translates to 2200 microseconds in total. 9472a87a47SBartosz Golaszewski */ 9572a87a47SBartosz Golaszewski #define INA226_TOTAL_CONV_TIME_DEFAULT 2200 9672a87a47SBartosz Golaszewski 97a0de56c8SMarc Titinger static struct regmap_config ina2xx_regmap_config = { 98a0de56c8SMarc Titinger .reg_bits = 8, 99a0de56c8SMarc Titinger .val_bits = 16, 100a0de56c8SMarc Titinger }; 101a0de56c8SMarc Titinger 102f7c2fe38SFelten, Lothar enum ina2xx_ids { ina219, ina226 }; 103f7c2fe38SFelten, Lothar 1046106db25SGuenter Roeck struct ina2xx_config { 1056106db25SGuenter Roeck u16 config_default; 1065d389b12SMaciej Purski int calibration_value; 1076106db25SGuenter Roeck int registers; 1086106db25SGuenter Roeck int shunt_div; 1096106db25SGuenter Roeck int bus_voltage_shift; 1106106db25SGuenter Roeck int bus_voltage_lsb; /* uV */ 1115d389b12SMaciej Purski int power_lsb_factor; 1126106db25SGuenter Roeck }; 1136106db25SGuenter Roeck 114f7c2fe38SFelten, Lothar struct ina2xx_data { 1156106db25SGuenter Roeck const struct ina2xx_config *config; 116f7c2fe38SFelten, Lothar 117509416a8SBartosz Golaszewski long rshunt; 1185d389b12SMaciej Purski long current_lsb_uA; 1195d389b12SMaciej Purski long power_lsb_uW; 120a0de56c8SMarc Titinger struct mutex config_lock; 121a0de56c8SMarc Titinger struct regmap *regmap; 122f7c2fe38SFelten, Lothar 12372a87a47SBartosz Golaszewski const struct attribute_group *groups[INA2XX_MAX_ATTRIBUTE_GROUPS]; 124f7c2fe38SFelten, Lothar }; 125f7c2fe38SFelten, Lothar 1266106db25SGuenter Roeck static const struct ina2xx_config ina2xx_config[] = { 1276106db25SGuenter Roeck [ina219] = { 1286106db25SGuenter Roeck .config_default = INA219_CONFIG_DEFAULT, 1295d389b12SMaciej Purski .calibration_value = 4096, 1306106db25SGuenter Roeck .registers = INA219_REGISTERS, 1316106db25SGuenter Roeck .shunt_div = 100, 1326106db25SGuenter Roeck .bus_voltage_shift = 3, 1336106db25SGuenter Roeck .bus_voltage_lsb = 4000, 1345d389b12SMaciej Purski .power_lsb_factor = 20, 1356106db25SGuenter Roeck }, 1366106db25SGuenter Roeck [ina226] = { 1376106db25SGuenter Roeck .config_default = INA226_CONFIG_DEFAULT, 1385d389b12SMaciej Purski .calibration_value = 2048, 1396106db25SGuenter Roeck .registers = INA226_REGISTERS, 1406106db25SGuenter Roeck .shunt_div = 400, 1416106db25SGuenter Roeck .bus_voltage_shift = 0, 1426106db25SGuenter Roeck .bus_voltage_lsb = 1250, 1435d389b12SMaciej Purski .power_lsb_factor = 25, 1446106db25SGuenter Roeck }, 1456106db25SGuenter Roeck }; 1466106db25SGuenter Roeck 14772a87a47SBartosz Golaszewski /* 14872a87a47SBartosz Golaszewski * Available averaging rates for ina226. The indices correspond with 14972a87a47SBartosz Golaszewski * the bit values expected by the chip (according to the ina226 datasheet, 15072a87a47SBartosz Golaszewski * table 3 AVG bit settings, found at 15149dc2fb0SAlexander A. Klimov * https://www.ti.com/lit/ds/symlink/ina226.pdf. 15272a87a47SBartosz Golaszewski */ 15372a87a47SBartosz Golaszewski static const int ina226_avg_tab[] = { 1, 4, 16, 64, 128, 256, 512, 1024 }; 15472a87a47SBartosz Golaszewski 15572a87a47SBartosz Golaszewski static int ina226_reg_to_interval(u16 config) 15672a87a47SBartosz Golaszewski { 15772a87a47SBartosz Golaszewski int avg = ina226_avg_tab[INA226_READ_AVG(config)]; 15872a87a47SBartosz Golaszewski 15972a87a47SBartosz Golaszewski /* 16072a87a47SBartosz Golaszewski * Multiply the total conversion time by the number of averages. 16172a87a47SBartosz Golaszewski * Return the result in milliseconds. 16272a87a47SBartosz Golaszewski */ 16372a87a47SBartosz Golaszewski return DIV_ROUND_CLOSEST(avg * INA226_TOTAL_CONV_TIME_DEFAULT, 1000); 16472a87a47SBartosz Golaszewski } 16572a87a47SBartosz Golaszewski 166a0de56c8SMarc Titinger /* 167a0de56c8SMarc Titinger * Return the new, shifted AVG field value of CONFIG register, 168a0de56c8SMarc Titinger * to use with regmap_update_bits 169a0de56c8SMarc Titinger */ 170a0de56c8SMarc Titinger static u16 ina226_interval_to_reg(int interval) 17172a87a47SBartosz Golaszewski { 17272a87a47SBartosz Golaszewski int avg, avg_bits; 17372a87a47SBartosz Golaszewski 17472a87a47SBartosz Golaszewski avg = DIV_ROUND_CLOSEST(interval * 1000, 17572a87a47SBartosz Golaszewski INA226_TOTAL_CONV_TIME_DEFAULT); 176d38df34eSBartosz Golaszewski avg_bits = find_closest(avg, ina226_avg_tab, 177d38df34eSBartosz Golaszewski ARRAY_SIZE(ina226_avg_tab)); 17872a87a47SBartosz Golaszewski 179a0de56c8SMarc Titinger return INA226_SHIFT_AVG(avg_bits); 18072a87a47SBartosz Golaszewski } 18172a87a47SBartosz Golaszewski 1825d389b12SMaciej Purski /* 1835d389b12SMaciej Purski * Calibration register is set to the best value, which eliminates 1845d389b12SMaciej Purski * truncation errors on calculating current register in hardware. 1855d389b12SMaciej Purski * According to datasheet (eq. 3) the best values are 2048 for 1865d389b12SMaciej Purski * ina226 and 4096 for ina219. They are hardcoded as calibration_value. 1875d389b12SMaciej Purski */ 1888a5fc795SBartosz Golaszewski static int ina2xx_calibrate(struct ina2xx_data *data) 1898a5fc795SBartosz Golaszewski { 1905d389b12SMaciej Purski return regmap_write(data->regmap, INA2XX_CALIBRATION, 1915d389b12SMaciej Purski data->config->calibration_value); 1928a5fc795SBartosz Golaszewski } 1938a5fc795SBartosz Golaszewski 194509416a8SBartosz Golaszewski /* 195509416a8SBartosz Golaszewski * Initialize the configuration and calibration registers. 196509416a8SBartosz Golaszewski */ 197509416a8SBartosz Golaszewski static int ina2xx_init(struct ina2xx_data *data) 198509416a8SBartosz Golaszewski { 199a0de56c8SMarc Titinger int ret = regmap_write(data->regmap, INA2XX_CONFIG, 200a0de56c8SMarc Titinger data->config->config_default); 201509416a8SBartosz Golaszewski if (ret < 0) 202509416a8SBartosz Golaszewski return ret; 203509416a8SBartosz Golaszewski 2048a5fc795SBartosz Golaszewski return ina2xx_calibrate(data); 205509416a8SBartosz Golaszewski } 206509416a8SBartosz Golaszewski 207a0de56c8SMarc Titinger static int ina2xx_read_reg(struct device *dev, int reg, unsigned int *regval) 208f7c2fe38SFelten, Lothar { 209468bf0e3SGuenter Roeck struct ina2xx_data *data = dev_get_drvdata(dev); 210a0de56c8SMarc Titinger int ret, retry; 211509416a8SBartosz Golaszewski 212a0de56c8SMarc Titinger dev_dbg(dev, "Starting register %d read\n", reg); 213509416a8SBartosz Golaszewski 214509416a8SBartosz Golaszewski for (retry = 5; retry; retry--) { 215a0de56c8SMarc Titinger 216a0de56c8SMarc Titinger ret = regmap_read(data->regmap, reg, regval); 217a0de56c8SMarc Titinger if (ret < 0) 218a0de56c8SMarc Titinger return ret; 219a0de56c8SMarc Titinger 220a0de56c8SMarc Titinger dev_dbg(dev, "read %d, val = 0x%04x\n", reg, *regval); 221509416a8SBartosz Golaszewski 222509416a8SBartosz Golaszewski /* 223509416a8SBartosz Golaszewski * If the current value in the calibration register is 0, the 224509416a8SBartosz Golaszewski * power and current registers will also remain at 0. In case 225509416a8SBartosz Golaszewski * the chip has been reset let's check the calibration 226509416a8SBartosz Golaszewski * register and reinitialize if needed. 227a0de56c8SMarc Titinger * We do that extra read of the calibration register if there 228a0de56c8SMarc Titinger * is some hint of a chip reset. 229509416a8SBartosz Golaszewski */ 230a0de56c8SMarc Titinger if (*regval == 0) { 231a0de56c8SMarc Titinger unsigned int cal; 232a0de56c8SMarc Titinger 233a0de56c8SMarc Titinger ret = regmap_read(data->regmap, INA2XX_CALIBRATION, 234a0de56c8SMarc Titinger &cal); 235a0de56c8SMarc Titinger if (ret < 0) 236a0de56c8SMarc Titinger return ret; 237a0de56c8SMarc Titinger 238a0de56c8SMarc Titinger if (cal == 0) { 239509416a8SBartosz Golaszewski dev_warn(dev, "chip not calibrated, reinitializing\n"); 240509416a8SBartosz Golaszewski 241a0de56c8SMarc Titinger ret = ina2xx_init(data); 242a0de56c8SMarc Titinger if (ret < 0) 243a0de56c8SMarc Titinger return ret; 244509416a8SBartosz Golaszewski /* 245a0de56c8SMarc Titinger * Let's make sure the power and current 246a0de56c8SMarc Titinger * registers have been updated before trying 247a0de56c8SMarc Titinger * again. 248509416a8SBartosz Golaszewski */ 249509416a8SBartosz Golaszewski msleep(INA2XX_MAX_DELAY); 250509416a8SBartosz Golaszewski continue; 251509416a8SBartosz Golaszewski } 252a0de56c8SMarc Titinger } 253509416a8SBartosz Golaszewski return 0; 254509416a8SBartosz Golaszewski } 255509416a8SBartosz Golaszewski 256509416a8SBartosz Golaszewski /* 257509416a8SBartosz Golaszewski * If we're here then although all write operations succeeded, the 258509416a8SBartosz Golaszewski * chip still returns 0 in the calibration register. Nothing more we 259509416a8SBartosz Golaszewski * can do here. 260509416a8SBartosz Golaszewski */ 261509416a8SBartosz Golaszewski dev_err(dev, "unable to reinitialize the chip\n"); 262509416a8SBartosz Golaszewski return -ENODEV; 263509416a8SBartosz Golaszewski } 264509416a8SBartosz Golaszewski 265a0de56c8SMarc Titinger static int ina2xx_get_value(struct ina2xx_data *data, u8 reg, 266a0de56c8SMarc Titinger unsigned int regval) 267f7c2fe38SFelten, Lothar { 2686106db25SGuenter Roeck int val; 269f7c2fe38SFelten, Lothar 270f7c2fe38SFelten, Lothar switch (reg) { 271f7c2fe38SFelten, Lothar case INA2XX_SHUNT_VOLTAGE: 272c0214f98SFabio Baltieri /* signed register */ 273a0de56c8SMarc Titinger val = DIV_ROUND_CLOSEST((s16)regval, data->config->shunt_div); 274f7c2fe38SFelten, Lothar break; 275f7c2fe38SFelten, Lothar case INA2XX_BUS_VOLTAGE: 276a0de56c8SMarc Titinger val = (regval >> data->config->bus_voltage_shift) 2776106db25SGuenter Roeck * data->config->bus_voltage_lsb; 2786106db25SGuenter Roeck val = DIV_ROUND_CLOSEST(val, 1000); 279f7c2fe38SFelten, Lothar break; 280f7c2fe38SFelten, Lothar case INA2XX_POWER: 2815d389b12SMaciej Purski val = regval * data->power_lsb_uW; 282f7c2fe38SFelten, Lothar break; 283f7c2fe38SFelten, Lothar case INA2XX_CURRENT: 2845d389b12SMaciej Purski /* signed register, result in mA */ 28538cd989eSNicolin Chen val = (s16)regval * data->current_lsb_uA; 2865d389b12SMaciej Purski val = DIV_ROUND_CLOSEST(val, 1000); 287f7c2fe38SFelten, Lothar break; 2888a5fc795SBartosz Golaszewski case INA2XX_CALIBRATION: 2895d389b12SMaciej Purski val = regval; 2908a5fc795SBartosz Golaszewski break; 291f7c2fe38SFelten, Lothar default: 292f7c2fe38SFelten, Lothar /* programmer goofed */ 293f7c2fe38SFelten, Lothar WARN_ON_ONCE(1); 294f7c2fe38SFelten, Lothar val = 0; 295f7c2fe38SFelten, Lothar break; 296f7c2fe38SFelten, Lothar } 297f7c2fe38SFelten, Lothar 298f7c2fe38SFelten, Lothar return val; 299f7c2fe38SFelten, Lothar } 300f7c2fe38SFelten, Lothar 3016a0f234fSGuenter Roeck static ssize_t ina2xx_value_show(struct device *dev, 302f7c2fe38SFelten, Lothar struct device_attribute *da, char *buf) 303f7c2fe38SFelten, Lothar { 304f7c2fe38SFelten, Lothar struct sensor_device_attribute *attr = to_sensor_dev_attr(da); 305a0de56c8SMarc Titinger struct ina2xx_data *data = dev_get_drvdata(dev); 306a0de56c8SMarc Titinger unsigned int regval; 307f7c2fe38SFelten, Lothar 308a0de56c8SMarc Titinger int err = ina2xx_read_reg(dev, attr->index, ®val); 309a0de56c8SMarc Titinger 310a0de56c8SMarc Titinger if (err < 0) 311a0de56c8SMarc Titinger return err; 312f7c2fe38SFelten, Lothar 3136106db25SGuenter Roeck return snprintf(buf, PAGE_SIZE, "%d\n", 314a0de56c8SMarc Titinger ina2xx_get_value(data, attr->index, regval)); 315f7c2fe38SFelten, Lothar } 316f7c2fe38SFelten, Lothar 3175a56a39bSAlex Qiu static int ina226_reg_to_alert(struct ina2xx_data *data, u8 bit, u16 regval) 3185a56a39bSAlex Qiu { 3195a56a39bSAlex Qiu int reg; 3205a56a39bSAlex Qiu 3215a56a39bSAlex Qiu switch (bit) { 3225a56a39bSAlex Qiu case INA226_SHUNT_OVER_VOLTAGE_BIT: 3235a56a39bSAlex Qiu case INA226_SHUNT_UNDER_VOLTAGE_BIT: 3245a56a39bSAlex Qiu reg = INA2XX_SHUNT_VOLTAGE; 3255a56a39bSAlex Qiu break; 3265a56a39bSAlex Qiu case INA226_BUS_OVER_VOLTAGE_BIT: 3275a56a39bSAlex Qiu case INA226_BUS_UNDER_VOLTAGE_BIT: 3285a56a39bSAlex Qiu reg = INA2XX_BUS_VOLTAGE; 3295a56a39bSAlex Qiu break; 3305a56a39bSAlex Qiu case INA226_POWER_OVER_LIMIT_BIT: 3315a56a39bSAlex Qiu reg = INA2XX_POWER; 3325a56a39bSAlex Qiu break; 3335a56a39bSAlex Qiu default: 3345a56a39bSAlex Qiu /* programmer goofed */ 3355a56a39bSAlex Qiu WARN_ON_ONCE(1); 3365a56a39bSAlex Qiu return 0; 3375a56a39bSAlex Qiu } 3385a56a39bSAlex Qiu 3395a56a39bSAlex Qiu return ina2xx_get_value(data, reg, regval); 3405a56a39bSAlex Qiu } 3415a56a39bSAlex Qiu 3425a56a39bSAlex Qiu /* 3435a56a39bSAlex Qiu * Turns alert limit values into register values. 3445a56a39bSAlex Qiu * Opposite of the formula in ina2xx_get_value(). 3455a56a39bSAlex Qiu */ 3465a56a39bSAlex Qiu static s16 ina226_alert_to_reg(struct ina2xx_data *data, u8 bit, int val) 3475a56a39bSAlex Qiu { 3485a56a39bSAlex Qiu switch (bit) { 3495a56a39bSAlex Qiu case INA226_SHUNT_OVER_VOLTAGE_BIT: 3505a56a39bSAlex Qiu case INA226_SHUNT_UNDER_VOLTAGE_BIT: 3515a56a39bSAlex Qiu val *= data->config->shunt_div; 3525a56a39bSAlex Qiu return clamp_val(val, SHRT_MIN, SHRT_MAX); 3535a56a39bSAlex Qiu case INA226_BUS_OVER_VOLTAGE_BIT: 3545a56a39bSAlex Qiu case INA226_BUS_UNDER_VOLTAGE_BIT: 3555a56a39bSAlex Qiu val = (val * 1000) << data->config->bus_voltage_shift; 3565a56a39bSAlex Qiu val = DIV_ROUND_CLOSEST(val, data->config->bus_voltage_lsb); 3575a56a39bSAlex Qiu return clamp_val(val, 0, SHRT_MAX); 3585a56a39bSAlex Qiu case INA226_POWER_OVER_LIMIT_BIT: 3595a56a39bSAlex Qiu val = DIV_ROUND_CLOSEST(val, data->power_lsb_uW); 3605a56a39bSAlex Qiu return clamp_val(val, 0, USHRT_MAX); 3615a56a39bSAlex Qiu default: 3625a56a39bSAlex Qiu /* programmer goofed */ 3635a56a39bSAlex Qiu WARN_ON_ONCE(1); 3645a56a39bSAlex Qiu return 0; 3655a56a39bSAlex Qiu } 3665a56a39bSAlex Qiu } 3675a56a39bSAlex Qiu 3685a56a39bSAlex Qiu static ssize_t ina226_alert_show(struct device *dev, 3695a56a39bSAlex Qiu struct device_attribute *da, char *buf) 3705a56a39bSAlex Qiu { 3715a56a39bSAlex Qiu struct sensor_device_attribute *attr = to_sensor_dev_attr(da); 3725a56a39bSAlex Qiu struct ina2xx_data *data = dev_get_drvdata(dev); 3735a56a39bSAlex Qiu int regval; 3745a56a39bSAlex Qiu int val = 0; 3755a56a39bSAlex Qiu int ret; 3765a56a39bSAlex Qiu 3775a56a39bSAlex Qiu mutex_lock(&data->config_lock); 3785a56a39bSAlex Qiu ret = regmap_read(data->regmap, INA226_MASK_ENABLE, ®val); 3795a56a39bSAlex Qiu if (ret) 3805a56a39bSAlex Qiu goto abort; 3815a56a39bSAlex Qiu 3825a56a39bSAlex Qiu if (regval & BIT(attr->index)) { 3835a56a39bSAlex Qiu ret = regmap_read(data->regmap, INA226_ALERT_LIMIT, ®val); 3845a56a39bSAlex Qiu if (ret) 3855a56a39bSAlex Qiu goto abort; 3865a56a39bSAlex Qiu val = ina226_reg_to_alert(data, attr->index, regval); 3875a56a39bSAlex Qiu } 3885a56a39bSAlex Qiu 3895a56a39bSAlex Qiu ret = snprintf(buf, PAGE_SIZE, "%d\n", val); 3905a56a39bSAlex Qiu abort: 3915a56a39bSAlex Qiu mutex_unlock(&data->config_lock); 3925a56a39bSAlex Qiu return ret; 3935a56a39bSAlex Qiu } 3945a56a39bSAlex Qiu 3955a56a39bSAlex Qiu static ssize_t ina226_alert_store(struct device *dev, 3965a56a39bSAlex Qiu struct device_attribute *da, 3975a56a39bSAlex Qiu const char *buf, size_t count) 3985a56a39bSAlex Qiu { 3995a56a39bSAlex Qiu struct sensor_device_attribute *attr = to_sensor_dev_attr(da); 4005a56a39bSAlex Qiu struct ina2xx_data *data = dev_get_drvdata(dev); 4015a56a39bSAlex Qiu unsigned long val; 4025a56a39bSAlex Qiu int ret; 4035a56a39bSAlex Qiu 4045a56a39bSAlex Qiu ret = kstrtoul(buf, 10, &val); 4055a56a39bSAlex Qiu if (ret < 0) 4065a56a39bSAlex Qiu return ret; 4075a56a39bSAlex Qiu 4085a56a39bSAlex Qiu /* 4095a56a39bSAlex Qiu * Clear all alerts first to avoid accidentally triggering ALERT pin 4105a56a39bSAlex Qiu * due to register write sequence. Then, only enable the alert 4115a56a39bSAlex Qiu * if the value is non-zero. 4125a56a39bSAlex Qiu */ 4135a56a39bSAlex Qiu mutex_lock(&data->config_lock); 4145a56a39bSAlex Qiu ret = regmap_update_bits(data->regmap, INA226_MASK_ENABLE, 4155a56a39bSAlex Qiu INA226_ALERT_CONFIG_MASK, 0); 4165a56a39bSAlex Qiu if (ret < 0) 4175a56a39bSAlex Qiu goto abort; 4185a56a39bSAlex Qiu 4195a56a39bSAlex Qiu ret = regmap_write(data->regmap, INA226_ALERT_LIMIT, 4205a56a39bSAlex Qiu ina226_alert_to_reg(data, attr->index, val)); 4215a56a39bSAlex Qiu if (ret < 0) 4225a56a39bSAlex Qiu goto abort; 4235a56a39bSAlex Qiu 4245a56a39bSAlex Qiu if (val != 0) { 4255a56a39bSAlex Qiu ret = regmap_update_bits(data->regmap, INA226_MASK_ENABLE, 4265a56a39bSAlex Qiu INA226_ALERT_CONFIG_MASK, 4275a56a39bSAlex Qiu BIT(attr->index)); 4285a56a39bSAlex Qiu if (ret < 0) 4295a56a39bSAlex Qiu goto abort; 4305a56a39bSAlex Qiu } 4315a56a39bSAlex Qiu 4325a56a39bSAlex Qiu ret = count; 4335a56a39bSAlex Qiu abort: 4345a56a39bSAlex Qiu mutex_unlock(&data->config_lock); 4355a56a39bSAlex Qiu return ret; 4365a56a39bSAlex Qiu } 4375a56a39bSAlex Qiu 4385a56a39bSAlex Qiu static ssize_t ina226_alarm_show(struct device *dev, 4395a56a39bSAlex Qiu struct device_attribute *da, char *buf) 4405a56a39bSAlex Qiu { 4415a56a39bSAlex Qiu struct sensor_device_attribute *attr = to_sensor_dev_attr(da); 4425a56a39bSAlex Qiu struct ina2xx_data *data = dev_get_drvdata(dev); 4435a56a39bSAlex Qiu int regval; 4445a56a39bSAlex Qiu int alarm = 0; 4455a56a39bSAlex Qiu int ret; 4465a56a39bSAlex Qiu 4475a56a39bSAlex Qiu ret = regmap_read(data->regmap, INA226_MASK_ENABLE, ®val); 4485a56a39bSAlex Qiu if (ret) 4495a56a39bSAlex Qiu return ret; 4505a56a39bSAlex Qiu 4515a56a39bSAlex Qiu alarm = (regval & BIT(attr->index)) && 4525a56a39bSAlex Qiu (regval & INA226_ALERT_FUNCTION_FLAG); 4535a56a39bSAlex Qiu return snprintf(buf, PAGE_SIZE, "%d\n", alarm); 4545a56a39bSAlex Qiu } 4555a56a39bSAlex Qiu 4565d389b12SMaciej Purski /* 4575d389b12SMaciej Purski * In order to keep calibration register value fixed, the product 4585d389b12SMaciej Purski * of current_lsb and shunt_resistor should also be fixed and equal 4595d389b12SMaciej Purski * to shunt_voltage_lsb = 1 / shunt_div multiplied by 10^9 in order 4605d389b12SMaciej Purski * to keep the scale. 4615d389b12SMaciej Purski */ 4625d389b12SMaciej Purski static int ina2xx_set_shunt(struct ina2xx_data *data, long val) 4635d389b12SMaciej Purski { 4645d389b12SMaciej Purski unsigned int dividend = DIV_ROUND_CLOSEST(1000000000, 4655d389b12SMaciej Purski data->config->shunt_div); 4665d389b12SMaciej Purski if (val <= 0 || val > dividend) 4675d389b12SMaciej Purski return -EINVAL; 4685d389b12SMaciej Purski 4695d389b12SMaciej Purski mutex_lock(&data->config_lock); 4705d389b12SMaciej Purski data->rshunt = val; 4715d389b12SMaciej Purski data->current_lsb_uA = DIV_ROUND_CLOSEST(dividend, val); 4725d389b12SMaciej Purski data->power_lsb_uW = data->config->power_lsb_factor * 4735d389b12SMaciej Purski data->current_lsb_uA; 4745d389b12SMaciej Purski mutex_unlock(&data->config_lock); 4755d389b12SMaciej Purski 4765d389b12SMaciej Purski return 0; 4775d389b12SMaciej Purski } 4785d389b12SMaciej Purski 4796a0f234fSGuenter Roeck static ssize_t ina2xx_shunt_show(struct device *dev, 4806a0f234fSGuenter Roeck struct device_attribute *da, char *buf) 4813ad86700SLothar Felten { 4823ad86700SLothar Felten struct ina2xx_data *data = dev_get_drvdata(dev); 4833ad86700SLothar Felten 4843ad86700SLothar Felten return snprintf(buf, PAGE_SIZE, "%li\n", data->rshunt); 4853ad86700SLothar Felten } 4863ad86700SLothar Felten 4876a0f234fSGuenter Roeck static ssize_t ina2xx_shunt_store(struct device *dev, 4888a5fc795SBartosz Golaszewski struct device_attribute *da, 4898a5fc795SBartosz Golaszewski const char *buf, size_t count) 4908a5fc795SBartosz Golaszewski { 4918a5fc795SBartosz Golaszewski unsigned long val; 4928a5fc795SBartosz Golaszewski int status; 493a0de56c8SMarc Titinger struct ina2xx_data *data = dev_get_drvdata(dev); 4948a5fc795SBartosz Golaszewski 4958a5fc795SBartosz Golaszewski status = kstrtoul(buf, 10, &val); 4968a5fc795SBartosz Golaszewski if (status < 0) 4978a5fc795SBartosz Golaszewski return status; 4988a5fc795SBartosz Golaszewski 4995d389b12SMaciej Purski status = ina2xx_set_shunt(data, val); 5008a5fc795SBartosz Golaszewski if (status < 0) 5018a5fc795SBartosz Golaszewski return status; 5028a5fc795SBartosz Golaszewski return count; 5038a5fc795SBartosz Golaszewski } 5048a5fc795SBartosz Golaszewski 5056a0f234fSGuenter Roeck static ssize_t ina226_interval_store(struct device *dev, 50672a87a47SBartosz Golaszewski struct device_attribute *da, 50772a87a47SBartosz Golaszewski const char *buf, size_t count) 50872a87a47SBartosz Golaszewski { 50972a87a47SBartosz Golaszewski struct ina2xx_data *data = dev_get_drvdata(dev); 51072a87a47SBartosz Golaszewski unsigned long val; 51172a87a47SBartosz Golaszewski int status; 51272a87a47SBartosz Golaszewski 51372a87a47SBartosz Golaszewski status = kstrtoul(buf, 10, &val); 51472a87a47SBartosz Golaszewski if (status < 0) 51572a87a47SBartosz Golaszewski return status; 51672a87a47SBartosz Golaszewski 51772a87a47SBartosz Golaszewski if (val > INT_MAX || val == 0) 51872a87a47SBartosz Golaszewski return -EINVAL; 51972a87a47SBartosz Golaszewski 520a0de56c8SMarc Titinger status = regmap_update_bits(data->regmap, INA2XX_CONFIG, 521a0de56c8SMarc Titinger INA226_AVG_RD_MASK, 522a0de56c8SMarc Titinger ina226_interval_to_reg(val)); 52372a87a47SBartosz Golaszewski if (status < 0) 52472a87a47SBartosz Golaszewski return status; 52572a87a47SBartosz Golaszewski 52672a87a47SBartosz Golaszewski return count; 52772a87a47SBartosz Golaszewski } 52872a87a47SBartosz Golaszewski 5296a0f234fSGuenter Roeck static ssize_t ina226_interval_show(struct device *dev, 53072a87a47SBartosz Golaszewski struct device_attribute *da, char *buf) 53172a87a47SBartosz Golaszewski { 532a0de56c8SMarc Titinger struct ina2xx_data *data = dev_get_drvdata(dev); 533a0de56c8SMarc Titinger int status; 534a0de56c8SMarc Titinger unsigned int regval; 53572a87a47SBartosz Golaszewski 536a0de56c8SMarc Titinger status = regmap_read(data->regmap, INA2XX_CONFIG, ®val); 537a0de56c8SMarc Titinger if (status) 538a0de56c8SMarc Titinger return status; 53972a87a47SBartosz Golaszewski 540a0de56c8SMarc Titinger return snprintf(buf, PAGE_SIZE, "%d\n", ina226_reg_to_interval(regval)); 54172a87a47SBartosz Golaszewski } 54272a87a47SBartosz Golaszewski 543f7c2fe38SFelten, Lothar /* shunt voltage */ 5446a0f234fSGuenter Roeck static SENSOR_DEVICE_ATTR_RO(in0_input, ina2xx_value, INA2XX_SHUNT_VOLTAGE); 5455a56a39bSAlex Qiu /* shunt voltage over/under voltage alert setting and alarm */ 5465a56a39bSAlex Qiu static SENSOR_DEVICE_ATTR_RW(in0_crit, ina226_alert, 5475a56a39bSAlex Qiu INA226_SHUNT_OVER_VOLTAGE_BIT); 5485a56a39bSAlex Qiu static SENSOR_DEVICE_ATTR_RW(in0_lcrit, ina226_alert, 5495a56a39bSAlex Qiu INA226_SHUNT_UNDER_VOLTAGE_BIT); 5505a56a39bSAlex Qiu static SENSOR_DEVICE_ATTR_RO(in0_crit_alarm, ina226_alarm, 5515a56a39bSAlex Qiu INA226_SHUNT_OVER_VOLTAGE_BIT); 5525a56a39bSAlex Qiu static SENSOR_DEVICE_ATTR_RO(in0_lcrit_alarm, ina226_alarm, 5535a56a39bSAlex Qiu INA226_SHUNT_UNDER_VOLTAGE_BIT); 554f7c2fe38SFelten, Lothar 555f7c2fe38SFelten, Lothar /* bus voltage */ 5566a0f234fSGuenter Roeck static SENSOR_DEVICE_ATTR_RO(in1_input, ina2xx_value, INA2XX_BUS_VOLTAGE); 5575a56a39bSAlex Qiu /* bus voltage over/under voltage alert setting and alarm */ 5585a56a39bSAlex Qiu static SENSOR_DEVICE_ATTR_RW(in1_crit, ina226_alert, 5595a56a39bSAlex Qiu INA226_BUS_OVER_VOLTAGE_BIT); 5605a56a39bSAlex Qiu static SENSOR_DEVICE_ATTR_RW(in1_lcrit, ina226_alert, 5615a56a39bSAlex Qiu INA226_BUS_UNDER_VOLTAGE_BIT); 5625a56a39bSAlex Qiu static SENSOR_DEVICE_ATTR_RO(in1_crit_alarm, ina226_alarm, 5635a56a39bSAlex Qiu INA226_BUS_OVER_VOLTAGE_BIT); 5645a56a39bSAlex Qiu static SENSOR_DEVICE_ATTR_RO(in1_lcrit_alarm, ina226_alarm, 5655a56a39bSAlex Qiu INA226_BUS_UNDER_VOLTAGE_BIT); 566f7c2fe38SFelten, Lothar 567f7c2fe38SFelten, Lothar /* calculated current */ 5686a0f234fSGuenter Roeck static SENSOR_DEVICE_ATTR_RO(curr1_input, ina2xx_value, INA2XX_CURRENT); 569f7c2fe38SFelten, Lothar 570f7c2fe38SFelten, Lothar /* calculated power */ 5716a0f234fSGuenter Roeck static SENSOR_DEVICE_ATTR_RO(power1_input, ina2xx_value, INA2XX_POWER); 5725a56a39bSAlex Qiu /* over-limit power alert setting and alarm */ 5735a56a39bSAlex Qiu static SENSOR_DEVICE_ATTR_RW(power1_crit, ina226_alert, 5745a56a39bSAlex Qiu INA226_POWER_OVER_LIMIT_BIT); 5755a56a39bSAlex Qiu static SENSOR_DEVICE_ATTR_RO(power1_crit_alarm, ina226_alarm, 5765a56a39bSAlex Qiu INA226_POWER_OVER_LIMIT_BIT); 577f7c2fe38SFelten, Lothar 5788a5fc795SBartosz Golaszewski /* shunt resistance */ 5796a0f234fSGuenter Roeck static SENSOR_DEVICE_ATTR_RW(shunt_resistor, ina2xx_shunt, INA2XX_CALIBRATION); 5808a5fc795SBartosz Golaszewski 58172a87a47SBartosz Golaszewski /* update interval (ina226 only) */ 5826a0f234fSGuenter Roeck static SENSOR_DEVICE_ATTR_RW(update_interval, ina226_interval, 0); 58372a87a47SBartosz Golaszewski 584f7c2fe38SFelten, Lothar /* pointers to created device attributes */ 585468bf0e3SGuenter Roeck static struct attribute *ina2xx_attrs[] = { 586f7c2fe38SFelten, Lothar &sensor_dev_attr_in0_input.dev_attr.attr, 587f7c2fe38SFelten, Lothar &sensor_dev_attr_in1_input.dev_attr.attr, 588f7c2fe38SFelten, Lothar &sensor_dev_attr_curr1_input.dev_attr.attr, 589f7c2fe38SFelten, Lothar &sensor_dev_attr_power1_input.dev_attr.attr, 5908a5fc795SBartosz Golaszewski &sensor_dev_attr_shunt_resistor.dev_attr.attr, 591f7c2fe38SFelten, Lothar NULL, 592f7c2fe38SFelten, Lothar }; 59372a87a47SBartosz Golaszewski 59472a87a47SBartosz Golaszewski static const struct attribute_group ina2xx_group = { 59572a87a47SBartosz Golaszewski .attrs = ina2xx_attrs, 59672a87a47SBartosz Golaszewski }; 59772a87a47SBartosz Golaszewski 59872a87a47SBartosz Golaszewski static struct attribute *ina226_attrs[] = { 5995a56a39bSAlex Qiu &sensor_dev_attr_in0_crit.dev_attr.attr, 6005a56a39bSAlex Qiu &sensor_dev_attr_in0_lcrit.dev_attr.attr, 6015a56a39bSAlex Qiu &sensor_dev_attr_in0_crit_alarm.dev_attr.attr, 6025a56a39bSAlex Qiu &sensor_dev_attr_in0_lcrit_alarm.dev_attr.attr, 6035a56a39bSAlex Qiu &sensor_dev_attr_in1_crit.dev_attr.attr, 6045a56a39bSAlex Qiu &sensor_dev_attr_in1_lcrit.dev_attr.attr, 6055a56a39bSAlex Qiu &sensor_dev_attr_in1_crit_alarm.dev_attr.attr, 6065a56a39bSAlex Qiu &sensor_dev_attr_in1_lcrit_alarm.dev_attr.attr, 6075a56a39bSAlex Qiu &sensor_dev_attr_power1_crit.dev_attr.attr, 6085a56a39bSAlex Qiu &sensor_dev_attr_power1_crit_alarm.dev_attr.attr, 60972a87a47SBartosz Golaszewski &sensor_dev_attr_update_interval.dev_attr.attr, 61072a87a47SBartosz Golaszewski NULL, 61172a87a47SBartosz Golaszewski }; 61272a87a47SBartosz Golaszewski 61372a87a47SBartosz Golaszewski static const struct attribute_group ina226_group = { 61472a87a47SBartosz Golaszewski .attrs = ina226_attrs, 61572a87a47SBartosz Golaszewski }; 616f7c2fe38SFelten, Lothar 617*67487038SStephen Kitt static const struct i2c_device_id ina2xx_id[]; 618*67487038SStephen Kitt 619*67487038SStephen Kitt static int ina2xx_probe(struct i2c_client *client) 620f7c2fe38SFelten, Lothar { 621468bf0e3SGuenter Roeck struct device *dev = &client->dev; 622468bf0e3SGuenter Roeck struct ina2xx_data *data; 623468bf0e3SGuenter Roeck struct device *hwmon_dev; 624468bf0e3SGuenter Roeck u32 val; 62572a87a47SBartosz Golaszewski int ret, group = 0; 626bd0ddd4dSJavier Martinez Canillas enum ina2xx_ids chip; 627bd0ddd4dSJavier Martinez Canillas 628bd0ddd4dSJavier Martinez Canillas if (client->dev.of_node) 629bd0ddd4dSJavier Martinez Canillas chip = (enum ina2xx_ids)of_device_get_match_data(&client->dev); 630bd0ddd4dSJavier Martinez Canillas else 631*67487038SStephen Kitt chip = i2c_match_id(ina2xx_id, client)->driver_data; 632f7c2fe38SFelten, Lothar 633468bf0e3SGuenter Roeck data = devm_kzalloc(dev, sizeof(*data), GFP_KERNEL); 634f7c2fe38SFelten, Lothar if (!data) 635f7c2fe38SFelten, Lothar return -ENOMEM; 636f7c2fe38SFelten, Lothar 637f7c2fe38SFelten, Lothar /* set the device type */ 638bd0ddd4dSJavier Martinez Canillas data->config = &ina2xx_config[chip]; 6390c4c5860SMarek Szyprowski mutex_init(&data->config_lock); 64072a87a47SBartosz Golaszewski 641001e2e73SMarc Titinger if (of_property_read_u32(dev->of_node, "shunt-resistor", &val) < 0) { 642001e2e73SMarc Titinger struct ina2xx_platform_data *pdata = dev_get_platdata(dev); 643001e2e73SMarc Titinger 644001e2e73SMarc Titinger if (pdata) 645001e2e73SMarc Titinger val = pdata->shunt_uohms; 646001e2e73SMarc Titinger else 647001e2e73SMarc Titinger val = INA2XX_RSHUNT_DEFAULT; 648001e2e73SMarc Titinger } 649001e2e73SMarc Titinger 6505d389b12SMaciej Purski ina2xx_set_shunt(data, val); 651001e2e73SMarc Titinger 652a0de56c8SMarc Titinger ina2xx_regmap_config.max_register = data->config->registers; 653a0de56c8SMarc Titinger 654a0de56c8SMarc Titinger data->regmap = devm_regmap_init_i2c(client, &ina2xx_regmap_config); 655a0de56c8SMarc Titinger if (IS_ERR(data->regmap)) { 656a0de56c8SMarc Titinger dev_err(dev, "failed to allocate register map\n"); 657a0de56c8SMarc Titinger return PTR_ERR(data->regmap); 658a0de56c8SMarc Titinger } 659a0de56c8SMarc Titinger 660509416a8SBartosz Golaszewski ret = ina2xx_init(data); 661509416a8SBartosz Golaszewski if (ret < 0) { 662509416a8SBartosz Golaszewski dev_err(dev, "error configuring the device: %d\n", ret); 663509416a8SBartosz Golaszewski return -ENODEV; 664509416a8SBartosz Golaszewski } 665509416a8SBartosz Golaszewski 66672a87a47SBartosz Golaszewski data->groups[group++] = &ina2xx_group; 66770df9ebbSNicolin Chen if (chip == ina226) 66872a87a47SBartosz Golaszewski data->groups[group++] = &ina226_group; 66972a87a47SBartosz Golaszewski 670468bf0e3SGuenter Roeck hwmon_dev = devm_hwmon_device_register_with_groups(dev, client->name, 67172a87a47SBartosz Golaszewski data, data->groups); 672468bf0e3SGuenter Roeck if (IS_ERR(hwmon_dev)) 673468bf0e3SGuenter Roeck return PTR_ERR(hwmon_dev); 674f7c2fe38SFelten, Lothar 675468bf0e3SGuenter Roeck dev_info(dev, "power monitor %s (Rshunt = %li uOhm)\n", 67670df9ebbSNicolin Chen client->name, data->rshunt); 6776106db25SGuenter Roeck 678f7c2fe38SFelten, Lothar return 0; 679f7c2fe38SFelten, Lothar } 680f7c2fe38SFelten, Lothar 681f7c2fe38SFelten, Lothar static const struct i2c_device_id ina2xx_id[] = { 682f7c2fe38SFelten, Lothar { "ina219", ina219 }, 683dc92cd0cSGuenter Roeck { "ina220", ina219 }, 684f7c2fe38SFelten, Lothar { "ina226", ina226 }, 685dc92cd0cSGuenter Roeck { "ina230", ina226 }, 686add513beSKevin Hilman { "ina231", ina226 }, 687f7c2fe38SFelten, Lothar { } 688f7c2fe38SFelten, Lothar }; 689f7c2fe38SFelten, Lothar MODULE_DEVICE_TABLE(i2c, ina2xx_id); 690f7c2fe38SFelten, Lothar 691df6b8c70SGuenter Roeck static const struct of_device_id __maybe_unused ina2xx_of_match[] = { 692bd0ddd4dSJavier Martinez Canillas { 693bd0ddd4dSJavier Martinez Canillas .compatible = "ti,ina219", 694bd0ddd4dSJavier Martinez Canillas .data = (void *)ina219 695bd0ddd4dSJavier Martinez Canillas }, 696bd0ddd4dSJavier Martinez Canillas { 697bd0ddd4dSJavier Martinez Canillas .compatible = "ti,ina220", 698bd0ddd4dSJavier Martinez Canillas .data = (void *)ina219 699bd0ddd4dSJavier Martinez Canillas }, 700bd0ddd4dSJavier Martinez Canillas { 701bd0ddd4dSJavier Martinez Canillas .compatible = "ti,ina226", 702bd0ddd4dSJavier Martinez Canillas .data = (void *)ina226 703bd0ddd4dSJavier Martinez Canillas }, 704bd0ddd4dSJavier Martinez Canillas { 705bd0ddd4dSJavier Martinez Canillas .compatible = "ti,ina230", 706bd0ddd4dSJavier Martinez Canillas .data = (void *)ina226 707bd0ddd4dSJavier Martinez Canillas }, 708bd0ddd4dSJavier Martinez Canillas { 709bd0ddd4dSJavier Martinez Canillas .compatible = "ti,ina231", 710bd0ddd4dSJavier Martinez Canillas .data = (void *)ina226 711bd0ddd4dSJavier Martinez Canillas }, 712bd0ddd4dSJavier Martinez Canillas { }, 713bd0ddd4dSJavier Martinez Canillas }; 714bd0ddd4dSJavier Martinez Canillas MODULE_DEVICE_TABLE(of, ina2xx_of_match); 715bd0ddd4dSJavier Martinez Canillas 716f7c2fe38SFelten, Lothar static struct i2c_driver ina2xx_driver = { 717f7c2fe38SFelten, Lothar .driver = { 718f7c2fe38SFelten, Lothar .name = "ina2xx", 719bd0ddd4dSJavier Martinez Canillas .of_match_table = of_match_ptr(ina2xx_of_match), 720f7c2fe38SFelten, Lothar }, 721*67487038SStephen Kitt .probe_new = ina2xx_probe, 722f7c2fe38SFelten, Lothar .id_table = ina2xx_id, 723f7c2fe38SFelten, Lothar }; 724f7c2fe38SFelten, Lothar 725d835ca0fSWei Yongjun module_i2c_driver(ina2xx_driver); 726f7c2fe38SFelten, Lothar 727f7c2fe38SFelten, Lothar MODULE_AUTHOR("Lothar Felten <l-felten@ti.com>"); 728f7c2fe38SFelten, Lothar MODULE_DESCRIPTION("ina2xx driver"); 729f7c2fe38SFelten, Lothar MODULE_LICENSE("GPL"); 730