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, ®val);
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, ®val);
3455a56a39bSAlex Qiu if (ret)
3465a56a39bSAlex Qiu goto abort;
3475a56a39bSAlex Qiu
348814db9f1SGuenter Roeck if (regval & mask) {
349d491e781SGuenter Roeck ret = regmap_read(regmap, INA226_ALERT_LIMIT, ®val);
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, ®val);
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, ®val);
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, ®val);
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, ®val);
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