1 /* SPDX-License-Identifier: GPL-2.0 */
3 * Low level suspend code for AM33XX SoCs
5 * Copyright (C) 2012-2018 Texas Instruments Incorporated - http://www.ti.com/
6 * Dave Gerlach, Vaibhav Bedia
9 #include <generated/ti-emif-asm-offsets.h>
10 #include <generated/ti-pm-asm-offsets.h>
11 #include <linux/linkage.h>
12 #include <linux/ti-emif-sram.h>
13 #include <asm/assembler.h>
14 #include <asm/memory.h>
19 #define AM33XX_CM_CLKCTRL_MODULESTATE_DISABLED 0x00030000
20 #define AM33XX_CM_CLKCTRL_MODULEMODE_DISABLE 0x0003
21 #define AM33XX_CM_CLKCTRL_MODULEMODE_ENABLE 0x0002
27 stmfd sp!, {r4 - r11, lr} @ save registers on stack
30 * Flush all data from the L1 and L2 data cache before disabling
37 * Clear the SCTLR.C bit to prevent further data cache
38 * allocation. Clearing SCTLR.C would make all the data accesses
39 * strongly ordered and would not hit the cache.
41 mrc p15, 0, r0, c1, c0, 0
42 bic r0, r0, #(1 << 2) @ Disable the C bit
43 mcr p15, 0, r0, c1, c0, 0
47 * Invalidate L1 and L2 data cache.
52 adr r9, am33xx_emif_sram_table
54 ldr r3, [r9, #EMIF_PM_ENTER_SR_OFFSET]
57 ldr r3, [r9, #EMIF_PM_SAVE_CONTEXT_OFFSET]
61 ldr r1, virt_emif_clkctrl
63 bic r2, r2, #AM33XX_CM_CLKCTRL_MODULEMODE_DISABLE
66 ldr r1, virt_emif_clkctrl
69 mov r3, #AM33XX_CM_CLKCTRL_MODULESTATE_DISABLED
74 * For the MPU WFI to be registered as an interrupt
75 * to WKUP_M3, MPU_CLKCTRL.MODULEMODE needs to be set
78 ldr r1, virt_mpu_clkctrl
80 bic r2, r2, #AM33XX_CM_CLKCTRL_MODULEMODE_DISABLE
84 * Execute an ISB instruction to ensure that all of the
85 * CP15 register changes have been committed.
90 * Execute a barrier instruction to ensure that all cache,
91 * TLB and branch predictor maintenance operations issued
98 * Execute a WFI instruction and wait until the
99 * STANDBYWFI output is asserted to indicate that the
100 * CPU is in idle and low power state. CPU can specualatively
101 * prefetch the instructions so add NOPs after WFI. Thirteen
102 * NOPs as per Cortex-A8 pipeline.
120 /* We come here in case of an abort due to a late interrupt */
122 /* Set MPU_CLKCTRL.MODULEMODE back to ENABLE */
123 ldr r1, virt_mpu_clkctrl
124 mov r2, #AM33XX_CM_CLKCTRL_MODULEMODE_ENABLE
128 ldr r1, virt_emif_clkctrl
129 mov r2, #AM33XX_CM_CLKCTRL_MODULEMODE_ENABLE
137 ldr r1, [r9, #EMIF_PM_ABORT_SR_OFFSET]
141 * Set SCTLR.C bit to allow data cache allocation
143 mrc p15, 0, r0, c1, c0, 0
144 orr r0, r0, #(1 << 2) @ Enable the C bit
145 mcr p15, 0, r0, c1, c0, 0
148 /* Let the suspend code know about the abort */
150 ldmfd sp!, {r4 - r11, pc} @ restore regs and return
151 ENDPROC(am33xx_do_wfi)
154 ENTRY(am33xx_resume_offset)
155 .word . - am33xx_do_wfi
157 ENTRY(am33xx_resume_from_deep_sleep)
159 ldr r0, phys_emif_clkctrl
160 mov r1, #AM33XX_CM_CLKCTRL_MODULEMODE_ENABLE
165 bne wait_emif_enable1
167 adr r9, am33xx_emif_sram_table
169 ldr r1, [r9, #EMIF_PM_RESTORE_CONTEXT_OFFSET]
172 ldr r1, [r9, #EMIF_PM_EXIT_SR_OFFSET]
176 /* We are back. Branch to the common CPU resume routine */
179 ENDPROC(am33xx_resume_from_deep_sleep)
186 .word cpu_resume - PAGE_OFFSET + 0x80000000
188 .word v7_flush_dcache_all
190 .word AM33XX_CM_MPU_MPU_CLKCTRL
192 .word AM33XX_CM_PER_EMIF_CLKCTRL
194 .word (AM33XX_CM_BASE + AM33XX_CM_PER_MOD + \
195 AM33XX_CM_PER_EMIF_CLKCTRL_OFFSET)
198 /* DDR related defines */
199 am33xx_emif_sram_table:
200 .space EMIF_PM_FUNCTIONS_SIZE
202 ENTRY(am33xx_pm_sram)
204 .word am33xx_do_wfi_sz
205 .word am33xx_resume_offset
206 .word am33xx_emif_sram_table
207 .word am33xx_pm_ro_sram_data
210 ENTRY(am33xx_pm_ro_sram_data)
211 .space AMX3_PM_RO_SRAM_DATA_SIZE
213 ENTRY(am33xx_do_wfi_sz)
214 .word . - am33xx_do_wfi