blob: aa715c8bbb90d1df93c859a15df5570276dfaa5e [file] [log] [blame]
/*
* Copyright (c) 2022, Carlo Caione <ccaione@baylibre.com>
*
* SPDX-License-Identifier: Apache-2.0
*/
/**
* @file
* @brief ARM Cortex-M suspend-to-RAM code (S2RAM)
*/
#include <zephyr/toolchain.h>
#include <offsets_short.h>
#include <zephyr/arch/cpu.h>
#include <zephyr/arch/common/pm_s2ram.h>
#define MAGIC (0xDABBAD00)
_ASM_FILE_PROLOGUE
GDATA(_cpu_context)
GDATA(marker)
SECTION_FUNC(TEXT, arch_pm_s2ram_suspend)
/*
* Save the CPU context
*
* r0: address of the system_off function
*/
push {r4-r12, lr}
ldr r1, =_cpu_context
mrs r2, msp
str r2, [r1, #___cpu_context_t_msp_OFFSET]
mrs r2, msplim
str r2, [r1, #___cpu_context_t_msplim_OFFSET]
mrs r2, psp
str r2, [r1, #___cpu_context_t_psp_OFFSET]
mrs r2, psplim
str r2, [r1, #___cpu_context_t_psplim_OFFSET]
mrs r2, apsr
str r2, [r1, #___cpu_context_t_apsr_OFFSET]
mrs r2, ipsr
str r2, [r1, #___cpu_context_t_ipsr_OFFSET]
mrs r2, epsr
str r2, [r1, #___cpu_context_t_epsr_OFFSET]
mrs r2, primask
str r2, [r1, #___cpu_context_t_primask_OFFSET]
mrs r2, faultmask
str r2, [r1, #___cpu_context_t_faultmask_OFFSET]
mrs r2, basepri
str r2, [r1, #___cpu_context_t_basepri_OFFSET]
mrs r2, control
str r2, [r1, #___cpu_context_t_control_OFFSET]
/*
* Set the marker to MAGIC value
*/
ldr r1, =marker
ldr r2, =MAGIC
str r2, [r1]
/*
* Call the system_off function passed as parameter. This should never
* return.
*/
blx r0
/*
* The system_off function returns here only when the powering off was
* not successful (in r0 the return value).
*/
/*
* Reset the marker
*/
ldr r1, =marker
mov r2, #0x0
str r2, [r1]
pop {r4-r12, lr}
bx lr
GTEXT(arch_pm_s2ram_resume)
SECTION_FUNC(TEXT, arch_pm_s2ram_resume)
/*
* Check if the marker is set
*/
ldr r0, =marker
ldr r0, [r0]
ldr r1, =MAGIC
cmp r0, r1
beq resume
bx lr
resume:
/*
* Reset the marker
*/
ldr r0, =marker
mov r1, #0x0
str r1, [r0]
/*
* Restore the CPU context
*/
ldr r0, =_cpu_context
ldr r1, [r0, #___cpu_context_t_msp_OFFSET]
msr msp, r1
ldr r1, [r0, #___cpu_context_t_msplim_OFFSET]
msr msplim, r1
ldr r1, [r0, #___cpu_context_t_psp_OFFSET]
msr psp, r1
ldr r1, [r0, #___cpu_context_t_psplim_OFFSET]
msr psplim, r1
ldr r1, [r0, #___cpu_context_t_apsr_OFFSET]
msr apsr_nzcvq, r1
ldr r1, [r0, #___cpu_context_t_ipsr_OFFSET]
msr ipsr, r1
ldr r1, [r0, #___cpu_context_t_epsr_OFFSET]
msr epsr, r1
ldr r1, [r0, #___cpu_context_t_primask_OFFSET]
msr primask, r1
ldr r1, [r0, #___cpu_context_t_faultmask_OFFSET]
msr faultmask, r1
ldr r1, [r0, #___cpu_context_t_basepri_OFFSET]
msr basepri, r1
ldr r1, [r0, #___cpu_context_t_control_OFFSET]
msr control, r1
isb
pop {r4-r12, lr}
/*
* Set the return value and return
*/
mov r0, #0
bx lr