Blackfin arch: Zero out bss region in L1/L2 memory.
[linux-2.6.git] / arch / blackfin / mach-common / head.S
1 /*
2  * Common Blackfin startup code
3  *
4  * Copyright 2004-2008 Analog Devices Inc.
5  *
6  * Enter bugs at http://blackfin.uclinux.org/
7  *
8  * Licensed under the GPL-2 or later.
9  */
10
11 #include <linux/linkage.h>
12 #include <linux/init.h>
13 #include <asm/blackfin.h>
14 #include <asm/thread_info.h>
15 #include <asm/trace.h>
16
17 __INIT
18
19 #define INITIAL_STACK   (L1_SCRATCH_START + L1_SCRATCH_LENGTH - 12)
20
21 ENTRY(__start)
22         /* R0: argument of command line string, passed from uboot, save it */
23         R7 = R0;
24         /* Enable Cycle Counter and Nesting Of Interrupts */
25 #ifdef CONFIG_BFIN_SCRATCH_REG_CYCLES
26         R0 = SYSCFG_SNEN;
27 #else
28         R0 = SYSCFG_SNEN | SYSCFG_CCEN;
29 #endif
30         SYSCFG = R0;
31         R0 = 0;
32
33         /* Clear Out All the data and pointer Registers */
34         R1 = R0;
35         R2 = R0;
36         R3 = R0;
37         R4 = R0;
38         R5 = R0;
39         R6 = R0;
40
41         P0 = R0;
42         P1 = R0;
43         P2 = R0;
44         P3 = R0;
45         P4 = R0;
46         P5 = R0;
47
48         LC0 = r0;
49         LC1 = r0;
50         L0 = r0;
51         L1 = r0;
52         L2 = r0;
53         L3 = r0;
54
55         /* Clear Out All the DAG Registers */
56         B0 = r0;
57         B1 = r0;
58         B2 = r0;
59         B3 = r0;
60
61         I0 = r0;
62         I1 = r0;
63         I2 = r0;
64         I3 = r0;
65
66         M0 = r0;
67         M1 = r0;
68         M2 = r0;
69         M3 = r0;
70
71         /*
72          * Clear ITEST_COMMAND and DTEST_COMMAND registers,
73          * Leaving these as non-zero can confuse the emulator
74          */
75         p0.L = LO(DTEST_COMMAND);
76         p0.H = HI(DTEST_COMMAND);
77         [p0] = R0;
78         [p0 + (ITEST_COMMAND - DTEST_COMMAND)] = R0;
79         CSYNC;
80
81         trace_buffer_init(p0,r0);
82         P0 = R1;
83         R0 = R1;
84
85         /* Turn off the icache */
86         p0.l = LO(IMEM_CONTROL);
87         p0.h = HI(IMEM_CONTROL);
88         R1 = [p0];
89         R0 = ~ENICPLB;
90         R0 = R0 & R1;
91         [p0] = R0;
92         SSYNC;
93
94         /* Turn off the dcache */
95         p0.l = LO(DMEM_CONTROL);
96         p0.h = HI(DMEM_CONTROL);
97         R1 = [p0];
98         R0 = ~ENDCPLB;
99         R0 = R0 & R1;
100         [p0] = R0;
101         SSYNC;
102
103         /* in case of double faults, save a few things */
104         p0.l = _init_retx;
105         p0.h = _init_retx;
106         R0 = RETX;
107         [P0] = R0;
108
109 #ifdef CONFIG_DEBUG_DOUBLEFAULT
110         /* Only save these if we are storing them,
111          * This happens here, since L1 gets clobbered
112          * below
113          */
114         p0.l = _saved_retx;
115         p0.h = _saved_retx;
116         p1.l = _init_saved_retx;
117         p1.h = _init_saved_retx;
118         r0 = [p0];
119         [p1] = r0;
120
121         p0.l = _saved_dcplb_fault_addr;
122         p0.h = _saved_dcplb_fault_addr;
123         p1.l = _init_saved_dcplb_fault_addr;
124         p1.h = _init_saved_dcplb_fault_addr;
125         r0 = [p0];
126         [p1] = r0;
127
128         p0.l = _saved_icplb_fault_addr;
129         p0.h = _saved_icplb_fault_addr;
130         p1.l = _init_saved_icplb_fault_addr;
131         p1.h = _init_saved_icplb_fault_addr;
132         r0 = [p0];
133         [p1] = r0;
134
135         p0.l = _saved_seqstat;
136         p0.h = _saved_seqstat;
137         p1.l = _init_saved_seqstat;
138         p1.h = _init_saved_seqstat;
139         r0 = [p0];
140         [p1] = r0;
141 #endif
142
143         /* Initialize stack pointer */
144         sp.l = lo(INITIAL_STACK);
145         sp.h = hi(INITIAL_STACK);
146         fp = sp;
147         usp = sp;
148
149 #ifdef CONFIG_EARLY_PRINTK
150         call _init_early_exception_vectors;
151 #endif
152
153         /* Put The Code for PLL Programming and SDRAM Programming in L1 ISRAM */
154         call _bfin_relocate_l1_mem;
155 #ifdef CONFIG_BFIN_KERNEL_CLOCK
156         call _start_dma_code;
157 #endif
158
159         /* This section keeps the processor in supervisor mode
160          * during kernel boot.  Switches to user mode at end of boot.
161          * See page 3-9 of Hardware Reference manual for documentation.
162          */
163
164         /* EVT15 = _real_start */
165
166         p0.l = lo(EVT15);
167         p0.h = hi(EVT15);
168         p1.l = _real_start;
169         p1.h = _real_start;
170         [p0] = p1;
171         csync;
172
173         p0.l = lo(IMASK);
174         p0.h = hi(IMASK);
175         p1.l = IMASK_IVG15;
176         p1.h = 0x0;
177         [p0] = p1;
178         csync;
179
180         raise 15;
181         p0.l = .LWAIT_HERE;
182         p0.h = .LWAIT_HERE;
183         reti = p0;
184 #if ANOMALY_05000281
185         nop; nop; nop;
186 #endif
187         rti;
188
189 .LWAIT_HERE:
190         jump .LWAIT_HERE;
191 ENDPROC(__start)
192
193 /* A little BF561 glue ... */
194 #ifndef WDOG_CTL
195 # define WDOG_CTL WDOGA_CTL
196 #endif
197
198 ENTRY(_real_start)
199         /* Enable nested interrupts */
200         [--sp] = reti;
201
202         /* watchdog off for now */
203         p0.l = lo(WDOG_CTL);
204         p0.h = hi(WDOG_CTL);
205         r0 = 0xAD6(z);
206         w[p0] = r0;
207         ssync;
208
209 #if L1_DATA_A_LENGTH > 0
210         r1.l = __sbss_l1;
211         r1.h = __sbss_l1;
212         r2.l = __ebss_l1;
213         r2.h = __ebss_l1;
214         r0 = 0 (z);
215         r2 = r2 - r1;
216         cc = r2 == 0;
217         if cc jump .L_a_l1_done;
218         r2 >>= 2;
219         p1 = r1;
220         p2 = r2;
221         lsetup (.L_clear_a_l1, .L_clear_a_l1 ) lc0 = p2;
222 .L_clear_a_l1:
223         [p1++] = r0;
224 .L_a_l1_done:
225 #endif
226
227 #if L1_DATA_B_LENGTH > 0
228         r1.l = __sbss_b_l1;
229         r1.h = __sbss_b_l1;
230         r2.l = __ebss_b_l1;
231         r2.h = __ebss_b_l1;
232         r0 = 0 (z);
233         r2 = r2 - r1;
234         cc = r2 == 0;
235         if cc jump .L_b_l1_done;
236         r2 >>= 2;
237         p1 = r1;
238         p2 = r2;
239         lsetup (.L_clear_b_l1, .L_clear_b_l1 ) lc0 = p2;
240 .L_clear_b_l1:
241         [p1++] = r0;
242 .L_b_l1_done:
243 #endif
244
245 #if L2_LENGTH > 0
246         r1.l = __sbss_l2;
247         r1.h = __sbss_l2;
248         r2.l = __ebss_l2;
249         r2.h = __ebss_l2;
250         r0 = 0 (z);
251         r2 = r2 - r1;
252         cc = r2 == 0;
253         if cc jump .L_l2_done;
254         r2 >>= 2;
255         p1 = r1;
256         p2 = r2;
257         lsetup (.L_clear_l2, .L_clear_l2 ) lc0 = p2;
258 .L_clear_l2:
259         [p1++] = r0;
260 .L_l2_done:
261 #endif
262
263         /* Zero out the bss region
264          * Note: this will fail if bss is 0 bytes ...
265          */
266         r0 = 0 (z);
267         r1.l = ___bss_start;
268         r1.h = ___bss_start;
269         r2.l = ___bss_stop;
270         r2.h = ___bss_stop;
271         r2 = r2 - r1;
272         r2 >>= 2;
273         p1 = r1;
274         p2 = r2;
275         lsetup (.L_clear_bss, .L_clear_bss) lc0 = p2;
276 .L_clear_bss:
277         [p1++] = r0;
278
279         /* In case there is a NULL pointer reference,
280          * zero out region before stext
281          */
282         p1 = r0;
283         r2.l = __stext;
284         r2.h = __stext;
285         r2 >>= 2;
286         p2 = r2;
287         lsetup (.L_clear_zero, .L_clear_zero) lc0 = p2;
288 .L_clear_zero:
289         [p1++] = r0;
290
291         /* Pass the u-boot arguments to the global value command line */
292         R0 = R7;
293         call _cmdline_init;
294
295         /* Load the current thread pointer and stack */
296         sp.l = _init_thread_union;
297         sp.h = _init_thread_union;
298         p1 = THREAD_SIZE (z);
299         sp = sp + p1;
300         usp = sp;
301         fp = sp;
302         jump.l _start_kernel;
303 ENDPROC(_real_start)
304
305 __FINIT