aboutsummaryrefslogtreecommitdiffstats
path: root/arch/blackfin/mach-bf537/head.S
diff options
context:
space:
mode:
authorBryan Wu <bryan.wu@analog.com>2007-05-06 17:50:22 -0400
committerLinus Torvalds <torvalds@woody.linux-foundation.org>2007-05-07 15:12:58 -0400
commit1394f03221790a988afc3e4b3cb79f2e477246a9 (patch)
tree2c1963c9a4f2d84a5e021307fde240c5d567cf70 /arch/blackfin/mach-bf537/head.S
parent73243284463a761e04d69d22c7516b2be7de096c (diff)
blackfin architecture
This adds support for the Analog Devices Blackfin processor architecture, and currently supports the BF533, BF532, BF531, BF537, BF536, BF534, and BF561 (Dual Core) devices, with a variety of development platforms including those avaliable from Analog Devices (BF533-EZKit, BF533-STAMP, BF537-STAMP, BF561-EZKIT), and Bluetechnix! Tinyboards. The Blackfin architecture was jointly developed by Intel and Analog Devices Inc. (ADI) as the Micro Signal Architecture (MSA) core and introduced it in December of 2000. Since then ADI has put this core into its Blackfin processor family of devices. The Blackfin core has the advantages of a clean, orthogonal,RISC-like microprocessor instruction set. It combines a dual-MAC (Multiply/Accumulate), state-of-the-art signal processing engine and single-instruction, multiple-data (SIMD) multimedia capabilities into a single instruction-set architecture. The Blackfin architecture, including the instruction set, is described by the ADSP-BF53x/BF56x Blackfin Processor Programming Reference http://blackfin.uclinux.org/gf/download/frsrelease/29/2549/Blackfin_PRM.pdf The Blackfin processor is already supported by major releases of gcc, and there are binary and source rpms/tarballs for many architectures at: http://blackfin.uclinux.org/gf/project/toolchain/frs There is complete documentation, including "getting started" guides available at: http://docs.blackfin.uclinux.org/ which provides links to the sources and patches you will need in order to set up a cross-compiling environment for bfin-linux-uclibc This patch, as well as the other patches (toolchain, distribution, uClibc) are actively supported by Analog Devices Inc, at: http://blackfin.uclinux.org/ We have tested this on LTP, and our test plan (including pass/fails) can be found at: http://docs.blackfin.uclinux.org/doku.php?id=testing_the_linux_kernel [m.kozlowski@tuxland.pl: balance parenthesis in blackfin header files] Signed-off-by: Bryan Wu <bryan.wu@analog.com> Signed-off-by: Mariusz Kozlowski <m.kozlowski@tuxland.pl> Signed-off-by: Aubrey Li <aubrey.li@analog.com> Signed-off-by: Jie Zhang <jie.zhang@analog.com> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'arch/blackfin/mach-bf537/head.S')
-rw-r--r--arch/blackfin/mach-bf537/head.S602
1 files changed, 602 insertions, 0 deletions
diff --git a/arch/blackfin/mach-bf537/head.S b/arch/blackfin/mach-bf537/head.S
new file mode 100644
index 000000000000..d104e1d8e07a
--- /dev/null
+++ b/arch/blackfin/mach-bf537/head.S
@@ -0,0 +1,602 @@
1/*
2 * File: arch/blackfin/mach-bf537/head.S
3 * Based on: arch/blackfin/mach-bf533/head.S
4 * Author: Jeff Dionne <jeff@uclinux.org> COPYRIGHT 1998 D. Jeff Dionne
5 *
6 * Created: 1998
7 * Description: Startup code for Blackfin BF537
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
36.global __rambase
37.global __ramstart
38.global __ramend
39.extern ___bss_stop
40.extern ___bss_start
41.extern _bf53x_relocate_l1_mem
42
43#define INITIAL_STACK 0xFFB01000
44
45.text
46
47ENTRY(__start)
48ENTRY(__stext)
49 /* R0: argument of command line string, passed from uboot, save it */
50 R7 = R0;
51 /* Set the SYSCFG register */
52 R0 = 0x36;
53 SYSCFG = R0; /*Enable Cycle Counter and Nesting Of Interrupts(3rd Bit)*/
54 R0 = 0;
55
56 /* Clear Out All the data and pointer Registers*/
57 R1 = R0;
58 R2 = R0;
59 R3 = R0;
60 R4 = R0;
61 R5 = R0;
62 R6 = R0;
63
64 P0 = R0;
65 P1 = R0;
66 P2 = R0;
67 P3 = R0;
68 P4 = R0;
69 P5 = R0;
70
71 LC0 = r0;
72 LC1 = r0;
73 L0 = r0;
74 L1 = r0;
75 L2 = r0;
76 L3 = r0;
77
78 /* Clear Out All the DAG Registers*/
79 B0 = r0;
80 B1 = r0;
81 B2 = r0;
82 B3 = r0;
83
84 I0 = r0;
85 I1 = r0;
86 I2 = r0;
87 I3 = r0;
88
89 M0 = r0;
90 M1 = r0;
91 M2 = r0;
92 M3 = r0;
93
94 /* Turn off the icache */
95 p0.l = (IMEM_CONTROL & 0xFFFF);
96 p0.h = (IMEM_CONTROL >> 16);
97 R1 = [p0];
98 R0 = ~ENICPLB;
99 R0 = R0 & R1;
100
101 /* Anomaly 05000125 */
102#ifdef ANOMALY_05000125
103 CLI R2;
104 SSYNC;
105#endif
106 [p0] = R0;
107 SSYNC;
108#ifdef ANOMALY_05000125
109 STI R2;
110#endif
111
112 /* Turn off the dcache */
113 p0.l = (DMEM_CONTROL & 0xFFFF);
114 p0.h = (DMEM_CONTROL >> 16);
115 R1 = [p0];
116 R0 = ~ENDCPLB;
117 R0 = R0 & R1;
118
119 /* Anomaly 05000125 */
120#ifdef ANOMALY_05000125
121 CLI R2;
122 SSYNC;
123#endif
124 [p0] = R0;
125 SSYNC;
126#ifdef ANOMALY_05000125
127 STI R2;
128#endif
129
130 /* Initialise General-Purpose I/O Modules on BF537 */
131 /* Rev 0.0 Anomaly 05000212 - PORTx_FER,
132 * PORT_MUX Registers Do Not accept "writes" correctly:
133 */
134 p0.h = hi(BFIN_PORT_MUX);
135 p0.l = lo(BFIN_PORT_MUX);
136#ifdef ANOMALY_05000212
137 R0.L = W[P0]; /* Read */
138 SSYNC;
139#endif
140 R0 = (PGDE_UART | PFTE_UART)(Z);
141#ifdef ANOMALY_05000212
142 W[P0] = R0.L; /* Write */
143 SSYNC;
144#endif
145 W[P0] = R0.L; /* Enable both UARTS */
146 SSYNC;
147
148 p0.h = hi(PORTF_FER);
149 p0.l = lo(PORTF_FER);
150#ifdef ANOMALY_05000212
151 R0.L = W[P0]; /* Read */
152 SSYNC;
153#endif
154 R0 = 0x000F(Z);
155#ifdef ANOMALY_05000212
156 W[P0] = R0.L; /* Write */
157 SSYNC;
158#endif
159 /* Enable peripheral function of PORTF for UART0 and UART1 */
160 W[P0] = R0.L;
161 SSYNC;
162
163#if !defined(CONFIG_BF534)
164 p0.h = hi(EMAC_SYSTAT);
165 p0.l = lo(EMAC_SYSTAT);
166 R0.h = 0xFFFF; /* Clear EMAC Interrupt Status bits */
167 R0.l = 0xFFFF;
168 [P0] = R0;
169 SSYNC;
170#endif
171
172#ifdef CONFIG_BF537_PORT_H
173 p0.h = hi(PORTH_FER);
174 p0.l = lo(PORTH_FER);
175 R0.L = W[P0]; /* Read */
176 SSYNC;
177 R0 = 0x0000;
178 W[P0] = R0.L; /* Write */
179 SSYNC;
180 W[P0] = R0.L; /* Disable peripheral function of PORTH */
181 SSYNC;
182#endif
183
184 /*Initialise UART*/
185 p0.h = hi(UART_LCR);
186 p0.l = lo(UART_LCR);
187 r0 = 0x0(Z);
188 w[p0] = r0.L; /* To enable DLL writes */
189 ssync;
190
191 p0.h = hi(UART_DLL);
192 p0.l = lo(UART_DLL);
193 r0 = 0x00(Z);
194 w[p0] = r0.L;
195 ssync;
196
197 p0.h = hi(UART_DLH);
198 p0.l = lo(UART_DLH);
199 r0 = 0x00(Z);
200 w[p0] = r0.L;
201 ssync;
202
203 p0.h = hi(UART_GCTL);
204 p0.l = lo(UART_GCTL);
205 r0 = 0x0(Z);
206 w[p0] = r0.L; /* To enable UART clock */
207 ssync;
208
209 /* Initialize stack pointer */
210 sp.l = lo(INITIAL_STACK);
211 sp.h = hi(INITIAL_STACK);
212 fp = sp;
213 usp = sp;
214
215 /* Put The Code for PLL Programming and SDRAM Programming in L1 ISRAM */
216 call _bf53x_relocate_l1_mem;
217#if CONFIG_BFIN_KERNEL_CLOCK
218 call _start_dma_code;
219#endif
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
275ENTRY(_real_start)
276 [ -- sp ] = reti;
277 p0.l = lo(WDOG_CTL);
278 p0.h = hi(WDOG_CTL);
279 r0 = 0xAD6(z);
280 w[p0] = r0; /* watchdog off for now */
281 ssync;
282
283 /* Code update for BSS size == 0
284 * Zero out the bss region.
285 */
286
287 p1.l = ___bss_start;
288 p1.h = ___bss_start;
289 p2.l = ___bss_stop;
290 p2.h = ___bss_stop;
291 r0 = 0;
292 p2 -= p1;
293 lsetup (.L_clear_bss, .L_clear_bss ) lc0 = p2;
294.L_clear_bss:
295 B[p1++] = r0;
296
297 /* In case there is a NULL pointer reference
298 * Zero out region before stext
299 */
300
301 p1.l = 0x0;
302 p1.h = 0x0;
303 r0.l = __stext;
304 r0.h = __stext;
305 r0 = r0 >> 1;
306 p2 = r0;
307 r0 = 0;
308 lsetup (.L_clear_zero, .L_clear_zero ) lc0 = p2;
309.L_clear_zero:
310 W[p1++] = r0;
311
312 /* pass the uboot arguments to the global value command line */
313 R0 = R7;
314 call _cmdline_init;
315
316 p1.l = __rambase;
317 p1.h = __rambase;
318 r0.l = __sdata;
319 r0.h = __sdata;
320 [p1] = r0;
321
322 p1.l = __ramstart;
323 p1.h = __ramstart;
324 p3.l = ___bss_stop;
325 p3.h = ___bss_stop;
326
327 r1 = p3;
328 [p1] = r1;
329
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 call _start_kernel;
344.L_exit:
345 jump.s .L_exit;
346
347.section .l1.text
348#if CONFIG_BFIN_KERNEL_CLOCK
349ENTRY(_start_dma_code)
350
351 /* Enable PHY CLK buffer output */
352 p0.h = hi(VR_CTL);
353 p0.l = lo(VR_CTL);
354 r0.l = w[p0];
355 bitset(r0, 14);
356 w[p0] = r0.l;
357 ssync;
358
359 p0.h = hi(SIC_IWR);
360 p0.l = lo(SIC_IWR);
361 r0.l = 0x1;
362 r0.h = 0x0;
363 [p0] = r0;
364 SSYNC;
365
366 /*
367 * Set PLL_CTL
368 * - [14:09] = MSEL[5:0] : CLKIN / VCO multiplication factors
369 * - [8] = BYPASS : BYPASS the PLL, run CLKIN into CCLK/SCLK
370 * - [7] = output delay (add 200ps of delay to mem signals)
371 * - [6] = input delay (add 200ps of input delay to mem signals)
372 * - [5] = PDWN : 1=All Clocks off
373 * - [3] = STOPCK : 1=Core Clock off
374 * - [1] = PLL_OFF : 1=Disable Power to PLL
375 * - [0] = DF : 1=Pass CLKIN/2 to PLL / 0=Pass CLKIN to PLL
376 * all other bits set to zero
377 */
378
379 p0.h = hi(PLL_LOCKCNT);
380 p0.l = lo(PLL_LOCKCNT);
381 r0 = 0x300(Z);
382 w[p0] = r0.l;
383 ssync;
384
385 P2.H = hi(EBIU_SDGCTL);
386 P2.L = lo(EBIU_SDGCTL);
387 R0 = [P2];
388 BITSET (R0, 24);
389 [P2] = R0;
390 SSYNC;
391
392 r0 = CONFIG_VCO_MULT & 63; /* Load the VCO multiplier */
393 r0 = r0 << 9; /* Shift it over, */
394 r1 = CLKIN_HALF; /* Do we need to divide CLKIN by 2?*/
395 r0 = r1 | r0;
396 r1 = PLL_BYPASS; /* Bypass the PLL? */
397 r1 = r1 << 8; /* Shift it over */
398 r0 = r1 | r0; /* add them all together */
399
400 p0.h = hi(PLL_CTL);
401 p0.l = lo(PLL_CTL); /* Load the address */
402 cli r2; /* Disable interrupts */
403 ssync;
404 w[p0] = r0.l; /* Set the value */
405 idle; /* Wait for the PLL to stablize */
406 sti r2; /* Enable interrupts */
407
408.Lcheck_again:
409 p0.h = hi(PLL_STAT);
410 p0.l = lo(PLL_STAT);
411 R0 = W[P0](Z);
412 CC = BITTST(R0,5);
413 if ! CC jump .Lcheck_again;
414
415 /* Configure SCLK & CCLK Dividers */
416 r0 = (CONFIG_CCLK_ACT_DIV | CONFIG_SCLK_DIV);
417 p0.h = hi(PLL_DIV);
418 p0.l = lo(PLL_DIV);
419 w[p0] = r0.l;
420 ssync;
421
422 p0.l = lo(EBIU_SDRRC);
423 p0.h = hi(EBIU_SDRRC);
424 r0 = mem_SDRRC;
425 w[p0] = r0.l;
426 ssync;
427
428 p0.l = (EBIU_SDBCTL & 0xFFFF);
429 p0.h = (EBIU_SDBCTL >> 16); /* SDRAM Memory Bank Control Register */
430 r0 = mem_SDBCTL;
431 w[p0] = r0.l;
432 ssync;
433
434 P2.H = hi(EBIU_SDGCTL);
435 P2.L = lo(EBIU_SDGCTL);
436 R0 = [P2];
437 BITCLR (R0, 24);
438 p0.h = hi(EBIU_SDSTAT);
439 p0.l = lo(EBIU_SDSTAT);
440 r2.l = w[p0];
441 cc = bittst(r2,3);
442 if !cc jump .Lskip;
443 NOP;
444 BITSET (R0, 23);
445.Lskip:
446 [P2] = R0;
447 SSYNC;
448
449 R0.L = lo(mem_SDGCTL);
450 R0.H = hi(mem_SDGCTL);
451 R1 = [p2];
452 R1 = R1 | R0;
453 [P2] = R1;
454 SSYNC;
455
456 p0.h = hi(SIC_IWR);
457 p0.l = lo(SIC_IWR);
458 r0.l = lo(IWR_ENABLE_ALL);
459 r0.h = hi(IWR_ENABLE_ALL);
460 [p0] = r0;
461 SSYNC;
462
463 RTS;
464#endif /* CONFIG_BFIN_KERNEL_CLOCK */
465
466ENTRY(_bfin_reset)
467 /* No more interrupts to be handled*/
468 CLI R6;
469 SSYNC;
470
471#if defined(CONFIG_MTD_M25P80)
472/*
473 * The following code fix the SPI flash reboot issue,
474 * /CS signal of the chip which is using PF10 return to GPIO mode
475 */
476 p0.h = hi(PORTF_FER);
477 p0.l = lo(PORTF_FER);
478 r0.l = 0x0000;
479 w[p0] = r0.l;
480 SSYNC;
481
482/* /CS return to high */
483 p0.h = hi(PORTFIO);
484 p0.l = lo(PORTFIO);
485 r0.l = 0xFFFF;
486 w[p0] = r0.l;
487 SSYNC;
488
489/* Delay some time, This is necessary */
490 r1.h = 0;
491 r1.l = 0x400;
492 p1 = r1;
493 lsetup (_delay_lab1,_delay_lab1_end ) lc1 = p1;
494_delay_lab1:
495 r0.h = 0;
496 r0.l = 0x8000;
497 p0 = r0;
498 lsetup (_delay_lab0,_delay_lab0_end ) lc0 = p0;
499_delay_lab0:
500 nop;
501_delay_lab0_end:
502 nop;
503_delay_lab1_end:
504 nop;
505#endif
506
507 /* Clear the bits 13-15 in SWRST if they werent cleared */
508 p0.h = hi(SWRST);
509 p0.l = lo(SWRST);
510 csync;
511 r0.l = w[p0];
512
513 /* Clear the IMASK register */
514 p0.h = hi(IMASK);
515 p0.l = lo(IMASK);
516 r0 = 0x0;
517 [p0] = r0;
518
519 /* Clear the ILAT register */
520 p0.h = hi(ILAT);
521 p0.l = lo(ILAT);
522 r0 = [p0];
523 [p0] = r0;
524 SSYNC;
525
526 /* Disable the WDOG TIMER */
527 p0.h = hi(WDOG_CTL);
528 p0.l = lo(WDOG_CTL);
529 r0.l = 0xAD6;
530 w[p0] = r0.l;
531 SSYNC;
532
533 /* Clear the sticky bit incase it is already set */
534 p0.h = hi(WDOG_CTL);
535 p0.l = lo(WDOG_CTL);
536 r0.l = 0x8AD6;
537 w[p0] = r0.l;
538 SSYNC;
539
540 /* Program the count value */
541 R0.l = 0x100;
542 R0.h = 0x0;
543 P0.h = hi(WDOG_CNT);
544 P0.l = lo(WDOG_CNT);
545 [P0] = R0;
546 SSYNC;
547
548 /* Program WDOG_STAT if necessary */
549 P0.h = hi(WDOG_CTL);
550 P0.l = lo(WDOG_CTL);
551 R0 = W[P0](Z);
552 CC = BITTST(R0,1);
553 if !CC JUMP .LWRITESTAT;
554 CC = BITTST(R0,2);
555 if !CC JUMP .LWRITESTAT;
556 JUMP .LSKIP_WRITE;
557
558.LWRITESTAT:
559 /* When watch dog timer is enabled,
560 * a write to STAT will load the contents of CNT to STAT
561 */
562 R0 = 0x0000(z);
563 P0.h = hi(WDOG_STAT);
564 P0.l = lo(WDOG_STAT)
565 [P0] = R0;
566 SSYNC;
567
568.LSKIP_WRITE:
569 /* Enable the reset event */
570 P0.h = hi(WDOG_CTL);
571 P0.l = lo(WDOG_CTL);
572 R0 = W[P0](Z);
573 BITCLR(R0,1);
574 BITCLR(R0,2);
575 W[P0] = R0.L;
576 SSYNC;
577 NOP;
578
579 /* Enable the wdog counter */
580 R0 = W[P0](Z);
581 BITCLR(R0,4);
582 W[P0] = R0.L;
583 SSYNC;
584
585 IDLE;
586
587 RTS;
588
589.data
590
591/*
592 * Set up the usable of RAM stuff. Size of RAM is determined then
593 * an initial stack set up at the end.
594 */
595
596.align 4
597__rambase:
598.long 0
599__ramstart:
600.long 0
601__ramend:
602.long 0