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