diff --git a/doc/hardware/peripherals/fuel_gauge.rst b/doc/hardware/peripherals/fuel_gauge.rst index bc042c8b21f936..bef7b12279603d 100644 --- a/doc/hardware/peripherals/fuel_gauge.rst +++ b/doc/hardware/peripherals/fuel_gauge.rst @@ -23,6 +23,15 @@ or present-time current/voltage. Properties are fetched using a client allocated array of :c:struct:`fuel_gauge_get_property`. This array is then populated by values as according to its `property_type` field. +Battery Cutoff +============== + +Many fuel gauges embedded within battery packs expose a register address that when written to with a +specific payload will do a battery cutoff. This battery cutoff is often referred to as ship, shelf, +or sleep mode due to its utility in reducing battery drain while devices are stored or shipped. + +The fuel gauge API exposes battery cutoff with the :c:func:`fuel_gauge_battery_cutoff` function. + Caching ======= diff --git a/drivers/fuel_gauge/fuel_gauge_syscall_handlers.c b/drivers/fuel_gauge/fuel_gauge_syscall_handlers.c index 299bd3d5c09d69..4c664b0f5513b5 100644 --- a/drivers/fuel_gauge/fuel_gauge_syscall_handlers.c +++ b/drivers/fuel_gauge/fuel_gauge_syscall_handlers.c @@ -70,3 +70,12 @@ static inline int z_vrfy_fuel_gauge_get_buffer_prop(const struct device *dev, } #include + +static inline int z_vrfy_fuel_gauge_battery_cutoff(const struct device *dev) +{ + Z_OOPS(Z_SYSCALL_DRIVER_FUEL_GAUGE(dev, battery_cutoff)); + + return z_impl_fuel_gauge_battery_cutoff(dev); +} + +#include diff --git a/drivers/fuel_gauge/sbs_gauge/emul_sbs_gauge.c b/drivers/fuel_gauge/sbs_gauge/emul_sbs_gauge.c index 69b9f798b55e48..c84a73e75ffe00 100644 --- a/drivers/fuel_gauge/sbs_gauge/emul_sbs_gauge.c +++ b/drivers/fuel_gauge/sbs_gauge/emul_sbs_gauge.c @@ -16,13 +16,17 @@ #include LOG_MODULE_REGISTER(sbs_sbs_gauge); +#include +#include #include +#include #include #include #include #include #include #include +#include #include "sbs_gauge.h" @@ -33,6 +37,13 @@ struct sbs_gauge_emul_data { uint16_t remaining_time_alarm; uint16_t mode; int16_t at_rate; + /* Whether the battery cutoff or not */ + bool is_cutoff; + /* + * Counts the number of times the cutoff payload has been sent to the designated + * register + */ + uint8_t cutoff_writes; struct { /* Non-register values associated with the state of the battery */ /* Battery terminal voltage */ @@ -46,8 +57,46 @@ struct sbs_gauge_emul_data { struct sbs_gauge_emul_cfg { /** I2C address of emulator */ uint16_t addr; + bool cutoff_support; + uint32_t cutoff_reg_addr; + uint16_t cutoff_payload[SBS_GAUGE_CUTOFF_PAYLOAD_MAX_SIZE]; }; +static void emul_sbs_gauge_maybe_do_battery_cutoff(const struct emul *target, int reg, int val) +{ + struct sbs_gauge_emul_data *data = target->data; + const struct sbs_gauge_emul_cfg *cfg = target->cfg; + + /* Check if this is a cutoff write */ + if (cfg->cutoff_support && reg == cfg->cutoff_reg_addr) { + __ASSERT_NO_MSG(ARRAY_SIZE(cfg->cutoff_payload) > 0); + /* + * Calculate the next payload element value for a battery cutoff. + * + * We thoroughly check bounds elsewhere, so we can be confident we're not indexing + * past the end of the array. + */ + uint16_t target_payload_elem_val = cfg->cutoff_payload[data->cutoff_writes]; + + if (target_payload_elem_val == val) { + data->cutoff_writes++; + __ASSERT_NO_MSG(data->cutoff_writes <= ARRAY_SIZE(cfg->cutoff_payload)); + } else { + /* Wrong payload target value, reset cutoff sequence detection. */ + data->cutoff_writes = 0; + } + + if (data->cutoff_writes == ARRAY_SIZE(cfg->cutoff_payload)) { + data->is_cutoff = true; + data->cutoff_writes = 0; + } + } + /* Not a cutoff write, reset payload counter */ + else { + data->cutoff_writes = 0; + } +} + static int emul_sbs_gauge_reg_write(const struct emul *target, int reg, int val) { struct sbs_gauge_emul_data *data = target->data; @@ -74,6 +123,12 @@ static int emul_sbs_gauge_reg_write(const struct emul *target, int reg, int val) return -EIO; } + /* + * One of the above registers is always designated as a "cutoff" register, usually it's + * MANUFACTURER ACCESS, but not always. + */ + emul_sbs_gauge_maybe_do_battery_cutoff(target, reg, val); + return 0; } @@ -245,8 +300,20 @@ static int emul_sbs_fuel_gauge_set_battery_charging(const struct emul *target, u return 0; } +static int emul_sbs_fuel_gauge_is_battery_cutoff(const struct emul *target, bool *cutoff) +{ + struct sbs_gauge_emul_data *data = target->data; + + __ASSERT_NO_MSG(cutoff != NULL); + + *cutoff = data->is_cutoff; + + return 0; +} + static const struct fuel_gauge_emul_driver_api sbs_gauge_backend_api = { .set_battery_charging = emul_sbs_fuel_gauge_set_battery_charging, + .is_battery_cutoff = emul_sbs_fuel_gauge_is_battery_cutoff, }; static const struct i2c_emul_api sbs_gauge_emul_api_i2c = { @@ -303,6 +370,9 @@ static int emul_sbs_sbs_gauge_init(const struct emul *target, const struct devic 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), \ + .cutoff_support = DT_PROP_OR(DT_DRV_INST(n), battery_cutoff_support, false), \ + .cutoff_reg_addr = DT_PROP_OR(DT_DRV_INST(n), battery_cutoff_reg_addr, 0), \ + .cutoff_payload = DT_PROP_OR(DT_DRV_INST(n), battery_cutoff_payload, {}), \ }; \ 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, \ diff --git a/drivers/fuel_gauge/sbs_gauge/sbs_gauge.c b/drivers/fuel_gauge/sbs_gauge/sbs_gauge.c index f1d107330cb3d5..b934c434961537 100644 --- a/drivers/fuel_gauge/sbs_gauge/sbs_gauge.c +++ b/drivers/fuel_gauge/sbs_gauge/sbs_gauge.c @@ -11,10 +11,14 @@ #include "sbs_gauge.h" +#include +#include +#include #include #include #include #include +#include LOG_MODULE_REGISTER(sbs_gauge); @@ -173,6 +177,25 @@ static int sbs_gauge_get_prop(const struct device *dev, struct fuel_gauge_get_pr return rc; } +static int sbs_gauge_do_battery_cutoff(const struct device *dev) +{ + int rc; + const struct sbs_gauge_config *cfg = dev->config; + + if (cfg->cutoff_cfg == NULL) { + return -ENOTSUP; + } + + for (int i = 0; i < cfg->cutoff_cfg->payload_size; i++) { + rc = sbs_cmd_reg_write(dev, cfg->cutoff_cfg->reg, cfg->cutoff_cfg->payload[i]); + if (rc != 0) { + return rc; + } + } + + return rc; +} + static int sbs_gauge_set_prop(const struct device *dev, struct fuel_gauge_set_property *prop) { int rc = 0; @@ -203,7 +226,6 @@ static int sbs_gauge_set_prop(const struct device *dev, struct fuel_gauge_set_pr rc = sbs_cmd_reg_write(dev, SBS_GAUGE_CMD_AR, prop->value.sbs_at_rate); prop->value.sbs_at_rate = val; break; - default: rc = -ENOTSUP; } @@ -307,17 +329,44 @@ static const struct fuel_gauge_driver_api sbs_gauge_driver_api = { .get_property = &sbs_gauge_get_props, .set_property = &sbs_gauge_set_props, .get_buffer_property = &sbs_gauge_get_buffer_prop, + .battery_cutoff = &sbs_gauge_do_battery_cutoff, }; -/* FIXME: fix init priority */ +/* Concatenates index to battery config to create unique cfg variable name per instance. */ +#define _SBS_GAUGE_BATT_CUTOFF_CFG_VAR_NAME(index) sbs_gauge_batt_cutoff_cfg_##index + +/* Declare and define the battery config struct */ +#define _SBS_GAUGE_CONFIG_DEFINE(index) \ + static const struct sbs_gauge_battery_cutoff_config _SBS_GAUGE_BATT_CUTOFF_CFG_VAR_NAME( \ + index) = { \ + .reg = DT_INST_PROP(index, battery_cutoff_reg_addr), \ + .payload = DT_INST_PROP(index, battery_cutoff_payload), \ + .payload_size = DT_INST_PROP_LEN(index, battery_cutoff_payload), \ + }; + +/* Conditionally defined battery config based on battery cutoff support */ +#define SBS_GAUGE_CONFIG_DEFINE(index) \ + COND_CODE_1(DT_INST_PROP_OR(index, battery_cutoff_support, false), \ + (_SBS_GAUGE_CONFIG_DEFINE(index)), (;)) + +/* Conditionally get the battery config variable name or NULL based on battery cutoff support */ +#define SBS_GAUGE_GET_BATTERY_CONFIG_NAME(index) \ + COND_CODE_1(DT_INST_PROP_OR(index, battery_cutoff_support, false), \ + (&_SBS_GAUGE_BATT_CUTOFF_CFG_VAR_NAME(index)), (NULL)) + #define SBS_GAUGE_INIT(index) \ - \ + SBS_GAUGE_CONFIG_DEFINE(index); \ static const struct sbs_gauge_config sbs_gauge_config_##index = { \ .i2c = I2C_DT_SPEC_INST_GET(index), \ - }; \ + .cutoff_cfg = SBS_GAUGE_GET_BATTERY_CONFIG_NAME(index)}; \ \ DEVICE_DT_INST_DEFINE(index, &sbs_gauge_init, NULL, NULL, &sbs_gauge_config_##index, \ POST_KERNEL, CONFIG_FUEL_GAUGE_INIT_PRIORITY, \ &sbs_gauge_driver_api); DT_INST_FOREACH_STATUS_OKAY(SBS_GAUGE_INIT) + +#define CUTOFF_PAYLOAD_SIZE_ASSERT(inst) \ + BUILD_ASSERT(DT_INST_PROP_LEN_OR(inst, battery_cutoff_payload, 0) <= \ + SBS_GAUGE_CUTOFF_PAYLOAD_MAX_SIZE); +DT_INST_FOREACH_STATUS_OKAY(CUTOFF_PAYLOAD_SIZE_ASSERT) diff --git a/drivers/fuel_gauge/sbs_gauge/sbs_gauge.h b/drivers/fuel_gauge/sbs_gauge/sbs_gauge.h index 8cafb65df38ca3..2ae8007125c5b6 100644 --- a/drivers/fuel_gauge/sbs_gauge/sbs_gauge.h +++ b/drivers/fuel_gauge/sbs_gauge/sbs_gauge.h @@ -47,8 +47,33 @@ #define SBS_GAUGE_DELAY 1000 +/* + * Nearly all cutoff payloads are actually a singular value that must be written twice to the fuel + * gauge. For the case where it's a singular value that must only be written to the fuel gauge only + * once, retransmitting the duplicate write has no significant negative consequences. + * + * Why not devicetree: Finding the maximum length of all the battery cutoff payloads in a devicetree + * at compile-time would require labyrinthine amount of macro-batics. + * + * Why not compute at runtime: It's not worth the memory given having more than a single fuel gauge + * is rare, and most will have a payload size of 2. + * + * This is validated as a BUILD_ASSERT in the driver. + */ +#define SBS_GAUGE_CUTOFF_PAYLOAD_MAX_SIZE 2 + +struct sbs_gauge_battery_cutoff_config { + /* Size of the payload array */ + size_t payload_size; + /* Array SMBus word values to write to cut off the battery */ + uint32_t payload[SBS_GAUGE_CUTOFF_PAYLOAD_MAX_SIZE]; + /* Register to write cutoff payload */ + uint8_t reg; +}; + struct sbs_gauge_config { struct i2c_dt_spec i2c; + const struct sbs_gauge_battery_cutoff_config *cutoff_cfg; }; #endif diff --git a/dts/bindings/fuel-gauge/battery-cutoff.yaml b/dts/bindings/fuel-gauge/battery-cutoff.yaml new file mode 100644 index 00000000000000..c3272cc5376ddf --- /dev/null +++ b/dts/bindings/fuel-gauge/battery-cutoff.yaml @@ -0,0 +1,29 @@ +# +# Copyright 2023 Google LLC +# +# SPDX-License-Identifier: Apache-2.0 +# + +description: | + + Properties for fuel-gauges that may control battery cutoff, this is common in SBS-compliant or + similarly smart battery fuel gauges. + + Note: These properties are to be used with meaningful defaults in fuel gauge ICs that can cut off + their associated battery from the system. See the default fuel gauge SBS Gauge compatible as an + example. + +properties: + battery-cutoff-support: + description: | + Helper prop that indicates whether this device can cutoff the battery; this is also often + referred to as ship or sleep mode. + type: boolean + battery-cutoff-reg-addr: + description: | + Address of register to receive cutoff payload for battery cutoff. + type: int + battery-cutoff-payload: + description: | + Payload to write to cutoff battery register. This must be array of maximum 2 integers. + type: array diff --git a/dts/bindings/fuel-gauge/sbs,default-sbs-gauge.yaml b/dts/bindings/fuel-gauge/sbs,default-sbs-gauge.yaml new file mode 100644 index 00000000000000..db000b80298aa7 --- /dev/null +++ b/dts/bindings/fuel-gauge/sbs,default-sbs-gauge.yaml @@ -0,0 +1,22 @@ +# +# Copyright 2023 Google LLC +# +# SPDX-License-Identifier: Apache-2.0 +# + +compatible: "sbs,default-sbs-gauge" + +include: ["sbs,sbs-gauge-new-api.yaml", "battery-cutoff.yaml"] + +description: | + Default generic smart battery fuel gauge driver. Includes support for battery cutoff if enabled. + + This compatible is intended to be used with the abstract SBS Gauge compatible because it is + actuated by the SBS driver for SBS compliant fuel gauge ICs. + +properties: + battery-cutoff-reg-addr: + # For SBS compliant fuel gauges this is usually "ManufactuerAccess" + default: 0x0 + battery-cutoff-payload: + default: [0x0010, 0x0010] diff --git a/include/zephyr/drivers/emul_fuel_gauge.h b/include/zephyr/drivers/emul_fuel_gauge.h index c8af1c91a561a1..63b85d227c195a 100644 --- a/include/zephyr/drivers/emul_fuel_gauge.h +++ b/include/zephyr/drivers/emul_fuel_gauge.h @@ -34,6 +34,7 @@ extern "C" { */ __subsystem struct fuel_gauge_emul_driver_api { int (*set_battery_charging)(const struct emul *emul, uint32_t uV, int uA); + int (*is_battery_cutoff)(const struct emul *emul, bool *cutoff); }; /** * @endcond @@ -66,6 +67,26 @@ static inline int emul_fuel_gauge_set_battery_charging(const struct emul *target return backend_api->set_battery_charging(target, uV, uA); } +/** + * @brief Check if the battery has been cut off. + * + * @param target Pointer to the emulator structure for the fuel gauge emulator instance. + * @param cutoff Pointer to bool storing variable. + * + * @retval 0 If successful. + * @retval -ENOTSUP if not supported by emulator. + */ +static inline int emul_fuel_gauge_is_battery_cutoff(const struct emul *target, bool *cutoff) +{ + const struct fuel_gauge_emul_driver_api *backend_api = + (const struct fuel_gauge_emul_driver_api *)target->backend_api; + + if (backend_api->is_battery_cutoff == 0) { + return -ENOTSUP; + } + return backend_api->is_battery_cutoff(target, cutoff); +} + #ifdef __cplusplus } #endif diff --git a/include/zephyr/drivers/fuel_gauge.h b/include/zephyr/drivers/fuel_gauge.h index fc8dd0d1d6b1eb..5be69baa8ab2a9 100644 --- a/include/zephyr/drivers/fuel_gauge.h +++ b/include/zephyr/drivers/fuel_gauge.h @@ -38,6 +38,8 @@ enum fuel_gauge_property { */ FUEL_GAUGE_AVG_CURRENT = 0, + /** Used to cutoff the battery from the system - useful for storage/shipping of devices */ + FUEL_GAUGE_BATTERY_CUTOFF, /** Battery current (uA); negative=discharging */ FUEL_GAUGE_CURRENT, /** Whether the battery underlying the fuel-gauge is cut off from charge */ @@ -268,6 +270,13 @@ typedef int (*fuel_gauge_get_buffer_property_t)(const struct device *dev, struct fuel_gauge_get_buffer_property *prop, void *dst, size_t dst_len); +/** + * @typedef fuel_gauge_battery_cutoff_t + * @brief Callback API for doing a battery cutoff. + * + * See fuel_gauge_battery_cutoff() for argument description + */ +typedef int (*fuel_gauge_battery_cutoff_t)(const struct device *dev); /* Caching is entirely on the onus of the client */ @@ -275,6 +284,7 @@ __subsystem struct fuel_gauge_driver_api { fuel_gauge_get_property_t get_property; fuel_gauge_set_property_t set_property; fuel_gauge_get_buffer_property_t get_buffer_property; + fuel_gauge_battery_cutoff_t battery_cutoff; }; /** @@ -363,6 +373,27 @@ static inline int z_impl_fuel_gauge_get_buffer_prop(const struct device *dev, return api->get_buffer_property(dev, prop, dst, dst_len); } +/** + * @brief Have fuel gauge cutoff its associated battery. + * + * @param dev Pointer to the battery fuel-gauge device + * + * @return return=0 if successful and battery cutoff is now in process, return < 0 if failed to do + * battery cutoff. + */ +__syscall int fuel_gauge_battery_cutoff(const struct device *dev); + +static inline int z_impl_fuel_gauge_battery_cutoff(const struct device *dev) +{ + const struct fuel_gauge_driver_api *api = (const struct fuel_gauge_driver_api *)dev->api; + + if (api->battery_cutoff == NULL) { + return -ENOSYS; + } + + return api->battery_cutoff(dev); +} + /** * @} */ diff --git a/tests/drivers/fuel_gauge/sbs_gauge/CMakeLists.txt b/tests/drivers/fuel_gauge/sbs_gauge/CMakeLists.txt index 151d3bf8ce9db6..cd386c5afd3e27 100644 --- a/tests/drivers/fuel_gauge/sbs_gauge/CMakeLists.txt +++ b/tests/drivers/fuel_gauge/sbs_gauge/CMakeLists.txt @@ -4,7 +4,8 @@ cmake_minimum_required(VERSION 3.20.0) find_package(Zephyr REQUIRED HINTS $ENV{ZEPHYR_BASE}) project(device) -FILE(GLOB app_sources src/test_sbs_gauge.c) +target_sources(app PRIVATE src/test_sbs_gauge.c) +target_sources_ifndef(CONFIG_TEST_SBS_CUTOFF_EXTENSION app PRIVATE src/test_cutoff_disabled.c) +target_sources_ifdef(CONFIG_TEST_SBS_CUTOFF_EXTENSION app PRIVATE src/test_cutoff.c) target_include_directories(app PRIVATE include) -target_sources(app PRIVATE ${app_sources}) diff --git a/tests/drivers/fuel_gauge/sbs_gauge/Kconfig b/tests/drivers/fuel_gauge/sbs_gauge/Kconfig new file mode 100644 index 00000000000000..c7a8fbb930fae3 --- /dev/null +++ b/tests/drivers/fuel_gauge/sbs_gauge/Kconfig @@ -0,0 +1,11 @@ +# Copyright 2023 Google LLC +# +# SPDX-License-Identifier: Apache-2.0 + +source "Kconfig.zephyr" + +config TEST_SBS_CUTOFF_EXTENSION + bool "Test Battery Cutoff" + help + Enabling this option adds test sources that verify if the battery cutoff extension to the + SBS driver are functional. diff --git a/tests/drivers/fuel_gauge/sbs_gauge/boards/emulated_board_cutoff.overlay b/tests/drivers/fuel_gauge/sbs_gauge/boards/emulated_board_cutoff.overlay new file mode 100644 index 00000000000000..cf40ff46b20bce --- /dev/null +++ b/tests/drivers/fuel_gauge/sbs_gauge/boards/emulated_board_cutoff.overlay @@ -0,0 +1,30 @@ +/* + * Copyright (c) 2023 Google LLC + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include + +/ { + fake_i2c_bus: i2c@100 { + status = "okay"; + compatible = "zephyr,i2c-emul-controller"; + clock-frequency = ; + #address-cells = <1>; + #size-cells = <0>; + reg = <0x100 4>; + }; +}; + +&fake_i2c_bus { + clock-frequency = ; + compatible = "zephyr,i2c-emul-controller"; + smartbattery0: smartbattery@b { + compatible = "sbs,default-sbs-gauge","sbs,sbs-gauge-new-api"; + reg = <0x0b>; + status = "okay"; + battery-cutoff-support; + battery-cutoff-payload = <0x0010 0x0020>; + }; +}; diff --git a/tests/drivers/fuel_gauge/sbs_gauge/src/test_cutoff.c b/tests/drivers/fuel_gauge/sbs_gauge/src/test_cutoff.c new file mode 100644 index 00000000000000..2728ac9ffb894a --- /dev/null +++ b/tests/drivers/fuel_gauge/sbs_gauge/src/test_cutoff.c @@ -0,0 +1,29 @@ +/* + * Copyright 2023 Google LLC + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include +#include +#include +#include +#include + +#include "test_sbs_gauge.h" + +ZTEST_F(sbs_gauge_new_api, test_cutoff) +{ + bool is_cutoff; + + /* Initially there should be no cutoff */ + zassert_ok(emul_fuel_gauge_is_battery_cutoff(fixture->sbs_fuel_gauge, &is_cutoff)); + zassert_false(is_cutoff); + + zassert_ok(fuel_gauge_battery_cutoff(fixture->dev)); + + /* Now we should've cutoff */ + zassert_ok(emul_fuel_gauge_is_battery_cutoff(fixture->sbs_fuel_gauge, &is_cutoff)); + zassert_true(is_cutoff); +} diff --git a/tests/drivers/fuel_gauge/sbs_gauge/src/test_cutoff_disabled.c b/tests/drivers/fuel_gauge/sbs_gauge/src/test_cutoff_disabled.c new file mode 100644 index 00000000000000..12084542e6db02 --- /dev/null +++ b/tests/drivers/fuel_gauge/sbs_gauge/src/test_cutoff_disabled.c @@ -0,0 +1,29 @@ +/* + * Copyright 2023 Google LLC + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include +#include +#include +#include +#include + +#include "test_sbs_gauge.h" + +ZTEST_F(sbs_gauge_new_api, test_cutoff_disabled) +{ + bool is_cutoff; + + /* Initially there should be no cutoff */ + zassert_ok(emul_fuel_gauge_is_battery_cutoff(fixture->sbs_fuel_gauge, &is_cutoff)); + zassert_false(is_cutoff); + + zassert_not_equal(fuel_gauge_battery_cutoff(fixture->dev), 0); + + /* We confirm there was no cutoff */ + zassert_ok(emul_fuel_gauge_is_battery_cutoff(fixture->sbs_fuel_gauge, &is_cutoff)); + zassert_false(is_cutoff); +} diff --git a/tests/drivers/fuel_gauge/sbs_gauge/testcase.yaml b/tests/drivers/fuel_gauge/sbs_gauge/testcase.yaml index 5e8500a8dece28..d7f85f58bb6789 100644 --- a/tests/drivers/fuel_gauge/sbs_gauge/testcase.yaml +++ b/tests/drivers/fuel_gauge/sbs_gauge/testcase.yaml @@ -40,3 +40,17 @@ tests: extra_args: - CONF_FILE="prj.conf;boards/qemu_cortex_a53.conf" - DTC_OVERLAY_FILE="boards/qemu_cortex_a53.overlay" + drivers.sbs_gauge_new_api.emulated.cutoff: + tags: + - drivers + - fuel_gauge + filter: dt_compat_enabled("sbs,sbs-gauge-new-api") + extra_args: + - DTC_OVERLAY_FILE="boards/emulated_board_cutoff.overlay" + extra_configs: + - CONFIG_EMUL=y + - CONFIG_TEST_SBS_CUTOFF_EXTENSION=y + - CONFIG_USERSPACE=y + platform_allow: + - native_posix + - qemu_x86