NetBSD/sys/arch/evbarm/imx7/imx7_start.S

329 lines
8.1 KiB
ArmAsm

/* $NetBSD: imx7_start.S,v 1.1 2016/05/17 06:44:46 ryo Exp $ */
/*-
* Copyright (c) 2014 Ryo Shimizu <ryo@nerv.org>
* 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 <arm/asm.h>
#include <arm/armreg.h>
#include <arm/cortex/scu_reg.h>
#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("<cortex_init>")
bl cortex_init
PRINT("</cortex_init>\r\n")
/*
* Set up a preliminary mapping in the MMU to allow us to run
* at KERNEL_BASE with caches on.
*/
PRINT("<mmu_init_table>")
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("</mmu_init_table>\r\n")
/*
* init the CPU TLB, Cache, MMU.
*/
PRINT("<arm_cpuinit>")
#ifdef VERBOSE_INIT_ARM
adr r11, xputc
#endif
movw r0, #:lower16:TEMP_L1_TABLE
movt r0, #:upper16:TEMP_L1_TABLE
bl arm_cpuinit
PRINT("</arm_cpuinit>\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 <arm/cortex/a9_mpsubr.S>
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))