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