dt-bindings: arm: rockchip: remove reference to fennec board
[sfrench/cifs-2.6.git] / arch / xtensa / kernel / coprocessor.S
1 /*
2  * arch/xtensa/kernel/coprocessor.S
3  *
4  * Xtensa processor configuration-specific table of coprocessor and
5  * other custom register layout information.
6  *
7  * This file is subject to the terms and conditions of the GNU General Public
8  * License.  See the file "COPYING" in the main directory of this archive
9  * for more details.
10  *
11  * Copyright (C) 2003 - 2007 Tensilica Inc.
12  */
13
14
15 #include <linux/linkage.h>
16 #include <asm/asm-offsets.h>
17 #include <asm/processor.h>
18 #include <asm/coprocessor.h>
19 #include <asm/thread_info.h>
20 #include <asm/asm-uaccess.h>
21 #include <asm/unistd.h>
22 #include <asm/ptrace.h>
23 #include <asm/current.h>
24 #include <asm/pgtable.h>
25 #include <asm/page.h>
26 #include <asm/signal.h>
27 #include <asm/tlbflush.h>
28
29 #if XTENSA_HAVE_COPROCESSORS
30
31 /*
32  * Macros for lazy context switch. 
33  */
34
35 #define SAVE_CP_REGS(x)                                                 \
36         .if XTENSA_HAVE_COPROCESSOR(x);                                 \
37                 .align 4;                                               \
38         .Lsave_cp_regs_cp##x:                                           \
39                 xchal_cp##x##_store a2 a4 a5 a6 a7;                     \
40                 jx      a0;                                             \
41         .endif
42
43 #define SAVE_CP_REGS_TAB(x)                                             \
44         .if XTENSA_HAVE_COPROCESSOR(x);                                 \
45                 .long .Lsave_cp_regs_cp##x;                             \
46         .else;                                                          \
47                 .long 0;                                                \
48         .endif;                                                         \
49         .long THREAD_XTREGS_CP##x
50
51
52 #define LOAD_CP_REGS(x)                                                 \
53         .if XTENSA_HAVE_COPROCESSOR(x);                                 \
54                 .align 4;                                               \
55         .Lload_cp_regs_cp##x:                                           \
56                 xchal_cp##x##_load a2 a4 a5 a6 a7;                      \
57                 jx      a0;                                             \
58         .endif
59
60 #define LOAD_CP_REGS_TAB(x)                                             \
61         .if XTENSA_HAVE_COPROCESSOR(x);                                 \
62                 .long .Lload_cp_regs_cp##x;                             \
63         .else;                                                          \
64                 .long 0;                                                \
65         .endif;                                                         \
66         .long THREAD_XTREGS_CP##x
67
68         SAVE_CP_REGS(0)
69         SAVE_CP_REGS(1)
70         SAVE_CP_REGS(2)
71         SAVE_CP_REGS(3)
72         SAVE_CP_REGS(4)
73         SAVE_CP_REGS(5)
74         SAVE_CP_REGS(6)
75         SAVE_CP_REGS(7)
76
77         LOAD_CP_REGS(0)
78         LOAD_CP_REGS(1)
79         LOAD_CP_REGS(2)
80         LOAD_CP_REGS(3)
81         LOAD_CP_REGS(4)
82         LOAD_CP_REGS(5)
83         LOAD_CP_REGS(6)
84         LOAD_CP_REGS(7)
85
86         .section ".rodata", "a"
87         .align 4
88 .Lsave_cp_regs_jump_table:
89         SAVE_CP_REGS_TAB(0)
90         SAVE_CP_REGS_TAB(1)
91         SAVE_CP_REGS_TAB(2)
92         SAVE_CP_REGS_TAB(3)
93         SAVE_CP_REGS_TAB(4)
94         SAVE_CP_REGS_TAB(5)
95         SAVE_CP_REGS_TAB(6)
96         SAVE_CP_REGS_TAB(7)
97
98 .Lload_cp_regs_jump_table:
99         LOAD_CP_REGS_TAB(0)
100         LOAD_CP_REGS_TAB(1)
101         LOAD_CP_REGS_TAB(2)
102         LOAD_CP_REGS_TAB(3)
103         LOAD_CP_REGS_TAB(4)
104         LOAD_CP_REGS_TAB(5)
105         LOAD_CP_REGS_TAB(6)
106         LOAD_CP_REGS_TAB(7)
107
108         .previous
109
110 /*
111  * coprocessor_flush(struct thread_info*, index)
112  *                             a2        a3
113  *
114  * Save coprocessor registers for coprocessor 'index'.
115  * The register values are saved to or loaded from the coprocessor area 
116  * inside the task_info structure.
117  *
118  * Note that this function doesn't update the coprocessor_owner information!
119  *
120  */
121
122 ENTRY(coprocessor_flush)
123
124         /* reserve 4 bytes on stack to save a0 */
125         abi_entry(4)
126
127         s32i    a0, a1, 0
128         movi    a0, .Lsave_cp_regs_jump_table
129         addx8   a3, a3, a0
130         l32i    a4, a3, 4
131         l32i    a3, a3, 0
132         add     a2, a2, a4
133         beqz    a3, 1f
134         callx0  a3
135 1:      l32i    a0, a1, 0
136
137         abi_ret(4)
138
139 ENDPROC(coprocessor_flush)
140
141 /*
142  * Entry condition:
143  *
144  *   a0:        trashed, original value saved on stack (PT_AREG0)
145  *   a1:        a1
146  *   a2:        new stack pointer, original in DEPC
147  *   a3:        a3
148  *   depc:      a2, original value saved on stack (PT_DEPC)
149  *   excsave_1: dispatch table
150  *
151  *   PT_DEPC >= VALID_DOUBLE_EXCEPTION_ADDRESS: double exception, DEPC
152  *           <  VALID_DOUBLE_EXCEPTION_ADDRESS: regular exception
153  */
154
155 ENTRY(fast_coprocessor_double)
156
157         wsr     a0, excsave1
158         call0   unrecoverable_exception
159
160 ENDPROC(fast_coprocessor_double)
161
162 ENTRY(fast_coprocessor)
163
164         /* Save remaining registers a1-a3 and SAR */
165
166         s32i    a3, a2, PT_AREG3
167         rsr     a3, sar
168         s32i    a1, a2, PT_AREG1
169         s32i    a3, a2, PT_SAR
170         mov     a1, a2
171         rsr     a2, depc
172         s32i    a2, a1, PT_AREG2
173
174         /*
175          * The hal macros require up to 4 temporary registers. We use a3..a6.
176          */
177
178         s32i    a4, a1, PT_AREG4
179         s32i    a5, a1, PT_AREG5
180         s32i    a6, a1, PT_AREG6
181
182         /* Find coprocessor number. Subtract first CP EXCCAUSE from EXCCAUSE */
183
184         rsr     a3, exccause
185         addi    a3, a3, -EXCCAUSE_COPROCESSOR0_DISABLED
186
187         /* Set corresponding CPENABLE bit -> (sar:cp-index, a3: 1<<cp-index)*/
188
189         ssl     a3                      # SAR: 32 - coprocessor_number
190         movi    a2, 1
191         rsr     a0, cpenable
192         sll     a2, a2
193         or      a0, a0, a2
194         wsr     a0, cpenable
195         rsync
196
197         /* Retrieve previous owner. (a3 still holds CP number) */
198
199         movi    a0, coprocessor_owner   # list of owners
200         addx4   a0, a3, a0              # entry for CP
201         l32i    a4, a0, 0
202
203         beqz    a4, 1f                  # skip 'save' if no previous owner
204
205         /* Disable coprocessor for previous owner. (a2 = 1 << CP number) */
206
207         l32i    a5, a4, THREAD_CPENABLE
208         xor     a5, a5, a2              # (1 << cp-id) still in a2
209         s32i    a5, a4, THREAD_CPENABLE
210
211         /*
212          * Get context save area and 'call' save routine. 
213          * (a4 still holds previous owner (thread_info), a3 CP number)
214          */
215
216         movi    a5, .Lsave_cp_regs_jump_table
217         movi    a0, 2f                  # a0: 'return' address
218         addx8   a3, a3, a5              # a3: coprocessor number
219         l32i    a2, a3, 4               # a2: xtregs offset
220         l32i    a3, a3, 0               # a3: jump address
221         add     a2, a2, a4
222         jx      a3
223
224         /* Note that only a0 and a1 were preserved. */
225
226 2:      rsr     a3, exccause
227         addi    a3, a3, -EXCCAUSE_COPROCESSOR0_DISABLED
228         movi    a0, coprocessor_owner
229         addx4   a0, a3, a0
230
231         /* Set new 'owner' (a0 points to the CP owner, a3 contains the CP nr) */
232
233 1:      GET_THREAD_INFO (a4, a1)
234         s32i    a4, a0, 0
235
236         /* Get context save area and 'call' load routine. */
237
238         movi    a5, .Lload_cp_regs_jump_table
239         movi    a0, 1f
240         addx8   a3, a3, a5
241         l32i    a2, a3, 4               # a2: xtregs offset
242         l32i    a3, a3, 0               # a3: jump address
243         add     a2, a2, a4
244         jx      a3
245
246         /* Restore all registers and return from exception handler. */
247
248 1:      l32i    a6, a1, PT_AREG6
249         l32i    a5, a1, PT_AREG5
250         l32i    a4, a1, PT_AREG4
251
252         l32i    a0, a1, PT_SAR
253         l32i    a3, a1, PT_AREG3
254         l32i    a2, a1, PT_AREG2
255         wsr     a0, sar
256         l32i    a0, a1, PT_AREG0
257         l32i    a1, a1, PT_AREG1
258
259         rfe
260
261 ENDPROC(fast_coprocessor)
262
263         .data
264
265 ENTRY(coprocessor_owner)
266
267         .fill XCHAL_CP_MAX, 4, 0
268
269 END(coprocessor_owner)
270
271 #endif /* XTENSA_HAVE_COPROCESSORS */