From e1401fcf5e3870502389b7de8ab54b3e6d493935 Mon Sep 17 00:00:00 2001 From: Aaron Massey Date: Fri, 26 May 2023 14:25:59 -0600 Subject: [PATCH] emul: Add SBS Gauge emulator backend_api In order to support easier setup of test scenarios with fuel gauge emulators, we should expose an API that can change internal emulator state. Add a minimal fuel gauge emulator backend API for setting the charging current and voltage with a sample implementation in the emul_sbs_gauge with an associated driver test. Signed-off-by: Aaron Massey --- doc/hardware/peripherals/fuel_gauge.rst | 1 + drivers/fuel_gauge/sbs_gauge/emul_sbs_gauge.c | 36 ++++++++- include/zephyr/drivers/emul_fuel_gauge.h | 73 +++++++++++++++++++ .../fuel_gauge/sbs_gauge/src/test_sbs_gauge.c | 31 ++++++++ 4 files changed, 138 insertions(+), 3 deletions(-) create mode 100644 include/zephyr/drivers/emul_fuel_gauge.h diff --git a/doc/hardware/peripherals/fuel_gauge.rst b/doc/hardware/peripherals/fuel_gauge.rst index b5f0bd26d88..bc042c8b21f 100644 --- a/doc/hardware/peripherals/fuel_gauge.rst +++ b/doc/hardware/peripherals/fuel_gauge.rst @@ -35,3 +35,4 @@ API Reference ************* .. doxygengroup:: fuel_gauge_interface +.. doxygengroup:: fuel_gauge_emulator_backend diff --git a/drivers/fuel_gauge/sbs_gauge/emul_sbs_gauge.c b/drivers/fuel_gauge/sbs_gauge/emul_sbs_gauge.c index 18dc997b014..f735e07598d 100644 --- a/drivers/fuel_gauge/sbs_gauge/emul_sbs_gauge.c +++ b/drivers/fuel_gauge/sbs_gauge/emul_sbs_gauge.c @@ -21,6 +21,7 @@ LOG_MODULE_REGISTER(sbs_sbs_gauge); #include #include #include +#include #include #include "sbs_gauge.h" @@ -32,6 +33,13 @@ struct sbs_gauge_emul_data { uint16_t remaining_time_alarm; uint16_t mode; int16_t at_rate; + struct { + /* Non-register values associated with the state of the battery */ + /* Battery terminal voltage */ + uint32_t uV; + /* Battery terminal current - Pos is charging, Neg is discharging */ + int uA; + } batt_state; }; /** Static configuration for the emulator */ @@ -90,6 +98,11 @@ static int emul_sbs_gauge_reg_read(const struct emul *target, int reg, int *val) *val = data->at_rate; break; case SBS_GAUGE_CMD_VOLTAGE: + *val = data->batt_state.uV / 1000; + break; + case SBS_GAUGE_CMD_CURRENT: + *val = data->batt_state.uA / 1000; + break; case SBS_GAUGE_CMD_AVG_CURRENT: case SBS_GAUGE_CMD_TEMP: case SBS_GAUGE_CMD_ASOC: @@ -102,7 +115,6 @@ static int emul_sbs_gauge_reg_read(const struct emul *target, int reg, int *val) case SBS_GAUGE_CMD_RUNTIME2EMPTY: case SBS_GAUGE_CMD_CYCLE_COUNT: case SBS_GAUGE_CMD_DESIGN_VOLTAGE: - case SBS_GAUGE_CMD_CURRENT: case SBS_GAUGE_CMD_CHG_CURRENT: case SBS_GAUGE_CMD_CHG_VOLTAGE: case SBS_GAUGE_CMD_FLAGS: @@ -220,6 +232,23 @@ static int sbs_gauge_emul_transfer_i2c(const struct emul *target, struct i2c_msg return rc; } +static int emul_sbs_fuel_gauge_set_battery_charging(const struct emul *target, uint32_t uV, int uA) +{ + struct sbs_gauge_emul_data *data = target->data; + + if (uV == 0 || uA == 0) + return -EINVAL; + + data->batt_state.uA = uA; + data->batt_state.uV = uV; + + return 0; +} + +static const struct fuel_gauge_emul_driver_api sbs_gauge_backend_api = { + .set_battery_charging = emul_sbs_fuel_gauge_set_battery_charging, +}; + static const struct i2c_emul_api sbs_gauge_emul_api_i2c = { .transfer = sbs_gauge_emul_transfer_i2c, }; @@ -243,11 +272,12 @@ static int emul_sbs_sbs_gauge_init(const struct emul *target, const struct devic * Main instantiation macro. SBS Gauge Emulator only implemented for I2C */ #define SBS_GAUGE_EMUL(n) \ - static struct sbs_gauge_emul_data sbs_gauge_emul_data_##n; \ + static struct sbs_gauge_emul_data sbs_gauge_emul_data_##n; \ static const struct sbs_gauge_emul_cfg sbs_gauge_emul_cfg_##n = { \ .addr = DT_INST_REG_ADDR(n), \ }; \ EMUL_DT_INST_DEFINE(n, emul_sbs_sbs_gauge_init, &sbs_gauge_emul_data_##n, \ - &sbs_gauge_emul_cfg_##n, &sbs_gauge_emul_api_i2c, NULL) + &sbs_gauge_emul_cfg_##n, &sbs_gauge_emul_api_i2c, \ + &sbs_gauge_backend_api) DT_INST_FOREACH_STATUS_OKAY(SBS_GAUGE_EMUL) diff --git a/include/zephyr/drivers/emul_fuel_gauge.h b/include/zephyr/drivers/emul_fuel_gauge.h new file mode 100644 index 00000000000..812de61a79f --- /dev/null +++ b/include/zephyr/drivers/emul_fuel_gauge.h @@ -0,0 +1,73 @@ +/* + * Copyright (c) 2023 Google LLC + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/** + * @file + * @brief Backend APIs for the fuel gauge emulators. + */ + +#ifndef ZEPHYR_INCLUDE_DRIVERS_EMUL_FUEL_GAUGE_H_ +#define ZEPHYR_INCLUDE_DRIVERS_EMUL_FUEL_GAUGE_H_ + +#include +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @brief Fuel gauge backend emulator APIs + * @defgroup fuel_gauge_emulator_backend fuel gauge backed emulator APIs + * @ingroup io_interfaces + * @{ + */ + +/** + * @cond INTERNAL_HIDDEN + * + * These are for internal use only, so skip these in public documentation. + */ +__subsystem struct fuel_gauge_emul_driver_api { + int (*set_battery_charging)(const struct emul *emul, uint32_t uV, int uA); +}; +/** + * @endcond + */ + +/** + * @brief Set charging for fuel gauge associated battery. + * + * Set how much the battery associated with a fuel gauge IC is charging or discharging. Where + * voltage is always positive and a positive or negative current denotes charging or discharging, + * respectively. + * + * @param target Pointer to the emulator structure for the fuel gauge emulator instance. + * @param uV Microvolts describing the battery voltage. + * @param uA Microamps describing the battery current where negative is discharging. + * + * @retval 0 If successful. + * @retval -EINVAL if mV or mA are 0. + */ +static inline int emul_fuel_gauge_set_battery_charging(const struct emul *target, uint32_t uV, + int uA) +{ + const struct fuel_gauge_emul_driver_api *backend_api = + (const struct fuel_gauge_emul_driver_api *)target->backend_api; + + return backend_api->set_battery_charging(target, uV, uA); +} + +#ifdef __cplusplus +} +#endif + +/** + * @} + */ + +#endif /* ZEPHYR_INCLUDE_DRIVERS_EMUL_FUEL_GAUGE_H_*/ diff --git a/tests/drivers/fuel_gauge/sbs_gauge/src/test_sbs_gauge.c b/tests/drivers/fuel_gauge/sbs_gauge/src/test_sbs_gauge.c index 54418eb1970..5a67149181d 100644 --- a/tests/drivers/fuel_gauge/sbs_gauge/src/test_sbs_gauge.c +++ b/tests/drivers/fuel_gauge/sbs_gauge/src/test_sbs_gauge.c @@ -6,6 +6,8 @@ */ #include +#include +#include #include #include #include @@ -16,6 +18,7 @@ struct sbs_gauge_new_api_fixture { const struct device *dev; + const struct emul *sbs_fuel_gauge; const struct fuel_gauge_driver_api *api; }; @@ -24,6 +27,7 @@ static void *sbs_gauge_new_api_setup(void) static ZTEST_DMEM struct sbs_gauge_new_api_fixture fixture; fixture.dev = DEVICE_DT_GET_ANY(sbs_sbs_gauge_new_api); + fixture.sbs_fuel_gauge = EMUL_DT_GET(DT_NODELABEL(smartbattery0)); k_object_access_all_grant(fixture.dev); @@ -344,5 +348,32 @@ ZTEST_USER_F(sbs_gauge_new_api, test_get_buffer_props__returns_ok) zassert_ok(ret); } +ZTEST_F(sbs_gauge_new_api, test_charging_5v_3a) +{ + /* Validate what props are supported by the driver */ + uint32_t expected_uV = 5000 * 1000; + uint32_t expected_uA = 3000 * 1000; + + struct fuel_gauge_get_property props[] = { + { + .property_type = FUEL_GAUGE_VOLTAGE, + }, + { + .property_type = FUEL_GAUGE_CURRENT, + }, + }; + + zassume_ok(emul_fuel_gauge_set_battery_charging(fixture->sbs_fuel_gauge, expected_uV, + expected_uA)); + zassert_ok(fuel_gauge_get_prop(fixture->dev, props, ARRAY_SIZE(props))); + + zassert_ok(props[0].status); + zassert_equal(props[0].value.voltage, expected_uV, "Got %d instead of %d", + props[0].value.voltage, expected_uV); + + zassert_ok(props[1].status); + zassert_equal(props[1].value.current, expected_uA, "Got %d instead of %d", + props[1].value.current, expected_uA); +} ZTEST_SUITE(sbs_gauge_new_api, NULL, sbs_gauge_new_api_setup, NULL, NULL, NULL);