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