summaryrefslogtreecommitdiff
path: root/arch/mn10300/kernel/head.S
diff options
context:
space:
mode:
Diffstat (limited to 'arch/mn10300/kernel/head.S')
-rw-r--r--arch/mn10300/kernel/head.S450
1 files changed, 450 insertions, 0 deletions
diff --git a/arch/mn10300/kernel/head.S b/arch/mn10300/kernel/head.S
new file mode 100644
index 000000000..73e00fc78
--- /dev/null
+++ b/arch/mn10300/kernel/head.S
@@ -0,0 +1,450 @@
+/* Boot entry point for MN10300 kernel
+ *
+ * Copyright (C) 2005 Red Hat, Inc. All Rights Reserved.
+ * Written by David Howells (dhowells@redhat.com)
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public Licence
+ * as published by the Free Software Foundation; either version
+ * 2 of the Licence, or (at your option) any later version.
+ */
+
+#include <linux/init.h>
+#include <linux/threads.h>
+#include <linux/linkage.h>
+#include <linux/serial_reg.h>
+#include <asm/thread_info.h>
+#include <asm/page.h>
+#include <asm/pgtable.h>
+#include <asm/frame.inc>
+#include <asm/param.h>
+#include <unit/serial.h>
+#ifdef CONFIG_SMP
+#include <asm/smp.h>
+#include <asm/intctl-regs.h>
+#include <asm/cpu-regs.h>
+#include <proc/smp-regs.h>
+#endif /* CONFIG_SMP */
+
+ __HEAD
+
+###############################################################################
+#
+# bootloader entry point
+#
+###############################################################################
+ .globl _start
+ .type _start,@function
+_start:
+#ifdef CONFIG_SMP
+ #
+ # If this is a secondary CPU (AP), then deal with that elsewhere
+ #
+ mov (CPUID),d3
+ and CPUID_MASK,d3
+ bne startup_secondary
+
+ #
+ # We're dealing with the primary CPU (BP) here, then.
+ # Keep BP's D0,D1,D2 register for boot check.
+ #
+
+ # Set up the Boot IPI for each secondary CPU
+ mov 0x1,a0
+loop_set_secondary_icr:
+ mov a0,a1
+ asl CROSS_ICR_CPU_SHIFT,a1
+ add CROSS_GxICR(SMP_BOOT_IRQ,0),a1
+ movhu (a1),d3
+ or GxICR_ENABLE|GxICR_LEVEL_0,d3
+ movhu d3,(a1)
+ movhu (a1),d3 # flush
+ inc a0
+ cmp NR_CPUS,a0
+ bne loop_set_secondary_icr
+#endif /* CONFIG_SMP */
+
+ # save commandline pointer
+ mov d0,a3
+
+ # preload the PGD pointer register
+ mov swapper_pg_dir,d0
+ mov d0,(PTBR)
+ clr d0
+ movbu d0,(PIDR)
+
+ # turn on the TLBs
+ mov MMUCTR_IIV|MMUCTR_DIV,d0
+ mov d0,(MMUCTR)
+#ifdef CONFIG_AM34_2
+ mov MMUCTR_ITE|MMUCTR_DTE|MMUCTR_CE|MMUCTR_WTE,d0
+#else
+ mov MMUCTR_ITE|MMUCTR_DTE|MMUCTR_CE,d0
+#endif
+ mov d0,(MMUCTR)
+
+ # turn on AM33v2 exception handling mode and set the trap table base
+ movhu (CPUP),d0
+ or CPUP_EXM_AM33V2,d0
+ movhu d0,(CPUP)
+ mov CONFIG_INTERRUPT_VECTOR_BASE,d0
+ mov d0,(TBR)
+
+ # invalidate and enable both of the caches
+#ifdef CONFIG_SMP
+ mov ECHCTR,a0
+ clr d0
+ mov d0,(a0)
+#endif
+ mov CHCTR,a0
+ clr d0
+ movhu d0,(a0) # turn off first
+ mov CHCTR_ICINV|CHCTR_DCINV,d0
+ movhu d0,(a0)
+ setlb
+ mov (a0),d0
+ btst CHCTR_ICBUSY|CHCTR_DCBUSY,d0 # wait till not busy
+ lne
+
+#ifdef CONFIG_MN10300_CACHE_ENABLED
+#ifdef CONFIG_MN10300_CACHE_WBACK
+#ifndef CONFIG_MN10300_CACHE_WBACK_NOWRALLOC
+ mov CHCTR_ICEN|CHCTR_DCEN|CHCTR_DCWTMD_WRBACK,d0
+#else
+ mov CHCTR_ICEN|CHCTR_DCEN|CHCTR_DCWTMD_WRBACK|CHCTR_DCALMD,d0
+#endif /* NOWRALLOC */
+#else
+ mov CHCTR_ICEN|CHCTR_DCEN|CHCTR_DCWTMD_WRTHROUGH,d0
+#endif /* WBACK */
+ movhu d0,(a0) # enable
+#endif /* ENABLED */
+
+ # turn on RTS on the debug serial port if applicable
+#ifdef CONFIG_MN10300_UNIT_ASB2305
+ bset UART_MCR_RTS,(ASB2305_DEBUG_MCR)
+#endif
+
+ # clear the BSS area
+ mov __bss_start,a0
+ mov __bss_stop,a1
+ clr d0
+bssclear:
+ cmp a1,a0
+ bge bssclear_end
+ mov d0,(a0)
+ inc4 a0
+ bra bssclear
+bssclear_end:
+
+ # retrieve the parameters (including command line) before we overwrite
+ # them
+ cmp 0xabadcafe,d1
+ bne __no_parameters
+
+__copy_parameters:
+ mov redboot_command_line,a0
+ mov a0,a1
+ add COMMAND_LINE_SIZE,a1
+1:
+ movbu (a3),d0
+ inc a3
+ movbu d0,(a0)
+ inc a0
+ cmp a1,a0
+ blt 1b
+
+ mov redboot_platform_name,a0
+ mov a0,a1
+ add COMMAND_LINE_SIZE,a1
+ mov d2,a3
+1:
+ movbu (a3),d0
+ inc a3
+ movbu d0,(a0)
+ inc a0
+ cmp a1,a0
+ blt 1b
+
+__no_parameters:
+
+ # set up the registers with recognisable rubbish in them
+ mov init_thread_union+THREAD_SIZE-12,sp
+
+ mov 0xea01eaea,d0
+ mov d0,(4,sp) # EPSW save area
+ mov 0xea02eaea,d0
+ mov d0,(8,sp) # PC save area
+
+ mov 0xeb0060ed,d0
+ mov d0,mdr
+ mov 0xeb0061ed,d0
+ mov d0,mdrq
+ mov 0xeb0062ed,d0
+ mov d0,mcrh
+ mov 0xeb0063ed,d0
+ mov d0,mcrl
+ mov 0xeb0064ed,d0
+ mov d0,mcvf
+ mov 0xed0065ed,a3
+ mov a3,usp
+
+ mov 0xed00e0ed,e0
+ mov 0xed00e1ed,e1
+ mov 0xed00e2ed,e2
+ mov 0xed00e3ed,e3
+ mov 0xed00e4ed,e4
+ mov 0xed00e5ed,e5
+ mov 0xed00e6ed,e6
+ mov 0xed00e7ed,e7
+
+ mov 0xed00d0ed,d0
+ mov 0xed00d1ed,d1
+ mov 0xed00d2ed,d2
+ mov 0xed00d3ed,d3
+ mov 0xed00a0ed,a0
+ mov 0xed00a1ed,a1
+ mov 0xed00a2ed,a2
+ mov 0,a3
+
+ # set up the initial kernel stack
+ SAVE_ALL
+ mov 0xffffffff,d0
+ mov d0,(REG_ORIG_D0,fp)
+
+ # put different recognisable rubbish in the regs
+ mov 0xfb0060ed,d0
+ mov d0,mdr
+ mov 0xfb0061ed,d0
+ mov d0,mdrq
+ mov 0xfb0062ed,d0
+ mov d0,mcrh
+ mov 0xfb0063ed,d0
+ mov d0,mcrl
+ mov 0xfb0064ed,d0
+ mov d0,mcvf
+ mov 0xfd0065ed,a0
+ mov a0,usp
+
+ mov 0xfd00e0ed,e0
+ mov 0xfd00e1ed,e1
+ mov 0xfd00e2ed,e2
+ mov 0xfd00e3ed,e3
+ mov 0xfd00e4ed,e4
+ mov 0xfd00e5ed,e5
+ mov 0xfd00e6ed,e6
+ mov 0xfd00e7ed,e7
+
+ mov 0xfd00d0ed,d0
+ mov 0xfd00d1ed,d1
+ mov 0xfd00d2ed,d2
+ mov 0xfd00d3ed,d3
+ mov 0xfd00a0ed,a0
+ mov 0xfd00a1ed,a1
+ mov 0xfd00a2ed,a2
+
+ # we may be holding current in E2
+#ifdef CONFIG_MN10300_CURRENT_IN_E2
+ mov init_task,e2
+#endif
+
+ # initialise the processor and the unit
+ call processor_init[],0
+ call unit_init[],0
+
+#ifdef CONFIG_SMP
+ # mark the primary CPU in cpu_boot_map
+ mov cpu_boot_map,a0
+ mov 0x1,d0
+ mov d0,(a0)
+
+ # signal each secondary CPU to begin booting
+ mov 0x1,d2 # CPU ID
+
+loop_request_boot_secondary:
+ mov d2,a0
+ # send SMP_BOOT_IPI to secondary CPU
+ asl CROSS_ICR_CPU_SHIFT,a0
+ add CROSS_GxICR(SMP_BOOT_IRQ,0),a0
+ movhu (a0),d0
+ or GxICR_REQUEST|GxICR_DETECT,d0
+ movhu d0,(a0)
+ movhu (a0),d0 # flush
+
+ # wait up to 100ms for AP's IPI to be received
+ clr d3
+wait_on_secondary_boot:
+ mov DELAY_TIME_BOOT_IPI,d0
+ call __delay[],0
+ inc d3
+ mov cpu_boot_map,a0
+ mov (a0),d0
+ lsr d2,d0
+ btst 0x1,d0
+ bne 1f
+ cmp TIME_OUT_COUNT_BOOT_IPI,d3
+ bne wait_on_secondary_boot
+1:
+ inc d2
+ cmp NR_CPUS,d2
+ bne loop_request_boot_secondary
+#endif /* CONFIG_SMP */
+
+#ifdef CONFIG_GDBSTUB
+ call gdbstub_init[],0
+
+#ifdef CONFIG_GDBSTUB_IMMEDIATE
+ .globl __gdbstub_pause
+__gdbstub_pause:
+ bra __gdbstub_pause
+#endif
+#endif
+
+ jmp start_kernel
+ .size _start,.-_start
+
+###############################################################################
+#
+# Secondary CPU boot point
+#
+###############################################################################
+#ifdef CONFIG_SMP
+startup_secondary:
+ # preload the PGD pointer register
+ mov swapper_pg_dir,d0
+ mov d0,(PTBR)
+ clr d0
+ movbu d0,(PIDR)
+
+ # turn on the TLBs
+ mov MMUCTR_IIV|MMUCTR_DIV,d0
+ mov d0,(MMUCTR)
+#ifdef CONFIG_AM34_2
+ mov MMUCTR_ITE|MMUCTR_DTE|MMUCTR_CE|MMUCTR_WTE,d0
+#else
+ mov MMUCTR_ITE|MMUCTR_DTE|MMUCTR_CE,d0
+#endif
+ mov d0,(MMUCTR)
+
+ # turn on AM33v2 exception handling mode and set the trap table base
+ movhu (CPUP),d0
+ or CPUP_EXM_AM33V2,d0
+ movhu d0,(CPUP)
+
+ # set the interrupt vector table
+ mov CONFIG_INTERRUPT_VECTOR_BASE,d0
+ mov d0,(TBR)
+
+ # invalidate and enable both of the caches
+ mov ECHCTR,a0
+ clr d0
+ mov d0,(a0)
+ mov CHCTR,a0
+ clr d0
+ movhu d0,(a0) # turn off first
+ mov CHCTR_ICINV|CHCTR_DCINV,d0
+ movhu d0,(a0)
+ setlb
+ mov (a0),d0
+ btst CHCTR_ICBUSY|CHCTR_DCBUSY,d0 # wait till not busy (use CPU loop buffer)
+ lne
+
+#ifdef CONFIG_MN10300_CACHE_ENABLED
+#ifdef CONFIG_MN10300_CACHE_WBACK
+#ifndef CONFIG_MN10300_CACHE_WBACK_NOWRALLOC
+ mov CHCTR_ICEN|CHCTR_DCEN|CHCTR_DCWTMD_WRBACK,d0
+#else
+ mov CHCTR_ICEN|CHCTR_DCEN|CHCTR_DCWTMD_WRBACK|CHCTR_DCALMD,d0
+#endif /* !NOWRALLOC */
+#else
+ mov CHCTR_ICEN|CHCTR_DCEN|CHCTR_DCWTMD_WRTHROUGH,d0
+#endif /* WBACK */
+ movhu d0,(a0) # enable
+#endif /* ENABLED */
+
+ # Clear the boot IPI interrupt for this CPU
+ movhu (GxICR(SMP_BOOT_IRQ)),d0
+ and ~GxICR_REQUEST,d0
+ movhu d0,(GxICR(SMP_BOOT_IRQ))
+ movhu (GxICR(SMP_BOOT_IRQ)),d0 # flush
+
+ /* get stack */
+ mov CONFIG_INTERRUPT_VECTOR_BASE + CONFIG_BOOT_STACK_OFFSET,a0
+ mov (CPUID),d0
+ and CPUID_MASK,d0
+ mulu CONFIG_BOOT_STACK_SIZE,d0
+ sub d0,a0
+ mov a0,sp
+
+ # init interrupt for AP
+ call smp_prepare_cpu_init[],0
+
+ # mark this secondary CPU in cpu_boot_map
+ mov (CPUID),d0
+ mov 0x1,d1
+ asl d0,d1
+ mov cpu_boot_map,a0
+ bset d1,(a0)
+
+ or EPSW_IE|EPSW_IM_1,epsw # permit level 0 interrupts
+ nop
+ nop
+#ifdef CONFIG_MN10300_CACHE_WBACK
+ # flush the local cache if it's in writeback mode
+ call mn10300_local_dcache_flush_inv[],0
+ setlb
+ mov (CHCTR),d0
+ btst CHCTR_DCBUSY,d0 # wait till not busy (use CPU loop buffer)
+ lne
+#endif
+
+ # now sleep waiting for further instructions
+secondary_sleep:
+ mov CPUM_SLEEP,d0
+ movhu d0,(CPUM)
+ nop
+ nop
+ bra secondary_sleep
+ .size startup_secondary,.-startup_secondary
+#endif /* CONFIG_SMP */
+
+###############################################################################
+#
+#
+#
+###############################################################################
+ENTRY(__head_end)
+
+/*
+ * This is initialized to disallow all access to the low 2G region
+ * - the high 2G region is managed directly by the MMU
+ * - range 0x70000000-0x7C000000 are initialised for use by VMALLOC
+ */
+ .section .bss
+ .balign PAGE_SIZE
+ENTRY(swapper_pg_dir)
+ .space PTRS_PER_PGD*4
+
+/*
+ * The page tables are initialized to only 8MB here - the final page
+ * tables are set up later depending on memory size.
+ */
+
+ .balign PAGE_SIZE
+ENTRY(empty_zero_page)
+ .space PAGE_SIZE
+
+ .balign PAGE_SIZE
+ENTRY(empty_bad_page)
+ .space PAGE_SIZE
+
+ .balign PAGE_SIZE
+ENTRY(empty_bad_pte_table)
+ .space PAGE_SIZE
+
+ .balign PAGE_SIZE
+ENTRY(large_page_table)
+ .space PAGE_SIZE
+
+ .balign PAGE_SIZE
+ENTRY(kernel_vmalloc_ptes)
+ .space ((VMALLOC_END-VMALLOC_START)/PAGE_SIZE)*4