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