/* $Id: imx23_olinuxino_start.S,v 1.3 2015/01/10 12:11:39 jmcneill 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 "opt_imx.h" #include #include #include #include #ifdef DEBUG #include #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