Merge branch 'master' of /home/cbou/linux-2.6
[pandora-kernel.git] / arch / blackfin / mach-bf533 / head.S
1 /*
2  * File:         arch/blackfin/mach-bf533/head.S
3  * Based on:
4  * Author:       Jeff Dionne <jeff@uclinux.org> COPYRIGHT 1998 D. Jeff Dionne
5  *
6  * Created:      1998
7  * Description:  bf533 startup file
8  *
9  * Modified:
10  *               Copyright 2004-2006 Analog Devices Inc.
11  *
12  * Bugs:         Enter bugs at http://blackfin.uclinux.org/
13  *
14  * This program is free software; you can redistribute it and/or modify
15  * it under the terms of the GNU General Public License as published by
16  * the Free Software Foundation; either version 2 of the License, or
17  * (at your option) any later version.
18  *
19  * This program is distributed in the hope that it will be useful,
20  * but WITHOUT ANY WARRANTY; without even the implied warranty of
21  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
22  * GNU General Public License for more details.
23  *
24  * You should have received a copy of the GNU General Public License
25  * along with this program; if not, see the file COPYING, or write
26  * to the Free Software Foundation, Inc.,
27  * 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
28  */
29
30 #include <linux/linkage.h>
31 #include <linux/init.h>
32 #include <asm/blackfin.h>
33 #include <asm/trace.h>
34 #ifdef CONFIG_BFIN_KERNEL_CLOCK
35 #include <asm/mach-common/clocks.h>
36 #include <asm/mach/mem_init.h>
37 #endif
38
39 .extern ___bss_stop
40 .extern ___bss_start
41 .extern _bf53x_relocate_l1_mem
42
43 #define INITIAL_STACK   0xFFB01000
44
45 __INIT
46
47 ENTRY(__start)
48         /* R0: argument of command line string, passed from uboot, save it */
49         R7 = R0;
50         /* Enable Cycle Counter and Nesting Of Interrupts */
51 #ifdef CONFIG_BFIN_SCRATCH_REG_CYCLES
52         R0 = SYSCFG_SNEN;
53 #else
54         R0 = SYSCFG_SNEN | SYSCFG_CCEN;
55 #endif
56         SYSCFG = R0;
57         R0 = 0;
58
59         /* Clear Out All the data and pointer Registers */
60         R1 = R0;
61         R2 = R0;
62         R3 = R0;
63         R4 = R0;
64         R5 = R0;
65         R6 = R0;
66
67         P0 = R0;
68         P1 = R0;
69         P2 = R0;
70         P3 = R0;
71         P4 = R0;
72         P5 = R0;
73
74         LC0 = r0;
75         LC1 = r0;
76         L0 = r0;
77         L1 = r0;
78         L2 = r0;
79         L3 = r0;
80
81         /* Clear Out All the DAG Registers */
82         B0 = r0;
83         B1 = r0;
84         B2 = r0;
85         B3 = r0;
86
87         I0 = r0;
88         I1 = r0;
89         I2 = r0;
90         I3 = r0;
91
92         M0 = r0;
93         M1 = r0;
94         M2 = r0;
95         M3 = r0;
96
97         trace_buffer_init(p0,r0);
98         P0 = R1;
99         R0 = R1;
100
101         p0.h = hi(FIO_MASKA_C);
102         p0.l = lo(FIO_MASKA_C);
103         r0 = 0xFFFF(Z);
104         w[p0] = r0.L;   /* Disable all interrupts */
105         ssync;
106
107         p0.h = hi(FIO_MASKB_C);
108         p0.l = lo(FIO_MASKB_C);
109         r0 = 0xFFFF(Z);
110         w[p0] = r0.L;   /* Disable all interrupts */
111         ssync;
112
113         /* Turn off the icache */
114         p0.l = LO(IMEM_CONTROL);
115         p0.h = HI(IMEM_CONTROL);
116         R1 = [p0];
117         R0 = ~ENICPLB;
118         R0 = R0 & R1;
119
120         /* Anomaly 05000125 */
121 #if ANOMALY_05000125
122         CLI R2;
123         SSYNC;
124 #endif
125         [p0] = R0;
126         SSYNC;
127 #if ANOMALY_05000125
128         STI R2;
129 #endif
130
131         /* Turn off the dcache */
132         p0.l = LO(DMEM_CONTROL);
133         p0.h = HI(DMEM_CONTROL);
134         R1 = [p0];
135         R0 = ~ENDCPLB;
136         R0 = R0 & R1;
137
138         /* Anomaly 05000125 */
139 #if ANOMALY_05000125
140         CLI R2;
141         SSYNC;
142 #endif
143         [p0] = R0;
144         SSYNC;
145 #if ANOMALY_05000125
146         STI R2;
147 #endif
148
149         /* Initialise UART - when booting from u-boot, the UART is not disabled
150          * so if we dont initalize here, our serial console gets hosed */
151         p0.h = hi(BFIN_UART_LCR);
152         p0.l = lo(BFIN_UART_LCR);
153         r0 = 0x0(Z);
154         w[p0] = r0.L;   /* To enable DLL writes */
155         ssync;
156
157         p0.h = hi(BFIN_UART_DLL);
158         p0.l = lo(BFIN_UART_DLL);
159         r0 = 0x0(Z);
160         w[p0] = r0.L;
161         ssync;
162
163         p0.h = hi(BFIN_UART_DLH);
164         p0.l = lo(BFIN_UART_DLH);
165         r0 = 0x00(Z);
166         w[p0] = r0.L;
167         ssync;
168
169         p0.h = hi(BFIN_UART_GCTL);
170         p0.l = lo(BFIN_UART_GCTL);
171         r0 = 0x0(Z);
172         w[p0] = r0.L;   /* To enable UART clock */
173         ssync;
174
175         /* Initialize stack pointer */
176         sp.l = lo(INITIAL_STACK);
177         sp.h = hi(INITIAL_STACK);
178         fp = sp;
179         usp = sp;
180
181 #ifdef CONFIG_EARLY_PRINTK
182         SP += -12;
183         call _init_early_exception_vectors;
184         SP += 12;
185 #endif
186
187         /* Put The Code for PLL Programming and SDRAM Programming in L1 ISRAM */
188         call _bf53x_relocate_l1_mem;
189 #ifdef CONFIG_BFIN_KERNEL_CLOCK
190         call _start_dma_code;
191 #endif
192
193         /* Code for initializing Async memory banks */
194
195         p2.h = hi(EBIU_AMBCTL1);
196         p2.l = lo(EBIU_AMBCTL1);
197         r0.h = hi(AMBCTL1VAL);
198         r0.l = lo(AMBCTL1VAL);
199         [p2] = r0;
200         ssync;
201
202         p2.h = hi(EBIU_AMBCTL0);
203         p2.l = lo(EBIU_AMBCTL0);
204         r0.h = hi(AMBCTL0VAL);
205         r0.l = lo(AMBCTL0VAL);
206         [p2] = r0;
207         ssync;
208
209         p2.h = hi(EBIU_AMGCTL);
210         p2.l = lo(EBIU_AMGCTL);
211         r0 = AMGCTLVAL;
212         w[p2] = r0;
213         ssync;
214
215         /* This section keeps the processor in supervisor mode
216          * during kernel boot.  Switches to user mode at end of boot.
217          * See page 3-9 of Hardware Reference manual for documentation.
218          */
219
220         /* EVT15 = _real_start */
221
222         p0.l = lo(EVT15);
223         p0.h = hi(EVT15);
224         p1.l = _real_start;
225         p1.h = _real_start;
226         [p0] = p1;
227         csync;
228
229         p0.l = lo(IMASK);
230         p0.h = hi(IMASK);
231         p1.l = IMASK_IVG15;
232         p1.h = 0x0;
233         [p0] = p1;
234         csync;
235
236         raise 15;
237         p0.l = .LWAIT_HERE;
238         p0.h = .LWAIT_HERE;
239         reti = p0;
240 #if ANOMALY_05000281
241         nop; nop; nop;
242 #endif
243         rti;
244
245 .LWAIT_HERE:
246         jump .LWAIT_HERE;
247 ENDPROC(__start)
248
249 ENTRY(_real_start)
250         [ -- sp ] = reti;
251         p0.l = lo(WDOG_CTL);
252         p0.h = hi(WDOG_CTL);
253         r0 = 0xAD6(z);
254         w[p0] = r0;     /* watchdog off for now */
255         ssync;
256
257         /* Code update for BSS size == 0
258          * Zero out the bss region.
259          */
260
261         p1.l = ___bss_start;
262         p1.h = ___bss_start;
263         p2.l = ___bss_stop;
264         p2.h = ___bss_stop;
265         r0 = 0;
266         p2 -= p1;
267         lsetup (.L_clear_bss, .L_clear_bss) lc0 = p2;
268 .L_clear_bss:
269         B[p1++] = r0;
270
271         /* In case there is a NULL pointer reference
272          * Zero out region before stext
273          */
274
275         p1.l = 0x0;
276         p1.h = 0x0;
277         r0.l = __stext;
278         r0.h = __stext;
279         r0 = r0 >> 1;
280         p2 = r0;
281         r0 = 0;
282         lsetup (.L_clear_zero, .L_clear_zero) lc0 = p2;
283 .L_clear_zero:
284         W[p1++] = r0;
285
286         /* pass the uboot arguments to the global value command line */
287         R0 = R7;
288         call _cmdline_init;
289
290         p1.l = __rambase;
291         p1.h = __rambase;
292         r0.l = __sdata;
293         r0.h = __sdata;
294         [p1] = r0;
295
296         p1.l = __ramstart;
297         p1.h = __ramstart;
298         p3.l = ___bss_stop;
299         p3.h = ___bss_stop;
300
301         r1 = p3;
302         [p1] = r1;
303
304         /*
305          * load the current thread pointer and stack
306          */
307         r1.l = _init_thread_union;
308         r1.h = _init_thread_union;
309
310         r2.l = 0x2000;
311         r2.h = 0x0000;
312         r1 = r1 + r2;
313         sp = r1;
314         usp = sp;
315         fp = sp;
316         jump.l _start_kernel;
317 ENDPROC(_real_start)
318
319 __FINIT
320
321 .section .l1.text
322 #ifdef CONFIG_BFIN_KERNEL_CLOCK
323 ENTRY(_start_dma_code)
324         p0.h = hi(SIC_IWR);
325         p0.l = lo(SIC_IWR);
326         r0.l = 0x1;
327         r0.h = 0x0;
328         [p0] = r0;
329         SSYNC;
330
331         /*
332          *  Set PLL_CTL
333          *   - [14:09] = MSEL[5:0] : CLKIN / VCO multiplication factors
334          *   - [8]     = BYPASS    : BYPASS the PLL, run CLKIN into CCLK/SCLK
335          *   - [7]     = output delay (add 200ps of delay to mem signals)
336          *   - [6]     = input delay (add 200ps of input delay to mem signals)
337          *   - [5]     = PDWN      : 1=All Clocks off
338          *   - [3]     = STOPCK    : 1=Core Clock off
339          *   - [1]     = PLL_OFF   : 1=Disable Power to PLL
340          *   - [0]     = DF        : 1=Pass CLKIN/2 to PLL / 0=Pass CLKIN to PLL
341          *   all other bits set to zero
342          */
343
344         p0.h = hi(PLL_LOCKCNT);
345         p0.l = lo(PLL_LOCKCNT);
346         r0 = 0x300(Z);
347         w[p0] = r0.l;
348         ssync;
349
350         P2.H = hi(EBIU_SDGCTL);
351         P2.L = lo(EBIU_SDGCTL);
352         R0 = [P2];
353         BITSET (R0, 24);
354         [P2] = R0;
355         SSYNC;
356
357         r0 = CONFIG_VCO_MULT & 63;       /* Load the VCO multiplier         */
358         r0 = r0 << 9;                    /* Shift it over,                  */
359         r1 = CLKIN_HALF;                 /* Do we need to divide CLKIN by 2?*/
360         r0 = r1 | r0;
361         r1 = PLL_BYPASS;                 /* Bypass the PLL?                 */
362         r1 = r1 << 8;                    /* Shift it over                   */
363         r0 = r1 | r0;                    /* add them all together           */
364
365         p0.h = hi(PLL_CTL);
366         p0.l = lo(PLL_CTL);              /* Load the address                */
367         cli r2;                          /* Disable interrupts              */
368         ssync;
369         w[p0] = r0.l;                    /* Set the value                   */
370         idle;                            /* Wait for the PLL to stablize    */
371         sti r2;                          /* Enable interrupts               */
372
373 .Lcheck_again:
374         p0.h = hi(PLL_STAT);
375         p0.l = lo(PLL_STAT);
376         R0 = W[P0](Z);
377         CC = BITTST(R0,5);
378         if ! CC jump .Lcheck_again;
379
380         /* Configure SCLK & CCLK Dividers */
381         r0 = (CONFIG_CCLK_ACT_DIV | CONFIG_SCLK_DIV);
382         p0.h = hi(PLL_DIV);
383         p0.l = lo(PLL_DIV);
384         w[p0] = r0.l;
385         ssync;
386
387         p0.l = lo(EBIU_SDRRC);
388         p0.h = hi(EBIU_SDRRC);
389         r0 = mem_SDRRC;
390         w[p0] = r0.l;
391         ssync;
392
393         P2.H = hi(EBIU_SDGCTL);
394         P2.L = lo(EBIU_SDGCTL);
395         R0 = [P2];
396         BITCLR (R0, 24);
397         p0.h = hi(EBIU_SDSTAT);
398         p0.l = lo(EBIU_SDSTAT);
399         r2.l = w[p0];
400         cc = bittst(r2,3);
401         if !cc jump .Lskip;
402         NOP;
403         BITSET (R0, 23);
404 .Lskip:
405         [P2] = R0;
406         SSYNC;
407
408         R0.L = lo(mem_SDGCTL);
409         R0.H = hi(mem_SDGCTL);
410         R1 = [p2];
411         R1 = R1 | R0;
412         [P2] = R1;
413         SSYNC;
414
415         p0.h = hi(SIC_IWR);
416         p0.l = lo(SIC_IWR);
417         r0.l = lo(IWR_ENABLE_ALL);
418         r0.h = hi(IWR_ENABLE_ALL);
419         [p0] = r0;
420         SSYNC;
421
422         RTS;
423 ENDPROC(_start_dma_code)
424 #endif /* CONFIG_BFIN_KERNEL_CLOCK */