xref: /linux/drivers/hwmon/ina2xx.c (revision ab7fbee452beca56b7c570d49190e679863362d5)
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>
28f7c2fe38SFelten, Lothar #include <linux/err.h>
29f7c2fe38SFelten, Lothar #include <linux/hwmon.h>
30f7c2fe38SFelten, Lothar #include <linux/hwmon-sysfs.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>
389e60bb81SGuenter Roeck #include <linux/util_macros.h>
39f7c2fe38SFelten, Lothar 
40f7c2fe38SFelten, Lothar /* common register definitions */
41f7c2fe38SFelten, Lothar #define INA2XX_CONFIG			0x00
42f7c2fe38SFelten, Lothar #define INA2XX_SHUNT_VOLTAGE		0x01 /* readonly */
43f7c2fe38SFelten, Lothar #define INA2XX_BUS_VOLTAGE		0x02 /* readonly */
44f7c2fe38SFelten, Lothar #define INA2XX_POWER			0x03 /* readonly */
45f7c2fe38SFelten, Lothar #define INA2XX_CURRENT			0x04 /* readonly */
46f7c2fe38SFelten, Lothar #define INA2XX_CALIBRATION		0x05
47f7c2fe38SFelten, Lothar 
48f7c2fe38SFelten, Lothar /* INA226 register definitions */
49f7c2fe38SFelten, Lothar #define INA226_MASK_ENABLE		0x06
50f7c2fe38SFelten, Lothar #define INA226_ALERT_LIMIT		0x07
51f7c2fe38SFelten, Lothar #define INA226_DIE_ID			0xFF
52f7c2fe38SFelten, Lothar 
53f7c2fe38SFelten, Lothar #define INA2XX_MAX_REGISTERS		8
54f7c2fe38SFelten, Lothar 
55f7c2fe38SFelten, Lothar /* settings - depend on use case */
56f7c2fe38SFelten, Lothar #define INA219_CONFIG_DEFAULT		0x399F	/* PGA=8 */
57f7c2fe38SFelten, Lothar #define INA226_CONFIG_DEFAULT		0x4527	/* averages=16 */
58f7c2fe38SFelten, Lothar 
59f7c2fe38SFelten, Lothar /* worst case is 68.10 ms (~14.6Hz, ina219) */
60f7c2fe38SFelten, Lothar #define INA2XX_CONVERSION_RATE		15
61509416a8SBartosz Golaszewski #define INA2XX_MAX_DELAY		69 /* worst case delay in ms */
62509416a8SBartosz Golaszewski 
63509416a8SBartosz Golaszewski #define INA2XX_RSHUNT_DEFAULT		10000
64f7c2fe38SFelten, Lothar 
6572a87a47SBartosz Golaszewski /* bit mask for reading the averaging setting in the configuration register */
66232177a3SGuenter Roeck #define INA226_AVG_RD_MASK		GENMASK(11, 9)
6772a87a47SBartosz Golaszewski 
68232177a3SGuenter Roeck #define INA226_READ_AVG(reg)		FIELD_GET(INA226_AVG_RD_MASK, reg)
6972a87a47SBartosz Golaszewski 
70232177a3SGuenter Roeck #define INA226_ALERT_POLARITY_MASK	BIT(1)
71ec5d234fSAmna Waseem #define INA226_ALERT_POL_LOW		0
72ec5d234fSAmna Waseem #define INA226_ALERT_POL_HIGH		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 /* common attrs, ina226 attrs and NULL */
8672a87a47SBartosz Golaszewski #define INA2XX_MAX_ATTRIBUTE_GROUPS	3
8772a87a47SBartosz Golaszewski 
8872a87a47SBartosz Golaszewski /*
8972a87a47SBartosz Golaszewski  * Both bus voltage and shunt voltage conversion times for ina226 are set
9072a87a47SBartosz Golaszewski  * to 0b0100 on POR, which translates to 2200 microseconds in total.
9172a87a47SBartosz Golaszewski  */
9272a87a47SBartosz Golaszewski #define INA226_TOTAL_CONV_TIME_DEFAULT	2200
9372a87a47SBartosz Golaszewski 
94bb25cdc2SGuenter Roeck static bool ina2xx_writeable_reg(struct device *dev, unsigned int reg)
95bb25cdc2SGuenter Roeck {
96bb25cdc2SGuenter Roeck 	switch (reg) {
97bb25cdc2SGuenter Roeck 	case INA2XX_CONFIG:
98bb25cdc2SGuenter Roeck 	case INA2XX_CALIBRATION:
99bb25cdc2SGuenter Roeck 	case INA226_MASK_ENABLE:
100bb25cdc2SGuenter Roeck 	case INA226_ALERT_LIMIT:
101bb25cdc2SGuenter Roeck 		return true;
102bb25cdc2SGuenter Roeck 	default:
103bb25cdc2SGuenter Roeck 		return false;
104bb25cdc2SGuenter Roeck 	}
105bb25cdc2SGuenter Roeck }
106bb25cdc2SGuenter Roeck 
107bb25cdc2SGuenter Roeck static bool ina2xx_volatile_reg(struct device *dev, unsigned int reg)
108bb25cdc2SGuenter Roeck {
109bb25cdc2SGuenter Roeck 	switch (reg) {
110bb25cdc2SGuenter Roeck 	case INA2XX_SHUNT_VOLTAGE:
111bb25cdc2SGuenter Roeck 	case INA2XX_BUS_VOLTAGE:
112bb25cdc2SGuenter Roeck 	case INA2XX_POWER:
113bb25cdc2SGuenter Roeck 	case INA2XX_CURRENT:
114bb25cdc2SGuenter Roeck 		return true;
115bb25cdc2SGuenter Roeck 	default:
116bb25cdc2SGuenter Roeck 		return false;
117bb25cdc2SGuenter Roeck 	}
118bb25cdc2SGuenter Roeck }
119bb25cdc2SGuenter Roeck 
1202bb47652SGuenter Roeck static const struct regmap_config ina2xx_regmap_config = {
121a0de56c8SMarc Titinger 	.reg_bits = 8,
122a0de56c8SMarc Titinger 	.val_bits = 16,
123bb25cdc2SGuenter Roeck 	.use_single_write = true,
124bb25cdc2SGuenter Roeck 	.use_single_read = true,
1252bb47652SGuenter Roeck 	.max_register = INA2XX_MAX_REGISTERS,
126bb25cdc2SGuenter Roeck 	.cache_type = REGCACHE_MAPLE,
127bb25cdc2SGuenter Roeck 	.volatile_reg = ina2xx_volatile_reg,
128bb25cdc2SGuenter Roeck 	.writeable_reg = ina2xx_writeable_reg,
129a0de56c8SMarc Titinger };
130a0de56c8SMarc Titinger 
131f7c2fe38SFelten, Lothar enum ina2xx_ids { ina219, ina226 };
132f7c2fe38SFelten, Lothar 
1336106db25SGuenter Roeck struct ina2xx_config {
1346106db25SGuenter Roeck 	u16 config_default;
1355d389b12SMaciej Purski 	int calibration_value;
1366106db25SGuenter Roeck 	int shunt_div;
1376106db25SGuenter Roeck 	int bus_voltage_shift;
1386106db25SGuenter Roeck 	int bus_voltage_lsb;	/* uV */
1395d389b12SMaciej Purski 	int power_lsb_factor;
1406106db25SGuenter Roeck };
1416106db25SGuenter Roeck 
142f7c2fe38SFelten, Lothar struct ina2xx_data {
1436106db25SGuenter Roeck 	const struct ina2xx_config *config;
144f7c2fe38SFelten, Lothar 
145509416a8SBartosz Golaszewski 	long rshunt;
1465d389b12SMaciej Purski 	long current_lsb_uA;
1475d389b12SMaciej Purski 	long power_lsb_uW;
148a0de56c8SMarc Titinger 	struct mutex config_lock;
149a0de56c8SMarc Titinger 	struct regmap *regmap;
150f7c2fe38SFelten, Lothar 
15172a87a47SBartosz Golaszewski 	const struct attribute_group *groups[INA2XX_MAX_ATTRIBUTE_GROUPS];
152f7c2fe38SFelten, Lothar };
153f7c2fe38SFelten, Lothar 
1546106db25SGuenter Roeck static const struct ina2xx_config ina2xx_config[] = {
1556106db25SGuenter Roeck 	[ina219] = {
1566106db25SGuenter Roeck 		.config_default = INA219_CONFIG_DEFAULT,
1575d389b12SMaciej Purski 		.calibration_value = 4096,
1586106db25SGuenter Roeck 		.shunt_div = 100,
1596106db25SGuenter Roeck 		.bus_voltage_shift = 3,
1606106db25SGuenter Roeck 		.bus_voltage_lsb = 4000,
1615d389b12SMaciej Purski 		.power_lsb_factor = 20,
1626106db25SGuenter Roeck 	},
1636106db25SGuenter Roeck 	[ina226] = {
1646106db25SGuenter Roeck 		.config_default = INA226_CONFIG_DEFAULT,
1655d389b12SMaciej Purski 		.calibration_value = 2048,
1666106db25SGuenter Roeck 		.shunt_div = 400,
1676106db25SGuenter Roeck 		.bus_voltage_shift = 0,
1686106db25SGuenter Roeck 		.bus_voltage_lsb = 1250,
1695d389b12SMaciej Purski 		.power_lsb_factor = 25,
1706106db25SGuenter Roeck 	},
1716106db25SGuenter Roeck };
1726106db25SGuenter Roeck 
17372a87a47SBartosz Golaszewski /*
17472a87a47SBartosz Golaszewski  * Available averaging rates for ina226. The indices correspond with
17572a87a47SBartosz Golaszewski  * the bit values expected by the chip (according to the ina226 datasheet,
17672a87a47SBartosz Golaszewski  * table 3 AVG bit settings, found at
17749dc2fb0SAlexander A. Klimov  * https://www.ti.com/lit/ds/symlink/ina226.pdf.
17872a87a47SBartosz Golaszewski  */
17972a87a47SBartosz Golaszewski static const int ina226_avg_tab[] = { 1, 4, 16, 64, 128, 256, 512, 1024 };
18072a87a47SBartosz Golaszewski 
18172a87a47SBartosz Golaszewski static int ina226_reg_to_interval(u16 config)
18272a87a47SBartosz Golaszewski {
18372a87a47SBartosz Golaszewski 	int avg = ina226_avg_tab[INA226_READ_AVG(config)];
18472a87a47SBartosz Golaszewski 
18572a87a47SBartosz Golaszewski 	/*
18672a87a47SBartosz Golaszewski 	 * Multiply the total conversion time by the number of averages.
18772a87a47SBartosz Golaszewski 	 * Return the result in milliseconds.
18872a87a47SBartosz Golaszewski 	 */
18972a87a47SBartosz Golaszewski 	return DIV_ROUND_CLOSEST(avg * INA226_TOTAL_CONV_TIME_DEFAULT, 1000);
19072a87a47SBartosz Golaszewski }
19172a87a47SBartosz Golaszewski 
192a0de56c8SMarc Titinger /*
193a0de56c8SMarc Titinger  * Return the new, shifted AVG field value of CONFIG register,
194a0de56c8SMarc Titinger  * to use with regmap_update_bits
195a0de56c8SMarc Titinger  */
196*ab7fbee4SGuenter Roeck static u16 ina226_interval_to_reg(unsigned long interval)
19772a87a47SBartosz Golaszewski {
19872a87a47SBartosz Golaszewski 	int avg, avg_bits;
19972a87a47SBartosz Golaszewski 
200*ab7fbee4SGuenter Roeck 	/*
201*ab7fbee4SGuenter Roeck 	 * The maximum supported interval is 1,024 * (2 * 8.244ms) ~= 16.8s.
202*ab7fbee4SGuenter Roeck 	 * Clamp to 32 seconds before calculations to avoid overflows.
203*ab7fbee4SGuenter Roeck 	 */
204*ab7fbee4SGuenter Roeck 	interval = clamp_val(interval, 0, 32000);
205*ab7fbee4SGuenter Roeck 
20672a87a47SBartosz Golaszewski 	avg = DIV_ROUND_CLOSEST(interval * 1000,
20772a87a47SBartosz Golaszewski 				INA226_TOTAL_CONV_TIME_DEFAULT);
208d38df34eSBartosz Golaszewski 	avg_bits = find_closest(avg, ina226_avg_tab,
209d38df34eSBartosz Golaszewski 				ARRAY_SIZE(ina226_avg_tab));
21072a87a47SBartosz Golaszewski 
211232177a3SGuenter Roeck 	return FIELD_PREP(INA226_AVG_RD_MASK, avg_bits);
21272a87a47SBartosz Golaszewski }
21372a87a47SBartosz Golaszewski 
214ec5d234fSAmna Waseem static int ina2xx_set_alert_polarity(struct ina2xx_data *data,
215ec5d234fSAmna Waseem 				     unsigned long val)
216ec5d234fSAmna Waseem {
217ec5d234fSAmna Waseem 	return regmap_update_bits(data->regmap, INA226_MASK_ENABLE,
218ec5d234fSAmna Waseem 				 INA226_ALERT_POLARITY_MASK,
219232177a3SGuenter Roeck 				 FIELD_PREP(INA226_ALERT_POLARITY_MASK, val));
220ec5d234fSAmna Waseem }
221ec5d234fSAmna Waseem 
2225d389b12SMaciej Purski /*
2235d389b12SMaciej Purski  * Calibration register is set to the best value, which eliminates
2245d389b12SMaciej Purski  * truncation errors on calculating current register in hardware.
2255d389b12SMaciej Purski  * According to datasheet (eq. 3) the best values are 2048 for
2265d389b12SMaciej Purski  * ina226 and 4096 for ina219. They are hardcoded as calibration_value.
2275d389b12SMaciej Purski  */
2288a5fc795SBartosz Golaszewski static int ina2xx_calibrate(struct ina2xx_data *data)
2298a5fc795SBartosz Golaszewski {
2305d389b12SMaciej Purski 	return regmap_write(data->regmap, INA2XX_CALIBRATION,
2315d389b12SMaciej Purski 			    data->config->calibration_value);
2328a5fc795SBartosz Golaszewski }
2338a5fc795SBartosz Golaszewski 
234509416a8SBartosz Golaszewski /*
235509416a8SBartosz Golaszewski  * Initialize the configuration and calibration registers.
236509416a8SBartosz Golaszewski  */
237509416a8SBartosz Golaszewski static int ina2xx_init(struct ina2xx_data *data)
238509416a8SBartosz Golaszewski {
239a0de56c8SMarc Titinger 	int ret = regmap_write(data->regmap, INA2XX_CONFIG,
240a0de56c8SMarc Titinger 			       data->config->config_default);
241509416a8SBartosz Golaszewski 	if (ret < 0)
242509416a8SBartosz Golaszewski 		return ret;
243509416a8SBartosz Golaszewski 
2448a5fc795SBartosz Golaszewski 	return ina2xx_calibrate(data);
245509416a8SBartosz Golaszewski }
246509416a8SBartosz Golaszewski 
247a0de56c8SMarc Titinger static int ina2xx_read_reg(struct device *dev, int reg, unsigned int *regval)
248f7c2fe38SFelten, Lothar {
249468bf0e3SGuenter Roeck 	struct ina2xx_data *data = dev_get_drvdata(dev);
250d491e781SGuenter Roeck 	struct regmap *regmap = data->regmap;
251a0de56c8SMarc Titinger 	int ret, retry;
252509416a8SBartosz Golaszewski 
253509416a8SBartosz Golaszewski 	for (retry = 5; retry; retry--) {
254d491e781SGuenter Roeck 		ret = regmap_read(regmap, reg, regval);
255a0de56c8SMarc Titinger 		if (ret < 0)
256a0de56c8SMarc Titinger 			return ret;
257a0de56c8SMarc Titinger 
258509416a8SBartosz Golaszewski 		/*
259509416a8SBartosz Golaszewski 		 * If the current value in the calibration register is 0, the
260509416a8SBartosz Golaszewski 		 * power and current registers will also remain at 0. In case
261509416a8SBartosz Golaszewski 		 * the chip has been reset let's check the calibration
262509416a8SBartosz Golaszewski 		 * register and reinitialize if needed.
263a0de56c8SMarc Titinger 		 * We do that extra read of the calibration register if there
264a0de56c8SMarc Titinger 		 * is some hint of a chip reset.
265509416a8SBartosz Golaszewski 		 */
266a0de56c8SMarc Titinger 		if (*regval == 0) {
267a0de56c8SMarc Titinger 			unsigned int cal;
268a0de56c8SMarc Titinger 
269bb25cdc2SGuenter Roeck 			ret = regmap_read_bypassed(regmap, INA2XX_CALIBRATION, &cal);
270a0de56c8SMarc Titinger 			if (ret < 0)
271a0de56c8SMarc Titinger 				return ret;
272a0de56c8SMarc Titinger 
273a0de56c8SMarc Titinger 			if (cal == 0) {
274509416a8SBartosz Golaszewski 				dev_warn(dev, "chip not calibrated, reinitializing\n");
275509416a8SBartosz Golaszewski 
276bb25cdc2SGuenter Roeck 				regcache_mark_dirty(regmap);
277bb25cdc2SGuenter Roeck 				regcache_sync(regmap);
278bb25cdc2SGuenter Roeck 
279509416a8SBartosz Golaszewski 				/*
280a0de56c8SMarc Titinger 				 * Let's make sure the power and current
281a0de56c8SMarc Titinger 				 * registers have been updated before trying
282a0de56c8SMarc Titinger 				 * again.
283509416a8SBartosz Golaszewski 				 */
284509416a8SBartosz Golaszewski 				msleep(INA2XX_MAX_DELAY);
285509416a8SBartosz Golaszewski 				continue;
286509416a8SBartosz Golaszewski 			}
287a0de56c8SMarc Titinger 		}
288509416a8SBartosz Golaszewski 		return 0;
289509416a8SBartosz Golaszewski 	}
290509416a8SBartosz Golaszewski 
291509416a8SBartosz Golaszewski 	/*
292509416a8SBartosz Golaszewski 	 * If we're here then although all write operations succeeded, the
293509416a8SBartosz Golaszewski 	 * chip still returns 0 in the calibration register. Nothing more we
294509416a8SBartosz Golaszewski 	 * can do here.
295509416a8SBartosz Golaszewski 	 */
296509416a8SBartosz Golaszewski 	dev_err(dev, "unable to reinitialize the chip\n");
297509416a8SBartosz Golaszewski 	return -ENODEV;
298509416a8SBartosz Golaszewski }
299509416a8SBartosz Golaszewski 
300a0de56c8SMarc Titinger static int ina2xx_get_value(struct ina2xx_data *data, u8 reg,
301a0de56c8SMarc Titinger 			    unsigned int regval)
302f7c2fe38SFelten, Lothar {
3036106db25SGuenter Roeck 	int val;
304f7c2fe38SFelten, Lothar 
305f7c2fe38SFelten, Lothar 	switch (reg) {
306f7c2fe38SFelten, Lothar 	case INA2XX_SHUNT_VOLTAGE:
307c0214f98SFabio Baltieri 		/* signed register */
308a0de56c8SMarc Titinger 		val = DIV_ROUND_CLOSEST((s16)regval, data->config->shunt_div);
309f7c2fe38SFelten, Lothar 		break;
310f7c2fe38SFelten, Lothar 	case INA2XX_BUS_VOLTAGE:
311a0de56c8SMarc Titinger 		val = (regval >> data->config->bus_voltage_shift)
3126106db25SGuenter Roeck 		  * data->config->bus_voltage_lsb;
3136106db25SGuenter Roeck 		val = DIV_ROUND_CLOSEST(val, 1000);
314f7c2fe38SFelten, Lothar 		break;
315f7c2fe38SFelten, Lothar 	case INA2XX_POWER:
3165d389b12SMaciej Purski 		val = regval * data->power_lsb_uW;
317f7c2fe38SFelten, Lothar 		break;
318f7c2fe38SFelten, Lothar 	case INA2XX_CURRENT:
3195d389b12SMaciej Purski 		/* signed register, result in mA */
32038cd989eSNicolin Chen 		val = (s16)regval * data->current_lsb_uA;
3215d389b12SMaciej Purski 		val = DIV_ROUND_CLOSEST(val, 1000);
322f7c2fe38SFelten, Lothar 		break;
3238a5fc795SBartosz Golaszewski 	case INA2XX_CALIBRATION:
3245d389b12SMaciej Purski 		val = regval;
3258a5fc795SBartosz Golaszewski 		break;
326f7c2fe38SFelten, Lothar 	default:
327f7c2fe38SFelten, Lothar 		/* programmer goofed */
328f7c2fe38SFelten, Lothar 		WARN_ON_ONCE(1);
329f7c2fe38SFelten, Lothar 		val = 0;
330f7c2fe38SFelten, Lothar 		break;
331f7c2fe38SFelten, Lothar 	}
332f7c2fe38SFelten, Lothar 
333f7c2fe38SFelten, Lothar 	return val;
334f7c2fe38SFelten, Lothar }
335f7c2fe38SFelten, Lothar 
3366a0f234fSGuenter Roeck static ssize_t ina2xx_value_show(struct device *dev,
337f7c2fe38SFelten, Lothar 				 struct device_attribute *da, char *buf)
338f7c2fe38SFelten, Lothar {
339f7c2fe38SFelten, Lothar 	struct sensor_device_attribute *attr = to_sensor_dev_attr(da);
340a0de56c8SMarc Titinger 	struct ina2xx_data *data = dev_get_drvdata(dev);
341a0de56c8SMarc Titinger 	unsigned int regval;
342f7c2fe38SFelten, Lothar 
343a0de56c8SMarc Titinger 	int err = ina2xx_read_reg(dev, attr->index, &regval);
344a0de56c8SMarc Titinger 
345a0de56c8SMarc Titinger 	if (err < 0)
346a0de56c8SMarc Titinger 		return err;
347f7c2fe38SFelten, Lothar 
348af9a9730SZihao Tang 	return sysfs_emit(buf, "%d\n", ina2xx_get_value(data, attr->index, regval));
349f7c2fe38SFelten, Lothar }
350f7c2fe38SFelten, Lothar 
351232177a3SGuenter Roeck static int ina226_reg_to_alert(struct ina2xx_data *data, u32 mask, u16 regval)
3525a56a39bSAlex Qiu {
3535a56a39bSAlex Qiu 	int reg;
3545a56a39bSAlex Qiu 
355232177a3SGuenter Roeck 	switch (mask) {
356232177a3SGuenter Roeck 	case INA226_SHUNT_OVER_VOLTAGE_MASK:
357232177a3SGuenter Roeck 	case INA226_SHUNT_UNDER_VOLTAGE_MASK:
3585a56a39bSAlex Qiu 		reg = INA2XX_SHUNT_VOLTAGE;
3595a56a39bSAlex Qiu 		break;
360232177a3SGuenter Roeck 	case INA226_BUS_OVER_VOLTAGE_MASK:
361232177a3SGuenter Roeck 	case INA226_BUS_UNDER_VOLTAGE_MASK:
3625a56a39bSAlex Qiu 		reg = INA2XX_BUS_VOLTAGE;
3635a56a39bSAlex Qiu 		break;
364232177a3SGuenter Roeck 	case INA226_POWER_OVER_LIMIT_MASK:
3655a56a39bSAlex Qiu 		reg = INA2XX_POWER;
3665a56a39bSAlex Qiu 		break;
3675a56a39bSAlex Qiu 	default:
3685a56a39bSAlex Qiu 		/* programmer goofed */
3695a56a39bSAlex Qiu 		WARN_ON_ONCE(1);
3705a56a39bSAlex Qiu 		return 0;
3715a56a39bSAlex Qiu 	}
3725a56a39bSAlex Qiu 
3735a56a39bSAlex Qiu 	return ina2xx_get_value(data, reg, regval);
3745a56a39bSAlex Qiu }
3755a56a39bSAlex Qiu 
3765a56a39bSAlex Qiu /*
3775a56a39bSAlex Qiu  * Turns alert limit values into register values.
3785a56a39bSAlex Qiu  * Opposite of the formula in ina2xx_get_value().
3795a56a39bSAlex Qiu  */
380*ab7fbee4SGuenter Roeck static u16 ina226_alert_to_reg(struct ina2xx_data *data, u32 mask, unsigned long val)
3815a56a39bSAlex Qiu {
382232177a3SGuenter Roeck 	switch (mask) {
383232177a3SGuenter Roeck 	case INA226_SHUNT_OVER_VOLTAGE_MASK:
384232177a3SGuenter Roeck 	case INA226_SHUNT_UNDER_VOLTAGE_MASK:
385*ab7fbee4SGuenter Roeck 		val = clamp_val(val, 0, SHRT_MAX * data->config->shunt_div);
3865a56a39bSAlex Qiu 		val *= data->config->shunt_div;
387*ab7fbee4SGuenter Roeck 		return clamp_val(val, 0, SHRT_MAX);
388232177a3SGuenter Roeck 	case INA226_BUS_OVER_VOLTAGE_MASK:
389232177a3SGuenter Roeck 	case INA226_BUS_UNDER_VOLTAGE_MASK:
390*ab7fbee4SGuenter Roeck 		val = clamp_val(val, 0, 200000);
3915a56a39bSAlex Qiu 		val = (val * 1000) << data->config->bus_voltage_shift;
3925a56a39bSAlex Qiu 		val = DIV_ROUND_CLOSEST(val, data->config->bus_voltage_lsb);
393*ab7fbee4SGuenter Roeck 		return clamp_val(val, 0, USHRT_MAX);
394232177a3SGuenter Roeck 	case INA226_POWER_OVER_LIMIT_MASK:
395*ab7fbee4SGuenter Roeck 		val = clamp_val(val, 0, UINT_MAX - data->power_lsb_uW);
3965a56a39bSAlex Qiu 		val = DIV_ROUND_CLOSEST(val, data->power_lsb_uW);
3975a56a39bSAlex Qiu 		return clamp_val(val, 0, USHRT_MAX);
3985a56a39bSAlex Qiu 	default:
3995a56a39bSAlex Qiu 		/* programmer goofed */
4005a56a39bSAlex Qiu 		WARN_ON_ONCE(1);
4015a56a39bSAlex Qiu 		return 0;
4025a56a39bSAlex Qiu 	}
4035a56a39bSAlex Qiu }
4045a56a39bSAlex Qiu 
4055a56a39bSAlex Qiu static ssize_t ina226_alert_show(struct device *dev,
4065a56a39bSAlex Qiu 				 struct device_attribute *da, char *buf)
4075a56a39bSAlex Qiu {
4085a56a39bSAlex Qiu 	struct sensor_device_attribute *attr = to_sensor_dev_attr(da);
4095a56a39bSAlex Qiu 	struct ina2xx_data *data = dev_get_drvdata(dev);
410d491e781SGuenter Roeck 	struct regmap *regmap = data->regmap;
4115a56a39bSAlex Qiu 	int regval;
4125a56a39bSAlex Qiu 	int val = 0;
4135a56a39bSAlex Qiu 	int ret;
4145a56a39bSAlex Qiu 
4155a56a39bSAlex Qiu 	mutex_lock(&data->config_lock);
416d491e781SGuenter Roeck 	ret = regmap_read(regmap, INA226_MASK_ENABLE, &regval);
4175a56a39bSAlex Qiu 	if (ret)
4185a56a39bSAlex Qiu 		goto abort;
4195a56a39bSAlex Qiu 
420232177a3SGuenter Roeck 	if (regval & attr->index) {
421d491e781SGuenter Roeck 		ret = regmap_read(regmap, INA226_ALERT_LIMIT, &regval);
4225a56a39bSAlex Qiu 		if (ret)
4235a56a39bSAlex Qiu 			goto abort;
4245a56a39bSAlex Qiu 		val = ina226_reg_to_alert(data, attr->index, regval);
4255a56a39bSAlex Qiu 	}
4265a56a39bSAlex Qiu 
4271f4d4af4SGuenter Roeck 	ret = sysfs_emit(buf, "%d\n", val);
4285a56a39bSAlex Qiu abort:
4295a56a39bSAlex Qiu 	mutex_unlock(&data->config_lock);
4305a56a39bSAlex Qiu 	return ret;
4315a56a39bSAlex Qiu }
4325a56a39bSAlex Qiu 
4335a56a39bSAlex Qiu static ssize_t ina226_alert_store(struct device *dev,
4345a56a39bSAlex Qiu 				  struct device_attribute *da,
4355a56a39bSAlex Qiu 				  const char *buf, size_t count)
4365a56a39bSAlex Qiu {
4375a56a39bSAlex Qiu 	struct sensor_device_attribute *attr = to_sensor_dev_attr(da);
4385a56a39bSAlex Qiu 	struct ina2xx_data *data = dev_get_drvdata(dev);
439d491e781SGuenter Roeck 	struct regmap *regmap = data->regmap;
4405a56a39bSAlex Qiu 	unsigned long val;
4415a56a39bSAlex Qiu 	int ret;
4425a56a39bSAlex Qiu 
4435a56a39bSAlex Qiu 	ret = kstrtoul(buf, 10, &val);
4445a56a39bSAlex Qiu 	if (ret < 0)
4455a56a39bSAlex Qiu 		return ret;
4465a56a39bSAlex Qiu 
4475a56a39bSAlex Qiu 	/*
4485a56a39bSAlex Qiu 	 * Clear all alerts first to avoid accidentally triggering ALERT pin
4495a56a39bSAlex Qiu 	 * due to register write sequence. Then, only enable the alert
4505a56a39bSAlex Qiu 	 * if the value is non-zero.
4515a56a39bSAlex Qiu 	 */
4525a56a39bSAlex Qiu 	mutex_lock(&data->config_lock);
453d491e781SGuenter Roeck 	ret = regmap_update_bits(regmap, INA226_MASK_ENABLE,
4545a56a39bSAlex Qiu 				 INA226_ALERT_CONFIG_MASK, 0);
4555a56a39bSAlex Qiu 	if (ret < 0)
4565a56a39bSAlex Qiu 		goto abort;
4575a56a39bSAlex Qiu 
458d491e781SGuenter Roeck 	ret = regmap_write(regmap, INA226_ALERT_LIMIT,
4595a56a39bSAlex Qiu 			   ina226_alert_to_reg(data, attr->index, val));
4605a56a39bSAlex Qiu 	if (ret < 0)
4615a56a39bSAlex Qiu 		goto abort;
4625a56a39bSAlex Qiu 
4635a56a39bSAlex Qiu 	if (val != 0) {
464d491e781SGuenter Roeck 		ret = regmap_update_bits(regmap, INA226_MASK_ENABLE,
4655a56a39bSAlex Qiu 					 INA226_ALERT_CONFIG_MASK,
466232177a3SGuenter Roeck 					 attr->index);
4675a56a39bSAlex Qiu 		if (ret < 0)
4685a56a39bSAlex Qiu 			goto abort;
4695a56a39bSAlex Qiu 	}
4705a56a39bSAlex Qiu 
4715a56a39bSAlex Qiu 	ret = count;
4725a56a39bSAlex Qiu abort:
4735a56a39bSAlex Qiu 	mutex_unlock(&data->config_lock);
4745a56a39bSAlex Qiu 	return ret;
4755a56a39bSAlex Qiu }
4765a56a39bSAlex Qiu 
4775a56a39bSAlex Qiu static ssize_t ina226_alarm_show(struct device *dev,
4785a56a39bSAlex Qiu 				 struct device_attribute *da, char *buf)
4795a56a39bSAlex Qiu {
4805a56a39bSAlex Qiu 	struct sensor_device_attribute *attr = to_sensor_dev_attr(da);
4815a56a39bSAlex Qiu 	struct ina2xx_data *data = dev_get_drvdata(dev);
482bb25cdc2SGuenter Roeck 	unsigned int mask;
4835a56a39bSAlex Qiu 	int alarm = 0;
4845a56a39bSAlex Qiu 	int ret;
4855a56a39bSAlex Qiu 
486bb25cdc2SGuenter Roeck 	ret = regmap_read_bypassed(data->regmap, INA226_MASK_ENABLE, &mask);
4875a56a39bSAlex Qiu 	if (ret)
4885a56a39bSAlex Qiu 		return ret;
4895a56a39bSAlex Qiu 
490bb25cdc2SGuenter Roeck 	alarm = (mask & attr->index) &&
491bb25cdc2SGuenter Roeck 		(mask & INA226_ALERT_FUNCTION_FLAG);
492bb25cdc2SGuenter Roeck 
493af9a9730SZihao Tang 	return sysfs_emit(buf, "%d\n", alarm);
4945a56a39bSAlex Qiu }
4955a56a39bSAlex Qiu 
4965d389b12SMaciej Purski /*
4975d389b12SMaciej Purski  * In order to keep calibration register value fixed, the product
4985d389b12SMaciej Purski  * of current_lsb and shunt_resistor should also be fixed and equal
4995d389b12SMaciej Purski  * to shunt_voltage_lsb = 1 / shunt_div multiplied by 10^9 in order
5005d389b12SMaciej Purski  * to keep the scale.
5015d389b12SMaciej Purski  */
502*ab7fbee4SGuenter Roeck static int ina2xx_set_shunt(struct ina2xx_data *data, unsigned long val)
5035d389b12SMaciej Purski {
5045d389b12SMaciej Purski 	unsigned int dividend = DIV_ROUND_CLOSEST(1000000000,
5055d389b12SMaciej Purski 						  data->config->shunt_div);
506*ab7fbee4SGuenter Roeck 	if (!val || val > dividend)
5075d389b12SMaciej Purski 		return -EINVAL;
5085d389b12SMaciej Purski 
5095d389b12SMaciej Purski 	data->rshunt = val;
5105d389b12SMaciej Purski 	data->current_lsb_uA = DIV_ROUND_CLOSEST(dividend, val);
5115d389b12SMaciej Purski 	data->power_lsb_uW = data->config->power_lsb_factor *
5125d389b12SMaciej Purski 			     data->current_lsb_uA;
5135d389b12SMaciej Purski 
5145d389b12SMaciej Purski 	return 0;
5155d389b12SMaciej Purski }
5165d389b12SMaciej Purski 
5176a0f234fSGuenter Roeck static ssize_t ina2xx_shunt_show(struct device *dev,
5186a0f234fSGuenter Roeck 				 struct device_attribute *da, char *buf)
5193ad86700SLothar Felten {
5203ad86700SLothar Felten 	struct ina2xx_data *data = dev_get_drvdata(dev);
5213ad86700SLothar Felten 
522af9a9730SZihao Tang 	return sysfs_emit(buf, "%li\n", data->rshunt);
5233ad86700SLothar Felten }
5243ad86700SLothar Felten 
5256a0f234fSGuenter Roeck static ssize_t ina2xx_shunt_store(struct device *dev,
5268a5fc795SBartosz Golaszewski 				  struct device_attribute *da,
5278a5fc795SBartosz Golaszewski 				  const char *buf, size_t count)
5288a5fc795SBartosz Golaszewski {
5298a5fc795SBartosz Golaszewski 	unsigned long val;
5308a5fc795SBartosz Golaszewski 	int status;
531a0de56c8SMarc Titinger 	struct ina2xx_data *data = dev_get_drvdata(dev);
5328a5fc795SBartosz Golaszewski 
5338a5fc795SBartosz Golaszewski 	status = kstrtoul(buf, 10, &val);
5348a5fc795SBartosz Golaszewski 	if (status < 0)
5358a5fc795SBartosz Golaszewski 		return status;
5368a5fc795SBartosz Golaszewski 
537*ab7fbee4SGuenter Roeck 	mutex_lock(&data->config_lock);
5385d389b12SMaciej Purski 	status = ina2xx_set_shunt(data, val);
539*ab7fbee4SGuenter Roeck 	mutex_unlock(&data->config_lock);
5408a5fc795SBartosz Golaszewski 	if (status < 0)
5418a5fc795SBartosz Golaszewski 		return status;
5428a5fc795SBartosz Golaszewski 	return count;
5438a5fc795SBartosz Golaszewski }
5448a5fc795SBartosz Golaszewski 
5456a0f234fSGuenter Roeck static ssize_t ina226_interval_store(struct device *dev,
54672a87a47SBartosz Golaszewski 				     struct device_attribute *da,
54772a87a47SBartosz Golaszewski 				     const char *buf, size_t count)
54872a87a47SBartosz Golaszewski {
54972a87a47SBartosz Golaszewski 	struct ina2xx_data *data = dev_get_drvdata(dev);
55072a87a47SBartosz Golaszewski 	unsigned long val;
55172a87a47SBartosz Golaszewski 	int status;
55272a87a47SBartosz Golaszewski 
55372a87a47SBartosz Golaszewski 	status = kstrtoul(buf, 10, &val);
55472a87a47SBartosz Golaszewski 	if (status < 0)
55572a87a47SBartosz Golaszewski 		return status;
55672a87a47SBartosz Golaszewski 
557a0de56c8SMarc Titinger 	status = regmap_update_bits(data->regmap, INA2XX_CONFIG,
558a0de56c8SMarc Titinger 				    INA226_AVG_RD_MASK,
559a0de56c8SMarc Titinger 				    ina226_interval_to_reg(val));
56072a87a47SBartosz Golaszewski 	if (status < 0)
56172a87a47SBartosz Golaszewski 		return status;
56272a87a47SBartosz Golaszewski 
56372a87a47SBartosz Golaszewski 	return count;
56472a87a47SBartosz Golaszewski }
56572a87a47SBartosz Golaszewski 
5666a0f234fSGuenter Roeck static ssize_t ina226_interval_show(struct device *dev,
56772a87a47SBartosz Golaszewski 				    struct device_attribute *da, char *buf)
56872a87a47SBartosz Golaszewski {
569a0de56c8SMarc Titinger 	struct ina2xx_data *data = dev_get_drvdata(dev);
570a0de56c8SMarc Titinger 	int status;
571a0de56c8SMarc Titinger 	unsigned int regval;
57272a87a47SBartosz Golaszewski 
573a0de56c8SMarc Titinger 	status = regmap_read(data->regmap, INA2XX_CONFIG, &regval);
574a0de56c8SMarc Titinger 	if (status)
575a0de56c8SMarc Titinger 		return status;
57672a87a47SBartosz Golaszewski 
577af9a9730SZihao Tang 	return sysfs_emit(buf, "%d\n", ina226_reg_to_interval(regval));
57872a87a47SBartosz Golaszewski }
57972a87a47SBartosz Golaszewski 
580f7c2fe38SFelten, Lothar /* shunt voltage */
5816a0f234fSGuenter Roeck static SENSOR_DEVICE_ATTR_RO(in0_input, ina2xx_value, INA2XX_SHUNT_VOLTAGE);
5825a56a39bSAlex Qiu /* shunt voltage over/under voltage alert setting and alarm */
5835a56a39bSAlex Qiu static SENSOR_DEVICE_ATTR_RW(in0_crit, ina226_alert,
584232177a3SGuenter Roeck 			     INA226_SHUNT_OVER_VOLTAGE_MASK);
5855a56a39bSAlex Qiu static SENSOR_DEVICE_ATTR_RW(in0_lcrit, ina226_alert,
586232177a3SGuenter Roeck 			     INA226_SHUNT_UNDER_VOLTAGE_MASK);
5875a56a39bSAlex Qiu static SENSOR_DEVICE_ATTR_RO(in0_crit_alarm, ina226_alarm,
588232177a3SGuenter Roeck 			     INA226_SHUNT_OVER_VOLTAGE_MASK);
5895a56a39bSAlex Qiu static SENSOR_DEVICE_ATTR_RO(in0_lcrit_alarm, ina226_alarm,
590232177a3SGuenter Roeck 			     INA226_SHUNT_UNDER_VOLTAGE_MASK);
591f7c2fe38SFelten, Lothar 
592f7c2fe38SFelten, Lothar /* bus voltage */
5936a0f234fSGuenter Roeck static SENSOR_DEVICE_ATTR_RO(in1_input, ina2xx_value, INA2XX_BUS_VOLTAGE);
5945a56a39bSAlex Qiu /* bus voltage over/under voltage alert setting and alarm */
5955a56a39bSAlex Qiu static SENSOR_DEVICE_ATTR_RW(in1_crit, ina226_alert,
596232177a3SGuenter Roeck 			     INA226_BUS_OVER_VOLTAGE_MASK);
5975a56a39bSAlex Qiu static SENSOR_DEVICE_ATTR_RW(in1_lcrit, ina226_alert,
598232177a3SGuenter Roeck 			     INA226_BUS_UNDER_VOLTAGE_MASK);
5995a56a39bSAlex Qiu static SENSOR_DEVICE_ATTR_RO(in1_crit_alarm, ina226_alarm,
600232177a3SGuenter Roeck 			     INA226_BUS_OVER_VOLTAGE_MASK);
6015a56a39bSAlex Qiu static SENSOR_DEVICE_ATTR_RO(in1_lcrit_alarm, ina226_alarm,
602232177a3SGuenter Roeck 			     INA226_BUS_UNDER_VOLTAGE_MASK);
603f7c2fe38SFelten, Lothar 
604f7c2fe38SFelten, Lothar /* calculated current */
6056a0f234fSGuenter Roeck static SENSOR_DEVICE_ATTR_RO(curr1_input, ina2xx_value, INA2XX_CURRENT);
606f7c2fe38SFelten, Lothar 
607f7c2fe38SFelten, Lothar /* calculated power */
6086a0f234fSGuenter Roeck static SENSOR_DEVICE_ATTR_RO(power1_input, ina2xx_value, INA2XX_POWER);
6095a56a39bSAlex Qiu /* over-limit power alert setting and alarm */
6105a56a39bSAlex Qiu static SENSOR_DEVICE_ATTR_RW(power1_crit, ina226_alert,
611232177a3SGuenter Roeck 			     INA226_POWER_OVER_LIMIT_MASK);
6125a56a39bSAlex Qiu static SENSOR_DEVICE_ATTR_RO(power1_crit_alarm, ina226_alarm,
613232177a3SGuenter Roeck 			     INA226_POWER_OVER_LIMIT_MASK);
614f7c2fe38SFelten, Lothar 
6158a5fc795SBartosz Golaszewski /* shunt resistance */
6166a0f234fSGuenter Roeck static SENSOR_DEVICE_ATTR_RW(shunt_resistor, ina2xx_shunt, INA2XX_CALIBRATION);
6178a5fc795SBartosz Golaszewski 
61872a87a47SBartosz Golaszewski /* update interval (ina226 only) */
6196a0f234fSGuenter Roeck static SENSOR_DEVICE_ATTR_RW(update_interval, ina226_interval, 0);
62072a87a47SBartosz Golaszewski 
621f7c2fe38SFelten, Lothar /* pointers to created device attributes */
622468bf0e3SGuenter Roeck static struct attribute *ina2xx_attrs[] = {
623f7c2fe38SFelten, Lothar 	&sensor_dev_attr_in0_input.dev_attr.attr,
624f7c2fe38SFelten, Lothar 	&sensor_dev_attr_in1_input.dev_attr.attr,
625f7c2fe38SFelten, Lothar 	&sensor_dev_attr_curr1_input.dev_attr.attr,
626f7c2fe38SFelten, Lothar 	&sensor_dev_attr_power1_input.dev_attr.attr,
6278a5fc795SBartosz Golaszewski 	&sensor_dev_attr_shunt_resistor.dev_attr.attr,
628f7c2fe38SFelten, Lothar 	NULL,
629f7c2fe38SFelten, Lothar };
63072a87a47SBartosz Golaszewski 
63172a87a47SBartosz Golaszewski static const struct attribute_group ina2xx_group = {
63272a87a47SBartosz Golaszewski 	.attrs = ina2xx_attrs,
63372a87a47SBartosz Golaszewski };
63472a87a47SBartosz Golaszewski 
63572a87a47SBartosz Golaszewski static struct attribute *ina226_attrs[] = {
6365a56a39bSAlex Qiu 	&sensor_dev_attr_in0_crit.dev_attr.attr,
6375a56a39bSAlex Qiu 	&sensor_dev_attr_in0_lcrit.dev_attr.attr,
6385a56a39bSAlex Qiu 	&sensor_dev_attr_in0_crit_alarm.dev_attr.attr,
6395a56a39bSAlex Qiu 	&sensor_dev_attr_in0_lcrit_alarm.dev_attr.attr,
6405a56a39bSAlex Qiu 	&sensor_dev_attr_in1_crit.dev_attr.attr,
6415a56a39bSAlex Qiu 	&sensor_dev_attr_in1_lcrit.dev_attr.attr,
6425a56a39bSAlex Qiu 	&sensor_dev_attr_in1_crit_alarm.dev_attr.attr,
6435a56a39bSAlex Qiu 	&sensor_dev_attr_in1_lcrit_alarm.dev_attr.attr,
6445a56a39bSAlex Qiu 	&sensor_dev_attr_power1_crit.dev_attr.attr,
6455a56a39bSAlex Qiu 	&sensor_dev_attr_power1_crit_alarm.dev_attr.attr,
64672a87a47SBartosz Golaszewski 	&sensor_dev_attr_update_interval.dev_attr.attr,
64772a87a47SBartosz Golaszewski 	NULL,
64872a87a47SBartosz Golaszewski };
64972a87a47SBartosz Golaszewski 
65072a87a47SBartosz Golaszewski static const struct attribute_group ina226_group = {
65172a87a47SBartosz Golaszewski 	.attrs = ina226_attrs,
65272a87a47SBartosz Golaszewski };
653f7c2fe38SFelten, Lothar 
65467487038SStephen Kitt static int ina2xx_probe(struct i2c_client *client)
655f7c2fe38SFelten, Lothar {
656468bf0e3SGuenter Roeck 	struct device *dev = &client->dev;
657468bf0e3SGuenter Roeck 	struct ina2xx_data *data;
658468bf0e3SGuenter Roeck 	struct device *hwmon_dev;
659468bf0e3SGuenter Roeck 	u32 val;
66072a87a47SBartosz Golaszewski 	int ret, group = 0;
661bd0ddd4dSJavier Martinez Canillas 	enum ina2xx_ids chip;
662bd0ddd4dSJavier Martinez Canillas 
6638b839699SAndrew Davis 	chip = (uintptr_t)i2c_get_match_data(client);
664f7c2fe38SFelten, Lothar 
665468bf0e3SGuenter Roeck 	data = devm_kzalloc(dev, sizeof(*data), GFP_KERNEL);
666f7c2fe38SFelten, Lothar 	if (!data)
667f7c2fe38SFelten, Lothar 		return -ENOMEM;
668f7c2fe38SFelten, Lothar 
669f7c2fe38SFelten, Lothar 	/* set the device type */
670bd0ddd4dSJavier Martinez Canillas 	data->config = &ina2xx_config[chip];
6710c4c5860SMarek Szyprowski 	mutex_init(&data->config_lock);
67272a87a47SBartosz Golaszewski 
67361a4a841SGuenter Roeck 	if (device_property_read_u32(dev, "shunt-resistor", &val) < 0)
674001e2e73SMarc Titinger 		val = INA2XX_RSHUNT_DEFAULT;
675001e2e73SMarc Titinger 
676*ab7fbee4SGuenter Roeck 	ret = ina2xx_set_shunt(data, val);
677*ab7fbee4SGuenter Roeck 	if (ret < 0)
678*ab7fbee4SGuenter Roeck 		return dev_err_probe(dev, ret, "Invalid shunt resistor value\n");
679001e2e73SMarc Titinger 
680a0de56c8SMarc Titinger 	data->regmap = devm_regmap_init_i2c(client, &ina2xx_regmap_config);
681a0de56c8SMarc Titinger 	if (IS_ERR(data->regmap)) {
682a0de56c8SMarc Titinger 		dev_err(dev, "failed to allocate register map\n");
683a0de56c8SMarc Titinger 		return PTR_ERR(data->regmap);
684a0de56c8SMarc Titinger 	}
685a0de56c8SMarc Titinger 
686ad20248aSSvyatoslav Ryhel 	ret = devm_regulator_get_enable(dev, "vs");
687ad20248aSSvyatoslav Ryhel 	if (ret)
688ad20248aSSvyatoslav Ryhel 		return dev_err_probe(dev, ret, "failed to enable vs regulator\n");
689ad20248aSSvyatoslav Ryhel 
690ec5d234fSAmna Waseem 	if (chip == ina226) {
69161a4a841SGuenter Roeck 		if (device_property_read_bool(dev, "ti,alert-polarity-active-high")) {
692ec5d234fSAmna Waseem 			ret = ina2xx_set_alert_polarity(data,
693ec5d234fSAmna Waseem 							INA226_ALERT_POL_HIGH);
694ec5d234fSAmna Waseem 			if (ret < 0) {
695ec5d234fSAmna Waseem 				return dev_err_probe(dev, ret,
696ec5d234fSAmna Waseem 					"failed to set alert polarity active high\n");
697ec5d234fSAmna Waseem 			}
698ec5d234fSAmna Waseem 		} else {
699ec5d234fSAmna Waseem 			/* Set default value i.e active low */
700ec5d234fSAmna Waseem 			ret = ina2xx_set_alert_polarity(data,
701ec5d234fSAmna Waseem 							INA226_ALERT_POL_LOW);
702ec5d234fSAmna Waseem 			if (ret < 0) {
703ec5d234fSAmna Waseem 				return dev_err_probe(dev, ret,
704ec5d234fSAmna Waseem 					"failed to set alert polarity active low\n");
705ec5d234fSAmna Waseem 			}
706ec5d234fSAmna Waseem 		}
707ec5d234fSAmna Waseem 	}
708ec5d234fSAmna Waseem 
709509416a8SBartosz Golaszewski 	ret = ina2xx_init(data);
710509416a8SBartosz Golaszewski 	if (ret < 0) {
711509416a8SBartosz Golaszewski 		dev_err(dev, "error configuring the device: %d\n", ret);
712509416a8SBartosz Golaszewski 		return -ENODEV;
713509416a8SBartosz Golaszewski 	}
714509416a8SBartosz Golaszewski 
71572a87a47SBartosz Golaszewski 	data->groups[group++] = &ina2xx_group;
71670df9ebbSNicolin Chen 	if (chip == ina226)
71772a87a47SBartosz Golaszewski 		data->groups[group++] = &ina226_group;
71872a87a47SBartosz Golaszewski 
719468bf0e3SGuenter Roeck 	hwmon_dev = devm_hwmon_device_register_with_groups(dev, client->name,
72072a87a47SBartosz Golaszewski 							   data, data->groups);
721468bf0e3SGuenter Roeck 	if (IS_ERR(hwmon_dev))
722468bf0e3SGuenter Roeck 		return PTR_ERR(hwmon_dev);
723f7c2fe38SFelten, Lothar 
724468bf0e3SGuenter Roeck 	dev_info(dev, "power monitor %s (Rshunt = %li uOhm)\n",
72570df9ebbSNicolin Chen 		 client->name, data->rshunt);
7266106db25SGuenter Roeck 
727f7c2fe38SFelten, Lothar 	return 0;
728f7c2fe38SFelten, Lothar }
729f7c2fe38SFelten, Lothar 
730f7c2fe38SFelten, Lothar static const struct i2c_device_id ina2xx_id[] = {
731f7c2fe38SFelten, Lothar 	{ "ina219", ina219 },
732dc92cd0cSGuenter Roeck 	{ "ina220", ina219 },
733f7c2fe38SFelten, Lothar 	{ "ina226", ina226 },
734dc92cd0cSGuenter Roeck 	{ "ina230", ina226 },
735add513beSKevin Hilman 	{ "ina231", ina226 },
736f7c2fe38SFelten, Lothar 	{ }
737f7c2fe38SFelten, Lothar };
738f7c2fe38SFelten, Lothar MODULE_DEVICE_TABLE(i2c, ina2xx_id);
739f7c2fe38SFelten, Lothar 
740df6b8c70SGuenter Roeck static const struct of_device_id __maybe_unused ina2xx_of_match[] = {
741bd0ddd4dSJavier Martinez Canillas 	{
742bd0ddd4dSJavier Martinez Canillas 		.compatible = "ti,ina219",
743bd0ddd4dSJavier Martinez Canillas 		.data = (void *)ina219
744bd0ddd4dSJavier Martinez Canillas 	},
745bd0ddd4dSJavier Martinez Canillas 	{
746bd0ddd4dSJavier Martinez Canillas 		.compatible = "ti,ina220",
747bd0ddd4dSJavier Martinez Canillas 		.data = (void *)ina219
748bd0ddd4dSJavier Martinez Canillas 	},
749bd0ddd4dSJavier Martinez Canillas 	{
750bd0ddd4dSJavier Martinez Canillas 		.compatible = "ti,ina226",
751bd0ddd4dSJavier Martinez Canillas 		.data = (void *)ina226
752bd0ddd4dSJavier Martinez Canillas 	},
753bd0ddd4dSJavier Martinez Canillas 	{
754bd0ddd4dSJavier Martinez Canillas 		.compatible = "ti,ina230",
755bd0ddd4dSJavier Martinez Canillas 		.data = (void *)ina226
756bd0ddd4dSJavier Martinez Canillas 	},
757bd0ddd4dSJavier Martinez Canillas 	{
758bd0ddd4dSJavier Martinez Canillas 		.compatible = "ti,ina231",
759bd0ddd4dSJavier Martinez Canillas 		.data = (void *)ina226
760bd0ddd4dSJavier Martinez Canillas 	},
761bd0ddd4dSJavier Martinez Canillas 	{ },
762bd0ddd4dSJavier Martinez Canillas };
763bd0ddd4dSJavier Martinez Canillas MODULE_DEVICE_TABLE(of, ina2xx_of_match);
764bd0ddd4dSJavier Martinez Canillas 
765f7c2fe38SFelten, Lothar static struct i2c_driver ina2xx_driver = {
766f7c2fe38SFelten, Lothar 	.driver = {
767f7c2fe38SFelten, Lothar 		.name	= "ina2xx",
768bd0ddd4dSJavier Martinez Canillas 		.of_match_table = of_match_ptr(ina2xx_of_match),
769f7c2fe38SFelten, Lothar 	},
7701975d167SUwe Kleine-König 	.probe		= ina2xx_probe,
771f7c2fe38SFelten, Lothar 	.id_table	= ina2xx_id,
772f7c2fe38SFelten, Lothar };
773f7c2fe38SFelten, Lothar 
774d835ca0fSWei Yongjun module_i2c_driver(ina2xx_driver);
775f7c2fe38SFelten, Lothar 
776f7c2fe38SFelten, Lothar MODULE_AUTHOR("Lothar Felten <l-felten@ti.com>");
777f7c2fe38SFelten, Lothar MODULE_DESCRIPTION("ina2xx driver");
778f7c2fe38SFelten, Lothar MODULE_LICENSE("GPL");
779