/* $NetBSD: imx7_start.S,v 1.1 2016/05/17 06:44:46 ryo Exp $ */ /*- * Copyright (c) 2014 Ryo Shimizu * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */ #include "opt_imx.h" #include "opt_cpuoptions.h" #include "opt_cputypes.h" #include "opt_multiprocessor.h" #include "opt_arm_debug.h" #include #include #include #include "assym.h" RCSID("$NetBSD: imx7_start.S,v 1.1 2016/05/17 06:44:46 ryo Exp $") #ifndef CONADDR #define CONADDR 0x30a60000 #endif #define COM_MULT 4 #define BOOT_MEMSIZE 256 /* temporary for boot up kernel */ #define TEMP_L1_TABLE (KERNEL_BASE - KERNEL_BASE_VOFFSET + \ BOOT_MEMSIZE * 0x100000 - L1_TABLE_SIZE) #define MD_CPU_HATCH _C_LABEL(imx7_cpu_hatch) #ifdef VERBOSE_INIT_ARM # define XPUTC_COM 1 # define XPUTC(n) mov r0, n; bl xputc # define XPUTC2(n) mov r0, n; blx r11 # define PRINT(str) bl xprint; .ascii str, "\0"; .align 2 # define PRINT_R0 bl print_r0 #else # define XPUTC(n) # define XPUTC2(n) # define PRINT(str) # define PRINT_R0 #endif /* VERBOSE_INIT_ARM */ /* * Kernel start routine for IMX7 boards. * At this point, this code has been loaded into SDRAM * and the MMU is off */ .section .start,"ax",%progbits .global _C_LABEL(imx7_start) _C_LABEL(imx7_start): /* * Save any arguments u-boot passed us. */ movw r4, #:lower16:uboot_args movt r4, #:upper16:uboot_args #if KERNEL_BASE_VOFFSET != 0 sub r4, r4, #KERNEL_BASE_VOFFSET #endif stmia r4, {r0-r3} /* Move into supervisor mode and disable IRQs/FIQs. */ cpsid if, #PSR_SVC32_MODE #ifdef VERBOSE_INIT_ARM PRINT(" PC=") mov r0, pc PRINT_R0 PRINT(" SP=") mov r0, sp PRINT_R0 PRINT("CPSR=") mrs r0, cpsr PRINT_R0 PRINT("CBAR=") mrc p15, 4, r0, c15, c0, 0 // read cbar PRINT_R0 #endif /* VERBOSE_INIT_ARM */ /* set temporary stack */ movw sp, #:lower16:tmpstack movt sp, #:upper16:tmpstack PRINT("") bl cortex_init PRINT("\r\n") /* * Set up a preliminary mapping in the MMU to allow us to run * at KERNEL_BASE with caches on. */ PRINT("") movw r1, #:lower16:mmu_init_table movt r1, #:upper16:mmu_init_table movw r0, #:lower16:TEMP_L1_TABLE movt r0, #:upper16:TEMP_L1_TABLE bl arm_boot_l1pt_init PRINT("\r\n") /* * init the CPU TLB, Cache, MMU. */ PRINT("") #ifdef VERBOSE_INIT_ARM adr r11, xputc #endif movw r0, #:lower16:TEMP_L1_TABLE movt r0, #:upper16:TEMP_L1_TABLE bl arm_cpuinit PRINT("\r\n") #ifdef MULTIPROCESSOR movw r1, #:lower16:IMX7_AIPS_BASE+AIPS1_SRC_BASE movt r1, #:upper16:IMX7_AIPS_BASE+AIPS1_SRC_BASE /* disable core1 */ ldr r2, [r1, #SRC_A7RCR1] and r2, r2, #~(SRC_A7RCR1_A7_CORE1_ENABLE) str r2, [r1, #SRC_A7RCR1] /* get number of CPU core */ mrc p15, 1, r0, c9, c0, 2 /* read L2CTRL register */ mov r0, r0, lsr #24 and r0, r0, #3 /* r0 = (num of core) - 1 */ mov r3, #0 /* flags for arm_cpu_hatched */ cmp r0, #0 ble .hatch_done /* enable core1 */ adr r2, imx7_mpstart str r2, [r1, #SRC_GPR3] /* set core1 entry address */ ldr r2, [r1, #SRC_A7RCR1] orr r2, r2, #SRC_A7RCR1_A7_CORE1_ENABLE /* enable core1 */ str r2, [r1, #SRC_A7RCR1] orr r3, r3, #(1<<1) /* cpu1 bit for arm_cpu_hatched */ /* wait hatched */ movw r2, #:lower16:arm_cpu_hatched movt r2, #:upper16:arm_cpu_hatched mov r1, #0x10000000 /* i = 0x10000000; do { */ 1: dmb /* memory barrier */ ldr r0, [r2] cmp r0, r3 /* if (arm_cpu_hatched == r3) */ beq .hatched /* goto .hatched; */ subs r1, r1, #1 bne 1b /* } while (--i != 0); */ .not_hatched: PRINT("\r\nnot hatched. arm_cpu_hatched=") PRINT_R0 b .hatch_done .hatched: PRINT("\r\nMULTIPROCESSOR hatched!\r\n") .hatch_done: #endif PRINT("jump to start()\r\n") movw lr, #:lower16:start movt lr, #:upper16:start bx lr /* NOTREACHED */ imx7_mpstart: /* invalidate cache */ movw ip, #:lower16:_C_LABEL(armv7_dcache_inv_all) movt ip, #:upper16:_C_LABEL(armv7_dcache_inv_all) #ifndef KERNEL_BASES_EQUAL sub ip, ip, #KERNEL_BASE_VOFFSET #endif blx ip b _C_LABEL(cortex_mpstart) #include mmu_init_table: /* map VA==PA for MEM (0x80000000-0xbfffffff) */ MMU_INIT(0x80000000, 0x80000000, 0x40000000 / L1_S_SIZE, L1_S_PROTO_armv7 | L1_S_APv7_KRW | L1_S_CACHEABLE) #if KERNEL_BASE_VOFFSET != 0 MMU_INIT(KERNEL_BASE, KERNEL_BASE - KERNEL_BASE_VOFFSET, (BOOT_MEMSIZE * L1_S_SIZE + L1_S_SIZE - 1) / L1_S_SIZE, L1_S_PROTO_armv7 | L1_S_APv7_KRW | L1_S_CACHEABLE) #endif /* * physical to physical */ /* Map the 12MB of primary peripherals (AIPS1 + AIPS2 + AIPS3) */ MMU_INIT(IMX7_IOREG_PBASE, IMX7_IOREG_PBASE, (IMX7_IOREG_SIZE + L1_S_SIZE - 1) / L1_S_SIZE, L1_S_PROTO_armv7 | L1_S_APv7_KRW | L1_S_V6_XN) /* Map the 1MB of armcore peripherals */ MMU_INIT(IMX7_ARMCORE_PBASE, IMX7_ARMCORE_PBASE, (IMX7_ARMCORE_SIZE + L1_S_SIZE - 1) / L1_S_SIZE, L1_S_PROTO_armv7 | L1_S_APv7_KRW | L1_S_V6_XN) /* * virtual to physical */ /* Map the 12MB of primary peripherals (AIPS1 + AIPS2 + AIPS3) */ MMU_INIT(KERNEL_IO_IOREG_VBASE, IMX7_IOREG_PBASE, (IMX7_IOREG_SIZE + L1_S_SIZE - 1) / L1_S_SIZE, L1_S_PROTO_armv7 | L1_S_APv7_KRW | L1_S_V6_XN) /* Map the 1MB of armcore peripherals */ MMU_INIT(KERNEL_IO_ARMCORE_VBASE, IMX7_ARMCORE_PBASE, (IMX7_ARMCORE_SIZE + L1_S_SIZE - 1) / L1_S_SIZE, L1_S_PROTO_armv7 | L1_S_APv7_KRW | L1_S_V6_XN) /* end of table */ MMU_INIT(0, 0, 0, 0) #ifdef VERBOSE_INIT_ARM /* * xprint - print strings pointed by $PC(LR) * and return to the end of string. * all registers are saved. * e.g.) * bl xprint <- call * .ascii "Hello\r\n\0" <- don't return here * .align 2 * nop <- return to here */ xprint: stmfd sp!, {r0, r1} mov r1, lr 1: ldrb r0, [r1], #1 stmfd sp!, {r0, r1, r2, r3} bl xputc ldmfd sp!, {r0, r1, r2, r3} cmp r0, #0 bne 1b add r1, r1, #3 bic lr, r1, #3 /* lr = 4byte-aligned end of string */ ldmfd sp!, {r0, r1} bx lr /* * print_r0 - show r0 hexadecimal with CR/LF. * all registers are saved. */ print_r0: stmfd sp!, {r0, r3, lr} mov r3, r0 mov r0, #'0' bl debugputc mov r0, #'x' bl debugputc bl print_r3 mov r0, #'\r' bl debugputc mov r0, #'\n' bl debugputc ldmfd sp!, {r0, r3, pc} /* * print_r3 - show r3 hexadecimal without CR/LF nor prefix(0x). * all registers are saved. */ print_r3: stmfd sp!, {r0, r3-r6, lr} mov r4, #28 /* num of shift. 28,24,20...8,4,0 */ mov r5, #0xf /* mask */ 1: and r6, r5, r3, ROR r4 cmp r6, #10 addlt r0, r6, #'0' addge r0, r6, #('a' - 0x0a) bl debugputc subs r4, r4, #4 bge 1b ldmfd sp!, {r0, r3-r6, pc} /* * debugputc - putc r0. xputc() is defined in arm/cortex/a9_mpsubr.S * all registers are saved. */ debugputc: stmfd sp!, {r0, r1, r2, r3, lr} bl xputc ldmfd sp!, {r0, r1, r2, r3, pc} #endif /* VERBOSE_INIT_ARM */ /* * temporary local stack */ .align 8 .space 4096 tmpstack: END(_C_LABEL(imx7_start))