Skip to content

Commit 8aaa503

Browse files
joe-mernashif
authored andcommitted
drivers: sensor: ti: Add INA232 native support
The INA232 is another device in the INA2XX family and is very similar to the already implemented INA230 and INA236. The main difference between the INA232 and the INA236 is that the INA232 does not have a Device ID register. Because of these similarities, it is implemented in the ina230.x files in the same way as the IN236. Modifications to the corresponding tests are included as well. Signed-off-by: Johannes Meyer <[email protected]>
1 parent d5e8273 commit 8aaa503

File tree

9 files changed

+168
-62
lines changed

9 files changed

+168
-62
lines changed

drivers/sensor/ti/ina2xx/Kconfig

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
config INA2XX
88
bool "INA2XX Current and Power Monitor"
99
default y
10-
depends on DT_HAS_TI_INA226_ENABLED || DT_HAS_TI_INA228_ENABLED || DT_HAS_TI_INA230_ENABLED || DT_HAS_TI_INA236_ENABLED || DT_HAS_TI_INA237_ENABLED
10+
depends on DT_HAS_TI_INA226_ENABLED || DT_HAS_TI_INA228_ENABLED || DT_HAS_TI_INA230_ENABLED || DT_HAS_TI_INA232_ENABLED || DT_HAS_TI_INA236_ENABLED || DT_HAS_TI_INA237_ENABLED
1111
select I2C
1212
help
1313
Enable driver for INA2XX Current and Power Monitor.
@@ -48,22 +48,30 @@ config INA226
4848
config INA230
4949
bool "INA230"
5050
default y
51-
depends on DT_HAS_TI_INA230_ENABLED || DT_HAS_TI_INA236_ENABLED
51+
depends on DT_HAS_TI_INA230_ENABLED || DT_HAS_TI_INA232_ENABLED || DT_HAS_TI_INA236_ENABLED
5252
select INA2XX_HAS_CHANNEL_BUS_VOLTAGE
5353
select INA2XX_HAS_CHANNEL_CURRENT
5454
select INA2XX_HAS_CHANNEL_POWER
5555
help
56-
Enable driver for INA230/INA231/INA236.
56+
Enable driver for INA230/INA231/INA232/INA236.
5757

5858
config INA230_TRIGGER
5959
bool "INA230 trigger mode"
6060
depends on INA230
6161
depends on GPIO
62-
depends on $(dt_compat_any_has_prop,$(DT_COMPAT_TI_INA230),alert-gpios) || $(dt_compat_any_has_prop,$(DT_COMPAT_TI_INA236),alert-gpios)
62+
depends on $(dt_compat_any_has_prop,$(DT_COMPAT_TI_INA230),alert-gpios) || $(dt_compat_any_has_prop,$(DT_COMPAT_TI_INA232),alert-gpios) || $(dt_compat_any_has_prop,$(DT_COMPAT_TI_INA236),alert-gpios)
6363
help
6464
Set to enable trigger mode using gpio interrupt, where
6565
interrupts are configured to line ALERT PIN.
6666

67+
config INA232
68+
bool "INA232"
69+
default y
70+
depends on DT_HAS_TI_INA232_ENABLED
71+
select INA230
72+
help
73+
Enable driver for INA232.
74+
6775
config INA236
6876
bool "INA236"
6977
default y

drivers/sensor/ti/ina2xx/ina230.c

Lines changed: 99 additions & 56 deletions
Original file line numberDiff line numberDiff line change
@@ -18,10 +18,12 @@ LOG_MODULE_REGISTER(INA230, CONFIG_SENSOR_LOG_LEVEL);
1818

1919
/** @brief The LSB value for the bus voltage register, in microvolts/LSB. */
2020
#define INA230_BUS_VOLTAGE_UV_LSB 1250U
21+
#define INA232_BUS_VOLTAGE_UV_LSB 1600U
2122
#define INA236_BUS_VOLTAGE_UV_LSB 1600U
2223

2324
/** @brief The scaling for the power register. */
2425
#define INA230_POWER_SCALING 25
26+
#define INA232_POWER_SCALING 32
2527
#define INA236_POWER_SCALING 32
2628

2729
INA2XX_REG_DEFINE(ina230_config, INA230_REG_CONFIG, 16);
@@ -39,6 +41,18 @@ static struct ina2xx_channels ina230_channels = {
3941
};
4042
#endif /* ti_ina230 */
4143

44+
#if DT_HAS_COMPAT_STATUS_OKAY(ti_ina232)
45+
INA2XX_CHANNEL_DEFINE(ina232_current, INA230_REG_CURRENT, 16, 0, 1, 1);
46+
INA2XX_CHANNEL_DEFINE(ina232_bus_voltage, INA230_REG_BUS_VOLT, 16, 0, INA232_BUS_VOLTAGE_UV_LSB, 1);
47+
INA2XX_CHANNEL_DEFINE(ina232_power, INA230_REG_POWER, 16, 0, INA232_POWER_SCALING, 1);
48+
49+
static struct ina2xx_channels ina232_channels = {
50+
.voltage = &ina232_bus_voltage,
51+
.current = &ina232_current,
52+
.power = &ina232_power,
53+
};
54+
#endif /* ti_ina232 */
55+
4256
#if DT_HAS_COMPAT_STATUS_OKAY(ti_ina236)
4357
INA2XX_CHANNEL_DEFINE(ina236_current, INA230_REG_CURRENT, 16, 0, 1, 1);
4458
INA2XX_CHANNEL_DEFINE(ina236_bus_voltage, INA230_REG_BUS_VOLT, 16, 0, INA236_BUS_VOLTAGE_UV_LSB, 1);
@@ -198,67 +212,96 @@ static DEVICE_API(sensor, ina230_driver_api) = {
198212
#define INA230_CFG_IRQ(inst)
199213
#endif /* CONFIG_INA230_TRIGGER */
200214

201-
#define INA230_DT_CONFIG(inst) \
202-
(DT_INST_PROP_OR(inst, high_precision, 0) << 12) | \
203-
(DT_INST_ENUM_IDX(inst, avg_count) << 9) | \
204-
(DT_INST_ENUM_IDX(inst, vbus_conversion_time_us) << 6) | \
205-
(DT_INST_ENUM_IDX(inst, vshunt_conversion_time_us) << 3) | \
206-
(DT_INST_ENUM_IDX(inst, adc_mode))
207-
208-
#define INA230_DT_CAL(inst) \
209-
(uint16_t)(((INA230_CAL_SCALING * 10000000ULL) / \
210-
((uint64_t)DT_INST_PROP(inst, current_lsb_microamps) * \
211-
DT_INST_PROP(inst, rshunt_micro_ohms))) >> \
212-
(DT_INST_PROP_OR(inst, high_precision, 0) << 1))
213-
214-
#define INA230_DRIVER_INIT(inst) \
215-
static struct ina230_data ina230_data_##inst; \
216-
static const struct ina230_config ina230_config_##inst = { \
217-
.common = { \
218-
.bus = I2C_DT_SPEC_INST_GET(inst), \
219-
.current_lsb = DT_INST_PROP(inst, current_lsb_microamps), \
220-
.config = INA230_DT_CONFIG(inst), \
221-
.cal = INA230_DT_CAL(inst), \
222-
.id_reg = NULL, \
223-
.config_reg = &ina230_config, \
224-
.adc_config_reg = NULL, \
225-
.cal_reg = &ina230_cal, \
226-
.channels = &ina230_channels, \
227-
}, \
228-
.uv_lsb = INA230_BUS_VOLTAGE_UV_LSB, \
229-
.power_scale = INA230_POWER_SCALING, \
230-
COND_CODE_1(DT_INST_NODE_HAS_PROP(inst, alert_gpios), \
231-
(INA230_CFG_IRQ(inst)), ())}; \
232-
SENSOR_DEVICE_DT_INST_DEFINE(inst, &ina230_init, NULL, \
233-
&ina230_data_##inst, &ina230_config_##inst, \
234-
POST_KERNEL, CONFIG_SENSOR_INIT_PRIORITY, &ina230_driver_api);
235-
236-
#define INA236_DRIVER_INIT(inst) \
237-
static struct ina230_data ina236_data_##inst; \
238-
static const struct ina230_config ina236_config_##inst = { \
239-
.common = { \
240-
.bus = I2C_DT_SPEC_INST_GET(inst), \
241-
.current_lsb = DT_INST_PROP(inst, current_lsb_microamps), \
242-
.config = INA230_DT_CONFIG(inst), \
243-
.cal = INA230_DT_CAL(inst), \
244-
.id_reg = NULL, \
245-
.config_reg = &ina230_config, \
246-
.adc_config_reg = NULL, \
247-
.cal_reg = &ina230_cal, \
248-
.channels = &ina236_channels, \
249-
}, \
250-
.uv_lsb = INA236_BUS_VOLTAGE_UV_LSB, \
251-
.power_scale = INA236_POWER_SCALING, \
252-
COND_CODE_1(DT_INST_NODE_HAS_PROP(inst, alert_gpios), \
253-
(INA230_CFG_IRQ(inst)), ())}; \
254-
SENSOR_DEVICE_DT_INST_DEFINE(inst, &ina230_init, NULL, \
255-
&ina236_data_##inst, &ina236_config_##inst, \
256-
POST_KERNEL, CONFIG_SENSOR_INIT_PRIORITY, &ina230_driver_api);
215+
#define INA230_DT_CONFIG(inst) \
216+
(DT_INST_PROP_OR(inst, high_precision, 0) << 12) | \
217+
(DT_INST_ENUM_IDX(inst, avg_count) << 9) | \
218+
(DT_INST_ENUM_IDX(inst, vbus_conversion_time_us) << 6) | \
219+
(DT_INST_ENUM_IDX(inst, vshunt_conversion_time_us) << 3) | \
220+
(DT_INST_ENUM_IDX(inst, adc_mode))
221+
222+
#define INA230_DT_CAL(inst) \
223+
(uint16_t)(((INA230_CAL_SCALING * 10000000ULL) / \
224+
((uint64_t)DT_INST_PROP(inst, current_lsb_microamps) * \
225+
DT_INST_PROP(inst, rshunt_micro_ohms))) >> \
226+
(DT_INST_PROP_OR(inst, high_precision, 0) << 1))
227+
228+
#define INA230_DRIVER_INIT(inst) \
229+
static struct ina230_data ina230_data_##inst; \
230+
static const struct ina230_config ina230_config_##inst = { \
231+
.common = \
232+
{ \
233+
.bus = I2C_DT_SPEC_INST_GET(inst), \
234+
.current_lsb = DT_INST_PROP(inst, current_lsb_microamps), \
235+
.config = INA230_DT_CONFIG(inst), \
236+
.cal = INA230_DT_CAL(inst), \
237+
.id_reg = NULL, \
238+
.config_reg = &ina230_config, \
239+
.adc_config_reg = NULL, \
240+
.cal_reg = &ina230_cal, \
241+
.channels = &ina230_channels, \
242+
}, \
243+
.uv_lsb = INA230_BUS_VOLTAGE_UV_LSB, \
244+
.power_scale = INA230_POWER_SCALING, \
245+
COND_CODE_1(DT_INST_NODE_HAS_PROP(inst, alert_gpios), \
246+
(INA230_CFG_IRQ(inst)), ())}; \
247+
SENSOR_DEVICE_DT_INST_DEFINE(inst, &ina230_init, NULL, &ina230_data_##inst, \
248+
&ina230_config_##inst, POST_KERNEL, \
249+
CONFIG_SENSOR_INIT_PRIORITY, &ina230_driver_api);
250+
251+
#define INA232_DRIVER_INIT(inst) \
252+
static struct ina230_data ina232_data_##inst; \
253+
static const struct ina230_config ina232_config_##inst = { \
254+
.common = \
255+
{ \
256+
.bus = I2C_DT_SPEC_INST_GET(inst), \
257+
.current_lsb = DT_INST_PROP(inst, current_lsb_microamps), \
258+
.config = INA230_DT_CONFIG(inst), \
259+
.cal = INA230_DT_CAL(inst), \
260+
.id_reg = NULL, \
261+
.config_reg = &ina230_config, \
262+
.adc_config_reg = NULL, \
263+
.cal_reg = &ina230_cal, \
264+
.channels = &ina232_channels, \
265+
}, \
266+
.uv_lsb = INA232_BUS_VOLTAGE_UV_LSB, \
267+
.power_scale = INA232_POWER_SCALING, \
268+
COND_CODE_1(DT_INST_NODE_HAS_PROP(inst, alert_gpios), \
269+
(INA230_CFG_IRQ(inst)), ())}; \
270+
SENSOR_DEVICE_DT_INST_DEFINE(inst, &ina230_init, NULL, &ina232_data_##inst, \
271+
&ina232_config_##inst, POST_KERNEL, \
272+
CONFIG_SENSOR_INIT_PRIORITY, &ina230_driver_api);
273+
274+
#define INA236_DRIVER_INIT(inst) \
275+
static struct ina230_data ina236_data_##inst; \
276+
static const struct ina230_config ina236_config_##inst = { \
277+
.common = \
278+
{ \
279+
.bus = I2C_DT_SPEC_INST_GET(inst), \
280+
.current_lsb = DT_INST_PROP(inst, current_lsb_microamps), \
281+
.config = INA230_DT_CONFIG(inst), \
282+
.cal = INA230_DT_CAL(inst), \
283+
.id_reg = NULL, \
284+
.config_reg = &ina230_config, \
285+
.adc_config_reg = NULL, \
286+
.cal_reg = &ina230_cal, \
287+
.channels = &ina236_channels, \
288+
}, \
289+
.uv_lsb = INA236_BUS_VOLTAGE_UV_LSB, \
290+
.power_scale = INA236_POWER_SCALING, \
291+
COND_CODE_1(DT_INST_NODE_HAS_PROP(inst, alert_gpios), \
292+
(INA230_CFG_IRQ(inst)), ())}; \
293+
SENSOR_DEVICE_DT_INST_DEFINE(inst, &ina230_init, NULL, &ina236_data_##inst, \
294+
&ina236_config_##inst, POST_KERNEL, \
295+
CONFIG_SENSOR_INIT_PRIORITY, &ina230_driver_api);
257296

258297
#define DT_DRV_COMPAT ti_ina230
259298
DT_INST_FOREACH_STATUS_OKAY(INA230_DRIVER_INIT)
260299
#undef DT_DRV_COMPAT
261300

301+
#define DT_DRV_COMPAT ti_ina232
302+
DT_INST_FOREACH_STATUS_OKAY(INA232_DRIVER_INIT)
303+
#undef DT_DRV_COMPAT
304+
262305
#define DT_DRV_COMPAT ti_ina236
263306
DT_INST_FOREACH_STATUS_OKAY(INA236_DRIVER_INIT)
264307
#undef DT_DRV_COMPAT

drivers/sensor/ti/ina2xx/ina230.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@
2727
#define INA230_REG_CALIB 0x05
2828
#define INA230_REG_MASK 0x06
2929
#define INA230_REG_ALERT 0x07
30+
#define INA232_REG_MANUFACTURER_ID 0x3E
3031
#define INA236_REG_MANUFACTURER_ID 0x3E
3132
#define INA236_REG_DEVICE_ID 0x3F
3233

dts/bindings/sensor/ti,ina232.yaml

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
#
2+
# Copyright 2025 The Zephyr Project Contributors
3+
#
4+
# SPDX-License-Identifier: Apache-2.0
5+
#
6+
7+
description: |
8+
TI INA232 Bidirectional Current and Power Monitor.
9+
The <zephyr/dt-bindings/sensor/ina230.h> file includes the
10+
macro for initializing the config register so it should
11+
be included.
12+
13+
compatible: "ti,ina232"
14+
15+
include: ti,ina230.yaml
16+
17+
properties:
18+
high-precision:
19+
type: boolean
20+
description: |
21+
Enable high precision mode (4x the resolution).

tests/drivers/build_all/sensor/i2c.dtsi

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1445,3 +1445,13 @@ test_i2c_wsen_pdms_25131308XXX05: wsen_pdms_25131308XXX05@c0 {
14451445
reg = <0xc0>;
14461446
sensor-type = <4>;
14471447
};
1448+
1449+
test_i2c_ina232: ina232@c1 {
1450+
compatible = "ti,ina232";
1451+
reg = <0xc1>;
1452+
current-lsb-microamps = <1000>;
1453+
rshunt-micro-ohms = <1000>;
1454+
mask = <0>;
1455+
alert-limit = <0>;
1456+
alert-gpios = <&test_gpio 0 0>;
1457+
};

tests/drivers/sensor/ina230/boards/native_sim.overlay

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,4 +23,12 @@
2323
current-lsb-microamps = <1000>;
2424
status = "okay";
2525
};
26+
27+
ina232_default_test: ina232@42 {
28+
compatible = "ti,ina232";
29+
reg = <0x42>;
30+
rshunt-micro-ohms = <2000>;
31+
current-lsb-microamps = <1000>;
32+
status = "okay";
33+
};
2634
};

tests/drivers/sensor/ina230/src/ina230_emul.c

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -168,6 +168,10 @@ static const struct i2c_emul_api ina230_emul_api_i2c = {
168168
{INA230_REG_MASK, 2, 0}, \
169169
{INA230_REG_ALERT, 2, 0}
170170

171+
#define CREATE_INA232_REGS \
172+
CREATE_INA230_REGS, \
173+
{INA232_REG_MANUFACTURER_ID, 2, 0x5449}
174+
171175
#define CREATE_INA236_REGS \
172176
CREATE_INA230_REGS, \
173177
{INA236_REG_MANUFACTURER_ID, 2, 0x449}, \
@@ -190,6 +194,10 @@ static const struct i2c_emul_api ina230_emul_api_i2c = {
190194
#define DT_DRV_COMPAT ti_ina230
191195
DT_INST_FOREACH_STATUS_OKAY_VARGS(INA230_EMUL, 0)
192196

197+
#undef DT_DRV_COMPAT
198+
#define DT_DRV_COMPAT ti_ina232
199+
DT_INST_FOREACH_STATUS_OKAY_VARGS(INA230_EMUL, 2)
200+
193201
#undef DT_DRV_COMPAT
194202
#define DT_DRV_COMPAT ti_ina236
195203
DT_INST_FOREACH_STATUS_OKAY_VARGS(INA230_EMUL, 6)

tests/drivers/sensor/ina230/src/ina230_emul.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
#define INA230_EMUL_H_
1010

1111
#define INA230_REGISTER_COUNT 8
12+
#define INA232_REGISTER_COUNT 1
1213
#define INA236_REGISTER_COUNT 2
1314

1415
int ina230_mock_set_register(void *data_ptr, int reg, uint32_t value);

tests/drivers/sensor/ina230/src/ina230_test.c

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616

1717
enum ina23x_ids {
1818
INA230,
19+
INA232,
1920
INA236
2021
};
2122

@@ -153,7 +154,8 @@ static void test_bus_voltage(struct ina230_fixture *fixture)
153154
0,
154155
};
155156

156-
double bitres = fixture->dev_type == INA236 ? 1.6e-3 : 1.25e-3;
157+
double bitres =
158+
(fixture->dev_type == INA232 || fixture->dev_type == INA236) ? 1.6e-3 : 1.25e-3;
157159

158160
for (int idx = 0; idx < ARRAY_SIZE(voltage_reg_vectors); idx++) {
159161
struct sensor_value sensor_val;
@@ -186,7 +188,7 @@ static void test_power(struct ina230_fixture *fixture)
186188
0,
187189
};
188190

189-
int scale = fixture->dev_type == INA236 ? 32 : 25;
191+
int scale = (fixture->dev_type == INA232 || fixture->dev_type == INA236) ? 32 : 25;
190192

191193
for (int idx = 0; idx < ARRAY_SIZE(power_reg_vectors); idx++) {
192194
struct sensor_value sensor_val;
@@ -248,6 +250,10 @@ static void test_power(struct ina230_fixture *fixture)
248250
#define DT_DRV_COMPAT ti_ina230
249251
DT_INST_FOREACH_STATUS_OKAY_VARGS(INA230_TESTS, 0)
250252

253+
#undef DT_DRV_COMPAT
254+
#define DT_DRV_COMPAT ti_ina232
255+
DT_INST_FOREACH_STATUS_OKAY_VARGS(INA230_TESTS, 2)
256+
251257
#undef DT_DRV_COMPAT
252258
#define DT_DRV_COMPAT ti_ina236
253259
DT_INST_FOREACH_STATUS_OKAY_VARGS(INA230_TESTS, 6)

0 commit comments

Comments
 (0)