Skip to content

Commit c37e50e

Browse files
adamkondraciukkl-cruz
authored andcommitted
[nrf fromlist] soc: nordic: nrf54h: Implement idle with cache retained state
Add new idle state with cache retention enabled. Upstream PR #: 95474 Signed-off-by: Adam Kondraciuk <[email protected]>
1 parent 5408ed3 commit c37e50e

File tree

4 files changed

+78
-33
lines changed

4 files changed

+78
-33
lines changed

dts/vendor/nordic/nrf54h20.dtsi

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@
3232
device_type = "cpu";
3333
clocks = <&cpuapp_hsfll>;
3434
clock-frequency = <DT_FREQ_M(320)>;
35-
cpu-power-states = <&idle_cache_disabled &s2ram>;
35+
cpu-power-states = <&idle_cache_retained &idle_cache_disabled &s2ram>;
3636
};
3737

3838
cpurad: cpu@3 {
@@ -41,7 +41,7 @@
4141
device_type = "cpu";
4242
clocks = <&cpurad_hsfll>;
4343
clock-frequency = <DT_FREQ_M(256)>;
44-
cpu-power-states = <&idle_cache_disabled>;
44+
cpu-power-states = <&idle_cache_retained &idle_cache_disabled>;
4545
};
4646

4747
cpuppr: cpu@d {
@@ -131,7 +131,13 @@
131131

132132
power-states {
133133
// substate-id = <0>; is reserved for "idle", cache powered on
134-
// substate-id = <1>; is reserved for "idle-cache-retained"
134+
idle_cache_retained: idle_cache_retained {
135+
compatible = "zephyr,power-state";
136+
power-state-name = "suspend-to-idle";
137+
substate-id = <1>;
138+
min-residency-us = <700>;
139+
exit-latency-us = <5>;
140+
};
135141
idle_cache_disabled: idle_cache_disabled {
136142
compatible = "zephyr,power-state";
137143
power-state-name = "suspend-to-idle";

soc/nordic/nrf54h/power.c

Lines changed: 39 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
#include <zephyr/arch/common/pm_s2ram.h>
1111
#include <hal/nrf_resetinfo.h>
1212
#include <hal/nrf_memconf.h>
13+
#include <hal/nrf_cache.h>
1314
#include <zephyr/cache.h>
1415
#include <power.h>
1516
#include <soc_lrcconf.h>
@@ -87,18 +88,43 @@ void nrf_poweroff(void)
8788
CODE_UNREACHABLE;
8889
}
8990

90-
static void s2idle_enter(uint8_t substate_id)
91+
static __ramfunc void cache_retain_and_sleep(void)
9192
{
93+
nrf_cache_task_trigger(NRF_DCACHE, NRF_CACHE_TASK_SAVE);
94+
nrf_cache_task_trigger(NRF_ICACHE, NRF_CACHE_TASK_SAVE);
95+
while (nrf_cache_busy_check(NRF_DCACHE) ||
96+
nrf_cache_busy_check(NRF_ICACHE)) {
97+
98+
}
99+
100+
__set_BASEPRI(0);
101+
__ISB();
102+
__DSB();
103+
__WFI();
104+
105+
nrf_cache_task_trigger(NRF_ICACHE, NRF_CACHE_TASK_RESTORE);
106+
nrf_cache_task_trigger(NRF_DCACHE, NRF_CACHE_TASK_RESTORE);
107+
while (nrf_cache_busy_check(NRF_DCACHE) ||
108+
nrf_cache_busy_check(NRF_ICACHE)) {
109+
110+
}
111+
}
112+
113+
void s2idle_enter(uint8_t substate_id)
114+
{
115+
#if !defined(CONFIG_SOC_NRF54H20_CPURAD)
116+
soc_lrcconf_poweron_request(&soc_node, NRF_LRCCONF_POWER_MAIN);
117+
#endif
92118
switch (substate_id) {
93119
case 0:
94120
/* Substate for idle with cache powered on - not implemented yet. */
95121
break;
96-
case 1: /* Substate for idle with cache retained - not implemented yet. */
97-
break;
122+
case 1: /* Substate for idle with cache retained. */
123+
soc_lrcconf_poweron_release(&soc_node, NRF_LRCCONF_POWER_DOMAIN_0);
124+
nrf_soc_memconf_retain_set(true);
125+
cache_retain_and_sleep();
126+
return;
98127
case 2: /* Substate for idle with cache disabled. */
99-
#if !defined(CONFIG_SOC_NRF54H20_CPURAD)
100-
soc_lrcconf_poweron_request(&soc_node, NRF_LRCCONF_POWER_MAIN);
101-
#endif
102128
common_suspend();
103129
break;
104130
default: /* Unknown substate. */
@@ -117,17 +143,19 @@ static void s2idle_exit(uint8_t substate_id)
117143
case 0:
118144
/* Substate for idle with cache powered on - not implemented yet. */
119145
break;
120-
case 1: /* Substate for idle with cache retained - not implemented yet. */
146+
case 1: /* Substate for idle with cache retained. */
147+
nrf_soc_memconf_retain_set(false);
121148
break;
122149
case 2: /* Substate for idle with cache disabled. */
123150
nrf_power_up_cache();
124-
common_resume();
125-
#if !defined(CONFIG_SOC_NRF54H20_CPURAD)
126-
soc_lrcconf_poweron_release(&soc_node, NRF_LRCCONF_POWER_MAIN);
127-
#endif
151+
break;
128152
default: /* Unknown substate. */
129153
return;
130154
}
155+
common_resume();
156+
#if !defined(CONFIG_SOC_NRF54H20_CPURAD)
157+
soc_lrcconf_poweron_release(&soc_node, NRF_LRCCONF_POWER_MAIN);
158+
#endif
131159
}
132160

133161
#if defined(CONFIG_PM_S2RAM)

soc/nordic/nrf54h/soc.c

Lines changed: 23 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,26 @@ sys_snode_t soc_node;
6161
ADDRESS_DOMAIN_Msk | \
6262
ADDRESS_BUS_Msk)))
6363

64+
void nrf_soc_memconf_retain_set(bool enable)
65+
{
66+
uint32_t ret_mask = BIT(RAMBLOCK_RET_BIT_ICACHE) | BIT(RAMBLOCK_RET_BIT_DCACHE);
67+
68+
nrf_memconf_ramblock_ret_mask_enable_set(NRF_MEMCONF, 0, ret_mask, enable);
69+
nrf_memconf_ramblock_ret_mask_enable_set(NRF_MEMCONF, 1, ret_mask, enable);
70+
71+
#if defined(RAMBLOCK_RET2_MASK)
72+
ret_mask = 0;
73+
#if defined(RAMBLOCK_RET2_BIT_ICACHE)
74+
ret_mask |= BIT(RAMBLOCK_RET2_BIT_ICACHE);
75+
#endif
76+
#if defined(RAMBLOCK_RET2_BIT_DCACHE)
77+
ret_mask |= BIT(RAMBLOCK_RET2_BIT_DCACHE);
78+
#endif
79+
nrf_memconf_ramblock_ret2_mask_enable_set(NRF_MEMCONF, 0, ret_mask, enable);
80+
nrf_memconf_ramblock_ret2_mask_enable_set(NRF_MEMCONF, 1, ret_mask, enable);
81+
#endif /* defined(RAMBLOCK_RET2_MASK) */
82+
}
83+
6484
static void power_domain_init(void)
6585
{
6686
/*
@@ -76,28 +96,12 @@ static void power_domain_init(void)
7696

7797
soc_lrcconf_poweron_request(&soc_node, NRF_LRCCONF_POWER_DOMAIN_0);
7898
nrf_lrcconf_poweron_force_set(NRF_LRCCONF010, NRF_LRCCONF_POWER_MAIN, false);
79-
80-
nrf_memconf_ramblock_ret_enable_set(NRF_MEMCONF, 0, RAMBLOCK_RET_BIT_ICACHE, false);
81-
nrf_memconf_ramblock_ret_enable_set(NRF_MEMCONF, 0, RAMBLOCK_RET_BIT_DCACHE, false);
82-
nrf_memconf_ramblock_ret_enable_set(NRF_MEMCONF, 1, RAMBLOCK_RET_BIT_ICACHE, false);
83-
nrf_memconf_ramblock_ret_enable_set(NRF_MEMCONF, 1, RAMBLOCK_RET_BIT_DCACHE, false);
84-
#if defined(RAMBLOCK_RET2_BIT_ICACHE)
85-
nrf_memconf_ramblock_ret2_enable_set(NRF_MEMCONF, 0, RAMBLOCK_RET2_BIT_ICACHE, false);
86-
nrf_memconf_ramblock_ret2_enable_set(NRF_MEMCONF, 1, RAMBLOCK_RET2_BIT_ICACHE, false);
87-
#endif
88-
#if defined(RAMBLOCK_RET2_BIT_DCACHE)
89-
nrf_memconf_ramblock_ret2_enable_set(NRF_MEMCONF, 0, RAMBLOCK_RET2_BIT_DCACHE, false);
90-
nrf_memconf_ramblock_ret2_enable_set(NRF_MEMCONF, 1, RAMBLOCK_RET2_BIT_DCACHE, false);
91-
#endif
99+
nrf_soc_memconf_retain_set(false);
92100
nrf_memconf_ramblock_ret_mask_enable_set(NRF_MEMCONF, 0, RAMBLOCK_RET_MASK, true);
93101
nrf_memconf_ramblock_ret_mask_enable_set(NRF_MEMCONF, 1, RAMBLOCK_RET_MASK, true);
94102
#if defined(RAMBLOCK_RET2_MASK)
95-
/*
96-
* TODO: Use nrf_memconf_ramblock_ret2_mask_enable_set() function
97-
* when will be provided by HAL.
98-
*/
99-
NRF_MEMCONF->POWER[0].RET2 = RAMBLOCK_RET2_MASK;
100-
NRF_MEMCONF->POWER[1].RET2 = RAMBLOCK_RET2_MASK;
103+
nrf_memconf_ramblock_ret2_mask_enable_set(NRF_MEMCONF, 0, RAMBLOCK_RET2_MASK, true);
104+
nrf_memconf_ramblock_ret2_mask_enable_set(NRF_MEMCONF, 1, RAMBLOCK_RET2_MASK, true);
101105
#endif
102106
}
103107

soc/nordic/nrf54h/soc.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,4 +36,11 @@
3636
#define RAMBLOCK_RET2_BIT_DCACHE MEMCONF_POWER_RET2_MEM7_Pos
3737
#endif
3838

39+
/**
40+
* @brief Enable or disable the retention for cache RAM blocks.
41+
*
42+
* @param enable True if the retention is to be enabled, false otherwise.
43+
*/
44+
void nrf_soc_memconf_retain_set(bool enable);
45+
3946
#endif /* SOC_ARM_NORDIC_NRF_NRF54H_SOC_H_ */

0 commit comments

Comments
 (0)