Blackfin arch: move more of our startup code to .init so it can be freed once we...
[linux-2.6.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 #if CONFIG_BFIN_KERNEL_CLOCK
34 #include <asm/mach/mem_init.h>
35 #endif
36 #if CONFIG_DEBUG_KERNEL_START
37 #include <asm/mach-common/def_LPBlackfin.h>
38 #endif
39
40 .global __rambase
41 .global __ramstart
42 .global __ramend
43 .extern ___bss_stop
44 .extern ___bss_start
45 .extern _bf53x_relocate_l1_mem
46
47 #define INITIAL_STACK   0xFFB01000
48
49 __INIT
50
51 ENTRY(__start)
52         /* R0: argument of command line string, passed from uboot, save it */
53         R7 = R0;
54         /* Set the SYSCFG register:
55          * Enable Cycle Counter and Nesting Of Interrupts (3rd Bit)
56          */
57         R0 = 0x36;
58         SYSCFG = R0;
59         R0 = 0;
60
61         /* Clear Out All the data and pointer Registers */
62         R1 = R0;
63         R2 = R0;
64         R3 = R0;
65         R4 = R0;
66         R5 = R0;
67         R6 = R0;
68
69         P0 = R0;
70         P1 = R0;
71         P2 = R0;
72         P3 = R0;
73         P4 = R0;
74         P5 = R0;
75
76         LC0 = r0;
77         LC1 = r0;
78         L0 = r0;
79         L1 = r0;
80         L2 = r0;
81         L3 = r0;
82
83         /* Clear Out All the DAG Registers */
84         B0 = r0;
85         B1 = r0;
86         B2 = r0;
87         B3 = r0;
88
89         I0 = r0;
90         I1 = r0;
91         I2 = r0;
92         I3 = r0;
93
94         M0 = r0;
95         M1 = r0;
96         M2 = r0;
97         M3 = r0;
98
99 #if CONFIG_DEBUG_KERNEL_START
100
101 /*
102  * Set up a temporary Event Vector Table, so if something bad happens before
103  * the kernel is fully started, it doesn't vector off into the bootloaders
104  * table
105  */
106         P0.l = lo(EVT2);
107         P0.h = hi(EVT2);
108         P1.l = lo(EVT15);
109         P1.h = hi(EVT15);
110         P2.l = debug_kernel_start_trap;
111         P2.h = debug_kernel_start_trap;
112
113         RTS = P2;
114         RTI = P2;
115         RTX = P2;
116         RTN = P2;
117         RTE = P2;
118
119 .Lfill_temp_vector_table:
120         [P0++] = P2;    /* Core Event Vector Table */
121         CC = P0 == P1;
122         if !CC JUMP .Lfill_temp_vector_table
123         P0 = r0;
124         P1 = r0;
125         P2 = r0;
126
127 #endif
128
129         p0.h = hi(FIO_MASKA_C);
130         p0.l = lo(FIO_MASKA_C);
131         r0 = 0xFFFF(Z);
132         w[p0] = r0.L;   /* Disable all interrupts */
133         ssync;
134
135         p0.h = hi(FIO_MASKB_C);
136         p0.l = lo(FIO_MASKB_C);
137         r0 = 0xFFFF(Z);
138         w[p0] = r0.L;   /* Disable all interrupts */
139         ssync;
140
141         /* Turn off the icache */
142         p0.l = (IMEM_CONTROL & 0xFFFF);
143         p0.h = (IMEM_CONTROL >> 16);
144         R1 = [p0];
145         R0 = ~ENICPLB;
146         R0 = R0 & R1;
147
148         /* Anomaly 05000125 */
149 #ifdef ANOMALY_05000125
150         CLI R2;
151         SSYNC;
152 #endif
153         [p0] = R0;
154         SSYNC;
155 #ifdef ANOMALY_05000125
156         STI R2;
157 #endif
158
159         /* Turn off the dcache */
160         p0.l = (DMEM_CONTROL & 0xFFFF);
161         p0.h = (DMEM_CONTROL >> 16);
162         R1 = [p0];
163         R0 = ~ENDCPLB;
164         R0 = R0 & R1;
165
166         /* Anomaly 05000125 */
167 #ifdef ANOMALY_05000125
168         CLI R2;
169         SSYNC;
170 #endif
171         [p0] = R0;
172         SSYNC;
173 #ifdef ANOMALY_05000125
174         STI R2;
175 #endif
176
177         /* Initialise UART - when booting from u-boot, the UART is not disabled
178          * so if we dont initalize here, our serial console gets hosed */
179         p0.h = hi(UART_LCR);
180         p0.l = lo(UART_LCR);
181         r0 = 0x0(Z);
182         w[p0] = r0.L;   /* To enable DLL writes */
183         ssync;
184
185         p0.h = hi(UART_DLL);
186         p0.l = lo(UART_DLL);
187         r0 = 0x0(Z);
188         w[p0] = r0.L;
189         ssync;
190
191         p0.h = hi(UART_DLH);
192         p0.l = lo(UART_DLH);
193         r0 = 0x00(Z);
194         w[p0] = r0.L;
195         ssync;
196
197         p0.h = hi(UART_GCTL);
198         p0.l = lo(UART_GCTL);
199         r0 = 0x0(Z);
200         w[p0] = r0.L;   /* To enable UART clock */
201         ssync;
202
203         /* Initialize stack pointer */
204         sp.l = lo(INITIAL_STACK);
205         sp.h = hi(INITIAL_STACK);
206         fp = sp;
207         usp = sp;
208
209         /* Put The Code for PLL Programming and SDRAM Programming in L1 ISRAM */
210         call _bf53x_relocate_l1_mem;
211 #if CONFIG_BFIN_KERNEL_CLOCK
212         call _start_dma_code;
213 #endif
214
215         /* Code for initializing Async memory banks */
216
217         p2.h = hi(EBIU_AMBCTL1);
218         p2.l = lo(EBIU_AMBCTL1);
219         r0.h = hi(AMBCTL1VAL);
220         r0.l = lo(AMBCTL1VAL);
221         [p2] = r0;
222         ssync;
223
224         p2.h = hi(EBIU_AMBCTL0);
225         p2.l = lo(EBIU_AMBCTL0);
226         r0.h = hi(AMBCTL0VAL);
227         r0.l = lo(AMBCTL0VAL);
228         [p2] = r0;
229         ssync;
230
231         p2.h = hi(EBIU_AMGCTL);
232         p2.l = lo(EBIU_AMGCTL);
233         r0 = AMGCTLVAL;
234         w[p2] = r0;
235         ssync;
236
237         /* This section keeps the processor in supervisor mode
238          * during kernel boot.  Switches to user mode at end of boot.
239          * See page 3-9 of Hardware Reference manual for documentation.
240          */
241
242         /* EVT15 = _real_start */
243
244         p0.l = lo(EVT15);
245         p0.h = hi(EVT15);
246         p1.l = _real_start;
247         p1.h = _real_start;
248         [p0] = p1;
249         csync;
250
251         p0.l = lo(IMASK);
252         p0.h = hi(IMASK);
253         p1.l = IMASK_IVG15;
254         p1.h = 0x0;
255         [p0] = p1;
256         csync;
257
258         raise 15;
259         p0.l = .LWAIT_HERE;
260         p0.h = .LWAIT_HERE;
261         reti = p0;
262 #if defined(ANOMALY_05000281)
263         nop; nop; nop;
264 #endif
265         rti;
266
267 .LWAIT_HERE:
268         jump .LWAIT_HERE;
269 ENDPROC(__start)
270
271 ENTRY(_real_start)
272         [ -- sp ] = reti;
273         p0.l = lo(WDOG_CTL);
274         p0.h = hi(WDOG_CTL);
275         r0 = 0xAD6(z);
276         w[p0] = r0;     /* watchdog off for now */
277         ssync;
278
279         /* Code update for BSS size == 0
280          * Zero out the bss region.
281          */
282
283         p1.l = ___bss_start;
284         p1.h = ___bss_start;
285         p2.l = ___bss_stop;
286         p2.h = ___bss_stop;
287         r0 = 0;
288         p2 -= p1;
289         lsetup (.L_clear_bss, .L_clear_bss) lc0 = p2;
290 .L_clear_bss:
291         B[p1++] = r0;
292
293         /* In case there is a NULL pointer reference
294          * Zero out region before stext
295          */
296
297         p1.l = 0x0;
298         p1.h = 0x0;
299         r0.l = __stext;
300         r0.h = __stext;
301         r0 = r0 >> 1;
302         p2 = r0;
303         r0 = 0;
304         lsetup (.L_clear_zero, .L_clear_zero) lc0 = p2;
305 .L_clear_zero:
306         W[p1++] = r0;
307
308         /* pass the uboot arguments to the global value command line */
309         R0 = R7;
310         call _cmdline_init;
311
312         p1.l = __rambase;
313         p1.h = __rambase;
314         r0.l = __sdata;
315         r0.h = __sdata;
316         [p1] = r0;
317
318         p1.l = __ramstart;
319         p1.h = __ramstart;
320         p3.l = ___bss_stop;
321         p3.h = ___bss_stop;
322
323         r1 = p3;
324         [p1] = r1;
325
326         /*
327          * load the current thread pointer and stack
328          */
329         r1.l = _init_thread_union;
330         r1.h = _init_thread_union;
331
332         r2.l = 0x2000;
333         r2.h = 0x0000;
334         r1 = r1 + r2;
335         sp = r1;
336         usp = sp;
337         fp = sp;
338         jump.l _start_kernel;
339 ENDPROC(_real_start)
340
341 __FINIT
342
343 .section .l1.text
344 #if CONFIG_BFIN_KERNEL_CLOCK
345 ENTRY(_start_dma_code)
346         p0.h = hi(SIC_IWR);
347         p0.l = lo(SIC_IWR);
348         r0.l = 0x1;
349         r0.h = 0x0;
350         [p0] = r0;
351         SSYNC;
352
353         /*
354          *  Set PLL_CTL
355          *   - [14:09] = MSEL[5:0] : CLKIN / VCO multiplication factors
356          *   - [8]     = BYPASS    : BYPASS the PLL, run CLKIN into CCLK/SCLK
357          *   - [7]     = output delay (add 200ps of delay to mem signals)
358          *   - [6]     = input delay (add 200ps of input delay to mem signals)
359          *   - [5]     = PDWN      : 1=All Clocks off
360          *   - [3]     = STOPCK    : 1=Core Clock off
361          *   - [1]     = PLL_OFF   : 1=Disable Power to PLL
362          *   - [0]     = DF        : 1=Pass CLKIN/2 to PLL / 0=Pass CLKIN to PLL
363          *   all other bits set to zero
364          */
365
366         p0.h = hi(PLL_LOCKCNT);
367         p0.l = lo(PLL_LOCKCNT);
368         r0 = 0x300(Z);
369         w[p0] = r0.l;
370         ssync;
371
372         P2.H = hi(EBIU_SDGCTL);
373         P2.L = lo(EBIU_SDGCTL);
374         R0 = [P2];
375         BITSET (R0, 24);
376         [P2] = R0;
377         SSYNC;
378
379         r0 = CONFIG_VCO_MULT & 63;       /* Load the VCO multiplier         */
380         r0 = r0 << 9;                    /* Shift it over,                  */
381         r1 = CLKIN_HALF;                 /* Do we need to divide CLKIN by 2?*/
382         r0 = r1 | r0;
383         r1 = PLL_BYPASS;                 /* Bypass the PLL?                 */
384         r1 = r1 << 8;                    /* Shift it over                   */
385         r0 = r1 | r0;                    /* add them all together           */
386
387         p0.h = hi(PLL_CTL);
388         p0.l = lo(PLL_CTL);              /* Load the address                */
389         cli r2;                          /* Disable interrupts              */
390         ssync;
391         w[p0] = r0.l;                    /* Set the value                   */
392         idle;                            /* Wait for the PLL to stablize    */
393         sti r2;                          /* Enable interrupts               */
394
395 .Lcheck_again:
396         p0.h = hi(PLL_STAT);
397         p0.l = lo(PLL_STAT);
398         R0 = W[P0](Z);
399         CC = BITTST(R0,5);
400         if ! CC jump .Lcheck_again;
401
402         /* Configure SCLK & CCLK Dividers */
403         r0 = (CONFIG_CCLK_ACT_DIV | CONFIG_SCLK_DIV);
404         p0.h = hi(PLL_DIV);
405         p0.l = lo(PLL_DIV);
406         w[p0] = r0.l;
407         ssync;
408
409         p0.l = lo(EBIU_SDRRC);
410         p0.h = hi(EBIU_SDRRC);
411         r0 = mem_SDRRC;
412         w[p0] = r0.l;
413         ssync;
414
415         p0.l = (EBIU_SDBCTL & 0xFFFF);
416         p0.h = (EBIU_SDBCTL >> 16);     /* SDRAM Memory Bank Control Register */
417         r0 = mem_SDBCTL;
418         w[p0] = r0.l;
419         ssync;
420
421         P2.H = hi(EBIU_SDGCTL);
422         P2.L = lo(EBIU_SDGCTL);
423         R0 = [P2];
424         BITCLR (R0, 24);
425         p0.h = hi(EBIU_SDSTAT);
426         p0.l = lo(EBIU_SDSTAT);
427         r2.l = w[p0];
428         cc = bittst(r2,3);
429         if !cc jump .Lskip;
430         NOP;
431         BITSET (R0, 23);
432 .Lskip:
433         [P2] = R0;
434         SSYNC;
435
436         R0.L = lo(mem_SDGCTL);
437         R0.H = hi(mem_SDGCTL);
438         R1 = [p2];
439         R1 = R1 | R0;
440         [P2] = R1;
441         SSYNC;
442
443         p0.h = hi(SIC_IWR);
444         p0.l = lo(SIC_IWR);
445         r0.l = lo(IWR_ENABLE_ALL);
446         r0.h = hi(IWR_ENABLE_ALL);
447         [p0] = r0;
448         SSYNC;
449
450         RTS;
451 ENDPROC(_start_dma_code)
452 #endif /* CONFIG_BFIN_KERNEL_CLOCK */
453
454 ENTRY(_bfin_reset)
455         /* No more interrupts to be handled*/
456         CLI R6;
457         SSYNC;
458
459 #if defined(CONFIG_BFIN_SHARED_FLASH_ENET)
460         p0.h = hi(FIO_INEN);
461         p0.l = lo(FIO_INEN);
462         r0.l = ~(1 << CONFIG_ENET_FLASH_PIN);
463         w[p0] = r0.l;
464
465         p0.h = hi(FIO_DIR);
466         p0.l = lo(FIO_DIR);
467         r0.l = (1 << CONFIG_ENET_FLASH_PIN);
468         w[p0] = r0.l;
469
470         p0.h = hi(FIO_FLAG_C);
471         p0.l = lo(FIO_FLAG_C);
472         r0.l = (1 << CONFIG_ENET_FLASH_PIN);
473         w[p0] = r0.l;
474 #endif
475
476         /* Clear the IMASK register */
477         p0.h = hi(IMASK);
478         p0.l = lo(IMASK);
479         r0 = 0x0;
480         [p0] = r0;
481
482         /* Clear the ILAT register */
483         p0.h = hi(ILAT);
484         p0.l = lo(ILAT);
485         r0 = [p0];
486         [p0] = r0;
487         SSYNC;
488
489         /* make sure SYSCR is set to use BMODE */
490         P0.h = hi(SYSCR);
491         P0.l = lo(SYSCR);
492         R0.l = 0x0;
493         W[P0] = R0.l;
494         SSYNC;
495
496         /* issue a system soft reset */
497         P1.h = hi(SWRST);
498         P1.l = lo(SWRST);
499         R1.l = 0x0007;
500         W[P1] = R1;
501         SSYNC;
502
503         /* clear system soft reset */
504         R0.l = 0x0000;
505         W[P0] = R0;
506         SSYNC;
507
508         /* issue core reset */
509         raise 1;
510
511         RTS;
512 ENDPROC(_bfin_reset)
513
514 #if CONFIG_DEBUG_KERNEL_START
515 debug_kernel_start_trap:
516         /* Set up a temp stack in L1 - SDRAM might not be working  */
517         P0.L = lo(L1_DATA_A_START + 0x100);
518         P0.H = hi(L1_DATA_A_START + 0x100);
519         SP = P0;
520
521         /* Make sure the Clocks are the way I think they should be */
522         r0 = CONFIG_VCO_MULT & 63;       /* Load the VCO multiplier         */
523         r0 = r0 << 9;                    /* Shift it over,                  */
524         r1 = CLKIN_HALF;                 /* Do we need to divide CLKIN by 2?*/
525         r0 = r1 | r0;
526         r1 = PLL_BYPASS;                 /* Bypass the PLL?                 */
527         r1 = r1 << 8;                    /* Shift it over                   */
528         r0 = r1 | r0;                    /* add them all together           */
529
530         p0.h = hi(PLL_CTL);
531         p0.l = lo(PLL_CTL);              /* Load the address                */
532         cli r2;                          /* Disable interrupts              */
533         ssync;
534         w[p0] = r0.l;                    /* Set the value                   */
535         idle;                            /* Wait for the PLL to stablize    */
536         sti r2;                          /* Enable interrupts               */
537
538 .Lcheck_again1:
539         p0.h = hi(PLL_STAT);
540         p0.l = lo(PLL_STAT);
541         R0 = W[P0](Z);
542         CC = BITTST(R0,5);
543         if ! CC jump .Lcheck_again1;
544
545         /* Configure SCLK & CCLK Dividers */
546         r0 = (CONFIG_CCLK_ACT_DIV | CONFIG_SCLK_DIV);
547         p0.h = hi(PLL_DIV);
548         p0.l = lo(PLL_DIV);
549         w[p0] = r0.l;
550         ssync;
551
552         /* Make sure UART is enabled - you can never be sure */
553
554 /*
555  * Setup for console. Argument comes from the menuconfig
556  */
557
558 #ifdef CONFIG_BAUD_9600
559 #define CONSOLE_BAUD_RATE       9600
560 #elif CONFIG_BAUD_19200
561 #define CONSOLE_BAUD_RATE       19200
562 #elif CONFIG_BAUD_38400
563 #define CONSOLE_BAUD_RATE       38400
564 #elif CONFIG_BAUD_57600
565 #define CONSOLE_BAUD_RATE       57600
566 #elif CONFIG_BAUD_115200
567 #define CONSOLE_BAUD_RATE       115200
568 #endif
569
570         p0.h = hi(UART_GCTL);
571         p0.l = lo(UART_GCTL);
572         r0 = 0x00(Z);
573         w[p0] = r0.L;   /* To Turn off UART clocks */
574         ssync;
575
576         p0.h = hi(UART_LCR);
577         p0.l = lo(UART_LCR);
578         r0 = 0x83(Z);
579         w[p0] = r0.L;   /* To enable DLL writes */
580         ssync;
581
582         R1 = (((CONFIG_CLKIN_HZ * CONFIG_VCO_MULT) / CONFIG_SCLK_DIV) / (CONSOLE_BAUD_RATE * 16));
583
584         p0.h = hi(UART_DLL);
585         p0.l = lo(UART_DLL);
586         r0 = 0xFF(Z);
587         r0 = R1 & R0;
588         w[p0] = r0.L;
589         ssync;
590
591         p0.h = hi(UART_DLH);
592         p0.l = lo(UART_DLH);
593         r1 >>= 8 ;
594         w[p0] = r1.L;
595         ssync;
596
597         p0.h = hi(UART_GCTL);
598         p0.l = lo(UART_GCTL);
599         r0 = 0x0(Z);
600         w[p0] = r0.L;   /* To enable UART clock */
601         ssync;
602
603         p0.h = hi(UART_LCR);
604         p0.l = lo(UART_LCR);
605         r0 = 0x03(Z);
606         w[p0] = r0.L;   /* To Turn on UART */
607         ssync;
608
609         p0.h = hi(UART_GCTL);
610         p0.l = lo(UART_GCTL);
611         r0 = 0x01(Z);
612         w[p0] = r0.L;   /* To Turn on UART Clocks */
613         ssync;
614
615         P0.h = hi(UART_THR);
616         P0.l = lo(UART_THR);
617         P1.h = hi(UART_LSR);
618         P1.l = lo(UART_LSR);
619
620         R0.L = 'K';
621         call .Lwait_char;
622         R0.L='e';
623         call .Lwait_char;
624         R0.L='r';
625         call .Lwait_char;
626         R0.L='n'
627         call .Lwait_char;
628         R0.L='e'
629         call .Lwait_char;
630         R0.L='l';
631         call .Lwait_char;
632         R0.L=' ';
633         call .Lwait_char;
634         R0.L='c';
635         call .Lwait_char;
636         R0.L='r';
637         call .Lwait_char;
638         R0.L='a';
639         call .Lwait_char;
640         R0.L='s';
641         call .Lwait_char;
642         R0.L='h';
643         call .Lwait_char;
644         R0.L='\r';
645         call .Lwait_char;
646         R0.L='\n';
647         call .Lwait_char;
648
649         R0.L='S';
650         call .Lwait_char;
651         R0.L='E';
652         call .Lwait_char;
653         R0.L='Q'
654         call .Lwait_char;
655         R0.L='S'
656         call .Lwait_char;
657         R0.L='T';
658         call .Lwait_char;
659         R0.L='A';
660         call .Lwait_char;
661         R0.L='T';
662         call .Lwait_char;
663         R0.L='=';
664         call .Lwait_char;
665         R2 = SEQSTAT;
666         call .Ldump_reg;
667
668         R0.L=' ';
669         call .Lwait_char;
670         R0.L='R';
671         call .Lwait_char;
672         R0.L='E'
673         call .Lwait_char;
674         R0.L='T'
675         call .Lwait_char;
676         R0.L='X';
677         call .Lwait_char;
678         R0.L='=';
679         call .Lwait_char;
680         R2 = RETX;
681         call .Ldump_reg;
682
683         R0.L='\r';
684         call .Lwait_char;
685         R0.L='\n';
686         call .Lwait_char;
687
688 .Ldebug_kernel_start_trap_done:
689         JUMP    .Ldebug_kernel_start_trap_done;
690 .Ldump_reg:
691         R3 = 32;
692         R4 = 0x0F;
693         R5 = ':';  /* one past 9 */
694
695 .Ldump_reg2:
696         R0 = R2;
697         R3 += -4;
698         R0 >>>= R3;
699         R0 = R0 & R4;
700         R0 += 0x30;
701         CC = R0 <= R5;
702         if CC JUMP .Ldump_reg1;
703         R0 += 7;
704
705 .Ldump_reg1:
706         R1.l = W[P1];
707         CC = BITTST(R1, 5);
708         if !CC JUMP .Ldump_reg1;
709         W[P0] = r0;
710
711         CC = R3 == 0;
712         if !CC JUMP .Ldump_reg2
713         RTS;
714
715 .Lwait_char:
716         R1.l = W[P1];
717         CC = BITTST(R1, 5);
718         if !CC JUMP .Lwait_char;
719         W[P0] = r0;
720         RTS;
721
722 #endif  /* CONFIG_DEBUG_KERNEL_START  */
723
724 .data
725
726 /*
727  * Set up the usable of RAM stuff. Size of RAM is determined then
728  * an initial stack set up at the end.
729  */
730
731 .align 4
732 __rambase:
733 .long   0
734 __ramstart:
735 .long   0
736 __ramend:
737 .long   0