/* Boot entry point for MN10300 kernel1*2* Copyright (C) 2005 Red Hat, Inc. All Rights Reserved.3* Written by David Howells ([email protected])4*5* This program is free software; you can redistribute it and/or6* modify it under the terms of the GNU General Public Licence7* as published by the Free Software Foundation; either version8* 2 of the Licence, or (at your option) any later version.9*/1011#include <linux/init.h>12#include <linux/threads.h>13#include <linux/linkage.h>14#include <linux/serial_reg.h>15#include <asm/thread_info.h>16#include <asm/page.h>17#include <asm/pgtable.h>18#include <asm/frame.inc>19#include <asm/param.h>20#include <unit/serial.h>21#ifdef CONFIG_SMP22#include <asm/smp.h>23#include <asm/intctl-regs.h>24#include <asm/cpu-regs.h>25#include <proc/smp-regs.h>26#endif /* CONFIG_SMP */2728__HEAD2930###############################################################################31#32# bootloader entry point33#34###############################################################################35.globl _start36.type _start,@function37_start:38#ifdef CONFIG_SMP39#40# If this is a secondary CPU (AP), then deal with that elsewhere41#42mov (CPUID),d343and CPUID_MASK,d344bne startup_secondary4546#47# We're dealing with the primary CPU (BP) here, then.48# Keep BP's D0,D1,D2 register for boot check.49#5051# Set up the Boot IPI for each secondary CPU52mov 0x1,a053loop_set_secondary_icr:54mov a0,a155asl CROSS_ICR_CPU_SHIFT,a156add CROSS_GxICR(SMP_BOOT_IRQ,0),a157movhu (a1),d358or GxICR_ENABLE|GxICR_LEVEL_0,d359movhu d3,(a1)60movhu (a1),d3 # flush61inc a062cmp NR_CPUS,a063bne loop_set_secondary_icr64#endif /* CONFIG_SMP */6566# save commandline pointer67mov d0,a36869# preload the PGD pointer register70mov swapper_pg_dir,d071mov d0,(PTBR)72clr d073movbu d0,(PIDR)7475# turn on the TLBs76mov MMUCTR_IIV|MMUCTR_DIV,d077mov d0,(MMUCTR)78#ifdef CONFIG_AM34_279mov MMUCTR_ITE|MMUCTR_DTE|MMUCTR_CE|MMUCTR_WTE,d080#else81mov MMUCTR_ITE|MMUCTR_DTE|MMUCTR_CE,d082#endif83mov d0,(MMUCTR)8485# turn on AM33v2 exception handling mode and set the trap table base86movhu (CPUP),d087or CPUP_EXM_AM33V2,d088movhu d0,(CPUP)89mov CONFIG_INTERRUPT_VECTOR_BASE,d090mov d0,(TBR)9192# invalidate and enable both of the caches93#ifdef CONFIG_SMP94mov ECHCTR,a095clr d096mov d0,(a0)97#endif98mov CHCTR,a099clr d0100movhu d0,(a0) # turn off first101mov CHCTR_ICINV|CHCTR_DCINV,d0102movhu d0,(a0)103setlb104mov (a0),d0105btst CHCTR_ICBUSY|CHCTR_DCBUSY,d0 # wait till not busy106lne107108#ifdef CONFIG_MN10300_CACHE_ENABLED109#ifdef CONFIG_MN10300_CACHE_WBACK110#ifndef CONFIG_MN10300_CACHE_WBACK_NOWRALLOC111mov CHCTR_ICEN|CHCTR_DCEN|CHCTR_DCWTMD_WRBACK,d0112#else113mov CHCTR_ICEN|CHCTR_DCEN|CHCTR_DCWTMD_WRBACK|CHCTR_DCALMD,d0114#endif /* NOWRALLOC */115#else116mov CHCTR_ICEN|CHCTR_DCEN|CHCTR_DCWTMD_WRTHROUGH,d0117#endif /* WBACK */118movhu d0,(a0) # enable119#endif /* ENABLED */120121# turn on RTS on the debug serial port if applicable122#ifdef CONFIG_MN10300_UNIT_ASB2305123bset UART_MCR_RTS,(ASB2305_DEBUG_MCR)124#endif125126# clear the BSS area127mov __bss_start,a0128mov __bss_stop,a1129clr d0130bssclear:131cmp a1,a0132bge bssclear_end133mov d0,(a0)134inc4 a0135bra bssclear136bssclear_end:137138# retrieve the parameters (including command line) before we overwrite139# them140cmp 0xabadcafe,d1141bne __no_parameters142143__copy_parameters:144mov redboot_command_line,a0145mov a0,a1146add COMMAND_LINE_SIZE,a11471:148movbu (a3),d0149inc a3150movbu d0,(a0)151inc a0152cmp a1,a0153blt 1b154155mov redboot_platform_name,a0156mov a0,a1157add COMMAND_LINE_SIZE,a1158mov d2,a31591:160movbu (a3),d0161inc a3162movbu d0,(a0)163inc a0164cmp a1,a0165blt 1b166167__no_parameters:168169# set up the registers with recognisable rubbish in them170mov init_thread_union+THREAD_SIZE-12,sp171172mov 0xea01eaea,d0173mov d0,(4,sp) # EPSW save area174mov 0xea02eaea,d0175mov d0,(8,sp) # PC save area176177mov 0xeb0060ed,d0178mov d0,mdr179mov 0xeb0061ed,d0180mov d0,mdrq181mov 0xeb0062ed,d0182mov d0,mcrh183mov 0xeb0063ed,d0184mov d0,mcrl185mov 0xeb0064ed,d0186mov d0,mcvf187mov 0xed0065ed,a3188mov a3,usp189190mov 0xed00e0ed,e0191mov 0xed00e1ed,e1192mov 0xed00e2ed,e2193mov 0xed00e3ed,e3194mov 0xed00e4ed,e4195mov 0xed00e5ed,e5196mov 0xed00e6ed,e6197mov 0xed00e7ed,e7198199mov 0xed00d0ed,d0200mov 0xed00d1ed,d1201mov 0xed00d2ed,d2202mov 0xed00d3ed,d3203mov 0xed00a0ed,a0204mov 0xed00a1ed,a1205mov 0xed00a2ed,a2206mov 0,a3207208# set up the initial kernel stack209SAVE_ALL210mov 0xffffffff,d0211mov d0,(REG_ORIG_D0,fp)212213# put different recognisable rubbish in the regs214mov 0xfb0060ed,d0215mov d0,mdr216mov 0xfb0061ed,d0217mov d0,mdrq218mov 0xfb0062ed,d0219mov d0,mcrh220mov 0xfb0063ed,d0221mov d0,mcrl222mov 0xfb0064ed,d0223mov d0,mcvf224mov 0xfd0065ed,a0225mov a0,usp226227mov 0xfd00e0ed,e0228mov 0xfd00e1ed,e1229mov 0xfd00e2ed,e2230mov 0xfd00e3ed,e3231mov 0xfd00e4ed,e4232mov 0xfd00e5ed,e5233mov 0xfd00e6ed,e6234mov 0xfd00e7ed,e7235236mov 0xfd00d0ed,d0237mov 0xfd00d1ed,d1238mov 0xfd00d2ed,d2239mov 0xfd00d3ed,d3240mov 0xfd00a0ed,a0241mov 0xfd00a1ed,a1242mov 0xfd00a2ed,a2243244# we may be holding current in E2245#ifdef CONFIG_MN10300_CURRENT_IN_E2246mov init_task,e2247#endif248249# initialise the processor and the unit250call processor_init[],0251call unit_init[],0252253#ifdef CONFIG_SMP254# mark the primary CPU in cpu_boot_map255mov cpu_boot_map,a0256mov 0x1,d0257mov d0,(a0)258259# signal each secondary CPU to begin booting260mov 0x1,d2 # CPU ID261262loop_request_boot_secondary:263mov d2,a0264# send SMP_BOOT_IPI to secondary CPU265asl CROSS_ICR_CPU_SHIFT,a0266add CROSS_GxICR(SMP_BOOT_IRQ,0),a0267movhu (a0),d0268or GxICR_REQUEST|GxICR_DETECT,d0269movhu d0,(a0)270movhu (a0),d0 # flush271272# wait up to 100ms for AP's IPI to be received273clr d3274wait_on_secondary_boot:275mov DELAY_TIME_BOOT_IPI,d0276call __delay[],0277inc d3278mov cpu_boot_map,a0279mov (a0),d0280lsr d2,d0281btst 0x1,d0282bne 1f283cmp TIME_OUT_COUNT_BOOT_IPI,d3284bne wait_on_secondary_boot2851:286inc d2287cmp NR_CPUS,d2288bne loop_request_boot_secondary289#endif /* CONFIG_SMP */290291#ifdef CONFIG_GDBSTUB292call gdbstub_init[],0293294#ifdef CONFIG_GDBSTUB_IMMEDIATE295.globl __gdbstub_pause296__gdbstub_pause:297bra __gdbstub_pause298#endif299#endif300301jmp start_kernel302.size _start,.-_start303304###############################################################################305#306# Secondary CPU boot point307#308###############################################################################309#ifdef CONFIG_SMP310startup_secondary:311# preload the PGD pointer register312mov swapper_pg_dir,d0313mov d0,(PTBR)314clr d0315movbu d0,(PIDR)316317# turn on the TLBs318mov MMUCTR_IIV|MMUCTR_DIV,d0319mov d0,(MMUCTR)320#ifdef CONFIG_AM34_2321mov MMUCTR_ITE|MMUCTR_DTE|MMUCTR_CE|MMUCTR_WTE,d0322#else323mov MMUCTR_ITE|MMUCTR_DTE|MMUCTR_CE,d0324#endif325mov d0,(MMUCTR)326327# turn on AM33v2 exception handling mode and set the trap table base328movhu (CPUP),d0329or CPUP_EXM_AM33V2,d0330movhu d0,(CPUP)331332# set the interrupt vector table333mov CONFIG_INTERRUPT_VECTOR_BASE,d0334mov d0,(TBR)335336# invalidate and enable both of the caches337mov ECHCTR,a0338clr d0339mov d0,(a0)340mov CHCTR,a0341clr d0342movhu d0,(a0) # turn off first343mov CHCTR_ICINV|CHCTR_DCINV,d0344movhu d0,(a0)345setlb346mov (a0),d0347btst CHCTR_ICBUSY|CHCTR_DCBUSY,d0 # wait till not busy (use CPU loop buffer)348lne349350#ifdef CONFIG_MN10300_CACHE_ENABLED351#ifdef CONFIG_MN10300_CACHE_WBACK352#ifndef CONFIG_MN10300_CACHE_WBACK_NOWRALLOC353mov CHCTR_ICEN|CHCTR_DCEN|CHCTR_DCWTMD_WRBACK,d0354#else355mov CHCTR_ICEN|CHCTR_DCEN|CHCTR_DCWTMD_WRBACK|CHCTR_DCALMD,d0356#endif /* !NOWRALLOC */357#else358mov CHCTR_ICEN|CHCTR_DCEN|CHCTR_DCWTMD_WRTHROUGH,d0359#endif /* WBACK */360movhu d0,(a0) # enable361#endif /* ENABLED */362363# Clear the boot IPI interrupt for this CPU364movhu (GxICR(SMP_BOOT_IRQ)),d0365and ~GxICR_REQUEST,d0366movhu d0,(GxICR(SMP_BOOT_IRQ))367movhu (GxICR(SMP_BOOT_IRQ)),d0 # flush368369/* get stack */370mov CONFIG_INTERRUPT_VECTOR_BASE + CONFIG_BOOT_STACK_OFFSET,a0371mov (CPUID),d0372and CPUID_MASK,d0373mulu CONFIG_BOOT_STACK_SIZE,d0374sub d0,a0375mov a0,sp376377# init interrupt for AP378call smp_prepare_cpu_init[],0379380# mark this secondary CPU in cpu_boot_map381mov (CPUID),d0382mov 0x1,d1383asl d0,d1384mov cpu_boot_map,a0385bset d1,(a0)386387or EPSW_IE|EPSW_IM_1,epsw # permit level 0 interrupts388nop389nop390#ifdef CONFIG_MN10300_CACHE_WBACK391# flush the local cache if it's in writeback mode392call mn10300_local_dcache_flush_inv[],0393setlb394mov (CHCTR),d0395btst CHCTR_DCBUSY,d0 # wait till not busy (use CPU loop buffer)396lne397#endif398399# now sleep waiting for further instructions400secondary_sleep:401mov CPUM_SLEEP,d0402movhu d0,(CPUM)403nop404nop405bra secondary_sleep406.size startup_secondary,.-startup_secondary407#endif /* CONFIG_SMP */408409###############################################################################410#411#412#413###############################################################################414ENTRY(__head_end)415416/*417* This is initialized to disallow all access to the low 2G region418* - the high 2G region is managed directly by the MMU419* - range 0x70000000-0x7C000000 are initialised for use by VMALLOC420*/421.section .bss422.balign PAGE_SIZE423ENTRY(swapper_pg_dir)424.space PTRS_PER_PGD*4425426/*427* The page tables are initialized to only 8MB here - the final page428* tables are set up later depending on memory size.429*/430431.balign PAGE_SIZE432ENTRY(empty_zero_page)433.space PAGE_SIZE434435.balign PAGE_SIZE436ENTRY(empty_bad_page)437.space PAGE_SIZE438439.balign PAGE_SIZE440ENTRY(empty_bad_pte_table)441.space PAGE_SIZE442443.balign PAGE_SIZE444ENTRY(large_page_table)445.space PAGE_SIZE446447.balign PAGE_SIZE448ENTRY(kernel_vmalloc_ptes)449.space ((VMALLOC_END-VMALLOC_START)/PAGE_SIZE)*4450451452