xref: /linux/drivers/hwmon/ina2xx.c (revision 3a39d672e7f48b8d6b91a09afa4b55352773b4b5)
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 
ina2xx_writeable_reg(struct device * dev,unsigned int reg)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 
ina2xx_volatile_reg(struct device * dev,unsigned int reg)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 
ina226_reg_to_interval(u16 config)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  */
ina226_interval_to_reg(long interval)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 
ina2xx_get_value(struct ina2xx_data * data,u8 reg,unsigned int regval)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  */
ina2xx_read_init(struct device * dev,int reg,long * val)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  */
ina226_alert_to_reg(struct ina2xx_data * data,int reg,long val)3094d5c2d98SGuenter 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);
3254d5c2d98SGuenter Roeck 	case INA2XX_CURRENT:
3264d5c2d98SGuenter Roeck 		val = clamp_val(val, INT_MIN / 1000, INT_MAX / 1000);
3274d5c2d98SGuenter Roeck 		/* signed register, result in mA */
3284d5c2d98SGuenter Roeck 		val = DIV_ROUND_CLOSEST(val * 1000, data->current_lsb_uA);
3294d5c2d98SGuenter 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 
ina226_alert_limit_read(struct ina2xx_data * data,u32 mask,int reg,long * val)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 
ina226_alert_limit_write(struct ina2xx_data * data,u32 mask,int reg,long val)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 
ina2xx_chip_read(struct device * dev,u32 attr,long * val)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 
ina226_alert_read(struct regmap * regmap,u32 mask,long * val)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 
ina2xx_in_read(struct device * dev,u32 attr,int channel,long * val)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 
ina2xx_power_read(struct device * dev,u32 attr,long * val)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 
ina2xx_curr_read(struct device * dev,u32 attr,long * val)479814db9f1SGuenter Roeck static int ina2xx_curr_read(struct device *dev, u32 attr, long *val)
480814db9f1SGuenter Roeck {
4814d5c2d98SGuenter Roeck 	struct ina2xx_data *data = dev_get_drvdata(dev);
4824d5c2d98SGuenter Roeck 	struct regmap *regmap = data->regmap;
483*63fb21afSGuenter Roeck 	unsigned int regval;
484*63fb21afSGuenter Roeck 	int ret;
4854d5c2d98SGuenter Roeck 
4864d5c2d98SGuenter Roeck 	/*
4874d5c2d98SGuenter Roeck 	 * While the chips supported by this driver do not directly support
4884d5c2d98SGuenter Roeck 	 * current limits, they do support setting shunt voltage limits.
4894d5c2d98SGuenter Roeck 	 * The shunt voltage divided by the shunt resistor value is the current.
4904d5c2d98SGuenter Roeck 	 * On top of that, calibration values are set such that in the shunt
4914d5c2d98SGuenter Roeck 	 * voltage register and the current register report the same values.
4924d5c2d98SGuenter Roeck 	 * That means we can report and configure current limits based on shunt
4934d5c2d98SGuenter Roeck 	 * voltage limits.
4944d5c2d98SGuenter Roeck 	 */
495814db9f1SGuenter Roeck 	switch (attr) {
496814db9f1SGuenter Roeck 	case hwmon_curr_input:
497*63fb21afSGuenter Roeck 		/*
498*63fb21afSGuenter Roeck 		 * Since the shunt voltage and the current register report the
499*63fb21afSGuenter Roeck 		 * same values when the chip is calibrated, we can calculate
500*63fb21afSGuenter Roeck 		 * the current directly from the shunt voltage without relying
501*63fb21afSGuenter Roeck 		 * on chip calibration.
502*63fb21afSGuenter Roeck 		 */
503*63fb21afSGuenter Roeck 		ret = regmap_read(regmap, INA2XX_SHUNT_VOLTAGE, &regval);
504*63fb21afSGuenter Roeck 		if (ret)
505*63fb21afSGuenter Roeck 			return ret;
506*63fb21afSGuenter Roeck 		*val = ina2xx_get_value(data, INA2XX_CURRENT, regval);
507*63fb21afSGuenter Roeck 		return 0;
5084d5c2d98SGuenter Roeck 	case hwmon_curr_lcrit:
5094d5c2d98SGuenter Roeck 		return ina226_alert_limit_read(data, INA226_SHUNT_UNDER_VOLTAGE_MASK,
5104d5c2d98SGuenter Roeck 					       INA2XX_CURRENT, val);
5114d5c2d98SGuenter Roeck 	case hwmon_curr_crit:
5124d5c2d98SGuenter Roeck 		return ina226_alert_limit_read(data, INA226_SHUNT_OVER_VOLTAGE_MASK,
5134d5c2d98SGuenter Roeck 					       INA2XX_CURRENT, val);
5144d5c2d98SGuenter Roeck 	case hwmon_curr_lcrit_alarm:
5154d5c2d98SGuenter Roeck 		return ina226_alert_read(regmap, INA226_SHUNT_UNDER_VOLTAGE_MASK, val);
5164d5c2d98SGuenter Roeck 	case hwmon_curr_crit_alarm:
5174d5c2d98SGuenter Roeck 		return ina226_alert_read(regmap, INA226_SHUNT_OVER_VOLTAGE_MASK, val);
518814db9f1SGuenter Roeck 	default:
519814db9f1SGuenter Roeck 		return -EOPNOTSUPP;
520814db9f1SGuenter Roeck 	}
521814db9f1SGuenter Roeck }
522814db9f1SGuenter Roeck 
ina2xx_read(struct device * dev,enum hwmon_sensor_types type,u32 attr,int channel,long * val)523814db9f1SGuenter Roeck static int ina2xx_read(struct device *dev, enum hwmon_sensor_types type,
524814db9f1SGuenter Roeck 		       u32 attr, int channel, long *val)
525814db9f1SGuenter Roeck {
526814db9f1SGuenter Roeck 	switch (type) {
527814db9f1SGuenter Roeck 	case hwmon_chip:
528814db9f1SGuenter Roeck 		return ina2xx_chip_read(dev, attr, val);
529814db9f1SGuenter Roeck 	case hwmon_in:
530814db9f1SGuenter Roeck 		return ina2xx_in_read(dev, attr, channel, val);
531814db9f1SGuenter Roeck 	case hwmon_power:
532814db9f1SGuenter Roeck 		return ina2xx_power_read(dev, attr, val);
533814db9f1SGuenter Roeck 	case hwmon_curr:
534814db9f1SGuenter Roeck 		return ina2xx_curr_read(dev, attr, val);
535814db9f1SGuenter Roeck 	default:
536814db9f1SGuenter Roeck 		return -EOPNOTSUPP;
537814db9f1SGuenter Roeck 	}
538814db9f1SGuenter Roeck }
539814db9f1SGuenter Roeck 
ina2xx_chip_write(struct device * dev,u32 attr,long val)540814db9f1SGuenter Roeck static int ina2xx_chip_write(struct device *dev, u32 attr, long val)
541814db9f1SGuenter Roeck {
542814db9f1SGuenter Roeck 	struct ina2xx_data *data = dev_get_drvdata(dev);
543814db9f1SGuenter Roeck 
544814db9f1SGuenter Roeck 	switch (attr) {
545814db9f1SGuenter Roeck 	case hwmon_chip_update_interval:
546814db9f1SGuenter Roeck 		return regmap_update_bits(data->regmap, INA2XX_CONFIG,
547814db9f1SGuenter Roeck 					  INA226_AVG_RD_MASK,
548814db9f1SGuenter Roeck 					  ina226_interval_to_reg(val));
549814db9f1SGuenter Roeck 	default:
550814db9f1SGuenter Roeck 		return -EOPNOTSUPP;
551814db9f1SGuenter Roeck 	}
552814db9f1SGuenter Roeck }
553814db9f1SGuenter Roeck 
ina2xx_in_write(struct device * dev,u32 attr,int channel,long val)554814db9f1SGuenter Roeck static int ina2xx_in_write(struct device *dev, u32 attr, int channel, long val)
555814db9f1SGuenter Roeck {
556814db9f1SGuenter Roeck 	struct ina2xx_data *data = dev_get_drvdata(dev);
557814db9f1SGuenter Roeck 
558814db9f1SGuenter Roeck 	switch (attr) {
559814db9f1SGuenter Roeck 	case hwmon_in_lcrit:
560814db9f1SGuenter Roeck 		return ina226_alert_limit_write(data,
561814db9f1SGuenter Roeck 			channel ? INA226_BUS_UNDER_VOLTAGE_MASK : INA226_SHUNT_UNDER_VOLTAGE_MASK,
5629965ebd1SGuenter Roeck 			channel ? INA2XX_BUS_VOLTAGE : INA2XX_SHUNT_VOLTAGE,
563814db9f1SGuenter Roeck 			val);
564814db9f1SGuenter Roeck 	case hwmon_in_crit:
565814db9f1SGuenter Roeck 		return ina226_alert_limit_write(data,
566814db9f1SGuenter Roeck 			channel ? INA226_BUS_OVER_VOLTAGE_MASK : INA226_SHUNT_OVER_VOLTAGE_MASK,
5679965ebd1SGuenter Roeck 			channel ? INA2XX_BUS_VOLTAGE : INA2XX_SHUNT_VOLTAGE,
568814db9f1SGuenter Roeck 			val);
569814db9f1SGuenter Roeck 	default:
570814db9f1SGuenter Roeck 		return -EOPNOTSUPP;
571814db9f1SGuenter Roeck 	}
572814db9f1SGuenter Roeck 	return 0;
573814db9f1SGuenter Roeck }
574814db9f1SGuenter Roeck 
ina2xx_power_write(struct device * dev,u32 attr,long val)575814db9f1SGuenter Roeck static int ina2xx_power_write(struct device *dev, u32 attr, long val)
576814db9f1SGuenter Roeck {
577814db9f1SGuenter Roeck 	struct ina2xx_data *data = dev_get_drvdata(dev);
578814db9f1SGuenter Roeck 
579814db9f1SGuenter Roeck 	switch (attr) {
580814db9f1SGuenter Roeck 	case hwmon_power_crit:
5819965ebd1SGuenter Roeck 		return ina226_alert_limit_write(data, INA226_POWER_OVER_LIMIT_MASK,
5829965ebd1SGuenter Roeck 						INA2XX_POWER, val);
583814db9f1SGuenter Roeck 	default:
584814db9f1SGuenter Roeck 		return -EOPNOTSUPP;
585814db9f1SGuenter Roeck 	}
586814db9f1SGuenter Roeck 	return 0;
587814db9f1SGuenter Roeck }
588814db9f1SGuenter Roeck 
ina2xx_curr_write(struct device * dev,u32 attr,long val)5894d5c2d98SGuenter Roeck static int ina2xx_curr_write(struct device *dev, u32 attr, long val)
5904d5c2d98SGuenter Roeck {
5914d5c2d98SGuenter Roeck 	struct ina2xx_data *data = dev_get_drvdata(dev);
5924d5c2d98SGuenter Roeck 
5934d5c2d98SGuenter Roeck 	switch (attr) {
5944d5c2d98SGuenter Roeck 	case hwmon_curr_lcrit:
5954d5c2d98SGuenter Roeck 		return ina226_alert_limit_write(data, INA226_SHUNT_UNDER_VOLTAGE_MASK,
5964d5c2d98SGuenter Roeck 						INA2XX_CURRENT, val);
5974d5c2d98SGuenter Roeck 	case hwmon_curr_crit:
5984d5c2d98SGuenter Roeck 		return ina226_alert_limit_write(data, INA226_SHUNT_OVER_VOLTAGE_MASK,
5994d5c2d98SGuenter Roeck 						INA2XX_CURRENT, val);
6004d5c2d98SGuenter Roeck 	default:
6014d5c2d98SGuenter Roeck 		return -EOPNOTSUPP;
6024d5c2d98SGuenter Roeck 	}
6034d5c2d98SGuenter Roeck 	return 0;
6044d5c2d98SGuenter Roeck }
6054d5c2d98SGuenter Roeck 
ina2xx_write(struct device * dev,enum hwmon_sensor_types type,u32 attr,int channel,long val)606814db9f1SGuenter Roeck static int ina2xx_write(struct device *dev, enum hwmon_sensor_types type,
607814db9f1SGuenter Roeck 			u32 attr, int channel, long val)
608814db9f1SGuenter Roeck {
609814db9f1SGuenter Roeck 	switch (type) {
610814db9f1SGuenter Roeck 	case hwmon_chip:
611814db9f1SGuenter Roeck 		return ina2xx_chip_write(dev, attr, val);
612814db9f1SGuenter Roeck 	case hwmon_in:
613814db9f1SGuenter Roeck 		return ina2xx_in_write(dev, attr, channel, val);
614814db9f1SGuenter Roeck 	case hwmon_power:
615814db9f1SGuenter Roeck 		return ina2xx_power_write(dev, attr, val);
6164d5c2d98SGuenter Roeck 	case hwmon_curr:
6174d5c2d98SGuenter Roeck 		return ina2xx_curr_write(dev, attr, val);
618814db9f1SGuenter Roeck 	default:
619814db9f1SGuenter Roeck 		return -EOPNOTSUPP;
620814db9f1SGuenter Roeck 	}
621814db9f1SGuenter Roeck }
622814db9f1SGuenter Roeck 
ina2xx_is_visible(const void * _data,enum hwmon_sensor_types type,u32 attr,int channel)623814db9f1SGuenter Roeck static umode_t ina2xx_is_visible(const void *_data, enum hwmon_sensor_types type,
624814db9f1SGuenter Roeck 				 u32 attr, int channel)
625814db9f1SGuenter Roeck {
626814db9f1SGuenter Roeck 	const struct ina2xx_data *data = _data;
627814db9f1SGuenter Roeck 	enum ina2xx_ids chip = data->chip;
628814db9f1SGuenter Roeck 
629814db9f1SGuenter Roeck 	switch (type) {
630814db9f1SGuenter Roeck 	case hwmon_in:
631814db9f1SGuenter Roeck 		switch (attr) {
632814db9f1SGuenter Roeck 		case hwmon_in_input:
633814db9f1SGuenter Roeck 			return 0444;
634814db9f1SGuenter Roeck 		case hwmon_in_lcrit:
635814db9f1SGuenter Roeck 		case hwmon_in_crit:
636814db9f1SGuenter Roeck 			if (chip == ina226)
637814db9f1SGuenter Roeck 				return 0644;
638814db9f1SGuenter Roeck 			break;
639814db9f1SGuenter Roeck 		case hwmon_in_lcrit_alarm:
640814db9f1SGuenter Roeck 		case hwmon_in_crit_alarm:
641814db9f1SGuenter Roeck 			if (chip == ina226)
642814db9f1SGuenter Roeck 				return 0444;
643814db9f1SGuenter Roeck 			break;
644814db9f1SGuenter Roeck 		default:
645814db9f1SGuenter Roeck 			break;
646814db9f1SGuenter Roeck 		}
647814db9f1SGuenter Roeck 		break;
648814db9f1SGuenter Roeck 	case hwmon_curr:
649814db9f1SGuenter Roeck 		switch (attr) {
650814db9f1SGuenter Roeck 		case hwmon_curr_input:
651814db9f1SGuenter Roeck 			return 0444;
6524d5c2d98SGuenter Roeck 		case hwmon_curr_lcrit:
6534d5c2d98SGuenter Roeck 		case hwmon_curr_crit:
6544d5c2d98SGuenter Roeck 			if (chip == ina226)
6554d5c2d98SGuenter Roeck 				return 0644;
6564d5c2d98SGuenter Roeck 			break;
6574d5c2d98SGuenter Roeck 		case hwmon_curr_lcrit_alarm:
6584d5c2d98SGuenter Roeck 		case hwmon_curr_crit_alarm:
6594d5c2d98SGuenter Roeck 			if (chip == ina226)
6604d5c2d98SGuenter Roeck 				return 0444;
6614d5c2d98SGuenter Roeck 			break;
662814db9f1SGuenter Roeck 		default:
663814db9f1SGuenter Roeck 			break;
664814db9f1SGuenter Roeck 		}
665814db9f1SGuenter Roeck 		break;
666814db9f1SGuenter Roeck 	case hwmon_power:
667814db9f1SGuenter Roeck 		switch (attr) {
668814db9f1SGuenter Roeck 		case hwmon_power_input:
669814db9f1SGuenter Roeck 			return 0444;
670814db9f1SGuenter Roeck 		case hwmon_power_crit:
671814db9f1SGuenter Roeck 			if (chip == ina226)
672814db9f1SGuenter Roeck 				return 0644;
673814db9f1SGuenter Roeck 			break;
674814db9f1SGuenter Roeck 		case hwmon_power_crit_alarm:
675814db9f1SGuenter Roeck 			if (chip == ina226)
676814db9f1SGuenter Roeck 				return 0444;
677814db9f1SGuenter Roeck 			break;
678814db9f1SGuenter Roeck 		default:
679814db9f1SGuenter Roeck 			break;
680814db9f1SGuenter Roeck 		}
681814db9f1SGuenter Roeck 		break;
682814db9f1SGuenter Roeck 	case hwmon_chip:
683814db9f1SGuenter Roeck 		switch (attr) {
684814db9f1SGuenter Roeck 		case hwmon_chip_update_interval:
685814db9f1SGuenter Roeck 			if (chip == ina226)
686814db9f1SGuenter Roeck 				return 0644;
687814db9f1SGuenter Roeck 			break;
688814db9f1SGuenter Roeck 		default:
689814db9f1SGuenter Roeck 			break;
690814db9f1SGuenter Roeck 		}
691814db9f1SGuenter Roeck 		break;
692814db9f1SGuenter Roeck 	default:
693814db9f1SGuenter Roeck 		break;
694814db9f1SGuenter Roeck 	}
695814db9f1SGuenter Roeck 	return 0;
696814db9f1SGuenter Roeck }
697814db9f1SGuenter Roeck 
698814db9f1SGuenter Roeck static const struct hwmon_channel_info * const ina2xx_info[] = {
699814db9f1SGuenter Roeck 	HWMON_CHANNEL_INFO(chip,
700814db9f1SGuenter Roeck 			   HWMON_C_UPDATE_INTERVAL),
701814db9f1SGuenter Roeck 	HWMON_CHANNEL_INFO(in,
702814db9f1SGuenter Roeck 			   HWMON_I_INPUT | HWMON_I_CRIT | HWMON_I_CRIT_ALARM |
703814db9f1SGuenter Roeck 			   HWMON_I_LCRIT | HWMON_I_LCRIT_ALARM,
704814db9f1SGuenter Roeck 			   HWMON_I_INPUT | HWMON_I_CRIT | HWMON_I_CRIT_ALARM |
705814db9f1SGuenter Roeck 			   HWMON_I_LCRIT | HWMON_I_LCRIT_ALARM
706814db9f1SGuenter Roeck 			   ),
7074d5c2d98SGuenter Roeck 	HWMON_CHANNEL_INFO(curr, HWMON_C_INPUT | HWMON_C_CRIT | HWMON_C_CRIT_ALARM |
7084d5c2d98SGuenter Roeck 			   HWMON_C_LCRIT | HWMON_C_LCRIT_ALARM),
709814db9f1SGuenter Roeck 	HWMON_CHANNEL_INFO(power,
710814db9f1SGuenter Roeck 			   HWMON_P_INPUT | HWMON_P_CRIT | HWMON_P_CRIT_ALARM),
711814db9f1SGuenter Roeck 	NULL
712814db9f1SGuenter Roeck };
713814db9f1SGuenter Roeck 
714814db9f1SGuenter Roeck static const struct hwmon_ops ina2xx_hwmon_ops = {
715814db9f1SGuenter Roeck 	.is_visible = ina2xx_is_visible,
716814db9f1SGuenter Roeck 	.read = ina2xx_read,
717814db9f1SGuenter Roeck 	.write = ina2xx_write,
718814db9f1SGuenter Roeck };
719814db9f1SGuenter Roeck 
720814db9f1SGuenter Roeck static const struct hwmon_chip_info ina2xx_chip_info = {
721814db9f1SGuenter Roeck 	.ops = &ina2xx_hwmon_ops,
722814db9f1SGuenter Roeck 	.info = ina2xx_info,
723814db9f1SGuenter Roeck };
724814db9f1SGuenter Roeck 
725814db9f1SGuenter Roeck /* shunt resistance */
7265a56a39bSAlex Qiu 
7275d389b12SMaciej Purski /*
7285d389b12SMaciej Purski  * In order to keep calibration register value fixed, the product
7295d389b12SMaciej Purski  * of current_lsb and shunt_resistor should also be fixed and equal
7305d389b12SMaciej Purski  * to shunt_voltage_lsb = 1 / shunt_div multiplied by 10^9 in order
7315d389b12SMaciej Purski  * to keep the scale.
7325d389b12SMaciej Purski  */
ina2xx_set_shunt(struct ina2xx_data * data,unsigned long val)733ab7fbee4SGuenter Roeck static int ina2xx_set_shunt(struct ina2xx_data *data, unsigned long val)
7345d389b12SMaciej Purski {
7355d389b12SMaciej Purski 	unsigned int dividend = DIV_ROUND_CLOSEST(1000000000,
7365d389b12SMaciej Purski 						  data->config->shunt_div);
737ab7fbee4SGuenter Roeck 	if (!val || val > dividend)
7385d389b12SMaciej Purski 		return -EINVAL;
7395d389b12SMaciej Purski 
7405d389b12SMaciej Purski 	data->rshunt = val;
7415d389b12SMaciej Purski 	data->current_lsb_uA = DIV_ROUND_CLOSEST(dividend, val);
7425d389b12SMaciej Purski 	data->power_lsb_uW = data->config->power_lsb_factor *
7435d389b12SMaciej Purski 			     data->current_lsb_uA;
7445d389b12SMaciej Purski 
7455d389b12SMaciej Purski 	return 0;
7465d389b12SMaciej Purski }
7475d389b12SMaciej Purski 
shunt_resistor_show(struct device * dev,struct device_attribute * da,char * buf)748814db9f1SGuenter Roeck static ssize_t shunt_resistor_show(struct device *dev,
7496a0f234fSGuenter Roeck 				   struct device_attribute *da, char *buf)
7503ad86700SLothar Felten {
7513ad86700SLothar Felten 	struct ina2xx_data *data = dev_get_drvdata(dev);
7523ad86700SLothar Felten 
753af9a9730SZihao Tang 	return sysfs_emit(buf, "%li\n", data->rshunt);
7543ad86700SLothar Felten }
7553ad86700SLothar Felten 
shunt_resistor_store(struct device * dev,struct device_attribute * da,const char * buf,size_t count)756814db9f1SGuenter Roeck static ssize_t shunt_resistor_store(struct device *dev,
7578a5fc795SBartosz Golaszewski 				    struct device_attribute *da,
7588a5fc795SBartosz Golaszewski 				    const char *buf, size_t count)
7598a5fc795SBartosz Golaszewski {
760814db9f1SGuenter Roeck 	struct ina2xx_data *data = dev_get_drvdata(dev);
7618a5fc795SBartosz Golaszewski 	unsigned long val;
7628a5fc795SBartosz Golaszewski 	int status;
7638a5fc795SBartosz Golaszewski 
7648a5fc795SBartosz Golaszewski 	status = kstrtoul(buf, 10, &val);
7658a5fc795SBartosz Golaszewski 	if (status < 0)
7668a5fc795SBartosz Golaszewski 		return status;
7678a5fc795SBartosz Golaszewski 
768ab7fbee4SGuenter Roeck 	mutex_lock(&data->config_lock);
7695d389b12SMaciej Purski 	status = ina2xx_set_shunt(data, val);
770ab7fbee4SGuenter Roeck 	mutex_unlock(&data->config_lock);
7718a5fc795SBartosz Golaszewski 	if (status < 0)
7728a5fc795SBartosz Golaszewski 		return status;
7738a5fc795SBartosz Golaszewski 	return count;
7748a5fc795SBartosz Golaszewski }
7758a5fc795SBartosz Golaszewski 
776814db9f1SGuenter Roeck static DEVICE_ATTR_RW(shunt_resistor);
77772a87a47SBartosz Golaszewski 
778f7c2fe38SFelten, Lothar /* pointers to created device attributes */
779468bf0e3SGuenter Roeck static struct attribute *ina2xx_attrs[] = {
780814db9f1SGuenter Roeck 	&dev_attr_shunt_resistor.attr,
781f7c2fe38SFelten, Lothar 	NULL,
782f7c2fe38SFelten, Lothar };
783814db9f1SGuenter Roeck ATTRIBUTE_GROUPS(ina2xx);
784f7c2fe38SFelten, Lothar 
78551c6fa32SGuenter Roeck /*
78651c6fa32SGuenter Roeck  * Initialize chip
78751c6fa32SGuenter Roeck  */
ina2xx_init(struct device * dev,struct ina2xx_data * data)78851c6fa32SGuenter Roeck static int ina2xx_init(struct device *dev, struct ina2xx_data *data)
78951c6fa32SGuenter Roeck {
79051c6fa32SGuenter Roeck 	struct regmap *regmap = data->regmap;
79151c6fa32SGuenter Roeck 	u32 shunt;
79251c6fa32SGuenter Roeck 	int ret;
79351c6fa32SGuenter Roeck 
79451c6fa32SGuenter Roeck 	if (device_property_read_u32(dev, "shunt-resistor", &shunt) < 0)
79551c6fa32SGuenter Roeck 		shunt = INA2XX_RSHUNT_DEFAULT;
79651c6fa32SGuenter Roeck 
79751c6fa32SGuenter Roeck 	ret = ina2xx_set_shunt(data, shunt);
79851c6fa32SGuenter Roeck 	if (ret < 0)
79951c6fa32SGuenter Roeck 		return ret;
80051c6fa32SGuenter Roeck 
80151c6fa32SGuenter Roeck 	ret = regmap_write(regmap, INA2XX_CONFIG, data->config->config_default);
80251c6fa32SGuenter Roeck 	if (ret < 0)
80351c6fa32SGuenter Roeck 		return ret;
80451c6fa32SGuenter Roeck 
80551c6fa32SGuenter Roeck 	if (data->chip == ina226) {
80651c6fa32SGuenter Roeck 		bool active_high = device_property_read_bool(dev, "ti,alert-polarity-active-high");
80751c6fa32SGuenter Roeck 
808aa7d1763SGuenter Roeck 		regmap_update_bits(regmap, INA226_MASK_ENABLE,
809aa7d1763SGuenter Roeck 				   INA226_ALERT_LATCH_ENABLE | INA226_ALERT_POLARITY,
810aa7d1763SGuenter Roeck 				   INA226_ALERT_LATCH_ENABLE |
81151c6fa32SGuenter Roeck 						FIELD_PREP(INA226_ALERT_POLARITY, active_high));
81251c6fa32SGuenter Roeck 	}
81351c6fa32SGuenter Roeck 
81451c6fa32SGuenter Roeck 	/*
81551c6fa32SGuenter Roeck 	 * Calibration register is set to the best value, which eliminates
81651c6fa32SGuenter Roeck 	 * truncation errors on calculating current register in hardware.
81751c6fa32SGuenter Roeck 	 * According to datasheet (eq. 3) the best values are 2048 for
81851c6fa32SGuenter Roeck 	 * ina226 and 4096 for ina219. They are hardcoded as calibration_value.
81951c6fa32SGuenter Roeck 	 */
82051c6fa32SGuenter Roeck 	return regmap_write(regmap, INA2XX_CALIBRATION,
82151c6fa32SGuenter Roeck 			    data->config->calibration_value);
82251c6fa32SGuenter Roeck }
82351c6fa32SGuenter Roeck 
ina2xx_probe(struct i2c_client * client)82467487038SStephen Kitt static int ina2xx_probe(struct i2c_client *client)
825f7c2fe38SFelten, Lothar {
826468bf0e3SGuenter Roeck 	struct device *dev = &client->dev;
827468bf0e3SGuenter Roeck 	struct ina2xx_data *data;
828468bf0e3SGuenter Roeck 	struct device *hwmon_dev;
829bd0ddd4dSJavier Martinez Canillas 	enum ina2xx_ids chip;
830814db9f1SGuenter Roeck 	int ret;
831bd0ddd4dSJavier Martinez Canillas 
8328b839699SAndrew Davis 	chip = (uintptr_t)i2c_get_match_data(client);
833f7c2fe38SFelten, Lothar 
834468bf0e3SGuenter Roeck 	data = devm_kzalloc(dev, sizeof(*data), GFP_KERNEL);
835f7c2fe38SFelten, Lothar 	if (!data)
836f7c2fe38SFelten, Lothar 		return -ENOMEM;
837f7c2fe38SFelten, Lothar 
838f7c2fe38SFelten, Lothar 	/* set the device type */
839bd0ddd4dSJavier Martinez Canillas 	data->config = &ina2xx_config[chip];
84051c6fa32SGuenter Roeck 	data->chip = chip;
8410c4c5860SMarek Szyprowski 	mutex_init(&data->config_lock);
84272a87a47SBartosz Golaszewski 
843a0de56c8SMarc Titinger 	data->regmap = devm_regmap_init_i2c(client, &ina2xx_regmap_config);
844a0de56c8SMarc Titinger 	if (IS_ERR(data->regmap)) {
845a0de56c8SMarc Titinger 		dev_err(dev, "failed to allocate register map\n");
846a0de56c8SMarc Titinger 		return PTR_ERR(data->regmap);
847a0de56c8SMarc Titinger 	}
848a0de56c8SMarc Titinger 
849ad20248aSSvyatoslav Ryhel 	ret = devm_regulator_get_enable(dev, "vs");
850ad20248aSSvyatoslav Ryhel 	if (ret)
851ad20248aSSvyatoslav Ryhel 		return dev_err_probe(dev, ret, "failed to enable vs regulator\n");
852ad20248aSSvyatoslav Ryhel 
85351c6fa32SGuenter Roeck 	ret = ina2xx_init(dev, data);
85451c6fa32SGuenter Roeck 	if (ret < 0)
85551c6fa32SGuenter Roeck 		return dev_err_probe(dev, ret, "failed to configure device\n");
856509416a8SBartosz Golaszewski 
857814db9f1SGuenter Roeck 	hwmon_dev = devm_hwmon_device_register_with_info(dev, client->name,
858814db9f1SGuenter Roeck 							 data, &ina2xx_chip_info,
859814db9f1SGuenter Roeck 							 ina2xx_groups);
860468bf0e3SGuenter Roeck 	if (IS_ERR(hwmon_dev))
861468bf0e3SGuenter Roeck 		return PTR_ERR(hwmon_dev);
862f7c2fe38SFelten, Lothar 
863468bf0e3SGuenter Roeck 	dev_info(dev, "power monitor %s (Rshunt = %li uOhm)\n",
86470df9ebbSNicolin Chen 		 client->name, data->rshunt);
8656106db25SGuenter Roeck 
866f7c2fe38SFelten, Lothar 	return 0;
867f7c2fe38SFelten, Lothar }
868f7c2fe38SFelten, Lothar 
869f7c2fe38SFelten, Lothar static const struct i2c_device_id ina2xx_id[] = {
870f7c2fe38SFelten, Lothar 	{ "ina219", ina219 },
871dc92cd0cSGuenter Roeck 	{ "ina220", ina219 },
872f7c2fe38SFelten, Lothar 	{ "ina226", ina226 },
873dc92cd0cSGuenter Roeck 	{ "ina230", ina226 },
874add513beSKevin Hilman 	{ "ina231", ina226 },
875f7c2fe38SFelten, Lothar 	{ }
876f7c2fe38SFelten, Lothar };
877f7c2fe38SFelten, Lothar MODULE_DEVICE_TABLE(i2c, ina2xx_id);
878f7c2fe38SFelten, Lothar 
879df6b8c70SGuenter Roeck static const struct of_device_id __maybe_unused ina2xx_of_match[] = {
880bd0ddd4dSJavier Martinez Canillas 	{
881bd0ddd4dSJavier Martinez Canillas 		.compatible = "ti,ina219",
882bd0ddd4dSJavier Martinez Canillas 		.data = (void *)ina219
883bd0ddd4dSJavier Martinez Canillas 	},
884bd0ddd4dSJavier Martinez Canillas 	{
885bd0ddd4dSJavier Martinez Canillas 		.compatible = "ti,ina220",
886bd0ddd4dSJavier Martinez Canillas 		.data = (void *)ina219
887bd0ddd4dSJavier Martinez Canillas 	},
888bd0ddd4dSJavier Martinez Canillas 	{
889bd0ddd4dSJavier Martinez Canillas 		.compatible = "ti,ina226",
890bd0ddd4dSJavier Martinez Canillas 		.data = (void *)ina226
891bd0ddd4dSJavier Martinez Canillas 	},
892bd0ddd4dSJavier Martinez Canillas 	{
893bd0ddd4dSJavier Martinez Canillas 		.compatible = "ti,ina230",
894bd0ddd4dSJavier Martinez Canillas 		.data = (void *)ina226
895bd0ddd4dSJavier Martinez Canillas 	},
896bd0ddd4dSJavier Martinez Canillas 	{
897bd0ddd4dSJavier Martinez Canillas 		.compatible = "ti,ina231",
898bd0ddd4dSJavier Martinez Canillas 		.data = (void *)ina226
899bd0ddd4dSJavier Martinez Canillas 	},
900bd0ddd4dSJavier Martinez Canillas 	{ },
901bd0ddd4dSJavier Martinez Canillas };
902bd0ddd4dSJavier Martinez Canillas MODULE_DEVICE_TABLE(of, ina2xx_of_match);
903bd0ddd4dSJavier Martinez Canillas 
904f7c2fe38SFelten, Lothar static struct i2c_driver ina2xx_driver = {
905f7c2fe38SFelten, Lothar 	.driver = {
906f7c2fe38SFelten, Lothar 		.name	= "ina2xx",
907bd0ddd4dSJavier Martinez Canillas 		.of_match_table = of_match_ptr(ina2xx_of_match),
908f7c2fe38SFelten, Lothar 	},
9091975d167SUwe Kleine-König 	.probe		= ina2xx_probe,
910f7c2fe38SFelten, Lothar 	.id_table	= ina2xx_id,
911f7c2fe38SFelten, Lothar };
912f7c2fe38SFelten, Lothar 
913d835ca0fSWei Yongjun module_i2c_driver(ina2xx_driver);
914f7c2fe38SFelten, Lothar 
915f7c2fe38SFelten, Lothar MODULE_AUTHOR("Lothar Felten <l-felten@ti.com>");
916f7c2fe38SFelten, Lothar MODULE_DESCRIPTION("ina2xx driver");
917f7c2fe38SFelten, Lothar MODULE_LICENSE("GPL");
918