154925552SJoseph Chen/* 254925552SJoseph Chen * (C) Copyright 2017 Rockchip Electronics Co., Ltd. 354925552SJoseph Chen * 454925552SJoseph Chen * SPDX-License-Identifier: GPL-2.0+ 554925552SJoseph Chen */ 654925552SJoseph Chen 754925552SJoseph Chen#include <asm/arm32_macros.S> 854925552SJoseph Chen#include <asm/macro.h> 954925552SJoseph Chen#include <asm-offsets.h> 1054925552SJoseph Chen#include <asm/psci.h> 1154925552SJoseph Chen#include <config.h> 1254925552SJoseph Chen#include <linux/linkage.h> 1354925552SJoseph Chen 1454925552SJoseph Chen .globl cpu_suspend 1554925552SJoseph Chen .globl cpu_do_suspend 1654925552SJoseph Chen .globl cpu_suspend_save 1754925552SJoseph Chen .globl cpu_resume 1854925552SJoseph Chen .globl cpu_do_resume 1954925552SJoseph Chen 2054925552SJoseph Chen/* 2154925552SJoseph Chen * int cpu_suspend(unsigned long arg, int (*fn)(unsigned long)) 2254925552SJoseph Chen * @arg will be passed to fn as argument 2354925552SJoseph Chen * return value: 0 - cpu resumed from suspended state. 2454925552SJoseph Chen * -1 - cpu not suspended. 2554925552SJoseph Chen */ 2654925552SJoseph ChenENTRY(cpu_suspend) 2754925552SJoseph Chen push {r4 - r12, lr} 2854925552SJoseph Chen 2954925552SJoseph Chen mov r5, sp 3054925552SJoseph Chen sub sp, sp, #PM_CTX_SIZE 3154925552SJoseph Chen push {r0, r1} 3254925552SJoseph Chen 33*abf4f551SJoseph Chen /* r9 is gd, save it to __suspend_gd !!! */ 34*abf4f551SJoseph Chen adr r4, __suspend_gd 3554925552SJoseph Chen str r9, [r4] 3654925552SJoseph Chen 3754925552SJoseph Chen mov r1, r5 3854925552SJoseph Chen add r0, sp, #8 3954925552SJoseph Chen blx cpu_suspend_save 4054925552SJoseph Chen 4154925552SJoseph Chen adr lr, aborted 4254925552SJoseph Chen /* Jump to arch specific suspend */ 4354925552SJoseph Chen pop {r0, pc} 4454925552SJoseph Chen 4554925552SJoseph Chenaborted: 4654925552SJoseph Chen /* cpu not suspended */ 4754925552SJoseph Chen add sp, sp, #PM_CTX_SIZE 4854925552SJoseph Chen /* Return -1 to the caller */ 4954925552SJoseph Chen mov r0, #(-1) 5054925552SJoseph Chen 5154925552SJoseph Chensuspend_return: 5254925552SJoseph Chen pop {r4 - r12, pc} 5354925552SJoseph ChenENDPROC(cpu_suspend) 5454925552SJoseph Chen 5554925552SJoseph ChenENTRY(cpu_do_suspend) 5654925552SJoseph Chen push {r4 - r11} 5754925552SJoseph Chen 5854925552SJoseph Chen read_midr r4 5954925552SJoseph Chen ubfx r5, r4, #4, #12 6054925552SJoseph Chen ldr r4, CORTEX_A7_PART_NUM 6154925552SJoseph Chen cmp r5, r4 6254925552SJoseph Chen beq a7_suspend 6354925552SJoseph Chen ldr r4, CORTEX_A9_PART_NUM 6454925552SJoseph Chen cmp r5, r4 6554925552SJoseph Chen beq a9_suspend 6654925552SJoseph Chen 6754925552SJoseph Chen /* cpu not supported */ 6854925552SJoseph Chen b . 6954925552SJoseph Chen 7054925552SJoseph Chen /* A9 needs PCR/DIAG */ 7154925552SJoseph Chena9_suspend: 7254925552SJoseph Chen read_pcr r4 7354925552SJoseph Chen read_diag r5 7454925552SJoseph Chen stmia r0!, {r4 - r5} 7554925552SJoseph Chen 7654925552SJoseph Chena7_suspend: 7754925552SJoseph Chen read_fcseidr r4 7854925552SJoseph Chen read_tpidruro r5 7954925552SJoseph Chen stmia r0!, {r4 - r5} 8054925552SJoseph Chen 8154925552SJoseph Chen read_dacr r4 8254925552SJoseph Chen read_ttbr0 r5 8354925552SJoseph Chen read_ttbr1 r6 8454925552SJoseph Chen read_ttbcr r7 8554925552SJoseph Chen read_sctlr r8 8654925552SJoseph Chen read_actlr r9 8754925552SJoseph Chen read_cpacr r10 8854925552SJoseph Chen stmia r0!, {r4 - r10} 8954925552SJoseph Chen 9054925552SJoseph Chen read_prrr r4 9154925552SJoseph Chen read_nmrr r5 9254925552SJoseph Chen read_vbar r6 9354925552SJoseph Chen mrs r7, CPSR 9454925552SJoseph Chen stmia r0, {r4 - r7} 9554925552SJoseph Chen 9654925552SJoseph Chen pop {r4 - r11} 9754925552SJoseph Chen bx lr 9854925552SJoseph ChenENDPROC(cpu_do_suspend) 9954925552SJoseph Chen 10054925552SJoseph ChenENTRY(cpu_resume) 10154925552SJoseph Chen /* Disable interrupt */ 10254925552SJoseph Chen cpsid aif 10354925552SJoseph Chen 10454925552SJoseph Chen /* Load gd !! */ 105*abf4f551SJoseph Chen adr r1, __suspend_gd 10654925552SJoseph Chen ldr r2, [r1] 10754925552SJoseph Chen 10854925552SJoseph Chen /* Get pm_ctx */ 10954925552SJoseph Chen add r2, r2, #PM_CTX_PHYS 11054925552SJoseph Chen ldr r0, [r2] 11154925552SJoseph Chen 11254925552SJoseph Chen /* Need to use r0!, because cpu_do_resume needs it */ 11354925552SJoseph Chen ldmia r0!, {sp, pc} 11454925552SJoseph ChenENDPROC(cpu_resume) 11554925552SJoseph Chen 11654925552SJoseph Chen/* 11754925552SJoseph Chen * void sm_do_cpu_do_resume(paddr suspend_regs) __noreturn; 11854925552SJoseph Chen * Restore the registers stored when cpu_do_suspend 11954925552SJoseph Chen * r0 points to the physical base address of the suspend_regs 12054925552SJoseph Chen * field of struct pm_ctx. 12154925552SJoseph Chen */ 12254925552SJoseph ChenENTRY(cpu_do_resume) 12354925552SJoseph Chen read_midr r4 12454925552SJoseph Chen ubfx r5, r4, #4, #12 12554925552SJoseph Chen ldr r4, CORTEX_A7_PART_NUM 12654925552SJoseph Chen cmp r5, r4 12754925552SJoseph Chen beq a7_resume 12854925552SJoseph Chen 12954925552SJoseph Chen /* 13054925552SJoseph Chen * A9 needs PCR/DIAG 13154925552SJoseph Chen */ 13254925552SJoseph Chen ldmia r0!, {r4 - r5} 13354925552SJoseph Chen write_pcr r4 13454925552SJoseph Chen write_diag r5 13554925552SJoseph Chen 13654925552SJoseph Chena7_resume: 13754925552SJoseph Chen /* v7 resume */ 13854925552SJoseph Chen mov ip, #0 13954925552SJoseph Chen 14054925552SJoseph Chen /* Invalidate icache to PoU */ 14154925552SJoseph Chen write_iciallu 14254925552SJoseph Chen /* set reserved context */ 14354925552SJoseph Chen write_contextidr ip 14454925552SJoseph Chen 14554925552SJoseph Chen ldmia r0!, {r4 - r5} 14654925552SJoseph Chen write_fcseidr r4 14754925552SJoseph Chen write_tpidruro r5 14854925552SJoseph Chen 14954925552SJoseph Chen ldmia r0!, {r4 - r10} 15054925552SJoseph Chen /* Invalidate entire TLB */ 15154925552SJoseph Chen write_tlbiall 15254925552SJoseph Chen write_dacr r4 15354925552SJoseph Chen write_ttbr0 r5 15454925552SJoseph Chen write_ttbr1 r6 15554925552SJoseph Chen write_ttbcr r7 15654925552SJoseph Chen 15754925552SJoseph Chen ldmia r0, {r4 - r7} 15854925552SJoseph Chen write_prrr r4 15954925552SJoseph Chen write_nmrr r5 16054925552SJoseph Chen write_vbar r6 16154925552SJoseph Chen 16254925552SJoseph Chen write_actlr r9 16354925552SJoseph Chen write_cpacr r10 16454925552SJoseph Chen write_bpiall 16554925552SJoseph Chen isb 16654925552SJoseph Chen dsb 16754925552SJoseph Chen 16854925552SJoseph Chen /* MMU will be enabled here */ 16954925552SJoseph Chen write_sctlr r8 17054925552SJoseph Chen isb 17154925552SJoseph Chen 17254925552SJoseph Chen /* Restore interrupt */ 17354925552SJoseph Chen msr CPSR_c, r7 17454925552SJoseph Chen 17554925552SJoseph Chen mov r0, #0 17654925552SJoseph Chen b suspend_return 17754925552SJoseph ChenENDPROC(cpu_do_resume) 17854925552SJoseph Chen 17954925552SJoseph Chen.align 4 180*abf4f551SJoseph Chen__suspend_gd: 18154925552SJoseph Chen .word 0x0 18254925552SJoseph ChenCORTEX_A7_PART_NUM: 18354925552SJoseph Chen .word 0xC07 18454925552SJoseph ChenCORTEX_A9_PART_NUM: 18554925552SJoseph Chen .word 0xC09 186