]> git.proxmox.com Git - mirror_ubuntu-hirsute-kernel.git/blob - arch/arm/mach-ep93xx/crunch-bits.S
treewide: Replace GPLv2 boilerplate/reference with SPDX - rule 500
[mirror_ubuntu-hirsute-kernel.git] / arch / arm / mach-ep93xx / crunch-bits.S
1 /* SPDX-License-Identifier: GPL-2.0-only */
2 /*
3 * arch/arm/kernel/crunch-bits.S
4 * Cirrus MaverickCrunch context switching and handling
5 *
6 * Copyright (C) 2006 Lennert Buytenhek <buytenh@wantstofly.org>
7 *
8 * Shamelessly stolen from the iWMMXt code by Nicolas Pitre, which is
9 * Copyright (c) 2003-2004, MontaVista Software, Inc.
10 */
11
12 #include <linux/linkage.h>
13 #include <asm/ptrace.h>
14 #include <asm/thread_info.h>
15 #include <asm/asm-offsets.h>
16 #include <asm/assembler.h>
17 #include <mach/ep93xx-regs.h>
18
19 /*
20 * We can't use hex constants here due to a bug in gas.
21 */
22 #define CRUNCH_MVDX0 0
23 #define CRUNCH_MVDX1 8
24 #define CRUNCH_MVDX2 16
25 #define CRUNCH_MVDX3 24
26 #define CRUNCH_MVDX4 32
27 #define CRUNCH_MVDX5 40
28 #define CRUNCH_MVDX6 48
29 #define CRUNCH_MVDX7 56
30 #define CRUNCH_MVDX8 64
31 #define CRUNCH_MVDX9 72
32 #define CRUNCH_MVDX10 80
33 #define CRUNCH_MVDX11 88
34 #define CRUNCH_MVDX12 96
35 #define CRUNCH_MVDX13 104
36 #define CRUNCH_MVDX14 112
37 #define CRUNCH_MVDX15 120
38 #define CRUNCH_MVAX0L 128
39 #define CRUNCH_MVAX0M 132
40 #define CRUNCH_MVAX0H 136
41 #define CRUNCH_MVAX1L 140
42 #define CRUNCH_MVAX1M 144
43 #define CRUNCH_MVAX1H 148
44 #define CRUNCH_MVAX2L 152
45 #define CRUNCH_MVAX2M 156
46 #define CRUNCH_MVAX2H 160
47 #define CRUNCH_MVAX3L 164
48 #define CRUNCH_MVAX3M 168
49 #define CRUNCH_MVAX3H 172
50 #define CRUNCH_DSPSC 176
51
52 #define CRUNCH_SIZE 184
53
54 .text
55
56 /*
57 * Lazy switching of crunch coprocessor context
58 *
59 * r10 = struct thread_info pointer
60 * r9 = ret_from_exception
61 * lr = undefined instr exit
62 *
63 * called from prefetch exception handler with interrupts enabled
64 */
65 ENTRY(crunch_task_enable)
66 inc_preempt_count r10, r3
67
68 ldr r8, =(EP93XX_APB_VIRT_BASE + 0x00130000) @ syscon addr
69
70 ldr r1, [r8, #0x80]
71 tst r1, #0x00800000 @ access to crunch enabled?
72 bne 2f @ if so no business here
73 mov r3, #0xaa @ unlock syscon swlock
74 str r3, [r8, #0xc0]
75 orr r1, r1, #0x00800000 @ enable access to crunch
76 str r1, [r8, #0x80]
77
78 ldr r3, =crunch_owner
79 add r0, r10, #TI_CRUNCH_STATE @ get task crunch save area
80 ldr r2, [sp, #60] @ current task pc value
81 ldr r1, [r3] @ get current crunch owner
82 str r0, [r3] @ this task now owns crunch
83 sub r2, r2, #4 @ adjust pc back
84 str r2, [sp, #60]
85
86 ldr r2, [r8, #0x80]
87 mov r2, r2 @ flush out enable (@@@)
88
89 teq r1, #0 @ test for last ownership
90 mov lr, r9 @ normal exit from exception
91 beq crunch_load @ no owner, skip save
92
93 crunch_save:
94 cfstr64 mvdx0, [r1, #CRUNCH_MVDX0] @ save 64b registers
95 cfstr64 mvdx1, [r1, #CRUNCH_MVDX1]
96 cfstr64 mvdx2, [r1, #CRUNCH_MVDX2]
97 cfstr64 mvdx3, [r1, #CRUNCH_MVDX3]
98 cfstr64 mvdx4, [r1, #CRUNCH_MVDX4]
99 cfstr64 mvdx5, [r1, #CRUNCH_MVDX5]
100 cfstr64 mvdx6, [r1, #CRUNCH_MVDX6]
101 cfstr64 mvdx7, [r1, #CRUNCH_MVDX7]
102 cfstr64 mvdx8, [r1, #CRUNCH_MVDX8]
103 cfstr64 mvdx9, [r1, #CRUNCH_MVDX9]
104 cfstr64 mvdx10, [r1, #CRUNCH_MVDX10]
105 cfstr64 mvdx11, [r1, #CRUNCH_MVDX11]
106 cfstr64 mvdx12, [r1, #CRUNCH_MVDX12]
107 cfstr64 mvdx13, [r1, #CRUNCH_MVDX13]
108 cfstr64 mvdx14, [r1, #CRUNCH_MVDX14]
109 cfstr64 mvdx15, [r1, #CRUNCH_MVDX15]
110
111 #ifdef __ARMEB__
112 #error fix me for ARMEB
113 #endif
114
115 cfmv32al mvfx0, mvax0 @ save 72b accumulators
116 cfstr32 mvfx0, [r1, #CRUNCH_MVAX0L]
117 cfmv32am mvfx0, mvax0
118 cfstr32 mvfx0, [r1, #CRUNCH_MVAX0M]
119 cfmv32ah mvfx0, mvax0
120 cfstr32 mvfx0, [r1, #CRUNCH_MVAX0H]
121 cfmv32al mvfx0, mvax1
122 cfstr32 mvfx0, [r1, #CRUNCH_MVAX1L]
123 cfmv32am mvfx0, mvax1
124 cfstr32 mvfx0, [r1, #CRUNCH_MVAX1M]
125 cfmv32ah mvfx0, mvax1
126 cfstr32 mvfx0, [r1, #CRUNCH_MVAX1H]
127 cfmv32al mvfx0, mvax2
128 cfstr32 mvfx0, [r1, #CRUNCH_MVAX2L]
129 cfmv32am mvfx0, mvax2
130 cfstr32 mvfx0, [r1, #CRUNCH_MVAX2M]
131 cfmv32ah mvfx0, mvax2
132 cfstr32 mvfx0, [r1, #CRUNCH_MVAX2H]
133 cfmv32al mvfx0, mvax3
134 cfstr32 mvfx0, [r1, #CRUNCH_MVAX3L]
135 cfmv32am mvfx0, mvax3
136 cfstr32 mvfx0, [r1, #CRUNCH_MVAX3M]
137 cfmv32ah mvfx0, mvax3
138 cfstr32 mvfx0, [r1, #CRUNCH_MVAX3H]
139
140 cfmv32sc mvdx0, dspsc @ save status word
141 cfstr64 mvdx0, [r1, #CRUNCH_DSPSC]
142
143 teq r0, #0 @ anything to load?
144 cfldr64eq mvdx0, [r1, #CRUNCH_MVDX0] @ mvdx0 was clobbered
145 beq 1f
146
147 crunch_load:
148 cfldr64 mvdx0, [r0, #CRUNCH_DSPSC] @ load status word
149 cfmvsc32 dspsc, mvdx0
150
151 cfldr32 mvfx0, [r0, #CRUNCH_MVAX0L] @ load 72b accumulators
152 cfmval32 mvax0, mvfx0
153 cfldr32 mvfx0, [r0, #CRUNCH_MVAX0M]
154 cfmvam32 mvax0, mvfx0
155 cfldr32 mvfx0, [r0, #CRUNCH_MVAX0H]
156 cfmvah32 mvax0, mvfx0
157 cfldr32 mvfx0, [r0, #CRUNCH_MVAX1L]
158 cfmval32 mvax1, mvfx0
159 cfldr32 mvfx0, [r0, #CRUNCH_MVAX1M]
160 cfmvam32 mvax1, mvfx0
161 cfldr32 mvfx0, [r0, #CRUNCH_MVAX1H]
162 cfmvah32 mvax1, mvfx0
163 cfldr32 mvfx0, [r0, #CRUNCH_MVAX2L]
164 cfmval32 mvax2, mvfx0
165 cfldr32 mvfx0, [r0, #CRUNCH_MVAX2M]
166 cfmvam32 mvax2, mvfx0
167 cfldr32 mvfx0, [r0, #CRUNCH_MVAX2H]
168 cfmvah32 mvax2, mvfx0
169 cfldr32 mvfx0, [r0, #CRUNCH_MVAX3L]
170 cfmval32 mvax3, mvfx0
171 cfldr32 mvfx0, [r0, #CRUNCH_MVAX3M]
172 cfmvam32 mvax3, mvfx0
173 cfldr32 mvfx0, [r0, #CRUNCH_MVAX3H]
174 cfmvah32 mvax3, mvfx0
175
176 cfldr64 mvdx0, [r0, #CRUNCH_MVDX0] @ load 64b registers
177 cfldr64 mvdx1, [r0, #CRUNCH_MVDX1]
178 cfldr64 mvdx2, [r0, #CRUNCH_MVDX2]
179 cfldr64 mvdx3, [r0, #CRUNCH_MVDX3]
180 cfldr64 mvdx4, [r0, #CRUNCH_MVDX4]
181 cfldr64 mvdx5, [r0, #CRUNCH_MVDX5]
182 cfldr64 mvdx6, [r0, #CRUNCH_MVDX6]
183 cfldr64 mvdx7, [r0, #CRUNCH_MVDX7]
184 cfldr64 mvdx8, [r0, #CRUNCH_MVDX8]
185 cfldr64 mvdx9, [r0, #CRUNCH_MVDX9]
186 cfldr64 mvdx10, [r0, #CRUNCH_MVDX10]
187 cfldr64 mvdx11, [r0, #CRUNCH_MVDX11]
188 cfldr64 mvdx12, [r0, #CRUNCH_MVDX12]
189 cfldr64 mvdx13, [r0, #CRUNCH_MVDX13]
190 cfldr64 mvdx14, [r0, #CRUNCH_MVDX14]
191 cfldr64 mvdx15, [r0, #CRUNCH_MVDX15]
192
193 1:
194 #ifdef CONFIG_PREEMPT_COUNT
195 get_thread_info r10
196 #endif
197 2: dec_preempt_count r10, r3
198 ret lr
199
200 /*
201 * Back up crunch regs to save area and disable access to them
202 * (mainly for gdb or sleep mode usage)
203 *
204 * r0 = struct thread_info pointer of target task or NULL for any
205 */
206 ENTRY(crunch_task_disable)
207 stmfd sp!, {r4, r5, lr}
208
209 mrs ip, cpsr
210 orr r2, ip, #PSR_I_BIT @ disable interrupts
211 msr cpsr_c, r2
212
213 ldr r4, =(EP93XX_APB_VIRT_BASE + 0x00130000) @ syscon addr
214
215 ldr r3, =crunch_owner
216 add r2, r0, #TI_CRUNCH_STATE @ get task crunch save area
217 ldr r1, [r3] @ get current crunch owner
218 teq r1, #0 @ any current owner?
219 beq 1f @ no: quit
220 teq r0, #0 @ any owner?
221 teqne r1, r2 @ or specified one?
222 bne 1f @ no: quit
223
224 ldr r5, [r4, #0x80] @ enable access to crunch
225 mov r2, #0xaa
226 str r2, [r4, #0xc0]
227 orr r5, r5, #0x00800000
228 str r5, [r4, #0x80]
229
230 mov r0, #0 @ nothing to load
231 str r0, [r3] @ no more current owner
232 ldr r2, [r4, #0x80] @ flush out enable (@@@)
233 mov r2, r2
234 bl crunch_save
235
236 mov r2, #0xaa @ disable access to crunch
237 str r2, [r4, #0xc0]
238 bic r5, r5, #0x00800000
239 str r5, [r4, #0x80]
240 ldr r5, [r4, #0x80] @ flush out enable (@@@)
241 mov r5, r5
242
243 1: msr cpsr_c, ip @ restore interrupt mode
244 ldmfd sp!, {r4, r5, pc}
245
246 /*
247 * Copy crunch state to given memory address
248 *
249 * r0 = struct thread_info pointer of target task
250 * r1 = memory address where to store crunch state
251 *
252 * this is called mainly in the creation of signal stack frames
253 */
254 ENTRY(crunch_task_copy)
255 mrs ip, cpsr
256 orr r2, ip, #PSR_I_BIT @ disable interrupts
257 msr cpsr_c, r2
258
259 ldr r3, =crunch_owner
260 add r2, r0, #TI_CRUNCH_STATE @ get task crunch save area
261 ldr r3, [r3] @ get current crunch owner
262 teq r2, r3 @ does this task own it...
263 beq 1f
264
265 @ current crunch values are in the task save area
266 msr cpsr_c, ip @ restore interrupt mode
267 mov r0, r1
268 mov r1, r2
269 mov r2, #CRUNCH_SIZE
270 b memcpy
271
272 1: @ this task owns crunch regs -- grab a copy from there
273 mov r0, #0 @ nothing to load
274 mov r3, lr @ preserve return address
275 bl crunch_save
276 msr cpsr_c, ip @ restore interrupt mode
277 ret r3
278
279 /*
280 * Restore crunch state from given memory address
281 *
282 * r0 = struct thread_info pointer of target task
283 * r1 = memory address where to get crunch state from
284 *
285 * this is used to restore crunch state when unwinding a signal stack frame
286 */
287 ENTRY(crunch_task_restore)
288 mrs ip, cpsr
289 orr r2, ip, #PSR_I_BIT @ disable interrupts
290 msr cpsr_c, r2
291
292 ldr r3, =crunch_owner
293 add r2, r0, #TI_CRUNCH_STATE @ get task crunch save area
294 ldr r3, [r3] @ get current crunch owner
295 teq r2, r3 @ does this task own it...
296 beq 1f
297
298 @ this task doesn't own crunch regs -- use its save area
299 msr cpsr_c, ip @ restore interrupt mode
300 mov r0, r2
301 mov r2, #CRUNCH_SIZE
302 b memcpy
303
304 1: @ this task owns crunch regs -- load them directly
305 mov r0, r1
306 mov r1, #0 @ nothing to save
307 mov r3, lr @ preserve return address
308 bl crunch_load
309 msr cpsr_c, ip @ restore interrupt mode
310 ret r3