docs: sphinx-requirements: Move sphinx_rtd_theme to top
[linux-2.6-microblaze.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