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)), \ 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>; }; }; }; diff --git a/soc/nordic/nrf54h/pm_s2ram.c b/soc/nordic/nrf54h/pm_s2ram.c index c339039045e..1ec5da4aa19 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 @@ -166,6 +167,8 @@ 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; } 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_ */