xref: /openbmc/linux/arch/m68k/coldfire/head.S (revision f86b9e03837beafb4b48d53a76ee4b88559226de)
1*f86b9e03SGreg Ungerer/*****************************************************************************/
2*f86b9e03SGreg Ungerer
3*f86b9e03SGreg Ungerer/*
4*f86b9e03SGreg Ungerer *	head.S -- common startup code for ColdFire CPUs.
5*f86b9e03SGreg Ungerer *
6*f86b9e03SGreg Ungerer *	(C) Copyright 1999-2011, Greg Ungerer <gerg@snapgear.com>.
7*f86b9e03SGreg Ungerer */
8*f86b9e03SGreg Ungerer
9*f86b9e03SGreg Ungerer/*****************************************************************************/
10*f86b9e03SGreg Ungerer
11*f86b9e03SGreg Ungerer#include <linux/linkage.h>
12*f86b9e03SGreg Ungerer#include <linux/init.h>
13*f86b9e03SGreg Ungerer#include <asm/asm-offsets.h>
14*f86b9e03SGreg Ungerer#include <asm/coldfire.h>
15*f86b9e03SGreg Ungerer#include <asm/mcfsim.h>
16*f86b9e03SGreg Ungerer#include <asm/mcfmmu.h>
17*f86b9e03SGreg Ungerer#include <asm/thread_info.h>
18*f86b9e03SGreg Ungerer
19*f86b9e03SGreg Ungerer/*****************************************************************************/
20*f86b9e03SGreg Ungerer
21*f86b9e03SGreg Ungerer/*
22*f86b9e03SGreg Ungerer *	If we don't have a fixed memory size, then lets build in code
23*f86b9e03SGreg Ungerer *	to auto detect the DRAM size. Obviously this is the preferred
24*f86b9e03SGreg Ungerer *	method, and should work for most boards. It won't work for those
25*f86b9e03SGreg Ungerer *	that do not have their RAM starting at address 0, and it only
26*f86b9e03SGreg Ungerer *	works on SDRAM (not boards fitted with SRAM).
27*f86b9e03SGreg Ungerer */
28*f86b9e03SGreg Ungerer#if CONFIG_RAMSIZE != 0
29*f86b9e03SGreg Ungerer.macro GET_MEM_SIZE
30*f86b9e03SGreg Ungerer	movel	#CONFIG_RAMSIZE,%d0	/* hard coded memory size */
31*f86b9e03SGreg Ungerer.endm
32*f86b9e03SGreg Ungerer
33*f86b9e03SGreg Ungerer#elif defined(CONFIG_M5206) || defined(CONFIG_M5206e) || \
34*f86b9e03SGreg Ungerer      defined(CONFIG_M5249) || defined(CONFIG_M525x) || \
35*f86b9e03SGreg Ungerer      defined(CONFIG_M527x) || defined(CONFIG_M528x) || \
36*f86b9e03SGreg Ungerer      defined(CONFIG_M5307) || defined(CONFIG_M5407)
37*f86b9e03SGreg Ungerer/*
38*f86b9e03SGreg Ungerer *	Not all these devices have exactly the same DRAM controller,
39*f86b9e03SGreg Ungerer *	but the DCMR register is virtually identical - give or take
40*f86b9e03SGreg Ungerer *	a couple of bits. The only exception is the 5272 devices, their
41*f86b9e03SGreg Ungerer *	DRAM controller is quite different.
42*f86b9e03SGreg Ungerer */
43*f86b9e03SGreg Ungerer.macro GET_MEM_SIZE
44*f86b9e03SGreg Ungerer	movel	MCFSIM_DMR0,%d0		/* get mask for 1st bank */
45*f86b9e03SGreg Ungerer	btst	#0,%d0			/* check if region enabled */
46*f86b9e03SGreg Ungerer	beq	1f
47*f86b9e03SGreg Ungerer	andl	#0xfffc0000,%d0
48*f86b9e03SGreg Ungerer	beq	1f
49*f86b9e03SGreg Ungerer	addl	#0x00040000,%d0		/* convert mask to size */
50*f86b9e03SGreg Ungerer1:
51*f86b9e03SGreg Ungerer	movel	MCFSIM_DMR1,%d1		/* get mask for 2nd bank */
52*f86b9e03SGreg Ungerer	btst	#0,%d1			/* check if region enabled */
53*f86b9e03SGreg Ungerer	beq	2f
54*f86b9e03SGreg Ungerer	andl	#0xfffc0000,%d1
55*f86b9e03SGreg Ungerer	beq	2f
56*f86b9e03SGreg Ungerer	addl	#0x00040000,%d1
57*f86b9e03SGreg Ungerer	addl	%d1,%d0			/* total mem size in d0 */
58*f86b9e03SGreg Ungerer2:
59*f86b9e03SGreg Ungerer.endm
60*f86b9e03SGreg Ungerer
61*f86b9e03SGreg Ungerer#elif defined(CONFIG_M5272)
62*f86b9e03SGreg Ungerer.macro GET_MEM_SIZE
63*f86b9e03SGreg Ungerer	movel	MCFSIM_CSOR7,%d0	/* get SDRAM address mask */
64*f86b9e03SGreg Ungerer	andil	#0xfffff000,%d0		/* mask out chip select options */
65*f86b9e03SGreg Ungerer	negl	%d0			/* negate bits */
66*f86b9e03SGreg Ungerer.endm
67*f86b9e03SGreg Ungerer
68*f86b9e03SGreg Ungerer#elif defined(CONFIG_M520x)
69*f86b9e03SGreg Ungerer.macro GET_MEM_SIZE
70*f86b9e03SGreg Ungerer	clrl	%d0
71*f86b9e03SGreg Ungerer	movel	MCFSIM_SDCS0, %d2	/* Get SDRAM chip select 0 config */
72*f86b9e03SGreg Ungerer	andl	#0x1f, %d2		/* Get only the chip select size */
73*f86b9e03SGreg Ungerer	beq	3f			/* Check if it is enabled */
74*f86b9e03SGreg Ungerer	addql	#1, %d2			/* Form exponent */
75*f86b9e03SGreg Ungerer	moveql	#1, %d0
76*f86b9e03SGreg Ungerer	lsll	%d2, %d0		/* 2 ^ exponent */
77*f86b9e03SGreg Ungerer3:
78*f86b9e03SGreg Ungerer	movel	MCFSIM_SDCS1, %d2	/* Get SDRAM chip select 1 config */
79*f86b9e03SGreg Ungerer	andl	#0x1f, %d2		/* Get only the chip select size */
80*f86b9e03SGreg Ungerer	beq	4f			/* Check if it is enabled */
81*f86b9e03SGreg Ungerer	addql	#1, %d2			/* Form exponent */
82*f86b9e03SGreg Ungerer	moveql	#1, %d1
83*f86b9e03SGreg Ungerer	lsll	%d2, %d1		/* 2 ^ exponent */
84*f86b9e03SGreg Ungerer	addl	%d1, %d0		/* Total size of SDRAM in d0 */
85*f86b9e03SGreg Ungerer4:
86*f86b9e03SGreg Ungerer.endm
87*f86b9e03SGreg Ungerer
88*f86b9e03SGreg Ungerer#else
89*f86b9e03SGreg Ungerer#error "ERROR: I don't know how to probe your boards memory size?"
90*f86b9e03SGreg Ungerer#endif
91*f86b9e03SGreg Ungerer
92*f86b9e03SGreg Ungerer/*****************************************************************************/
93*f86b9e03SGreg Ungerer
94*f86b9e03SGreg Ungerer/*
95*f86b9e03SGreg Ungerer *	Boards and platforms can do specific early hardware setup if
96*f86b9e03SGreg Ungerer *	they need to. Most don't need this, define away if not required.
97*f86b9e03SGreg Ungerer */
98*f86b9e03SGreg Ungerer#ifndef PLATFORM_SETUP
99*f86b9e03SGreg Ungerer#define	PLATFORM_SETUP
100*f86b9e03SGreg Ungerer#endif
101*f86b9e03SGreg Ungerer
102*f86b9e03SGreg Ungerer/*****************************************************************************/
103*f86b9e03SGreg Ungerer
104*f86b9e03SGreg Ungerer.global	_start
105*f86b9e03SGreg Ungerer.global _rambase
106*f86b9e03SGreg Ungerer.global _ramvec
107*f86b9e03SGreg Ungerer.global	_ramstart
108*f86b9e03SGreg Ungerer.global	_ramend
109*f86b9e03SGreg Ungerer#if defined(CONFIG_UBOOT)
110*f86b9e03SGreg Ungerer.global	_init_sp
111*f86b9e03SGreg Ungerer#endif
112*f86b9e03SGreg Ungerer
113*f86b9e03SGreg Ungerer/*****************************************************************************/
114*f86b9e03SGreg Ungerer
115*f86b9e03SGreg Ungerer.data
116*f86b9e03SGreg Ungerer
117*f86b9e03SGreg Ungerer/*
118*f86b9e03SGreg Ungerer *	During startup we store away the RAM setup. These are not in the
119*f86b9e03SGreg Ungerer *	bss, since their values are determined and written before the bss
120*f86b9e03SGreg Ungerer *	has been cleared.
121*f86b9e03SGreg Ungerer */
122*f86b9e03SGreg Ungerer_rambase:
123*f86b9e03SGreg Ungerer.long	0
124*f86b9e03SGreg Ungerer_ramvec:
125*f86b9e03SGreg Ungerer.long	0
126*f86b9e03SGreg Ungerer_ramstart:
127*f86b9e03SGreg Ungerer.long	0
128*f86b9e03SGreg Ungerer_ramend:
129*f86b9e03SGreg Ungerer.long	0
130*f86b9e03SGreg Ungerer#if defined(CONFIG_UBOOT)
131*f86b9e03SGreg Ungerer_init_sp:
132*f86b9e03SGreg Ungerer.long	0
133*f86b9e03SGreg Ungerer#endif
134*f86b9e03SGreg Ungerer
135*f86b9e03SGreg Ungerer/*****************************************************************************/
136*f86b9e03SGreg Ungerer
137*f86b9e03SGreg Ungerer__HEAD
138*f86b9e03SGreg Ungerer
139*f86b9e03SGreg Ungerer#ifdef CONFIG_MMU
140*f86b9e03SGreg Ungerer_start0:
141*f86b9e03SGreg Ungerer	jmp	_start
142*f86b9e03SGreg Ungerer.global kernel_pg_dir
143*f86b9e03SGreg Ungerer.equ	kernel_pg_dir,_start0
144*f86b9e03SGreg Ungerer.equ	.,_start0+0x1000
145*f86b9e03SGreg Ungerer#endif
146*f86b9e03SGreg Ungerer
147*f86b9e03SGreg Ungerer/*
148*f86b9e03SGreg Ungerer *	This is the codes first entry point. This is where it all
149*f86b9e03SGreg Ungerer *	begins...
150*f86b9e03SGreg Ungerer */
151*f86b9e03SGreg Ungerer
152*f86b9e03SGreg Ungerer_start:
153*f86b9e03SGreg Ungerer	nop					/* filler */
154*f86b9e03SGreg Ungerer	movew	#0x2700, %sr			/* no interrupts */
155*f86b9e03SGreg Ungerer	movel	#CACHE_INIT,%d0			/* disable cache */
156*f86b9e03SGreg Ungerer	movec	%d0,%CACR
157*f86b9e03SGreg Ungerer	nop
158*f86b9e03SGreg Ungerer#if defined(CONFIG_UBOOT)
159*f86b9e03SGreg Ungerer	movel	%sp,_init_sp			/* save initial stack pointer */
160*f86b9e03SGreg Ungerer#endif
161*f86b9e03SGreg Ungerer#ifdef CONFIG_MBAR
162*f86b9e03SGreg Ungerer	movel	#CONFIG_MBAR+1,%d0		/* configured MBAR address */
163*f86b9e03SGreg Ungerer	movec	%d0,%MBAR			/* set it */
164*f86b9e03SGreg Ungerer#endif
165*f86b9e03SGreg Ungerer
166*f86b9e03SGreg Ungerer	/*
167*f86b9e03SGreg Ungerer	 *	Do any platform or board specific setup now. Most boards
168*f86b9e03SGreg Ungerer	 *	don't need anything. Those exceptions are define this in
169*f86b9e03SGreg Ungerer	 *	their board specific includes.
170*f86b9e03SGreg Ungerer	 */
171*f86b9e03SGreg Ungerer	PLATFORM_SETUP
172*f86b9e03SGreg Ungerer
173*f86b9e03SGreg Ungerer	/*
174*f86b9e03SGreg Ungerer	 *	Create basic memory configuration. Set VBR accordingly,
175*f86b9e03SGreg Ungerer	 *	and size memory.
176*f86b9e03SGreg Ungerer	 */
177*f86b9e03SGreg Ungerer	movel	#CONFIG_VECTORBASE,%a7
178*f86b9e03SGreg Ungerer	movec   %a7,%VBR			/* set vectors addr */
179*f86b9e03SGreg Ungerer	movel	%a7,_ramvec
180*f86b9e03SGreg Ungerer
181*f86b9e03SGreg Ungerer	movel	#CONFIG_RAMBASE,%a7		/* mark the base of RAM */
182*f86b9e03SGreg Ungerer	movel	%a7,_rambase
183*f86b9e03SGreg Ungerer
184*f86b9e03SGreg Ungerer	GET_MEM_SIZE				/* macro code determines size */
185*f86b9e03SGreg Ungerer	addl	%a7,%d0
186*f86b9e03SGreg Ungerer	movel	%d0,_ramend			/* set end ram addr */
187*f86b9e03SGreg Ungerer
188*f86b9e03SGreg Ungerer	/*
189*f86b9e03SGreg Ungerer	 *	Now that we know what the memory is, lets enable cache
190*f86b9e03SGreg Ungerer	 *	and get things moving. This is Coldfire CPU specific. Not
191*f86b9e03SGreg Ungerer	 *	all version cores have identical cache register setup. But
192*f86b9e03SGreg Ungerer	 *	it is very similar. Define the exact settings in the headers
193*f86b9e03SGreg Ungerer	 *	then the code here is the same for all.
194*f86b9e03SGreg Ungerer	 */
195*f86b9e03SGreg Ungerer	movel	#ACR0_MODE,%d0			/* set RAM region for caching */
196*f86b9e03SGreg Ungerer	movec	%d0,%ACR0
197*f86b9e03SGreg Ungerer	movel	#ACR1_MODE,%d0			/* anything else to cache? */
198*f86b9e03SGreg Ungerer	movec	%d0,%ACR1
199*f86b9e03SGreg Ungerer#ifdef ACR2_MODE
200*f86b9e03SGreg Ungerer	movel	#ACR2_MODE,%d0
201*f86b9e03SGreg Ungerer	movec	%d0,%ACR2
202*f86b9e03SGreg Ungerer	movel	#ACR3_MODE,%d0
203*f86b9e03SGreg Ungerer	movec	%d0,%ACR3
204*f86b9e03SGreg Ungerer#endif
205*f86b9e03SGreg Ungerer	movel	#CACHE_MODE,%d0			/* enable cache */
206*f86b9e03SGreg Ungerer	movec	%d0,%CACR
207*f86b9e03SGreg Ungerer	nop
208*f86b9e03SGreg Ungerer
209*f86b9e03SGreg Ungerer#ifdef CONFIG_MMU
210*f86b9e03SGreg Ungerer	/*
211*f86b9e03SGreg Ungerer	 *	Identity mapping for the kernel region.
212*f86b9e03SGreg Ungerer	 */
213*f86b9e03SGreg Ungerer	movel	#(MMUBASE+1),%d0		/* enable MMUBAR registers */
214*f86b9e03SGreg Ungerer	movec	%d0,%MMUBAR
215*f86b9e03SGreg Ungerer	movel	#MMUOR_CA,%d0			/* clear TLB entries */
216*f86b9e03SGreg Ungerer	movel	%d0,MMUOR
217*f86b9e03SGreg Ungerer	movel	#0,%d0				/* set ASID to 0 */
218*f86b9e03SGreg Ungerer	movec	%d0,%asid
219*f86b9e03SGreg Ungerer
220*f86b9e03SGreg Ungerer	movel	#MMUCR_EN,%d0			/* Enable the identity map */
221*f86b9e03SGreg Ungerer	movel	%d0,MMUCR
222*f86b9e03SGreg Ungerer	nop					/* sync i-pipeline */
223*f86b9e03SGreg Ungerer
224*f86b9e03SGreg Ungerer	movel	#_vstart,%a0			/* jump to "virtual" space */
225*f86b9e03SGreg Ungerer	jmp	%a0@
226*f86b9e03SGreg Ungerer_vstart:
227*f86b9e03SGreg Ungerer#endif /* CONFIG_MMU */
228*f86b9e03SGreg Ungerer
229*f86b9e03SGreg Ungerer#ifdef CONFIG_ROMFS_FS
230*f86b9e03SGreg Ungerer	/*
231*f86b9e03SGreg Ungerer	 *	Move ROM filesystem above bss :-)
232*f86b9e03SGreg Ungerer	 */
233*f86b9e03SGreg Ungerer	lea	__bss_start,%a0			/* get start of bss */
234*f86b9e03SGreg Ungerer	lea	__bss_stop,%a1			/* set up destination  */
235*f86b9e03SGreg Ungerer	movel	%a0,%a2				/* copy of bss start */
236*f86b9e03SGreg Ungerer
237*f86b9e03SGreg Ungerer	movel	8(%a0),%d0			/* get size of ROMFS */
238*f86b9e03SGreg Ungerer	addql	#8,%d0				/* allow for rounding */
239*f86b9e03SGreg Ungerer	andl	#0xfffffffc, %d0		/* whole words */
240*f86b9e03SGreg Ungerer
241*f86b9e03SGreg Ungerer	addl	%d0,%a0				/* copy from end */
242*f86b9e03SGreg Ungerer	addl	%d0,%a1				/* copy from end */
243*f86b9e03SGreg Ungerer	movel	%a1,_ramstart			/* set start of ram */
244*f86b9e03SGreg Ungerer
245*f86b9e03SGreg Ungerer_copy_romfs:
246*f86b9e03SGreg Ungerer	movel	-(%a0),%d0			/* copy dword */
247*f86b9e03SGreg Ungerer	movel	%d0,-(%a1)
248*f86b9e03SGreg Ungerer	cmpl	%a0,%a2				/* check if at end */
249*f86b9e03SGreg Ungerer	bne	_copy_romfs
250*f86b9e03SGreg Ungerer
251*f86b9e03SGreg Ungerer#else /* CONFIG_ROMFS_FS */
252*f86b9e03SGreg Ungerer	lea	__bss_stop,%a1
253*f86b9e03SGreg Ungerer	movel	%a1,_ramstart
254*f86b9e03SGreg Ungerer#endif /* CONFIG_ROMFS_FS */
255*f86b9e03SGreg Ungerer
256*f86b9e03SGreg Ungerer
257*f86b9e03SGreg Ungerer	/*
258*f86b9e03SGreg Ungerer	 *	Zero out the bss region.
259*f86b9e03SGreg Ungerer	 */
260*f86b9e03SGreg Ungerer	lea	__bss_start,%a0			/* get start of bss */
261*f86b9e03SGreg Ungerer	lea	__bss_stop,%a1			/* get end of bss */
262*f86b9e03SGreg Ungerer	clrl	%d0				/* set value */
263*f86b9e03SGreg Ungerer_clear_bss:
264*f86b9e03SGreg Ungerer	movel	%d0,(%a0)+			/* clear each word */
265*f86b9e03SGreg Ungerer	cmpl	%a0,%a1				/* check if at end */
266*f86b9e03SGreg Ungerer	bne	_clear_bss
267*f86b9e03SGreg Ungerer
268*f86b9e03SGreg Ungerer	/*
269*f86b9e03SGreg Ungerer	 *	Load the current task pointer and stack.
270*f86b9e03SGreg Ungerer	 */
271*f86b9e03SGreg Ungerer	lea	init_thread_union,%a0
272*f86b9e03SGreg Ungerer	lea	THREAD_SIZE(%a0),%sp
273*f86b9e03SGreg Ungerer
274*f86b9e03SGreg Ungerer#ifdef CONFIG_MMU
275*f86b9e03SGreg Ungerer.global m68k_cputype
276*f86b9e03SGreg Ungerer.global m68k_mmutype
277*f86b9e03SGreg Ungerer.global m68k_fputype
278*f86b9e03SGreg Ungerer.global m68k_machtype
279*f86b9e03SGreg Ungerer	movel	#CPU_COLDFIRE,%d0
280*f86b9e03SGreg Ungerer	movel	%d0,m68k_cputype		/* Mark us as a ColdFire */
281*f86b9e03SGreg Ungerer	movel	#MMU_COLDFIRE,%d0
282*f86b9e03SGreg Ungerer	movel	%d0,m68k_mmutype
283*f86b9e03SGreg Ungerer	movel	#FPU_COLDFIRE,%d0
284*f86b9e03SGreg Ungerer	movel	%d0,m68k_fputype
285*f86b9e03SGreg Ungerer	movel	#MACH_M54XX,%d0
286*f86b9e03SGreg Ungerer	movel	%d0,m68k_machtype		/* Mark us as a 54xx machine */
287*f86b9e03SGreg Ungerer	lea	init_task,%a2			/* Set "current" init task */
288*f86b9e03SGreg Ungerer#endif
289*f86b9e03SGreg Ungerer
290*f86b9e03SGreg Ungerer	/*
291*f86b9e03SGreg Ungerer	 *	Assember start up done, start code proper.
292*f86b9e03SGreg Ungerer	 */
293*f86b9e03SGreg Ungerer	jsr	start_kernel			/* start Linux kernel */
294*f86b9e03SGreg Ungerer
295*f86b9e03SGreg Ungerer_exit:
296*f86b9e03SGreg Ungerer	jmp	_exit				/* should never get here */
297*f86b9e03SGreg Ungerer
298*f86b9e03SGreg Ungerer/*****************************************************************************/
299