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