xref: /linux/drivers/hwmon/ina2xx.c (revision 4d5c2d986757e4d6f56761af8ab689218a2bc432)
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>
28814db9f1SGuenter Roeck #include <linux/device.h>
29f7c2fe38SFelten, Lothar #include <linux/err.h>
30f7c2fe38SFelten, Lothar #include <linux/hwmon.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>
38814db9f1SGuenter Roeck #include <linux/sysfs.h>
399e60bb81SGuenter Roeck #include <linux/util_macros.h>
40f7c2fe38SFelten, Lothar 
41f7c2fe38SFelten, Lothar /* common register definitions */
42f7c2fe38SFelten, Lothar #define INA2XX_CONFIG			0x00
43f7c2fe38SFelten, Lothar #define INA2XX_SHUNT_VOLTAGE		0x01 /* readonly */
44f7c2fe38SFelten, Lothar #define INA2XX_BUS_VOLTAGE		0x02 /* readonly */
45f7c2fe38SFelten, Lothar #define INA2XX_POWER			0x03 /* readonly */
46f7c2fe38SFelten, Lothar #define INA2XX_CURRENT			0x04 /* readonly */
47f7c2fe38SFelten, Lothar #define INA2XX_CALIBRATION		0x05
48f7c2fe38SFelten, Lothar 
49f7c2fe38SFelten, Lothar /* INA226 register definitions */
50f7c2fe38SFelten, Lothar #define INA226_MASK_ENABLE		0x06
51f7c2fe38SFelten, Lothar #define INA226_ALERT_LIMIT		0x07
52f7c2fe38SFelten, Lothar #define INA226_DIE_ID			0xFF
53f7c2fe38SFelten, Lothar 
54f7c2fe38SFelten, Lothar #define INA2XX_MAX_REGISTERS		8
55f7c2fe38SFelten, Lothar 
56f7c2fe38SFelten, Lothar /* settings - depend on use case */
57f7c2fe38SFelten, Lothar #define INA219_CONFIG_DEFAULT		0x399F	/* PGA=8 */
58f7c2fe38SFelten, Lothar #define INA226_CONFIG_DEFAULT		0x4527	/* averages=16 */
59f7c2fe38SFelten, Lothar 
60f7c2fe38SFelten, Lothar /* worst case is 68.10 ms (~14.6Hz, ina219) */
61f7c2fe38SFelten, Lothar #define INA2XX_CONVERSION_RATE		15
62509416a8SBartosz Golaszewski #define INA2XX_MAX_DELAY		69 /* worst case delay in ms */
63509416a8SBartosz Golaszewski 
64509416a8SBartosz Golaszewski #define INA2XX_RSHUNT_DEFAULT		10000
65f7c2fe38SFelten, Lothar 
6672a87a47SBartosz Golaszewski /* bit mask for reading the averaging setting in the configuration register */
67232177a3SGuenter Roeck #define INA226_AVG_RD_MASK		GENMASK(11, 9)
6872a87a47SBartosz Golaszewski 
69232177a3SGuenter Roeck #define INA226_READ_AVG(reg)		FIELD_GET(INA226_AVG_RD_MASK, reg)
7072a87a47SBartosz Golaszewski 
71aa7d1763SGuenter Roeck #define INA226_ALERT_LATCH_ENABLE	BIT(0)
7251c6fa32SGuenter Roeck #define INA226_ALERT_POLARITY		BIT(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 /*
8672a87a47SBartosz Golaszewski  * Both bus voltage and shunt voltage conversion times for ina226 are set
8772a87a47SBartosz Golaszewski  * to 0b0100 on POR, which translates to 2200 microseconds in total.
8872a87a47SBartosz Golaszewski  */
8972a87a47SBartosz Golaszewski #define INA226_TOTAL_CONV_TIME_DEFAULT	2200
9072a87a47SBartosz Golaszewski 
91bb25cdc2SGuenter Roeck static bool ina2xx_writeable_reg(struct device *dev, unsigned int reg)
92bb25cdc2SGuenter Roeck {
93bb25cdc2SGuenter Roeck 	switch (reg) {
94bb25cdc2SGuenter Roeck 	case INA2XX_CONFIG:
95bb25cdc2SGuenter Roeck 	case INA2XX_CALIBRATION:
96bb25cdc2SGuenter Roeck 	case INA226_MASK_ENABLE:
97bb25cdc2SGuenter Roeck 	case INA226_ALERT_LIMIT:
98bb25cdc2SGuenter Roeck 		return true;
99bb25cdc2SGuenter Roeck 	default:
100bb25cdc2SGuenter Roeck 		return false;
101bb25cdc2SGuenter Roeck 	}
102bb25cdc2SGuenter Roeck }
103bb25cdc2SGuenter Roeck 
104bb25cdc2SGuenter Roeck static bool ina2xx_volatile_reg(struct device *dev, unsigned int reg)
105bb25cdc2SGuenter Roeck {
106bb25cdc2SGuenter Roeck 	switch (reg) {
107bb25cdc2SGuenter Roeck 	case INA2XX_SHUNT_VOLTAGE:
108bb25cdc2SGuenter Roeck 	case INA2XX_BUS_VOLTAGE:
109bb25cdc2SGuenter Roeck 	case INA2XX_POWER:
110bb25cdc2SGuenter Roeck 	case INA2XX_CURRENT:
111bb25cdc2SGuenter Roeck 		return true;
112bb25cdc2SGuenter Roeck 	default:
113bb25cdc2SGuenter Roeck 		return false;
114bb25cdc2SGuenter Roeck 	}
115bb25cdc2SGuenter Roeck }
116bb25cdc2SGuenter Roeck 
1172bb47652SGuenter Roeck static const struct regmap_config ina2xx_regmap_config = {
118a0de56c8SMarc Titinger 	.reg_bits = 8,
119a0de56c8SMarc Titinger 	.val_bits = 16,
120bb25cdc2SGuenter Roeck 	.use_single_write = true,
121bb25cdc2SGuenter Roeck 	.use_single_read = true,
1222bb47652SGuenter Roeck 	.max_register = INA2XX_MAX_REGISTERS,
123bb25cdc2SGuenter Roeck 	.cache_type = REGCACHE_MAPLE,
124bb25cdc2SGuenter Roeck 	.volatile_reg = ina2xx_volatile_reg,
125bb25cdc2SGuenter Roeck 	.writeable_reg = ina2xx_writeable_reg,
126a0de56c8SMarc Titinger };
127a0de56c8SMarc Titinger 
128f7c2fe38SFelten, Lothar enum ina2xx_ids { ina219, ina226 };
129f7c2fe38SFelten, Lothar 
1306106db25SGuenter Roeck struct ina2xx_config {
1316106db25SGuenter Roeck 	u16 config_default;
1325d389b12SMaciej Purski 	int calibration_value;
1336106db25SGuenter Roeck 	int shunt_div;
1346106db25SGuenter Roeck 	int bus_voltage_shift;
1356106db25SGuenter Roeck 	int bus_voltage_lsb;	/* uV */
1365d389b12SMaciej Purski 	int power_lsb_factor;
1376106db25SGuenter Roeck };
1386106db25SGuenter Roeck 
139f7c2fe38SFelten, Lothar struct ina2xx_data {
1406106db25SGuenter Roeck 	const struct ina2xx_config *config;
14151c6fa32SGuenter Roeck 	enum ina2xx_ids chip;
142f7c2fe38SFelten, Lothar 
143509416a8SBartosz Golaszewski 	long rshunt;
1445d389b12SMaciej Purski 	long current_lsb_uA;
1455d389b12SMaciej Purski 	long power_lsb_uW;
146a0de56c8SMarc Titinger 	struct mutex config_lock;
147a0de56c8SMarc Titinger 	struct regmap *regmap;
148f7c2fe38SFelten, Lothar };
149f7c2fe38SFelten, Lothar 
1506106db25SGuenter Roeck static const struct ina2xx_config ina2xx_config[] = {
1516106db25SGuenter Roeck 	[ina219] = {
1526106db25SGuenter Roeck 		.config_default = INA219_CONFIG_DEFAULT,
1535d389b12SMaciej Purski 		.calibration_value = 4096,
1546106db25SGuenter Roeck 		.shunt_div = 100,
1556106db25SGuenter Roeck 		.bus_voltage_shift = 3,
1566106db25SGuenter Roeck 		.bus_voltage_lsb = 4000,
1575d389b12SMaciej Purski 		.power_lsb_factor = 20,
1586106db25SGuenter Roeck 	},
1596106db25SGuenter Roeck 	[ina226] = {
1606106db25SGuenter Roeck 		.config_default = INA226_CONFIG_DEFAULT,
1615d389b12SMaciej Purski 		.calibration_value = 2048,
1626106db25SGuenter Roeck 		.shunt_div = 400,
1636106db25SGuenter Roeck 		.bus_voltage_shift = 0,
1646106db25SGuenter Roeck 		.bus_voltage_lsb = 1250,
1655d389b12SMaciej Purski 		.power_lsb_factor = 25,
1666106db25SGuenter Roeck 	},
1676106db25SGuenter Roeck };
1686106db25SGuenter Roeck 
16972a87a47SBartosz Golaszewski /*
17072a87a47SBartosz Golaszewski  * Available averaging rates for ina226. The indices correspond with
17172a87a47SBartosz Golaszewski  * the bit values expected by the chip (according to the ina226 datasheet,
17272a87a47SBartosz Golaszewski  * table 3 AVG bit settings, found at
17349dc2fb0SAlexander A. Klimov  * https://www.ti.com/lit/ds/symlink/ina226.pdf.
17472a87a47SBartosz Golaszewski  */
17572a87a47SBartosz Golaszewski static const int ina226_avg_tab[] = { 1, 4, 16, 64, 128, 256, 512, 1024 };
17672a87a47SBartosz Golaszewski 
17772a87a47SBartosz Golaszewski static int ina226_reg_to_interval(u16 config)
17872a87a47SBartosz Golaszewski {
17972a87a47SBartosz Golaszewski 	int avg = ina226_avg_tab[INA226_READ_AVG(config)];
18072a87a47SBartosz Golaszewski 
18172a87a47SBartosz Golaszewski 	/*
18272a87a47SBartosz Golaszewski 	 * Multiply the total conversion time by the number of averages.
18372a87a47SBartosz Golaszewski 	 * Return the result in milliseconds.
18472a87a47SBartosz Golaszewski 	 */
18572a87a47SBartosz Golaszewski 	return DIV_ROUND_CLOSEST(avg * INA226_TOTAL_CONV_TIME_DEFAULT, 1000);
18672a87a47SBartosz Golaszewski }
18772a87a47SBartosz Golaszewski 
188a0de56c8SMarc Titinger /*
189a0de56c8SMarc Titinger  * Return the new, shifted AVG field value of CONFIG register,
190a0de56c8SMarc Titinger  * to use with regmap_update_bits
191a0de56c8SMarc Titinger  */
192814db9f1SGuenter Roeck static u16 ina226_interval_to_reg(long interval)
19372a87a47SBartosz Golaszewski {
19472a87a47SBartosz Golaszewski 	int avg, avg_bits;
19572a87a47SBartosz Golaszewski 
196ab7fbee4SGuenter Roeck 	/*
197ab7fbee4SGuenter Roeck 	 * The maximum supported interval is 1,024 * (2 * 8.244ms) ~= 16.8s.
198ab7fbee4SGuenter Roeck 	 * Clamp to 32 seconds before calculations to avoid overflows.
199ab7fbee4SGuenter Roeck 	 */
200ab7fbee4SGuenter Roeck 	interval = clamp_val(interval, 0, 32000);
201ab7fbee4SGuenter Roeck 
20272a87a47SBartosz Golaszewski 	avg = DIV_ROUND_CLOSEST(interval * 1000,
20372a87a47SBartosz Golaszewski 				INA226_TOTAL_CONV_TIME_DEFAULT);
204d38df34eSBartosz Golaszewski 	avg_bits = find_closest(avg, ina226_avg_tab,
205d38df34eSBartosz Golaszewski 				ARRAY_SIZE(ina226_avg_tab));
20672a87a47SBartosz Golaszewski 
207232177a3SGuenter Roeck 	return FIELD_PREP(INA226_AVG_RD_MASK, avg_bits);
20872a87a47SBartosz Golaszewski }
20972a87a47SBartosz Golaszewski 
210c263d916SGuenter Roeck static int ina2xx_get_value(struct ina2xx_data *data, u8 reg,
211c263d916SGuenter Roeck 			    unsigned int regval)
212c263d916SGuenter Roeck {
213c263d916SGuenter Roeck 	int val;
214c263d916SGuenter Roeck 
215c263d916SGuenter Roeck 	switch (reg) {
216c263d916SGuenter Roeck 	case INA2XX_SHUNT_VOLTAGE:
217c263d916SGuenter Roeck 		/* signed register */
218c263d916SGuenter Roeck 		val = DIV_ROUND_CLOSEST((s16)regval, data->config->shunt_div);
219c263d916SGuenter Roeck 		break;
220c263d916SGuenter Roeck 	case INA2XX_BUS_VOLTAGE:
221c263d916SGuenter Roeck 		val = (regval >> data->config->bus_voltage_shift) *
222c263d916SGuenter Roeck 		  data->config->bus_voltage_lsb;
223c263d916SGuenter Roeck 		val = DIV_ROUND_CLOSEST(val, 1000);
224c263d916SGuenter Roeck 		break;
225c263d916SGuenter Roeck 	case INA2XX_POWER:
226c263d916SGuenter Roeck 		val = regval * data->power_lsb_uW;
227c263d916SGuenter Roeck 		break;
228c263d916SGuenter Roeck 	case INA2XX_CURRENT:
229c263d916SGuenter Roeck 		/* signed register, result in mA */
230c263d916SGuenter Roeck 		val = (s16)regval * data->current_lsb_uA;
231c263d916SGuenter Roeck 		val = DIV_ROUND_CLOSEST(val, 1000);
232c263d916SGuenter Roeck 		break;
233c263d916SGuenter Roeck 	case INA2XX_CALIBRATION:
234c263d916SGuenter Roeck 		val = regval;
235c263d916SGuenter Roeck 		break;
236c263d916SGuenter Roeck 	default:
237c263d916SGuenter Roeck 		/* programmer goofed */
238c263d916SGuenter Roeck 		WARN_ON_ONCE(1);
239c263d916SGuenter Roeck 		val = 0;
240c263d916SGuenter Roeck 		break;
241c263d916SGuenter Roeck 	}
242c263d916SGuenter Roeck 
243c263d916SGuenter Roeck 	return val;
244c263d916SGuenter Roeck }
245c263d916SGuenter Roeck 
246814db9f1SGuenter Roeck /*
247814db9f1SGuenter Roeck  * Read and convert register value from chip. If the register value is 0,
248814db9f1SGuenter Roeck  * check if the chip has been power cycled or reset. If so, re-initialize it.
249814db9f1SGuenter Roeck  */
250814db9f1SGuenter Roeck static int ina2xx_read_init(struct device *dev, int reg, long *val)
251f7c2fe38SFelten, Lothar {
252468bf0e3SGuenter Roeck 	struct ina2xx_data *data = dev_get_drvdata(dev);
253d491e781SGuenter Roeck 	struct regmap *regmap = data->regmap;
254814db9f1SGuenter Roeck 	unsigned int regval;
255a0de56c8SMarc Titinger 	int ret, retry;
256509416a8SBartosz Golaszewski 
257509416a8SBartosz Golaszewski 	for (retry = 5; retry; retry--) {
258814db9f1SGuenter Roeck 		ret = regmap_read(regmap, reg, &regval);
259a0de56c8SMarc Titinger 		if (ret < 0)
260a0de56c8SMarc Titinger 			return ret;
261a0de56c8SMarc Titinger 
262509416a8SBartosz Golaszewski 		/*
263509416a8SBartosz Golaszewski 		 * If the current value in the calibration register is 0, the
264509416a8SBartosz Golaszewski 		 * power and current registers will also remain at 0. In case
265509416a8SBartosz Golaszewski 		 * the chip has been reset let's check the calibration
266509416a8SBartosz Golaszewski 		 * register and reinitialize if needed.
267a0de56c8SMarc Titinger 		 * We do that extra read of the calibration register if there
268a0de56c8SMarc Titinger 		 * is some hint of a chip reset.
269509416a8SBartosz Golaszewski 		 */
270814db9f1SGuenter Roeck 		if (regval == 0) {
271a0de56c8SMarc Titinger 			unsigned int cal;
272a0de56c8SMarc Titinger 
273bb25cdc2SGuenter Roeck 			ret = regmap_read_bypassed(regmap, INA2XX_CALIBRATION, &cal);
274a0de56c8SMarc Titinger 			if (ret < 0)
275a0de56c8SMarc Titinger 				return ret;
276a0de56c8SMarc Titinger 
277a0de56c8SMarc Titinger 			if (cal == 0) {
278509416a8SBartosz Golaszewski 				dev_warn(dev, "chip not calibrated, reinitializing\n");
279509416a8SBartosz Golaszewski 
280bb25cdc2SGuenter Roeck 				regcache_mark_dirty(regmap);
281bb25cdc2SGuenter Roeck 				regcache_sync(regmap);
282bb25cdc2SGuenter Roeck 
283509416a8SBartosz Golaszewski 				/*
284a0de56c8SMarc Titinger 				 * Let's make sure the power and current
285a0de56c8SMarc Titinger 				 * registers have been updated before trying
286a0de56c8SMarc Titinger 				 * again.
287509416a8SBartosz Golaszewski 				 */
288509416a8SBartosz Golaszewski 				msleep(INA2XX_MAX_DELAY);
289509416a8SBartosz Golaszewski 				continue;
290509416a8SBartosz Golaszewski 			}
291a0de56c8SMarc Titinger 		}
292814db9f1SGuenter Roeck 		*val = ina2xx_get_value(data, reg, regval);
293509416a8SBartosz Golaszewski 		return 0;
294509416a8SBartosz Golaszewski 	}
295509416a8SBartosz Golaszewski 
296509416a8SBartosz Golaszewski 	/*
297509416a8SBartosz Golaszewski 	 * If we're here then although all write operations succeeded, the
298509416a8SBartosz Golaszewski 	 * chip still returns 0 in the calibration register. Nothing more we
299509416a8SBartosz Golaszewski 	 * can do here.
300509416a8SBartosz Golaszewski 	 */
301509416a8SBartosz Golaszewski 	dev_err(dev, "unable to reinitialize the chip\n");
302509416a8SBartosz Golaszewski 	return -ENODEV;
303509416a8SBartosz Golaszewski }
304509416a8SBartosz Golaszewski 
3055a56a39bSAlex Qiu /*
3065a56a39bSAlex Qiu  * Turns alert limit values into register values.
3075a56a39bSAlex Qiu  * Opposite of the formula in ina2xx_get_value().
3085a56a39bSAlex Qiu  */
309*4d5c2d98SGuenter Roeck static u16 ina226_alert_to_reg(struct ina2xx_data *data, int reg, long val)
3105a56a39bSAlex Qiu {
3119965ebd1SGuenter Roeck 	switch (reg) {
3129965ebd1SGuenter Roeck 	case INA2XX_SHUNT_VOLTAGE:
313ab7fbee4SGuenter Roeck 		val = clamp_val(val, 0, SHRT_MAX * data->config->shunt_div);
3145a56a39bSAlex Qiu 		val *= data->config->shunt_div;
315ab7fbee4SGuenter Roeck 		return clamp_val(val, 0, SHRT_MAX);
3169965ebd1SGuenter Roeck 	case INA2XX_BUS_VOLTAGE:
317ab7fbee4SGuenter Roeck 		val = clamp_val(val, 0, 200000);
3185a56a39bSAlex Qiu 		val = (val * 1000) << data->config->bus_voltage_shift;
3195a56a39bSAlex Qiu 		val = DIV_ROUND_CLOSEST(val, data->config->bus_voltage_lsb);
320ab7fbee4SGuenter Roeck 		return clamp_val(val, 0, USHRT_MAX);
3219965ebd1SGuenter Roeck 	case INA2XX_POWER:
322ab7fbee4SGuenter Roeck 		val = clamp_val(val, 0, UINT_MAX - data->power_lsb_uW);
3235a56a39bSAlex Qiu 		val = DIV_ROUND_CLOSEST(val, data->power_lsb_uW);
3245a56a39bSAlex Qiu 		return clamp_val(val, 0, USHRT_MAX);
325*4d5c2d98SGuenter Roeck 	case INA2XX_CURRENT:
326*4d5c2d98SGuenter Roeck 		val = clamp_val(val, INT_MIN / 1000, INT_MAX / 1000);
327*4d5c2d98SGuenter Roeck 		/* signed register, result in mA */
328*4d5c2d98SGuenter Roeck 		val = DIV_ROUND_CLOSEST(val * 1000, data->current_lsb_uA);
329*4d5c2d98SGuenter Roeck 		return clamp_val(val, SHRT_MIN, SHRT_MAX);
3305a56a39bSAlex Qiu 	default:
3315a56a39bSAlex Qiu 		/* programmer goofed */
3325a56a39bSAlex Qiu 		WARN_ON_ONCE(1);
3335a56a39bSAlex Qiu 		return 0;
3345a56a39bSAlex Qiu 	}
3355a56a39bSAlex Qiu }
3365a56a39bSAlex Qiu 
337814db9f1SGuenter Roeck static int ina226_alert_limit_read(struct ina2xx_data *data, u32 mask, int reg, long *val)
3385a56a39bSAlex Qiu {
339d491e781SGuenter Roeck 	struct regmap *regmap = data->regmap;
3405a56a39bSAlex Qiu 	int regval;
3415a56a39bSAlex Qiu 	int ret;
3425a56a39bSAlex Qiu 
3435a56a39bSAlex Qiu 	mutex_lock(&data->config_lock);
344d491e781SGuenter Roeck 	ret = regmap_read(regmap, INA226_MASK_ENABLE, &regval);
3455a56a39bSAlex Qiu 	if (ret)
3465a56a39bSAlex Qiu 		goto abort;
3475a56a39bSAlex Qiu 
348814db9f1SGuenter Roeck 	if (regval & mask) {
349d491e781SGuenter Roeck 		ret = regmap_read(regmap, INA226_ALERT_LIMIT, &regval);
3505a56a39bSAlex Qiu 		if (ret)
3515a56a39bSAlex Qiu 			goto abort;
352814db9f1SGuenter Roeck 		*val = ina2xx_get_value(data, reg, regval);
353814db9f1SGuenter Roeck 	} else {
354814db9f1SGuenter Roeck 		*val = 0;
3555a56a39bSAlex Qiu 	}
3565a56a39bSAlex Qiu abort:
3575a56a39bSAlex Qiu 	mutex_unlock(&data->config_lock);
3585a56a39bSAlex Qiu 	return ret;
3595a56a39bSAlex Qiu }
3605a56a39bSAlex Qiu 
3619965ebd1SGuenter Roeck static int ina226_alert_limit_write(struct ina2xx_data *data, u32 mask, int reg, long val)
3625a56a39bSAlex Qiu {
363d491e781SGuenter Roeck 	struct regmap *regmap = data->regmap;
3645a56a39bSAlex Qiu 	int ret;
3655a56a39bSAlex Qiu 
366814db9f1SGuenter Roeck 	if (val < 0)
367814db9f1SGuenter Roeck 		return -EINVAL;
3685a56a39bSAlex Qiu 
3695a56a39bSAlex Qiu 	/*
3705a56a39bSAlex Qiu 	 * Clear all alerts first to avoid accidentally triggering ALERT pin
3715a56a39bSAlex Qiu 	 * due to register write sequence. Then, only enable the alert
3725a56a39bSAlex Qiu 	 * if the value is non-zero.
3735a56a39bSAlex Qiu 	 */
3745a56a39bSAlex Qiu 	mutex_lock(&data->config_lock);
375d491e781SGuenter Roeck 	ret = regmap_update_bits(regmap, INA226_MASK_ENABLE,
3765a56a39bSAlex Qiu 				 INA226_ALERT_CONFIG_MASK, 0);
3775a56a39bSAlex Qiu 	if (ret < 0)
3785a56a39bSAlex Qiu 		goto abort;
3795a56a39bSAlex Qiu 
380d491e781SGuenter Roeck 	ret = regmap_write(regmap, INA226_ALERT_LIMIT,
3819965ebd1SGuenter Roeck 			   ina226_alert_to_reg(data, reg, val));
3825a56a39bSAlex Qiu 	if (ret < 0)
3835a56a39bSAlex Qiu 		goto abort;
3845a56a39bSAlex Qiu 
385814db9f1SGuenter Roeck 	if (val)
386d491e781SGuenter Roeck 		ret = regmap_update_bits(regmap, INA226_MASK_ENABLE,
387814db9f1SGuenter Roeck 					 INA226_ALERT_CONFIG_MASK, mask);
3885a56a39bSAlex Qiu abort:
3895a56a39bSAlex Qiu 	mutex_unlock(&data->config_lock);
3905a56a39bSAlex Qiu 	return ret;
3915a56a39bSAlex Qiu }
3925a56a39bSAlex Qiu 
393814db9f1SGuenter Roeck static int ina2xx_chip_read(struct device *dev, u32 attr, long *val)
3945a56a39bSAlex Qiu {
3955a56a39bSAlex Qiu 	struct ina2xx_data *data = dev_get_drvdata(dev);
396814db9f1SGuenter Roeck 	u32 regval;
3975a56a39bSAlex Qiu 	int ret;
3985a56a39bSAlex Qiu 
399814db9f1SGuenter Roeck 	switch (attr) {
400814db9f1SGuenter Roeck 	case hwmon_chip_update_interval:
401814db9f1SGuenter Roeck 		ret = regmap_read(data->regmap, INA2XX_CONFIG, &regval);
4025a56a39bSAlex Qiu 		if (ret)
4035a56a39bSAlex Qiu 			return ret;
4045a56a39bSAlex Qiu 
405814db9f1SGuenter Roeck 		*val = ina226_reg_to_interval(regval);
406814db9f1SGuenter Roeck 		break;
407814db9f1SGuenter Roeck 	default:
408814db9f1SGuenter Roeck 		return -EOPNOTSUPP;
4095a56a39bSAlex Qiu 	}
410814db9f1SGuenter Roeck 	return 0;
411814db9f1SGuenter Roeck }
412814db9f1SGuenter Roeck 
413814db9f1SGuenter Roeck static int ina226_alert_read(struct regmap *regmap, u32 mask, long *val)
414814db9f1SGuenter Roeck {
415814db9f1SGuenter Roeck 	unsigned int regval;
416814db9f1SGuenter Roeck 	int ret;
417814db9f1SGuenter Roeck 
418814db9f1SGuenter Roeck 	ret = regmap_read_bypassed(regmap, INA226_MASK_ENABLE, &regval);
419814db9f1SGuenter Roeck 	if (ret)
420814db9f1SGuenter Roeck 		return ret;
421814db9f1SGuenter Roeck 
422814db9f1SGuenter Roeck 	*val = (regval & mask) && (regval & INA226_ALERT_FUNCTION_FLAG);
423814db9f1SGuenter Roeck 
424814db9f1SGuenter Roeck 	return 0;
425814db9f1SGuenter Roeck }
426814db9f1SGuenter Roeck 
427814db9f1SGuenter Roeck static int ina2xx_in_read(struct device *dev, u32 attr, int channel, long *val)
428814db9f1SGuenter Roeck {
429814db9f1SGuenter Roeck 	int voltage_reg = channel ? INA2XX_BUS_VOLTAGE : INA2XX_SHUNT_VOLTAGE;
430814db9f1SGuenter Roeck 	u32 under_voltage_mask = channel ? INA226_BUS_UNDER_VOLTAGE_MASK
431814db9f1SGuenter Roeck 					 : INA226_SHUNT_UNDER_VOLTAGE_MASK;
432814db9f1SGuenter Roeck 	u32 over_voltage_mask = channel ? INA226_BUS_OVER_VOLTAGE_MASK
433814db9f1SGuenter Roeck 					: INA226_SHUNT_OVER_VOLTAGE_MASK;
434814db9f1SGuenter Roeck 	struct ina2xx_data *data = dev_get_drvdata(dev);
435814db9f1SGuenter Roeck 	struct regmap *regmap = data->regmap;
436814db9f1SGuenter Roeck 	unsigned int regval;
437814db9f1SGuenter Roeck 	int ret;
438814db9f1SGuenter Roeck 
439814db9f1SGuenter Roeck 	switch (attr) {
440814db9f1SGuenter Roeck 	case hwmon_in_input:
441814db9f1SGuenter Roeck 		ret = regmap_read(regmap, voltage_reg, &regval);
442814db9f1SGuenter Roeck 		if (ret)
443814db9f1SGuenter Roeck 			return ret;
444814db9f1SGuenter Roeck 		*val = ina2xx_get_value(data, voltage_reg, regval);
445814db9f1SGuenter Roeck 		break;
446814db9f1SGuenter Roeck 	case hwmon_in_lcrit:
447814db9f1SGuenter Roeck 		return ina226_alert_limit_read(data, under_voltage_mask,
448814db9f1SGuenter Roeck 					       voltage_reg, val);
449814db9f1SGuenter Roeck 	case hwmon_in_crit:
450814db9f1SGuenter Roeck 		return ina226_alert_limit_read(data, over_voltage_mask,
451814db9f1SGuenter Roeck 					       voltage_reg, val);
452814db9f1SGuenter Roeck 	case hwmon_in_lcrit_alarm:
453814db9f1SGuenter Roeck 		return ina226_alert_read(regmap, under_voltage_mask, val);
454814db9f1SGuenter Roeck 	case hwmon_in_crit_alarm:
455814db9f1SGuenter Roeck 		return ina226_alert_read(regmap, over_voltage_mask, val);
456814db9f1SGuenter Roeck 	default:
457814db9f1SGuenter Roeck 		return -EOPNOTSUPP;
458814db9f1SGuenter Roeck 	}
459814db9f1SGuenter Roeck 	return 0;
460814db9f1SGuenter Roeck }
461814db9f1SGuenter Roeck 
462814db9f1SGuenter Roeck static int ina2xx_power_read(struct device *dev, u32 attr, long *val)
463814db9f1SGuenter Roeck {
464814db9f1SGuenter Roeck 	struct ina2xx_data *data = dev_get_drvdata(dev);
465814db9f1SGuenter Roeck 
466814db9f1SGuenter Roeck 	switch (attr) {
467814db9f1SGuenter Roeck 	case hwmon_power_input:
468814db9f1SGuenter Roeck 		return ina2xx_read_init(dev, INA2XX_POWER, val);
469814db9f1SGuenter Roeck 	case hwmon_power_crit:
470814db9f1SGuenter Roeck 		return ina226_alert_limit_read(data, INA226_POWER_OVER_LIMIT_MASK,
471814db9f1SGuenter Roeck 					       INA2XX_POWER, val);
472814db9f1SGuenter Roeck 	case hwmon_power_crit_alarm:
473814db9f1SGuenter Roeck 		return ina226_alert_read(data->regmap, INA226_POWER_OVER_LIMIT_MASK, val);
474814db9f1SGuenter Roeck 	default:
475814db9f1SGuenter Roeck 		return -EOPNOTSUPP;
476814db9f1SGuenter Roeck 	}
477814db9f1SGuenter Roeck }
478814db9f1SGuenter Roeck 
479814db9f1SGuenter Roeck static int ina2xx_curr_read(struct device *dev, u32 attr, long *val)
480814db9f1SGuenter Roeck {
481*4d5c2d98SGuenter Roeck 	struct ina2xx_data *data = dev_get_drvdata(dev);
482*4d5c2d98SGuenter Roeck 	struct regmap *regmap = data->regmap;
483*4d5c2d98SGuenter Roeck 
484*4d5c2d98SGuenter Roeck 	/*
485*4d5c2d98SGuenter Roeck 	 * While the chips supported by this driver do not directly support
486*4d5c2d98SGuenter Roeck 	 * current limits, they do support setting shunt voltage limits.
487*4d5c2d98SGuenter Roeck 	 * The shunt voltage divided by the shunt resistor value is the current.
488*4d5c2d98SGuenter Roeck 	 * On top of that, calibration values are set such that in the shunt
489*4d5c2d98SGuenter Roeck 	 * voltage register and the current register report the same values.
490*4d5c2d98SGuenter Roeck 	 * That means we can report and configure current limits based on shunt
491*4d5c2d98SGuenter Roeck 	 * voltage limits.
492*4d5c2d98SGuenter Roeck 	 */
493814db9f1SGuenter Roeck 	switch (attr) {
494814db9f1SGuenter Roeck 	case hwmon_curr_input:
495814db9f1SGuenter Roeck 		return ina2xx_read_init(dev, INA2XX_CURRENT, val);
496*4d5c2d98SGuenter Roeck 	case hwmon_curr_lcrit:
497*4d5c2d98SGuenter Roeck 		return ina226_alert_limit_read(data, INA226_SHUNT_UNDER_VOLTAGE_MASK,
498*4d5c2d98SGuenter Roeck 					       INA2XX_CURRENT, val);
499*4d5c2d98SGuenter Roeck 	case hwmon_curr_crit:
500*4d5c2d98SGuenter Roeck 		return ina226_alert_limit_read(data, INA226_SHUNT_OVER_VOLTAGE_MASK,
501*4d5c2d98SGuenter Roeck 					       INA2XX_CURRENT, val);
502*4d5c2d98SGuenter Roeck 	case hwmon_curr_lcrit_alarm:
503*4d5c2d98SGuenter Roeck 		return ina226_alert_read(regmap, INA226_SHUNT_UNDER_VOLTAGE_MASK, val);
504*4d5c2d98SGuenter Roeck 	case hwmon_curr_crit_alarm:
505*4d5c2d98SGuenter Roeck 		return ina226_alert_read(regmap, INA226_SHUNT_OVER_VOLTAGE_MASK, val);
506814db9f1SGuenter Roeck 	default:
507814db9f1SGuenter Roeck 		return -EOPNOTSUPP;
508814db9f1SGuenter Roeck 	}
509814db9f1SGuenter Roeck }
510814db9f1SGuenter Roeck 
511814db9f1SGuenter Roeck static int ina2xx_read(struct device *dev, enum hwmon_sensor_types type,
512814db9f1SGuenter Roeck 		       u32 attr, int channel, long *val)
513814db9f1SGuenter Roeck {
514814db9f1SGuenter Roeck 	switch (type) {
515814db9f1SGuenter Roeck 	case hwmon_chip:
516814db9f1SGuenter Roeck 		return ina2xx_chip_read(dev, attr, val);
517814db9f1SGuenter Roeck 	case hwmon_in:
518814db9f1SGuenter Roeck 		return ina2xx_in_read(dev, attr, channel, val);
519814db9f1SGuenter Roeck 	case hwmon_power:
520814db9f1SGuenter Roeck 		return ina2xx_power_read(dev, attr, val);
521814db9f1SGuenter Roeck 	case hwmon_curr:
522814db9f1SGuenter Roeck 		return ina2xx_curr_read(dev, attr, val);
523814db9f1SGuenter Roeck 	default:
524814db9f1SGuenter Roeck 		return -EOPNOTSUPP;
525814db9f1SGuenter Roeck 	}
526814db9f1SGuenter Roeck }
527814db9f1SGuenter Roeck 
528814db9f1SGuenter Roeck static int ina2xx_chip_write(struct device *dev, u32 attr, long val)
529814db9f1SGuenter Roeck {
530814db9f1SGuenter Roeck 	struct ina2xx_data *data = dev_get_drvdata(dev);
531814db9f1SGuenter Roeck 
532814db9f1SGuenter Roeck 	switch (attr) {
533814db9f1SGuenter Roeck 	case hwmon_chip_update_interval:
534814db9f1SGuenter Roeck 		return regmap_update_bits(data->regmap, INA2XX_CONFIG,
535814db9f1SGuenter Roeck 					  INA226_AVG_RD_MASK,
536814db9f1SGuenter Roeck 					  ina226_interval_to_reg(val));
537814db9f1SGuenter Roeck 	default:
538814db9f1SGuenter Roeck 		return -EOPNOTSUPP;
539814db9f1SGuenter Roeck 	}
540814db9f1SGuenter Roeck }
541814db9f1SGuenter Roeck 
542814db9f1SGuenter Roeck static int ina2xx_in_write(struct device *dev, u32 attr, int channel, long val)
543814db9f1SGuenter Roeck {
544814db9f1SGuenter Roeck 	struct ina2xx_data *data = dev_get_drvdata(dev);
545814db9f1SGuenter Roeck 
546814db9f1SGuenter Roeck 	switch (attr) {
547814db9f1SGuenter Roeck 	case hwmon_in_lcrit:
548814db9f1SGuenter Roeck 		return ina226_alert_limit_write(data,
549814db9f1SGuenter Roeck 			channel ? INA226_BUS_UNDER_VOLTAGE_MASK : INA226_SHUNT_UNDER_VOLTAGE_MASK,
5509965ebd1SGuenter Roeck 			channel ? INA2XX_BUS_VOLTAGE : INA2XX_SHUNT_VOLTAGE,
551814db9f1SGuenter Roeck 			val);
552814db9f1SGuenter Roeck 	case hwmon_in_crit:
553814db9f1SGuenter Roeck 		return ina226_alert_limit_write(data,
554814db9f1SGuenter Roeck 			channel ? INA226_BUS_OVER_VOLTAGE_MASK : INA226_SHUNT_OVER_VOLTAGE_MASK,
5559965ebd1SGuenter Roeck 			channel ? INA2XX_BUS_VOLTAGE : INA2XX_SHUNT_VOLTAGE,
556814db9f1SGuenter Roeck 			val);
557814db9f1SGuenter Roeck 	default:
558814db9f1SGuenter Roeck 		return -EOPNOTSUPP;
559814db9f1SGuenter Roeck 	}
560814db9f1SGuenter Roeck 	return 0;
561814db9f1SGuenter Roeck }
562814db9f1SGuenter Roeck 
563814db9f1SGuenter Roeck static int ina2xx_power_write(struct device *dev, u32 attr, long val)
564814db9f1SGuenter Roeck {
565814db9f1SGuenter Roeck 	struct ina2xx_data *data = dev_get_drvdata(dev);
566814db9f1SGuenter Roeck 
567814db9f1SGuenter Roeck 	switch (attr) {
568814db9f1SGuenter Roeck 	case hwmon_power_crit:
5699965ebd1SGuenter Roeck 		return ina226_alert_limit_write(data, INA226_POWER_OVER_LIMIT_MASK,
5709965ebd1SGuenter Roeck 						INA2XX_POWER, val);
571814db9f1SGuenter Roeck 	default:
572814db9f1SGuenter Roeck 		return -EOPNOTSUPP;
573814db9f1SGuenter Roeck 	}
574814db9f1SGuenter Roeck 	return 0;
575814db9f1SGuenter Roeck }
576814db9f1SGuenter Roeck 
577*4d5c2d98SGuenter Roeck static int ina2xx_curr_write(struct device *dev, u32 attr, long val)
578*4d5c2d98SGuenter Roeck {
579*4d5c2d98SGuenter Roeck 	struct ina2xx_data *data = dev_get_drvdata(dev);
580*4d5c2d98SGuenter Roeck 
581*4d5c2d98SGuenter Roeck 	switch (attr) {
582*4d5c2d98SGuenter Roeck 	case hwmon_curr_lcrit:
583*4d5c2d98SGuenter Roeck 		return ina226_alert_limit_write(data, INA226_SHUNT_UNDER_VOLTAGE_MASK,
584*4d5c2d98SGuenter Roeck 						INA2XX_CURRENT, val);
585*4d5c2d98SGuenter Roeck 	case hwmon_curr_crit:
586*4d5c2d98SGuenter Roeck 		return ina226_alert_limit_write(data, INA226_SHUNT_OVER_VOLTAGE_MASK,
587*4d5c2d98SGuenter Roeck 						INA2XX_CURRENT, val);
588*4d5c2d98SGuenter Roeck 	default:
589*4d5c2d98SGuenter Roeck 		return -EOPNOTSUPP;
590*4d5c2d98SGuenter Roeck 	}
591*4d5c2d98SGuenter Roeck 	return 0;
592*4d5c2d98SGuenter Roeck }
593*4d5c2d98SGuenter Roeck 
594814db9f1SGuenter Roeck static int ina2xx_write(struct device *dev, enum hwmon_sensor_types type,
595814db9f1SGuenter Roeck 			u32 attr, int channel, long val)
596814db9f1SGuenter Roeck {
597814db9f1SGuenter Roeck 	switch (type) {
598814db9f1SGuenter Roeck 	case hwmon_chip:
599814db9f1SGuenter Roeck 		return ina2xx_chip_write(dev, attr, val);
600814db9f1SGuenter Roeck 	case hwmon_in:
601814db9f1SGuenter Roeck 		return ina2xx_in_write(dev, attr, channel, val);
602814db9f1SGuenter Roeck 	case hwmon_power:
603814db9f1SGuenter Roeck 		return ina2xx_power_write(dev, attr, val);
604*4d5c2d98SGuenter Roeck 	case hwmon_curr:
605*4d5c2d98SGuenter Roeck 		return ina2xx_curr_write(dev, attr, val);
606814db9f1SGuenter Roeck 	default:
607814db9f1SGuenter Roeck 		return -EOPNOTSUPP;
608814db9f1SGuenter Roeck 	}
609814db9f1SGuenter Roeck }
610814db9f1SGuenter Roeck 
611814db9f1SGuenter Roeck static umode_t ina2xx_is_visible(const void *_data, enum hwmon_sensor_types type,
612814db9f1SGuenter Roeck 				 u32 attr, int channel)
613814db9f1SGuenter Roeck {
614814db9f1SGuenter Roeck 	const struct ina2xx_data *data = _data;
615814db9f1SGuenter Roeck 	enum ina2xx_ids chip = data->chip;
616814db9f1SGuenter Roeck 
617814db9f1SGuenter Roeck 	switch (type) {
618814db9f1SGuenter Roeck 	case hwmon_in:
619814db9f1SGuenter Roeck 		switch (attr) {
620814db9f1SGuenter Roeck 		case hwmon_in_input:
621814db9f1SGuenter Roeck 			return 0444;
622814db9f1SGuenter Roeck 		case hwmon_in_lcrit:
623814db9f1SGuenter Roeck 		case hwmon_in_crit:
624814db9f1SGuenter Roeck 			if (chip == ina226)
625814db9f1SGuenter Roeck 				return 0644;
626814db9f1SGuenter Roeck 			break;
627814db9f1SGuenter Roeck 		case hwmon_in_lcrit_alarm:
628814db9f1SGuenter Roeck 		case hwmon_in_crit_alarm:
629814db9f1SGuenter Roeck 			if (chip == ina226)
630814db9f1SGuenter Roeck 				return 0444;
631814db9f1SGuenter Roeck 			break;
632814db9f1SGuenter Roeck 		default:
633814db9f1SGuenter Roeck 			break;
634814db9f1SGuenter Roeck 		}
635814db9f1SGuenter Roeck 		break;
636814db9f1SGuenter Roeck 	case hwmon_curr:
637814db9f1SGuenter Roeck 		switch (attr) {
638814db9f1SGuenter Roeck 		case hwmon_curr_input:
639814db9f1SGuenter Roeck 			return 0444;
640*4d5c2d98SGuenter Roeck 		case hwmon_curr_lcrit:
641*4d5c2d98SGuenter Roeck 		case hwmon_curr_crit:
642*4d5c2d98SGuenter Roeck 			if (chip == ina226)
643*4d5c2d98SGuenter Roeck 				return 0644;
644*4d5c2d98SGuenter Roeck 			break;
645*4d5c2d98SGuenter Roeck 		case hwmon_curr_lcrit_alarm:
646*4d5c2d98SGuenter Roeck 		case hwmon_curr_crit_alarm:
647*4d5c2d98SGuenter Roeck 			if (chip == ina226)
648*4d5c2d98SGuenter Roeck 				return 0444;
649*4d5c2d98SGuenter Roeck 			break;
650814db9f1SGuenter Roeck 		default:
651814db9f1SGuenter Roeck 			break;
652814db9f1SGuenter Roeck 		}
653814db9f1SGuenter Roeck 		break;
654814db9f1SGuenter Roeck 	case hwmon_power:
655814db9f1SGuenter Roeck 		switch (attr) {
656814db9f1SGuenter Roeck 		case hwmon_power_input:
657814db9f1SGuenter Roeck 			return 0444;
658814db9f1SGuenter Roeck 		case hwmon_power_crit:
659814db9f1SGuenter Roeck 			if (chip == ina226)
660814db9f1SGuenter Roeck 				return 0644;
661814db9f1SGuenter Roeck 			break;
662814db9f1SGuenter Roeck 		case hwmon_power_crit_alarm:
663814db9f1SGuenter Roeck 			if (chip == ina226)
664814db9f1SGuenter Roeck 				return 0444;
665814db9f1SGuenter Roeck 			break;
666814db9f1SGuenter Roeck 		default:
667814db9f1SGuenter Roeck 			break;
668814db9f1SGuenter Roeck 		}
669814db9f1SGuenter Roeck 		break;
670814db9f1SGuenter Roeck 	case hwmon_chip:
671814db9f1SGuenter Roeck 		switch (attr) {
672814db9f1SGuenter Roeck 		case hwmon_chip_update_interval:
673814db9f1SGuenter Roeck 			if (chip == ina226)
674814db9f1SGuenter Roeck 				return 0644;
675814db9f1SGuenter Roeck 			break;
676814db9f1SGuenter Roeck 		default:
677814db9f1SGuenter Roeck 			break;
678814db9f1SGuenter Roeck 		}
679814db9f1SGuenter Roeck 		break;
680814db9f1SGuenter Roeck 	default:
681814db9f1SGuenter Roeck 		break;
682814db9f1SGuenter Roeck 	}
683814db9f1SGuenter Roeck 	return 0;
684814db9f1SGuenter Roeck }
685814db9f1SGuenter Roeck 
686814db9f1SGuenter Roeck static const struct hwmon_channel_info * const ina2xx_info[] = {
687814db9f1SGuenter Roeck 	HWMON_CHANNEL_INFO(chip,
688814db9f1SGuenter Roeck 			   HWMON_C_UPDATE_INTERVAL),
689814db9f1SGuenter Roeck 	HWMON_CHANNEL_INFO(in,
690814db9f1SGuenter Roeck 			   HWMON_I_INPUT | HWMON_I_CRIT | HWMON_I_CRIT_ALARM |
691814db9f1SGuenter Roeck 			   HWMON_I_LCRIT | HWMON_I_LCRIT_ALARM,
692814db9f1SGuenter Roeck 			   HWMON_I_INPUT | HWMON_I_CRIT | HWMON_I_CRIT_ALARM |
693814db9f1SGuenter Roeck 			   HWMON_I_LCRIT | HWMON_I_LCRIT_ALARM
694814db9f1SGuenter Roeck 			   ),
695*4d5c2d98SGuenter Roeck 	HWMON_CHANNEL_INFO(curr, HWMON_C_INPUT | HWMON_C_CRIT | HWMON_C_CRIT_ALARM |
696*4d5c2d98SGuenter Roeck 			   HWMON_C_LCRIT | HWMON_C_LCRIT_ALARM),
697814db9f1SGuenter Roeck 	HWMON_CHANNEL_INFO(power,
698814db9f1SGuenter Roeck 			   HWMON_P_INPUT | HWMON_P_CRIT | HWMON_P_CRIT_ALARM),
699814db9f1SGuenter Roeck 	NULL
700814db9f1SGuenter Roeck };
701814db9f1SGuenter Roeck 
702814db9f1SGuenter Roeck static const struct hwmon_ops ina2xx_hwmon_ops = {
703814db9f1SGuenter Roeck 	.is_visible = ina2xx_is_visible,
704814db9f1SGuenter Roeck 	.read = ina2xx_read,
705814db9f1SGuenter Roeck 	.write = ina2xx_write,
706814db9f1SGuenter Roeck };
707814db9f1SGuenter Roeck 
708814db9f1SGuenter Roeck static const struct hwmon_chip_info ina2xx_chip_info = {
709814db9f1SGuenter Roeck 	.ops = &ina2xx_hwmon_ops,
710814db9f1SGuenter Roeck 	.info = ina2xx_info,
711814db9f1SGuenter Roeck };
712814db9f1SGuenter Roeck 
713814db9f1SGuenter Roeck /* shunt resistance */
7145a56a39bSAlex Qiu 
7155d389b12SMaciej Purski /*
7165d389b12SMaciej Purski  * In order to keep calibration register value fixed, the product
7175d389b12SMaciej Purski  * of current_lsb and shunt_resistor should also be fixed and equal
7185d389b12SMaciej Purski  * to shunt_voltage_lsb = 1 / shunt_div multiplied by 10^9 in order
7195d389b12SMaciej Purski  * to keep the scale.
7205d389b12SMaciej Purski  */
721ab7fbee4SGuenter Roeck static int ina2xx_set_shunt(struct ina2xx_data *data, unsigned long val)
7225d389b12SMaciej Purski {
7235d389b12SMaciej Purski 	unsigned int dividend = DIV_ROUND_CLOSEST(1000000000,
7245d389b12SMaciej Purski 						  data->config->shunt_div);
725ab7fbee4SGuenter Roeck 	if (!val || val > dividend)
7265d389b12SMaciej Purski 		return -EINVAL;
7275d389b12SMaciej Purski 
7285d389b12SMaciej Purski 	data->rshunt = val;
7295d389b12SMaciej Purski 	data->current_lsb_uA = DIV_ROUND_CLOSEST(dividend, val);
7305d389b12SMaciej Purski 	data->power_lsb_uW = data->config->power_lsb_factor *
7315d389b12SMaciej Purski 			     data->current_lsb_uA;
7325d389b12SMaciej Purski 
7335d389b12SMaciej Purski 	return 0;
7345d389b12SMaciej Purski }
7355d389b12SMaciej Purski 
736814db9f1SGuenter Roeck static ssize_t shunt_resistor_show(struct device *dev,
7376a0f234fSGuenter Roeck 				   struct device_attribute *da, char *buf)
7383ad86700SLothar Felten {
7393ad86700SLothar Felten 	struct ina2xx_data *data = dev_get_drvdata(dev);
7403ad86700SLothar Felten 
741af9a9730SZihao Tang 	return sysfs_emit(buf, "%li\n", data->rshunt);
7423ad86700SLothar Felten }
7433ad86700SLothar Felten 
744814db9f1SGuenter Roeck static ssize_t shunt_resistor_store(struct device *dev,
7458a5fc795SBartosz Golaszewski 				    struct device_attribute *da,
7468a5fc795SBartosz Golaszewski 				    const char *buf, size_t count)
7478a5fc795SBartosz Golaszewski {
748814db9f1SGuenter Roeck 	struct ina2xx_data *data = dev_get_drvdata(dev);
7498a5fc795SBartosz Golaszewski 	unsigned long val;
7508a5fc795SBartosz Golaszewski 	int status;
7518a5fc795SBartosz Golaszewski 
7528a5fc795SBartosz Golaszewski 	status = kstrtoul(buf, 10, &val);
7538a5fc795SBartosz Golaszewski 	if (status < 0)
7548a5fc795SBartosz Golaszewski 		return status;
7558a5fc795SBartosz Golaszewski 
756ab7fbee4SGuenter Roeck 	mutex_lock(&data->config_lock);
7575d389b12SMaciej Purski 	status = ina2xx_set_shunt(data, val);
758ab7fbee4SGuenter Roeck 	mutex_unlock(&data->config_lock);
7598a5fc795SBartosz Golaszewski 	if (status < 0)
7608a5fc795SBartosz Golaszewski 		return status;
7618a5fc795SBartosz Golaszewski 	return count;
7628a5fc795SBartosz Golaszewski }
7638a5fc795SBartosz Golaszewski 
764814db9f1SGuenter Roeck static DEVICE_ATTR_RW(shunt_resistor);
76572a87a47SBartosz Golaszewski 
766f7c2fe38SFelten, Lothar /* pointers to created device attributes */
767468bf0e3SGuenter Roeck static struct attribute *ina2xx_attrs[] = {
768814db9f1SGuenter Roeck 	&dev_attr_shunt_resistor.attr,
769f7c2fe38SFelten, Lothar 	NULL,
770f7c2fe38SFelten, Lothar };
771814db9f1SGuenter Roeck ATTRIBUTE_GROUPS(ina2xx);
772f7c2fe38SFelten, Lothar 
77351c6fa32SGuenter Roeck /*
77451c6fa32SGuenter Roeck  * Initialize chip
77551c6fa32SGuenter Roeck  */
77651c6fa32SGuenter Roeck static int ina2xx_init(struct device *dev, struct ina2xx_data *data)
77751c6fa32SGuenter Roeck {
77851c6fa32SGuenter Roeck 	struct regmap *regmap = data->regmap;
77951c6fa32SGuenter Roeck 	u32 shunt;
78051c6fa32SGuenter Roeck 	int ret;
78151c6fa32SGuenter Roeck 
78251c6fa32SGuenter Roeck 	if (device_property_read_u32(dev, "shunt-resistor", &shunt) < 0)
78351c6fa32SGuenter Roeck 		shunt = INA2XX_RSHUNT_DEFAULT;
78451c6fa32SGuenter Roeck 
78551c6fa32SGuenter Roeck 	ret = ina2xx_set_shunt(data, shunt);
78651c6fa32SGuenter Roeck 	if (ret < 0)
78751c6fa32SGuenter Roeck 		return ret;
78851c6fa32SGuenter Roeck 
78951c6fa32SGuenter Roeck 	ret = regmap_write(regmap, INA2XX_CONFIG, data->config->config_default);
79051c6fa32SGuenter Roeck 	if (ret < 0)
79151c6fa32SGuenter Roeck 		return ret;
79251c6fa32SGuenter Roeck 
79351c6fa32SGuenter Roeck 	if (data->chip == ina226) {
79451c6fa32SGuenter Roeck 		bool active_high = device_property_read_bool(dev, "ti,alert-polarity-active-high");
79551c6fa32SGuenter Roeck 
796aa7d1763SGuenter Roeck 		regmap_update_bits(regmap, INA226_MASK_ENABLE,
797aa7d1763SGuenter Roeck 				   INA226_ALERT_LATCH_ENABLE | INA226_ALERT_POLARITY,
798aa7d1763SGuenter Roeck 				   INA226_ALERT_LATCH_ENABLE |
79951c6fa32SGuenter Roeck 						FIELD_PREP(INA226_ALERT_POLARITY, active_high));
80051c6fa32SGuenter Roeck 	}
80151c6fa32SGuenter Roeck 
80251c6fa32SGuenter Roeck 	/*
80351c6fa32SGuenter Roeck 	 * Calibration register is set to the best value, which eliminates
80451c6fa32SGuenter Roeck 	 * truncation errors on calculating current register in hardware.
80551c6fa32SGuenter Roeck 	 * According to datasheet (eq. 3) the best values are 2048 for
80651c6fa32SGuenter Roeck 	 * ina226 and 4096 for ina219. They are hardcoded as calibration_value.
80751c6fa32SGuenter Roeck 	 */
80851c6fa32SGuenter Roeck 	return regmap_write(regmap, INA2XX_CALIBRATION,
80951c6fa32SGuenter Roeck 			    data->config->calibration_value);
81051c6fa32SGuenter Roeck }
81151c6fa32SGuenter Roeck 
81267487038SStephen Kitt static int ina2xx_probe(struct i2c_client *client)
813f7c2fe38SFelten, Lothar {
814468bf0e3SGuenter Roeck 	struct device *dev = &client->dev;
815468bf0e3SGuenter Roeck 	struct ina2xx_data *data;
816468bf0e3SGuenter Roeck 	struct device *hwmon_dev;
817bd0ddd4dSJavier Martinez Canillas 	enum ina2xx_ids chip;
818814db9f1SGuenter Roeck 	int ret;
819bd0ddd4dSJavier Martinez Canillas 
8208b839699SAndrew Davis 	chip = (uintptr_t)i2c_get_match_data(client);
821f7c2fe38SFelten, Lothar 
822468bf0e3SGuenter Roeck 	data = devm_kzalloc(dev, sizeof(*data), GFP_KERNEL);
823f7c2fe38SFelten, Lothar 	if (!data)
824f7c2fe38SFelten, Lothar 		return -ENOMEM;
825f7c2fe38SFelten, Lothar 
826f7c2fe38SFelten, Lothar 	/* set the device type */
827bd0ddd4dSJavier Martinez Canillas 	data->config = &ina2xx_config[chip];
82851c6fa32SGuenter Roeck 	data->chip = chip;
8290c4c5860SMarek Szyprowski 	mutex_init(&data->config_lock);
83072a87a47SBartosz Golaszewski 
831a0de56c8SMarc Titinger 	data->regmap = devm_regmap_init_i2c(client, &ina2xx_regmap_config);
832a0de56c8SMarc Titinger 	if (IS_ERR(data->regmap)) {
833a0de56c8SMarc Titinger 		dev_err(dev, "failed to allocate register map\n");
834a0de56c8SMarc Titinger 		return PTR_ERR(data->regmap);
835a0de56c8SMarc Titinger 	}
836a0de56c8SMarc Titinger 
837ad20248aSSvyatoslav Ryhel 	ret = devm_regulator_get_enable(dev, "vs");
838ad20248aSSvyatoslav Ryhel 	if (ret)
839ad20248aSSvyatoslav Ryhel 		return dev_err_probe(dev, ret, "failed to enable vs regulator\n");
840ad20248aSSvyatoslav Ryhel 
84151c6fa32SGuenter Roeck 	ret = ina2xx_init(dev, data);
84251c6fa32SGuenter Roeck 	if (ret < 0)
84351c6fa32SGuenter Roeck 		return dev_err_probe(dev, ret, "failed to configure device\n");
844509416a8SBartosz Golaszewski 
845814db9f1SGuenter Roeck 	hwmon_dev = devm_hwmon_device_register_with_info(dev, client->name,
846814db9f1SGuenter Roeck 							 data, &ina2xx_chip_info,
847814db9f1SGuenter Roeck 							 ina2xx_groups);
848468bf0e3SGuenter Roeck 	if (IS_ERR(hwmon_dev))
849468bf0e3SGuenter Roeck 		return PTR_ERR(hwmon_dev);
850f7c2fe38SFelten, Lothar 
851468bf0e3SGuenter Roeck 	dev_info(dev, "power monitor %s (Rshunt = %li uOhm)\n",
85270df9ebbSNicolin Chen 		 client->name, data->rshunt);
8536106db25SGuenter Roeck 
854f7c2fe38SFelten, Lothar 	return 0;
855f7c2fe38SFelten, Lothar }
856f7c2fe38SFelten, Lothar 
857f7c2fe38SFelten, Lothar static const struct i2c_device_id ina2xx_id[] = {
858f7c2fe38SFelten, Lothar 	{ "ina219", ina219 },
859dc92cd0cSGuenter Roeck 	{ "ina220", ina219 },
860f7c2fe38SFelten, Lothar 	{ "ina226", ina226 },
861dc92cd0cSGuenter Roeck 	{ "ina230", ina226 },
862add513beSKevin Hilman 	{ "ina231", ina226 },
863f7c2fe38SFelten, Lothar 	{ }
864f7c2fe38SFelten, Lothar };
865f7c2fe38SFelten, Lothar MODULE_DEVICE_TABLE(i2c, ina2xx_id);
866f7c2fe38SFelten, Lothar 
867df6b8c70SGuenter Roeck static const struct of_device_id __maybe_unused ina2xx_of_match[] = {
868bd0ddd4dSJavier Martinez Canillas 	{
869bd0ddd4dSJavier Martinez Canillas 		.compatible = "ti,ina219",
870bd0ddd4dSJavier Martinez Canillas 		.data = (void *)ina219
871bd0ddd4dSJavier Martinez Canillas 	},
872bd0ddd4dSJavier Martinez Canillas 	{
873bd0ddd4dSJavier Martinez Canillas 		.compatible = "ti,ina220",
874bd0ddd4dSJavier Martinez Canillas 		.data = (void *)ina219
875bd0ddd4dSJavier Martinez Canillas 	},
876bd0ddd4dSJavier Martinez Canillas 	{
877bd0ddd4dSJavier Martinez Canillas 		.compatible = "ti,ina226",
878bd0ddd4dSJavier Martinez Canillas 		.data = (void *)ina226
879bd0ddd4dSJavier Martinez Canillas 	},
880bd0ddd4dSJavier Martinez Canillas 	{
881bd0ddd4dSJavier Martinez Canillas 		.compatible = "ti,ina230",
882bd0ddd4dSJavier Martinez Canillas 		.data = (void *)ina226
883bd0ddd4dSJavier Martinez Canillas 	},
884bd0ddd4dSJavier Martinez Canillas 	{
885bd0ddd4dSJavier Martinez Canillas 		.compatible = "ti,ina231",
886bd0ddd4dSJavier Martinez Canillas 		.data = (void *)ina226
887bd0ddd4dSJavier Martinez Canillas 	},
888bd0ddd4dSJavier Martinez Canillas 	{ },
889bd0ddd4dSJavier Martinez Canillas };
890bd0ddd4dSJavier Martinez Canillas MODULE_DEVICE_TABLE(of, ina2xx_of_match);
891bd0ddd4dSJavier Martinez Canillas 
892f7c2fe38SFelten, Lothar static struct i2c_driver ina2xx_driver = {
893f7c2fe38SFelten, Lothar 	.driver = {
894f7c2fe38SFelten, Lothar 		.name	= "ina2xx",
895bd0ddd4dSJavier Martinez Canillas 		.of_match_table = of_match_ptr(ina2xx_of_match),
896f7c2fe38SFelten, Lothar 	},
8971975d167SUwe Kleine-König 	.probe		= ina2xx_probe,
898f7c2fe38SFelten, Lothar 	.id_table	= ina2xx_id,
899f7c2fe38SFelten, Lothar };
900f7c2fe38SFelten, Lothar 
901d835ca0fSWei Yongjun module_i2c_driver(ina2xx_driver);
902f7c2fe38SFelten, Lothar 
903f7c2fe38SFelten, Lothar MODULE_AUTHOR("Lothar Felten <l-felten@ti.com>");
904f7c2fe38SFelten, Lothar MODULE_DESCRIPTION("ina2xx driver");
905f7c2fe38SFelten, Lothar MODULE_LICENSE("GPL");
906