ia64: allocate percpu area for cpu0 like percpu areas for other cpus
[linux-2.6.git] / 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         /* Disabling of CPLBs should be proceeded by a CSYNC */
89         CSYNC;
90         [p0] = R0;
91         SSYNC;
92
93         /* Turn off the dcache */
94         p0.l = LO(DMEM_CONTROL);
95         p0.h = HI(DMEM_CONTROL);
96         R1 = [p0];
97         R0 = ~ENDCPLB;
98         R0 = R0 & R1;
99
100         /* Disabling of CPLBs should be proceeded by a CSYNC */
101         CSYNC;
102         [p0] = R0;
103         SSYNC;
104
105         /* in case of double faults, save a few things */
106         p0.l = _init_retx_coreb;
107         p0.h = _init_retx_coreb;
108         R0 = RETX;
109         [P0] = R0;
110
111 #ifdef CONFIG_DEBUG_DOUBLEFAULT
112         /* Only save these if we are storing them,
113          * This happens here, since L1 gets clobbered
114          * below
115          */
116         GET_PDA(p0, r0);
117         r7 = [p0 + PDA_DF_RETX];
118         p1.l = _init_saved_retx_coreb;
119         p1.h = _init_saved_retx_coreb;
120         [p1] = r7;
121
122         r7 = [p0 + PDA_DF_DCPLB];
123         p1.l = _init_saved_dcplb_fault_addr_coreb;
124         p1.h = _init_saved_dcplb_fault_addr_coreb;
125         [p1] = r7;
126
127         r7 = [p0 + PDA_DF_ICPLB];
128         p1.l = _init_saved_icplb_fault_addr_coreb;
129         p1.h = _init_saved_icplb_fault_addr_coreb;
130         [p1] = r7;
131
132         r7 = [p0 + PDA_DF_SEQSTAT];
133         p1.l = _init_saved_seqstat_coreb;
134         p1.h = _init_saved_seqstat_coreb;
135         [p1] = r7;
136 #endif
137
138         /* Initialize stack pointer */
139         sp.l = lo(INITIAL_STACK);
140         sp.h = hi(INITIAL_STACK);
141         fp = sp;
142         usp = sp;
143
144         /* This section keeps the processor in supervisor mode
145          * during core B startup.  Branches to the idle task.
146          */
147
148         /* EVT15 = _real_start */
149
150         p0.l = lo(EVT15);
151         p0.h = hi(EVT15);
152         p1.l = _coreb_start;
153         p1.h = _coreb_start;
154         [p0] = p1;
155         csync;
156
157         p0.l = lo(IMASK);
158         p0.h = hi(IMASK);
159         p1.l = IMASK_IVG15;
160         p1.h = 0x0;
161         [p0] = p1;
162         csync;
163
164         raise 15;
165         p0.l = .LWAIT_HERE;
166         p0.h = .LWAIT_HERE;
167         reti = p0;
168 #if defined(ANOMALY_05000281)
169         nop; nop; nop;
170 #endif
171         rti;
172
173 .LWAIT_HERE:
174         jump .LWAIT_HERE;
175 ENDPROC(_coreb_trampoline_start)
176 ENTRY(_coreb_trampoline_end)
177
178 ENTRY(_coreb_start)
179         [--sp] = reti;
180
181         p0.l = lo(WDOGB_CTL);
182         p0.h = hi(WDOGB_CTL);
183         r0 = 0xAD6(z);
184         w[p0] = r0;     /* Clear the watchdog. */
185         ssync;
186
187         /*
188          * switch to IDLE stack.
189          */
190         p0.l = _secondary_stack;
191         p0.h = _secondary_stack;
192         sp = [p0];
193         usp = sp;
194         fp = sp;
195         sp += -12;
196         call _init_pda
197         sp += 12;
198         call _secondary_start_kernel;
199 .L_exit:
200         jump.s  .L_exit;
201 ENDPROC(_coreb_start)
202
203 __FINIT