ARM: rockchip: rk3228: implement function rk3228_restart
[firefly-linux-kernel-4.4.55.git] / arch / arm / kernel / sleep.S
1 #include <linux/linkage.h>
2 #include <linux/threads.h>
3 #include <asm/asm-offsets.h>
4 #include <asm/assembler.h>
5 #include <asm/glue-cache.h>
6 #include <asm/glue-proc.h>
7 #include "entry-header.S"
8         .text
9
10 /*
11  * Save CPU state for a suspend.  This saves the CPU general purpose
12  * registers, and allocates space on the kernel stack to save the CPU
13  * specific registers and some other data for resume.
14  *  r0 = suspend function arg0
15  *  r1 = suspend function
16  */
17 ENTRY(__cpu_suspend)
18         stmfd   sp!, {r4 - r11, lr}
19 #ifdef MULTI_CPU
20         ldr     r10, =processor
21         ldr     r4, [r10, #CPU_SLEEP_SIZE] @ size of CPU sleep state
22 #else
23         ldr     r4, =cpu_suspend_size
24 #endif
25         mov     r5, sp                  @ current virtual SP
26         add     r4, r4, #12             @ Space for pgd, virt sp, phys resume fn
27         sub     sp, sp, r4              @ allocate CPU state on stack
28         stmfd   sp!, {r0, r1}           @ save suspend func arg and pointer
29         add     r0, sp, #8              @ save pointer to save block
30         mov     r1, r4                  @ size of save block
31         mov     r2, r5                  @ virtual SP
32         ldr     r3, =sleep_save_sp
33 #ifdef CONFIG_SMP
34         get_thread_info r5
35         ldr     lr, [r5, #TI_CPU]       @ cpu logical index
36         add     r3, r3, lr, lsl #2
37 #endif
38         bl      __cpu_suspend_save
39         adr     lr, BSYM(cpu_suspend_abort)
40         ldmfd   sp!, {r0, pc}           @ call suspend fn
41 ENDPROC(__cpu_suspend)
42         .ltorg
43
44 cpu_suspend_abort:
45         ldmia   sp!, {r1 - r3}          @ pop phys pgd, virt SP, phys resume fn
46         teq     r0, #0
47         moveq   r0, #1                  @ force non-zero value
48         mov     sp, r2
49         ldmfd   sp!, {r4 - r11, pc}
50 ENDPROC(cpu_suspend_abort)
51
52 /*
53  * r0 = control register value
54  */
55         .align  5
56         .pushsection    .idmap.text,"ax"
57 ENTRY(cpu_resume_mmu)
58         ldr     r3, =cpu_resume_after_mmu
59         instr_sync
60         mcr     p15, 0, r0, c1, c0, 0   @ turn on MMU, I-cache, etc
61         mrc     p15, 0, r0, c0, c0, 0   @ read id reg
62         instr_sync
63         mov     r0, r0
64         mov     r0, r0
65         mov     pc, r3                  @ jump to virtual address
66 ENDPROC(cpu_resume_mmu)
67         .popsection
68 cpu_resume_after_mmu:
69         bl      cpu_init                @ restore the und/abt/irq banked regs
70         mov     r0, #0                  @ return zero on success
71         ldmfd   sp!, {r4 - r11, pc}
72 ENDPROC(cpu_resume_after_mmu)
73
74 /*
75  * Note: Yes, part of the following code is located into the .data section.
76  *       This is to allow sleep_save_sp to be accessed with a relative load
77  *       while we can't rely on any MMU translation.  We could have put
78  *       sleep_save_sp in the .text section as well, but some setups might
79  *       insist on it to be truly read-only.
80  */
81         .data
82         .align
83 ENTRY(cpu_resume)
84 ARM_BE8(setend be)                      @ ensure we are in BE mode
85 #ifdef CONFIG_SMP
86         mov     r1, #0                  @ fall-back logical index for UP
87         ALT_SMP(mrc p15, 0, r0, c0, c0, 5)
88         ALT_UP_B(1f)
89         bic     r0, #0xff000000
90         bl      cpu_logical_index       @ return logical index in r1
91 1:
92         adr     r0, sleep_save_sp
93         ldr     r0, [r0, r1, lsl #2]    @ stack phys addr
94 #else
95         ldr     r0, sleep_save_sp       @ stack phys addr
96 #endif
97         setmode PSR_I_BIT | PSR_F_BIT | SVC_MODE, r1  @ set SVC, irqs off
98         @ load phys pgd, stack, resume fn
99   ARM(  ldmia   r0!, {r1, sp, pc}       )
100 THUMB(  ldmia   r0!, {r1, r2, r3}       )
101 THUMB(  mov     sp, r2                  )
102 THUMB(  bx      r3                      )
103 ENDPROC(cpu_resume)
104
105 sleep_save_sp:
106         .rept   CONFIG_NR_CPUS
107         .long   0                               @ preserve stack phys ptr here
108         .endr
109
110 #ifdef CONFIG_SMP
111 cpu_logical_index:
112         adr     r3, cpu_map_ptr
113         ldr     r2, [r3]
114         add     r3, r3, r2              @ virt_to_phys(__cpu_logical_map)
115         mov     r1, #0
116 1:
117         ldr     r2, [r3, r1, lsl #2]
118         cmp     r2, r0
119         moveq   pc, lr
120         add     r1, r1, #1
121         b       1b
122
123 cpu_map_ptr:
124         .long __cpu_logical_map - .
125 #endif