1*4882a593Smuzhiyun/* SPDX-License-Identifier: GPL-2.0 */ 2*4882a593Smuzhiyun/* 3*4882a593Smuzhiyun * head.S - Common startup code for 68000 core based CPU's 4*4882a593Smuzhiyun * 5*4882a593Smuzhiyun * 2012.10.21, Luis Alves <ljalvs@gmail.com>, Single head.S file for all 6*4882a593Smuzhiyun * 68000 core based CPU's. Based on the sources from: 7*4882a593Smuzhiyun * Coldfire by Greg Ungerer <gerg@snapgear.com> 8*4882a593Smuzhiyun * 68328 by D. Jeff Dionne <jeff@ryeham.ee.ryerson.ca>, 9*4882a593Smuzhiyun * Kenneth Albanowski <kjahds@kjahds.com>, 10*4882a593Smuzhiyun * The Silver Hammer Group, Ltd. 11*4882a593Smuzhiyun * 12*4882a593Smuzhiyun */ 13*4882a593Smuzhiyun 14*4882a593Smuzhiyun#include <linux/linkage.h> 15*4882a593Smuzhiyun#include <linux/init.h> 16*4882a593Smuzhiyun#include <asm/asm-offsets.h> 17*4882a593Smuzhiyun#include <asm/thread_info.h> 18*4882a593Smuzhiyun 19*4882a593Smuzhiyun 20*4882a593Smuzhiyun/***************************************************************************** 21*4882a593Smuzhiyun * UCSIMM and UCDIMM use CONFIG_MEMORY_RESERVE to reserve some RAM 22*4882a593Smuzhiyun *****************************************************************************/ 23*4882a593Smuzhiyun#ifdef CONFIG_MEMORY_RESERVE 24*4882a593Smuzhiyun#define RAMEND (CONFIG_RAMBASE+CONFIG_RAMSIZE)-(CONFIG_MEMORY_RESERVE*0x100000) 25*4882a593Smuzhiyun#else 26*4882a593Smuzhiyun#define RAMEND (CONFIG_RAMBASE+CONFIG_RAMSIZE) 27*4882a593Smuzhiyun#endif 28*4882a593Smuzhiyun/*****************************************************************************/ 29*4882a593Smuzhiyun 30*4882a593Smuzhiyun.global _start 31*4882a593Smuzhiyun.global _rambase 32*4882a593Smuzhiyun.global _ramvec 33*4882a593Smuzhiyun.global _ramstart 34*4882a593Smuzhiyun.global _ramend 35*4882a593Smuzhiyun 36*4882a593Smuzhiyun#if defined(CONFIG_PILOT) || defined(CONFIG_INIT_LCD) 37*4882a593Smuzhiyun.global bootlogo_bits 38*4882a593Smuzhiyun#endif 39*4882a593Smuzhiyun 40*4882a593Smuzhiyun/* Defining DEBUG_HEAD_CODE, serial port in 68x328 is inited */ 41*4882a593Smuzhiyun/* #define DEBUG_HEAD_CODE */ 42*4882a593Smuzhiyun#undef DEBUG_HEAD_CODE 43*4882a593Smuzhiyun 44*4882a593Smuzhiyun.data 45*4882a593Smuzhiyun 46*4882a593Smuzhiyun/***************************************************************************** 47*4882a593Smuzhiyun * RAM setup pointers. Used by the kernel to determine RAM location and size. 48*4882a593Smuzhiyun *****************************************************************************/ 49*4882a593Smuzhiyun 50*4882a593Smuzhiyun_rambase: 51*4882a593Smuzhiyun .long 0 52*4882a593Smuzhiyun_ramvec: 53*4882a593Smuzhiyun .long 0 54*4882a593Smuzhiyun_ramstart: 55*4882a593Smuzhiyun .long 0 56*4882a593Smuzhiyun_ramend: 57*4882a593Smuzhiyun .long 0 58*4882a593Smuzhiyun 59*4882a593Smuzhiyun__HEAD 60*4882a593Smuzhiyun 61*4882a593Smuzhiyun/***************************************************************************** 62*4882a593Smuzhiyun * Entry point, where all begins! 63*4882a593Smuzhiyun *****************************************************************************/ 64*4882a593Smuzhiyun 65*4882a593Smuzhiyun_start: 66*4882a593Smuzhiyun 67*4882a593Smuzhiyun/* Pilot need this specific signature at the start of ROM */ 68*4882a593Smuzhiyun#ifdef CONFIG_PILOT 69*4882a593Smuzhiyun .byte 0x4e, 0xfa, 0x00, 0x0a /* bra opcode (jmp 10 bytes) */ 70*4882a593Smuzhiyun .byte 'b', 'o', 'o', 't' 71*4882a593Smuzhiyun .word 10000 72*4882a593Smuzhiyun nop 73*4882a593Smuzhiyun moveq #0, %d0 74*4882a593Smuzhiyun movew %d0, 0xfffff618 /* Watchdog off */ 75*4882a593Smuzhiyun movel #0x00011f07, 0xfffff114 /* CS A1 Mask */ 76*4882a593Smuzhiyun#endif /* CONFIG_PILOT */ 77*4882a593Smuzhiyun 78*4882a593Smuzhiyun movew #0x2700, %sr /* disable all interrupts */ 79*4882a593Smuzhiyun 80*4882a593Smuzhiyun/***************************************************************************** 81*4882a593Smuzhiyun * Setup PLL and wait for it to settle (in 68x328 cpu's). 82*4882a593Smuzhiyun * Also, if enabled, init serial port. 83*4882a593Smuzhiyun *****************************************************************************/ 84*4882a593Smuzhiyun#if defined(CONFIG_M68328) || \ 85*4882a593Smuzhiyun defined(CONFIG_M68EZ328) || \ 86*4882a593Smuzhiyun defined(CONFIG_M68VZ328) 87*4882a593Smuzhiyun 88*4882a593Smuzhiyun/* Serial port setup. Should only be needed if debugging this startup code. */ 89*4882a593Smuzhiyun#ifdef DEBUG_HEAD_CODE 90*4882a593Smuzhiyun movew #0x0800, 0xfffff906 /* Ignore CTS */ 91*4882a593Smuzhiyun movew #0x010b, 0xfffff902 /* BAUD to 9600 */ 92*4882a593Smuzhiyun movew #0xe100, 0xfffff900 /* enable */ 93*4882a593Smuzhiyun#endif /* DEBUG_HEAD */ 94*4882a593Smuzhiyun 95*4882a593Smuzhiyun#ifdef CONFIG_PILOT 96*4882a593Smuzhiyun movew #0x2410, 0xfffff200 /* PLLCR */ 97*4882a593Smuzhiyun#else 98*4882a593Smuzhiyun movew #0x2400, 0xfffff200 /* PLLCR */ 99*4882a593Smuzhiyun#endif 100*4882a593Smuzhiyun movew #0x0123, 0xfffff202 /* PLLFSR */ 101*4882a593Smuzhiyun moveq #0, %d0 102*4882a593Smuzhiyun movew #16384, %d0 /* PLL settle wait loop */ 103*4882a593Smuzhiyun_pll_settle: 104*4882a593Smuzhiyun subw #1, %d0 105*4882a593Smuzhiyun bne _pll_settle 106*4882a593Smuzhiyun#endif /* CONFIG_M68x328 */ 107*4882a593Smuzhiyun 108*4882a593Smuzhiyun 109*4882a593Smuzhiyun/***************************************************************************** 110*4882a593Smuzhiyun * If running kernel from ROM some specific initialization has to be done. 111*4882a593Smuzhiyun * (Assuming that everything is already init'ed when running from RAM) 112*4882a593Smuzhiyun *****************************************************************************/ 113*4882a593Smuzhiyun#ifdef CONFIG_ROMKERNEL 114*4882a593Smuzhiyun 115*4882a593Smuzhiyun/***************************************************************************** 116*4882a593Smuzhiyun * Init chip registers (uCsimm specific) 117*4882a593Smuzhiyun *****************************************************************************/ 118*4882a593Smuzhiyun#ifdef CONFIG_UCSIMM 119*4882a593Smuzhiyun moveb #0x00, 0xfffffb0b /* Watchdog off */ 120*4882a593Smuzhiyun moveb #0x10, 0xfffff000 /* SCR */ 121*4882a593Smuzhiyun moveb #0x00, 0xfffff40b /* enable chip select */ 122*4882a593Smuzhiyun moveb #0x00, 0xfffff423 /* enable /DWE */ 123*4882a593Smuzhiyun moveb #0x08, 0xfffffd0d /* disable hardmap */ 124*4882a593Smuzhiyun moveb #0x07, 0xfffffd0e /* level 7 interrupt clear */ 125*4882a593Smuzhiyun movew #0x8600, 0xfffff100 /* FLASH at 0x10c00000 */ 126*4882a593Smuzhiyun movew #0x018b, 0xfffff110 /* 2Meg, enable, 0ws */ 127*4882a593Smuzhiyun movew #0x8f00, 0xfffffc00 /* DRAM configuration */ 128*4882a593Smuzhiyun movew #0x9667, 0xfffffc02 /* DRAM control */ 129*4882a593Smuzhiyun movew #0x0000, 0xfffff106 /* DRAM at 0x00000000 */ 130*4882a593Smuzhiyun movew #0x068f, 0xfffff116 /* 8Meg, enable, 0ws */ 131*4882a593Smuzhiyun moveb #0x40, 0xfffff300 /* IVR */ 132*4882a593Smuzhiyun movel #0x007FFFFF, %d0 /* IMR */ 133*4882a593Smuzhiyun movel %d0, 0xfffff304 134*4882a593Smuzhiyun moveb 0xfffff42b, %d0 135*4882a593Smuzhiyun andb #0xe0, %d0 136*4882a593Smuzhiyun moveb %d0, 0xfffff42b 137*4882a593Smuzhiyun#endif 138*4882a593Smuzhiyun 139*4882a593Smuzhiyun/***************************************************************************** 140*4882a593Smuzhiyun * Init LCD controller. 141*4882a593Smuzhiyun * (Assuming that LCD controller is already init'ed when running from RAM) 142*4882a593Smuzhiyun *****************************************************************************/ 143*4882a593Smuzhiyun#ifdef CONFIG_INIT_LCD 144*4882a593Smuzhiyun#ifdef CONFIG_PILOT 145*4882a593Smuzhiyun moveb #0, 0xfffffA27 /* LCKCON */ 146*4882a593Smuzhiyun movel #_start, 0xfffffA00 /* LSSA */ 147*4882a593Smuzhiyun moveb #0xa, 0xfffffA05 /* LVPW */ 148*4882a593Smuzhiyun movew #0x9f, 0xFFFFFa08 /* LXMAX */ 149*4882a593Smuzhiyun movew #0x9f, 0xFFFFFa0a /* LYMAX */ 150*4882a593Smuzhiyun moveb #9, 0xfffffa29 /* LBAR */ 151*4882a593Smuzhiyun moveb #0, 0xfffffa25 /* LPXCD */ 152*4882a593Smuzhiyun moveb #0x04, 0xFFFFFa20 /* LPICF */ 153*4882a593Smuzhiyun moveb #0x58, 0xfffffA27 /* LCKCON */ 154*4882a593Smuzhiyun moveb #0x85, 0xfffff429 /* PFDATA */ 155*4882a593Smuzhiyun moveb #0xd8, 0xfffffA27 /* LCKCON */ 156*4882a593Smuzhiyun moveb #0xc5, 0xfffff429 /* PFDATA */ 157*4882a593Smuzhiyun moveb #0xd5, 0xfffff429 /* PFDATA */ 158*4882a593Smuzhiyun movel #bootlogo_bits, 0xFFFFFA00 /* LSSA */ 159*4882a593Smuzhiyun moveb #10, 0xFFFFFA05 /* LVPW */ 160*4882a593Smuzhiyun movew #160, 0xFFFFFA08 /* LXMAX */ 161*4882a593Smuzhiyun movew #160, 0xFFFFFA0A /* LYMAX */ 162*4882a593Smuzhiyun#else /* CONFIG_PILOT */ 163*4882a593Smuzhiyun movel #bootlogo_bits, 0xfffffA00 /* LSSA */ 164*4882a593Smuzhiyun moveb #0x28, 0xfffffA05 /* LVPW */ 165*4882a593Smuzhiyun movew #0x280, 0xFFFFFa08 /* LXMAX */ 166*4882a593Smuzhiyun movew #0x1df, 0xFFFFFa0a /* LYMAX */ 167*4882a593Smuzhiyun moveb #0, 0xfffffa29 /* LBAR */ 168*4882a593Smuzhiyun moveb #0, 0xfffffa25 /* LPXCD */ 169*4882a593Smuzhiyun moveb #0x08, 0xFFFFFa20 /* LPICF */ 170*4882a593Smuzhiyun moveb #0x01, 0xFFFFFA21 /* -ve pol */ 171*4882a593Smuzhiyun moveb #0x81, 0xfffffA27 /* LCKCON */ 172*4882a593Smuzhiyun movew #0xff00, 0xfffff412 /* LCD pins */ 173*4882a593Smuzhiyun#endif /* CONFIG_PILOT */ 174*4882a593Smuzhiyun#endif /* CONFIG_INIT_LCD */ 175*4882a593Smuzhiyun 176*4882a593Smuzhiyun/***************************************************************************** 177*4882a593Smuzhiyun * Kernel is running from FLASH/ROM (XIP) 178*4882a593Smuzhiyun * Copy init text & data to RAM 179*4882a593Smuzhiyun *****************************************************************************/ 180*4882a593Smuzhiyun moveal #_etext, %a0 181*4882a593Smuzhiyun moveal #_sdata, %a1 182*4882a593Smuzhiyun moveal #__bss_start, %a2 183*4882a593Smuzhiyun_copy_initmem: 184*4882a593Smuzhiyun movel %a0@+, %a1@+ 185*4882a593Smuzhiyun cmpal %a1, %a2 186*4882a593Smuzhiyun bhi _copy_initmem 187*4882a593Smuzhiyun#endif /* CONFIG_ROMKERNEL */ 188*4882a593Smuzhiyun 189*4882a593Smuzhiyun/***************************************************************************** 190*4882a593Smuzhiyun * Setup basic memory information for kernel 191*4882a593Smuzhiyun *****************************************************************************/ 192*4882a593Smuzhiyun movel #CONFIG_VECTORBASE,_ramvec /* set vector base location */ 193*4882a593Smuzhiyun movel #CONFIG_RAMBASE,_rambase /* set the base of RAM */ 194*4882a593Smuzhiyun movel #RAMEND, _ramend /* set end ram addr */ 195*4882a593Smuzhiyun lea __bss_stop,%a1 196*4882a593Smuzhiyun movel %a1,_ramstart 197*4882a593Smuzhiyun 198*4882a593Smuzhiyun/***************************************************************************** 199*4882a593Smuzhiyun * If the kernel is in RAM, move romfs to right above bss and 200*4882a593Smuzhiyun * adjust _ramstart to where romfs ends. 201*4882a593Smuzhiyun * 202*4882a593Smuzhiyun * (Do this only if CONFIG_MTD_UCLINUX is true) 203*4882a593Smuzhiyun *****************************************************************************/ 204*4882a593Smuzhiyun 205*4882a593Smuzhiyun#if defined(CONFIG_ROMFS_FS) && defined(CONFIG_RAMKERNEL) && \ 206*4882a593Smuzhiyun defined(CONFIG_MTD_UCLINUX) 207*4882a593Smuzhiyun lea __bss_start, %a0 /* get start of bss */ 208*4882a593Smuzhiyun lea __bss_stop, %a1 /* set up destination */ 209*4882a593Smuzhiyun movel %a0, %a2 /* copy of bss start */ 210*4882a593Smuzhiyun 211*4882a593Smuzhiyun movel 8(%a0), %d0 /* get size of ROMFS */ 212*4882a593Smuzhiyun addql #8, %d0 /* allow for rounding */ 213*4882a593Smuzhiyun andl #0xfffffffc, %d0 /* whole words */ 214*4882a593Smuzhiyun 215*4882a593Smuzhiyun addl %d0, %a0 /* copy from end */ 216*4882a593Smuzhiyun addl %d0, %a1 /* copy from end */ 217*4882a593Smuzhiyun movel %a1, _ramstart /* set start of ram */ 218*4882a593Smuzhiyun_copy_romfs: 219*4882a593Smuzhiyun movel -(%a0), -(%a1) /* copy dword */ 220*4882a593Smuzhiyun cmpl %a0, %a2 /* check if at end */ 221*4882a593Smuzhiyun bne _copy_romfs 222*4882a593Smuzhiyun#endif /* CONFIG_ROMFS_FS && CONFIG_RAMKERNEL && CONFIG_MTD_UCLINUX */ 223*4882a593Smuzhiyun 224*4882a593Smuzhiyun/***************************************************************************** 225*4882a593Smuzhiyun * Clear bss region 226*4882a593Smuzhiyun *****************************************************************************/ 227*4882a593Smuzhiyun lea __bss_start, %a0 /* get start of bss */ 228*4882a593Smuzhiyun lea __bss_stop, %a1 /* get end of bss */ 229*4882a593Smuzhiyun_clear_bss: 230*4882a593Smuzhiyun movel #0, (%a0)+ /* clear each word */ 231*4882a593Smuzhiyun cmpl %a0, %a1 /* check if at end */ 232*4882a593Smuzhiyun bne _clear_bss 233*4882a593Smuzhiyun 234*4882a593Smuzhiyun/***************************************************************************** 235*4882a593Smuzhiyun * Load the current task pointer and stack. 236*4882a593Smuzhiyun *****************************************************************************/ 237*4882a593Smuzhiyun lea init_thread_union,%a0 238*4882a593Smuzhiyun lea THREAD_SIZE(%a0),%sp 239*4882a593Smuzhiyun jsr start_kernel /* start Linux kernel */ 240*4882a593Smuzhiyun_exit: 241*4882a593Smuzhiyun jmp _exit /* should never get here */ 242