diff --git a/CODEOWNERS b/CODEOWNERS index cccc9a0580d..843ab546d66 100644 --- a/CODEOWNERS +++ b/CODEOWNERS @@ -185,6 +185,7 @@ /drivers/*/*npcx* @MulinChao @WealianLiao @ChiHuaL /drivers/adc/ @anangl /drivers/adc/adc_stm32.c @cybertale +/drivers/bbram/* @yperess @sjg20 @jackrosenthal /drivers/bluetooth/ @joerchan @jhedberg @Vudentz /drivers/cache/ @carlocaione /drivers/syscon/ @carlocaione diff --git a/drivers/CMakeLists.txt b/drivers/CMakeLists.txt index 14650cfbaa3..ff47275c0db 100644 --- a/drivers/CMakeLists.txt +++ b/drivers/CMakeLists.txt @@ -58,3 +58,4 @@ add_subdirectory_ifdef(CONFIG_PTP_CLOCK ptp_clock) add_subdirectory_ifdef(CONFIG_EDAC edac) add_subdirectory_ifdef(CONFIG_CACHE_MANAGEMENT cache) add_subdirectory_ifdef(CONFIG_SYSCON syscon) +add_subdirectory_ifdef(CONFIG_BBRAM bbram) diff --git a/drivers/Kconfig b/drivers/Kconfig index 4b913ea4c0f..34bf5cd9ed7 100644 --- a/drivers/Kconfig +++ b/drivers/Kconfig @@ -117,4 +117,6 @@ source "drivers/cache/Kconfig" source "drivers/syscon/Kconfig" +source "drivers/bbram/Kconfig" + endmenu diff --git a/drivers/bbram/CMakeLists.txt b/drivers/bbram/CMakeLists.txt new file mode 100644 index 00000000000..cce72264923 --- /dev/null +++ b/drivers/bbram/CMakeLists.txt @@ -0,0 +1,7 @@ +# Copyright (c) 2021 Google Inc. +# SPDX-License-Identifier: Apache-2.0 + +zephyr_library() + +zephyr_library_sources_ifdef(CONFIG_BBRAM_NPCX bbram_npcx.c) +zephyr_library_sources_ifdef(CONFIG_BBRAM_EMUL bbram_emul.c) diff --git a/drivers/bbram/Kconfig b/drivers/bbram/Kconfig new file mode 100644 index 00000000000..5a887f15efe --- /dev/null +++ b/drivers/bbram/Kconfig @@ -0,0 +1,25 @@ +# Copyright (c) 2021 Google Inc +# SPDX-License-Identifier: Apache-2.0 + +menuconfig BBRAM + bool "Battery-backed RAM drivers" + help + Enable BBRAM (battery-backed RAM) driver configuration. + +if BBRAM + +module = BBRAM +module-str = bbram +source "subsys/logging/Kconfig.template.log_config" + +config BBRAM_INIT_PRIORITY + int "Init priority" + default 10 + help + BBRAM driver initialization priority + +source "drivers/bbram/Kconfig.npcx" + +source "drivers/bbram/Kconfig.bbram_emul" + +endif # BBRAM diff --git a/drivers/bbram/Kconfig.bbram_emul b/drivers/bbram/Kconfig.bbram_emul new file mode 100644 index 00000000000..4ed2cb5e66e --- /dev/null +++ b/drivers/bbram/Kconfig.bbram_emul @@ -0,0 +1,7 @@ +# Copyright (c) 2021 Google Inc +# SPDX-License-Identifier: Apache-2.0 + +config BBRAM_EMUL + bool "Battery-backed RAM emulated drivers" + help + This option enables the BBRAM emulation driver. diff --git a/drivers/bbram/Kconfig.npcx b/drivers/bbram/Kconfig.npcx new file mode 100644 index 00000000000..3e95e604fff --- /dev/null +++ b/drivers/bbram/Kconfig.npcx @@ -0,0 +1,8 @@ +# Copyright (c) 2021 Google Inc +# SPDX-License-Identifier: Apache-2.0 + +config BBRAM_NPCX + bool "Nuvoton NPCX embedded controller (EC) Battery-backed RAM drivers" + depends on SOC_FAMILY_NPCX + help + This option enables the BBRAM driver for NPCX family of processors. diff --git a/drivers/bbram/bbram_emul.c b/drivers/bbram/bbram_emul.c new file mode 100644 index 00000000000..d21f63b568f --- /dev/null +++ b/drivers/bbram/bbram_emul.c @@ -0,0 +1,148 @@ +/* + * Copyright 2021 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ + +#define DT_DRV_COMPAT zephyr_bbram_emul + +#include +#include + +#include +LOG_MODULE_REGISTER(bbram, CONFIG_BBRAM_LOG_LEVEL); + +/** Device config */ +struct bbram_emul_config { + /** BBRAM size (Unit:bytes) */ + int size; +}; + +/** Device data */ +struct bbram_emul_data { + /** Memory */ + uint8_t *data; + /** Status register */ + struct { + /** True if BBRAM is in an invalid state */ + uint8_t is_invalid : 1; + /** True if BBRAM incurred a standby power failure */ + uint8_t standby_failure : 1; + /** True if BBRAM incurred a power failure */ + uint8_t power_failure : 1; + } status; +}; + +int bbram_emul_set_invalid(const struct device *dev, bool is_invalid) +{ + struct bbram_emul_data *data = dev->data; + + data->status.is_invalid = is_invalid; + return 0; +} + +int bbram_emul_set_standby_power_state(const struct device *dev, bool failure) +{ + struct bbram_emul_data *data = dev->data; + + data->status.standby_failure = failure; + return 0; +} + +int bbram_emul_set_power_state(const struct device *dev, bool failure) +{ + struct bbram_emul_data *data = dev->data; + + data->status.power_failure = failure; + return 0; +} + +static int bbram_emul_check_invalid(const struct device *dev) +{ + struct bbram_emul_data *data = dev->data; + bool is_invalid = data->status.is_invalid; + + data->status.is_invalid = false; + return is_invalid; +} + +static int bbram_emul_check_standby_power(const struct device *dev) +{ + struct bbram_emul_data *data = dev->data; + bool failure = data->status.standby_failure; + + data->status.standby_failure = false; + return failure; +} + +static int bbram_emul_check_power(const struct device *dev) +{ + struct bbram_emul_data *data = dev->data; + bool failure = data->status.power_failure; + + data->status.power_failure = false; + return failure; +} + +static int bbram_emul_get_size(const struct device *dev, size_t *size) +{ + const struct bbram_emul_config *config = dev->config; + + *size = config->size; + return 0; +} + +static int bbram_emul_read(const struct device *dev, size_t offset, size_t size, + uint8_t *data) +{ + const struct bbram_emul_config *config = dev->config; + struct bbram_emul_data *dev_data = dev->data; + + if (size < 1 || offset + size > config->size || bbram_emul_check_invalid(dev)) { + return -EFAULT; + } + + memcpy(data, dev_data->data + offset, size); + return 0; +} + +static int bbram_emul_write(const struct device *dev, size_t offset, size_t size, + const uint8_t *data) +{ + const struct bbram_emul_config *config = dev->config; + struct bbram_emul_data *dev_data = dev->data; + + if (size < 1 || offset + size > config->size || bbram_emul_check_invalid(dev)) { + return -EFAULT; + } + + memcpy(dev_data->data + offset, data, size); + return 0; +} + +static const struct bbram_driver_api bbram_emul_driver_api = { + .check_invalid = bbram_emul_check_invalid, + .check_standby_power = bbram_emul_check_standby_power, + .check_power = bbram_emul_check_power, + .get_size = bbram_emul_get_size, + .read = bbram_emul_read, + .write = bbram_emul_write, +}; + +static int bbram_emul_init(const struct device *dev) +{ + return 0; +} + +#define BBRAM_INIT(inst) \ + static uint8_t bbram_emul_mem_##inst[DT_INST_PROP(inst, size)]; \ + static struct bbram_emul_data bbram_emul_data_##inst = { \ + .data = bbram_emul_mem_##inst, \ + }; \ + static struct bbram_emul_config bbram_emul_config_##inst = { \ + .size = DT_INST_PROP(inst, size), \ + }; \ + DEVICE_DT_INST_DEFINE(inst, &bbram_emul_init, NULL, &bbram_emul_data_##inst, \ + &bbram_emul_config_##inst, PRE_KERNEL_1, CONFIG_BBRAM_INIT_PRIORITY, \ + &bbram_emul_driver_api); + +DT_INST_FOREACH_STATUS_OKAY(BBRAM_INIT); diff --git a/drivers/bbram/bbram_npcx.c b/drivers/bbram/bbram_npcx.c new file mode 100644 index 00000000000..b7fb8b02ed3 --- /dev/null +++ b/drivers/bbram/bbram_npcx.c @@ -0,0 +1,119 @@ +/* + * Copyright (c) 2021 Google Inc + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#define DT_DRV_COMPAT nuvoton_npcx_bbram + +#include +#include +#include + +#include +LOG_MODULE_REGISTER(bbram, CONFIG_BBRAM_LOG_LEVEL); + +/** Device config */ +struct bbram_npcx_config { + /** BBRAM base address */ + uintptr_t base_addr; + /** BBRAM size (Unit:bytes) */ + int size; + /** Status register base address */ + uintptr_t status_reg_addr; +}; + +#define NPCX_STATUS_IBBR BIT(7) +#define NPCX_STATUS_VSBY BIT(1) +#define NPCX_STATUS_VCC1 BIT(0) + +#define DRV_CONFIG(dev) ((const struct bbram_npcx_config *)(dev)->config) +#define DRV_STATUS(dev) \ + (*((volatile uint8_t *)DRV_CONFIG(dev)->status_reg_addr)) + +static int get_bit_and_reset(const struct device *dev, int mask) +{ + int result = DRV_STATUS(dev) & mask; + + /* Clear the bit(s) */ + DRV_STATUS(dev) = mask; + + return result; +} + +static int bbram_npcx_check_invalid(const struct device *dev) +{ + return get_bit_and_reset(dev, NPCX_STATUS_IBBR); +} + +static int bbram_npcx_check_standby_power(const struct device *dev) +{ + return get_bit_and_reset(dev, NPCX_STATUS_VSBY); +} + +static int bbram_npcx_check_power(const struct device *dev) +{ + return get_bit_and_reset(dev, NPCX_STATUS_VCC1); +} + +static int bbram_npcx_get_size(const struct device *dev, size_t *size) +{ + const struct bbram_npcx_config *config = DRV_CONFIG(dev); + + *size = config->size; + return 0; +} + +static int bbram_npcx_read(const struct device *dev, size_t offset, size_t size, + uint8_t *data) +{ + const struct bbram_npcx_config *config = DRV_CONFIG(dev); + + if (size < 1 || offset + size > config->size || bbram_npcx_check_invalid(dev)) { + return -EFAULT; + } + + + bytecpy(data, ((volatile uint8_t *)config->base_addr + offset), size); + return 0; +} + +static int bbram_npcx_write(const struct device *dev, size_t offset, size_t size, + const uint8_t *data) +{ + const struct bbram_npcx_config *config = DRV_CONFIG(dev); + + if (size < 1 || offset + size > config->size || bbram_npcx_check_invalid(dev)) { + return -EFAULT; + } + + bytecpy(((volatile uint8_t *)config->base_addr + offset), data, size); + return 0; +} + +static const struct bbram_driver_api bbram_npcx_driver_api = { + .check_invalid = bbram_npcx_check_invalid, + .check_standby_power = bbram_npcx_check_standby_power, + .check_power = bbram_npcx_check_power, + .get_size = bbram_npcx_get_size, + .read = bbram_npcx_read, + .write = bbram_npcx_write, +}; + +static int bbram_npcx_init(const struct device *dev) +{ + return 0; +} + +#define BBRAM_INIT(inst) \ + static struct { \ + } bbram_data_##inst; \ + static const struct bbram_npcx_config bbram_cfg_##inst = { \ + .base_addr = DT_INST_REG_ADDR_BY_NAME(inst, memory), \ + .size = DT_INST_REG_SIZE_BY_NAME(inst, memory), \ + .status_reg_addr = DT_INST_REG_ADDR_BY_NAME(inst, status), \ + }; \ + DEVICE_DT_INST_DEFINE(inst, bbram_npcx_init, NULL, &bbram_data_##inst, &bbram_cfg_##inst, \ + PRE_KERNEL_1, CONFIG_BBRAM_INIT_PRIORITY, &bbram_npcx_driver_api); + +DT_INST_FOREACH_STATUS_OKAY(BBRAM_INIT); diff --git a/dts/arm/nuvoton/npcx.dtsi b/dts/arm/nuvoton/npcx.dtsi index 7922a5b7250..861fd7fe52b 100644 --- a/dts/arm/nuvoton/npcx.dtsi +++ b/dts/arm/nuvoton/npcx.dtsi @@ -69,6 +69,14 @@ }; soc { + bbram: bb-ram@400af000 { + compatible = "nuvoton,npcx-bbram"; + reg = <0x400af000 0x80 + 0x400af100 0x1>; + reg-names = "memory", "status"; + label = "BBRAM"; + }; + pcc: clock-controller@4000d000 { compatible = "nuvoton,npcx-pcc"; /* Cells for bus type, clock control reg and bit */ diff --git a/dts/bindings/memory-controllers/nuvoton,npcx-bbram.yaml b/dts/bindings/memory-controllers/nuvoton,npcx-bbram.yaml new file mode 100644 index 00000000000..2d958749238 --- /dev/null +++ b/dts/bindings/memory-controllers/nuvoton,npcx-bbram.yaml @@ -0,0 +1,15 @@ +# Copyright (c) 2021 Google Inc. +# SPDX-License-Identifier: Apache-2.0 + +description: Nuvoton, NPCX Battery Backed RAM node + +compatible: "nuvoton,npcx-bbram" + +include: base.yaml + +properties: + reg: + required: true + + label: + required: true diff --git a/dts/bindings/memory-controllers/zephyr,bbram-emul.yaml b/dts/bindings/memory-controllers/zephyr,bbram-emul.yaml new file mode 100644 index 00000000000..7581d6913b7 --- /dev/null +++ b/dts/bindings/memory-controllers/zephyr,bbram-emul.yaml @@ -0,0 +1,17 @@ +# Copyright (c) 2021 Google Inc. +# SPDX-License-Identifier: Apache-2.0 + +description: Zephyr, Battery Backed RAM emulator node + +compatible: "zephyr,bbram-emul" + +include: base.yaml + +properties: + size: + type: int + required: true + description: Size of the BBRAM region in bytes. + + label: + required: true diff --git a/include/drivers/bbram.h b/include/drivers/bbram.h new file mode 100644 index 00000000000..23382a46ef0 --- /dev/null +++ b/include/drivers/bbram.h @@ -0,0 +1,228 @@ +/* + * Copyright (c) 2021 Google Inc + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#ifndef ZEPHYR_INCLUDE_DRIVERS_BBRAM_H +#define ZEPHYR_INCLUDE_DRIVERS_BBRAM_H + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * API template to check if the BBRAM is invalid. + * + * @see bbram_check_invlaid + */ +typedef int (*bbram_api_check_invalid)(const struct device *dev); + +/** + * API template to check for standby power failure. + * + * @see bbram_check_standby_power + */ +typedef int (*bbram_api_check_standby_power)(const struct device *dev); + +/** + * API template to check for V CC1 power failure. + * + * @see bbram_check_power + */ +typedef int (*bbram_api_check_power)(const struct device *dev); + +/** + * API template to check the size of the BBRAM + * + * @see bbram_get_size + */ +typedef int (*bbram_api_get_size)(const struct device *dev, size_t *size); + +/** + * API template to read from BBRAM. + * + * @see bbram_read + */ +typedef int (*bbram_api_read)(const struct device *dev, size_t offset, size_t size, + uint8_t *data); + +/** + * API template to write to BBRAM. + * + * @see bbram_write + */ +typedef int (*bbram_api_write)(const struct device *dev, size_t offset, size_t size, + const uint8_t *data); + +__subsystem struct bbram_driver_api { + bbram_api_check_invalid check_invalid; + bbram_api_check_standby_power check_standby_power; + bbram_api_check_power check_power; + bbram_api_get_size get_size; + bbram_api_read read; + bbram_api_write write; +}; + +/** + * @brief Check if BBRAM is invalid + * + * Check if "Invalid Battery-Backed RAM" status is set then reset the status + * bit. This may occur as a result to low voltage at the VBAT pin. + * + * @param dev BBRAM device pointer. + * @return 0 if the Battery-Backed RAM data is valid, -EFAULT otherwise. + */ +__syscall int bbram_check_invalid(const struct device *dev); + +static inline int z_impl_bbram_check_invalid(const struct device *dev) +{ + const struct bbram_driver_api *api = + (const struct bbram_driver_api *)dev->api; + + if (!api->check_invalid) { + return -ENOTSUP; + } + + return api->check_invalid(dev); +} + +/** + * @brief Check for standby (Volt SBY) power failure. + * + * Check if the V standby power domain is turned on after it was off then reset + * the status bit. + * + * @param dev BBRAM device pointer. + * @return 0 if V SBY power domain is in normal operation. + */ +__syscall int bbram_check_standby_power(const struct device *dev); + +static inline int z_impl_bbram_check_standby_power(const struct device *dev) +{ + const struct bbram_driver_api *api = + (const struct bbram_driver_api *)dev->api; + + if (!api->check_standby_power) { + return -ENOTSUP; + } + + return api->check_standby_power(dev); +} + +/** + * @brief Check for V CC1 power failure. + * + * This will return an error if the V CC1 power domain is turned on after it was + * off and reset the status bit. + * + * @param dev BBRAM device pointer. + * @return 0 if the V CC1 power domain is in normal operation, -EFAULT + * otherwise. + */ +__syscall int bbram_check_power(const struct device *dev); + +static inline int z_impl_bbram_check_power(const struct device *dev) +{ + const struct bbram_driver_api *api = + (const struct bbram_driver_api *)dev->api; + + if (!api->check_power) { + return -ENOTSUP; + } + + return api->check_power(dev); +} + +/** + * Get the size of the BBRAM (in bytes). + * + * @param dev BBRAM device pointer. + * @param size Pointer to write the size to. + * @return 0 for success, -EFAULT otherwise. + */ +__syscall int bbram_get_size(const struct device *dev, size_t *size); + +static inline int z_impl_bbram_get_size(const struct device *dev, size_t *size) +{ + const struct bbram_driver_api *api = + (const struct bbram_driver_api *)dev->api; + + if (!api->get_size) { + return -ENOTSUP; + } + + return api->get_size(dev, size); +} + +/** + * Read bytes from BBRAM. + * + * @param dev The BBRAM device pointer to read from. + * @param offset The offset into the RAM address to start reading from. + * @param size The number of bytes to read. + * @param data The buffer to load the data into. + * @return 0 on success, -EFAULT if the address range is out of bounds. + */ +__syscall int bbram_read(const struct device *dev, size_t offset, size_t size, + uint8_t *data); + +static inline int z_impl_bbram_read(const struct device *dev, size_t offset, + size_t size, uint8_t *data) +{ + const struct bbram_driver_api *api = + (const struct bbram_driver_api *)dev->api; + + if (!api->read) { + return -ENOTSUP; + } + + return api->read(dev, offset, size, data); +} + +/** + * Write bytes to BBRAM. + * + * @param dev The BBRAM device pointer to write to. + * @param offset The offset into the RAM address to start writing to. + * @param size The number of bytes to write. + * @param data Pointer to the start of data to write. + * @return 0 on success, -EFAULT if the address range is out of bounds. + */ +__syscall int bbram_write(const struct device *dev, size_t offset, size_t size, + const uint8_t *data); + +static inline int z_impl_bbram_write(const struct device *dev, size_t offset, + size_t size, const uint8_t *data) +{ + const struct bbram_driver_api *api = + (const struct bbram_driver_api *)dev->api; + + if (!api->write) { + return -ENOTSUP; + } + + return api->write(dev, offset, size, data); +} + +/** + * + * @param dev + * @param is_invalid + * @return + */ +int bbram_emul_set_invalid(const struct device *dev, bool is_invalid); + +int bbram_emul_set_standby_power_state(const struct device *dev, bool failure); + +int bbram_emul_set_power_state(const struct device *dev, bool failure); + +#ifdef __cplusplus +} +#endif + +#include + +#endif /* ZEPHYR_INCLUDE_DRIVERS_BBRAM_H */ diff --git a/include/sys/util.h b/include/sys/util.h index ff2ead6f565..66418b77576 100644 --- a/include/sys/util.h +++ b/include/sys/util.h @@ -223,6 +223,22 @@ static inline int64_t arithmetic_shift_right(int64_t value, uint8_t shift) return (value >> shift) | (sign_ext << (64 - shift)); } +/** + * @brief byte by byte memcpy. + * + * Copy `size` bytes of `src` into `dest`. This is guaranteed to be done byte by byte. + * + * @param dst Pointer to the destination memory. + * @param src Pointer to the source of the data. + * @param size The number of bytes to copy. + */ +static inline void bytecpy(void *dst, const void *src, size_t size) +{ + for (size_t i = 0; i < size; ++i) { + ((uint8_t *)dst)[i] = ((uint8_t *)src)[i]; + } +} + /** * @brief Convert a single character into a hexadecimal nibble. * diff --git a/tests/drivers/bbram/CMakeLists.txt b/tests/drivers/bbram/CMakeLists.txt new file mode 100644 index 00000000000..90dc6efaca8 --- /dev/null +++ b/tests/drivers/bbram/CMakeLists.txt @@ -0,0 +1,10 @@ +# Copyright 2021 Google LLC +# SPDX-License-Identifier: Apache-2.0 + +cmake_minimum_required(VERSION 3.13.1) + +find_package(Zephyr REQUIRED HINTS $ENV{ZEPHYR_BASE}) +project(bbram) + +FILE(GLOB app_sources src/*.c) +target_sources(app PRIVATE ${app_sources}) diff --git a/tests/drivers/bbram/boards/native_posix.overlay b/tests/drivers/bbram/boards/native_posix.overlay new file mode 100644 index 00000000000..f241f65af0b --- /dev/null +++ b/tests/drivers/bbram/boards/native_posix.overlay @@ -0,0 +1,14 @@ +/* + * Copyright 2021 Google LLC + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/ { + bbram: bbram { + compatible = "zephyr,bbram-emul"; + status = "okay"; + size = <0xff>; + label = "BBRAM"; + }; +}; diff --git a/tests/drivers/bbram/prj.conf b/tests/drivers/bbram/prj.conf new file mode 100644 index 00000000000..a05c395f55d --- /dev/null +++ b/tests/drivers/bbram/prj.conf @@ -0,0 +1,6 @@ +# Copyright 2021 Google LLC +# SPDX-License-Identifier: Apache-2.0 + +CONFIG_ZTEST=y +CONFIG_BBRAM=y +CONFIG_BBRAM_EMUL=y diff --git a/tests/drivers/bbram/src/main.c b/tests/drivers/bbram/src/main.c new file mode 100644 index 00000000000..06351804231 --- /dev/null +++ b/tests/drivers/bbram/src/main.c @@ -0,0 +1,125 @@ +/* + * Copyright 2021 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include +#include +#include + +#define BBRAM_NODELABEL DT_NODELABEL(bbram) +#define BBRAM_LABEL DT_LABEL(BBRAM_NODELABEL) +#define BBRAM_SIZE DT_PROP(BBRAM_NODELABEL, size) + +static void test_get_size(void) +{ + const struct device *dev = device_get_binding(BBRAM_LABEL); + size_t size; + + zassert_ok(bbram_get_size(dev, &size), NULL); + zassert_equal(size, BBRAM_SIZE, NULL); +} + +static void test_bbram_out_of_bounds(void) +{ + const struct device *dev = device_get_binding(BBRAM_LABEL); + uint8_t buffer[BBRAM_SIZE]; + + zassert_not_null(dev, NULL); + zassert_equal(bbram_read(dev, 0, 0, buffer), -EFAULT, NULL); + zassert_equal(bbram_read(dev, 0, BBRAM_SIZE + 1, buffer), -EFAULT, NULL); + zassert_equal(bbram_read(dev, BBRAM_SIZE - 1, 2, buffer), -EFAULT, NULL); + zassert_equal(bbram_write(dev, 0, 0, buffer), -EFAULT, NULL); + zassert_equal(bbram_write(dev, 0, BBRAM_SIZE + 1, buffer), -EFAULT, NULL); + zassert_equal(bbram_write(dev, BBRAM_SIZE - 1, 2, buffer), -EFAULT, NULL); +} + +static void test_read_write(void) +{ + const struct device *dev = device_get_binding(BBRAM_LABEL); + uint8_t buffer[BBRAM_SIZE]; + uint8_t expected[BBRAM_SIZE]; + + for (int i = 0; i < BBRAM_SIZE; ++i) { + expected[i] = i; + } + /* Set and verify content. */ + zassert_ok(bbram_write(dev, 0, BBRAM_SIZE, expected), NULL); + zassert_ok(bbram_read(dev, 0, BBRAM_SIZE, buffer), NULL); + zassert_mem_equal(buffer, expected, BBRAM_SIZE, NULL); +} + +static void test_set_invalid(void) +{ + const struct device *dev = device_get_binding(BBRAM_LABEL); + + zassert_equal(bbram_check_invalid(dev), 0, NULL); + zassert_ok(bbram_emul_set_invalid(dev, true), NULL); + zassert_equal(bbram_check_invalid(dev), 1, NULL); + zassert_equal(bbram_check_invalid(dev), 0, NULL); +} + +static void test_set_standby(void) +{ + const struct device *dev = device_get_binding(BBRAM_LABEL); + + zassert_equal(bbram_check_standby_power(dev), 0, NULL); + zassert_ok(bbram_emul_set_standby_power_state(dev, true), NULL); + zassert_equal(bbram_check_standby_power(dev), 1, NULL); + zassert_equal(bbram_check_standby_power(dev), 0, NULL); +} + +static void test_set_power(void) +{ + const struct device *dev = device_get_binding(BBRAM_LABEL); + + zassert_equal(bbram_check_power(dev), 0, NULL); + zassert_ok(bbram_emul_set_power_state(dev, true), NULL); + zassert_equal(bbram_check_power(dev), 1, NULL); + zassert_equal(bbram_check_power(dev), 0, NULL); +} + +static void test_reset_invalid_on_read(void) +{ + const struct device *dev = device_get_binding(BBRAM_LABEL); + uint8_t buffer[BBRAM_SIZE]; + + zassert_ok(bbram_emul_set_invalid(dev, true), NULL); + zassert_equal(bbram_read(dev, 0, BBRAM_SIZE, buffer), -EFAULT, NULL); + zassert_equal(bbram_check_invalid(dev), 0, NULL); +} + +static void test_reset_invalid_on_write(void) +{ + const struct device *dev = device_get_binding(BBRAM_LABEL); + uint8_t buffer[BBRAM_SIZE]; + + zassert_ok(bbram_emul_set_invalid(dev, true), NULL); + zassert_equal(bbram_write(dev, 0, BBRAM_SIZE, buffer), -EFAULT, NULL); + zassert_equal(bbram_check_invalid(dev), 0, NULL); +} + +static void setup(void) +{ + const struct device *dev = device_get_binding(BBRAM_LABEL); + + bbram_emul_set_invalid(dev, false); + bbram_emul_set_standby_power_state(dev, false); + bbram_emul_set_power_state(dev, false); +} + +void test_main(void) +{ + ztest_test_suite( + bbram, + ztest_unit_test_setup_teardown(test_get_size, setup, unit_test_noop), + ztest_unit_test_setup_teardown(test_bbram_out_of_bounds, setup, unit_test_noop), + ztest_unit_test_setup_teardown(test_read_write, setup, unit_test_noop), + ztest_unit_test_setup_teardown(test_set_invalid, setup, unit_test_noop), + ztest_unit_test_setup_teardown(test_set_standby, setup, unit_test_noop), + ztest_unit_test_setup_teardown(test_set_power, setup, unit_test_noop), + ztest_unit_test_setup_teardown(test_reset_invalid_on_read, setup, unit_test_noop), + ztest_unit_test_setup_teardown(test_reset_invalid_on_write, setup, unit_test_noop)); + ztest_run_test_suite(bbram); +} diff --git a/tests/drivers/bbram/testcase.yaml b/tests/drivers/bbram/testcase.yaml new file mode 100644 index 00000000000..c4ffd17c2db --- /dev/null +++ b/tests/drivers/bbram/testcase.yaml @@ -0,0 +1,10 @@ +# Copyright 2021 Google LLC +# SPDX-License-Identifier: Apache-2.0 + +tests: + drivers.bbram: + tags: drivers bbram + harness: ztest + platform_allow: native_posix + integration_platforms: + - native_posix