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 <linux/init.h>
32#include <asm/blackfin.h>
33#if CONFIG_BFIN_KERNEL_CLOCK
34#include <asm/mach/mem_init.h>
35#endif
36
37.global __rambase
38.global __ramstart
39.global __ramend
40.extern ___bss_stop
41.extern ___bss_start
42.extern _bf53x_relocate_l1_mem
43
44#define INITIAL_STACK	0xFFB01000
45
46__INIT
47
48ENTRY(__start)
49	/* R0: argument of command line string, passed from uboot, save it */
50	R7 = R0;
51	/* Set the SYSCFG register:
52	 * Enable Cycle Counter and Nesting Of Interrupts (3rd Bit)
53	 */
54	R0 = 0x36;
55	SYSCFG = R0;
56	R0 = 0;
57
58	/* Clear Out All the data and pointer Registers */
59	R1 = R0;
60	R2 = R0;
61	R3 = R0;
62	R4 = R0;
63	R5 = R0;
64	R6 = R0;
65
66	P0 = R0;
67	P1 = R0;
68	P2 = R0;
69	P3 = R0;
70	P4 = R0;
71	P5 = R0;
72
73	LC0 = r0;
74	LC1 = r0;
75	L0 = r0;
76	L1 = r0;
77	L2 = r0;
78	L3 = r0;
79
80	/* Clear Out All the DAG Registers */
81	B0 = r0;
82	B1 = r0;
83	B2 = r0;
84	B3 = r0;
85
86	I0 = r0;
87	I1 = r0;
88	I2 = r0;
89	I3 = r0;
90
91	M0 = r0;
92	M1 = r0;
93	M2 = r0;
94	M3 = r0;
95
96	/* Turn off the icache */
97	p0.l = (IMEM_CONTROL & 0xFFFF);
98	p0.h = (IMEM_CONTROL >> 16);
99	R1 = [p0];
100	R0 = ~ENICPLB;
101	R0 = R0 & R1;
102
103	/* Anomaly 05000125 */
104#ifdef ANOMALY_05000125
105	CLI R2;
106	SSYNC;
107#endif
108	[p0] = R0;
109	SSYNC;
110#ifdef ANOMALY_05000125
111	STI R2;
112#endif
113
114	/* Turn off the dcache */
115	p0.l = (DMEM_CONTROL & 0xFFFF);
116	p0.h = (DMEM_CONTROL >> 16);
117	R1 = [p0];
118	R0 = ~ENDCPLB;
119	R0 = R0 & R1;
120
121	/* Anomaly 05000125 */
122#ifdef ANOMALY_05000125
123	CLI R2;
124	SSYNC;
125#endif
126	[p0] = R0;
127	SSYNC;
128#ifdef ANOMALY_05000125
129	STI R2;
130#endif
131
132	/* Initialise UART - when booting from u-boot, the UART is not disabled
133	 * so if we dont initalize here, our serial console gets hosed */
134	p0.h = hi(UART_LCR);
135	p0.l = lo(UART_LCR);
136	r0 = 0x0(Z);
137	w[p0] = r0.L;	/* To enable DLL writes */
138	ssync;
139
140	p0.h = hi(UART_DLL);
141	p0.l = lo(UART_DLL);
142	r0 = 0x0(Z);
143	w[p0] = r0.L;
144	ssync;
145
146	p0.h = hi(UART_DLH);
147	p0.l = lo(UART_DLH);
148	r0 = 0x00(Z);
149	w[p0] = r0.L;
150	ssync;
151
152	p0.h = hi(UART_GCTL);
153	p0.l = lo(UART_GCTL);
154	r0 = 0x0(Z);
155	w[p0] = r0.L;	/* To enable UART clock */
156	ssync;
157
158	/* Initialize stack pointer */
159	sp.l = lo(INITIAL_STACK);
160	sp.h = hi(INITIAL_STACK);
161	fp = sp;
162	usp = sp;
163
164	/* Put The Code for PLL Programming and SDRAM Programming in L1 ISRAM */
165	call _bf53x_relocate_l1_mem;
166#if CONFIG_BFIN_KERNEL_CLOCK
167	call _start_dma_code;
168#endif
169
170	/* Code for initializing Async memory banks */
171
172	p2.h = hi(EBIU_AMBCTL1);
173	p2.l = lo(EBIU_AMBCTL1);
174	r0.h = hi(AMBCTL1VAL);
175	r0.l = lo(AMBCTL1VAL);
176	[p2] = r0;
177	ssync;
178
179	p2.h = hi(EBIU_AMBCTL0);
180	p2.l = lo(EBIU_AMBCTL0);
181	r0.h = hi(AMBCTL0VAL);
182	r0.l = lo(AMBCTL0VAL);
183	[p2] = r0;
184	ssync;
185
186	p2.h = hi(EBIU_AMGCTL);
187	p2.l = lo(EBIU_AMGCTL);
188	r0 = AMGCTLVAL;
189	w[p2] = r0;
190	ssync;
191
192	/* This section keeps the processor in supervisor mode
193	 * during kernel boot.  Switches to user mode at end of boot.
194	 * See page 3-9 of Hardware Reference manual for documentation.
195	 */
196
197	/* EVT15 = _real_start */
198
199	p0.l = lo(EVT15);
200	p0.h = hi(EVT15);
201	p1.l = _real_start;
202	p1.h = _real_start;
203	[p0] = p1;
204	csync;
205
206	p0.l = lo(IMASK);
207	p0.h = hi(IMASK);
208	p1.l = IMASK_IVG15;
209	p1.h = 0x0;
210	[p0] = p1;
211	csync;
212
213	raise 15;
214	p0.l = .LWAIT_HERE;
215	p0.h = .LWAIT_HERE;
216	reti = p0;
217#if defined(ANOMALY_05000281)
218	nop; nop; nop;
219#endif
220	rti;
221
222.LWAIT_HERE:
223	jump .LWAIT_HERE;
224ENDPROC(__start)
225
226ENTRY(_real_start)
227	[ -- sp ] = reti;
228	p0.l = lo(WDOGA_CTL);
229	p0.h = hi(WDOGA_CTL);
230	r0 = 0xAD6(z);
231	w[p0] = r0;	/* watchdog off for now */
232	ssync;
233
234	/* Code update for BSS size == 0
235	 * Zero out the bss region.
236	 */
237
238	p1.l = ___bss_start;
239	p1.h = ___bss_start;
240	p2.l = ___bss_stop;
241	p2.h = ___bss_stop;
242	r0 = 0;
243	p2 -= p1;
244	lsetup (.L_clear_bss, .L_clear_bss) lc0 = p2;
245.L_clear_bss:
246	B[p1++] = r0;
247
248	/* In case there is a NULL pointer reference
249	 * Zero out region before stext
250	 */
251
252	p1.l = 0x0;
253	p1.h = 0x0;
254	r0.l = __stext;
255	r0.h = __stext;
256	r0 = r0 >> 1;
257	p2 = r0;
258	r0 = 0;
259	lsetup (.L_clear_zero, .L_clear_zero) lc0 = p2;
260.L_clear_zero:
261	W[p1++] = r0;
262
263	/* pass the uboot arguments to the global value command line */
264	R0 = R7;
265	call _cmdline_init;
266
267	p1.l = __rambase;
268	p1.h = __rambase;
269	r0.l = __sdata;
270	r0.h = __sdata;
271	[p1] = r0;
272
273	p1.l = __ramstart;
274	p1.h = __ramstart;
275	p3.l = ___bss_stop;
276	p3.h = ___bss_stop;
277
278	r1 = p3;
279	[p1] = r1;
280
281	/*
282	 * load the current thread pointer and stack
283	 */
284	r1.l = _init_thread_union;
285	r1.h = _init_thread_union;
286
287	r2.l = 0x2000;
288	r2.h = 0x0000;
289	r1 = r1 + r2;
290	sp = r1;
291	usp = sp;
292	fp = sp;
293	jump.l _start_kernel;
294ENDPROC(_real_start)
295
296__FINIT
297
298.section .l1.text
299#if CONFIG_BFIN_KERNEL_CLOCK
300ENTRY(_start_dma_code)
301	p0.h = hi(SICA_IWR0);
302	p0.l = lo(SICA_IWR0);
303	r0.l = 0x1;
304	[p0] = r0;
305	SSYNC;
306
307	/*
308	 *  Set PLL_CTL
309	 *   - [14:09] = MSEL[5:0] : CLKIN / VCO multiplication factors
310	 *   - [8]     = BYPASS    : BYPASS the PLL, run CLKIN into CCLK/SCLK
311	 *   - [7]     = output delay (add 200ps of delay to mem signals)
312	 *   - [6]     = input delay (add 200ps of input delay to mem signals)
313	 *   - [5]     = PDWN      : 1=All Clocks off
314	 *   - [3]     = STOPCK    : 1=Core Clock off
315	 *   - [1]     = PLL_OFF   : 1=Disable Power to PLL
316	 *   - [0]     = DF        : 1=Pass CLKIN/2 to PLL / 0=Pass CLKIN to PLL
317	 *   all other bits set to zero
318	 */
319
320	p0.h = hi(PLL_LOCKCNT);
321	p0.l = lo(PLL_LOCKCNT);
322	r0 = 0x300(Z);
323	w[p0] = r0.l;
324	ssync;
325
326	P2.H = hi(EBIU_SDGCTL);
327	P2.L = lo(EBIU_SDGCTL);
328	R0 = [P2];
329	BITSET (R0, 24);
330	[P2] = R0;
331	SSYNC;
332
333	r0 = CONFIG_VCO_MULT & 63;       /* Load the VCO multiplier         */
334	r0 = r0 << 9;                    /* Shift it over,                  */
335	r1 = CLKIN_HALF;                 /* Do we need to divide CLKIN by 2?*/
336	r0 = r1 | r0;
337	r1 = PLL_BYPASS;                 /* Bypass the PLL?                 */
338	r1 = r1 << 8;                    /* Shift it over                   */
339	r0 = r1 | r0;                    /* add them all together           */
340
341	p0.h = hi(PLL_CTL);
342	p0.l = lo(PLL_CTL);              /* Load the address                */
343	cli r2;                          /* Disable interrupts              */
344	ssync;
345	w[p0] = r0.l;                    /* Set the value                   */
346	idle;                            /* Wait for the PLL to stablize    */
347	sti r2;                          /* Enable interrupts               */
348
349.Lcheck_again:
350	p0.h = hi(PLL_STAT);
351	p0.l = lo(PLL_STAT);
352	R0 = W[P0](Z);
353	CC = BITTST(R0,5);
354	if ! CC jump .Lcheck_again;
355
356	/* Configure SCLK & CCLK Dividers */
357	r0 = (CONFIG_CCLK_ACT_DIV | CONFIG_SCLK_DIV);
358	p0.h = hi(PLL_DIV);
359	p0.l = lo(PLL_DIV);
360	w[p0] = r0.l;
361	ssync;
362
363	p0.l = lo(EBIU_SDRRC);
364	p0.h = hi(EBIU_SDRRC);
365	r0 = mem_SDRRC;
366	w[p0] = r0.l;
367	ssync;
368
369	p0.l = (EBIU_SDBCTL & 0xFFFF);
370	p0.h = (EBIU_SDBCTL >> 16);     /* SDRAM Memory Bank Control Register */
371	r0 = mem_SDBCTL;
372	w[p0] = r0.l;
373	ssync;
374
375	P2.H = hi(EBIU_SDGCTL);
376	P2.L = lo(EBIU_SDGCTL);
377	R0 = [P2];
378	BITCLR (R0, 24);
379	p0.h = hi(EBIU_SDSTAT);
380	p0.l = lo(EBIU_SDSTAT);
381	r2.l = w[p0];
382	cc = bittst(r2,3);
383	if !cc jump .Lskip;
384	NOP;
385	BITSET (R0, 23);
386.Lskip:
387	[P2] = R0;
388	SSYNC;
389
390	R0.L = lo(mem_SDGCTL);
391	R0.H = hi(mem_SDGCTL);
392	R1 = [p2];
393	R1 = R1 | R0;
394	[P2] = R1;
395	SSYNC;
396
397	RTS;
398ENDPROC(_start_dma_code)
399#endif /* CONFIG_BFIN_KERNEL_CLOCK */
400
401ENTRY(_bfin_reset)
402	/* No more interrupts to be handled*/
403	CLI R6;
404	SSYNC;
405
406#if defined(CONFIG_BFIN_SHARED_FLASH_ENET)
407	p0.h = hi(FIO_INEN);
408	p0.l = lo(FIO_INEN);
409	r0.l = ~(PF1 | PF0);
410	w[p0] = r0.l;
411
412	p0.h = hi(FIO_DIR);
413	p0.l = lo(FIO_DIR);
414	r0.l = (PF1 | PF0);
415	w[p0] = r0.l;
416
417	p0.h = hi(FIO_FLAG_C);
418	p0.l = lo(FIO_FLAG_C);
419	r0.l = (PF1 | PF0);
420	w[p0] = r0.l;
421#endif
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	/* make sure SYSCR is set to use BMODE */
437	P0.h = hi(SICA_SYSCR);
438	P0.l = lo(SICA_SYSCR);
439	R0.l = 0x20;
440	W[P0] = R0.l;
441	SSYNC;
442
443	/* issue a system soft reset */
444	P1.h = hi(SICA_SWRST);
445	P1.l = lo(SICA_SWRST);
446	R1.l = 0x0007;
447	W[P1] = R1;
448	SSYNC;
449
450	/* clear system soft reset */
451	R0.l = 0x0000;
452	W[P0] = R0;
453	SSYNC;
454
455	/* issue core reset */
456	raise 1;
457
458	RTS;
459ENDPROC(_bfin_reset)
460
461.data
462
463/*
464 * Set up the usable of RAM stuff. Size of RAM is determined then
465 * an initial stack set up at the end.
466 */
467
468.align 4
469__rambase:
470.long   0
471__ramstart:
472.long   0
473__ramend:
474.long   0
475