1 // SPDX-License-Identifier: GPL-2.0-only
3 * Driver for Texas Instruments INA238 power monitor chip
4 * Datasheet: https://www.ti.com/product/ina238
6 * Copyright (C) 2021 Nathan Rossi <nathan.rossi@digi.com>
10 #include <linux/hwmon.h>
11 #include <linux/i2c.h>
12 #include <linux/init.h>
13 #include <linux/kernel.h>
14 #include <linux/module.h>
16 #include <linux/regmap.h>
18 #include <linux/platform_data/ina2xx.h>
20 /* INA238 register definitions */
21 #define INA238_CONFIG 0x0
22 #define INA238_ADC_CONFIG 0x1
23 #define INA238_SHUNT_CALIBRATION 0x2
24 #define INA238_SHUNT_VOLTAGE 0x4
25 #define INA238_BUS_VOLTAGE 0x5
26 #define INA238_DIE_TEMP 0x6
27 #define INA238_CURRENT 0x7
28 #define INA238_POWER 0x8
29 #define INA238_DIAG_ALERT 0xb
30 #define INA238_SHUNT_OVER_VOLTAGE 0xc
31 #define INA238_SHUNT_UNDER_VOLTAGE 0xd
32 #define INA238_BUS_OVER_VOLTAGE 0xe
33 #define INA238_BUS_UNDER_VOLTAGE 0xf
34 #define INA238_TEMP_LIMIT 0x10
35 #define INA238_POWER_LIMIT 0x11
36 #define INA238_DEVICE_ID 0x3f /* not available on INA237 */
38 #define INA238_CONFIG_ADCRANGE BIT(4)
40 #define INA238_DIAG_ALERT_TMPOL BIT(7)
41 #define INA238_DIAG_ALERT_SHNTOL BIT(6)
42 #define INA238_DIAG_ALERT_SHNTUL BIT(5)
43 #define INA238_DIAG_ALERT_BUSOL BIT(4)
44 #define INA238_DIAG_ALERT_BUSUL BIT(3)
45 #define INA238_DIAG_ALERT_POL BIT(2)
47 #define INA238_REGISTERS 0x11
49 #define INA238_RSHUNT_DEFAULT 10000 /* uOhm */
51 /* Default configuration of device on reset. */
52 #define INA238_CONFIG_DEFAULT 0
53 /* 16 sample averaging, 1052us conversion time, continuous mode */
54 #define INA238_ADC_CONFIG_DEFAULT 0xfb6a
55 /* Configure alerts to be based on averaged value (SLOWALERT) */
56 #define INA238_DIAG_ALERT_DEFAULT 0x2000
58 * This driver uses a fixed calibration value in order to scale current/power
59 * based on a fixed shunt resistor value. This allows for conversion within the
60 * device to avoid integer limits whilst current/power accuracy is scaled
61 * relative to the shunt resistor value within the driver. This is similar to
62 * how the ina2xx driver handles current/power scaling.
64 * The end result of this is that increasing shunt values (from a fixed 20 mOhm
65 * shunt) increase the effective current/power accuracy whilst limiting the
66 * range and decreasing shunt values decrease the effective accuracy but
69 * The value of the Current register is calculated given the following:
70 * Current (A) = (shunt voltage register * 5) * calibration / 81920
72 * The maximum shunt voltage is 163.835 mV (0x7fff, ADC_RANGE = 0, gain = 4).
73 * With the maximum current value of 0x7fff and a fixed shunt value results in
74 * a calibration value of 16384 (0x4000).
76 * 0x7fff = (0x7fff * 5) * calibration / 81920
77 * calibration = 0x4000
79 * Equivalent calibration is applied for the Power register (maximum value for
80 * bus voltage is 102396.875 mV, 0x7fff), where the maximum power that can
81 * occur is ~16776192 uW (register value 0x147a8):
83 * This scaling means the resulting values for Current and Power registers need
84 * to be scaled by the difference between the fixed shunt resistor and the
85 * actual shunt resistor:
87 * shunt = 0x4000 / (819.2 * 10^6) / 0.001 = 20000 uOhms (with 1mA/lsb)
89 * Current (mA) = register value * 20000 / rshunt / 4 * gain
90 * Power (W) = 0.2 * register value * 20000 / rshunt / 4 * gain
92 #define INA238_CALIBRATION_VALUE 16384
93 #define INA238_FIXED_SHUNT 20000
95 #define INA238_SHUNT_VOLTAGE_LSB 5 /* 5 uV/lsb */
96 #define INA238_BUS_VOLTAGE_LSB 3125 /* 3.125 mV/lsb */
97 #define INA238_DIE_TEMP_LSB 125 /* 125 mC/lsb */
99 static const struct regmap_config ina238_regmap_config
= {
100 .max_register
= INA238_REGISTERS
,
106 struct i2c_client
*client
;
107 struct mutex config_lock
;
108 struct regmap
*regmap
;
113 static int ina238_read_reg24(const struct i2c_client
*client
, u8 reg
, u32
*val
)
118 /* 24-bit register read */
119 err
= i2c_smbus_read_i2c_block_data(client
, reg
, 3, data
);
124 *val
= (data
[0] << 16) | (data
[1] << 8) | data
[2];
129 static int ina238_read_in(struct device
*dev
, u32 attr
, int channel
,
132 struct ina238_data
*data
= dev_get_drvdata(dev
);
141 reg
= INA238_SHUNT_VOLTAGE
;
144 reg
= INA238_SHUNT_OVER_VOLTAGE
;
147 reg
= INA238_SHUNT_UNDER_VOLTAGE
;
149 case hwmon_in_max_alarm
:
150 reg
= INA238_DIAG_ALERT
;
151 mask
= INA238_DIAG_ALERT_SHNTOL
;
153 case hwmon_in_min_alarm
:
154 reg
= INA238_DIAG_ALERT
;
155 mask
= INA238_DIAG_ALERT_SHNTUL
;
164 reg
= INA238_BUS_VOLTAGE
;
167 reg
= INA238_BUS_OVER_VOLTAGE
;
170 reg
= INA238_BUS_UNDER_VOLTAGE
;
172 case hwmon_in_max_alarm
:
173 reg
= INA238_DIAG_ALERT
;
174 mask
= INA238_DIAG_ALERT_BUSOL
;
176 case hwmon_in_min_alarm
:
177 reg
= INA238_DIAG_ALERT
;
178 mask
= INA238_DIAG_ALERT_BUSUL
;
188 err
= regmap_read(data
->regmap
, reg
, ®val
);
196 /* signed register, value in mV */
197 regval
= (s16
)regval
;
199 /* gain of 1 -> LSB / 4 */
200 *val
= (regval
* INA238_SHUNT_VOLTAGE_LSB
) /
201 (1000 * (4 - data
->gain
+ 1));
203 *val
= (regval
* INA238_BUS_VOLTAGE_LSB
) / 1000;
205 case hwmon_in_max_alarm
:
206 case hwmon_in_min_alarm
:
207 *val
= !!(regval
& mask
);
214 static int ina238_write_in(struct device
*dev
, u32 attr
, int channel
,
217 struct ina238_data
*data
= dev_get_drvdata(dev
);
220 if (attr
!= hwmon_in_max
&& attr
!= hwmon_in_min
)
223 /* convert decimal to register value */
226 /* signed value, clamp to max range +/-163 mV */
227 regval
= clamp_val(val
, -163, 163);
228 regval
= (regval
* 1000 * (4 - data
->gain
+ 1)) /
229 INA238_SHUNT_VOLTAGE_LSB
;
230 regval
= clamp_val(regval
, S16_MIN
, S16_MAX
);
234 return regmap_write(data
->regmap
,
235 INA238_SHUNT_OVER_VOLTAGE
, regval
);
237 return regmap_write(data
->regmap
,
238 INA238_SHUNT_UNDER_VOLTAGE
, regval
);
243 /* signed value, positive values only. Clamp to max 102.396 V */
244 regval
= clamp_val(val
, 0, 102396);
245 regval
= (regval
* 1000) / INA238_BUS_VOLTAGE_LSB
;
246 regval
= clamp_val(regval
, 0, S16_MAX
);
250 return regmap_write(data
->regmap
,
251 INA238_BUS_OVER_VOLTAGE
, regval
);
253 return regmap_write(data
->regmap
,
254 INA238_BUS_UNDER_VOLTAGE
, regval
);
263 static int ina238_read_current(struct device
*dev
, u32 attr
, long *val
)
265 struct ina238_data
*data
= dev_get_drvdata(dev
);
270 case hwmon_curr_input
:
271 err
= regmap_read(data
->regmap
, INA238_CURRENT
, ®val
);
275 /* Signed register, fixed 1mA current lsb. result in mA */
276 *val
= div_s64((s16
)regval
* INA238_FIXED_SHUNT
* data
->gain
,
286 static int ina238_read_power(struct device
*dev
, u32 attr
, long *val
)
288 struct ina238_data
*data
= dev_get_drvdata(dev
);
294 case hwmon_power_input
:
295 err
= ina238_read_reg24(data
->client
, INA238_POWER
, ®val
);
299 /* Fixed 1mA lsb, scaled by 1000000 to have result in uW */
300 power
= div_u64(regval
* 1000ULL * INA238_FIXED_SHUNT
*
301 data
->gain
, 20 * data
->rshunt
);
302 /* Clamp value to maximum value of long */
303 *val
= clamp_val(power
, 0, LONG_MAX
);
305 case hwmon_power_max
:
306 err
= regmap_read(data
->regmap
, INA238_POWER_LIMIT
, ®val
);
311 * Truncated 24-bit compare register, lower 8-bits are
312 * truncated. Same conversion to/from uW as POWER register.
314 power
= div_u64((regval
<< 8) * 1000ULL * INA238_FIXED_SHUNT
*
315 data
->gain
, 20 * data
->rshunt
);
316 /* Clamp value to maximum value of long */
317 *val
= clamp_val(power
, 0, LONG_MAX
);
319 case hwmon_power_max_alarm
:
320 err
= regmap_read(data
->regmap
, INA238_DIAG_ALERT
, ®val
);
324 *val
= !!(regval
& INA238_DIAG_ALERT_POL
);
333 static int ina238_write_power(struct device
*dev
, u32 attr
, long val
)
335 struct ina238_data
*data
= dev_get_drvdata(dev
);
338 if (attr
!= hwmon_power_max
)
342 * Unsigned postive values. Compared against the 24-bit power register,
343 * lower 8-bits are truncated. Same conversion to/from uW as POWER
346 regval
= clamp_val(val
, 0, LONG_MAX
);
347 regval
= div_u64(val
* 20ULL * data
->rshunt
,
348 1000ULL * INA238_FIXED_SHUNT
* data
->gain
);
349 regval
= clamp_val(regval
>> 8, 0, U16_MAX
);
351 return regmap_write(data
->regmap
, INA238_POWER_LIMIT
, regval
);
354 static int ina238_read_temp(struct device
*dev
, u32 attr
, long *val
)
356 struct ina238_data
*data
= dev_get_drvdata(dev
);
361 case hwmon_temp_input
:
362 err
= regmap_read(data
->regmap
, INA238_DIE_TEMP
, ®val
);
366 /* Signed, bits 15-4 of register, result in mC */
367 *val
= ((s16
)regval
>> 4) * INA238_DIE_TEMP_LSB
;
370 err
= regmap_read(data
->regmap
, INA238_TEMP_LIMIT
, ®val
);
374 /* Signed, bits 15-4 of register, result in mC */
375 *val
= ((s16
)regval
>> 4) * INA238_DIE_TEMP_LSB
;
377 case hwmon_temp_max_alarm
:
378 err
= regmap_read(data
->regmap
, INA238_DIAG_ALERT
, ®val
);
382 *val
= !!(regval
& INA238_DIAG_ALERT_TMPOL
);
391 static int ina238_write_temp(struct device
*dev
, u32 attr
, long val
)
393 struct ina238_data
*data
= dev_get_drvdata(dev
);
396 if (attr
!= hwmon_temp_max
)
399 /* Signed, bits 15-4 of register */
400 regval
= (val
/ INA238_DIE_TEMP_LSB
) << 4;
401 regval
= clamp_val(regval
, S16_MIN
, S16_MAX
) & 0xfff0;
403 return regmap_write(data
->regmap
, INA238_TEMP_LIMIT
, regval
);
406 static int ina238_read(struct device
*dev
, enum hwmon_sensor_types type
,
407 u32 attr
, int channel
, long *val
)
411 return ina238_read_in(dev
, attr
, channel
, val
);
413 return ina238_read_current(dev
, attr
, val
);
415 return ina238_read_power(dev
, attr
, val
);
417 return ina238_read_temp(dev
, attr
, val
);
424 static int ina238_write(struct device
*dev
, enum hwmon_sensor_types type
,
425 u32 attr
, int channel
, long val
)
427 struct ina238_data
*data
= dev_get_drvdata(dev
);
430 mutex_lock(&data
->config_lock
);
434 err
= ina238_write_in(dev
, attr
, channel
, val
);
437 err
= ina238_write_power(dev
, attr
, val
);
440 err
= ina238_write_temp(dev
, attr
, val
);
447 mutex_unlock(&data
->config_lock
);
451 static umode_t
ina238_is_visible(const void *drvdata
,
452 enum hwmon_sensor_types type
,
453 u32 attr
, int channel
)
459 case hwmon_in_max_alarm
:
460 case hwmon_in_min_alarm
:
470 case hwmon_curr_input
:
477 case hwmon_power_input
:
478 case hwmon_power_max_alarm
:
480 case hwmon_power_max
:
487 case hwmon_temp_input
:
488 case hwmon_temp_max_alarm
:
500 #define INA238_HWMON_IN_CONFIG (HWMON_I_INPUT | \
501 HWMON_I_MAX | HWMON_I_MAX_ALARM | \
502 HWMON_I_MIN | HWMON_I_MIN_ALARM)
504 static const struct hwmon_channel_info
* const ina238_info
[] = {
505 HWMON_CHANNEL_INFO(in
,
506 /* 0: shunt voltage */
507 INA238_HWMON_IN_CONFIG
,
509 INA238_HWMON_IN_CONFIG
),
510 HWMON_CHANNEL_INFO(curr
,
511 /* 0: current through shunt */
513 HWMON_CHANNEL_INFO(power
,
515 HWMON_P_INPUT
| HWMON_P_MAX
| HWMON_P_MAX_ALARM
),
516 HWMON_CHANNEL_INFO(temp
,
517 /* 0: die temperature */
518 HWMON_T_INPUT
| HWMON_T_MAX
| HWMON_T_MAX_ALARM
),
522 static const struct hwmon_ops ina238_hwmon_ops
= {
523 .is_visible
= ina238_is_visible
,
525 .write
= ina238_write
,
528 static const struct hwmon_chip_info ina238_chip_info
= {
529 .ops
= &ina238_hwmon_ops
,
533 static int ina238_probe(struct i2c_client
*client
)
535 struct ina2xx_platform_data
*pdata
= dev_get_platdata(&client
->dev
);
536 struct device
*dev
= &client
->dev
;
537 struct device
*hwmon_dev
;
538 struct ina238_data
*data
;
542 data
= devm_kzalloc(dev
, sizeof(*data
), GFP_KERNEL
);
546 data
->client
= client
;
547 mutex_init(&data
->config_lock
);
549 data
->regmap
= devm_regmap_init_i2c(client
, &ina238_regmap_config
);
550 if (IS_ERR(data
->regmap
)) {
551 dev_err(dev
, "failed to allocate register map\n");
552 return PTR_ERR(data
->regmap
);
555 /* load shunt value */
556 data
->rshunt
= INA238_RSHUNT_DEFAULT
;
557 if (device_property_read_u32(dev
, "shunt-resistor", &data
->rshunt
) < 0 && pdata
)
558 data
->rshunt
= pdata
->shunt_uohms
;
559 if (data
->rshunt
== 0) {
560 dev_err(dev
, "invalid shunt resister value %u\n", data
->rshunt
);
564 /* load shunt gain value */
565 if (device_property_read_u32(dev
, "ti,shunt-gain", &data
->gain
) < 0)
566 data
->gain
= 4; /* Default of ADCRANGE = 0 */
567 if (data
->gain
!= 1 && data
->gain
!= 4) {
568 dev_err(dev
, "invalid shunt gain value %u\n", data
->gain
);
572 /* Setup CONFIG register */
573 config
= INA238_CONFIG_DEFAULT
;
575 config
|= INA238_CONFIG_ADCRANGE
; /* ADCRANGE = 1 is /1 */
576 ret
= regmap_write(data
->regmap
, INA238_CONFIG
, config
);
578 dev_err(dev
, "error configuring the device: %d\n", ret
);
582 /* Setup ADC_CONFIG register */
583 ret
= regmap_write(data
->regmap
, INA238_ADC_CONFIG
,
584 INA238_ADC_CONFIG_DEFAULT
);
586 dev_err(dev
, "error configuring the device: %d\n", ret
);
590 /* Setup SHUNT_CALIBRATION register with fixed value */
591 ret
= regmap_write(data
->regmap
, INA238_SHUNT_CALIBRATION
,
592 INA238_CALIBRATION_VALUE
);
594 dev_err(dev
, "error configuring the device: %d\n", ret
);
598 /* Setup alert/alarm configuration */
599 ret
= regmap_write(data
->regmap
, INA238_DIAG_ALERT
,
600 INA238_DIAG_ALERT_DEFAULT
);
602 dev_err(dev
, "error configuring the device: %d\n", ret
);
606 hwmon_dev
= devm_hwmon_device_register_with_info(dev
, client
->name
, data
,
609 if (IS_ERR(hwmon_dev
))
610 return PTR_ERR(hwmon_dev
);
612 dev_info(dev
, "power monitor %s (Rshunt = %u uOhm, gain = %u)\n",
613 client
->name
, data
->rshunt
, data
->gain
);
618 static const struct i2c_device_id ina238_id
[] = {
622 MODULE_DEVICE_TABLE(i2c
, ina238_id
);
624 static const struct of_device_id __maybe_unused ina238_of_match
[] = {
625 { .compatible
= "ti,ina237" },
626 { .compatible
= "ti,ina238" },
629 MODULE_DEVICE_TABLE(of
, ina238_of_match
);
631 static struct i2c_driver ina238_driver
= {
634 .of_match_table
= of_match_ptr(ina238_of_match
),
636 .probe
= ina238_probe
,
637 .id_table
= ina238_id
,
640 module_i2c_driver(ina238_driver
);
642 MODULE_AUTHOR("Nathan Rossi <nathan.rossi@digi.com>");
643 MODULE_DESCRIPTION("ina238 driver");
644 MODULE_LICENSE("GPL");