Skip to content

Commit 274e538

Browse files
nordic-krchrlubos
authored andcommitted
[nrf fromtree] soc: nordic: common: vpr: Implement erratas in cpu idle
Use custom cpu_idle implementation for all VPRs and implement workarounds for erratas which impact sleeping Signed-off-by: Krzysztof Chruściński <krzysztof.chruscinski@nordicsemi.no> (cherry picked from commit b84d6f9)
1 parent f196909 commit 274e538

2 files changed

Lines changed: 44 additions & 8 deletions

File tree

soc/nordic/common/vpr/Kconfig

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,8 +11,8 @@ config RISCV_CORE_NORDIC_VPR
1111
select RISCV_HAS_CLIC
1212
select RISCV_SOC_CONTEXT_SAVE
1313
select HAS_FLASH_LOAD_OFFSET
14-
select ARCH_HAS_CUSTOM_CPU_IDLE if !SOC_SERIES_NRF54L
15-
select ARCH_HAS_CUSTOM_CPU_ATOMIC_IDLE if !SOC_SERIES_NRF54L
14+
select ARCH_HAS_CUSTOM_CPU_IDLE
15+
select ARCH_HAS_CUSTOM_CPU_ATOMIC_IDLE
1616
select INCLUDE_RESET_VECTOR
1717
imply XIP
1818
help

soc/nordic/common/vpr/soc_idle.c

Lines changed: 42 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,19 @@
66
#include <zephyr/irq.h>
77
#include <zephyr/sys/barrier.h>
88
#include <zephyr/tracing/tracing.h>
9+
#include <nrfx.h>
10+
11+
/* Optionally apply errata workaround for waking up from hibernation */
12+
static ALWAYS_INLINE void hibernate_dummy_write(void)
13+
{
14+
if (!IS_ENABLED(CONFIG_NORDIC_VPR_HIBERNATE)) {
15+
return;
16+
}
17+
18+
if (NRF_ERRATA_DYNAMIC_CHECK(54H, 111) || NRF_ERRATA_DYNAMIC_CHECK(54L, 18)) {
19+
*(volatile int *)0x5004C804 = 1;
20+
}
21+
}
922

1023
/*
1124
* Due to a HW issue, VPR requires MSTATUS.MIE to be enabled when entering sleep.
@@ -16,23 +29,46 @@ void arch_cpu_idle(void)
1629
#if defined(CONFIG_TRACING)
1730
sys_trace_idle();
1831
#endif
19-
barrier_dsync_fence_full();
20-
irq_unlock(MSTATUS_IEN);
32+
33+
if (NRF_ERRATA_DYNAMIC_CHECK(54H, 93)) {
34+
barrier_dsync_fence_full();
35+
irq_unlock(MSTATUS_IEN);
36+
}
37+
2138
__asm__ volatile("wfi");
39+
hibernate_dummy_write();
40+
if (!NRF_ERRATA_DYNAMIC_CHECK(54H, 93)) {
41+
#if defined(CONFIG_TRACING)
42+
/* Makes sense only if sleeping with interrupts locked. */
43+
sys_trace_idle_exit();
44+
#endif
45+
irq_unlock(MSTATUS_IEN);
46+
}
2247
}
2348

2449
void arch_cpu_atomic_idle(unsigned int key)
2550
{
2651
#if defined(CONFIG_TRACING)
2752
sys_trace_idle();
2853
#endif
29-
barrier_dsync_fence_full();
30-
irq_unlock(MSTATUS_IEN);
54+
if (NRF_ERRATA_DYNAMIC_CHECK(54H, 93)) {
55+
barrier_dsync_fence_full();
56+
irq_unlock(MSTATUS_IEN);
57+
}
3158
__asm__ volatile("wfi");
59+
hibernate_dummy_write();
3260

33-
/* Disable interrupts if needed. */
34-
__asm__ volatile ("csrc mstatus, %0"
61+
if (NRF_ERRATA_DYNAMIC_CHECK(54H, 93)) {
62+
/* Disable interrupts if needed. */
63+
__asm__ volatile ("csrc mstatus, %0"
3564
:
3665
: "r" (~key & MSTATUS_IEN)
3766
: "memory");
67+
} else {
68+
#if defined(CONFIG_TRACING)
69+
/* Makes sense only if sleeping with interrupts locked. */
70+
sys_trace_idle_exit();
71+
#endif
72+
irq_unlock(key);
73+
}
3874
}

0 commit comments

Comments
 (0)