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