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