From 4a3ba8eaca8f5255f550db7bc54dc3e23212da64 Mon Sep 17 00:00:00 2001 From: Rafal Dyla Date: Tue, 1 Oct 2024 09:02:02 +0200 Subject: [PATCH] nrfs: Add global domain power request service Service for powering peripherals that use GPIO pins in the global power domains: - Active Fast - Active Slow - Main Slow Signed-off-by: Rafal Dyla --- nrfs/include/internal/nrfs_callbacks.h | 10 +++ nrfs/include/internal/nrfs_hdr.h | 12 ++-- .../internal/requests/nrfs_gdpwr_reqs.h | 24 +++++++ .../internal/requests/nrfs_reqs_common.h | 13 ++-- nrfs/include/internal/services/nrfs_gdpwr.h | 45 +++++++++++++ nrfs/include/services/nrfs_gdpwr.h | 67 +++++++++++++++++++ nrfs/src/internal/nrfs_dispatcher.c | 5 ++ nrfs/src/services/nrfs_gdpwr.c | 67 +++++++++++++++++++ 8 files changed, 232 insertions(+), 11 deletions(-) create mode 100644 nrfs/include/internal/requests/nrfs_gdpwr_reqs.h create mode 100644 nrfs/include/internal/services/nrfs_gdpwr.h create mode 100644 nrfs/include/services/nrfs_gdpwr.h create mode 100644 nrfs/src/services/nrfs_gdpwr.c diff --git a/nrfs/include/internal/nrfs_callbacks.h b/nrfs/include/internal/nrfs_callbacks.h index fd7e9a60..746bca8c 100644 --- a/nrfs/include/internal/nrfs_callbacks.h +++ b/nrfs/include/internal/nrfs_callbacks.h @@ -96,6 +96,16 @@ void nrfs_dvfs_service_notify(void *p_notification, size_t size); */ void nrfs_clock_service_notify(void *p_notification, size_t size); +/** + * @brief Function for notifying the global domain power request service about incoming message. + * + * This function is called internally by the dispatcher when the corresponding message arrives. + * + * @param[in] p_notification Pointer to the notification payload. + * @param[in] size Notification payload size. + */ +void nrfs_gdpwr_service_notify(void *p_notification, size_t size); + #ifdef __cplusplus } #endif diff --git a/nrfs/include/internal/nrfs_hdr.h b/nrfs/include/internal/nrfs_hdr.h index e284e509..035ebef6 100644 --- a/nrfs/include/internal/nrfs_hdr.h +++ b/nrfs/include/internal/nrfs_hdr.h @@ -9,14 +9,16 @@ #include -#include +#include +#include +#include +#include #include +#include #include +#include #include -#include -#include -#include -#include + #ifdef __cplusplus extern "C" { diff --git a/nrfs/include/internal/requests/nrfs_gdpwr_reqs.h b/nrfs/include/internal/requests/nrfs_gdpwr_reqs.h new file mode 100644 index 00000000..21ff6bb2 --- /dev/null +++ b/nrfs/include/internal/requests/nrfs_gdpwr_reqs.h @@ -0,0 +1,24 @@ +/* + * Copyright (c) 2024 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#ifndef NRFS_GDPWR_REQS_H +#define NRFS_GDPWR_REQS_H + +#include "nrfs_reqs_common.h" + +#ifdef __cplusplus +extern "C" { +#endif + +enum { + NRFS_GDPWR_REQ_SET_POWER_REQUEST= NRFS_REQUEST_ID_DEF(NRFS_SERVICE_ID_GDPWR, 0x01), +}; + +#ifdef __cplusplus +} +#endif + +#endif /* NRFS_GDPWR_REQS_H */ diff --git a/nrfs/include/internal/requests/nrfs_reqs_common.h b/nrfs/include/internal/requests/nrfs_reqs_common.h index 3a18960d..6f3edf2b 100644 --- a/nrfs/include/internal/requests/nrfs_reqs_common.h +++ b/nrfs/include/internal/requests/nrfs_reqs_common.h @@ -53,14 +53,15 @@ extern "C" { #endif enum { - NRFS_SERVICE_ID_TEMP, + NRFS_SERVICE_ID_CLOCK, + NRFS_SERVICE_ID_DIAG, + NRFS_SERVICE_ID_DVFS, + NRFS_SERVICE_ID_GDPWR, NRFS_SERVICE_ID_MRAM, - NRFS_SERVICE_ID_RESET, - NRFS_SERVICE_ID_USB, NRFS_SERVICE_ID_PMIC, - NRFS_SERVICE_ID_DVFS, - NRFS_SERVICE_ID_DIAG, - NRFS_SERVICE_ID_CLOCK, + NRFS_SERVICE_ID_RESET, + NRFS_SERVICE_ID_TEMP, + NRFS_SERVICE_ID_USB }; #ifdef __cplusplus diff --git a/nrfs/include/internal/services/nrfs_gdpwr.h b/nrfs/include/internal/services/nrfs_gdpwr.h new file mode 100644 index 00000000..947fe745 --- /dev/null +++ b/nrfs/include/internal/services/nrfs_gdpwr.h @@ -0,0 +1,45 @@ +/* + * Copyright (c) 2024 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#ifndef NRFS_INTERNAL_GDPWR_H +#define NRFS_INTERNAL_GDPWR_H + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/** @brief Power domain selection */ +typedef enum __NRFS_PACKED { + GDPWR_POWER_DOMAIN_ACTIVE_FAST, + GDPWR_POWER_DOMAIN_ACTIVE_SLOW, + GDPWR_POWER_DOMAIN_MAIN_SLOW +} gdpwr_power_domain_t; + +typedef enum __NRFS_PACKED { + GDPWR_POWER_REQUEST_CLEAR, + GDPWR_POWER_REQUEST_SET +} gdpwr_request_type_t; + +/** @brief Power domain data structure. */ +typedef struct __NRFS_PACKED { + gdpwr_power_domain_t power_domain; + gdpwr_request_type_t request_type; +} nrfs_gdpwr_power_domain_data_t; + +/** @brief global domain power request structure. */ +typedef struct __NRFS_PACKED { + nrfs_hdr_t hdr; /**< Header of the message. */ + nrfs_ctx_t ctx; /**< Context of the message. */ + nrfs_gdpwr_power_domain_data_t data; /**< Data of the request. */ +} nrfs_gdpwr_req_t; + +#ifdef __cplusplus +} +#endif + +#endif /* NRFS_INTERNAL_GDPWR_H */ diff --git a/nrfs/include/services/nrfs_gdpwr.h b/nrfs/include/services/nrfs_gdpwr.h new file mode 100644 index 00000000..807460b6 --- /dev/null +++ b/nrfs/include/services/nrfs_gdpwr.h @@ -0,0 +1,67 @@ +/* + * Copyright (c) 2024 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#ifndef NRFS_GDPWR_H +#define NRFS_GDPWR_H + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/** @brief Global domain power request service response notification types. */ +typedef enum __NRFS_PACKED { + NRFS_GDPWR_REQ_APPLIED, /** Request accepted. */ + NRFS_GDPWR_REQ_REJECTED /** Request rejected. */ +} nrfs_gdpwr_evt_type_t; + +/** @brief Global domain power request service response data structure. */ +typedef struct { + nrfs_gdpwr_evt_type_t type; +} nrfs_gdpwr_evt_t; + +/** @brief Global domain power request service event handler type. */ +typedef void (*nrfs_gdpwr_evt_handler_t)(nrfs_gdpwr_evt_t const *p_evt, + void *context); + +/** + * @brief Function for initializing the global domain power request service. + * + * @param[in] handler Function called as a response to the request. + * + * @retval NRFS_SUCCESS Service initialized successfully. + * @retval NRFS_ERR_INVALID_STATE Service was already initialized. + */ +nrfs_err_t nrfs_gdpwr_init(nrfs_gdpwr_evt_handler_t handler); + +/** + * @brief Function for uninitializing the global domain power request service. + * + * @warning Notifications from previous requests are dropped after service uninitialization. + */ +void nrfs_gdpwr_uninit(void); + +/** + * @brief Function for requesting and releasing power request in the specific global domain. + * + * @param[in] power_domain selection of power domain in the global domain. + * @param[in] req_type set/clear power request for specific power domain. + * @param[in] p_context Opaque user data that will be passed to registered callback. + * + * @retval NRFS_SUCCESS Request sent successfully. + * @retval NRFS_ERR_INVALID_STATE Service is uninitialized. + * @retval NRFS_ERR_IPC Backend returned error during request sending. + */ +nrfs_err_t nrfs_gdpwr_power_request(gdpwr_power_domain_t power_domain, + gdpwr_request_type_t req_type, + void *p_context); + +#ifdef __cplusplus +} +#endif + +#endif /* NRFS_GDPWR_H */ diff --git a/nrfs/src/internal/nrfs_dispatcher.c b/nrfs/src/internal/nrfs_dispatcher.c index 038ae110..34e1cbdd 100644 --- a/nrfs/src/internal/nrfs_dispatcher.c +++ b/nrfs/src/internal/nrfs_dispatcher.c @@ -50,6 +50,11 @@ static const nrfs_service_cb_t services_callbacks[] = { #else [NRFS_SERVICE_ID_CLOCK] = NULL, #endif +#ifdef NRFS_GDPWR_SERVICE_ENABLED + [NRFS_SERVICE_ID_GDPWR] = nrfs_gdpwr_service_notify, +#else + [NRFS_SERVICE_ID_GDPWR] = NULL, +#endif }; /* Warning! All "UNSOLICITED" features are not supported. This is intended for possible future use. */ diff --git a/nrfs/src/services/nrfs_gdpwr.c b/nrfs/src/services/nrfs_gdpwr.c new file mode 100644 index 00000000..88c7f73d --- /dev/null +++ b/nrfs/src/services/nrfs_gdpwr.c @@ -0,0 +1,67 @@ +/* + * Copyright (c) 2024 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include +#include + +typedef struct { + nrfs_gdpwr_evt_handler_t handler; + bool is_initialized; +} nrfs_gdpwr_cb_t; +static nrfs_gdpwr_cb_t m_cb; + +nrfs_err_t nrfs_gdpwr_init(nrfs_gdpwr_evt_handler_t handler) +{ + if (m_cb.is_initialized) { + return NRFS_ERR_INVALID_STATE; + } + + m_cb.handler = handler; + m_cb.is_initialized = true; + return NRFS_SUCCESS; +} + +void nrfs_gdpwr_uninit(void) +{ + m_cb.is_initialized = false; +} + +void nrfs_gdpwr_service_notify(void *p_notification, size_t size) +{ + if (!m_cb.handler || !m_cb.is_initialized) { + return; + } + + nrfs_gdpwr_evt_t evt; + nrfs_generic_t *p_data = (nrfs_generic_t *)p_notification; + + if (NRFS_HDR_FILTER_ERR_GET(&p_data->hdr)) { + evt.type = NRFS_GDPWR_REQ_REJECTED; + m_cb.handler(&evt, (void *)p_data->ctx.ctx); + return; + } + + evt.type = NRFS_GDPWR_REQ_APPLIED; + m_cb.handler(&evt, (void *)p_data->ctx.ctx); +} + +nrfs_err_t nrfs_gdpwr_power_request(gdpwr_power_domain_t power_domain, + gdpwr_request_type_t req_type, + void *p_context) +{ + if (!m_cb.is_initialized) { + return NRFS_ERR_INVALID_STATE; + } + + nrfs_gdpwr_req_t req; + + NRFS_SERVICE_HDR_FILL(&req, NRFS_GDPWR_REQ_SET_POWER_REQUEST); + req.ctx.ctx = (uint32_t)p_context; + req.data.power_domain = power_domain; + req.data.request_type = req_type; + return nrfs_backend_send(&req, sizeof(req)); +}