Linux-libre 5.4.49-gnu
[librecmc/linux-libre.git] / arch / unicore32 / kernel / sleep.S
1 /* SPDX-License-Identifier: GPL-2.0-only */
2 /*
3  * linux/arch/unicore32/kernel/sleep.S
4  *
5  * Code specific to PKUnity SoC and UniCore ISA
6  *
7  *      Maintained by GUAN Xue-tao <gxt@mprc.pku.edu.cn>
8  *      Copyright (C) 2001-2010 Guan Xuetao
9  */
10
11 #include <linux/linkage.h>
12 #include <asm/assembler.h>
13 #include <mach/hardware.h>
14
15                 .text
16
17 pkunity_cpu_save_cp:
18
19         @ get coprocessor registers
20
21         movc    r3, p0.c7, #0                   @ PID
22         movc    r4, p0.c2, #0                   @ translation table base addr
23         movc    r5, p0.c1, #0                   @ control reg
24
25
26         @ store them plus current virtual stack ptr on stack
27         mov     r6, sp
28         stm.w   (r3 - r6), [sp-]
29
30         mov     pc, lr
31
32 pkunity_cpu_save_sp:
33         @ preserve phys address of stack
34         mov     r0, sp
35         stw.w   lr, [sp+], #-4
36         b.l     sleep_phys_sp
37         ldw     r1, =sleep_save_sp
38         stw     r0, [r1]
39         ldw.w   pc, [sp]+, #4
40
41 /*
42  * puv3_cpu_suspend()
43  *
44  * Forces CPU into sleep state.
45  *
46  * r0 = value for PWRMODE M field for desired sleep state
47  */
48
49 ENTRY(puv3_cpu_suspend)
50         stm.w   (r16 - r27, lr), [sp-]          @ save registers on stack
51         stm.w   (r4 - r15), [sp-]               @ save registers on stack
52
53 #ifdef  CONFIG_UNICORE_FPU_F64
54         sfm.w   (f0  - f7 ), [sp-]
55         sfm.w   (f8  - f15), [sp-]
56         sfm.w   (f16 - f23), [sp-]
57         sfm.w   (f24 - f31), [sp-]
58         cff     r4, s31
59         stm.w   (r4), [sp-]
60 #endif
61         b.l     pkunity_cpu_save_cp
62
63         b.l     pkunity_cpu_save_sp
64
65         @ clean data cache
66         mov     r1, #0
67         movc    p0.c5, r1, #14
68         nop
69         nop
70         nop
71         nop
72
73
74
75         @ DDR2 BaseAddr
76         ldw     r0, =(PKUNITY_DDR2CTRL_BASE)
77
78         @ PM BaseAddr
79         ldw     r1, =(PKUNITY_PM_BASE)
80
81         @ set PLL_SYS_CFG reg, 275
82         movl    r6, #0x00002401
83         stw     r6, [r1+], #0x18
84         @ set PLL_DDR_CFG reg, 66MHz
85         movl    r6, #0x00100c00
86         stw     r6, [r1+], #0x1c
87
88         @ set wake up source
89         movl    r8, #0x800001ff         @ epip4d
90         stw     r8, [r1+], #0xc
91
92         @ set PGSR
93         movl    r5, #0x40000
94         stw     r5, [r1+], #0x10
95
96         @ prepare DDR2 refresh settings
97         ldw     r5, [r0+], #0x24
98         or      r5, r5, #0x00000001
99
100         @ prepare PMCR for PLL changing
101         movl    r6, #0xc
102
103         @ prepare for closing PLL
104         movl    r7, #0x1
105
106         @ prepare sleep mode
107         mov     r8, #0x1
108
109 @       movl    r0, 0x11111111
110 @       put_word_ocd r0
111         b       pkunity_cpu_do_suspend
112
113         .ltorg
114         .align  5
115 pkunity_cpu_do_suspend:
116         b       101f
117         @ put DDR2 into self-refresh
118 100:    stw     r5, [r0+], #0x24
119         @ change PLL
120         stw     r6, [r1]
121         b       1f
122
123         .ltorg
124         .align  5
125 101:    b       102f
126         @ wait for PLL changing complete
127 1:      ldw     r6, [r1+], #0x44
128         csub.a  r6, #0x1
129         bne     1b
130         b       2f
131
132         .ltorg
133         .align  5
134 102:    b       100b
135         @ close PLL
136 2:      stw     r7, [r1+], #0x4
137         @ enter sleep mode
138         stw     r8, [r1]
139 3:      b       3b
140
141
142
143
144 /*
145  * puv3_cpu_resume()
146  *
147  * entry point from bootloader into kernel during resume
148  *
149  * Note: Yes, part of the following code is located into the .data section.
150  *       This is to allow sleep_save_sp to be accessed with a relative load
151  *       while we can't rely on any MMU translation.  We could have put
152  *       sleep_save_sp in the .text section as well, but some setups might
153  *       insist on it to be truly read-only.
154  */
155
156         .data
157         .align 5
158 ENTRY(puv3_cpu_resume)
159 @       movl    r0, 0x20202020
160 @       put_word_ocd r0
161
162         ldw     r0, sleep_save_sp               @ stack phys addr
163         ldw     r2, =resume_after_mmu           @ its absolute virtual address
164         ldm     (r3 - r6), [r0]+                @ CP regs + virt stack ptr
165         mov     sp, r6                          @ CP regs + virt stack ptr
166
167         mov     r1, #0
168         movc    p0.c6, r1, #6                   @ invalidate I & D TLBs
169         movc    p0.c5, r1, #28                  @ invalidate I & D caches, BTB
170
171         movc    p0.c7, r3, #0                   @ PID
172         movc    p0.c2, r4, #0                   @ translation table base addr
173         movc    p0.c1, r5, #0                   @ control reg, turn on mmu
174         nop
175         jump    r2
176         nop
177         nop
178         nop
179         nop
180         nop
181
182 sleep_save_sp:
183         .word   0                               @ preserve stack phys ptr here
184
185         .text
186 resume_after_mmu:
187 @       movl    r0, 0x30303030
188 @       put_word_ocd r0
189
190 #ifdef  CONFIG_UNICORE_FPU_F64
191         lfm.w   (f0  - f7 ), [sp]+
192         lfm.w   (f8  - f15), [sp]+
193         lfm.w   (f16 - f23), [sp]+
194         lfm.w   (f24 - f31), [sp]+
195         ldm.w   (r4), [sp]+
196         ctf     r4, s31
197 #endif
198         ldm.w   (r4 - r15), [sp]+               @ restore registers from stack
199         ldm.w   (r16 - r27, pc), [sp]+          @ return to caller