From 77652a5fbb8a9666a1f38f4d80df925bfcc5e9c9 Mon Sep 17 00:00:00 2001 From: Adam Kondraciuk Date: Wed, 18 Sep 2024 17:58:24 +0200 Subject: [PATCH 1/3] soc: nordic: Add LRCCONF management Due to the possibility of simultaneous accesess to LRCCONF registers, additional management is required. Signed-off-by: Adam Kondraciuk --- .../clock_control/clock_control_nrf2_common.c | 35 ---- .../clock_control/clock_control_nrf2_common.h | 10 -- .../clock_control/clock_control_nrf2_fll16m.c | 8 +- .../clock_control/clock_control_nrf2_hfxo.c | 8 +- soc/nordic/common/CMakeLists.txt | 3 + soc/nordic/common/soc_lrcconf.c | 61 +++++++ soc/nordic/common/soc_lrcconf.h | 34 ++++ soc/nordic/nrf54h/power.c | 163 ++++++++++++------ soc/nordic/nrf54h/soc.c | 16 +- soc/nordic/nrf54h/soc.h | 11 ++ 10 files changed, 240 insertions(+), 109 deletions(-) create mode 100644 soc/nordic/common/soc_lrcconf.c create mode 100644 soc/nordic/common/soc_lrcconf.h diff --git a/drivers/clock_control/clock_control_nrf2_common.c b/drivers/clock_control/clock_control_nrf2_common.c index 7f8f2cbcd422f1..f3b21a5dd1fbe0 100644 --- a/drivers/clock_control/clock_control_nrf2_common.c +++ b/drivers/clock_control/clock_control_nrf2_common.c @@ -4,7 +4,6 @@ */ #include "clock_control_nrf2_common.h" -#include #include LOG_MODULE_REGISTER(clock_control_nrf2, CONFIG_CLOCK_CONTROL_LOG_LEVEL); @@ -25,9 +24,6 @@ LOG_MODULE_REGISTER(clock_control_nrf2, CONFIG_CLOCK_CONTROL_LOG_LEVEL); */ STRUCT_CLOCK_CONFIG(generic, ONOFF_CNT_MAX); -static sys_slist_t poweron_main_list; -static struct k_spinlock poweron_main_lock; - static void update_config(struct clock_config_generic *cfg) { atomic_val_t prev_flags = atomic_or(&cfg->flags, FLAG_UPDATE_NEEDED); @@ -163,34 +159,3 @@ int api_nosys_on_off(const struct device *dev, clock_control_subsys_t sys) return -ENOSYS; } - -void clock_request_lrcconf_poweron_main(struct clock_lrcconf_sink *sink) -{ - K_SPINLOCK(&poweron_main_lock) { - if (sys_slist_len(&poweron_main_list) == 0) { - LOG_DBG("%s forced on", "main domain"); - NRF_LRCCONF010->POWERON &= ~LRCCONF_POWERON_MAIN_Msk; - NRF_LRCCONF010->POWERON |= LRCCONF_POWERON_MAIN_AlwaysOn; - } - - sys_slist_find_and_remove(&poweron_main_list, &sink->node); - sys_slist_append(&poweron_main_list, &sink->node); - } -} - -void clock_release_lrcconf_poweron_main(struct clock_lrcconf_sink *sink) -{ - K_SPINLOCK(&poweron_main_lock) { - if (!sys_slist_find_and_remove(&poweron_main_list, &sink->node)) { - K_SPINLOCK_BREAK; - } - - if (sys_slist_len(&poweron_main_list) > 0) { - K_SPINLOCK_BREAK; - } - - LOG_DBG("%s automatic", "main domain"); - NRF_LRCCONF010->POWERON &= ~LRCCONF_POWERON_MAIN_Msk; - NRF_LRCCONF010->POWERON |= LRCCONF_POWERON_MAIN_Automatic; - } -} diff --git a/drivers/clock_control/clock_control_nrf2_common.h b/drivers/clock_control/clock_control_nrf2_common.h index 67d303c132d9bc..858698c38ea7ea 100644 --- a/drivers/clock_control/clock_control_nrf2_common.h +++ b/drivers/clock_control/clock_control_nrf2_common.h @@ -75,14 +75,4 @@ void clock_config_update_end(void *clk_cfg, int status); int api_nosys_on_off(const struct device *dev, clock_control_subsys_t sys); -struct clock_lrcconf_sink { - sys_snode_t node; -}; - -/** - * @brief Request or release lrcconf main power domain - */ -void clock_request_lrcconf_poweron_main(struct clock_lrcconf_sink *sink); -void clock_release_lrcconf_poweron_main(struct clock_lrcconf_sink *sink); - #endif /* ZEPHYR_DRIVERS_CLOCK_CONTROL_NRF2_COMMON_H_ */ diff --git a/drivers/clock_control/clock_control_nrf2_fll16m.c b/drivers/clock_control/clock_control_nrf2_fll16m.c index 7462d822f4480a..613e433e527492 100644 --- a/drivers/clock_control/clock_control_nrf2_fll16m.c +++ b/drivers/clock_control/clock_control_nrf2_fll16m.c @@ -8,7 +8,7 @@ #include "clock_control_nrf2_common.h" #include #include -#include +#include #include LOG_MODULE_DECLARE(clock_control_nrf2, CONFIG_CLOCK_CONTROL_LOG_LEVEL); @@ -64,7 +64,7 @@ static const struct clock_options { struct fll16m_dev_data { STRUCT_CLOCK_CONFIG(fll16m, ARRAY_SIZE(clock_options)) clk_cfg; struct onoff_client hfxo_cli; - struct clock_lrcconf_sink lrcconf_sink; + sys_snode_t fll16m_node; }; struct fll16m_dev_config { @@ -76,13 +76,13 @@ static void activate_fll16m_mode(struct fll16m_dev_data *dev_data, uint8_t mode) /* TODO: change to nrf_lrcconf_* function when such is available. */ if (mode != FLL16M_MODE_DEFAULT) { - clock_request_lrcconf_poweron_main(&dev_data->lrcconf_sink); + soc_lrcconf_poweron_request(&dev_data->fll16m_node, NRF_LRCCONF_POWER_MAIN); } NRF_LRCCONF010->CLKCTRL[0].SRC = mode; if (mode == FLL16M_MODE_DEFAULT) { - clock_release_lrcconf_poweron_main(&dev_data->lrcconf_sink); + soc_lrcconf_poweron_release(&dev_data->fll16m_node, NRF_LRCCONF_POWER_MAIN); } nrf_lrcconf_task_trigger(NRF_LRCCONF010, NRF_LRCCONF_TASK_CLKSTART_0); diff --git a/drivers/clock_control/clock_control_nrf2_hfxo.c b/drivers/clock_control/clock_control_nrf2_hfxo.c index ca49d9015ccb03..977c0aaa0d6804 100644 --- a/drivers/clock_control/clock_control_nrf2_hfxo.c +++ b/drivers/clock_control/clock_control_nrf2_hfxo.c @@ -11,7 +11,7 @@ #include LOG_MODULE_DECLARE(clock_control_nrf2, CONFIG_CLOCK_CONTROL_LOG_LEVEL); -#include +#include BUILD_ASSERT(DT_NUM_INST_STATUS_OKAY(DT_DRV_COMPAT) == 1, "multiple instances not supported"); @@ -20,7 +20,7 @@ struct dev_data_hfxo { struct onoff_manager mgr; onoff_notify_fn notify; struct k_timer timer; - struct clock_lrcconf_sink lrcconf_sink; + sys_snode_t hfxo_node; }; struct dev_config_hfxo { @@ -58,7 +58,7 @@ static void onoff_start_hfxo(struct onoff_manager *mgr, onoff_notify_fn notify) dev_data->notify = notify; nrf_lrcconf_event_clear(NRF_LRCCONF010, NRF_LRCCONF_EVENT_HFXOSTARTED); - clock_request_lrcconf_poweron_main(&dev_data->lrcconf_sink); + soc_lrcconf_poweron_request(&dev_data->hfxo_node, NRF_LRCCONF_POWER_MAIN); nrf_lrcconf_task_trigger(NRF_LRCCONF010, NRF_LRCCONF_TASK_REQHFXO); /* Due to a hardware issue, the HFXOSTARTED event is currently @@ -74,7 +74,7 @@ static void onoff_stop_hfxo(struct onoff_manager *mgr, onoff_notify_fn notify) CONTAINER_OF(mgr, struct dev_data_hfxo, mgr); nrf_lrcconf_task_trigger(NRF_LRCCONF010, NRF_LRCCONF_TASK_STOPREQHFXO); - clock_release_lrcconf_poweron_main(&dev_data->lrcconf_sink); + soc_lrcconf_poweron_release(&dev_data->hfxo_node, NRF_LRCCONF_POWER_MAIN); notify(mgr, 0); } diff --git a/soc/nordic/common/CMakeLists.txt b/soc/nordic/common/CMakeLists.txt index 38c55c614e9e55..4e000006d41bd2 100644 --- a/soc/nordic/common/CMakeLists.txt +++ b/soc/nordic/common/CMakeLists.txt @@ -12,6 +12,9 @@ if(CONFIG_ARM) endif() zephyr_library_sources_ifdef(CONFIG_POWEROFF poweroff.c) +if(CONFIG_ARM) + zephyr_library_sources_ifdef(CONFIG_NRF_PLATFORM_HALTIUM soc_lrcconf.c) +endif() if((CONFIG_SOC_SERIES_NRF54HX OR CONFIG_SOC_SERIES_NRF92X) AND CONFIG_CPU_HAS_CUSTOM_FIXED_SOC_MPU_REGIONS) zephyr_library_sources(nrf54hx_nrf92x_mpu_regions.c) diff --git a/soc/nordic/common/soc_lrcconf.c b/soc/nordic/common/soc_lrcconf.c new file mode 100644 index 00000000000000..f7a40c1d099e3d --- /dev/null +++ b/soc/nordic/common/soc_lrcconf.c @@ -0,0 +1,61 @@ +/* + * Copyright (c) 2024 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include + +static struct k_spinlock lock; +static sys_slist_t poweron_main_list; +static sys_slist_t poweron_active_list; + +void soc_lrcconf_poweron_request(sys_snode_t *node, nrf_lrcconf_power_domain_mask_t domain) +{ + __ASSERT(is_power_of_two(domain), "Only one bit can be set for the domain parameter"); + + sys_slist_t *poweron_list; + + if (domain == NRF_LRCCONF_POWER_MAIN) { + poweron_list = &poweron_main_list; + } else if (domain == NRF_LRCCONF_POWER_DOMAIN_0) { + poweron_list = &poweron_active_list; + } else { + return; + } + K_SPINLOCK(&lock) { + if (sys_slist_len(poweron_list) == 0) { + nrf_lrcconf_poweron_force_set(NRF_LRCCONF010, domain, true); + } + + sys_slist_find_and_remove(poweron_list, node); + sys_slist_append(poweron_list, node); + } +} + +void soc_lrcconf_poweron_release(sys_snode_t *node, nrf_lrcconf_power_domain_mask_t domain) +{ + __ASSERT(is_power_of_two(domain), "Only one bit can be set for the domain parameter"); + + sys_slist_t *poweron_list; + + if (domain == NRF_LRCCONF_POWER_MAIN) { + poweron_list = &poweron_main_list; + } else if (domain == NRF_LRCCONF_POWER_DOMAIN_0) { + poweron_list = &poweron_active_list; + } else { + return; + } + + K_SPINLOCK(&lock) { + if (!sys_slist_find_and_remove(poweron_list, node)) { + K_SPINLOCK_BREAK; + } + + if (sys_slist_len(poweron_list) > 0) { + K_SPINLOCK_BREAK; + } + nrf_lrcconf_poweron_force_set(NRF_LRCCONF010, domain, false); + } +} diff --git a/soc/nordic/common/soc_lrcconf.h b/soc/nordic/common/soc_lrcconf.h new file mode 100644 index 00000000000000..5ce4711252968c --- /dev/null +++ b/soc/nordic/common/soc_lrcconf.h @@ -0,0 +1,34 @@ +/* + * Copyright (c) 2024 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/** + * @file nRF SoC specific helpers for lrcconf management + */ + +#ifndef ZEPHYR_SOC_NORDIC_COMMON_LRCCONF_H_ +#define ZEPHYR_SOC_NORDIC_COMMON_LRCCONF_H_ + +#include + +/** + * @brief Request lrcconf power domain + * + * @param node Pointer to the @ref sys_snode_t structure which is the ID of the + * requesting module. + * @param domain The mask that represents the power domain ID. + */ +void soc_lrcconf_poweron_request(sys_snode_t *node, nrf_lrcconf_power_domain_mask_t domain); + +/** + * @brief Release lrcconf power domain + * + * @param node Pointer to the @ref sys_snode_t structure which is the ID of the + * requesting module. + * @param domain The mask that represents the power domain ID. + */ +void soc_lrcconf_poweron_release(sys_snode_t *node, nrf_lrcconf_power_domain_mask_t domain); + +#endif /* ZEPHYR_SOC_NORDIC_COMMON_LRCCONF_H_ */ diff --git a/soc/nordic/nrf54h/power.c b/soc/nordic/nrf54h/power.c index ad7ae18d9bb191..1a59320d80b48b 100644 --- a/soc/nordic/nrf54h/power.c +++ b/soc/nordic/nrf54h/power.c @@ -9,20 +9,26 @@ #include #include #include -#include #include #include #include +#include +#include "soc.h" #include "pm_s2ram.h" -static void suspend_common(void) +static void common_suspend(void) { + sys_snode_t *node; - /* Flush, disable and power down DCACHE */ - sys_cache_data_flush_all(); - sys_cache_data_disable(); - nrf_memconf_ramblock_control_enable_set(NRF_MEMCONF, RAMBLOCK_POWER_ID, - RAMBLOCK_CONTROL_BIT_DCACHE, false); + node = soc_pd_sys_snode_get(); + + if (IS_ENABLED(CONFIG_DCACHE)) { + /* Flush, disable and power down DCACHE */ + sys_cache_data_flush_all(); + sys_cache_data_disable(); + nrf_memconf_ramblock_control_enable_set(NRF_MEMCONF, RAMBLOCK_POWER_ID, + RAMBLOCK_CONTROL_BIT_DCACHE, false); + } if (IS_ENABLED(CONFIG_ICACHE)) { /* Disable and power down ICACHE */ @@ -31,9 +37,30 @@ static void suspend_common(void) RAMBLOCK_CONTROL_BIT_ICACHE, false); } - /* Disable retention */ - nrf_lrcconf_retain_set(NRF_LRCCONF010, NRF_LRCCONF_POWER_DOMAIN_0, false); - nrf_lrcconf_poweron_force_set(NRF_LRCCONF010, NRF_LRCCONF_POWER_DOMAIN_0, false); + soc_lrcconf_poweron_release(node, NRF_LRCCONF_POWER_DOMAIN_0); +} + +static void common_resume(void) +{ + sys_snode_t *node; + + node = soc_pd_sys_snode_get(); + + if (IS_ENABLED(CONFIG_ICACHE)) { + /* Power up and re-enable ICACHE */ + nrf_memconf_ramblock_control_enable_set(NRF_MEMCONF, RAMBLOCK_POWER_ID, + RAMBLOCK_CONTROL_BIT_ICACHE, true); + sys_cache_instr_enable(); + } + + if (IS_ENABLED(CONFIG_DCACHE)) { + /* Power up and re-enable DCACHE */ + nrf_memconf_ramblock_control_enable_set(NRF_MEMCONF, RAMBLOCK_POWER_ID, + RAMBLOCK_CONTROL_BIT_DCACHE, true); + sys_cache_data_enable(); + } + + soc_lrcconf_poweron_request(node, NRF_LRCCONF_POWER_DOMAIN_0); } void nrf_poweroff(void) @@ -41,13 +68,12 @@ void nrf_poweroff(void) nrf_resetinfo_resetreas_local_set(NRF_RESETINFO, 0); nrf_resetinfo_restore_valid_set(NRF_RESETINFO, false); +#if !defined(CONFIG_SOC_NRF54H20_CPURAD) + /* Disable retention */ nrf_lrcconf_retain_set(NRF_LRCCONF010, NRF_LRCCONF_POWER_MAIN, false); - - /* TODO: Move it around k_cpu_idle() implementation. */ - nrf_lrcconf_poweron_force_set(NRF_LRCCONF010, NRF_LRCCONF_POWER_MAIN, false); - nrf_lrcconf_poweron_force_set(NRF_LRCCONF010, NRF_LRCCONF_POWER_DOMAIN_0, false); - - suspend_common(); + nrf_lrcconf_retain_set(NRF_LRCCONF010, NRF_LRCCONF_POWER_DOMAIN_0, false); +#endif + common_suspend(); nrf_lrcconf_task_trigger(NRF_LRCCONF010, NRF_LRCCONF_TASK_SYSTEMOFFREADY); @@ -59,30 +85,65 @@ void nrf_poweroff(void) CODE_UNREACHABLE; } -#if IS_ENABLED(CONFIG_PM_S2RAM) -/* Resume domain after local suspend to RAM. */ -static void sys_resume(void) +static void s2idle_enter(uint8_t substate_id) { - if (IS_ENABLED(CONFIG_ICACHE)) { - /* Power up and re-enable ICACHE */ - nrf_memconf_ramblock_control_enable_set(NRF_MEMCONF, RAMBLOCK_POWER_ID, - RAMBLOCK_CONTROL_BIT_ICACHE, true); - sys_cache_instr_enable(); + sys_snode_t *node; + + node = soc_pd_sys_snode_get(); + + switch (substate_id) { + case 0: + /* Substate for idle with cache powered on - not implemented yet. */ + break; + case 1: /* Substate for idle with cache retained - not implemented yet. */ + break; + case 2: /* Substate for idle with cache disabled. */ +#if !defined(CONFIG_SOC_NRF54H20_CPURAD) + soc_lrcconf_poweron_request(node, NRF_LRCCONF_POWER_MAIN); +#endif + common_suspend(); + break; + default: /* Unknown substate. */ + return; } - if (IS_ENABLED(CONFIG_DCACHE)) { - /* Power up and re-enable DCACHE */ - nrf_memconf_ramblock_control_enable_set(NRF_MEMCONF, RAMBLOCK_POWER_ID, - RAMBLOCK_CONTROL_BIT_DCACHE, true); - sys_cache_data_enable(); + __set_BASEPRI(0); + __ISB(); + __DSB(); + __WFI(); +} + +static void s2idle_exit(uint8_t substate_id) +{ + sys_snode_t *node; + + node = soc_pd_sys_snode_get(); + + switch (substate_id) { + case 0: + /* Substate for idle with cache powered on - not implemented yet. */ + break; + case 1: /* Substate for idle with cache retained - not implemented yet. */ + break; + case 2: /* Substate for idle with cache disabled. */ + common_resume(); +#if !defined(CONFIG_SOC_NRF54H20_CPURAD) + soc_lrcconf_poweron_release(node, NRF_LRCCONF_POWER_MAIN); +#endif + default: /* Unknown substate. */ + return; } +} +#if defined(CONFIG_PM_S2RAM) +/* Resume domain after local suspend to RAM. */ +static void s2ram_exit(void) +{ + common_resume(); +#if !defined(CONFIG_SOC_NRF54H20_CPURAD) /* Re-enable domain retention. */ nrf_lrcconf_retain_set(NRF_LRCCONF010, NRF_LRCCONF_POWER_DOMAIN_0, true); - - /* TODO: Move it around k_cpu_idle() implementation. */ - nrf_lrcconf_poweron_force_set(NRF_LRCCONF010, NRF_LRCCONF_POWER_MAIN, - !IS_ENABLED(CONFIG_SOC_NRF54H20_CPURAD)); +#endif } /* Function called during local domain suspend to RAM. */ @@ -94,10 +155,12 @@ static int sys_suspend_to_ram(void) nrf_resetinfo_resetreas_local_set(NRF_RESETINFO, NRF_RESETINFO_RESETREAS_LOCAL_UNRETAINED_MASK); nrf_resetinfo_restore_valid_set(NRF_RESETINFO, true); - nrf_lrcconf_poweron_force_set(NRF_LRCCONF010, NRF_LRCCONF_POWER_DOMAIN_0, false); - nrf_lrcconf_poweron_force_set(NRF_LRCCONF010, NRF_LRCCONF_POWER_MAIN, false); - suspend_common(); +#if !defined(CONFIG_SOC_NRF54H20_CPURAD) + /* Disable retention */ + nrf_lrcconf_retain_set(NRF_LRCCONF010, NRF_LRCCONF_POWER_DOMAIN_0, false); +#endif + common_suspend(); __set_BASEPRI(0); __ISB(); @@ -110,7 +173,7 @@ static int sys_suspend_to_ram(void) return -EBUSY; } -static void do_suspend_to_ram(void) +static void s2ram_enter(void) { /* * Save the CPU context (including the return address),set the SRAM @@ -119,24 +182,26 @@ static void do_suspend_to_ram(void) if (soc_s2ram_suspend(sys_suspend_to_ram)) { return; } - - /* - * On resuming or error we return exactly *HERE* - */ - - sys_resume(); } -#endif /* IS_ENABLED(CONFIG_PM_S2RAM) */ +#endif /* defined(CONFIG_PM_S2RAM) */ void pm_state_set(enum pm_state state, uint8_t substate_id) { - if (state != PM_STATE_SUSPEND_TO_RAM) { - k_cpu_idle(); - return; + if (state == PM_STATE_SUSPEND_TO_IDLE) { + s2idle_enter(substate_id); + /* Resume here. */ + s2idle_exit(substate_id); + } +#if defined(CONFIG_PM_S2RAM) + else if (state == PM_STATE_SUSPEND_TO_RAM) { + s2ram_enter(); + /* On resuming or error we return exactly *HERE* */ + s2ram_exit(); } -#if IS_ENABLED(CONFIG_PM_S2RAM) - do_suspend_to_ram(); #endif + else { + k_cpu_idle(); + } } void pm_state_exit_post_ops(enum pm_state state, uint8_t substate_id) diff --git a/soc/nordic/nrf54h/soc.c b/soc/nordic/nrf54h/soc.c index 4ffb17bef51a67..85570bd9ff37db 100644 --- a/soc/nordic/nrf54h/soc.c +++ b/soc/nordic/nrf54h/soc.c @@ -19,6 +19,7 @@ #include #include #include +#include #include LOG_MODULE_REGISTER(soc, CONFIG_SOC_LOG_LEVEL); @@ -29,6 +30,8 @@ LOG_MODULE_REGISTER(soc, CONFIG_SOC_LOG_LEVEL); #define HSFLL_NODE DT_NODELABEL(cpurad_hsfll) #endif +static sys_snode_t soc_node; + #define FICR_ADDR_GET(node_id, name) \ DT_REG_ADDR(DT_PHANDLE_BY_NAME(node_id, nordic_ficrs, name)) + \ DT_PHA_BY_NAME(node_id, nordic_ficrs, name, offset) @@ -38,6 +41,10 @@ LOG_MODULE_REGISTER(soc, CONFIG_SOC_LOG_LEVEL); ADDRESS_SECURITY_Msk | \ ADDRESS_DOMAIN_Msk | \ ADDRESS_BUS_Msk))) +sys_snode_t *soc_pd_sys_snode_get(void) +{ + return &soc_node; +} static void power_domain_init(void) { @@ -52,13 +59,9 @@ static void power_domain_init(void) * WFI the power domain will be correctly retained. */ - nrf_lrcconf_poweron_force_set(NRF_LRCCONF010, NRF_LRCCONF_POWER_DOMAIN_0, - !IS_ENABLED(CONFIG_SOC_NRF54H20_CPURAD)); - nrf_lrcconf_poweron_force_set(NRF_LRCCONF010, NRF_LRCCONF_POWER_MAIN, - !IS_ENABLED(CONFIG_SOC_NRF54H20_CPURAD)); + soc_lrcconf_poweron_request(&soc_node, NRF_LRCCONF_POWER_DOMAIN_0); + nrf_lrcconf_poweron_force_set(NRF_LRCCONF010, NRF_LRCCONF_POWER_MAIN, false); - nrf_lrcconf_retain_set(NRF_LRCCONF010, NRF_LRCCONF_POWER_MAIN, true); - nrf_lrcconf_retain_set(NRF_LRCCONF010, NRF_LRCCONF_POWER_DOMAIN_0, true); nrf_memconf_ramblock_ret_enable_set(NRF_MEMCONF, 0, RAMBLOCK_RET_BIT_ICACHE, false); nrf_memconf_ramblock_ret_enable_set(NRF_MEMCONF, 0, RAMBLOCK_RET_BIT_DCACHE, false); nrf_memconf_ramblock_ret_enable_set(NRF_MEMCONF, 1, RAMBLOCK_RET_BIT_ICACHE, false); @@ -122,7 +125,6 @@ bool z_arm_on_enter_cpu_idle(void) #ifdef CONFIG_LOG_FRONTEND_STMESP log_frontend_stmesp_pre_sleep(); #endif - return true; } #endif diff --git a/soc/nordic/nrf54h/soc.h b/soc/nordic/nrf54h/soc.h index db79e2c8c720a9..f952bd092d6c8e 100644 --- a/soc/nordic/nrf54h/soc.h +++ b/soc/nordic/nrf54h/soc.h @@ -8,6 +8,7 @@ #define SOC_ARM_NORDIC_NRF_NRF54H_SOC_H_ #include +#include #if defined(CONFIG_SOC_NRF54H20_CPUAPP) || defined(CONFIG_SOC_NRF54H20_ENGB_CPUAPP) #define RAMBLOCK_CONTROL_BIT_ICACHE MEMCONF_POWER_CONTROL_MEM1_Pos @@ -36,4 +37,14 @@ #define RAMBLOCK_RET2_BIT_DCACHE MEMCONF_POWER_RET2_MEM7_Pos #endif +/** + * @brief Get the ID of the node used by the power domain management. + * + * This function returns the node ID to be shared with other dependent modules. + * + * @return The pointer to the node assigned to the SOC module + * used for the power domain management purposes. + */ +sys_snode_t *soc_pd_sys_snode_get(void); + #endif /* SOC_ARM_NORDIC_NRF_NRF54H_SOC_H_ */ From dc871e99e98f879b57ae7b89c38e8186bb4ed341 Mon Sep 17 00:00:00 2001 From: Adam Kondraciuk Date: Wed, 2 Oct 2024 10:39:56 +0200 Subject: [PATCH 2/3] dts: arm: nordic: Add power states for nRF54H20 Add `idle` and `s2ram` power states for nRF54H20 cpuapp and cpurad. Also the substate `idle_cache_disable` added. Signed-off-by: Adam Kondraciuk --- dts/common/nordic/nrf54h20.dtsi | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/dts/common/nordic/nrf54h20.dtsi b/dts/common/nordic/nrf54h20.dtsi index 8da783386865bd..417eb4670ed85a 100644 --- a/dts/common/nordic/nrf54h20.dtsi +++ b/dts/common/nordic/nrf54h20.dtsi @@ -31,7 +31,7 @@ device_type = "cpu"; clocks = <&cpuapp_hsfll>; clock-frequency = ; - cpu-power-states = <&idle &s2ram>; + cpu-power-states = <&idle_cache_disabled &s2ram>; }; cpurad: cpu@3 { @@ -40,6 +40,7 @@ device_type = "cpu"; clocks = <&cpurad_hsfll>; clock-frequency = ; + cpu-power-states = <&idle_cache_disabled>; }; cpuppr: cpu@d { @@ -128,12 +129,14 @@ }; power-states { - idle: idle { + // substate-id = <0>; is reserved for "idle", cache powered on + // substate-id = <1>; is reserved for "idle-cache-retained" + idle_cache_disabled: idle_cache_disabled { compatible = "zephyr,power-state"; power-state-name = "suspend-to-idle"; + substate-id = <2>; min-residency-us = <100000>; }; - s2ram: s2ram { compatible = "zephyr,power-state"; power-state-name = "suspend-to-ram"; From a65320de4068b33cfb18b28ee2e67c2853e86490 Mon Sep 17 00:00:00 2001 From: Adam Kondraciuk Date: Tue, 12 Nov 2024 11:24:40 +0100 Subject: [PATCH 3/3] soc: nordic: nrf54h: disable IRQ before PM config IRQs must be disabled before starting any procedures to prepare for low-power states. Signed-off-by: Adam Kondraciuk --- soc/nordic/nrf54h/pm_s2ram.c | 3 --- soc/nordic/nrf54h/power.c | 4 ++++ 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/soc/nordic/nrf54h/pm_s2ram.c b/soc/nordic/nrf54h/pm_s2ram.c index 88529c4bb755b2..20c28e42df555a 100644 --- a/soc/nordic/nrf54h/pm_s2ram.c +++ b/soc/nordic/nrf54h/pm_s2ram.c @@ -111,18 +111,15 @@ int soc_s2ram_suspend(pm_s2ram_system_off_fn_t system_off) { int ret; - __disable_irq(); nvic_suspend(&backup_data.nvic_context); mpu_suspend(&backup_data.mpu_context); ret = arch_pm_s2ram_suspend(system_off); if (ret < 0) { - __enable_irq(); return ret; } mpu_resume(&backup_data.mpu_context); nvic_resume(&backup_data.nvic_context); - __enable_irq(); return ret; } diff --git a/soc/nordic/nrf54h/power.c b/soc/nordic/nrf54h/power.c index 1a59320d80b48b..11c16b32e714da 100644 --- a/soc/nordic/nrf54h/power.c +++ b/soc/nordic/nrf54h/power.c @@ -188,15 +188,19 @@ static void s2ram_enter(void) void pm_state_set(enum pm_state state, uint8_t substate_id) { if (state == PM_STATE_SUSPEND_TO_IDLE) { + __disable_irq(); s2idle_enter(substate_id); /* Resume here. */ s2idle_exit(substate_id); + __enable_irq(); } #if defined(CONFIG_PM_S2RAM) else if (state == PM_STATE_SUSPEND_TO_RAM) { + __disable_irq(); s2ram_enter(); /* On resuming or error we return exactly *HERE* */ s2ram_exit(); + __enable_irq(); } #endif else {