215 lines
5.7 KiB
ArmAsm
215 lines
5.7 KiB
ArmAsm
/* $Id: imx23_olinuxino_start.S,v 1.2 2013/10/07 17:36:40 matt Exp $ */
|
|
|
|
/*
|
|
* Copyright (c) 2012 The NetBSD Foundation, Inc.
|
|
* All rights reserved.
|
|
*
|
|
* This code is derived from software contributed to The NetBSD Foundation
|
|
* by Petri Laakso.
|
|
*
|
|
* 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 NETBSD FOUNDATION, INC. AND CONTRIBUTORS
|
|
* ``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 FOUNDATION OR CONTRIBUTORS
|
|
* 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 <machine/asm.h>
|
|
#include <machine/pmap.h>
|
|
#include <arm/armreg.h>
|
|
#include <arm/imx/imx23var.h>
|
|
#ifdef DEBUG
|
|
#include <arm/imx/imx23_uartdbgreg.h>
|
|
#endif
|
|
|
|
.section .start,"ax",%progbits
|
|
|
|
.global _C_LABEL(olinuxino_start)
|
|
_C_LABEL(olinuxino_start):
|
|
/*
|
|
* Set up the first level page table. The page table has 4096 section
|
|
* page table entries which each one maps 1MB of virtual memory.
|
|
* Section entries are mapped from mmu_init_table to the page table.
|
|
*/
|
|
l1pt_p .req r0
|
|
mit_p .req r1
|
|
va .req r2
|
|
pa .req r3
|
|
n_sec .req r4
|
|
attr .req r5
|
|
pte_p .req r6
|
|
sec .req r7
|
|
tmp .req r8
|
|
tmp2 .req r9
|
|
|
|
ldr l1pt_p, .Ll1_pt
|
|
|
|
/* Zero the page table. */
|
|
mov tmp, #0
|
|
add tmp2, l1pt_p, #L1_TABLE_SIZE
|
|
1: str tmp, [l1pt_p], #4
|
|
cmp l1pt_p, tmp2
|
|
blt 1b
|
|
|
|
ldr l1pt_p, .Ll1_pt
|
|
|
|
/* Map sections to the page table. */
|
|
ldr mit_p, =mmu_init_table
|
|
ldmia mit_p!, {va, pa, n_sec, attr}
|
|
|
|
/*
|
|
* Calculate PTE addresses for a MVA's.
|
|
*
|
|
* Bits[31:14] of the Translation Table Base register are concatenated
|
|
* with bits[31:20] of the modified virtual address and two zero bits
|
|
* to produce a physical address of the page table entry for a MVA:
|
|
*
|
|
* PTE = (TTBR & 0xffffc000) | ((MVA & 0xfff00000)>>18)
|
|
*/
|
|
3: ldr tmp, =0xffffc000
|
|
and pte_p, l1pt_p, tmp
|
|
ldr tmp, =0xfff00000
|
|
and va, va, tmp
|
|
mov va, va, LSR #18
|
|
orr pte_p, pte_p, va
|
|
|
|
2: orr sec, pa, attr
|
|
str sec, [pte_p], #4 /* Store #n_sec sections to the page */
|
|
add pa, pa, #0x100000 /* table. */
|
|
subs n_sec, #1
|
|
bne 2b
|
|
|
|
ldmia mit_p!, {va, pa, n_sec, attr}
|
|
cmp n_sec, #0
|
|
bne 3b
|
|
|
|
/*
|
|
* The Translation Table Base Register holds the physical address of
|
|
* the page table.
|
|
*/
|
|
mcr p15, 0, l1pt_p, c2, c0, 0
|
|
|
|
.unreq l1pt_p
|
|
.unreq mit_p
|
|
.unreq va
|
|
.unreq pa
|
|
.unreq n_sec
|
|
.unreq attr
|
|
.unreq pte_p
|
|
.unreq sec
|
|
.unreq tmp
|
|
.unreq tmp2
|
|
|
|
/*
|
|
* Sections are in domain 0 and we set D0 access control to client
|
|
* mode, which means AP bits are checked. Since we are running
|
|
* privileged mode and APs are kernel read/write, access is granted.
|
|
*/
|
|
mov r0, #DOMAIN_CLIENT<<(PMAP_DOMAIN_KERNEL*2)
|
|
mcr p15, 0, r0, c3, c0, 0
|
|
|
|
/*
|
|
* Enable the MMU.
|
|
*/
|
|
mrc p15, 0, r0, c1, c0, 0
|
|
ldr r1, =(CPU_CONTROL_IC_ENABLE | CPU_CONTROL_DC_ENABLE \
|
|
| CPU_CONTROL_AFLT_ENABLE | CPU_CONTROL_MMU_ENABLE)
|
|
orr r0, r0, r1
|
|
mcr p15, 0, r0, c1, c0, 0
|
|
nop /* Fetch flat. */
|
|
nop /* Fetch flat. */
|
|
|
|
/*
|
|
* Now MMU is on and instruction fetches are translated.
|
|
*/
|
|
|
|
/*
|
|
* Jump to start in locore.S. start sets the sp point to DRAM, zeroes
|
|
* the .bss and calls initarm. start never returns.
|
|
*/
|
|
ldr pc, =start
|
|
1: b 1b
|
|
|
|
/* NOTREACHED */
|
|
|
|
/*
|
|
* Initial first level translation table on a 16kB boundary located at the
|
|
* end of the DRAM.
|
|
*
|
|
* The translation table has 4096 32-bit section entries, each describing 1MB of
|
|
* virtual memory which means 4GB of virtual memory to be addressed.
|
|
*/
|
|
.Ll1_pt:
|
|
.word (DRAM_BASE + MEMSIZE * 1024 * 1024 - L1_TABLE_SIZE)
|
|
|
|
#define MMU_INIT(va,pa,n_sec,attr) \
|
|
.word va; \
|
|
.word pa; \
|
|
.word n_sec; \
|
|
.word attr;
|
|
|
|
mmu_init_table:
|
|
/* On-chip RAM */
|
|
MMU_INIT(0x00000000, 0x00000000,
|
|
1,
|
|
L1_S_AP(AP_KRW) | L1_S_DOM(PMAP_DOMAIN_KERNEL) | L1_S_PROTO)
|
|
|
|
/* On-chip ROM (Vectors) */
|
|
MMU_INIT(0xFFFF0000, 0xFFFF0000,
|
|
1,
|
|
L1_S_AP(AP_KRW) | L1_S_DOM(PMAP_DOMAIN_KERNEL) | L1_S_PROTO)
|
|
|
|
/* DRAM */
|
|
MMU_INIT(KERNEL_BASE_virt, KERNEL_BASE_phys,
|
|
MEMSIZE,
|
|
L1_S_AP(AP_KRW) | L1_S_DOM(PMAP_DOMAIN_KERNEL) | L1_S_C |\
|
|
L1_S_B | L1_S_PROTO)
|
|
|
|
/* VA == PA mapping for instruction fetches just after MMU_ENABLE. */
|
|
MMU_INIT(KERNEL_BASE_phys, KERNEL_BASE_phys,
|
|
1,
|
|
L1_S_AP(AP_KRW) | L1_S_DOM(PMAP_DOMAIN_KERNEL) | L1_S_C |\
|
|
L1_S_B | L1_S_PROTO)
|
|
|
|
/* Peripherals */
|
|
MMU_INIT(APBH_BASE, APBH_BASE,
|
|
1,
|
|
L1_S_AP(AP_KRW) | L1_S_DOM(PMAP_DOMAIN_KERNEL) | L1_S_PROTO)
|
|
|
|
MMU_INIT(0, 0, 0, 0)
|
|
|
|
#ifdef DEBUG
|
|
/*
|
|
* Write character in r0 register to Debug UART.
|
|
*/
|
|
.global _C_LABEL(dbputc)
|
|
_C_LABEL(dbputc):
|
|
stmfd sp!, {r0, r1, r2, lr}
|
|
|
|
/* Wait until transmit FIFO has space for the new character. */
|
|
ldr r1, =(HW_UARTDBG_BASE + HW_UARTDBGFR)
|
|
1: ldr r2, [r1]
|
|
ands r2, r2, #0x20 /* HW_UARTDBGFR_TXFF */
|
|
bne 1b
|
|
|
|
ldr r1, =(HW_UARTDBG_BASE + HW_UARTDBGDR)
|
|
strb r0, [r1]
|
|
|
|
ldmfd sp!, {r0, r1, r2, pc}
|
|
#endif
|