Commit | Line | Data |
---|---|---|
c51b4488 | 1 | /* |
96f1050d | 2 | * BF561 coreB bootstrap file |
c51b4488 | 3 | * |
96f1050d RG |
4 | * Copyright 2007-2009 Analog Devices Inc. |
5 | * Philippe Gerum <rpm@xenomai.org> | |
c51b4488 | 6 | * |
96f1050d | 7 | * Licensed under the GPL-2 or later. |
c51b4488 GY |
8 | */ |
9 | ||
10 | #include <linux/linkage.h> | |
11 | #include <linux/init.h> | |
12 | #include <asm/blackfin.h> | |
13 | #include <asm/asm-offsets.h> | |
0b39db28 | 14 | #include <asm/trace.h> |
c51b4488 | 15 | |
c6345ab1 SZ |
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 | |
c51b4488 GY |
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) | |
b648072d MF |
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; | |
c51b4488 | 33 | |
b648072d MF |
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); | |
0b39db28 | 43 | |
b648072d | 44 | /* Zero out registers required by Blackfin ABI */ |
c51b4488 | 45 | |
b648072d MF |
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; | |
eb7bd9c4 | 62 | CSYNC; |
b648072d MF |
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; | |
c51b4488 | 70 | SSYNC; |
c51b4488 GY |
71 | |
72 | /* Turn off the dcache */ | |
b648072d MF |
73 | r1 = [p5 + (DMEM_CONTROL - COREMMR_BASE)]; |
74 | BITCLR (r1, ENDCPLB_P); | |
75 | [p5 + (DMEM_CONTROL - COREMMR_BASE)] = r1; | |
c51b4488 | 76 | SSYNC; |
c51b4488 GY |
77 | |
78 | /* in case of double faults, save a few things */ | |
fb1d9be5 MF |
79 | p1.l = _initial_pda_coreb; |
80 | p1.h = _initial_pda_coreb; | |
81 | r4 = RETX; | |
c51b4488 GY |
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); | |
fb1d9be5 MF |
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; | |
c51b4488 | 96 | #endif |
fb1d9be5 | 97 | [p1 + PDA_INIT_RETX] = r4; |
c51b4488 GY |
98 | |
99 | /* Initialize stack pointer */ | |
100 | sp.l = lo(INITIAL_STACK); | |
101 | sp.h = hi(INITIAL_STACK); | |
102 | fp = sp; | |
103 | usp = sp; | |
104 | ||
105 | /* This section keeps the processor in supervisor mode | |
106 | * during core B startup. Branches to the idle task. | |
107 | */ | |
108 | ||
109 | /* EVT15 = _real_start */ | |
110 | ||
c51b4488 GY |
111 | p1.l = _coreb_start; |
112 | p1.h = _coreb_start; | |
b648072d | 113 | [p5 + (EVT15 - COREMMR_BASE)] = p1; |
c51b4488 GY |
114 | csync; |
115 | ||
b648072d MF |
116 | r0 = EVT_IVG15 (z); |
117 | sti r0; | |
c51b4488 GY |
118 | |
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; | |
127 | ||
128 | .LWAIT_HERE: | |
129 | jump .LWAIT_HERE; | |
130 | ENDPROC(_coreb_trampoline_start) | |
c51b4488 | 131 | |
6f546bc3 | 132 | #ifdef CONFIG_HOTPLUG_CPU |
0b39db28 | 133 | .section ".text" |
6f546bc3 | 134 | ENTRY(_coreb_die) |
0b39db28 GY |
135 | sp.l = lo(INITIAL_STACK); |
136 | sp.h = hi(INITIAL_STACK); | |
137 | fp = sp; | |
138 | usp = sp; | |
139 | ||
0b39db28 GY |
140 | CLI R2; |
141 | SSYNC; | |
142 | IDLE; | |
143 | STI R2; | |
144 | ||
145 | R0 = IWR_DISABLE_ALL; | |
6f546bc3 GY |
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; | |
0b39db28 GY |
151 | |
152 | p0.h = hi(COREB_L1_CODE_START); | |
153 | p0.l = lo(COREB_L1_CODE_START); | |
154 | jump (p0); | |
6f546bc3 GY |
155 | ENDPROC(_coreb_die) |
156 | #endif | |
0b39db28 | 157 | |
6ce0466d | 158 | __INIT |
c51b4488 GY |
159 | ENTRY(_coreb_start) |
160 | [--sp] = reti; | |
161 | ||
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; | |
167 | ||
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; | |
0b39db28 GY |
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 | |
c51b4488 GY |
183 | sp += -12; |
184 | call _init_pda | |
185 | sp += 12; | |
0b39db28 GY |
186 | #ifdef CONFIG_HOTPLUG_CPU |
187 | 3: | |
188 | #endif | |
c51b4488 GY |
189 | call _secondary_start_kernel; |
190 | .L_exit: | |
191 | jump.s .L_exit; | |
192 | ENDPROC(_coreb_start) |