]> git.karo-electronics.de Git - karo-tx-linux.git/blob - arch/blackfin/mach-bf561/secondary.S
Blackfin: SMP: optimize start up code a bit
[karo-tx-linux.git] / arch / blackfin / mach-bf561 / secondary.S
1 /*
2  * BF561 coreB bootstrap file
3  *
4  * Copyright 2007-2009 Analog Devices Inc.
5  *               Philippe Gerum <rpm@xenomai.org>
6  *
7  * Licensed under the GPL-2 or later.
8  */
9
10 #include <linux/linkage.h>
11 #include <linux/init.h>
12 #include <asm/blackfin.h>
13 #include <asm/asm-offsets.h>
14 #include <asm/trace.h>
15
16 /*
17  * This code must come first as CoreB is hardcoded (in hardware)
18  * to start at the beginning of its L1 instruction memory.
19  */
20 .section .l1.text.head
21
22 /* Lay the initial stack into the L1 scratch area of Core B */
23 #define INITIAL_STACK   (COREB_L1_SCRATCH_START + L1_SCRATCH_LENGTH - 12)
24
25 ENTRY(_coreb_trampoline_start)
26         /* Enable Cycle Counter and Nesting Of Interrupts */
27 #ifdef CONFIG_BFIN_SCRATCH_REG_CYCLES
28         R0 = SYSCFG_SNEN;
29 #else
30         R0 = SYSCFG_SNEN | SYSCFG_CCEN;
31 #endif
32         SYSCFG = R0;
33
34         /* Optimization register tricks: keep a base value in the
35          * reserved P registers so we use the load/store with an
36          * offset syntax.  R0 = [P5 + <constant>];
37          *   P5 - core MMR base
38          *   R6 - 0
39          */
40         r6 = 0;
41         p5.l = 0;
42         p5.h = hi(COREMMR_BASE);
43
44         /* Zero out registers required by Blackfin ABI */
45
46         /* Disable circular buffers */
47         L0 = r6;
48         L1 = r6;
49         L2 = r6;
50         L3 = r6;
51
52         /* Disable hardware loops in case we were started by 'go' */
53         LC0 = r6;
54         LC1 = r6;
55
56         /*
57          * Clear ITEST_COMMAND and DTEST_COMMAND registers,
58          * Leaving these as non-zero can confuse the emulator
59          */
60         [p5 + (DTEST_COMMAND - COREMMR_BASE)] = r6;
61         [p5 + (ITEST_COMMAND - COREMMR_BASE)] = r6;
62         CSYNC;
63
64         trace_buffer_init(p0,r0);
65
66         /* Turn off the icache */
67         r1 = [p5 + (IMEM_CONTROL - COREMMR_BASE)];
68         BITCLR (r1, ENICPLB_P);
69         [p5 + (IMEM_CONTROL - COREMMR_BASE)] = r1;
70         SSYNC;
71
72         /* Turn off the dcache */
73         r1 = [p5 + (DMEM_CONTROL - COREMMR_BASE)];
74         BITCLR (r1, ENDCPLB_P);
75         [p5 + (DMEM_CONTROL - COREMMR_BASE)] = r1;
76         SSYNC;
77
78         /* in case of double faults, save a few things */
79         p0.l = _init_retx_coreb;
80         p0.h = _init_retx_coreb;
81         R0 = RETX;
82         [P0] = R0;
83
84 #ifdef CONFIG_DEBUG_DOUBLEFAULT
85         /* Only save these if we are storing them,
86          * This happens here, since L1 gets clobbered
87          * below
88          */
89         GET_PDA(p0, r0);
90         r5 = [p0 + PDA_DF_RETX];
91         p1.l = _init_saved_retx_coreb;
92         p1.h = _init_saved_retx_coreb;
93         [p1] = r5;
94
95         r5 = [p0 + PDA_DF_DCPLB];
96         p1.l = _init_saved_dcplb_fault_addr_coreb;
97         p1.h = _init_saved_dcplb_fault_addr_coreb;
98         [p1] = r5;
99
100         r5 = [p0 + PDA_DF_ICPLB];
101         p1.l = _init_saved_icplb_fault_addr_coreb;
102         p1.h = _init_saved_icplb_fault_addr_coreb;
103         [p1] = r5;
104
105         r5 = [p0 + PDA_DF_SEQSTAT];
106         p1.l = _init_saved_seqstat_coreb;
107         p1.h = _init_saved_seqstat_coreb;
108         [p1] = r5;
109 #endif
110
111         /* Initialize stack pointer */
112         sp.l = lo(INITIAL_STACK);
113         sp.h = hi(INITIAL_STACK);
114         fp = sp;
115         usp = sp;
116
117         /* This section keeps the processor in supervisor mode
118          * during core B startup.  Branches to the idle task.
119          */
120
121         /* EVT15 = _real_start */
122
123         p1.l = _coreb_start;
124         p1.h = _coreb_start;
125         [p5 + (EVT15 - COREMMR_BASE)] = p1;
126         csync;
127
128         r0 = EVT_IVG15 (z);
129         sti r0;
130
131         raise 15;
132         p0.l = .LWAIT_HERE;
133         p0.h = .LWAIT_HERE;
134         reti = p0;
135 #if defined(ANOMALY_05000281)
136         nop; nop; nop;
137 #endif
138         rti;
139
140 .LWAIT_HERE:
141         jump .LWAIT_HERE;
142 ENDPROC(_coreb_trampoline_start)
143
144 #ifdef CONFIG_HOTPLUG_CPU
145 .section ".text"
146 ENTRY(_coreb_die)
147         sp.l = lo(INITIAL_STACK);
148         sp.h = hi(INITIAL_STACK);
149         fp = sp;
150         usp = sp;
151
152         CLI R2;
153         SSYNC;
154         IDLE;
155         STI R2;
156
157         R0 = IWR_DISABLE_ALL;
158         P0.H = hi(SYSMMR_BASE);
159         P0.L = lo(SYSMMR_BASE);
160         [P0 + (SICB_IWR0 - SYSMMR_BASE)] = R0;
161         [P0 + (SICB_IWR1 - SYSMMR_BASE)] = R0;
162         SSYNC;
163
164         p0.h = hi(COREB_L1_CODE_START);
165         p0.l = lo(COREB_L1_CODE_START);
166         jump (p0);
167 ENDPROC(_coreb_die)
168 #endif
169
170 __INIT
171 ENTRY(_coreb_start)
172         [--sp] = reti;
173
174         p0.l = lo(WDOGB_CTL);
175         p0.h = hi(WDOGB_CTL);
176         r0 = 0xAD6(z);
177         w[p0] = r0;     /* Clear the watchdog. */
178         ssync;
179
180         /*
181          * switch to IDLE stack.
182          */
183         p0.l = _secondary_stack;
184         p0.h = _secondary_stack;
185         sp = [p0];
186         usp = sp;
187         fp = sp;
188 #ifdef CONFIG_HOTPLUG_CPU
189         p0.l = _hotplug_coreb;
190         p0.h = _hotplug_coreb;
191         r0 = [p0];
192         cc = BITTST(r0, 0);
193         if cc jump 3f;
194 #endif
195         sp += -12;
196         call _init_pda
197         sp += 12;
198 #ifdef CONFIG_HOTPLUG_CPU
199 3:
200 #endif
201         call _secondary_start_kernel;
202 .L_exit:
203         jump.s  .L_exit;
204 ENDPROC(_coreb_start)