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