Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
23 changes: 18 additions & 5 deletions Documentation/hwmon/ina2xx.rst
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,16 @@ Supported chips:

https://www.ti.com/

* Texas Instruments INA260

Prefix: 'ina260'

Addresses: I2C 0x40 - 0x4f

Datasheet: Publicly available at the Texas Instruments website

https://www.ti.com/

Author: Lothar Felten <lothar.felten@gmail.com>

Description
Expand All @@ -72,6 +82,9 @@ INA230 and INA231 are high or low side current shunt and power monitors
with an I2C interface. The chips monitor both a shunt voltage drop and
bus supply voltage.

INA260 is a high or low side current and power monitor with integrated shunt
resistor.

The shunt value in micro-ohms can be set via platform data or device tree at
compile-time or via the shunt_resistor attribute in sysfs at run-time. Please
refer to the Documentation/devicetree/bindings/hwmon/ti,ina2xx.yaml for bindings
Expand All @@ -87,16 +100,16 @@ The actual programmed interval may vary from the desired value.
General sysfs entries
---------------------

======================= ===============================
======================= ===============================================
in0_input Shunt voltage(mV) channel
in1_input Bus voltage(mV) channel
curr1_input Current(mA) measurement channel
power1_input Power(uW) measurement channel
shunt_resistor Shunt resistance(uOhm) channel
======================= ===============================
shunt_resistor Shunt resistance(uOhm) channel (not for ina260)
======================= ===============================================

Sysfs entries for ina226, ina230 and ina231 only
------------------------------------------------
Additional sysfs entries for ina226, ina230, ina231, and ina260
---------------------------------------------------------------

======================= ====================================================
curr1_lcrit Critical low current
Expand Down
5 changes: 3 additions & 2 deletions drivers/hwmon/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -2167,11 +2167,12 @@ config SENSORS_INA2XX
select REGMAP_I2C
help
If you say yes here you get support for INA219, INA220, INA226,
INA230, and INA231 power monitor chips.
INA230, INA231, and INA260 power monitor chips.

The INA2xx driver is configured for the default configuration of
the part as described in the datasheet.
Default value for Rshunt is 10 mOhms.
Default value for Rshunt is 10 mOhms except for INA260 which has an
internal 2 mOhm shunt resistor.
This driver can also be built as a module. If so, the module
will be called ina2xx.

Expand Down
45 changes: 41 additions & 4 deletions drivers/hwmon/ina2xx.c
Original file line number Diff line number Diff line change
Expand Up @@ -56,12 +56,14 @@
/* settings - depend on use case */
#define INA219_CONFIG_DEFAULT 0x399F /* PGA=8 */
#define INA226_CONFIG_DEFAULT 0x4527 /* averages=16 */
#define INA260_CONFIG_DEFAULT 0x6527 /* averages=16 */

/* worst case is 68.10 ms (~14.6Hz, ina219) */
#define INA2XX_CONVERSION_RATE 15
#define INA2XX_MAX_DELAY 69 /* worst case delay in ms */

#define INA2XX_RSHUNT_DEFAULT 10000
#define INA260_RSHUNT 2000

/* bit mask for reading the averaging setting in the configuration register */
#define INA226_AVG_RD_MASK GENMASK(11, 9)
Expand Down Expand Up @@ -125,10 +127,12 @@ static const struct regmap_config ina2xx_regmap_config = {
.writeable_reg = ina2xx_writeable_reg,
};

enum ina2xx_ids { ina219, ina226 };
enum ina2xx_ids { ina219, ina226, ina260 };

struct ina2xx_config {
u16 config_default;
bool has_alerts; /* chip supports alerts and limits */
bool has_ishunt; /* chip has internal shunt resistor */
int calibration_value;
int shunt_div;
int bus_voltage_shift;
Expand All @@ -155,6 +159,8 @@ static const struct ina2xx_config ina2xx_config[] = {
.bus_voltage_shift = 3,
.bus_voltage_lsb = 4000,
.power_lsb_factor = 20,
.has_alerts = false,
.has_ishunt = false,
},
[ina226] = {
.config_default = INA226_CONFIG_DEFAULT,
Expand All @@ -163,6 +169,17 @@ static const struct ina2xx_config ina2xx_config[] = {
.bus_voltage_shift = 0,
.bus_voltage_lsb = 1250,
.power_lsb_factor = 25,
.has_alerts = true,
.has_ishunt = false,
},
[ina260] = {
.config_default = INA260_CONFIG_DEFAULT,
.shunt_div = 400,
.bus_voltage_shift = 0,
.bus_voltage_lsb = 1250,
.power_lsb_factor = 8,
.has_alerts = true,
.has_ishunt = true,
},
};

Expand Down Expand Up @@ -254,6 +271,15 @@ static int ina2xx_read_init(struct device *dev, int reg, long *val)
unsigned int regval;
int ret, retry;

if (data->config->has_ishunt) {
/* No calibration needed */
ret = regmap_read(regmap, reg, &regval);
if (ret < 0)
return ret;
*val = ina2xx_get_value(data, reg, regval);
return 0;
}

for (retry = 5; retry; retry--) {
ret = regmap_read(regmap, reg, &regval);
if (ret < 0)
Expand Down Expand Up @@ -682,7 +708,7 @@ static umode_t ina2xx_is_visible(const void *_data, enum hwmon_sensor_types type
case hwmon_chip:
switch (attr) {
case hwmon_chip_update_interval:
if (chip == ina226)
if (chip == ina226 || chip == ina260)
return 0644;
break;
default:
Expand Down Expand Up @@ -791,7 +817,9 @@ static int ina2xx_init(struct device *dev, struct ina2xx_data *data)
u32 shunt;
int ret;

if (device_property_read_u32(dev, "shunt-resistor", &shunt) < 0)
if (data->config->has_ishunt)
shunt = INA260_RSHUNT;
else if (device_property_read_u32(dev, "shunt-resistor", &shunt) < 0)
shunt = INA2XX_RSHUNT_DEFAULT;

ret = ina2xx_set_shunt(data, shunt);
Expand All @@ -811,6 +839,9 @@ static int ina2xx_init(struct device *dev, struct ina2xx_data *data)
FIELD_PREP(INA226_ALERT_POLARITY, active_high));
}

if (data->config->has_ishunt)
return 0;

/*
* Calibration register is set to the best value, which eliminates
* truncation errors on calculating current register in hardware.
Expand Down Expand Up @@ -856,7 +887,8 @@ static int ina2xx_probe(struct i2c_client *client)

hwmon_dev = devm_hwmon_device_register_with_info(dev, client->name,
data, &ina2xx_chip_info,
ina2xx_groups);
data->config->has_ishunt ?
NULL : ina2xx_groups);
if (IS_ERR(hwmon_dev))
return PTR_ERR(hwmon_dev);

Expand All @@ -872,6 +904,7 @@ static const struct i2c_device_id ina2xx_id[] = {
{ "ina226", ina226 },
{ "ina230", ina226 },
{ "ina231", ina226 },
{ "ina260", ina260 },
{ }
};
MODULE_DEVICE_TABLE(i2c, ina2xx_id);
Expand All @@ -897,6 +930,10 @@ static const struct of_device_id __maybe_unused ina2xx_of_match[] = {
.compatible = "ti,ina231",
.data = (void *)ina226
},
{
.compatible = "ti,ina260",
.data = (void *)ina260
},
{ },
};
MODULE_DEVICE_TABLE(of, ina2xx_of_match);
Expand Down