diff --git a/drivers/CMakeLists.txt b/drivers/CMakeLists.txt index 3e4f36486485..4923a95e626f 100644 --- a/drivers/CMakeLists.txt +++ b/drivers/CMakeLists.txt @@ -72,3 +72,4 @@ add_subdirectory_ifdef(CONFIG_BOARD_XENVM xen) add_subdirectory_ifdef(CONFIG_MM_DRV mm) add_subdirectory_ifdef(CONFIG_RESET reset) add_subdirectory_ifdef(CONFIG_COREDUMP_DEVICE coredump) +add_subdirectory_ifdef(CONFIG_RETREG retreg) diff --git a/drivers/Kconfig b/drivers/Kconfig index 42abc99dae33..17e9d8219e3e 100644 --- a/drivers/Kconfig +++ b/drivers/Kconfig @@ -147,4 +147,6 @@ source "drivers/coredump/Kconfig" source "drivers/xen/Kconfig" +source "drivers/retreg/Kconfig" + endmenu diff --git a/drivers/retreg/CMakeLists.txt b/drivers/retreg/CMakeLists.txt new file mode 100644 index 000000000000..b3a0ab76447f --- /dev/null +++ b/drivers/retreg/CMakeLists.txt @@ -0,0 +1,5 @@ +# SPDX-License-Identifier: Apache-2.0 + +zephyr_library() + +zephyr_library_sources_ifdef(CONFIG_USERSPACE retreg_handlers.c) diff --git a/drivers/retreg/Kconfig b/drivers/retreg/Kconfig new file mode 100644 index 000000000000..09d8179e0750 --- /dev/null +++ b/drivers/retreg/Kconfig @@ -0,0 +1,12 @@ +menuconfig RETREG + bool "Retention registers support" + help + Enable support for the hardware retention registers + +if RETREG + +module = RETREG +module-str = retreg +source "subsys/logging/Kconfig.template.log_config" + +endif diff --git a/drivers/retreg/retreg_handlers.c b/drivers/retreg/retreg_handlers.c new file mode 100644 index 000000000000..884e6bda0c25 --- /dev/null +++ b/drivers/retreg/retreg_handlers.c @@ -0,0 +1,38 @@ +/* + * Copyright (c) 2022 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include + +static inline int z_vrfy_retreg_read(const struct device *dev, uint32_t reg_idx, + void *data, size_t len) +{ + Z_OOPS(Z_SYSCALL_DRIVER_RETREG(dev, read)); + Z_OOPS(Z_SYSCALL_MEMORY_WRITE(data, len)); + return z_impl_retreg_read((const struct device *)dev, reg_idx, + (void *)data, + len); +} +#include + +static inline int z_vrfy_retreg_write(const struct device *dev, uint32_t reg_idx, + const void *data, size_t len) +{ + Z_OOPS(Z_SYSCALL_DRIVER_RETREG(dev, write)); + Z_OOPS(Z_SYSCALL_MEMORY_READ(data, len)); + return z_impl_retreg_write((const struct device *)dev, reg_idx, + (const void *)data, len); +} +#include + +static inline const struct retreg_layout *z_vrfy_get_retreg_layout(const struct device *dev) +{ + Z_OOPS(Z_SYSCALL_DRIVER_RETREG(dev, get_parameters)); + return z_impl_get_reteg_layou(dev); +} +#include + +struct retreg_layout *z_impl_get_retreg_layout(const struct device *dev); diff --git a/include/zephyr/drivers/retreg.h b/include/zephyr/drivers/retreg.h new file mode 100644 index 000000000000..ef2a8b88c7a5 --- /dev/null +++ b/include/zephyr/drivers/retreg.h @@ -0,0 +1,190 @@ +/* + * Copyright (c) 2022 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/** + * @file + * + * @brief Public API for Retention Registers drivers + */ + +#ifndef ZEPHYR_INCLUDE_DRIVERS_RETREG_H_ +#define ZEPHYR_INCLUDE_DRIVERS_RETREG_H_ + +#include +#include +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @brief Retention Registers Interface + * @defgroup retreg_interface Retention Registers Interface + * @ingroup io_interfaces + * @{ + */ + +struct retreg_layout_group { + size_t reg_count; /* count of reg sequence of the same size */ + size_t reg_size; /* the size in bytes */ +}; + +struct retreg_layout { + size_t group_num; + struct retreg_layout_group *groups; +}; +/** + * @} + */ + +/** + * @brief Retention Registers internal Interface + * @defgroup retreg_internal_interface Retention Registers internal Interface + * @ingroup io_interfaces + * @{ + */ + +/** + * @brief Retention Register read implementation handler type + */ +typedef int (*retreg_api_read)(const struct device *dev, uint32_t idx, + void *data, + size_t len); +/** + * @brief Retention Register write implementation handler type + */ +typedef int (*retreg_api_write)(const struct device *dev, uint32_t idx, + const void *data, size_t len); + + +/** + * Retention parameters. Contents of this structure suppose to be + * filled in during the device initialization and stay constant + * through a runtime. + */ +struct retreg_parameters { + struct retreg_layout *retreg_layout; +}; + +/** + * @brief Retrieve paramiters of the retention registers. + * + * @param dev Retention registers device whose paramiters to retrieve. + * @param params The pointer to the paramiters will be returned in + * this argument. + */ +typedef const struct retreg_parameters *(*retreg_api_get_parameters)(const struct device *dev); + + +__subsystem struct retreg_driver_api { + retreg_api_read read; + retreg_api_write write; + retreg_api_get_parameters get_parameters; +}; + +/** + * @} + */ + +/** + * @addtogroup retreg_interface + * @{ + */ + +/** + * @brief Read data from retention register + * + * @param dev : device + * @param reg_idx : index of the retention register + * @param data : Buffer to store read data + * @param len : Number of bytes to read. + * + * @return 0 on success, negative errno code on fail. + */ +__syscall int retreg_read(const struct device *dev, uint32_t reg_idx, void *data, + size_t len); + +static inline int z_impl_retreg_read(const struct device *dev, uint32_t reg_idx, void *data, + size_t len) +{ + const struct retreg_driver_api *api = + (const struct retreg_driver_api *)dev->api; + + return api->read(dev, reg_idx, data, len); +} + +/** + * @brief Write data to retention register + * + * @param dev : device + * @param reg_idx : index of the retention register + * @param data : data to write + * @param len : Number of bytes to write. + * + * @return 0 on success, negative errno code on fail. + */ +__syscall int retreg_write(const struct device *dev, uint32_t reg_idx, const void *data, + size_t len); + +static inline int z_impl_retreg_write(const struct device *dev, uint32_t reg_idx, const void *data, + size_t len) +{ + const struct retreg_driver_api *api = + (const struct retreg_driver_api *)dev->api; + + return api->write(dev, reg_idx, data, len); +} + + +/** + * @brief Retrieve a retention registers layout. + * + * A retention registers device layout is a run-length encoded description of the + * susbsequent registers size on the device. + * + * For retention devices which have uniform register sizes, this routine + * returns an array of length 1, which specifies the page size and + * number of pages in the memory. + * + * Layouts for retention devices with nonuniform registers sizes will be + * returned as an array with multiple elements, each of which + * describes a group of registers that all have the same size. In this + * case, the sequence of array elements specifies the order in which + * these groups occur on the device. + * + * @param dev retention registers device whose layout to retrieve. + * + * @retval Pointer to the layout data. It might be NULL if layout is not + * supported by the driver. + */ +__syscall struct retreg_layout *reteg_get_layout(const struct device *dev, + const struct retreg_layout **layout, + size_t *layout_size); + +static inline const struct retreg_layout *z_impl_get_retreg_layout(const struct device *dev) +{ + const struct retreg_driver_api *api = + (const struct retreg_driver_api *)dev->api; + + const struct retreg_parameters *params; + + params = api->get_parameters(dev); + return params->retreg_layout; +} + +/** + * @} + */ + +#ifdef __cplusplus +} +#endif + +#include + +#endif /* ZEPHYR_INCLUDE_DRIVERS_RETREG_H_ */