|
| 1 | +/* |
| 2 | + * Copyright (c) 2025 Nordic Semiconductor ASA |
| 3 | + * SPDX-License-Identifier: Apache-2.0 |
| 4 | + */ |
| 5 | + |
| 6 | +#include <stdbool.h> |
| 7 | +#include <zephyr/arch/common/pm_s2ram.h> |
| 8 | +#include <hal/nrf_resetinfo.h> |
| 9 | +#include "pm_s2ram.h" |
| 10 | +#include "power.h" |
| 11 | + |
| 12 | +#include <zephyr/devicetree.h> |
| 13 | +#include <zephyr/storage/flash_map.h> |
| 14 | + |
| 15 | +#include "bootutil/fault_injection_hardening.h" |
| 16 | + |
| 17 | +#if DT_NODE_EXISTS(DT_NODELABEL(mcuboot_s2ram)) &&\ |
| 18 | + DT_NODE_HAS_COMPAT(DT_NODELABEL(mcuboot_s2ram), zephyr_memory_region) |
| 19 | +/* Linker section name is given by `zephyr,memory-region` property of |
| 20 | + * `zephyr,memory-region` compatible DT node with nodelabel `mcuboot_s2ram`. |
| 21 | + */ |
| 22 | +__attribute__((section(DT_PROP(DT_NODELABEL(mcuboot_s2ram), zephyr_memory_region)))) |
| 23 | +volatile struct mcuboot_resume_s mcuboot_resume; |
| 24 | +#else |
| 25 | +#error "mcuboot resume support section not defined in dts" |
| 26 | +#endif |
| 27 | + |
| 28 | +#define FIXED_PARTITION_ADDR(node_label) \ |
| 29 | + (DT_REG_ADDR(DT_NODELABEL(node_label)) + \ |
| 30 | + COND_CODE_0(DT_FIXED_PARTITION_EXISTS(DT_NODELABEL(node_label)), (0), \ |
| 31 | + (DT_REG_ADDR(DT_GPARENT(DT_NODELABEL(node_label)))))) |
| 32 | + |
| 33 | + |
| 34 | +int soc_s2ram_suspend(pm_s2ram_system_off_fn_t system_off) |
| 35 | +{ |
| 36 | + (void)(system_off); |
| 37 | + return -1; |
| 38 | +} |
| 39 | + |
| 40 | +void pm_s2ram_mark_set(void) |
| 41 | +{ |
| 42 | + /* empty */ |
| 43 | +} |
| 44 | + |
| 45 | +struct arm_vector_table { |
| 46 | + uint32_t msp; |
| 47 | + uint32_t reset; |
| 48 | +}; |
| 49 | + |
| 50 | +/* This could be read from slot's image_header.ih_hdr_size, but immediate value |
| 51 | + * is much faster to reach |
| 52 | + */ |
| 53 | +#define APP_EXE_START_OFFSET 0x800 /* nRF54H20 */ |
| 54 | + |
| 55 | +bool pm_s2ram_mark_check_and_clear(void) |
| 56 | +{ |
| 57 | + uint32_t reset_reason = nrf_resetinfo_resetreas_local_get(NRF_RESETINFO); |
| 58 | + |
| 59 | + if (reset_reason != NRF_RESETINFO_RESETREAS_LOCAL_UNRETAINED_MASK) { |
| 60 | + /* Normal boot */ |
| 61 | + return false; |
| 62 | + } |
| 63 | + |
| 64 | + /* S2RAM resume expected, do doublecheck */ |
| 65 | + if (mcuboot_resume.magic == MCUBOOT_S2RAM_RESUME_MAGIC) { |
| 66 | + /* clear magic to avoid accidental reuse */ |
| 67 | + mcuboot_resume.magic = 0; |
| 68 | + } else { |
| 69 | + /* magic not valid, normal boot */ |
| 70 | + goto resume_failed; |
| 71 | + } |
| 72 | + |
| 73 | + /* s2ram boot */ |
| 74 | + struct arm_vector_table *vt; |
| 75 | + vt = (struct arm_vector_table *) |
| 76 | + (FIXED_PARTITION_ADDR(slot0_partition) + APP_EXE_START_OFFSET); |
| 77 | + |
| 78 | + /* Jump to application */ |
| 79 | + __asm__ volatile ( |
| 80 | + /* vt->reset -> r0 */ |
| 81 | + " mov r0, %0\n" |
| 82 | + /* vt->msp -> r1 */ |
| 83 | + " mov r1, %1\n" |
| 84 | + /* set stack pointer */ |
| 85 | + " msr msp, r1\n" |
| 86 | + /* jump to reset vector of an app */ |
| 87 | + " bx r0\n" |
| 88 | + : |
| 89 | + : "r" (vt->reset), "r" (vt->msp) |
| 90 | + : "r0", "r1", "memory" |
| 91 | + ); |
| 92 | + |
| 93 | +resume_failed: |
| 94 | + FIH_PANIC; |
| 95 | + |
| 96 | + return true; |
| 97 | +} |
0 commit comments