From 2df71409478e2df1f5c3ecf0304b1f9841a0179e Mon Sep 17 00:00:00 2001 From: Bartosz Bilas Date: Mon, 15 Nov 2021 19:51:09 +0100 Subject: [PATCH] drivers: sensor: ina230: driver refactoring Create an explicit ina230 driver which is supposed to work with 230 and 231 variants. While at it switch to i2c_dt_spec helpers and change device-tree node names to use - instead of _ in order to follow convention. Signed-off-by: Bartosz Bilas --- drivers/sensor/ina23x/CMakeLists.txt | 4 +- drivers/sensor/ina23x/Kconfig | 10 +- drivers/sensor/ina23x/ina230.c | 349 ++++++++++++++++ drivers/sensor/ina23x/ina230.h | 54 +++ .../{ina23x_trigger.c => ina230_trigger.c} | 39 +- drivers/sensor/ina23x/ina23x.c | 374 ------------------ drivers/sensor/ina23x/ina23x.h | 53 --- dts/bindings/sensor/ti,ina230.yaml | 36 ++ dts/bindings/sensor/ti,ina23x.yaml | 56 --- include/dt-bindings/sensor/ina230.h | 68 ++++ include/dt-bindings/sensor/ina23x.h | 67 ---- tests/drivers/build_all/sensor/i2c.dtsi | 22 +- tests/drivers/build_all/sensor/prj.conf | 1 + .../build_all/sensor/sensors_trigger_own.conf | 2 +- 14 files changed, 556 insertions(+), 579 deletions(-) create mode 100644 drivers/sensor/ina23x/ina230.c create mode 100644 drivers/sensor/ina23x/ina230.h rename drivers/sensor/ina23x/{ina23x_trigger.c => ina230_trigger.c} (51%) delete mode 100644 drivers/sensor/ina23x/ina23x.c delete mode 100644 drivers/sensor/ina23x/ina23x.h create mode 100644 dts/bindings/sensor/ti,ina230.yaml delete mode 100644 dts/bindings/sensor/ti,ina23x.yaml create mode 100644 include/dt-bindings/sensor/ina230.h delete mode 100644 include/dt-bindings/sensor/ina23x.h diff --git a/drivers/sensor/ina23x/CMakeLists.txt b/drivers/sensor/ina23x/CMakeLists.txt index 7f9a24681ab..cd165d8db5b 100644 --- a/drivers/sensor/ina23x/CMakeLists.txt +++ b/drivers/sensor/ina23x/CMakeLists.txt @@ -2,6 +2,6 @@ zephyr_library() -zephyr_library_sources(ina23x.c) zephyr_library_sources(ina23x_common.c) -zephyr_library_sources_ifdef(CONFIG_INA23X_TRIGGER ina23x_trigger.c) +zephyr_library_sources_ifdef(CONFIG_INA230 ina230.c) +zephyr_library_sources_ifdef(CONFIG_INA230_TRIGGER ina230_trigger.c) diff --git a/drivers/sensor/ina23x/Kconfig b/drivers/sensor/ina23x/Kconfig index a8125b5510e..a309c085dd5 100644 --- a/drivers/sensor/ina23x/Kconfig +++ b/drivers/sensor/ina23x/Kconfig @@ -10,8 +10,14 @@ config INA23X if INA23X -config INA23X_TRIGGER - bool "Trigger mode" +config INA230 + bool "INA230" + help + Enable driver for INA230/INA231. + +config INA230_TRIGGER + bool "INA230 trigger mode" + depends on INA230 help Set to enable trigger mode using gpio interrupt, where interrupts are configured to line ALERT PIN. diff --git a/drivers/sensor/ina23x/ina230.c b/drivers/sensor/ina23x/ina230.c new file mode 100644 index 00000000000..ae6d8a1fa17 --- /dev/null +++ b/drivers/sensor/ina23x/ina230.c @@ -0,0 +1,349 @@ +/* + * Copyright 2021 The Chromium OS Authors + * Copyright 2021 Grinn + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#define DT_DRV_COMPAT ti_ina230 + +#include +#include +#include "ina230.h" +#include "ina23x_common.h" + +LOG_MODULE_REGISTER(INA230, CONFIG_SENSOR_LOG_LEVEL); + +/** + * @brief Internal fixed value of INA230 that is used to ensure + * scaling is properly maintained. + * + */ +#define INA230_INTERNAL_FIXED_SCALING_VALUE 5120 + +/** + * @brief The LSB value for the bus voltage register. + * + */ +#define INA230_BUS_VOLTAGE_LSB 125 + +/** + * @brief The LSB value for the power register. + * + */ +#define INA230_POWER_VALUE_LSB 25 + +/** + * @brief sensor value get + * + * @retval 0 for success + * @retval -ENOTSUP for unsupported channels + */ +static int ina230_channel_get(const struct device *dev, + enum sensor_channel chan, + struct sensor_value *val) +{ + struct ina230_data *data = dev->data; + const struct ina230_config *const config = dev->config; + + switch (chan) { + case SENSOR_CHAN_VOLTAGE: + if (config->current_lsb == INA23X_CURRENT_LSB_1MA) { + uint32_t bus_mv = ((data->bus_voltage * + INA230_BUS_VOLTAGE_LSB) / 100); + + val->val1 = bus_mv / 1000U; + val->val2 = (bus_mv % 1000) * 1000; + } else { + val->val1 = data->bus_voltage; + val->val2 = 0; + } + break; + + case SENSOR_CHAN_CURRENT: + if (config->current_lsb == INA23X_CURRENT_LSB_1MA) { + /** + * If current is negative, convert it to a + * magnitude and return the negative of that + * magnitude. + */ + if (data->current & INA23X_CURRENT_SIGN_BIT) { + uint16_t current_mag = (~data->current + 1); + + val->val1 = -(current_mag / 1000U); + val->val2 = -(current_mag % 1000) * 1000; + } else { + val->val1 = data->current / 1000U; + val->val2 = (data->current % 1000) * 1000; + } + } else { + val->val1 = data->current; + val->val2 = 0; + } + break; + + case SENSOR_CHAN_POWER: + if (config->current_lsb == INA23X_CURRENT_LSB_1MA) { + uint32_t power_mw = data->power * INA230_POWER_VALUE_LSB; + + val->val1 = power_mw / 1000U; + val->val2 = (power_mw % 1000) * 1000; + } else { + val->val1 = data->power; + val->val2 = 0; + } + break; + + default: + return -ENOTSUP; + } + + return 0; +} + +/** + * @brief sensor sample fetch + * + * @retval 0 for success + * @retval -ENOTSUP for unsupported channels + */ +static int ina230_sample_fetch(const struct device *dev, + enum sensor_channel chan) +{ + struct ina230_data *data = dev->data; + const struct ina230_config *config = dev->config; + int ret; + + if (chan != SENSOR_CHAN_ALL && + chan != SENSOR_CHAN_VOLTAGE && + chan != SENSOR_CHAN_CURRENT && + chan != SENSOR_CHAN_POWER) { + return -ENOTSUP; + } + + if ((chan == SENSOR_CHAN_ALL) || (chan == SENSOR_CHAN_VOLTAGE)) { + ret = ina23x_reg_read_16(&config->bus, INA230_REG_BUS_VOLT, &data->bus_voltage); + if (ret < 0) { + LOG_ERR("Failed to read bus voltage"); + return ret; + } + } + + if ((chan == SENSOR_CHAN_ALL) || (chan == SENSOR_CHAN_CURRENT)) { + ret = ina23x_reg_read_16(&config->bus, INA230_REG_CURRENT, &data->current); + if (ret < 0) { + LOG_ERR("Failed to read current"); + return ret; + } + } + + if ((chan == SENSOR_CHAN_ALL) || (chan == SENSOR_CHAN_POWER)) { + ret = ina23x_reg_read_16(&config->bus, INA230_REG_POWER, &data->power); + if (ret < 0) { + LOG_ERR("Failed to read power"); + return ret; + } + } + + return 0; +} + +/** + * @brief sensor attribute set + * + * @retval 0 for success + * @retval -ENOTSUP for unsupported channels + * @retval -EIO for i2c write failure + */ +static int ina230_attr_set(const struct device *dev, enum sensor_channel chan, + enum sensor_attribute attr, + const struct sensor_value *val) +{ + const struct ina230_config *config = dev->config; + uint16_t data = val->val1; + + switch (attr) { + case SENSOR_ATTR_CONFIGURATION: + return ina23x_reg_write(&config->bus, INA230_REG_CONFIG, data); + case SENSOR_ATTR_CALIBRATION: + return ina23x_reg_write(&config->bus, INA230_REG_CALIB, data); + case SENSOR_ATTR_FEATURE_MASK: + return ina23x_reg_write(&config->bus, INA230_REG_MASK, data); + case SENSOR_ATTR_ALERT: + return ina23x_reg_write(&config->bus, INA230_REG_ALERT, data); + default: + LOG_ERR("INA230 attribute not supported."); + return -ENOTSUP; + } +} + +/** + * @brief sensor attribute get + * + * @retval 0 for success + * @retval -ENOTSUP for unsupported channels + * @retval -EIO for i2c read failure + */ +static int ina230_attr_get(const struct device *dev, enum sensor_channel chan, + enum sensor_attribute attr, + struct sensor_value *val) +{ + const struct ina230_config *config = dev->config; + uint16_t data; + int ret; + + switch (attr) { + case SENSOR_ATTR_CONFIGURATION: + ret = ina23x_reg_read_16(&config->bus, INA230_REG_CONFIG, &data); + if (ret < 0) { + return ret; + } + break; + case SENSOR_ATTR_CALIBRATION: + ret = ina23x_reg_read_16(&config->bus, INA230_REG_CALIB, &data); + if (ret < 0) { + return ret; + } + break; + case SENSOR_ATTR_FEATURE_MASK: + ret = ina23x_reg_read_16(&config->bus, INA230_REG_MASK, &data); + if (ret < 0) { + return ret; + } + break; + case SENSOR_ATTR_ALERT: + ret = ina23x_reg_read_16(&config->bus, INA230_REG_ALERT, &data); + if (ret < 0) { + return ret; + } + break; + default: + LOG_ERR("INA230 attribute not supported."); + return -ENOTSUP; + } + + val->val1 = data; + val->val2 = 0; + + return 0; +} + +/** + * @brief sensor calibrate + * + * @retval 0 for success + * @retval -EIO for i2c write failure + */ +static int ina230_calibrate(const struct device *dev) +{ + const struct ina230_config *config = dev->config; + uint16_t val; + int ret; + + val = (INA230_INTERNAL_FIXED_SCALING_VALUE / (config->current_lsb * config->rshunt)); + + ret = ina23x_reg_write(&config->bus, INA230_REG_CALIB, val); + if (ret < 0) { + return ret; + } + + return 0; +} + +/** + * @brief Initialize the INA230 + * + * @retval 0 for success + * @retval -EINVAL on error + */ +static int ina230_init(const struct device *dev) +{ + const struct ina230_config *const config = dev->config; + int ret; + + if (!device_is_ready(config->bus.bus)) { + LOG_ERR("I2C bus %s is not ready", config->bus.bus->name); + return -ENODEV; + } + + ret = ina23x_reg_write(&config->bus, INA230_REG_CONFIG, config->config); + if (ret < 0) { + LOG_ERR("Failed to write configuration register!"); + return ret; + } + + ret = ina230_calibrate(dev); + if (ret < 0) { + LOG_ERR("Failed to write calibration register!"); + return ret; + } + +#ifdef CONFIG_INA230_TRIGGER + if (config->trig_enabled) { + ret = ina230_trigger_mode_init(dev); + if (ret < 0) { + LOG_ERR("Failed to init trigger mode\n"); + return ret; + } + + ret = ina23x_reg_write(&config->bus, INA230_REG_ALERT, + config->alert_limit); + if (ret < 0) { + LOG_ERR("Failed to write alert register!"); + return ret; + } + + ret = ina23x_reg_write(&config->bus, INA230_REG_MASK, config->mask); + if (ret < 0) { + LOG_ERR("Failed to write mask register!"); + return ret; + } + } +#endif /* CONFIG_INA230_TRIGGER */ + + return 0; +} + +static const struct sensor_driver_api ina230_driver_api = { + .attr_set = ina230_attr_set, + .attr_get = ina230_attr_get, +#ifdef CONFIG_INA230_TRIGGER + .trigger_set = ina230_trigger_set, +#endif + .sample_fetch = ina230_sample_fetch, + .channel_get = ina230_channel_get, +}; + +BUILD_ASSERT(DT_NUM_INST_STATUS_OKAY(DT_DRV_COMPAT) > 0, + "No compatible ina230 instances found"); + +#ifdef CONFIG_INA230_TRIGGER +#define INA230_CFG_IRQ(inst) \ + .trig_enabled = true, \ + .mask = DT_INST_PROP(inst, mask), \ + .alert_limit = DT_INST_PROP(inst, alert_limit), \ + .gpio_alert = GPIO_DT_SPEC_INST_GET(inst, irq_gpios) +#else +#define INA230_CFG_IRQ(inst) +#endif /* CONFIG_INA230_TRIGGER */ + +#define INA230_DRIVER_INIT(inst) \ + static struct ina230_data drv_data_##inst; \ + static const struct ina230_config drv_config_##inst = { \ + .bus = I2C_DT_SPEC_INST_GET(inst), \ + .config = DT_INST_PROP(inst, config), \ + .current_lsb = DT_INST_PROP(inst, current_lsb), \ + .rshunt = DT_INST_PROP(inst, rshunt), \ + COND_CODE_1(DT_INST_NODE_HAS_PROP(inst, irq_gpios), \ + (INA230_CFG_IRQ(inst)), ()) \ + }; \ + DEVICE_DT_INST_DEFINE(inst, \ + &ina230_init, \ + NULL, \ + &drv_data_##inst, \ + &drv_config_##inst, \ + POST_KERNEL, \ + CONFIG_SENSOR_INIT_PRIORITY, \ + &ina230_driver_api); + +DT_INST_FOREACH_STATUS_OKAY(INA230_DRIVER_INIT) diff --git a/drivers/sensor/ina23x/ina230.h b/drivers/sensor/ina23x/ina230.h new file mode 100644 index 00000000000..a53c812efa6 --- /dev/null +++ b/drivers/sensor/ina23x/ina230.h @@ -0,0 +1,54 @@ +/* + * Copyright 2021 The Chromium OS Authors + * Copyright (c) 2021 Grinn + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#ifndef ZEPHYR_DRIVERS_SENSOR_INA23X_INA230_H_ +#define ZEPHYR_DRIVERS_SENSOR_INA23X_INA230_H_ + +#include +#include + +#define INA230_REG_CONFIG 0x00 +#define INA230_REG_SHUNT_VOLT 0x01 +#define INA230_REG_BUS_VOLT 0x02 +#define INA230_REG_POWER 0x03 +#define INA230_REG_CURRENT 0x04 +#define INA230_REG_CALIB 0x05 +#define INA230_REG_MASK 0x06 +#define INA230_REG_ALERT 0x07 + +struct ina230_data { + const struct device *dev; + uint16_t current; + uint16_t bus_voltage; + uint16_t power; +#ifdef CONFIG_INA230_TRIGGER + const struct device *gpio; + struct gpio_callback gpio_cb; + struct k_work work; + sensor_trigger_handler_t handler_alert; +#endif /* CONFIG_INA230_TRIGGER */ +}; + +struct ina230_config { + struct i2c_dt_spec bus; + uint16_t config; + uint16_t current_lsb; + uint16_t rshunt; +#ifdef CONFIG_INA230_TRIGGER + bool trig_enabled; + uint16_t mask; + const struct gpio_dt_spec gpio_alert; + uint16_t alert_limit; +#endif /* CONFIG_INA230_TRIGGER */ +}; + +int ina230_trigger_mode_init(const struct device *dev); +int ina230_trigger_set(const struct device *dev, + const struct sensor_trigger *trig, + sensor_trigger_handler_t handler); + +#endif /* ZEPHYR_DRIVERS_SENSOR_INA23X_INA230_H_ */ diff --git a/drivers/sensor/ina23x/ina23x_trigger.c b/drivers/sensor/ina23x/ina230_trigger.c similarity index 51% rename from drivers/sensor/ina23x/ina23x_trigger.c rename to drivers/sensor/ina23x/ina230_trigger.c index ad8dcf2180a..d63321a4dd3 100644 --- a/drivers/sensor/ina23x/ina23x_trigger.c +++ b/drivers/sensor/ina23x/ina230_trigger.c @@ -1,5 +1,6 @@ /* * Copyright 2021 The Chromium OS Authors + * Copyright 2021 Grinn * * SPDX-License-Identifier: Apache-2.0 */ @@ -8,44 +9,44 @@ #include #include -#include "ina23x.h" +#include "ina230.h" -LOG_MODULE_DECLARE(INA23X, CONFIG_SENSOR_LOG_LEVEL); +LOG_MODULE_DECLARE(INA230, CONFIG_SENSOR_LOG_LEVEL); -static void ina23x_gpio_callback(const struct device *port, +static void ina230_gpio_callback(const struct device *port, struct gpio_callback *cb, uint32_t pin) { - struct sensor_trigger ina23x_trigger; - struct ina23x_data *ina23x = CONTAINER_OF(cb, struct ina23x_data, gpio_cb); - const struct device *dev = (const struct device *)ina23x->dev; + struct sensor_trigger ina230_trigger; + struct ina230_data *ina230 = CONTAINER_OF(cb, struct ina230_data, gpio_cb); + const struct device *dev = (const struct device *)ina230->dev; ARG_UNUSED(port); ARG_UNUSED(pin); ARG_UNUSED(cb); - if (ina23x->handler_alert) { - ina23x_trigger.type = SENSOR_TRIG_DATA_READY; - ina23x->handler_alert(dev, &ina23x_trigger); + if (ina230->handler_alert) { + ina230_trigger.type = SENSOR_TRIG_DATA_READY; + ina230->handler_alert(dev, &ina230_trigger); } } -int ina23x_trigger_set(const struct device *dev, +int ina230_trigger_set(const struct device *dev, const struct sensor_trigger *trig, sensor_trigger_handler_t handler) { - struct ina23x_data *ina23x = dev->data; + struct ina230_data *ina230 = dev->data; ARG_UNUSED(trig); - ina23x->handler_alert = handler; + ina230->handler_alert = handler; return 0; } -int ina23x_trigger_mode_init(const struct device *dev) +int ina230_trigger_mode_init(const struct device *dev) { - struct ina23x_data *ina23x = dev->data; - const struct ina23x_config *config = dev->config; + struct ina230_data *ina230 = dev->data; + const struct ina230_config *config = dev->config; int ret; /* setup alert gpio interrupt */ @@ -54,7 +55,7 @@ int ina23x_trigger_mode_init(const struct device *dev) return -ENODEV; } - ina23x->dev = dev; + ina230->dev = dev; ret = gpio_pin_configure_dt(&config->gpio_alert, GPIO_INPUT); if (ret < 0) { @@ -62,11 +63,11 @@ int ina23x_trigger_mode_init(const struct device *dev) return ret; } - gpio_init_callback(&ina23x->gpio_cb, - ina23x_gpio_callback, + gpio_init_callback(&ina230->gpio_cb, + ina230_gpio_callback, BIT(config->gpio_alert.pin)); - ret = gpio_add_callback(config->gpio_alert.port, &ina23x->gpio_cb); + ret = gpio_add_callback(config->gpio_alert.port, &ina230->gpio_cb); if (ret < 0) { LOG_ERR("Could not set gpio callback"); return ret; diff --git a/drivers/sensor/ina23x/ina23x.c b/drivers/sensor/ina23x/ina23x.c deleted file mode 100644 index 47f796a758f..00000000000 --- a/drivers/sensor/ina23x/ina23x.c +++ /dev/null @@ -1,374 +0,0 @@ -/* - * Copyright 2021 The Chromium OS Authors - * - * SPDX-License-Identifier: Apache-2.0 - */ - -#define DT_DRV_COMPAT ti_ina23x - -#include -#include -#include -#include -#include -#include - -#include "ina23x.h" - -LOG_MODULE_REGISTER(INA23X, CONFIG_SENSOR_LOG_LEVEL); - -/** - * @brief Macro used to test if the current's sign bit is set - */ -#define CURRENT_SIGN_BIT 0x8000 - -/** - * @brief Macro used to check if the current's LSB is 1mA - */ -#define CURRENT_LSB_1MA 1 - -/** - * @brief Macro for creating the INA23X calibration value - * CALIB = (5120 / (current_lsb * rshunt)) - * NOTE: The 5120 value is a fixed value internal to the - * INA23X that is used to ensure scaling is properly - * maintained. - * - * @param current_lsb Value of the Current register LSB in milliamps - * @param rshunt Shunt resistor value in milliohms - */ - #define INA23X_CALIB(current_lsb, rshunt) (5120 / ((current_lsb) * (rshunt))) - -/** - * @brief Macro to convert raw Bus voltage to millivolts when current_lsb is - * set to 1mA. - * - * reg value read from bus voltage register - * clsb value of current_lsb - */ -#define INA23X_BUS_MV(reg) ((reg) * 125 / 100) - -/** - * @brief Macro to convert raw power value to milliwatts when current_lsb is - * set to 1mA. - * - * reg value read from power register - * clsb value of current_lsb - */ -#define INA23X_POW_MW(reg) ((reg) * 25) - -static int ina23x_reg_read(const struct device *dev, uint8_t reg, int16_t *val) -{ - const struct ina23x_config *const config = dev->config; - uint8_t data[2]; - int ret; - - ret = i2c_burst_read(config->bus, config->i2c_slv_addr, reg, data, 2); - if (ret < 0) { - return ret; - } - - *val = sys_get_be16(data); - - return ret; -} - -static int ina23x_reg_write(const struct device *dev, uint8_t reg, uint16_t val) -{ - const struct ina23x_config *const config = dev->config; - uint8_t tx_buf[3]; - - tx_buf[0] = reg; - sys_put_be16(val, &tx_buf[1]); - - return i2c_write(config->bus, tx_buf, sizeof(tx_buf), config->i2c_slv_addr); -} - -/** - * @brief sensor value get - * - * @return 0 for success - * @return -ENOTSUP for unsupported channels - */ -static int ina23x_channel_get(const struct device *dev, - enum sensor_channel chan, - struct sensor_value *val) -{ - struct ina23x_data *ina23x = dev->data; - const struct ina23x_config *const config = dev->config; - - switch (chan) { - case SENSOR_CHAN_VOLTAGE: - if (config->current_lsb == CURRENT_LSB_1MA) { - val->val1 = INA23X_BUS_MV(ina23x->bus_voltage) / 1000U; - val->val2 = (INA23X_BUS_MV(ina23x->bus_voltage) % 1000) * 1000; - } else { - val->val1 = ina23x->bus_voltage; - val->val2 = 0; - } - break; - - case SENSOR_CHAN_CURRENT: - if (config->current_lsb == CURRENT_LSB_1MA) { - /** - * If current is negative, convert it to a - * magnitude and return the negative of that - * magnitude. - */ - if (ina23x->current & CURRENT_SIGN_BIT) { - uint16_t current_mag = (~ina23x->current + 1); - - val->val1 = -(current_mag / 1000U); - val->val2 = -(current_mag % 1000) * 1000; - } else { - val->val1 = ina23x->current / 1000U; - val->val2 = (ina23x->current % 1000) * 1000; - } - } else { - val->val1 = ina23x->current; - val->val2 = 0; - } - break; - - case SENSOR_CHAN_POWER: - if (config->current_lsb == CURRENT_LSB_1MA) { - val->val1 = INA23X_POW_MW(ina23x->power) / 1000U; - val->val2 = (INA23X_POW_MW(ina23x->power) % 1000) * 1000; - } else { - val->val1 = ina23x->power; - val->val2 = 0; - } - break; - - default: - return -ENOTSUP; - } - - return 0; -} - -/** - * @brief sensor sample fetch - * - * @return 0 for success - * @return -ENOTSUP for unsupported channels - */ -static int ina23x_sample_fetch(const struct device *dev, - enum sensor_channel chan) -{ - struct ina23x_data *ina23x = dev->data; - int ret; - - if (chan != SENSOR_CHAN_ALL && - chan != SENSOR_CHAN_VOLTAGE && - chan != SENSOR_CHAN_CURRENT && - chan != SENSOR_CHAN_POWER) { - return -ENOTSUP; - } - - if ((chan == SENSOR_CHAN_ALL) || (chan == SENSOR_CHAN_VOLTAGE)) { - ret = ina23x_reg_read(dev, INA23X_REG_BUS_VOLT, &ina23x->bus_voltage); - if (ret < 0) { - LOG_ERR("Failed to read bus voltage"); - return ret; - } - } - - if ((chan == SENSOR_CHAN_ALL) || (chan == SENSOR_CHAN_CURRENT)) { - ret = ina23x_reg_read(dev, INA23X_REG_CURRENT, &ina23x->current); - if (ret < 0) { - LOG_ERR("Failed to read current"); - return ret; - } - } - - if ((chan == SENSOR_CHAN_ALL) || (chan == SENSOR_CHAN_POWER)) { - ret = ina23x_reg_read(dev, INA23X_REG_POWER, &ina23x->power); - if (ret < 0) { - LOG_ERR("Failed to read power"); - return ret; - } - } - - return 0; -} - -/** - * @brief sensor attribute set - * - * @return 0 for success - * @return -ENOTSUP for unsupported channels - * @return -EIO for i2c write failure - */ -static int ina23x_attr_set(const struct device *dev, enum sensor_channel chan, - enum sensor_attribute attr, - const struct sensor_value *val) -{ - uint16_t data = val->val1; - - switch (attr) { - case SENSOR_ATTR_CONFIGURATION: - return ina23x_reg_write(dev, INA23X_REG_CONFIG, data); - case SENSOR_ATTR_CALIBRATION: - return ina23x_reg_write(dev, INA23X_REG_CALIB, data); - case SENSOR_ATTR_FEATURE_MASK: - return ina23x_reg_write(dev, INA23X_REG_MASK, data); - case SENSOR_ATTR_ALERT: - return ina23x_reg_write(dev, INA23X_REG_ALERT, data); - default: - LOG_ERR("INA23X attribute not supported."); - return -ENOTSUP; - } -} - -/** - * @brief sensor attribute get - * - * @return 0 for success - * @return -ENOTSUP for unsupported channels - * @return -EIO for i2c read failure - */ -static int ina23x_attr_get(const struct device *dev, enum sensor_channel chan, - enum sensor_attribute attr, - struct sensor_value *val) -{ - uint16_t data; - int ret; - - switch (attr) { - case SENSOR_ATTR_CONFIGURATION: - ret = ina23x_reg_read(dev, INA23X_REG_CONFIG, &data); - if (ret < 0) { - return ret; - } - break; - case SENSOR_ATTR_CALIBRATION: - ret = ina23x_reg_read(dev, INA23X_REG_CALIB, &data); - if (ret < 0) { - return ret; - } - break; - case SENSOR_ATTR_FEATURE_MASK: - ret = ina23x_reg_read(dev, INA23X_REG_MASK, &data); - if (ret < 0) { - return ret; - } - break; - case SENSOR_ATTR_ALERT: - ret = ina23x_reg_read(dev, INA23X_REG_ALERT, &data); - if (ret < 0) { - return ret; - } - break; - default: - LOG_ERR("INA23X attribute not supported."); - return -ENOTSUP; - } - - val->val1 = data; - val->val2 = 0; - - return 0; -} - -/** - * @brief Initialize the INA23x - * - * @return 0 for success - * @return -EINVAL on error - */ -static int ina23x_init(const struct device *dev) -{ - const struct ina23x_config *const config = dev->config; - uint16_t cal; - int ret; - - if (!device_is_ready(config->bus)) { - LOG_ERR("Device %s is not ready", config->bus->name); - return -ENODEV; - } - - ret = ina23x_reg_write(dev, INA23X_REG_CONFIG, config->config); - if (ret < 0) { - LOG_ERR("Failed to write configuration register!"); - return ret; - } - - cal = INA23X_CALIB(config->current_lsb, config->rshunt); - - ret = ina23x_reg_write(dev, INA23X_REG_CALIB, cal); - if (ret < 0) { - LOG_ERR("Failed to write calibration register!"); - return ret; - } - -#ifdef CONFIG_INA23X_TRIGGER - if (config->trig_enabled) { - ret = ina23x_trigger_mode_init(dev); - if (ret < 0) { - LOG_ERR("Failed to init trigger mode\n"); - return ret; - } - - ret = ina23x_reg_write(dev, INA23X_REG_ALERT, - config->alert_limit); - if (ret < 0) { - LOG_ERR("Failed to write alert register!"); - return ret; - } - - ret = ina23x_reg_write(dev, INA23X_REG_MASK, config->mask); - if (ret < 0) { - LOG_ERR("Failed to write mask register!"); - return ret; - } - } -#endif /* CONFIG_INA23X_TRIGGER */ - - return 0; -} - -static const struct sensor_driver_api ina23x_driver_api = { - .attr_set = ina23x_attr_set, - .attr_get = ina23x_attr_get, -#ifdef CONFIG_INA23X_TRIGGER - .trigger_set = ina23x_trigger_set, -#endif - .sample_fetch = ina23x_sample_fetch, - .channel_get = ina23x_channel_get, -}; - -BUILD_ASSERT(DT_NUM_INST_STATUS_OKAY(DT_DRV_COMPAT) > 0, - "No compatible ina23x instances found"); - -#ifdef CONFIG_INA23X_TRIGGER -#define INA23X_CFG_IRQ(inst) \ - .trig_enabled = true, \ - .mask = DT_INST_PROP(inst, mask), \ - .alert_limit = DT_INST_PROP(inst, alert_limit), \ - .gpio_alert = GPIO_DT_SPEC_INST_GET(inst, irq_gpios) -#else -#define INA23X_CFG_IRQ(inst) -#endif /* CONFIG_INA23X_TRIGGER */ - -#define INA23X_DRIVER_INIT(inst) \ - static struct ina23x_data drv_data_##inst; \ - static const struct ina23x_config drv_config_##inst = { \ - .bus = DEVICE_DT_GET(DT_INST_BUS(inst)), \ - .i2c_slv_addr = DT_INST_REG_ADDR(inst), \ - .config = DT_INST_PROP(inst, config), \ - .current_lsb = DT_INST_PROP(inst, current_lsb), \ - .rshunt = DT_INST_PROP(inst, rshunt), \ - COND_CODE_1(DT_INST_NODE_HAS_PROP(inst, irq_gpios), \ - (INA23X_CFG_IRQ(inst)), ()) \ - }; \ - DEVICE_DT_INST_DEFINE(inst, \ - &ina23x_init, \ - NULL, \ - &drv_data_##inst, \ - &drv_config_##inst, \ - POST_KERNEL, \ - CONFIG_SENSOR_INIT_PRIORITY, \ - &ina23x_driver_api); - -DT_INST_FOREACH_STATUS_OKAY(INA23X_DRIVER_INIT) diff --git a/drivers/sensor/ina23x/ina23x.h b/drivers/sensor/ina23x/ina23x.h deleted file mode 100644 index 5cb3a2b9840..00000000000 --- a/drivers/sensor/ina23x/ina23x.h +++ /dev/null @@ -1,53 +0,0 @@ -/* - * Copyright (c) 2021 The Chromium OS Authors - * - * SPDX-License-Identifier: Apache-2.0 - */ - -#ifndef ZEPHYR_DRIVERS_SENSOR_INA23X_H_ -#define ZEPHYR_DRIVERS_SENSOR_INA23X_H_ - -#include - -#define INA23X_REG_CONFIG 0x00 -#define INA23X_REG_SHUNT_VOLT 0x01 -#define INA23X_REG_BUS_VOLT 0x02 -#define INA23X_REG_POWER 0x03 -#define INA23X_REG_CURRENT 0x04 -#define INA23X_REG_CALIB 0x05 -#define INA23X_REG_MASK 0x06 -#define INA23X_REG_ALERT 0x07 - -struct ina23x_data { - const struct device *dev; - uint16_t current; - uint16_t bus_voltage; - uint16_t power; -#ifdef CONFIG_INA23X_TRIGGER - const struct device *gpio; - struct gpio_callback gpio_cb; - struct k_work work; - sensor_trigger_handler_t handler_alert; -#endif /* CONFIG_INA23X_TRIGGER */ -}; - -struct ina23x_config { - const struct device *bus; - const uint16_t i2c_slv_addr; - uint16_t config; - uint16_t current_lsb; - uint16_t rshunt; -#ifdef CONFIG_INA23X_TRIGGER - bool trig_enabled; - uint16_t mask; - const struct gpio_dt_spec gpio_alert; - uint16_t alert_limit; -#endif /* CONFIG_INA23X_TRIGGER */ -}; - -int ina23x_trigger_mode_init(const struct device *dev); -int ina23x_trigger_set(const struct device *dev, - const struct sensor_trigger *trig, - sensor_trigger_handler_t handler); - -#endif /* ZEPHYR_DRIVERS_SENSOR_INA23X_H_ */ diff --git a/dts/bindings/sensor/ti,ina230.yaml b/dts/bindings/sensor/ti,ina230.yaml new file mode 100644 index 00000000000..f74997a3273 --- /dev/null +++ b/dts/bindings/sensor/ti,ina230.yaml @@ -0,0 +1,36 @@ +# +# Copyright 2021 The Chromium OS Authors +# Copyright 2021 Grinn +# +# SPDX-License-Identifier: Apache-2.0 +# + +description: | + TI INA230 and INA231 Bidirectional Current and Power Monitor. + The file should be included + in the DeviceTree and it provides macro that can be used for + initializing the configuration register. + +compatible: "ti,ina230" + +include: ti,ina23x-common.yaml + +properties: + mask: + type: int + required: false + default: 0 + # default all alert sources to disabled + description: Mask register, default matches the power-on reset value + + alert-limit: + type: int + required: false + default: 0 + # default alert limit is 0V + description: Alert register, default matches the power-on reset value + + irq-gpios: + type: phandle-array + required: false + description: IRQ Alert pin diff --git a/dts/bindings/sensor/ti,ina23x.yaml b/dts/bindings/sensor/ti,ina23x.yaml deleted file mode 100644 index ebc36136971..00000000000 --- a/dts/bindings/sensor/ti,ina23x.yaml +++ /dev/null @@ -1,56 +0,0 @@ -# -# Copyright 2021 The Chromium OS Authors -# -# SPDX-License-Identifier: Apache-2.0 -# - - -description: | - TI INA230 and INA231 Bidirectional Current and Power Monitor. - The file should be included - in the DeviceTree and it provides Macros that can be used for - initializing the Configuration register. - -compatible: "ti,ina23x" - -include: i2c-device.yaml - -properties: - config: - type: int - required: true - description: Configuration register - - current_lsb: - type: int - required: true - description: | - Value of Current LSB in milliamps. When set to 1mA, - Current is read in A, Bus Voltage in V, Shunt - Voltage in V, and Power in mW. Any other value - results in Current, Voltage, and Power registers - being read in counts. - - rshunt: - type: int - required: true - description: Shunt resistor value in milliohms - - mask: - type: int - required: false - default: 0 - # default all alert sources to disabled - description: Mask register, default matches the power-on reset value - - alert_limit: - type: int - required: false - default: 0 - # default alert limit is 0V - description: Alert register, default matches the power-on reset value - - irq-gpios: - type: phandle-array - required: false - description: IRQ Alert pin diff --git a/include/dt-bindings/sensor/ina230.h b/include/dt-bindings/sensor/ina230.h new file mode 100644 index 00000000000..527b899a77d --- /dev/null +++ b/include/dt-bindings/sensor/ina230.h @@ -0,0 +1,68 @@ +/* + * Copyright 2021 The Chromium OS Authors + * Copyright (c) 2021 Grinn + * + * SPDX-License-Identifier: Apache-2.0 + */ +#ifndef ZEPHYR_INCLUDE_DT_BINDINGS_INA230_H_ +#define ZEPHYR_INCLUDE_DT_BINDINGS_INA230_H_ + +#include + +/* Mask/Enable bits that asserts the ALERT pin */ +#define INA230_SHUNT_VOLTAGE_OVER BIT(15) +#define INA230_SHUNT_VOLTAGE_UNDER BIT(14) +#define INA230_BUS_VOLTAGE_OVER BIT(13) +#define INA230_BUS_VOLTAGE_UNDER BIT(12) +#define INA230_OVER_LIMIT_POWER BIT(11) +#define INA230_CONVERSION_READY BIT(10) +#define INA230_ALERT_FUNCTION_FLAG BIT(4) +#define INA230_CONVERSION_READY_FLAG BIT(3) +#define INA230_MATH_OVERFLOW_FLAG BIT(2) +#define INA230_ALERT_POLARITY BIT(1) +#define INA230_ALERT_LATCH_ENABLE BIT(0) + +/* Operating Mode */ +#define INA230_OPER_MODE_POWER_DOWN 0x00 +#define INA230_OPER_MODE_SHUNT_VOLTAGE_TRIG 0x01 +#define INA230_OPER_MODE_BUS_VOLTAGE_TRIG 0x02 +#define INA230_OPER_MODE_SHUNT_BUS_VOLTAGE_TRIG 0x03 +#define INA230_OPER_MODE_SHUNT_VOLTAGE_CONT 0x05 +#define INA230_OPER_MODE_BUS_VOLTAGE_CONT 0x06 +#define INA230_OPER_MODE_SHUNT_BUS_VOLTAGE_CONT 0x07 + +/* Conversion time for bus and shunt in micro-seconds */ +#define INA230_CONV_TIME_140 0x00 +#define INA230_CONV_TIME_204 0x01 +#define INA230_CONV_TIME_332 0x02 +#define INA230_CONV_TIME_588 0x03 +#define INA230_CONV_TIME_1100 0x04 +#define INA230_CONV_TIME_2116 0x05 +#define INA230_CONV_TIME_4156 0x06 +#define INA230_CONV_TIME_8244 0x07 + +/* Averaging Mode */ +#define INA230_AVG_MODE_1 0x00 +#define INA230_AVG_MODE_4 0x01 +#define INA230_AVG_MODE_16 0x02 +#define INA230_AVG_MODE_64 0x03 +#define INA230_AVG_MODE_128 0x04 +#define INA230_AVG_MODE_256 0x05 +#define INA230_AVG_MODE_512 0x06 +#define INA230_AVG_MODE_1024 0x07 + +/** + * @brief Macro for creating the INA230 configuration value + * + * @param mode Operating mode. + * @param svct Conversion time for shunt voltage. + * @param bvct Conversion time for bus voltage. + * @param avg Averaging mode. + */ +#define INA230_CONFIG(mode, \ + svct, \ + bvct, \ + avg) \ + (((avg) << 9) | ((bvct) << 6) | ((svct) << 3) | (mode)) + +#endif /* ZEPHYR_INCLUDE_DT_BINDINGS_INA230_H_ */ diff --git a/include/dt-bindings/sensor/ina23x.h b/include/dt-bindings/sensor/ina23x.h deleted file mode 100644 index 45472a72cc5..00000000000 --- a/include/dt-bindings/sensor/ina23x.h +++ /dev/null @@ -1,67 +0,0 @@ -/* - * Copyright 2021 The Chromium OS Authors - * - * SPDX-License-Identifier: Apache-2.0 - */ -#ifndef ZEPHYR_INCLUDE_DT_BINDINGS_INA23X_H_ -#define ZEPHYR_INCLUDE_DT_BINDINGS_INA23X_H_ - -#include - -/* Mask/Enable bits that asserts the ALERT pin */ -#define INA23X_SHUNT_VOLTAGE_OVER BIT(15) -#define INA23X_SHUNT_VOLTAGE_UNDER BIT(14) -#define INA23X_BUS_VOLTAGE_OVER BIT(13) -#define INA23X_BUS_VOLTAGE_UNDER BIT(12) -#define INA23X_OVER_LIMIT_POWER BIT(11) -#define INA23X_CONVERSION_READY BIT(10) -#define INA23X_ALERT_FUNCTION_FLAG BIT(4) -#define INA23X_CONVERSION_READY_FLAG BIT(3) -#define INA23X_MATH_OVERFLOW_FLAG BIT(2) -#define INA23X_ALERT_POLARITY BIT(1) -#define INA23X_ALERT_LATCH_ENABLE BIT(0) - -/* Operating Mode */ -#define INA23X_OPER_MODE_POWER_DOWN 0x00 -#define INA23X_OPER_MODE_SHUNT_VOLTAGE_TRIG 0x01 -#define INA23X_OPER_MODE_BUS_VOLTAGE_TRIG 0x02 -#define INA23X_OPER_MODE_SHUNT_BUS_VOLTAGE_TRIG 0x03 -#define INA23X_OPER_MODE_SHUNT_VOLTAGE_CONT 0x05 -#define INA23X_OPER_MODE_BUS_VOLTAGE_CONT 0x06 -#define INA23X_OPER_MODE_SHUNT_BUS_VOLTAGE_CONT 0x07 - -/* Conversion time for bus and shunt in micro-seconds */ -#define INA23X_CONV_TIME_140 0x00 -#define INA23X_CONV_TIME_204 0x01 -#define INA23X_CONV_TIME_332 0x02 -#define INA23X_CONV_TIME_588 0x03 -#define INA23X_CONV_TIME_1100 0x04 -#define INA23X_CONV_TIME_2116 0x05 -#define INA23X_CONV_TIME_4156 0x06 -#define INA23X_CONV_TIME_8244 0x07 - -/* Averaging Mode */ -#define INA23X_AVG_MODE_1 0x00 -#define INA23X_AVG_MODE_4 0x01 -#define INA23X_AVG_MODE_16 0x02 -#define INA23X_AVG_MODE_64 0x03 -#define INA23X_AVG_MODE_128 0x04 -#define INA23X_AVG_MODE_256 0x05 -#define INA23X_AVG_MODE_512 0x06 -#define INA23X_AVG_MODE_1024 0x07 - -/** - * @brief Macro for creating the INA23X configuration value - * - * @param mode Operating mode. - * @param svct Conversion time for shunt voltage. - * @param bvct Conversion time for bus voltage. - * @param avg Averaging mode. - */ -#define INA23X_CONFIG(mode, \ - svct, \ - bvct, \ - avg) \ - (((avg) << 9) | ((bvct) << 6) | ((svct) << 3) | (mode)) - -#endif /* ZEPHYR_INCLUDE_DT_BINDINGS_INA23X_H_ */ diff --git a/tests/drivers/build_all/sensor/i2c.dtsi b/tests/drivers/build_all/sensor/i2c.dtsi index 98f52037979..e1b23ad4186 100644 --- a/tests/drivers/build_all/sensor/i2c.dtsi +++ b/tests/drivers/build_all/sensor/i2c.dtsi @@ -666,15 +666,15 @@ test_i2c_lm75: lm75@4e { reg = <0x4e>; }; -test_i2c_ina23x: ina23x@4f { - compatible = "ti,ina23x"; - label = "INA23X"; +test_i2c_ina230: ina230@4f { + compatible = "ti,ina230"; + label = "INA230"; reg = <0x4f>; config = <0>; - current_lsb = <1>; + current-lsb = <1>; rshunt = <0>; mask = <0>; - alert_limit = <0>; + alert-limit = <0>; irq-gpios = <&test_gpio 0 0>; }; @@ -684,3 +684,15 @@ test_i2c_lm77: lm77@50 { reg = <0x50>; int-gpios = <&test_gpio 0 0>; }; + +test_i2c_ina231: ina231@51 { + compatible = "ti,ina230"; + label = "INA231"; + reg = <0x51>; + config = <0>; + current-lsb = <1>; + rshunt = <0>; + mask = <0>; + alert-limit = <0>; + irq-gpios = <&test_gpio 0 0>; +}; diff --git a/tests/drivers/build_all/sensor/prj.conf b/tests/drivers/build_all/sensor/prj.conf index 6ca5ade3350..bdb51cb22b6 100644 --- a/tests/drivers/build_all/sensor/prj.conf +++ b/tests/drivers/build_all/sensor/prj.conf @@ -99,3 +99,4 @@ CONFIG_TMP116=y CONFIG_VCNL4040=y CONFIG_VL53L0X=y CONFIG_INA23X=y +CONFIG_INA230=y diff --git a/tests/drivers/build_all/sensor/sensors_trigger_own.conf b/tests/drivers/build_all/sensor/sensors_trigger_own.conf index da8e2b3e110..28a05c164b8 100644 --- a/tests/drivers/build_all/sensor/sensors_trigger_own.conf +++ b/tests/drivers/build_all/sensor/sensors_trigger_own.conf @@ -36,4 +36,4 @@ CONFIG_STTS751_TRIGGER_OWN_THREAD=y CONFIG_SX9500_TRIGGER_OWN_THREAD=y CONFIG_TMP007_TRIGGER_OWN_THREAD=y CONFIG_VCNL4040_TRIGGER_OWN_THREAD=y -CONFIG_INA23X_TRIGGER=y +CONFIG_INA230_TRIGGER=y