Merge commit 'v2.6.30-rc1' into perfcounters/core
[linux-2.6] / arch / blackfin / mach-bf561 / secondary.S
1 /*
2  * File:         arch/blackfin/mach-bf561/secondary.S
3  * Based on:     arch/blackfin/mach-bf561/head.S
4  * Author:       Philippe Gerum <rpm@xenomai.org>
5  *
6  *               Copyright 2007 Analog Devices Inc.
7  *
8  * Description:  BF561 coreB bootstrap file
9  *
10  * This program is free software; you can redistribute it and/or modify
11  * it under the terms of the GNU General Public License as published by
12  * the Free Software Foundation; either version 2 of the License, or
13  * (at your option) any later version.
14  *
15  * This program is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  * GNU General Public License for more details.
19  *
20  * You should have received a copy of the GNU General Public License
21  * along with this program; if not, see the file COPYING, or write
22  * to the Free Software Foundation, Inc.,
23  * 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
24  */
25
26 #include <linux/linkage.h>
27 #include <linux/init.h>
28 #include <asm/blackfin.h>
29 #include <asm/asm-offsets.h>
30
31 __INIT
32
33 /* Lay the initial stack into the L1 scratch area of Core B */
34 #define INITIAL_STACK   (COREB_L1_SCRATCH_START + L1_SCRATCH_LENGTH - 12)
35
36 ENTRY(_coreb_trampoline_start)
37         /* Set the SYSCFG register */
38         R0 = 0x36;
39         SYSCFG = R0; /*Enable Cycle Counter and Nesting Of Interrupts(3rd Bit)*/
40         R0 = 0;
41
42         /*Clear Out All the data and pointer  Registers*/
43         R1 = R0;
44         R2 = R0;
45         R3 = R0;
46         R4 = R0;
47         R5 = R0;
48         R6 = R0;
49         R7 = R0;
50
51         P0 = R0;
52         P1 = R0;
53         P2 = R0;
54         P3 = R0;
55         P4 = R0;
56         P5 = R0;
57
58         LC0 = r0;
59         LC1 = r0;
60         L0 = r0;
61         L1 = r0;
62         L2 = r0;
63         L3 = r0;
64
65         /* Clear Out All the DAG Registers*/
66         B0 = r0;
67         B1 = r0;
68         B2 = r0;
69         B3 = r0;
70
71         I0 = r0;
72         I1 = r0;
73         I2 = r0;
74         I3 = r0;
75
76         M0 = r0;
77         M1 = r0;
78         M2 = r0;
79         M3 = r0;
80
81         /* Turn off the icache */
82         p0.l = LO(IMEM_CONTROL);
83         p0.h = HI(IMEM_CONTROL);
84         R1 = [p0];
85         R0 = ~ENICPLB;
86         R0 = R0 & R1;
87
88         /* Anomaly 05000125 */
89 #ifdef ANOMALY_05000125
90         CLI R2;
91         SSYNC;
92 #endif
93         [p0] = R0;
94         SSYNC;
95 #ifdef ANOMALY_05000125
96         STI R2;
97 #endif
98
99         /* Turn off the dcache */
100         p0.l = LO(DMEM_CONTROL);
101         p0.h = HI(DMEM_CONTROL);
102         R1 = [p0];
103         R0 = ~ENDCPLB;
104         R0 = R0 & R1;
105
106         /* Anomaly 05000125 */
107 #ifdef ANOMALY_05000125
108         CLI R2;
109         SSYNC;
110 #endif
111         [p0] = R0;
112         SSYNC;
113 #ifdef ANOMALY_05000125
114         STI R2;
115 #endif
116
117         /* in case of double faults, save a few things */
118         p0.l = _init_retx_coreb;
119         p0.h = _init_retx_coreb;
120         R0 = RETX;
121         [P0] = R0;
122
123 #ifdef CONFIG_DEBUG_DOUBLEFAULT
124         /* Only save these if we are storing them,
125          * This happens here, since L1 gets clobbered
126          * below
127          */
128         GET_PDA(p0, r0);
129         r7 = [p0 + PDA_RETX];
130         p1.l = _init_saved_retx_coreb;
131         p1.h = _init_saved_retx_coreb;
132         [p1] = r7;
133
134         r7 = [p0 + PDA_DCPLB];
135         p1.l = _init_saved_dcplb_fault_addr_coreb;
136         p1.h = _init_saved_dcplb_fault_addr_coreb;
137         [p1] = r7;
138
139         r7 = [p0 + PDA_ICPLB];
140         p1.l = _init_saved_icplb_fault_addr_coreb;
141         p1.h = _init_saved_icplb_fault_addr_coreb;
142         [p1] = r7;
143
144         r7 = [p0 + PDA_SEQSTAT];
145         p1.l = _init_saved_seqstat_coreb;
146         p1.h = _init_saved_seqstat_coreb;
147         [p1] = r7;
148 #endif
149
150         /* Initialize stack pointer */
151         sp.l = lo(INITIAL_STACK);
152         sp.h = hi(INITIAL_STACK);
153         fp = sp;
154         usp = sp;
155
156         /* This section keeps the processor in supervisor mode
157          * during core B startup.  Branches to the idle task.
158          */
159
160         /* EVT15 = _real_start */
161
162         p0.l = lo(EVT15);
163         p0.h = hi(EVT15);
164         p1.l = _coreb_start;
165         p1.h = _coreb_start;
166         [p0] = p1;
167         csync;
168
169         p0.l = lo(IMASK);
170         p0.h = hi(IMASK);
171         p1.l = IMASK_IVG15;
172         p1.h = 0x0;
173         [p0] = p1;
174         csync;
175
176         raise 15;
177         p0.l = .LWAIT_HERE;
178         p0.h = .LWAIT_HERE;
179         reti = p0;
180 #if defined(ANOMALY_05000281)
181         nop; nop; nop;
182 #endif
183         rti;
184
185 .LWAIT_HERE:
186         jump .LWAIT_HERE;
187 ENDPROC(_coreb_trampoline_start)
188 ENTRY(_coreb_trampoline_end)
189
190 ENTRY(_coreb_start)
191         [--sp] = reti;
192
193         p0.l = lo(WDOGB_CTL);
194         p0.h = hi(WDOGB_CTL);
195         r0 = 0xAD6(z);
196         w[p0] = r0;     /* Clear the watchdog. */
197         ssync;
198
199         /*
200          * switch to IDLE stack.
201          */
202         p0.l = _secondary_stack;
203         p0.h = _secondary_stack;
204         sp = [p0];
205         usp = sp;
206         fp = sp;
207         sp += -12;
208         call _init_pda
209         sp += 12;
210         call _secondary_start_kernel;
211 .L_exit:
212         jump.s  .L_exit;
213 ENDPROC(_coreb_start)
214
215 __FINIT