1/* 2 * Copyright (c) 2023 Renesas Electronics Corporation 3 * 4 * SPDX-License-Identifier: Apache-2.0 5 */ 6 7#if __ZEPHYR__ 8 9#define RESETHANDLER __start 10#define RAM_TEXT_SECTION .ramfunc 11 12#if defined(CONFIG_FPU) 13#define USE_FPU 1 14#else 15#define USE_FPU 0 16#endif 17/* No MTB support for Zephyr */ 18#define USE_MTB 0 19 20#elif defined(MYNEWT) 21 #include <syscfg/syscfg.h> 22#define RESETHANDLER ResetHandler 23#define RAM_TEXT_SECTION .text_ram 24#define USE_FPU MYNEWT_VAL(HARDFLOAT) 25#define USE_MTB 1 26#endif 27 28 .syntax unified 29 .section .bss 30 .global da1469x_sleep_context 31 .type da1469x_sleep_context, %object 32 .align 4 33da1469x_sleep_context: 34.saved_primask: 35 .space 4 /* PRIMASK */ 36.saved_msp: 37 .space 4 /* MSP */ 38.saved_psp: 39 .space 4 /* PSP */ 40.saved_control: 41 .space 4 /* CONTROL */ 42.saved_regs: 43 .space 40 /* R4-R12, LR */ 44.saved_nvic: 45 .space 8 /* ISER[0..1] */ 46 .space 44 /* IPR[0..43] */ 47.saved_scb: 48 .space 28 /* SCR, CCR, SHPR[0..11], CPACR */ 49#if defined(FPU) 50.saved_fpu: 51 .space 8 /* FPCCR, FPDSCR */ 52#endif 53 54 .equ CLK_AMBA_REG, 0x50000000 55 .equ RESET_STAT_REG, 0x500000BC 56 .equ NVIC_BASE, 0xE000E100 57 .equ NVIC_IPR_OFFSET, 0x300 58 .equ SCB_BASE, 0xE000ED00 59 .equ SCB_SCR_OFFSET, 0x010 60 .equ SCB_SHCSR_OFFSET, 0x024 61 .equ SCB_CPACR_OFFSET, 0x088 62 .equ FPU_BASE, 0xE000EF30 63 .equ FPU_FPCCR_OFFSET, 0x004 64 .equ FPU_FPDSCR_OFFSET, 0x00C 65 .equ QSPIC_BASE, 0x38000000 66 .equ QSPIC_CTRLBUS_OFFSET, 0x000 67 .equ QSPIC_CTRLMOD_OFFSET, 0x004 68 .equ QSPIC_WRITEDATA_OFFSET, 0x018 69 70 .equ SCB_CPACR_MASK, 0x00F00000 /* CP10 and CP11 */ 71 .equ SCB_SHCSR_MASK, 0x000F0000 /* xxxFAULTENA */ 72 .equ FPU_FPCCR_MASK, 0xF0000000 /* ASPEN, LSPEN, LSPENS, CLRONRET */ 73 74 .section RAM_TEXT_SECTION, "ax" 75 .thumb 76 .thumb_func 77 .align 2 78 .globl da1469x_enter_sleep 79 .type da1469x_enter_sleep, %function 80da1469x_enter_sleep: 81 ldr r3, =da1469x_sleep_context 82 83/* Disable interrupts and save original PRIMASK */ 84 mrs r0, PRIMASK 85 cpsid i 86 stmia r3!, {r0} 87 88/* Save MSP, PSP, CONTROL and general purpose registers */ 89 mrs r0, MSP 90 mrs r1, PSP 91 mrs r2, CONTROL 92 stmia r3!, {r0-r2,r4-r12, lr} 93 94/* Save NVIC state (ISER[0..1] and IPR[0..43]) */ 95 ldr r0, =NVIC_BASE 96 add r1, r0, NVIC_IPR_OFFSET 97 ldmia r0!, {r4-r5} 98 stmia r3!, {r4-r5} 99 ldmia r1, {r0, r2, r4-r12} 100 stmia r3!, {r0, r2, r4-r12} 101 102/* Save SCB state (SCR, CCR, SHPR and SHCSR) */ 103 ldr r0, =(SCB_BASE + SCB_SCR_OFFSET) 104 ldmia r0, {r4-r9} 105 and r9, r9, #(SCB_SHCSR_MASK) 106 ldr r10, [r0, #(SCB_CPACR_OFFSET - SCB_SCR_OFFSET)] 107 and r10, r10, #(SCB_CPACR_MASK) 108 stmia r3!, {r4-r10} 109 110#if USE_FPU 111/* Save FPU state (FPCCR and FPDSCR) */ 112 ldr r0, =FPU_BASE 113 ldr r4, [r0, #(FPU_FPCCR_OFFSET)] 114 and r4, r4, #(FPU_FPCCR_MASK) 115 ldr r5, [r0, #(FPU_FPDSCR_OFFSET)] 116 stmia r3!, {r4-r5} 117#endif 118 119/* Clear RESET_STAT_REG so wakeup handler can detect wakeup from deep sleep */ 120 ldr r0, =RESET_STAT_REG 121 movs r3, #0 122 str r3, [r0, #0] 123 124/* Disable QSPI continuous mode to achieve flash standby */ 125 ldr r0, =QSPIC_BASE 126 ldr r1, [r0, #(QSPIC_CTRLMOD_OFFSET)] 127 bic r1, r1, #1 /* Clear automode */ 128 orr r1, r1, #0x3c /* Set IO2/IO3 DAT and OEN */ 129 str r1, [r0, #(QSPIC_CTRLMOD_OFFSET)] 130 mov r1, #1 /* Set single */ 131 str r1, [r0, #(QSPIC_CTRLBUS_OFFSET)] 132 mov r1, #8 /* Enable CS */ 133 str r1, [r0, #(QSPIC_CTRLBUS_OFFSET)] 134 mov r1, #0xff /* Exit QPI mode */ 135 strb r1, [r0, #(QSPIC_WRITEDATA_OFFSET)] 136 mov r1, #16 /* Disable CS */ 137 str r1, [r0, #(QSPIC_CTRLBUS_OFFSET)] 138 139/* Disable QSPI controller clock */ 140 ldr r0, =CLK_AMBA_REG 141 ldr r1, [r0, #0] 142 bic r1, r1, #0x1000 143 str r1, [r0, #0] 144 145/* Set SCB->SCR[SLEEPDEEP] so we can enter deep sleep */ 146 ldr r0, =(SCB_BASE + SCB_SCR_OFFSET) 147 ldr r1, [r0, #0] 148 orr r1, r1, #4 /* SLEEPDEEP */ 149 str r1, [r0, #0] 150 151/* Sleep! */ 152 dsb 153 wfi 154 155/* 156 * If deep sleep was executed we'll restart in reset handler, otherwise we just 157 * restore registers and continue by returning false to caller to indicate we 158 * did not sleep. 159 */ 160 str r1, [r0, #0] 161 162/* Enable QSPI controller clock */ 163 ldr r2, =CLK_AMBA_REG 164 ldr r1, [r2, #0] 165 orr r1, r1, #0x1000 166 str r1, [r2, #0] 167 168/* Put flash back into automode. We need to do this before we start executing code 169 from flash again. 170*/ 171 ldr r0, =QSPIC_BASE 172 str r1, [r0, #(QSPIC_CTRLBUS_OFFSET)] 173 mov r1, #4 /* Set quad */ 174 str r1, [r0, #(QSPIC_CTRLBUS_OFFSET)] 175 ldr r1, [r0, #(QSPIC_CTRLMOD_OFFSET)] 176 bic r1, r1, #0xc /* Clear IO2/IO3 OEN */ 177 orr r1, r1, #1 /* Enable automode */ 178 str r1, [r0, #(QSPIC_CTRLMOD_OFFSET)] 179 180 mov r0, #0 181 b da1469x_restore_state 182 183 .section RAM_TEXT_SECTION, "ax" 184 .globl da1469x_wakeup 185 .type da1469x_wakeup, %function 186da1469x_wakeup: 187/* Disable interrupts, we'll restore proper PRIMASK at the end */ 188 cpsid i 189 190 /* 191 * Temporarily restore saved MSP as temporary stack pointer to allow proper 192 * stacking in case of an exception. 193 */ 194 ldr r3, =.saved_msp 195 ldr sp, [r3, #0] 196 197 /* Restore NVIC state */ 198 ldr r3, =.saved_nvic 199 ldr r0, =NVIC_BASE 200 add r1, r0, NVIC_IPR_OFFSET 201 ldmia r3!, {r4-r5} 202 stmia r0!, {r4-r5} 203 ldmia r3!, {r0, r2, r4-r12} 204 stmia r1, {r0, r2, r4-r12} 205 206 /* Restore SCB state */ 207 ldmia r3!, {r4-r10} 208 ldr r0, =(SCB_BASE + SCB_SCR_OFFSET) 209 ldr r1, [r0, #(SCB_CPACR_OFFSET - SCB_SCR_OFFSET)] 210 orr r10, r10, r1 211 str r10, [r0, #(SCB_CPACR_OFFSET - SCB_SCR_OFFSET)] 212 ldr r1, [r0, #(SCB_SHCSR_OFFSET - SCB_SCR_OFFSET)] 213 orr r9, r9, r1 214 stmia r0!, {r4-r9} 215 216#if USE_FPU 217/* Restore FPU state */ 218 ldmia r3!, {r4-r5} 219 ldr r0, =FPU_BASE 220 ldr r1, [r0, #(FPU_FPCCR_OFFSET)] 221 orr r4, r4, r1 222 str r4, [r0, #(FPU_FPCCR_OFFSET)] 223 str r5, [r0, #(FPU_FPDSCR_OFFSET)] 224#endif 225 226/* Restore MSP, PSP and CONTROL */ 227 ldr r3, =.saved_msp 228 ldmia r3!, {r0-r2} 229 msr MSP, r0 230 msr PSP, r1 231 msr CONTROL, r2 232 233/* Enable QSPI controller clock */ 234 ldr r0, =CLK_AMBA_REG 235 ldr r1, [r0, #0] 236 orr r1, r1, #0x1000 237 str r1, [r0, #0] 238 239/* 240 * Flash is likely in QPI mode but QSPIC assumes it is in single mode so we 241 * should make sure both are in sync by forcing exit from QPI mode and then 242 * re-enter it. We need to do this before we start executing code from flash 243 * again. 244 */ 245 ldr r0, =QSPIC_BASE 246 ldr r1, [r0, #(QSPIC_CTRLMOD_OFFSET)] 247 bic r1, r1, #1 /* Clear automode */ 248 orr r1, r1, #0x3c /* Set IO2/IO3 DAT and OEN */ 249 str r1, [r0, #(QSPIC_CTRLMOD_OFFSET)] 250 mov r1, #1 /* Set single */ 251 str r1, [r0, #(QSPIC_CTRLBUS_OFFSET)] 252 mov r1, #8 /* Enable CS */ 253 str r1, [r0, #(QSPIC_CTRLBUS_OFFSET)] 254 mov r1, #0xff /* Exit QPI mode */ 255 strb r1, [r0, #(QSPIC_WRITEDATA_OFFSET)] 256 mov r1, #16 /* Disable CS */ 257 str r1, [r0, #(QSPIC_CTRLBUS_OFFSET)] 258 mov r1, #4 /* Set quad */ 259 str r1, [r0, #(QSPIC_CTRLBUS_OFFSET)] 260 ldr r1, [r0, #(QSPIC_CTRLMOD_OFFSET)] 261 bic r1, r1, #0xc /* Clear IO2/IO3 OEN */ 262 orr r1, r1, #1 /* Enable automode */ 263 str r1, [r0, #(QSPIC_CTRLMOD_OFFSET)] 264 265/* Finish restore, return true to caller to indicate we slept */ 266 mov r0, #1 267 ldr r3, =da1469x_restore_state 268 bx r3 269 270 .section RAM_TEXT_SECTION, "ax" 271 .globl da1469x_restore_state 272 .type da1469x_restore_state, %function 273da1469x_restore_state: 274 ldr r3, =.saved_regs 275 ldmia r3!, {r4-r12, lr} 276 277 ldr r3, =.saved_primask 278 ldr r3, [r3, #0] 279 msr PRIMASK, r3 280 281 bx lr 282 283 .section RAM_TEXT_SECTION, "ax" 284 .globl da1469x_wakeup_handler 285 .type da1469x_wakeup_handler, %function 286da1469x_wakeup_handler: 287 ldr r0, =RESET_STAT_REG 288 ldr r0, [r0, #0] 289 teq r0, #0 290 ite eq 291 ldreq r3, =da1469x_wakeup 292 ldrne r3, =RESETHANDLER 293 bx r3 294