Merge branch 'akpm'
[linux-2.6/next.git] / arch / blackfin / mach-bf561 / secondary.S
blob01e5408620ac60f39b9d4f7e720caa74b48d4ca0
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  */
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>
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
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)
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;
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);
44         /* Zero out registers required by Blackfin ABI */
46         /* Disable circular buffers */
47         L0 = r6;
48         L1 = r6;
49         L2 = r6;
50         L3 = r6;
52         /* Disable hardware loops in case we were started by 'go' */
53         LC0 = r6;
54         LC1 = r6;
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;
64         trace_buffer_init(p0,r0);
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;
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;
78         /* in case of double faults, save a few things */
79         p1.l = _initial_pda_coreb;
80         p1.h = _initial_pda_coreb;
81         r4 = RETX;
82 #ifdef CONFIG_DEBUG_DOUBLEFAULT
83         /* Only save these if we are storing them,
84          * This happens here, since L1 gets clobbered
85          * below
86          */
87         GET_PDA(p0, r0);
88         r0 = [p0 + PDA_DF_RETX];
89         r1 = [p0 + PDA_DF_DCPLB];
90         r2 = [p0 + PDA_DF_ICPLB];
91         r3 = [p0 + PDA_DF_SEQSTAT];
92         [p1 + PDA_INIT_DF_RETX] = r0;
93         [p1 + PDA_INIT_DF_DCPLB] = r1;
94         [p1 + PDA_INIT_DF_ICPLB] = r2;
95         [p1 + PDA_INIT_DF_SEQSTAT] = r3;
96 #endif
97         [p1 + PDA_INIT_RETX] = r4;
99         /* Initialize stack pointer */
100         sp.l = lo(INITIAL_STACK);
101         sp.h = hi(INITIAL_STACK);
102         fp = sp;
103         usp = sp;
105         /* This section keeps the processor in supervisor mode
106          * during core B startup.  Branches to the idle task.
107          */
109         /* EVT15 = _real_start */
111         p1.l = _coreb_start;
112         p1.h = _coreb_start;
113         [p5 + (EVT15 - COREMMR_BASE)] = p1;
114         csync;
116         r0 = EVT_IVG15 (z);
117         sti r0;
119         raise 15;
120         p0.l = .LWAIT_HERE;
121         p0.h = .LWAIT_HERE;
122         reti = p0;
123 #if defined(ANOMALY_05000281)
124         nop; nop; nop;
125 #endif
126         rti;
128 .LWAIT_HERE:
129         jump .LWAIT_HERE;
130 ENDPROC(_coreb_trampoline_start)
132 #ifdef CONFIG_HOTPLUG_CPU
133 .section ".text"
134 ENTRY(_coreb_die)
135         sp.l = lo(INITIAL_STACK);
136         sp.h = hi(INITIAL_STACK);
137         fp = sp;
138         usp = sp;
140         CLI R2;
141         SSYNC;
142         IDLE;
143         STI R2;
145         R0 = IWR_DISABLE_ALL;
146         P0.H = hi(SYSMMR_BASE);
147         P0.L = lo(SYSMMR_BASE);
148         [P0 + (SICB_IWR0 - SYSMMR_BASE)] = R0;
149         [P0 + (SICB_IWR1 - SYSMMR_BASE)] = R0;
150         SSYNC;
152         p0.h = hi(COREB_L1_CODE_START);
153         p0.l = lo(COREB_L1_CODE_START);
154         jump (p0);
155 ENDPROC(_coreb_die)
156 #endif
158 __INIT
159 ENTRY(_coreb_start)
160         [--sp] = reti;
162         p0.l = lo(WDOGB_CTL);
163         p0.h = hi(WDOGB_CTL);
164         r0 = 0xAD6(z);
165         w[p0] = r0;     /* Clear the watchdog. */
166         ssync;
168         /*
169          * switch to IDLE stack.
170          */
171         p0.l = _secondary_stack;
172         p0.h = _secondary_stack;
173         sp = [p0];
174         usp = sp;
175         fp = sp;
176 #ifdef CONFIG_HOTPLUG_CPU
177         p0.l = _hotplug_coreb;
178         p0.h = _hotplug_coreb;
179         r0 = [p0];
180         cc = BITTST(r0, 0);
181         if cc jump 3f;
182 #endif
183         sp += -12;
184         call _init_pda
185         sp += 12;
186 #ifdef CONFIG_HOTPLUG_CPU
188 #endif
189         call _secondary_start_kernel;
190 .L_exit:
191         jump.s  .L_exit;
192 ENDPROC(_coreb_start)