aboutsummaryrefslogtreecommitdiffstats
path: root/arch/blackfin/mach-bf561/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-bf561/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-bf561/head.S')
-rw-r--r--arch/blackfin/mach-bf561/head.S512
1 files changed, 512 insertions, 0 deletions
diff --git a/arch/blackfin/mach-bf561/head.S b/arch/blackfin/mach-bf561/head.S
new file mode 100644
index 000000000000..7bca478526b9
--- /dev/null
+++ b/arch/blackfin/mach-bf561/head.S
@@ -0,0 +1,512 @@
1/*
2 * File: arch/blackfin/mach-bf561/head.S
3 * Based on: arch/blackfin/mach-bf533/head.S
4 * Author:
5 *
6 * Created:
7 * Description: BF561 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
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 UART*/
131 p0.h = hi(UART_LCR);
132 p0.l = lo(UART_LCR);
133 r0 = 0x0(Z);
134 w[p0] = r0.L; /* To enable DLL writes */
135 ssync;
136
137 p0.h = hi(UART_DLL);
138 p0.l = lo(UART_DLL);
139 r0 = 0x0(Z);
140 w[p0] = r0.L;
141 ssync;
142
143 p0.h = hi(UART_DLH);
144 p0.l = lo(UART_DLH);
145 r0 = 0x00(Z);
146 w[p0] = r0.L;
147 ssync;
148
149 p0.h = hi(UART_GCTL);
150 p0.l = lo(UART_GCTL);
151 r0 = 0x0(Z);
152 w[p0] = r0.L; /* To enable UART clock */
153 ssync;
154
155 /* Initialize stack pointer */
156 sp.l = lo(INITIAL_STACK);
157 sp.h = hi(INITIAL_STACK);
158 fp = sp;
159 usp = sp;
160
161 /* Put The Code for PLL Programming and SDRAM Programming in L1 ISRAM */
162 call _bf53x_relocate_l1_mem;
163#if CONFIG_BFIN_KERNEL_CLOCK
164 call _start_dma_code;
165#endif
166
167 /* Code for initializing Async memory banks */
168
169 p2.h = hi(EBIU_AMBCTL1);
170 p2.l = lo(EBIU_AMBCTL1);
171 r0.h = hi(AMBCTL1VAL);
172 r0.l = lo(AMBCTL1VAL);
173 [p2] = r0;
174 ssync;
175
176 p2.h = hi(EBIU_AMBCTL0);
177 p2.l = lo(EBIU_AMBCTL0);
178 r0.h = hi(AMBCTL0VAL);
179 r0.l = lo(AMBCTL0VAL);
180 [p2] = r0;
181 ssync;
182
183 p2.h = hi(EBIU_AMGCTL);
184 p2.l = lo(EBIU_AMGCTL);
185 r0 = AMGCTLVAL;
186 w[p2] = r0;
187 ssync;
188
189 /* This section keeps the processor in supervisor mode
190 * during kernel boot. Switches to user mode at end of boot.
191 * See page 3-9 of Hardware Reference manual for documentation.
192 */
193
194 /* EVT15 = _real_start */
195
196 p0.l = lo(EVT15);
197 p0.h = hi(EVT15);
198 p1.l = _real_start;
199 p1.h = _real_start;
200 [p0] = p1;
201 csync;
202
203 p0.l = lo(IMASK);
204 p0.h = hi(IMASK);
205 p1.l = IMASK_IVG15;
206 p1.h = 0x0;
207 [p0] = p1;
208 csync;
209
210 raise 15;
211 p0.l = .LWAIT_HERE;
212 p0.h = .LWAIT_HERE;
213 reti = p0;
214#if defined(ANOMALY_05000281)
215 nop; nop; nop;
216#endif
217 rti;
218
219.LWAIT_HERE:
220 jump .LWAIT_HERE;
221
222ENTRY(_real_start)
223 [ -- sp ] = reti;
224 p0.l = lo(WDOGA_CTL);
225 p0.h = hi(WDOGA_CTL);
226 r0 = 0xAD6(z);
227 w[p0] = r0; /* watchdog off for now */
228 ssync;
229
230 /* Code update for BSS size == 0
231 * Zero out the bss region.
232 */
233
234 p1.l = ___bss_start;
235 p1.h = ___bss_start;
236 p2.l = ___bss_stop;
237 p2.h = ___bss_stop;
238 r0 = 0;
239 p2 -= p1;
240 lsetup (.L_clear_bss, .L_clear_bss ) lc0 = p2;
241.L_clear_bss:
242 B[p1++] = r0;
243
244 /* In case there is a NULL pointer reference
245 * Zero out region before stext
246 */
247
248 p1.l = 0x0;
249 p1.h = 0x0;
250 r0.l = __stext;
251 r0.h = __stext;
252 r0 = r0 >> 1;
253 p2 = r0;
254 r0 = 0;
255 lsetup (.L_clear_zero, .L_clear_zero ) lc0 = p2;
256.L_clear_zero:
257 W[p1++] = r0;
258
259/* pass the uboot arguments to the global value command line */
260 R0 = R7;
261 call _cmdline_init;
262
263 p1.l = __rambase;
264 p1.h = __rambase;
265 r0.l = __sdata;
266 r0.h = __sdata;
267 [p1] = r0;
268
269 p1.l = __ramstart;
270 p1.h = __ramstart;
271 p3.l = ___bss_stop;
272 p3.h = ___bss_stop;
273
274 r1 = p3;
275 [p1] = r1;
276
277 /*
278 * load the current thread pointer and stack
279 */
280 r1.l = _init_thread_union;
281 r1.h = _init_thread_union;
282
283 r2.l = 0x2000;
284 r2.h = 0x0000;
285 r1 = r1 + r2;
286 sp = r1;
287 usp = sp;
288 fp = sp;
289 call _start_kernel;
290.L_exit:
291 jump.s .L_exit;
292
293.section .l1.text
294#if CONFIG_BFIN_KERNEL_CLOCK
295ENTRY(_start_dma_code)
296 p0.h = hi(SICA_IWR0);
297 p0.l = lo(SICA_IWR0);
298 r0.l = 0x1;
299 [p0] = r0;
300 SSYNC;
301
302 /*
303 * Set PLL_CTL
304 * - [14:09] = MSEL[5:0] : CLKIN / VCO multiplication factors
305 * - [8] = BYPASS : BYPASS the PLL, run CLKIN into CCLK/SCLK
306 * - [7] = output delay (add 200ps of delay to mem signals)
307 * - [6] = input delay (add 200ps of input delay to mem signals)
308 * - [5] = PDWN : 1=All Clocks off
309 * - [3] = STOPCK : 1=Core Clock off
310 * - [1] = PLL_OFF : 1=Disable Power to PLL
311 * - [0] = DF : 1=Pass CLKIN/2 to PLL / 0=Pass CLKIN to PLL
312 * all other bits set to zero
313 */
314
315 p0.h = hi(PLL_LOCKCNT);
316 p0.l = lo(PLL_LOCKCNT);
317 r0 = 0x300(Z);
318 w[p0] = r0.l;
319 ssync;
320
321 P2.H = hi(EBIU_SDGCTL);
322 P2.L = lo(EBIU_SDGCTL);
323 R0 = [P2];
324 BITSET (R0, 24);
325 [P2] = R0;
326 SSYNC;
327
328 r0 = CONFIG_VCO_MULT & 63; /* Load the VCO multiplier */
329 r0 = r0 << 9; /* Shift it over, */
330 r1 = CLKIN_HALF; /* Do we need to divide CLKIN by 2?*/
331 r0 = r1 | r0;
332 r1 = PLL_BYPASS; /* Bypass the PLL? */
333 r1 = r1 << 8; /* Shift it over */
334 r0 = r1 | r0; /* add them all together */
335
336 p0.h = hi(PLL_CTL);
337 p0.l = lo(PLL_CTL); /* Load the address */
338 cli r2; /* Disable interrupts */
339 ssync;
340 w[p0] = r0.l; /* Set the value */
341 idle; /* Wait for the PLL to stablize */
342 sti r2; /* Enable interrupts */
343
344.Lcheck_again:
345 p0.h = hi(PLL_STAT);
346 p0.l = lo(PLL_STAT);
347 R0 = W[P0](Z);
348 CC = BITTST(R0,5);
349 if ! CC jump .Lcheck_again;
350
351 /* Configure SCLK & CCLK Dividers */
352 r0 = (CONFIG_CCLK_ACT_DIV | CONFIG_SCLK_DIV);
353 p0.h = hi(PLL_DIV);
354 p0.l = lo(PLL_DIV);
355 w[p0] = r0.l;
356 ssync;
357
358 p0.l = lo(EBIU_SDRRC);
359 p0.h = hi(EBIU_SDRRC);
360 r0 = mem_SDRRC;
361 w[p0] = r0.l;
362 ssync;
363
364 p0.l = (EBIU_SDBCTL & 0xFFFF);
365 p0.h = (EBIU_SDBCTL >> 16); /* SDRAM Memory Bank Control Register */
366 r0 = mem_SDBCTL;
367 w[p0] = r0.l;
368 ssync;
369
370 P2.H = hi(EBIU_SDGCTL);
371 P2.L = lo(EBIU_SDGCTL);
372 R0 = [P2];
373 BITCLR (R0, 24);
374 p0.h = hi(EBIU_SDSTAT);
375 p0.l = lo(EBIU_SDSTAT);
376 r2.l = w[p0];
377 cc = bittst(r2,3);
378 if !cc jump .Lskip;
379 NOP;
380 BITSET (R0, 23);
381.Lskip:
382 [P2] = R0;
383 SSYNC;
384
385 R0.L = lo(mem_SDGCTL);
386 R0.H = hi(mem_SDGCTL);
387 R1 = [p2];
388 R1 = R1 | R0;
389 [P2] = R1;
390 SSYNC;
391
392 RTS;
393#endif /* CONFIG_BFIN_KERNEL_CLOCK */
394
395ENTRY(_bfin_reset)
396 /* No more interrupts to be handled*/
397 CLI R6;
398 SSYNC;
399
400#if defined(CONFIG_BFIN_SHARED_FLASH_ENET)
401 p0.h = hi(FIO_INEN);
402 p0.l = lo(FIO_INEN);
403 r0.l = ~(PF1 | PF0);
404 w[p0] = r0.l;
405
406 p0.h = hi(FIO_DIR);
407 p0.l = lo(FIO_DIR);
408 r0.l = (PF1 | PF0);
409 w[p0] = r0.l;
410
411 p0.h = hi(FIO_FLAG_C);
412 p0.l = lo(FIO_FLAG_C);
413 r0.l = (PF1 | PF0);
414 w[p0] = r0.l;
415#endif
416
417 /* Clear the bits 13-15 in SWRST if they werent cleared */
418 p0.h = hi(SICA_SWRST);
419 p0.l = lo(SICA_SWRST);
420 csync;
421 r0.l = w[p0];
422
423 /* Clear the IMASK register */
424 p0.h = hi(IMASK);
425 p0.l = lo(IMASK);
426 r0 = 0x0;
427 [p0] = r0;
428
429 /* Clear the ILAT register */
430 p0.h = hi(ILAT);
431 p0.l = lo(ILAT);
432 r0 = [p0];
433 [p0] = r0;
434 SSYNC;
435
436 /* Disable the WDOG TIMER */
437 p0.h = hi(WDOGA_CTL);
438 p0.l = lo(WDOGA_CTL);
439 r0.l = 0xAD6;
440 w[p0] = r0.l;
441 SSYNC;
442
443 /* Clear the sticky bit incase it is already set */
444 p0.h = hi(WDOGA_CTL);
445 p0.l = lo(WDOGA_CTL);
446 r0.l = 0x8AD6;
447 w[p0] = r0.l;
448 SSYNC;
449
450 /* Program the count value */
451 R0.l = 0x100;
452 R0.h = 0x0;
453 P0.h = hi(WDOGA_CNT);
454 P0.l = lo(WDOGA_CNT);
455 [P0] = R0;
456 SSYNC;
457
458 /* Program WDOG_STAT if necessary */
459 P0.h = hi(WDOGA_CTL);
460 P0.l = lo(WDOGA_CTL);
461 R0 = W[P0](Z);
462 CC = BITTST(R0,1);
463 if !CC JUMP .LWRITESTAT;
464 CC = BITTST(R0,2);
465 if !CC JUMP .LWRITESTAT;
466 JUMP .LSKIP_WRITE;
467
468.LWRITESTAT:
469 /* When watch dog timer is enabled,
470 * a write to STAT will load the contents of CNT to STAT
471 */
472 R0 = 0x0000(z);
473 P0.h = hi(WDOGA_STAT);
474 P0.l = lo(WDOGA_STAT)
475 [P0] = R0;
476 SSYNC;
477
478.LSKIP_WRITE:
479 /* Enable the reset event */
480 P0.h = hi(WDOGA_CTL);
481 P0.l = lo(WDOGA_CTL);
482 R0 = W[P0](Z);
483 BITCLR(R0,1);
484 BITCLR(R0,2);
485 W[P0] = R0.L;
486 SSYNC;
487 NOP;
488
489 /* Enable the wdog counter */
490 R0 = W[P0](Z);
491 BITCLR(R0,4);
492 W[P0] = R0.L;
493 SSYNC;
494
495 IDLE;
496
497 RTS;
498
499.data
500
501/*
502 * Set up the usable of RAM stuff. Size of RAM is determined then
503 * an initial stack set up at the end.
504 */
505
506.align 4
507__rambase:
508.long 0
509__ramstart:
510.long 0
511__ramend:
512.long 0