Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 10 additions & 3 deletions boards/nordic/nrf54h20dk/nrf54h20dk_nrf54h20_cpuapp.dts
Original file line number Diff line number Diff line change
Expand Up @@ -330,14 +330,21 @@ zephyr_udc0: &usbhs {
status = "okay";
};

/* Trim this RAM block for making room on all run-time common S2RAM cpu context. */
/* Trim this RAM block for power management related features. */
&cpuapp_ram0 {
reg = <0x22000000 (DT_SIZE_K(32) - 32)>;
ranges = <0x0 0x22000000 (0x8000 - 0x20)>;
reg = <0x22000000 (DT_SIZE_K(32) - 256)>;
ranges = <0x0 0x22000000 (0x8000 - 0x100)>;
};

/ {
soc {
/* cache control functions - must be executed from local SRAM */
pm_ramfunc: cpuapp_s2ram@22007f00 {
compatible = "zephyr,memory-region", "mmio-sram";
reg = <0x22007f00 192>;
zephyr,memory-region = "PMLocalRamfunc";
};

/* run-time common S2RAM cpu context RAM */
pm_s2ram: cpuapp_s2ram@22007fe0 {
compatible = "zephyr,memory-region", "mmio-sram";
Expand Down
17 changes: 17 additions & 0 deletions boards/nordic/nrf54h20dk/nrf54h20dk_nrf54h20_cpurad.dts
Original file line number Diff line number Diff line change
Expand Up @@ -116,3 +116,20 @@ slot1_partition: &cpurad_slot1_partition {
zephyr_udc0: &usbhs {
status = "disabled";
};

/* Trim this RAM block for power management related features. */
&cpurad_ram0 {
reg = <0x23000000 (DT_SIZE_K(192) - 192)>;
ranges = <0x0 0x23000000 (0x30000 - 0xC0)>;
};

/ {
soc {
/* cache control functions - must be executed from RAM */
pm_ramfunc: cpurad_s2ram@2302ff40 {
compatible = "zephyr,memory-region", "mmio-sram";
reg = <0x2302ff80 192>;
zephyr,memory-region = "PMLocalRamfunc";
};
};
};
12 changes: 9 additions & 3 deletions dts/vendor/nordic/nrf54h20.dtsi
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@
device_type = "cpu";
clocks = <&cpuapp_hsfll>;
clock-frequency = <DT_FREQ_M(320)>;
cpu-power-states = <&idle_cache_disabled &s2ram>;
cpu-power-states = <&idle_cache_retained &idle_cache_disabled &s2ram>;
};

cpurad: cpu@3 {
Expand All @@ -40,7 +40,7 @@
device_type = "cpu";
clocks = <&cpurad_hsfll>;
clock-frequency = <DT_FREQ_M(256)>;
cpu-power-states = <&idle_cache_disabled>;
cpu-power-states = <&idle_cache_retained &idle_cache_disabled>;
};

cpuppr: cpu@d {
Expand Down Expand Up @@ -130,7 +130,13 @@

power-states {
// substate-id = <0>; is reserved for "idle", cache powered on
// substate-id = <1>; is reserved for "idle-cache-retained"
idle_cache_retained: idle_cache_retained {
compatible = "zephyr,power-state";
power-state-name = "suspend-to-idle";
substate-id = <1>;
min-residency-us = <700>;
exit-latency-us = <5>;
};
idle_cache_disabled: idle_cache_disabled {
compatible = "zephyr,power-state";
power-state-name = "suspend-to-idle";
Expand Down
5 changes: 5 additions & 0 deletions soc/nordic/nrf54h/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,11 @@ if(CONFIG_ARM)
zephyr_library_sources(soc.c)
if(CONFIG_PM OR CONFIG_POWEROFF)
zephyr_library_sources(power.c)
zephyr_code_relocate(
FILES power.c
FILTER ".*\\.cache_retain_and_sleep"
LOCATION PMLocalRamfunc_TEXT
)
endif()
endif()

Expand Down
3 changes: 3 additions & 0 deletions soc/nordic/nrf54h/Kconfig.defconfig.nrf54h20_cpuapp
Original file line number Diff line number Diff line change
Expand Up @@ -14,4 +14,7 @@ config SHELL_BACKEND_SERIAL
config POWER_DOMAIN
default y

config CODE_DATA_RELOCATION
default y if PM || POWEROFF

endif # SOC_NRF54H20_CPUAPP
3 changes: 3 additions & 0 deletions soc/nordic/nrf54h/Kconfig.defconfig.nrf54h20_cpurad
Original file line number Diff line number Diff line change
Expand Up @@ -14,4 +14,7 @@ config PM
config POWER_DOMAIN
default y

config CODE_DATA_RELOCATION
default y if PM || POWEROFF

endif # SOC_NRF54H20_CPURAD
50 changes: 39 additions & 11 deletions soc/nordic/nrf54h/power.c
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
#include <zephyr/arch/common/pm_s2ram.h>
#include <hal/nrf_resetinfo.h>
#include <hal/nrf_memconf.h>
#include <hal/nrf_cache.h>
#include <zephyr/cache.h>
#include <power.h>
#include <soc_lrcconf.h>
Expand Down Expand Up @@ -87,18 +88,43 @@ void nrf_poweroff(void)
CODE_UNREACHABLE;
}

static void s2idle_enter(uint8_t substate_id)
static __attribute__((__used__, noinline)) void cache_retain_and_sleep(void)
{
nrf_cache_task_trigger(NRF_DCACHE, NRF_CACHE_TASK_SAVE);
nrf_cache_task_trigger(NRF_ICACHE, NRF_CACHE_TASK_SAVE);
while (nrf_cache_busy_check(NRF_DCACHE) ||
nrf_cache_busy_check(NRF_ICACHE)) {

}

__set_BASEPRI(0);
__ISB();
__DSB();
__WFI();

nrf_cache_task_trigger(NRF_ICACHE, NRF_CACHE_TASK_RESTORE);
nrf_cache_task_trigger(NRF_DCACHE, NRF_CACHE_TASK_RESTORE);
while (nrf_cache_busy_check(NRF_DCACHE) ||
nrf_cache_busy_check(NRF_ICACHE)) {

}
}

void s2idle_enter(uint8_t substate_id)
{
#if !defined(CONFIG_SOC_NRF54H20_CPURAD)
soc_lrcconf_poweron_request(&soc_node, NRF_LRCCONF_POWER_MAIN);
#endif
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 1: /* Substate for idle with cache retained. */
soc_lrcconf_poweron_release(&soc_node, NRF_LRCCONF_POWER_DOMAIN_0);
nrf_soc_memconf_retain_set(true);
cache_retain_and_sleep();
return;
case 2: /* Substate for idle with cache disabled. */
#if !defined(CONFIG_SOC_NRF54H20_CPURAD)
soc_lrcconf_poweron_request(&soc_node, NRF_LRCCONF_POWER_MAIN);
#endif
common_suspend();
break;
default: /* Unknown substate. */
Expand All @@ -117,17 +143,19 @@ static void s2idle_exit(uint8_t 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. */
case 1: /* Substate for idle with cache retained. */
nrf_soc_memconf_retain_set(false);
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);
#endif
break;
default: /* Unknown substate. */
return;
}
common_resume();
#if !defined(CONFIG_SOC_NRF54H20_CPURAD)
soc_lrcconf_poweron_release(&soc_node, NRF_LRCCONF_POWER_MAIN);
#endif
}

#if defined(CONFIG_PM_S2RAM)
Expand Down
42 changes: 23 additions & 19 deletions soc/nordic/nrf54h/soc.c
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,26 @@ sys_snode_t soc_node;
ADDRESS_DOMAIN_Msk | \
ADDRESS_BUS_Msk)))

void nrf_soc_memconf_retain_set(bool enable)
{
uint32_t ret_mask = BIT(RAMBLOCK_RET_BIT_ICACHE) | BIT(RAMBLOCK_RET_BIT_DCACHE);

nrf_memconf_ramblock_ret_mask_enable_set(NRF_MEMCONF, 0, ret_mask, enable);
nrf_memconf_ramblock_ret_mask_enable_set(NRF_MEMCONF, 1, ret_mask, enable);

#if defined(RAMBLOCK_RET2_MASK)
ret_mask = 0;
#if defined(RAMBLOCK_RET2_BIT_ICACHE)
ret_mask |= BIT(RAMBLOCK_RET2_BIT_ICACHE);
#endif
#if defined(RAMBLOCK_RET2_BIT_DCACHE)
ret_mask |= BIT(RAMBLOCK_RET2_BIT_DCACHE);
#endif
nrf_memconf_ramblock_ret2_mask_enable_set(NRF_MEMCONF, 0, ret_mask, enable);
nrf_memconf_ramblock_ret2_mask_enable_set(NRF_MEMCONF, 1, ret_mask, enable);
#endif /* defined(RAMBLOCK_RET2_MASK) */
}

static void power_domain_init(void)
{
/*
Expand All @@ -75,28 +95,12 @@ static void power_domain_init(void)

soc_lrcconf_poweron_request(&soc_node, NRF_LRCCONF_POWER_DOMAIN_0);
nrf_lrcconf_poweron_force_set(NRF_LRCCONF010, NRF_LRCCONF_POWER_MAIN, false);

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);
nrf_memconf_ramblock_ret_enable_set(NRF_MEMCONF, 1, RAMBLOCK_RET_BIT_DCACHE, false);
#if defined(RAMBLOCK_RET2_BIT_ICACHE)
nrf_memconf_ramblock_ret2_enable_set(NRF_MEMCONF, 0, RAMBLOCK_RET2_BIT_ICACHE, false);
nrf_memconf_ramblock_ret2_enable_set(NRF_MEMCONF, 1, RAMBLOCK_RET2_BIT_ICACHE, false);
#endif
#if defined(RAMBLOCK_RET2_BIT_DCACHE)
nrf_memconf_ramblock_ret2_enable_set(NRF_MEMCONF, 0, RAMBLOCK_RET2_BIT_DCACHE, false);
nrf_memconf_ramblock_ret2_enable_set(NRF_MEMCONF, 1, RAMBLOCK_RET2_BIT_DCACHE, false);
#endif
nrf_soc_memconf_retain_set(false);
nrf_memconf_ramblock_ret_mask_enable_set(NRF_MEMCONF, 0, RAMBLOCK_RET_MASK, true);
nrf_memconf_ramblock_ret_mask_enable_set(NRF_MEMCONF, 1, RAMBLOCK_RET_MASK, true);
#if defined(RAMBLOCK_RET2_MASK)
/*
* TODO: Use nrf_memconf_ramblock_ret2_mask_enable_set() function
* when will be provided by HAL.
*/
NRF_MEMCONF->POWER[0].RET2 = RAMBLOCK_RET2_MASK;
NRF_MEMCONF->POWER[1].RET2 = RAMBLOCK_RET2_MASK;
nrf_memconf_ramblock_ret2_mask_enable_set(NRF_MEMCONF, 0, RAMBLOCK_RET2_MASK, true);
nrf_memconf_ramblock_ret2_mask_enable_set(NRF_MEMCONF, 1, RAMBLOCK_RET2_MASK, true);
#endif
}

Expand Down
7 changes: 7 additions & 0 deletions soc/nordic/nrf54h/soc.h
Original file line number Diff line number Diff line change
Expand Up @@ -36,4 +36,11 @@
#define RAMBLOCK_RET2_BIT_DCACHE MEMCONF_POWER_RET2_MEM7_Pos
#endif

/**
* @brief Enable or disable the retention for cache RAM blocks.
*
* @param enable True if the retention is to be enabled, false otherwise.
*/
void nrf_soc_memconf_retain_set(bool enable);

#endif /* SOC_ARM_NORDIC_NRF_NRF54H_SOC_H_ */