From b06dc8bc2c6ad5d68a9852017cb9e5678c3b88e5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Krzysztof=20Chru=C5=9Bci=C5=84ski?= Date: Mon, 7 Apr 2025 15:13:19 +0200 Subject: [PATCH 1/4] [nrf fromtree] soc: nordic: nrf54h: power: Enable cache as early as possible MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add nrf_cache_power_up and nrf_cache_power_down functions. In case of s2ram power up cache as early as possible, before restoring ARM core registers. It improves restore time from 180 us to 33 us. As a minor optimization nrf_memconf_ramblock_control_mask_enable_set is used which allows to control ram blocks for icache and dcache in a single register write. Signed-off-by: Krzysztof Chruściński (cherry picked from commit a36b154fd187e9d548d81bdefdfcdec296890a92) (cherry picked from commit da14f332693c9153dc573dba0a49012071cdc50c) --- soc/nordic/nrf54h/pm_s2ram.c | 3 ++ soc/nordic/nrf54h/power.c | 61 +++++++++++++++++++++--------------- soc/nordic/nrf54h/power.h | 5 +++ 3 files changed, 43 insertions(+), 26 deletions(-) diff --git a/soc/nordic/nrf54h/pm_s2ram.c b/soc/nordic/nrf54h/pm_s2ram.c index c339039045e..c6ed87cbc3e 100644 --- a/soc/nordic/nrf54h/pm_s2ram.c +++ b/soc/nordic/nrf54h/pm_s2ram.c @@ -9,6 +9,7 @@ #include #include #include "pm_s2ram.h" +#include "power.h" #include @@ -170,6 +171,8 @@ int soc_s2ram_suspend(pm_s2ram_system_off_fn_t system_off) return ret; } + nrf_power_up_cache(); + mpu_resume(&backup_data.mpu_context); nvic_resume(&backup_data.nvic_context); scb_resume(&backup_data.scb_context); diff --git a/soc/nordic/nrf54h/power.c b/soc/nordic/nrf54h/power.c index a3b39a4c5fe..97f01c5b8dc 100644 --- a/soc/nordic/nrf54h/power.c +++ b/soc/nordic/nrf54h/power.c @@ -18,42 +18,50 @@ extern sys_snode_t soc_node; -static void common_suspend(void) +static void nrf_power_down_cache(void) { - 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); - } + static const uint32_t msk = + (IS_ENABLED(CONFIG_DCACHE) ? BIT(RAMBLOCK_CONTROL_BIT_DCACHE) : 0) | + (IS_ENABLED(CONFIG_ICACHE) ? BIT(RAMBLOCK_CONTROL_BIT_ICACHE) : 0); - if (IS_ENABLED(CONFIG_ICACHE)) { - /* Disable and power down ICACHE */ - sys_cache_instr_disable(); - nrf_memconf_ramblock_control_enable_set(NRF_MEMCONF, RAMBLOCK_POWER_ID, - RAMBLOCK_CONTROL_BIT_ICACHE, false); + if (msk == 0) { + return; } - soc_lrcconf_poweron_release(&soc_node, NRF_LRCCONF_POWER_DOMAIN_0); + /* Functions are non-empty only if cache is enabled. + * Data cache disabling include flushing. + */ + sys_cache_data_disable(); + sys_cache_instr_disable(); + nrf_memconf_ramblock_control_mask_enable_set(NRF_MEMCONF, RAMBLOCK_POWER_ID, msk, false); } -static void common_resume(void) +void nrf_power_up_cache(void) { - 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(); - } + static const uint32_t msk = + (IS_ENABLED(CONFIG_DCACHE) ? BIT(RAMBLOCK_CONTROL_BIT_DCACHE) : 0) | + (IS_ENABLED(CONFIG_ICACHE) ? BIT(RAMBLOCK_CONTROL_BIT_ICACHE) : 0); - 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(); + if (msk == 0) { + return; } + nrf_memconf_ramblock_control_mask_enable_set(NRF_MEMCONF, RAMBLOCK_POWER_ID, msk, true); + sys_cache_instr_enable(); + sys_cache_data_enable(); +} + +static void common_suspend(void) +{ + soc_lrcconf_poweron_release(&soc_node, NRF_LRCCONF_POWER_DOMAIN_0); + nrf_power_down_cache(); +} + +static void common_resume(void) +{ + /* Common part does not include cache enabling. In case of s2ram it is done + * as early as possible to speed up the process. + */ soc_lrcconf_poweron_request(&soc_node, NRF_LRCCONF_POWER_DOMAIN_0); } @@ -112,6 +120,7 @@ static void s2idle_exit(uint8_t substate_id) case 1: /* Substate for idle with cache retained - not implemented yet. */ break; case 2: /* Substate for idle with cache disabled. */ + nrf_power_up_cache(); common_resume(); #if !defined(CONFIG_SOC_NRF54H20_CPURAD) soc_lrcconf_poweron_release(&soc_node, NRF_LRCCONF_POWER_MAIN); diff --git a/soc/nordic/nrf54h/power.h b/soc/nordic/nrf54h/power.h index 021c20ec4dc..87489574e72 100644 --- a/soc/nordic/nrf54h/power.h +++ b/soc/nordic/nrf54h/power.h @@ -17,4 +17,9 @@ */ void nrf_poweroff(void); +/** + * @brief Power up and enable instruction and data cache. + */ +void nrf_power_up_cache(void); + #endif /* _ZEPHYR_SOC_ARM_NORDIC_NRF_POWER_H_ */ From 04a4f3e453f8e6d9c2a92943761803e58573fe3e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Krzysztof=20Chru=C5=9Bci=C5=84ski?= Date: Mon, 7 Apr 2025 14:43:04 +0200 Subject: [PATCH 2/4] [nrf fromtree] dts: common: nordic: nrf54h20: Update exit-latency-us timing MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Update exit-latency-us with newly measured values. Measurement is taking into account additional timing compared to wakeup from WFI. Signed-off-by: Krzysztof Chruściński (cherry picked from commit a4a613036cb5a4701645137757a734dcc15aef49) (cherry picked from commit d2534ea357d7371c43e8cc021e2418356457bda1) --- dts/common/nordic/nrf54h20.dtsi | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/dts/common/nordic/nrf54h20.dtsi b/dts/common/nordic/nrf54h20.dtsi index 7c06ba441a3..7fbfa94722d 100644 --- a/dts/common/nordic/nrf54h20.dtsi +++ b/dts/common/nordic/nrf54h20.dtsi @@ -137,13 +137,13 @@ power-state-name = "suspend-to-idle"; substate-id = <2>; min-residency-us = <1000>; - exit-latency-us = <30>; + exit-latency-us = <7>; }; s2ram: s2ram { compatible = "zephyr,power-state"; power-state-name = "suspend-to-ram"; min-residency-us = <2000>; - exit-latency-us = <260>; + exit-latency-us = <33>; }; }; }; From d7384b8057ff7867a8c270c2fe512329c9d1e8ff Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Krzysztof=20Chru=C5=9Bci=C5=84ski?= Date: Wed, 16 Apr 2025 13:12:23 +0200 Subject: [PATCH 3/4] [nrf fromlist] soc: nordic: nrf54h: Fix s2ram MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Cache was not enabled when s2ram did not completed which lead to system malfunction. Always power up cache when returning from s2ram function. Upstream PR #: 88709 Signed-off-by: Krzysztof Chruściński --- soc/nordic/nrf54h/pm_s2ram.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/soc/nordic/nrf54h/pm_s2ram.c b/soc/nordic/nrf54h/pm_s2ram.c index c6ed87cbc3e..1ec5da4aa19 100644 --- a/soc/nordic/nrf54h/pm_s2ram.c +++ b/soc/nordic/nrf54h/pm_s2ram.c @@ -167,12 +167,12 @@ int soc_s2ram_suspend(pm_s2ram_system_off_fn_t system_off) nvic_suspend(&backup_data.nvic_context); mpu_suspend(&backup_data.mpu_context); ret = arch_pm_s2ram_suspend(system_off); + /* Cache is powered down so power up is needed even if s2ram failed. */ + nrf_power_up_cache(); if (ret < 0) { return ret; } - nrf_power_up_cache(); - mpu_resume(&backup_data.mpu_context); nvic_resume(&backup_data.nvic_context); scb_resume(&backup_data.scb_context); From fecfe6f9a0aec8f210d925934eac9d6289718d1a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Krzysztof=20Chru=C5=9Bci=C5=84ski?= Date: Thu, 10 Apr 2025 12:38:29 +0200 Subject: [PATCH 4/4] [nrf fromtree] drivers: spi: nrfx_spis: Fix spis120 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ISR safe runtime PM can only be used for all instances except for spis120 which requires standard runtime PM. Added compilation guard against using CONFIG_PM_DEVICE_SYSTEM_MANAGED with spis120. Signed-off-by: Krzysztof Chruściński (cherry picked from commit 8d6ab28ff772a1cb10b53b1db1902d9716edaa13) --- drivers/spi/spi_nrfx_spis.c | 19 ++++++++++++++++--- 1 file changed, 16 insertions(+), 3 deletions(-) diff --git a/drivers/spi/spi_nrfx_spis.c b/drivers/spi/spi_nrfx_spis.c index 049154f791d..1526109865c 100644 --- a/drivers/spi/spi_nrfx_spis.c +++ b/drivers/spi/spi_nrfx_spis.c @@ -24,6 +24,18 @@ LOG_MODULE_REGISTER(spi_nrfx_spis, CONFIG_SPI_LOG_LEVEL); #include #endif +#define SPIS_IS_FAST(idx) IS_EQ(idx, 120) + +#define NRFX_SPIS_IS_FAST(unused, prefix, id, _) SPIS_IS_FAST(prefix##id) + +#if NRFX_FOREACH_ENABLED(SPIS, NRFX_SPIS_IS_FAST, (+), (0), _) +/* If fast instances are used then system managed device PM cannot be used because + * it may call PM actions from locked context and fast SPIM PM actions can only be + * called from a thread context. + */ +BUILD_ASSERT(!IS_ENABLED(CONFIG_PM_DEVICE_SYSTEM_MANAGED)); +#endif + struct spi_nrfx_data { struct spi_context ctx; const struct device *dev; @@ -335,7 +347,7 @@ static void event_handler(const nrfx_spis_evt_t *p_event, void *p_context) spi_context_complete(&dev_data->ctx, dev_data->dev, p_event->rx_amount); - pm_device_runtime_put(dev_data->dev); + pm_device_runtime_put_async(dev_data->dev, K_NO_WAIT); } } @@ -457,7 +469,7 @@ static int spi_nrfx_init(const struct device *dev) * - Name-based HAL IRQ handlers, e.g. nrfx_spis_0_irq_handler */ -#define SPIS_NODE(idx) COND_CODE_1(IS_EQ(idx, 120), (spis##idx), (spi##idx)) +#define SPIS_NODE(idx) COND_CODE_1(SPIS_IS_FAST(idx), (spis##idx), (spi##idx)) #define SPIS(idx) DT_NODELABEL(SPIS_NODE(idx)) @@ -502,7 +514,8 @@ static int spi_nrfx_init(const struct device *dev) BUILD_ASSERT(!DT_NODE_HAS_PROP(SPIS(idx), wake_gpios) || \ !(DT_GPIO_FLAGS(SPIS(idx), wake_gpios) & GPIO_ACTIVE_LOW),\ "WAKE line must be configured as active high"); \ - PM_DEVICE_DT_DEFINE(SPIS(idx), spi_nrfx_pm_action, 1); \ + PM_DEVICE_DT_DEFINE(SPIS(idx), spi_nrfx_pm_action, \ + COND_CODE_1(SPIS_IS_FAST(idx), (0), (PM_DEVICE_ISR_SAFE))); \ SPI_DEVICE_DT_DEFINE(SPIS(idx), \ spi_nrfx_init, \ PM_DEVICE_DT_GET(SPIS(idx)), \