Blackfin arch: issue reset via SWRST so we dont clobber the watchdog state
[linux-block.git] / arch / blackfin / mach-bf533 / head.S
CommitLineData
1394f032
BW
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
50ENTRY(__start)
51ENTRY(__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 */
177 p0.h = hi(UART_LCR);
178 p0.l = lo(UART_LCR);
179 r0 = 0x0(Z);
180 w[p0] = r0.L; /* To enable DLL writes */
181 ssync;
182
183 p0.h = hi(UART_DLL);
184 p0.l = lo(UART_DLL);
185 r0 = 0x0(Z);
186 w[p0] = r0.L;
187 ssync;
188
189 p0.h = hi(UART_DLH);
190 p0.l = lo(UART_DLH);
191 r0 = 0x00(Z);
192 w[p0] = r0.L;
193 ssync;
194
195 p0.h = hi(UART_GCTL);
196 p0.l = lo(UART_GCTL);
197 r0 = 0x0(Z);
198 w[p0] = r0.L; /* To enable UART clock */
199 ssync;
200
201 /* Initialize stack pointer */
202 sp.l = lo(INITIAL_STACK);
203 sp.h = hi(INITIAL_STACK);
204 fp = sp;
205 usp = sp;
206
207 /* Put The Code for PLL Programming and SDRAM Programming in L1 ISRAM */
208 call _bf53x_relocate_l1_mem;
209#if CONFIG_BFIN_KERNEL_CLOCK
210 call _start_dma_code;
211#endif
212
213 /* Code for initializing Async memory banks */
214
215 p2.h = hi(EBIU_AMBCTL1);
216 p2.l = lo(EBIU_AMBCTL1);
217 r0.h = hi(AMBCTL1VAL);
218 r0.l = lo(AMBCTL1VAL);
219 [p2] = r0;
220 ssync;
221
222 p2.h = hi(EBIU_AMBCTL0);
223 p2.l = lo(EBIU_AMBCTL0);
224 r0.h = hi(AMBCTL0VAL);
225 r0.l = lo(AMBCTL0VAL);
226 [p2] = r0;
227 ssync;
228
229 p2.h = hi(EBIU_AMGCTL);
230 p2.l = lo(EBIU_AMGCTL);
231 r0 = AMGCTLVAL;
232 w[p2] = r0;
233 ssync;
234
235 /* This section keeps the processor in supervisor mode
236 * during kernel boot. Switches to user mode at end of boot.
237 * See page 3-9 of Hardware Reference manual for documentation.
238 */
239
240 /* EVT15 = _real_start */
241
242 p0.l = lo(EVT15);
243 p0.h = hi(EVT15);
244 p1.l = _real_start;
245 p1.h = _real_start;
246 [p0] = p1;
247 csync;
248
249 p0.l = lo(IMASK);
250 p0.h = hi(IMASK);
251 p1.l = IMASK_IVG15;
252 p1.h = 0x0;
253 [p0] = p1;
254 csync;
255
256 raise 15;
257 p0.l = .LWAIT_HERE;
258 p0.h = .LWAIT_HERE;
259 reti = p0;
260#if defined(ANOMALY_05000281)
261 nop; nop; nop;
262#endif
263 rti;
264
265.LWAIT_HERE:
266 jump .LWAIT_HERE;
267
268ENTRY(_real_start)
269 [ -- sp ] = reti;
270 p0.l = lo(WDOG_CTL);
271 p0.h = hi(WDOG_CTL);
272 r0 = 0xAD6(z);
273 w[p0] = r0; /* watchdog off for now */
274 ssync;
275
276 /* Code update for BSS size == 0
277 * Zero out the bss region.
278 */
279
280 p1.l = ___bss_start;
281 p1.h = ___bss_start;
282 p2.l = ___bss_stop;
283 p2.h = ___bss_stop;
284 r0 = 0;
285 p2 -= p1;
286 lsetup (.L_clear_bss, .L_clear_bss) lc0 = p2;
287.L_clear_bss:
288 B[p1++] = r0;
289
290 /* In case there is a NULL pointer reference
291 * Zero out region before stext
292 */
293
294 p1.l = 0x0;
295 p1.h = 0x0;
296 r0.l = __stext;
297 r0.h = __stext;
298 r0 = r0 >> 1;
299 p2 = r0;
300 r0 = 0;
301 lsetup (.L_clear_zero, .L_clear_zero) lc0 = p2;
302.L_clear_zero:
303 W[p1++] = r0;
304
305/* pass the uboot arguments to the global value command line */
306 R0 = R7;
307 call _cmdline_init;
308
309 p1.l = __rambase;
310 p1.h = __rambase;
311 r0.l = __sdata;
312 r0.h = __sdata;
313 [p1] = r0;
314
315 p1.l = __ramstart;
316 p1.h = __ramstart;
317 p3.l = ___bss_stop;
318 p3.h = ___bss_stop;
319
320 r1 = p3;
321 [p1] = r1;
322
323 /*
324 * load the current thread pointer and stack
325 */
326 r1.l = _init_thread_union;
327 r1.h = _init_thread_union;
328
329 r2.l = 0x2000;
330 r2.h = 0x0000;
331 r1 = r1 + r2;
332 sp = r1;
333 usp = sp;
334 fp = sp;
335 call _start_kernel;
336.L_exit:
337 jump.s .L_exit;
338
339.section .l1.text
340#if CONFIG_BFIN_KERNEL_CLOCK
341ENTRY(_start_dma_code)
342 p0.h = hi(SIC_IWR);
343 p0.l = lo(SIC_IWR);
344 r0.l = 0x1;
345 r0.h = 0x0;
346 [p0] = r0;
347 SSYNC;
348
349 /*
350 * Set PLL_CTL
351 * - [14:09] = MSEL[5:0] : CLKIN / VCO multiplication factors
352 * - [8] = BYPASS : BYPASS the PLL, run CLKIN into CCLK/SCLK
353 * - [7] = output delay (add 200ps of delay to mem signals)
354 * - [6] = input delay (add 200ps of input delay to mem signals)
355 * - [5] = PDWN : 1=All Clocks off
356 * - [3] = STOPCK : 1=Core Clock off
357 * - [1] = PLL_OFF : 1=Disable Power to PLL
358 * - [0] = DF : 1=Pass CLKIN/2 to PLL / 0=Pass CLKIN to PLL
359 * all other bits set to zero
360 */
361
362 p0.h = hi(PLL_LOCKCNT);
363 p0.l = lo(PLL_LOCKCNT);
364 r0 = 0x300(Z);
365 w[p0] = r0.l;
366 ssync;
367
368 P2.H = hi(EBIU_SDGCTL);
369 P2.L = lo(EBIU_SDGCTL);
370 R0 = [P2];
371 BITSET (R0, 24);
372 [P2] = R0;
373 SSYNC;
374
375 r0 = CONFIG_VCO_MULT & 63; /* Load the VCO multiplier */
376 r0 = r0 << 9; /* Shift it over, */
377 r1 = CLKIN_HALF; /* Do we need to divide CLKIN by 2?*/
378 r0 = r1 | r0;
379 r1 = PLL_BYPASS; /* Bypass the PLL? */
380 r1 = r1 << 8; /* Shift it over */
381 r0 = r1 | r0; /* add them all together */
382
383 p0.h = hi(PLL_CTL);
384 p0.l = lo(PLL_CTL); /* Load the address */
385 cli r2; /* Disable interrupts */
386 ssync;
387 w[p0] = r0.l; /* Set the value */
388 idle; /* Wait for the PLL to stablize */
389 sti r2; /* Enable interrupts */
390
391.Lcheck_again:
392 p0.h = hi(PLL_STAT);
393 p0.l = lo(PLL_STAT);
394 R0 = W[P0](Z);
395 CC = BITTST(R0,5);
396 if ! CC jump .Lcheck_again;
397
398 /* Configure SCLK & CCLK Dividers */
399 r0 = (CONFIG_CCLK_ACT_DIV | CONFIG_SCLK_DIV);
400 p0.h = hi(PLL_DIV);
401 p0.l = lo(PLL_DIV);
402 w[p0] = r0.l;
403 ssync;
404
405 p0.l = lo(EBIU_SDRRC);
406 p0.h = hi(EBIU_SDRRC);
407 r0 = mem_SDRRC;
408 w[p0] = r0.l;
409 ssync;
410
411 p0.l = (EBIU_SDBCTL & 0xFFFF);
412 p0.h = (EBIU_SDBCTL >> 16); /* SDRAM Memory Bank Control Register */
413 r0 = mem_SDBCTL;
414 w[p0] = r0.l;
415 ssync;
416
417 P2.H = hi(EBIU_SDGCTL);
418 P2.L = lo(EBIU_SDGCTL);
419 R0 = [P2];
420 BITCLR (R0, 24);
421 p0.h = hi(EBIU_SDSTAT);
422 p0.l = lo(EBIU_SDSTAT);
423 r2.l = w[p0];
424 cc = bittst(r2,3);
425 if !cc jump .Lskip;
426 NOP;
427 BITSET (R0, 23);
428.Lskip:
429 [P2] = R0;
430 SSYNC;
431
432 R0.L = lo(mem_SDGCTL);
433 R0.H = hi(mem_SDGCTL);
434 R1 = [p2];
435 R1 = R1 | R0;
436 [P2] = R1;
437 SSYNC;
438
439 p0.h = hi(SIC_IWR);
440 p0.l = lo(SIC_IWR);
441 r0.l = lo(IWR_ENABLE_ALL)
442 r0.h = hi(IWR_ENABLE_ALL)
443 [p0] = r0;
444 SSYNC;
445
446 RTS;
447#endif /* CONFIG_BFIN_KERNEL_CLOCK */
448
449ENTRY(_bfin_reset)
450 /* No more interrupts to be handled*/
451 CLI R6;
452 SSYNC;
453
454#if defined(CONFIG_BFIN_SHARED_FLASH_ENET)
455 p0.h = hi(FIO_INEN);
456 p0.l = lo(FIO_INEN);
457 r0.l = ~(1 << CONFIG_ENET_FLASH_PIN);
458 w[p0] = r0.l;
459
460 p0.h = hi(FIO_DIR);
461 p0.l = lo(FIO_DIR);
462 r0.l = (1 << CONFIG_ENET_FLASH_PIN);
463 w[p0] = r0.l;
464
465 p0.h = hi(FIO_FLAG_C);
466 p0.l = lo(FIO_FLAG_C);
467 r0.l = (1 << CONFIG_ENET_FLASH_PIN);
468 w[p0] = r0.l;
469#endif
470
1394f032
BW
471 /* Clear the IMASK register */
472 p0.h = hi(IMASK);
473 p0.l = lo(IMASK);
474 r0 = 0x0;
475 [p0] = r0;
476
477 /* Clear the ILAT register */
478 p0.h = hi(ILAT);
479 p0.l = lo(ILAT);
480 r0 = [p0];
481 [p0] = r0;
482 SSYNC;
483
ef9256d2
MF
484 /* make sure SYSCR is set to use BMODE */
485 P0.h = hi(SYSCR);
486 P0.l = lo(SYSCR);
487 R0.l = 0x0;
488 W[P0] = R0.l;
1394f032
BW
489 SSYNC;
490
ef9256d2
MF
491 /* issue a system soft reset */
492 P1.h = hi(SWRST);
493 P1.l = lo(SWRST);
494 R1.l = 0x0007;
495 W[P1] = R1;
1394f032
BW
496 SSYNC;
497
ef9256d2
MF
498 /* clear system soft reset */
499 R0.l = 0x0000;
500 W[P0] = R0;
1394f032
BW
501 SSYNC;
502
ef9256d2
MF
503 /* issue core reset */
504 raise 1;
1394f032
BW
505
506 RTS;
ef9256d2 507ENDPROC(_bfin_reset)
1394f032
BW
508
509#if CONFIG_DEBUG_KERNEL_START
510debug_kernel_start_trap:
511 /* Set up a temp stack in L1 - SDRAM might not be working */
512 P0.L = lo(L1_DATA_A_START + 0x100);
513 P0.H = hi(L1_DATA_A_START + 0x100);
514 SP = P0;
515
516 /* Make sure the Clocks are the way I think they should be */
517 r0 = CONFIG_VCO_MULT & 63; /* Load the VCO multiplier */
518 r0 = r0 << 9; /* Shift it over, */
519 r1 = CLKIN_HALF; /* Do we need to divide CLKIN by 2?*/
520 r0 = r1 | r0;
521 r1 = PLL_BYPASS; /* Bypass the PLL? */
522 r1 = r1 << 8; /* Shift it over */
523 r0 = r1 | r0; /* add them all together */
524
525 p0.h = hi(PLL_CTL);
526 p0.l = lo(PLL_CTL); /* Load the address */
527 cli r2; /* Disable interrupts */
528 ssync;
529 w[p0] = r0.l; /* Set the value */
530 idle; /* Wait for the PLL to stablize */
531 sti r2; /* Enable interrupts */
532
533.Lcheck_again1:
534 p0.h = hi(PLL_STAT);
535 p0.l = lo(PLL_STAT);
536 R0 = W[P0](Z);
537 CC = BITTST(R0,5);
538 if ! CC jump .Lcheck_again1;
539
540 /* Configure SCLK & CCLK Dividers */
541 r0 = (CONFIG_CCLK_ACT_DIV | CONFIG_SCLK_DIV);
542 p0.h = hi(PLL_DIV);
543 p0.l = lo(PLL_DIV);
544 w[p0] = r0.l;
545 ssync;
546
547 /* Make sure UART is enabled - you can never be sure */
548
549/*
550 * Setup for console. Argument comes from the menuconfig
551 */
552
553#ifdef CONFIG_BAUD_9600
554#define CONSOLE_BAUD_RATE 9600
555#elif CONFIG_BAUD_19200
556#define CONSOLE_BAUD_RATE 19200
557#elif CONFIG_BAUD_38400
558#define CONSOLE_BAUD_RATE 38400
559#elif CONFIG_BAUD_57600
560#define CONSOLE_BAUD_RATE 57600
561#elif CONFIG_BAUD_115200
562#define CONSOLE_BAUD_RATE 115200
563#endif
564
565 p0.h = hi(UART_GCTL);
566 p0.l = lo(UART_GCTL);
567 r0 = 0x00(Z);
568 w[p0] = r0.L; /* To Turn off UART clocks */
569 ssync;
570
571 p0.h = hi(UART_LCR);
572 p0.l = lo(UART_LCR);
573 r0 = 0x83(Z);
574 w[p0] = r0.L; /* To enable DLL writes */
575 ssync;
576
577 R1 = (((CONFIG_CLKIN_HZ * CONFIG_VCO_MULT) / CONFIG_SCLK_DIV) / (CONSOLE_BAUD_RATE * 16));
578
579 p0.h = hi(UART_DLL);
580 p0.l = lo(UART_DLL);
581 r0 = 0xFF(Z);
582 r0 = R1 & R0;
583 w[p0] = r0.L;
584 ssync;
585
586 p0.h = hi(UART_DLH);
587 p0.l = lo(UART_DLH);
588 r1 >>= 8 ;
589 w[p0] = r1.L;
590 ssync;
591
592 p0.h = hi(UART_GCTL);
593 p0.l = lo(UART_GCTL);
594 r0 = 0x0(Z);
595 w[p0] = r0.L; /* To enable UART clock */
596 ssync;
597
598 p0.h = hi(UART_LCR);
599 p0.l = lo(UART_LCR);
600 r0 = 0x03(Z);
601 w[p0] = r0.L; /* To Turn on UART */
602 ssync;
603
604 p0.h = hi(UART_GCTL);
605 p0.l = lo(UART_GCTL);
606 r0 = 0x01(Z);
607 w[p0] = r0.L; /* To Turn on UART Clocks */
608 ssync;
609
610 P0.h = hi(UART_THR);
611 P0.l = lo(UART_THR);
612 P1.h = hi(UART_LSR);
613 P1.l = lo(UART_LSR);
614
615 R0.L = 'K';
616 call .Lwait_char;
617 R0.L='e';
618 call .Lwait_char;
619 R0.L='r';
620 call .Lwait_char;
621 R0.L='n'
622 call .Lwait_char;
623 R0.L='e'
624 call .Lwait_char;
625 R0.L='l';
626 call .Lwait_char;
627 R0.L=' ';
628 call .Lwait_char;
629 R0.L='c';
630 call .Lwait_char;
631 R0.L='r';
632 call .Lwait_char;
633 R0.L='a';
634 call .Lwait_char;
635 R0.L='s';
636 call .Lwait_char;
637 R0.L='h';
638 call .Lwait_char;
639 R0.L='\r';
640 call .Lwait_char;
641 R0.L='\n';
642 call .Lwait_char;
643
644 R0.L='S';
645 call .Lwait_char;
646 R0.L='E';
647 call .Lwait_char;
648 R0.L='Q'
649 call .Lwait_char;
650 R0.L='S'
651 call .Lwait_char;
652 R0.L='T';
653 call .Lwait_char;
654 R0.L='A';
655 call .Lwait_char;
656 R0.L='T';
657 call .Lwait_char;
658 R0.L='=';
659 call .Lwait_char;
660 R2 = SEQSTAT;
661 call .Ldump_reg;
662
663 R0.L=' ';
664 call .Lwait_char;
665 R0.L='R';
666 call .Lwait_char;
667 R0.L='E'
668 call .Lwait_char;
669 R0.L='T'
670 call .Lwait_char;
671 R0.L='X';
672 call .Lwait_char;
673 R0.L='=';
674 call .Lwait_char;
675 R2 = RETX;
676 call .Ldump_reg;
677
678 R0.L='\r';
679 call .Lwait_char;
680 R0.L='\n';
681 call .Lwait_char;
682
683.Ldebug_kernel_start_trap_done:
684 JUMP .Ldebug_kernel_start_trap_done;
685.Ldump_reg:
686 R3 = 32;
687 R4 = 0x0F;
688 R5 = ':'; /* one past 9 */
689
690.Ldump_reg2:
691 R0 = R2;
692 R3 += -4;
693 R0 >>>= R3;
694 R0 = R0 & R4;
695 R0 += 0x30;
696 CC = R0 <= R5;
697 if CC JUMP .Ldump_reg1;
698 R0 += 7;
699
700.Ldump_reg1:
701 R1.l = W[P1];
702 CC = BITTST(R1, 5);
703 if !CC JUMP .Ldump_reg1;
704 W[P0] = r0;
705
706 CC = R3 == 0;
707 if !CC JUMP .Ldump_reg2
708 RTS;
709
710.Lwait_char:
711 R1.l = W[P1];
712 CC = BITTST(R1, 5);
713 if !CC JUMP .Lwait_char;
714 W[P0] = r0;
715 RTS;
716
717#endif /* CONFIG_DEBUG_KERNEL_START */
718
719.data
720
721/*
722 * Set up the usable of RAM stuff. Size of RAM is determined then
723 * an initial stack set up at the end.
724 */
725
726.align 4
727__rambase:
728.long 0
729__ramstart:
730.long 0
731__ramend:
732.long 0