xref: /kernel/linux/linux-6.6/arch/m68k/coldfire/head.S (revision 62306a36)
162306a36Sopenharmony_ci/* SPDX-License-Identifier: GPL-2.0 */
262306a36Sopenharmony_ci/*****************************************************************************/
362306a36Sopenharmony_ci
462306a36Sopenharmony_ci/*
562306a36Sopenharmony_ci *	head.S -- common startup code for ColdFire CPUs.
662306a36Sopenharmony_ci *
762306a36Sopenharmony_ci *	(C) Copyright 1999-2011, Greg Ungerer <gerg@snapgear.com>.
862306a36Sopenharmony_ci */
962306a36Sopenharmony_ci
1062306a36Sopenharmony_ci/*****************************************************************************/
1162306a36Sopenharmony_ci
1262306a36Sopenharmony_ci#include <linux/linkage.h>
1362306a36Sopenharmony_ci#include <linux/init.h>
1462306a36Sopenharmony_ci#include <asm/asm-offsets.h>
1562306a36Sopenharmony_ci#include <asm/coldfire.h>
1662306a36Sopenharmony_ci#include <asm/mcfsim.h>
1762306a36Sopenharmony_ci#include <asm/mcfmmu.h>
1862306a36Sopenharmony_ci#include <asm/thread_info.h>
1962306a36Sopenharmony_ci
2062306a36Sopenharmony_ci/*****************************************************************************/
2162306a36Sopenharmony_ci
2262306a36Sopenharmony_ci/*
2362306a36Sopenharmony_ci *	If we don't have a fixed memory size, then lets build in code
2462306a36Sopenharmony_ci *	to auto detect the DRAM size. Obviously this is the preferred
2562306a36Sopenharmony_ci *	method, and should work for most boards. It won't work for those
2662306a36Sopenharmony_ci *	that do not have their RAM starting at address 0, and it only
2762306a36Sopenharmony_ci *	works on SDRAM (not boards fitted with SRAM).
2862306a36Sopenharmony_ci */
2962306a36Sopenharmony_ci#if CONFIG_RAMSIZE != 0
3062306a36Sopenharmony_ci.macro GET_MEM_SIZE
3162306a36Sopenharmony_ci	movel	#CONFIG_RAMSIZE,%d0	/* hard coded memory size */
3262306a36Sopenharmony_ci.endm
3362306a36Sopenharmony_ci
3462306a36Sopenharmony_ci#elif defined(CONFIG_M5206) || defined(CONFIG_M5206e) || \
3562306a36Sopenharmony_ci      defined(CONFIG_M5249) || defined(CONFIG_M525x) || \
3662306a36Sopenharmony_ci      defined(CONFIG_M527x) || defined(CONFIG_M528x) || \
3762306a36Sopenharmony_ci      defined(CONFIG_M5307) || defined(CONFIG_M5407)
3862306a36Sopenharmony_ci/*
3962306a36Sopenharmony_ci *	Not all these devices have exactly the same DRAM controller,
4062306a36Sopenharmony_ci *	but the DCMR register is virtually identical - give or take
4162306a36Sopenharmony_ci *	a couple of bits. The only exception is the 5272 devices, their
4262306a36Sopenharmony_ci *	DRAM controller is quite different.
4362306a36Sopenharmony_ci */
4462306a36Sopenharmony_ci.macro GET_MEM_SIZE
4562306a36Sopenharmony_ci	movel	MCFSIM_DMR0,%d0		/* get mask for 1st bank */
4662306a36Sopenharmony_ci	btst	#0,%d0			/* check if region enabled */
4762306a36Sopenharmony_ci	beq	1f
4862306a36Sopenharmony_ci	andl	#0xfffc0000,%d0
4962306a36Sopenharmony_ci	beq	1f
5062306a36Sopenharmony_ci	addl	#0x00040000,%d0		/* convert mask to size */
5162306a36Sopenharmony_ci1:
5262306a36Sopenharmony_ci	movel	MCFSIM_DMR1,%d1		/* get mask for 2nd bank */
5362306a36Sopenharmony_ci	btst	#0,%d1			/* check if region enabled */
5462306a36Sopenharmony_ci	beq	2f
5562306a36Sopenharmony_ci	andl	#0xfffc0000,%d1
5662306a36Sopenharmony_ci	beq	2f
5762306a36Sopenharmony_ci	addl	#0x00040000,%d1
5862306a36Sopenharmony_ci	addl	%d1,%d0			/* total mem size in d0 */
5962306a36Sopenharmony_ci2:
6062306a36Sopenharmony_ci.endm
6162306a36Sopenharmony_ci
6262306a36Sopenharmony_ci#elif defined(CONFIG_M5272)
6362306a36Sopenharmony_ci.macro GET_MEM_SIZE
6462306a36Sopenharmony_ci	movel	MCFSIM_CSOR7,%d0	/* get SDRAM address mask */
6562306a36Sopenharmony_ci	andil	#0xfffff000,%d0		/* mask out chip select options */
6662306a36Sopenharmony_ci	negl	%d0			/* negate bits */
6762306a36Sopenharmony_ci.endm
6862306a36Sopenharmony_ci
6962306a36Sopenharmony_ci#elif defined(CONFIG_M520x)
7062306a36Sopenharmony_ci.macro GET_MEM_SIZE
7162306a36Sopenharmony_ci	clrl	%d0
7262306a36Sopenharmony_ci	movel	MCFSIM_SDCS0, %d2	/* Get SDRAM chip select 0 config */
7362306a36Sopenharmony_ci	andl	#0x1f, %d2		/* Get only the chip select size */
7462306a36Sopenharmony_ci	beq	3f			/* Check if it is enabled */
7562306a36Sopenharmony_ci	addql	#1, %d2			/* Form exponent */
7662306a36Sopenharmony_ci	moveql	#1, %d0
7762306a36Sopenharmony_ci	lsll	%d2, %d0		/* 2 ^ exponent */
7862306a36Sopenharmony_ci3:
7962306a36Sopenharmony_ci	movel	MCFSIM_SDCS1, %d2	/* Get SDRAM chip select 1 config */
8062306a36Sopenharmony_ci	andl	#0x1f, %d2		/* Get only the chip select size */
8162306a36Sopenharmony_ci	beq	4f			/* Check if it is enabled */
8262306a36Sopenharmony_ci	addql	#1, %d2			/* Form exponent */
8362306a36Sopenharmony_ci	moveql	#1, %d1
8462306a36Sopenharmony_ci	lsll	%d2, %d1		/* 2 ^ exponent */
8562306a36Sopenharmony_ci	addl	%d1, %d0		/* Total size of SDRAM in d0 */
8662306a36Sopenharmony_ci4:
8762306a36Sopenharmony_ci.endm
8862306a36Sopenharmony_ci
8962306a36Sopenharmony_ci#else
9062306a36Sopenharmony_ci#error "ERROR: I don't know how to probe your boards memory size?"
9162306a36Sopenharmony_ci#endif
9262306a36Sopenharmony_ci
9362306a36Sopenharmony_ci/*****************************************************************************/
9462306a36Sopenharmony_ci
9562306a36Sopenharmony_ci/*
9662306a36Sopenharmony_ci *	Boards and platforms can do specific early hardware setup if
9762306a36Sopenharmony_ci *	they need to. Most don't need this, define away if not required.
9862306a36Sopenharmony_ci */
9962306a36Sopenharmony_ci#ifndef PLATFORM_SETUP
10062306a36Sopenharmony_ci#define	PLATFORM_SETUP
10162306a36Sopenharmony_ci#endif
10262306a36Sopenharmony_ci
10362306a36Sopenharmony_ci/*****************************************************************************/
10462306a36Sopenharmony_ci
10562306a36Sopenharmony_ci.global	_start
10662306a36Sopenharmony_ci.global _rambase
10762306a36Sopenharmony_ci.global _ramvec
10862306a36Sopenharmony_ci.global	_ramstart
10962306a36Sopenharmony_ci.global	_ramend
11062306a36Sopenharmony_ci#if defined(CONFIG_UBOOT)
11162306a36Sopenharmony_ci.global	_init_sp
11262306a36Sopenharmony_ci#endif
11362306a36Sopenharmony_ci
11462306a36Sopenharmony_ci/*****************************************************************************/
11562306a36Sopenharmony_ci
11662306a36Sopenharmony_ci.data
11762306a36Sopenharmony_ci
11862306a36Sopenharmony_ci/*
11962306a36Sopenharmony_ci *	During startup we store away the RAM setup. These are not in the
12062306a36Sopenharmony_ci *	bss, since their values are determined and written before the bss
12162306a36Sopenharmony_ci *	has been cleared.
12262306a36Sopenharmony_ci */
12362306a36Sopenharmony_ci_rambase:
12462306a36Sopenharmony_ci.long	0
12562306a36Sopenharmony_ci_ramvec:
12662306a36Sopenharmony_ci.long	0
12762306a36Sopenharmony_ci_ramstart:
12862306a36Sopenharmony_ci.long	0
12962306a36Sopenharmony_ci_ramend:
13062306a36Sopenharmony_ci.long	0
13162306a36Sopenharmony_ci#if defined(CONFIG_UBOOT)
13262306a36Sopenharmony_ci_init_sp:
13362306a36Sopenharmony_ci.long	0
13462306a36Sopenharmony_ci#endif
13562306a36Sopenharmony_ci
13662306a36Sopenharmony_ci/*****************************************************************************/
13762306a36Sopenharmony_ci
13862306a36Sopenharmony_ci__HEAD
13962306a36Sopenharmony_ci
14062306a36Sopenharmony_ci#ifdef CONFIG_MMU
14162306a36Sopenharmony_ci_start0:
14262306a36Sopenharmony_ci	jmp	_start
14362306a36Sopenharmony_ci.global kernel_pg_dir
14462306a36Sopenharmony_ci.equ	kernel_pg_dir,_start0
14562306a36Sopenharmony_ci.equ	.,_start0+0x1000
14662306a36Sopenharmony_ci#endif
14762306a36Sopenharmony_ci
14862306a36Sopenharmony_ci/*
14962306a36Sopenharmony_ci *	This is the codes first entry point. This is where it all
15062306a36Sopenharmony_ci *	begins...
15162306a36Sopenharmony_ci */
15262306a36Sopenharmony_ci
15362306a36Sopenharmony_ci_start:
15462306a36Sopenharmony_ci	nop					/* filler */
15562306a36Sopenharmony_ci	movew	#0x2700, %sr			/* no interrupts */
15662306a36Sopenharmony_ci	movel	#CACHE_INIT,%d0			/* disable cache */
15762306a36Sopenharmony_ci	movec	%d0,%CACR
15862306a36Sopenharmony_ci	nop
15962306a36Sopenharmony_ci#if defined(CONFIG_UBOOT)
16062306a36Sopenharmony_ci	movel	%sp,_init_sp			/* save initial stack pointer */
16162306a36Sopenharmony_ci#endif
16262306a36Sopenharmony_ci#ifdef CONFIG_MBAR
16362306a36Sopenharmony_ci	movel	#CONFIG_MBAR+1,%d0		/* configured MBAR address */
16462306a36Sopenharmony_ci	movec	%d0,%MBAR			/* set it */
16562306a36Sopenharmony_ci#endif
16662306a36Sopenharmony_ci
16762306a36Sopenharmony_ci	/*
16862306a36Sopenharmony_ci	 *	Do any platform or board specific setup now. Most boards
16962306a36Sopenharmony_ci	 *	don't need anything. Those exceptions are define this in
17062306a36Sopenharmony_ci	 *	their board specific includes.
17162306a36Sopenharmony_ci	 */
17262306a36Sopenharmony_ci	PLATFORM_SETUP
17362306a36Sopenharmony_ci
17462306a36Sopenharmony_ci	/*
17562306a36Sopenharmony_ci	 *	Create basic memory configuration. Set VBR accordingly,
17662306a36Sopenharmony_ci	 *	and size memory.
17762306a36Sopenharmony_ci	 */
17862306a36Sopenharmony_ci	movel	#CONFIG_VECTORBASE,%a7
17962306a36Sopenharmony_ci	movec   %a7,%VBR			/* set vectors addr */
18062306a36Sopenharmony_ci	movel	%a7,_ramvec
18162306a36Sopenharmony_ci
18262306a36Sopenharmony_ci	movel	#CONFIG_RAMBASE,%a7		/* mark the base of RAM */
18362306a36Sopenharmony_ci	movel	%a7,_rambase
18462306a36Sopenharmony_ci
18562306a36Sopenharmony_ci	GET_MEM_SIZE				/* macro code determines size */
18662306a36Sopenharmony_ci	addl	%a7,%d0
18762306a36Sopenharmony_ci	movel	%d0,_ramend			/* set end ram addr */
18862306a36Sopenharmony_ci
18962306a36Sopenharmony_ci	/*
19062306a36Sopenharmony_ci	 *	Now that we know what the memory is, lets enable cache
19162306a36Sopenharmony_ci	 *	and get things moving. This is Coldfire CPU specific. Not
19262306a36Sopenharmony_ci	 *	all version cores have identical cache register setup. But
19362306a36Sopenharmony_ci	 *	it is very similar. Define the exact settings in the headers
19462306a36Sopenharmony_ci	 *	then the code here is the same for all.
19562306a36Sopenharmony_ci	 */
19662306a36Sopenharmony_ci	movel	#ACR0_MODE,%d0			/* set RAM region for caching */
19762306a36Sopenharmony_ci	movec	%d0,%ACR0
19862306a36Sopenharmony_ci	movel	#ACR1_MODE,%d0			/* anything else to cache? */
19962306a36Sopenharmony_ci	movec	%d0,%ACR1
20062306a36Sopenharmony_ci#ifdef ACR2_MODE
20162306a36Sopenharmony_ci	movel	#ACR2_MODE,%d0
20262306a36Sopenharmony_ci	movec	%d0,%ACR2
20362306a36Sopenharmony_ci	movel	#ACR3_MODE,%d0
20462306a36Sopenharmony_ci	movec	%d0,%ACR3
20562306a36Sopenharmony_ci#endif
20662306a36Sopenharmony_ci	movel	#CACHE_MODE,%d0			/* enable cache */
20762306a36Sopenharmony_ci	movec	%d0,%CACR
20862306a36Sopenharmony_ci	nop
20962306a36Sopenharmony_ci
21062306a36Sopenharmony_ci#ifdef CONFIG_MMU
21162306a36Sopenharmony_ci	/*
21262306a36Sopenharmony_ci	 *	Identity mapping for the kernel region.
21362306a36Sopenharmony_ci	 */
21462306a36Sopenharmony_ci	movel	#(MMUBASE+1),%d0		/* enable MMUBAR registers */
21562306a36Sopenharmony_ci	movec	%d0,%MMUBAR
21662306a36Sopenharmony_ci	movel	#MMUOR_CA,%d0			/* clear TLB entries */
21762306a36Sopenharmony_ci	movel	%d0,MMUOR
21862306a36Sopenharmony_ci	movel	#0,%d0				/* set ASID to 0 */
21962306a36Sopenharmony_ci	movec	%d0,%asid
22062306a36Sopenharmony_ci
22162306a36Sopenharmony_ci	movel	#MMUCR_EN,%d0			/* Enable the identity map */
22262306a36Sopenharmony_ci	movel	%d0,MMUCR
22362306a36Sopenharmony_ci	nop					/* sync i-pipeline */
22462306a36Sopenharmony_ci
22562306a36Sopenharmony_ci	movel	#_vstart,%a0			/* jump to "virtual" space */
22662306a36Sopenharmony_ci	jmp	%a0@
22762306a36Sopenharmony_ci_vstart:
22862306a36Sopenharmony_ci#endif /* CONFIG_MMU */
22962306a36Sopenharmony_ci
23062306a36Sopenharmony_ci#ifdef CONFIG_ROMFS_FS
23162306a36Sopenharmony_ci	/*
23262306a36Sopenharmony_ci	 *	Move ROM filesystem above bss :-)
23362306a36Sopenharmony_ci	 */
23462306a36Sopenharmony_ci	lea	__bss_start,%a0			/* get start of bss */
23562306a36Sopenharmony_ci	lea	__bss_stop,%a1			/* set up destination  */
23662306a36Sopenharmony_ci	movel	%a0,%a2				/* copy of bss start */
23762306a36Sopenharmony_ci
23862306a36Sopenharmony_ci	movel	8(%a0),%d0			/* get size of ROMFS */
23962306a36Sopenharmony_ci	addql	#8,%d0				/* allow for rounding */
24062306a36Sopenharmony_ci	andl	#0xfffffffc, %d0		/* whole words */
24162306a36Sopenharmony_ci
24262306a36Sopenharmony_ci	addl	%d0,%a0				/* copy from end */
24362306a36Sopenharmony_ci	addl	%d0,%a1				/* copy from end */
24462306a36Sopenharmony_ci	movel	%a1,_ramstart			/* set start of ram */
24562306a36Sopenharmony_ci
24662306a36Sopenharmony_ci_copy_romfs:
24762306a36Sopenharmony_ci	movel	-(%a0),%d0			/* copy dword */
24862306a36Sopenharmony_ci	movel	%d0,-(%a1)
24962306a36Sopenharmony_ci	cmpl	%a0,%a2				/* check if at end */
25062306a36Sopenharmony_ci	bne	_copy_romfs
25162306a36Sopenharmony_ci
25262306a36Sopenharmony_ci#else /* CONFIG_ROMFS_FS */
25362306a36Sopenharmony_ci	lea	__bss_stop,%a1
25462306a36Sopenharmony_ci	movel	%a1,_ramstart
25562306a36Sopenharmony_ci#endif /* CONFIG_ROMFS_FS */
25662306a36Sopenharmony_ci
25762306a36Sopenharmony_ci
25862306a36Sopenharmony_ci	/*
25962306a36Sopenharmony_ci	 *	Zero out the bss region.
26062306a36Sopenharmony_ci	 */
26162306a36Sopenharmony_ci	lea	__bss_start,%a0			/* get start of bss */
26262306a36Sopenharmony_ci	lea	__bss_stop,%a1			/* get end of bss */
26362306a36Sopenharmony_ci	clrl	%d0				/* set value */
26462306a36Sopenharmony_ci_clear_bss:
26562306a36Sopenharmony_ci	movel	%d0,(%a0)+			/* clear each word */
26662306a36Sopenharmony_ci	cmpl	%a0,%a1				/* check if at end */
26762306a36Sopenharmony_ci	bne	_clear_bss
26862306a36Sopenharmony_ci
26962306a36Sopenharmony_ci	/*
27062306a36Sopenharmony_ci	 *	Load the current task pointer and stack.
27162306a36Sopenharmony_ci	 */
27262306a36Sopenharmony_ci	lea	init_thread_union,%a0
27362306a36Sopenharmony_ci	lea	THREAD_SIZE(%a0),%sp
27462306a36Sopenharmony_ci
27562306a36Sopenharmony_ci#ifdef CONFIG_MMU
27662306a36Sopenharmony_ci.global m68k_cputype
27762306a36Sopenharmony_ci.global m68k_mmutype
27862306a36Sopenharmony_ci.global m68k_fputype
27962306a36Sopenharmony_ci.global m68k_machtype
28062306a36Sopenharmony_ci	movel	#CPU_COLDFIRE,%d0
28162306a36Sopenharmony_ci	movel	%d0,m68k_cputype		/* Mark us as a ColdFire */
28262306a36Sopenharmony_ci	movel	#MMU_COLDFIRE,%d0
28362306a36Sopenharmony_ci	movel	%d0,m68k_mmutype
28462306a36Sopenharmony_ci	movel	#FPUTYPE,%d0
28562306a36Sopenharmony_ci	movel	%d0,m68k_fputype		/* Mark FPU type */
28662306a36Sopenharmony_ci	movel	#MACHINE,%d0
28762306a36Sopenharmony_ci	movel	%d0,m68k_machtype		/* Mark machine type */
28862306a36Sopenharmony_ci	lea	init_task,%a2			/* Set "current" init task */
28962306a36Sopenharmony_ci#endif
29062306a36Sopenharmony_ci
29162306a36Sopenharmony_ci	/*
29262306a36Sopenharmony_ci	 *	Assembler start up done, start code proper.
29362306a36Sopenharmony_ci	 */
29462306a36Sopenharmony_ci	jsr	start_kernel			/* start Linux kernel */
29562306a36Sopenharmony_ci
29662306a36Sopenharmony_ci_exit:
29762306a36Sopenharmony_ci	jmp	_exit				/* should never get here */
29862306a36Sopenharmony_ci
29962306a36Sopenharmony_ci/*****************************************************************************/
300