123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451 |
- /* 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
|