1f7c2fe38SFelten, Lothar /* 2f7c2fe38SFelten, Lothar * Driver for Texas Instruments INA219, INA226 power monitor chips 3f7c2fe38SFelten, Lothar * 4f7c2fe38SFelten, Lothar * INA219: 5f7c2fe38SFelten, Lothar * Zero Drift Bi-Directional Current/Power Monitor with I2C Interface 6f7c2fe38SFelten, Lothar * Datasheet: http://www.ti.com/product/ina219 7f7c2fe38SFelten, Lothar * 8dc92cd0cSGuenter Roeck * INA220: 9dc92cd0cSGuenter Roeck * Bi-Directional Current/Power Monitor with I2C Interface 10dc92cd0cSGuenter Roeck * Datasheet: http://www.ti.com/product/ina220 11dc92cd0cSGuenter Roeck * 12f7c2fe38SFelten, Lothar * INA226: 13f7c2fe38SFelten, Lothar * Bi-Directional Current/Power Monitor with I2C Interface 14f7c2fe38SFelten, Lothar * Datasheet: http://www.ti.com/product/ina226 15f7c2fe38SFelten, Lothar * 16dc92cd0cSGuenter Roeck * INA230: 17dc92cd0cSGuenter Roeck * Bi-directional Current/Power Monitor with I2C Interface 18dc92cd0cSGuenter Roeck * Datasheet: http://www.ti.com/product/ina230 19dc92cd0cSGuenter Roeck * 20f7c2fe38SFelten, Lothar * Copyright (C) 2012 Lothar Felten <l-felten@ti.com> 21f7c2fe38SFelten, Lothar * Thanks to Jan Volkering 22f7c2fe38SFelten, Lothar * 23f7c2fe38SFelten, Lothar * This program is free software; you can redistribute it and/or modify 24f7c2fe38SFelten, Lothar * it under the terms of the GNU General Public License as published by 25f7c2fe38SFelten, Lothar * the Free Software Foundation; version 2 of the License. 26f7c2fe38SFelten, Lothar */ 27f7c2fe38SFelten, Lothar 28f7c2fe38SFelten, Lothar #include <linux/kernel.h> 29f7c2fe38SFelten, Lothar #include <linux/module.h> 30f7c2fe38SFelten, Lothar #include <linux/init.h> 31f7c2fe38SFelten, Lothar #include <linux/err.h> 32f7c2fe38SFelten, Lothar #include <linux/slab.h> 33f7c2fe38SFelten, Lothar #include <linux/i2c.h> 34f7c2fe38SFelten, Lothar #include <linux/hwmon.h> 35f7c2fe38SFelten, Lothar #include <linux/hwmon-sysfs.h> 36dcd8f392SJean Delvare #include <linux/jiffies.h> 37*bd0ddd4dSJavier Martinez Canillas #include <linux/of_device.h> 3831e7ad74STang Yuantian #include <linux/of.h> 39509416a8SBartosz Golaszewski #include <linux/delay.h> 40d38df34eSBartosz Golaszewski #include <linux/util_macros.h> 41a0de56c8SMarc Titinger #include <linux/regmap.h> 42f7c2fe38SFelten, Lothar 43f7c2fe38SFelten, Lothar #include <linux/platform_data/ina2xx.h> 44f7c2fe38SFelten, Lothar 45f7c2fe38SFelten, Lothar /* common register definitions */ 46f7c2fe38SFelten, Lothar #define INA2XX_CONFIG 0x00 47f7c2fe38SFelten, Lothar #define INA2XX_SHUNT_VOLTAGE 0x01 /* readonly */ 48f7c2fe38SFelten, Lothar #define INA2XX_BUS_VOLTAGE 0x02 /* readonly */ 49f7c2fe38SFelten, Lothar #define INA2XX_POWER 0x03 /* readonly */ 50f7c2fe38SFelten, Lothar #define INA2XX_CURRENT 0x04 /* readonly */ 51f7c2fe38SFelten, Lothar #define INA2XX_CALIBRATION 0x05 52f7c2fe38SFelten, Lothar 53f7c2fe38SFelten, Lothar /* INA226 register definitions */ 54f7c2fe38SFelten, Lothar #define INA226_MASK_ENABLE 0x06 55f7c2fe38SFelten, Lothar #define INA226_ALERT_LIMIT 0x07 56f7c2fe38SFelten, Lothar #define INA226_DIE_ID 0xFF 57f7c2fe38SFelten, Lothar 58f7c2fe38SFelten, Lothar /* register count */ 59f7c2fe38SFelten, Lothar #define INA219_REGISTERS 6 60f7c2fe38SFelten, Lothar #define INA226_REGISTERS 8 61f7c2fe38SFelten, Lothar 62f7c2fe38SFelten, Lothar #define INA2XX_MAX_REGISTERS 8 63f7c2fe38SFelten, Lothar 64f7c2fe38SFelten, Lothar /* settings - depend on use case */ 65f7c2fe38SFelten, Lothar #define INA219_CONFIG_DEFAULT 0x399F /* PGA=8 */ 66f7c2fe38SFelten, Lothar #define INA226_CONFIG_DEFAULT 0x4527 /* averages=16 */ 67f7c2fe38SFelten, Lothar 68f7c2fe38SFelten, Lothar /* worst case is 68.10 ms (~14.6Hz, ina219) */ 69f7c2fe38SFelten, Lothar #define INA2XX_CONVERSION_RATE 15 70509416a8SBartosz Golaszewski #define INA2XX_MAX_DELAY 69 /* worst case delay in ms */ 71509416a8SBartosz Golaszewski 72509416a8SBartosz Golaszewski #define INA2XX_RSHUNT_DEFAULT 10000 73f7c2fe38SFelten, Lothar 7472a87a47SBartosz Golaszewski /* bit mask for reading the averaging setting in the configuration register */ 7572a87a47SBartosz Golaszewski #define INA226_AVG_RD_MASK 0x0E00 7672a87a47SBartosz Golaszewski 7772a87a47SBartosz Golaszewski #define INA226_READ_AVG(reg) (((reg) & INA226_AVG_RD_MASK) >> 9) 7872a87a47SBartosz Golaszewski #define INA226_SHIFT_AVG(val) ((val) << 9) 7972a87a47SBartosz Golaszewski 8072a87a47SBartosz Golaszewski /* common attrs, ina226 attrs and NULL */ 8172a87a47SBartosz Golaszewski #define INA2XX_MAX_ATTRIBUTE_GROUPS 3 8272a87a47SBartosz Golaszewski 8372a87a47SBartosz Golaszewski /* 8472a87a47SBartosz Golaszewski * Both bus voltage and shunt voltage conversion times for ina226 are set 8572a87a47SBartosz Golaszewski * to 0b0100 on POR, which translates to 2200 microseconds in total. 8672a87a47SBartosz Golaszewski */ 8772a87a47SBartosz Golaszewski #define INA226_TOTAL_CONV_TIME_DEFAULT 2200 8872a87a47SBartosz Golaszewski 89a0de56c8SMarc Titinger static struct regmap_config ina2xx_regmap_config = { 90a0de56c8SMarc Titinger .reg_bits = 8, 91a0de56c8SMarc Titinger .val_bits = 16, 92a0de56c8SMarc Titinger }; 93a0de56c8SMarc Titinger 94f7c2fe38SFelten, Lothar enum ina2xx_ids { ina219, ina226 }; 95f7c2fe38SFelten, Lothar 966106db25SGuenter Roeck struct ina2xx_config { 976106db25SGuenter Roeck u16 config_default; 986106db25SGuenter Roeck int calibration_factor; 996106db25SGuenter Roeck int registers; 1006106db25SGuenter Roeck int shunt_div; 1016106db25SGuenter Roeck int bus_voltage_shift; 1026106db25SGuenter Roeck int bus_voltage_lsb; /* uV */ 1036106db25SGuenter Roeck int power_lsb; /* uW */ 1046106db25SGuenter Roeck }; 1056106db25SGuenter Roeck 106f7c2fe38SFelten, Lothar struct ina2xx_data { 1076106db25SGuenter Roeck const struct ina2xx_config *config; 108f7c2fe38SFelten, Lothar 109509416a8SBartosz Golaszewski long rshunt; 110a0de56c8SMarc Titinger struct mutex config_lock; 111a0de56c8SMarc Titinger struct regmap *regmap; 112f7c2fe38SFelten, Lothar 11372a87a47SBartosz Golaszewski const struct attribute_group *groups[INA2XX_MAX_ATTRIBUTE_GROUPS]; 114f7c2fe38SFelten, Lothar }; 115f7c2fe38SFelten, Lothar 1166106db25SGuenter Roeck static const struct ina2xx_config ina2xx_config[] = { 1176106db25SGuenter Roeck [ina219] = { 1186106db25SGuenter Roeck .config_default = INA219_CONFIG_DEFAULT, 1196106db25SGuenter Roeck .calibration_factor = 40960000, 1206106db25SGuenter Roeck .registers = INA219_REGISTERS, 1216106db25SGuenter Roeck .shunt_div = 100, 1226106db25SGuenter Roeck .bus_voltage_shift = 3, 1236106db25SGuenter Roeck .bus_voltage_lsb = 4000, 1246106db25SGuenter Roeck .power_lsb = 20000, 1256106db25SGuenter Roeck }, 1266106db25SGuenter Roeck [ina226] = { 1276106db25SGuenter Roeck .config_default = INA226_CONFIG_DEFAULT, 1286106db25SGuenter Roeck .calibration_factor = 5120000, 1296106db25SGuenter Roeck .registers = INA226_REGISTERS, 1306106db25SGuenter Roeck .shunt_div = 400, 1316106db25SGuenter Roeck .bus_voltage_shift = 0, 1326106db25SGuenter Roeck .bus_voltage_lsb = 1250, 1336106db25SGuenter Roeck .power_lsb = 25000, 1346106db25SGuenter Roeck }, 1356106db25SGuenter Roeck }; 1366106db25SGuenter Roeck 13772a87a47SBartosz Golaszewski /* 13872a87a47SBartosz Golaszewski * Available averaging rates for ina226. The indices correspond with 13972a87a47SBartosz Golaszewski * the bit values expected by the chip (according to the ina226 datasheet, 14072a87a47SBartosz Golaszewski * table 3 AVG bit settings, found at 14172a87a47SBartosz Golaszewski * http://www.ti.com/lit/ds/symlink/ina226.pdf. 14272a87a47SBartosz Golaszewski */ 14372a87a47SBartosz Golaszewski static const int ina226_avg_tab[] = { 1, 4, 16, 64, 128, 256, 512, 1024 }; 14472a87a47SBartosz Golaszewski 14572a87a47SBartosz Golaszewski static int ina226_reg_to_interval(u16 config) 14672a87a47SBartosz Golaszewski { 14772a87a47SBartosz Golaszewski int avg = ina226_avg_tab[INA226_READ_AVG(config)]; 14872a87a47SBartosz Golaszewski 14972a87a47SBartosz Golaszewski /* 15072a87a47SBartosz Golaszewski * Multiply the total conversion time by the number of averages. 15172a87a47SBartosz Golaszewski * Return the result in milliseconds. 15272a87a47SBartosz Golaszewski */ 15372a87a47SBartosz Golaszewski return DIV_ROUND_CLOSEST(avg * INA226_TOTAL_CONV_TIME_DEFAULT, 1000); 15472a87a47SBartosz Golaszewski } 15572a87a47SBartosz Golaszewski 156a0de56c8SMarc Titinger /* 157a0de56c8SMarc Titinger * Return the new, shifted AVG field value of CONFIG register, 158a0de56c8SMarc Titinger * to use with regmap_update_bits 159a0de56c8SMarc Titinger */ 160a0de56c8SMarc Titinger static u16 ina226_interval_to_reg(int interval) 16172a87a47SBartosz Golaszewski { 16272a87a47SBartosz Golaszewski int avg, avg_bits; 16372a87a47SBartosz Golaszewski 16472a87a47SBartosz Golaszewski avg = DIV_ROUND_CLOSEST(interval * 1000, 16572a87a47SBartosz Golaszewski INA226_TOTAL_CONV_TIME_DEFAULT); 166d38df34eSBartosz Golaszewski avg_bits = find_closest(avg, ina226_avg_tab, 167d38df34eSBartosz Golaszewski ARRAY_SIZE(ina226_avg_tab)); 16872a87a47SBartosz Golaszewski 169a0de56c8SMarc Titinger return INA226_SHIFT_AVG(avg_bits); 17072a87a47SBartosz Golaszewski } 17172a87a47SBartosz Golaszewski 1728a5fc795SBartosz Golaszewski static int ina2xx_calibrate(struct ina2xx_data *data) 1738a5fc795SBartosz Golaszewski { 174b721fe2aSBartosz Golaszewski u16 val = DIV_ROUND_CLOSEST(data->config->calibration_factor, 175b721fe2aSBartosz Golaszewski data->rshunt); 176b721fe2aSBartosz Golaszewski 177a0de56c8SMarc Titinger return regmap_write(data->regmap, INA2XX_CALIBRATION, val); 1788a5fc795SBartosz Golaszewski } 1798a5fc795SBartosz Golaszewski 180509416a8SBartosz Golaszewski /* 181509416a8SBartosz Golaszewski * Initialize the configuration and calibration registers. 182509416a8SBartosz Golaszewski */ 183509416a8SBartosz Golaszewski static int ina2xx_init(struct ina2xx_data *data) 184509416a8SBartosz Golaszewski { 185a0de56c8SMarc Titinger int ret = regmap_write(data->regmap, INA2XX_CONFIG, 186a0de56c8SMarc Titinger data->config->config_default); 187509416a8SBartosz Golaszewski if (ret < 0) 188509416a8SBartosz Golaszewski return ret; 189509416a8SBartosz Golaszewski 190509416a8SBartosz Golaszewski /* 191509416a8SBartosz Golaszewski * Set current LSB to 1mA, shunt is in uOhms 192509416a8SBartosz Golaszewski * (equation 13 in datasheet). 193509416a8SBartosz Golaszewski */ 1948a5fc795SBartosz Golaszewski return ina2xx_calibrate(data); 195509416a8SBartosz Golaszewski } 196509416a8SBartosz Golaszewski 197a0de56c8SMarc Titinger static int ina2xx_read_reg(struct device *dev, int reg, unsigned int *regval) 198f7c2fe38SFelten, Lothar { 199468bf0e3SGuenter Roeck struct ina2xx_data *data = dev_get_drvdata(dev); 200a0de56c8SMarc Titinger int ret, retry; 201509416a8SBartosz Golaszewski 202a0de56c8SMarc Titinger dev_dbg(dev, "Starting register %d read\n", reg); 203509416a8SBartosz Golaszewski 204509416a8SBartosz Golaszewski for (retry = 5; retry; retry--) { 205a0de56c8SMarc Titinger 206a0de56c8SMarc Titinger ret = regmap_read(data->regmap, reg, regval); 207a0de56c8SMarc Titinger if (ret < 0) 208a0de56c8SMarc Titinger return ret; 209a0de56c8SMarc Titinger 210a0de56c8SMarc Titinger dev_dbg(dev, "read %d, val = 0x%04x\n", reg, *regval); 211509416a8SBartosz Golaszewski 212509416a8SBartosz Golaszewski /* 213509416a8SBartosz Golaszewski * If the current value in the calibration register is 0, the 214509416a8SBartosz Golaszewski * power and current registers will also remain at 0. In case 215509416a8SBartosz Golaszewski * the chip has been reset let's check the calibration 216509416a8SBartosz Golaszewski * register and reinitialize if needed. 217a0de56c8SMarc Titinger * We do that extra read of the calibration register if there 218a0de56c8SMarc Titinger * is some hint of a chip reset. 219509416a8SBartosz Golaszewski */ 220a0de56c8SMarc Titinger if (*regval == 0) { 221a0de56c8SMarc Titinger unsigned int cal; 222a0de56c8SMarc Titinger 223a0de56c8SMarc Titinger ret = regmap_read(data->regmap, INA2XX_CALIBRATION, 224a0de56c8SMarc Titinger &cal); 225a0de56c8SMarc Titinger if (ret < 0) 226a0de56c8SMarc Titinger return ret; 227a0de56c8SMarc Titinger 228a0de56c8SMarc Titinger if (cal == 0) { 229509416a8SBartosz Golaszewski dev_warn(dev, "chip not calibrated, reinitializing\n"); 230509416a8SBartosz Golaszewski 231a0de56c8SMarc Titinger ret = ina2xx_init(data); 232a0de56c8SMarc Titinger if (ret < 0) 233a0de56c8SMarc Titinger return ret; 234509416a8SBartosz Golaszewski /* 235a0de56c8SMarc Titinger * Let's make sure the power and current 236a0de56c8SMarc Titinger * registers have been updated before trying 237a0de56c8SMarc Titinger * again. 238509416a8SBartosz Golaszewski */ 239509416a8SBartosz Golaszewski msleep(INA2XX_MAX_DELAY); 240509416a8SBartosz Golaszewski continue; 241509416a8SBartosz Golaszewski } 242a0de56c8SMarc Titinger } 243509416a8SBartosz Golaszewski return 0; 244509416a8SBartosz Golaszewski } 245509416a8SBartosz Golaszewski 246509416a8SBartosz Golaszewski /* 247509416a8SBartosz Golaszewski * If we're here then although all write operations succeeded, the 248509416a8SBartosz Golaszewski * chip still returns 0 in the calibration register. Nothing more we 249509416a8SBartosz Golaszewski * can do here. 250509416a8SBartosz Golaszewski */ 251509416a8SBartosz Golaszewski dev_err(dev, "unable to reinitialize the chip\n"); 252509416a8SBartosz Golaszewski return -ENODEV; 253509416a8SBartosz Golaszewski } 254509416a8SBartosz Golaszewski 255a0de56c8SMarc Titinger static int ina2xx_get_value(struct ina2xx_data *data, u8 reg, 256a0de56c8SMarc Titinger unsigned int regval) 257f7c2fe38SFelten, Lothar { 2586106db25SGuenter Roeck int val; 259f7c2fe38SFelten, Lothar 260f7c2fe38SFelten, Lothar switch (reg) { 261f7c2fe38SFelten, Lothar case INA2XX_SHUNT_VOLTAGE: 262c0214f98SFabio Baltieri /* signed register */ 263a0de56c8SMarc Titinger val = DIV_ROUND_CLOSEST((s16)regval, data->config->shunt_div); 264f7c2fe38SFelten, Lothar break; 265f7c2fe38SFelten, Lothar case INA2XX_BUS_VOLTAGE: 266a0de56c8SMarc Titinger val = (regval >> data->config->bus_voltage_shift) 2676106db25SGuenter Roeck * data->config->bus_voltage_lsb; 2686106db25SGuenter Roeck val = DIV_ROUND_CLOSEST(val, 1000); 269f7c2fe38SFelten, Lothar break; 270f7c2fe38SFelten, Lothar case INA2XX_POWER: 271a0de56c8SMarc Titinger val = regval * data->config->power_lsb; 272f7c2fe38SFelten, Lothar break; 273f7c2fe38SFelten, Lothar case INA2XX_CURRENT: 274c0214f98SFabio Baltieri /* signed register, LSB=1mA (selected), in mA */ 275a0de56c8SMarc Titinger val = (s16)regval; 276f7c2fe38SFelten, Lothar break; 2778a5fc795SBartosz Golaszewski case INA2XX_CALIBRATION: 278b721fe2aSBartosz Golaszewski val = DIV_ROUND_CLOSEST(data->config->calibration_factor, 279a0de56c8SMarc Titinger regval); 2808a5fc795SBartosz Golaszewski break; 281f7c2fe38SFelten, Lothar default: 282f7c2fe38SFelten, Lothar /* programmer goofed */ 283f7c2fe38SFelten, Lothar WARN_ON_ONCE(1); 284f7c2fe38SFelten, Lothar val = 0; 285f7c2fe38SFelten, Lothar break; 286f7c2fe38SFelten, Lothar } 287f7c2fe38SFelten, Lothar 288f7c2fe38SFelten, Lothar return val; 289f7c2fe38SFelten, Lothar } 290f7c2fe38SFelten, Lothar 291f7c2fe38SFelten, Lothar static ssize_t ina2xx_show_value(struct device *dev, 292f7c2fe38SFelten, Lothar struct device_attribute *da, char *buf) 293f7c2fe38SFelten, Lothar { 294f7c2fe38SFelten, Lothar struct sensor_device_attribute *attr = to_sensor_dev_attr(da); 295a0de56c8SMarc Titinger struct ina2xx_data *data = dev_get_drvdata(dev); 296a0de56c8SMarc Titinger unsigned int regval; 297f7c2fe38SFelten, Lothar 298a0de56c8SMarc Titinger int err = ina2xx_read_reg(dev, attr->index, ®val); 299a0de56c8SMarc Titinger 300a0de56c8SMarc Titinger if (err < 0) 301a0de56c8SMarc Titinger return err; 302f7c2fe38SFelten, Lothar 3036106db25SGuenter Roeck return snprintf(buf, PAGE_SIZE, "%d\n", 304a0de56c8SMarc Titinger ina2xx_get_value(data, attr->index, regval)); 305f7c2fe38SFelten, Lothar } 306f7c2fe38SFelten, Lothar 3078a5fc795SBartosz Golaszewski static ssize_t ina2xx_set_shunt(struct device *dev, 3088a5fc795SBartosz Golaszewski struct device_attribute *da, 3098a5fc795SBartosz Golaszewski const char *buf, size_t count) 3108a5fc795SBartosz Golaszewski { 3118a5fc795SBartosz Golaszewski unsigned long val; 3128a5fc795SBartosz Golaszewski int status; 313a0de56c8SMarc Titinger struct ina2xx_data *data = dev_get_drvdata(dev); 3148a5fc795SBartosz Golaszewski 3158a5fc795SBartosz Golaszewski status = kstrtoul(buf, 10, &val); 3168a5fc795SBartosz Golaszewski if (status < 0) 3178a5fc795SBartosz Golaszewski return status; 3188a5fc795SBartosz Golaszewski 3198a5fc795SBartosz Golaszewski if (val == 0 || 3208a5fc795SBartosz Golaszewski /* Values greater than the calibration factor make no sense. */ 3218a5fc795SBartosz Golaszewski val > data->config->calibration_factor) 3228a5fc795SBartosz Golaszewski return -EINVAL; 3238a5fc795SBartosz Golaszewski 324a0de56c8SMarc Titinger mutex_lock(&data->config_lock); 3258a5fc795SBartosz Golaszewski data->rshunt = val; 3268a5fc795SBartosz Golaszewski status = ina2xx_calibrate(data); 327a0de56c8SMarc Titinger mutex_unlock(&data->config_lock); 3288a5fc795SBartosz Golaszewski if (status < 0) 3298a5fc795SBartosz Golaszewski return status; 3308a5fc795SBartosz Golaszewski 3318a5fc795SBartosz Golaszewski return count; 3328a5fc795SBartosz Golaszewski } 3338a5fc795SBartosz Golaszewski 33472a87a47SBartosz Golaszewski static ssize_t ina226_set_interval(struct device *dev, 33572a87a47SBartosz Golaszewski struct device_attribute *da, 33672a87a47SBartosz Golaszewski const char *buf, size_t count) 33772a87a47SBartosz Golaszewski { 33872a87a47SBartosz Golaszewski struct ina2xx_data *data = dev_get_drvdata(dev); 33972a87a47SBartosz Golaszewski unsigned long val; 34072a87a47SBartosz Golaszewski int status; 34172a87a47SBartosz Golaszewski 34272a87a47SBartosz Golaszewski status = kstrtoul(buf, 10, &val); 34372a87a47SBartosz Golaszewski if (status < 0) 34472a87a47SBartosz Golaszewski return status; 34572a87a47SBartosz Golaszewski 34672a87a47SBartosz Golaszewski if (val > INT_MAX || val == 0) 34772a87a47SBartosz Golaszewski return -EINVAL; 34872a87a47SBartosz Golaszewski 349a0de56c8SMarc Titinger status = regmap_update_bits(data->regmap, INA2XX_CONFIG, 350a0de56c8SMarc Titinger INA226_AVG_RD_MASK, 351a0de56c8SMarc Titinger ina226_interval_to_reg(val)); 35272a87a47SBartosz Golaszewski if (status < 0) 35372a87a47SBartosz Golaszewski return status; 35472a87a47SBartosz Golaszewski 35572a87a47SBartosz Golaszewski return count; 35672a87a47SBartosz Golaszewski } 35772a87a47SBartosz Golaszewski 35872a87a47SBartosz Golaszewski static ssize_t ina226_show_interval(struct device *dev, 35972a87a47SBartosz Golaszewski struct device_attribute *da, char *buf) 36072a87a47SBartosz Golaszewski { 361a0de56c8SMarc Titinger struct ina2xx_data *data = dev_get_drvdata(dev); 362a0de56c8SMarc Titinger int status; 363a0de56c8SMarc Titinger unsigned int regval; 36472a87a47SBartosz Golaszewski 365a0de56c8SMarc Titinger status = regmap_read(data->regmap, INA2XX_CONFIG, ®val); 366a0de56c8SMarc Titinger if (status) 367a0de56c8SMarc Titinger return status; 36872a87a47SBartosz Golaszewski 369a0de56c8SMarc Titinger return snprintf(buf, PAGE_SIZE, "%d\n", ina226_reg_to_interval(regval)); 37072a87a47SBartosz Golaszewski } 37172a87a47SBartosz Golaszewski 372f7c2fe38SFelten, Lothar /* shunt voltage */ 373f0df0fd9SGuenter Roeck static SENSOR_DEVICE_ATTR(in0_input, S_IRUGO, ina2xx_show_value, NULL, 374f0df0fd9SGuenter Roeck INA2XX_SHUNT_VOLTAGE); 375f7c2fe38SFelten, Lothar 376f7c2fe38SFelten, Lothar /* bus voltage */ 377f0df0fd9SGuenter Roeck static SENSOR_DEVICE_ATTR(in1_input, S_IRUGO, ina2xx_show_value, NULL, 378f0df0fd9SGuenter Roeck INA2XX_BUS_VOLTAGE); 379f7c2fe38SFelten, Lothar 380f7c2fe38SFelten, Lothar /* calculated current */ 381f0df0fd9SGuenter Roeck static SENSOR_DEVICE_ATTR(curr1_input, S_IRUGO, ina2xx_show_value, NULL, 382f0df0fd9SGuenter Roeck INA2XX_CURRENT); 383f7c2fe38SFelten, Lothar 384f7c2fe38SFelten, Lothar /* calculated power */ 385f0df0fd9SGuenter Roeck static SENSOR_DEVICE_ATTR(power1_input, S_IRUGO, ina2xx_show_value, NULL, 386f0df0fd9SGuenter Roeck INA2XX_POWER); 387f7c2fe38SFelten, Lothar 3888a5fc795SBartosz Golaszewski /* shunt resistance */ 3898a5fc795SBartosz Golaszewski static SENSOR_DEVICE_ATTR(shunt_resistor, S_IRUGO | S_IWUSR, 3908a5fc795SBartosz Golaszewski ina2xx_show_value, ina2xx_set_shunt, 3918a5fc795SBartosz Golaszewski INA2XX_CALIBRATION); 3928a5fc795SBartosz Golaszewski 39372a87a47SBartosz Golaszewski /* update interval (ina226 only) */ 39472a87a47SBartosz Golaszewski static SENSOR_DEVICE_ATTR(update_interval, S_IRUGO | S_IWUSR, 39572a87a47SBartosz Golaszewski ina226_show_interval, ina226_set_interval, 0); 39672a87a47SBartosz Golaszewski 397f7c2fe38SFelten, Lothar /* pointers to created device attributes */ 398468bf0e3SGuenter Roeck static struct attribute *ina2xx_attrs[] = { 399f7c2fe38SFelten, Lothar &sensor_dev_attr_in0_input.dev_attr.attr, 400f7c2fe38SFelten, Lothar &sensor_dev_attr_in1_input.dev_attr.attr, 401f7c2fe38SFelten, Lothar &sensor_dev_attr_curr1_input.dev_attr.attr, 402f7c2fe38SFelten, Lothar &sensor_dev_attr_power1_input.dev_attr.attr, 4038a5fc795SBartosz Golaszewski &sensor_dev_attr_shunt_resistor.dev_attr.attr, 404f7c2fe38SFelten, Lothar NULL, 405f7c2fe38SFelten, Lothar }; 40672a87a47SBartosz Golaszewski 40772a87a47SBartosz Golaszewski static const struct attribute_group ina2xx_group = { 40872a87a47SBartosz Golaszewski .attrs = ina2xx_attrs, 40972a87a47SBartosz Golaszewski }; 41072a87a47SBartosz Golaszewski 41172a87a47SBartosz Golaszewski static struct attribute *ina226_attrs[] = { 41272a87a47SBartosz Golaszewski &sensor_dev_attr_update_interval.dev_attr.attr, 41372a87a47SBartosz Golaszewski NULL, 41472a87a47SBartosz Golaszewski }; 41572a87a47SBartosz Golaszewski 41672a87a47SBartosz Golaszewski static const struct attribute_group ina226_group = { 41772a87a47SBartosz Golaszewski .attrs = ina226_attrs, 41872a87a47SBartosz Golaszewski }; 419f7c2fe38SFelten, Lothar 420f7c2fe38SFelten, Lothar static int ina2xx_probe(struct i2c_client *client, 421f7c2fe38SFelten, Lothar const struct i2c_device_id *id) 422f7c2fe38SFelten, Lothar { 423468bf0e3SGuenter Roeck struct device *dev = &client->dev; 424468bf0e3SGuenter Roeck struct ina2xx_data *data; 425468bf0e3SGuenter Roeck struct device *hwmon_dev; 426468bf0e3SGuenter Roeck u32 val; 42772a87a47SBartosz Golaszewski int ret, group = 0; 428*bd0ddd4dSJavier Martinez Canillas enum ina2xx_ids chip; 429*bd0ddd4dSJavier Martinez Canillas 430*bd0ddd4dSJavier Martinez Canillas if (client->dev.of_node) 431*bd0ddd4dSJavier Martinez Canillas chip = (enum ina2xx_ids)of_device_get_match_data(&client->dev); 432*bd0ddd4dSJavier Martinez Canillas else 433*bd0ddd4dSJavier Martinez Canillas chip = id->driver_data; 434f7c2fe38SFelten, Lothar 435468bf0e3SGuenter Roeck data = devm_kzalloc(dev, sizeof(*data), GFP_KERNEL); 436f7c2fe38SFelten, Lothar if (!data) 437f7c2fe38SFelten, Lothar return -ENOMEM; 438f7c2fe38SFelten, Lothar 439f7c2fe38SFelten, Lothar /* set the device type */ 440*bd0ddd4dSJavier Martinez Canillas data->config = &ina2xx_config[chip]; 44172a87a47SBartosz Golaszewski 442001e2e73SMarc Titinger if (of_property_read_u32(dev->of_node, "shunt-resistor", &val) < 0) { 443001e2e73SMarc Titinger struct ina2xx_platform_data *pdata = dev_get_platdata(dev); 444001e2e73SMarc Titinger 445001e2e73SMarc Titinger if (pdata) 446001e2e73SMarc Titinger val = pdata->shunt_uohms; 447001e2e73SMarc Titinger else 448001e2e73SMarc Titinger val = INA2XX_RSHUNT_DEFAULT; 449001e2e73SMarc Titinger } 450001e2e73SMarc Titinger 451001e2e73SMarc Titinger if (val <= 0 || val > data->config->calibration_factor) 452509416a8SBartosz Golaszewski return -ENODEV; 453509416a8SBartosz Golaszewski 454001e2e73SMarc Titinger data->rshunt = val; 455001e2e73SMarc Titinger 456a0de56c8SMarc Titinger ina2xx_regmap_config.max_register = data->config->registers; 457a0de56c8SMarc Titinger 458a0de56c8SMarc Titinger data->regmap = devm_regmap_init_i2c(client, &ina2xx_regmap_config); 459a0de56c8SMarc Titinger if (IS_ERR(data->regmap)) { 460a0de56c8SMarc Titinger dev_err(dev, "failed to allocate register map\n"); 461a0de56c8SMarc Titinger return PTR_ERR(data->regmap); 462a0de56c8SMarc Titinger } 463a0de56c8SMarc Titinger 464509416a8SBartosz Golaszewski ret = ina2xx_init(data); 465509416a8SBartosz Golaszewski if (ret < 0) { 466509416a8SBartosz Golaszewski dev_err(dev, "error configuring the device: %d\n", ret); 467509416a8SBartosz Golaszewski return -ENODEV; 468509416a8SBartosz Golaszewski } 469509416a8SBartosz Golaszewski 470a0de56c8SMarc Titinger mutex_init(&data->config_lock); 471f7c2fe38SFelten, Lothar 47272a87a47SBartosz Golaszewski data->groups[group++] = &ina2xx_group; 4735aa4e83dSMarc Titinger if (id->driver_data == ina226) 47472a87a47SBartosz Golaszewski data->groups[group++] = &ina226_group; 47572a87a47SBartosz Golaszewski 476468bf0e3SGuenter Roeck hwmon_dev = devm_hwmon_device_register_with_groups(dev, client->name, 47772a87a47SBartosz Golaszewski data, data->groups); 478468bf0e3SGuenter Roeck if (IS_ERR(hwmon_dev)) 479468bf0e3SGuenter Roeck return PTR_ERR(hwmon_dev); 480f7c2fe38SFelten, Lothar 481468bf0e3SGuenter Roeck dev_info(dev, "power monitor %s (Rshunt = %li uOhm)\n", 482509416a8SBartosz Golaszewski id->name, data->rshunt); 4836106db25SGuenter Roeck 484f7c2fe38SFelten, Lothar return 0; 485f7c2fe38SFelten, Lothar } 486f7c2fe38SFelten, Lothar 487f7c2fe38SFelten, Lothar static const struct i2c_device_id ina2xx_id[] = { 488f7c2fe38SFelten, Lothar { "ina219", ina219 }, 489dc92cd0cSGuenter Roeck { "ina220", ina219 }, 490f7c2fe38SFelten, Lothar { "ina226", ina226 }, 491dc92cd0cSGuenter Roeck { "ina230", ina226 }, 492add513beSKevin Hilman { "ina231", ina226 }, 493f7c2fe38SFelten, Lothar { } 494f7c2fe38SFelten, Lothar }; 495f7c2fe38SFelten, Lothar MODULE_DEVICE_TABLE(i2c, ina2xx_id); 496f7c2fe38SFelten, Lothar 497*bd0ddd4dSJavier Martinez Canillas static const struct of_device_id ina2xx_of_match[] = { 498*bd0ddd4dSJavier Martinez Canillas { 499*bd0ddd4dSJavier Martinez Canillas .compatible = "ti,ina219", 500*bd0ddd4dSJavier Martinez Canillas .data = (void *)ina219 501*bd0ddd4dSJavier Martinez Canillas }, 502*bd0ddd4dSJavier Martinez Canillas { 503*bd0ddd4dSJavier Martinez Canillas .compatible = "ti,ina220", 504*bd0ddd4dSJavier Martinez Canillas .data = (void *)ina219 505*bd0ddd4dSJavier Martinez Canillas }, 506*bd0ddd4dSJavier Martinez Canillas { 507*bd0ddd4dSJavier Martinez Canillas .compatible = "ti,ina226", 508*bd0ddd4dSJavier Martinez Canillas .data = (void *)ina226 509*bd0ddd4dSJavier Martinez Canillas }, 510*bd0ddd4dSJavier Martinez Canillas { 511*bd0ddd4dSJavier Martinez Canillas .compatible = "ti,ina230", 512*bd0ddd4dSJavier Martinez Canillas .data = (void *)ina226 513*bd0ddd4dSJavier Martinez Canillas }, 514*bd0ddd4dSJavier Martinez Canillas { 515*bd0ddd4dSJavier Martinez Canillas .compatible = "ti,ina231", 516*bd0ddd4dSJavier Martinez Canillas .data = (void *)ina226 517*bd0ddd4dSJavier Martinez Canillas }, 518*bd0ddd4dSJavier Martinez Canillas { }, 519*bd0ddd4dSJavier Martinez Canillas }; 520*bd0ddd4dSJavier Martinez Canillas MODULE_DEVICE_TABLE(of, ina2xx_of_match); 521*bd0ddd4dSJavier Martinez Canillas 522f7c2fe38SFelten, Lothar static struct i2c_driver ina2xx_driver = { 523f7c2fe38SFelten, Lothar .driver = { 524f7c2fe38SFelten, Lothar .name = "ina2xx", 525*bd0ddd4dSJavier Martinez Canillas .of_match_table = of_match_ptr(ina2xx_of_match), 526f7c2fe38SFelten, Lothar }, 527f7c2fe38SFelten, Lothar .probe = ina2xx_probe, 528f7c2fe38SFelten, Lothar .id_table = ina2xx_id, 529f7c2fe38SFelten, Lothar }; 530f7c2fe38SFelten, Lothar 531d835ca0fSWei Yongjun module_i2c_driver(ina2xx_driver); 532f7c2fe38SFelten, Lothar 533f7c2fe38SFelten, Lothar MODULE_AUTHOR("Lothar Felten <l-felten@ti.com>"); 534f7c2fe38SFelten, Lothar MODULE_DESCRIPTION("ina2xx driver"); 535f7c2fe38SFelten, Lothar MODULE_LICENSE("GPL"); 536