Skip to content

Commit aeff82d

Browse files
[nrf noup] soc: arm: nrf54h: poweroff: Add support for s2ram
Add functions for local domain suspend to RAM. Add matching resume procedure. Add pm_s2ram function for determining source of reset. Signed-off-by: Adam Kondraciuk <[email protected]>
1 parent 2d40098 commit aeff82d

File tree

6 files changed

+193
-3
lines changed

6 files changed

+193
-3
lines changed

soc/nordic/common/poweroff.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
#include <zephyr/sys/poweroff.h>
77
#include <zephyr/toolchain.h>
88

9+
#if !defined(CONFIG_SOC_SERIES_NRF54HX)
910
#if defined(CONFIG_SOC_SERIES_NRF51X) || defined(CONFIG_SOC_SERIES_NRF52X)
1011
#include <hal/nrf_power.h>
1112
#else
@@ -22,3 +23,4 @@ void z_sys_poweroff(void)
2223

2324
CODE_UNREACHABLE;
2425
}
26+
#endif /* !defined(CONFIG_SOC_SERIES_NRF54HX) */

soc/nordic/nrf54h/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
if(CONFIG_ARM)
55
zephyr_include_directories(.)
66
zephyr_library_sources(soc.c)
7+
zephyr_sources_ifdef(CONFIG_POWEROFF poweroff.c)
78
endif()
89

910
# Ensure that image size aligns with 16 bytes so that MRAMC finalizes all writes

soc/nordic/nrf54h/Kconfig

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,8 @@ config SOC_NRF54H20_CPUAPP
1717
select CPU_HAS_ICACHE
1818
select CPU_HAS_FPU
1919
select HAS_SEGGER_RTT if ZEPHYR_SEGGER_MODULE
20+
select HAS_PM
21+
select HAS_POWEROFF
2022

2123
config SOC_NRF54H20_CPURAD
2224
select ARM
@@ -28,6 +30,8 @@ config SOC_NRF54H20_CPURAD
2830
select CPU_HAS_ICACHE
2931
select CPU_HAS_FPU
3032
select HAS_SEGGER_RTT if ZEPHYR_SEGGER_MODULE
33+
select HAS_PM
34+
select HAS_POWEROFF
3135

3236
config SOC_NRF54H20_CPUPPR
3337
depends on RISCV_CORE_NORDIC_VPR

soc/nordic/nrf54h/poweroff.c

Lines changed: 182 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,182 @@
1+
/*
2+
* Copyright (c) 2024 Nordic Semiconductor ASA
3+
* SPDX-License-Identifier: Apache-2.0
4+
*/
5+
6+
#include <zephyr/kernel.h>
7+
#include <zephyr/sys/poweroff.h>
8+
#include <zephyr/toolchain.h>
9+
#include <zephyr/pm/policy.h>
10+
#include <zephyr/arch/common/pm_s2ram.h>
11+
#include <hal/nrf_resetinfo.h>
12+
#include <hal/nrf_lrcconf.h>
13+
#include <hal/nrf_memconf.h>
14+
#include <zephyr/cache.h>
15+
16+
#if defined(NRF_APPLICATION)
17+
#define RAMBLOCK_CONTROL_BIT_ICACHE 1
18+
#define RAMBLOCK_CONTROL_BIT_DCACHE 2
19+
#define RAMBLOCK_POWER_ID 0
20+
#define RAMBLOCK_CONTROL_OFF 0
21+
#elif defined(NRF_RADIOCORE)
22+
#define RAMBLOCK_CONTROL_BIT_ICACHE 2
23+
#define RAMBLOCK_CONTROL_BIT_DCACHE 3
24+
#define RAMBLOCK_POWER_ID 0
25+
#define RAMBLOCK_CONTROL_OFF 0
26+
#else
27+
#error "Unsupported domain."
28+
#endif
29+
30+
static void suspend_common(void)
31+
{
32+
if (IS_ENABLED(CONFIG_DCACHE)) {
33+
/* Flush, disable and power down DCACHE */
34+
sys_cache_data_flush_all();
35+
sys_cache_data_disable();
36+
nrf_memconf_ramblock_control_enable_set(NRF_MEMCONF, RAMBLOCK_POWER_ID,
37+
RAMBLOCK_CONTROL_BIT_DCACHE, false);
38+
}
39+
40+
if (IS_ENABLED(CONFIG_ICACHE)) {
41+
/* Flush, disable and power down ICACHE */
42+
sys_cache_instr_disable();
43+
nrf_memconf_ramblock_control_enable_set(NRF_MEMCONF, RAMBLOCK_POWER_ID,
44+
RAMBLOCK_CONTROL_BIT_ICACHE, false);
45+
}
46+
47+
/* Disable retention */
48+
nrf_lrcconf_retain_set(NRF_LRCCONF010, NRF_LRCCONF_POWER_DOMAIN_0, false);
49+
nrf_lrcconf_poweron_force_set(NRF_LRCCONF010, NRF_LRCCONF_POWER_DOMAIN_0, false);
50+
51+
k_cpu_idle();
52+
}
53+
54+
void z_sys_poweroff(void)
55+
{
56+
nrf_resetinfo_resetreas_local_set(NRF_RESETINFO, 0);
57+
nrf_resetinfo_restore_valid_set(NRF_RESETINFO, false);
58+
59+
nrf_lrcconf_retain_set(NRF_LRCCONF010, NRF_LRCCONF_POWER_MAIN, false);
60+
nrf_lrcconf_poweron_force_set(NRF_LRCCONF010, NRF_LRCCONF_POWER_MAIN, false);
61+
62+
nrf_lrcconf_task_trigger(NRF_LRCCONF010, NRF_LRCCONF_TASK_SYSTEMOFFREADY);
63+
64+
suspend_common();
65+
66+
CODE_UNREACHABLE;
67+
}
68+
69+
__weak void z_pm_soc_resume(void)
70+
{
71+
}
72+
73+
/* Resume domain after local suspend to RAM. */
74+
void z_pm_sys_resume(void)
75+
{
76+
if (IS_ENABLED(CONFIG_ICACHE)) {
77+
/* Power up and re-enable ICACHE */
78+
nrf_memconf_ramblock_control_enable_set(NRF_MEMCONF, RAMBLOCK_POWER_ID,
79+
RAMBLOCK_CONTROL_BIT_ICACHE, true);
80+
sys_cache_instr_enable();
81+
}
82+
83+
if (IS_ENABLED(CONFIG_DCACHE)) {
84+
/* Power up and re-enable DCACHE */
85+
nrf_memconf_ramblock_control_enable_set(NRF_MEMCONF, RAMBLOCK_POWER_ID,
86+
RAMBLOCK_CONTROL_BIT_DCACHE, true);
87+
sys_cache_data_enable();
88+
}
89+
90+
/* Re-enable domain retention. */
91+
nrf_lrcconf_retain_set(NRF_LRCCONF010, NRF_LRCCONF_POWER_DOMAIN_0, true);
92+
nrf_lrcconf_poweron_force_set(NRF_LRCCONF010, NRF_LRCCONF_POWER_MAIN, true);
93+
nrf_lrcconf_poweron_force_set(NRF_LRCCONF010, NRF_LRCCONF_POWER_DOMAIN_0, true);
94+
95+
96+
z_pm_soc_resume();
97+
}
98+
99+
/* Function called during local domain suspend to RAM. */
100+
int z_pm_sys_suspend(void)
101+
{
102+
/* Set intormation which is used on domain wakeup to determine if resume from RAM shall
103+
* be performed.
104+
*/
105+
nrf_resetinfo_resetreas_local_set(NRF_RESETINFO,
106+
NRF_RESETINFO_RESETREAS_LOCAL_UNRETAINED_MASK);
107+
nrf_resetinfo_restore_valid_set(NRF_RESETINFO, true);
108+
nrf_lrcconf_poweron_force_set(NRF_LRCCONF010, NRF_LRCCONF_POWER_MAIN, false);
109+
110+
suspend_common();
111+
112+
/*
113+
* We might reach this point is k_cpu_idle returns (there is a pre sleep hook that
114+
* can abort sleeping.
115+
*/
116+
return -EBUSY;
117+
}
118+
119+
void pm_s2ram_mark_set(void)
120+
{
121+
/* empty */
122+
}
123+
124+
bool pm_s2ram_mark_check_and_clear(void)
125+
{
126+
bool unretained_wake;
127+
bool restore_valid;
128+
129+
unretained_wake = nrf_resetinfo_resetreas_local_get(NRF_RESETINFO) &
130+
NRF_RESETINFO_RESETREAS_LOCAL_UNRETAINED_MASK;
131+
nrf_resetinfo_resetreas_local_set(NRF_RESETINFO, 0);
132+
133+
restore_valid = nrf_resetinfo_restore_valid_check(NRF_RESETINFO);
134+
nrf_resetinfo_restore_valid_set(NRF_RESETINFO, false);
135+
136+
return (unretained_wake & restore_valid) ? true : false;
137+
}
138+
139+
#if CONFIG_PM
140+
141+
__weak bool z_pm_do_suspend(void)
142+
{
143+
return true;
144+
}
145+
146+
void do_suspend(void)
147+
{
148+
if (!z_pm_do_suspend()) {
149+
return;
150+
}
151+
152+
/*
153+
* Save the CPU context (including the return address),set the SRAM
154+
* marker and power off the system.
155+
*/
156+
(void)pm_s2ram_suspend(z_pm_sys_suspend);
157+
158+
/*
159+
* On resuming or error we return exactly *HERE*
160+
*/
161+
162+
z_pm_sys_resume();
163+
}
164+
165+
void pm_state_set(enum pm_state state, uint8_t substate_id)
166+
{
167+
if (state != PM_STATE_SUSPEND_TO_RAM) {
168+
return;
169+
}
170+
171+
do_suspend();
172+
}
173+
174+
void pm_state_exit_post_ops(enum pm_state state, uint8_t substate_id)
175+
{
176+
if (state != PM_STATE_SUSPEND_TO_RAM) {
177+
return;
178+
}
179+
180+
irq_unlock(0);
181+
}
182+
#endif

soc/nordic/nrf54h/soc.c

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -46,8 +46,9 @@ static void power_domain_init(void)
4646
* WFI the power domain will be correctly retained.
4747
*/
4848

49-
nrf_lrcconf_poweron_force_set(NRF_LRCCONF010, NRF_LRCCONF_POWER_MAIN, true);
50-
nrf_lrcconf_poweron_force_set(NRF_LRCCONF010, NRF_LRCCONF_POWER_DOMAIN_0, true);
49+
nrf_lrcconf_poweron_force_set(NRF_LRCCONF010, NRF_LRCCONF_POWER_MAIN,
50+
!IS_ENABLED(CONFIG_HALTIUM_CPURAD));
51+
nrf_lrcconf_poweron_force_set(NRF_LRCCONF010, NRF_LRCCONF_POWER_DOMAIN_0, false);
5152

5253
nrf_lrcconf_retain_set(NRF_LRCCONF010, NRF_LRCCONF_POWER_MAIN, true);
5354
nrf_lrcconf_retain_set(NRF_LRCCONF010, NRF_LRCCONF_POWER_DOMAIN_0, true);

subsys/pm/Kconfig

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@ config PM_S2RAM_CUSTOM_MARKING
4242
depends on PM_S2RAM
4343
help
4444
By default a magic word in RAM is used to mark entering suspend-to-RAM. Enabling
45-
this option allows custom implementation of functions which handles the marking.
45+
this option allows custom implementation of functions which handle the marking.
4646

4747
config PM_NEED_ALL_DEVICES_IDLE
4848
bool "System Low Power Mode Needs All Devices Idle"

0 commit comments

Comments
 (0)