11.3Sjmcneill/* $Id: imx23_olinuxino_start.S,v 1.3 2015/01/10 12:11:39 jmcneill Exp $ */
21.1Sjkunz
31.1Sjkunz/*
41.1Sjkunz * Copyright (c) 2012 The NetBSD Foundation, Inc.
51.1Sjkunz * All rights reserved.
61.1Sjkunz *
71.1Sjkunz * This code is derived from software contributed to The NetBSD Foundation
81.1Sjkunz * by Petri Laakso.
91.1Sjkunz *
101.1Sjkunz * Redistribution and use in source and binary forms, with or without
111.1Sjkunz * modification, are permitted provided that the following conditions
121.1Sjkunz * are met:
131.1Sjkunz * 1. Redistributions of source code must retain the above copyright
141.1Sjkunz *    notice, this list of conditions and the following disclaimer.
151.1Sjkunz * 2. Redistributions in binary form must reproduce the above copyright
161.1Sjkunz *    notice, this list of conditions and the following disclaimer in the
171.1Sjkunz *    documentation and/or other materials provided with the distribution.
181.1Sjkunz *
191.1Sjkunz * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
201.1Sjkunz * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
211.1Sjkunz * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
221.1Sjkunz * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
231.1Sjkunz * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
241.1Sjkunz * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
251.1Sjkunz * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
261.1Sjkunz * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
271.1Sjkunz * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
281.1Sjkunz * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
291.1Sjkunz * POSSIBILITY OF SUCH DAMAGE.
301.1Sjkunz */
311.1Sjkunz
321.3Sjmcneill#include "opt_imx.h"
331.3Sjmcneill
341.1Sjkunz#include <machine/asm.h>
351.1Sjkunz#include <machine/pmap.h>
361.1Sjkunz#include <arm/armreg.h>
371.1Sjkunz#include <arm/imx/imx23var.h>
381.2Smatt#ifdef DEBUG
391.1Sjkunz#include <arm/imx/imx23_uartdbgreg.h>
401.2Smatt#endif
411.1Sjkunz
421.1Sjkunz.section .start,"ax",%progbits
431.1Sjkunz
441.1Sjkunz.global	_C_LABEL(olinuxino_start)
451.1Sjkunz_C_LABEL(olinuxino_start):
461.1Sjkunz	/*
471.1Sjkunz	 * Set up the first level page table. The page table has 4096 section
481.1Sjkunz	 * page table entries which each one maps 1MB of virtual memory.
491.1Sjkunz	 * Section entries are mapped from mmu_init_table to the page table.
501.1Sjkunz	 */
511.1Sjkunz	l1pt_p	.req r0
521.1Sjkunz	mit_p	.req r1
531.1Sjkunz	va	.req r2
541.1Sjkunz	pa	.req r3
551.1Sjkunz	n_sec	.req r4
561.1Sjkunz	attr	.req r5
571.1Sjkunz	pte_p	.req r6
581.1Sjkunz	sec	.req r7
591.1Sjkunz	tmp	.req r8
601.1Sjkunz	tmp2	.req r9
611.1Sjkunz
621.2Smatt	ldr	l1pt_p, .Ll1_pt
631.1Sjkunz
641.1Sjkunz	/* Zero the page table. */
651.1Sjkunz	mov	tmp, #0
661.1Sjkunz	add	tmp2, l1pt_p, #L1_TABLE_SIZE
671.1Sjkunz1:	str	tmp, [l1pt_p], #4
681.1Sjkunz	cmp	l1pt_p, tmp2
691.1Sjkunz	blt	1b
701.1Sjkunz
711.2Smatt	ldr	l1pt_p, .Ll1_pt
721.1Sjkunz
731.2Smatt	/* Map sections to the page table. */
741.1Sjkunz	ldr	mit_p, =mmu_init_table
751.1Sjkunz	ldmia	mit_p!, {va, pa, n_sec, attr}
761.1Sjkunz
771.1Sjkunz	/*
781.1Sjkunz	 * Calculate PTE addresses for a MVA's.
791.1Sjkunz	 *
801.1Sjkunz	 * Bits[31:14] of the Translation Table Base register are concatenated
811.1Sjkunz	 * with bits[31:20] of the modified virtual address and two zero bits
821.1Sjkunz	 * to produce a physical address of the page table entry for a MVA:
831.1Sjkunz	 *
841.1Sjkunz	 * PTE = (TTBR & 0xffffc000) | ((MVA & 0xfff00000)>>18)
851.1Sjkunz	 */
861.1Sjkunz3:	ldr	tmp, =0xffffc000
871.1Sjkunz	and	pte_p, l1pt_p, tmp
881.1Sjkunz	ldr	tmp, =0xfff00000
891.1Sjkunz	and	va, va, tmp
901.1Sjkunz	mov	va, va, LSR #18
911.1Sjkunz	orr	pte_p, pte_p, va
921.1Sjkunz
931.1Sjkunz2:	orr	sec, pa, attr
941.1Sjkunz	str	sec, [pte_p], #4	/* Store #n_sec sections to the page */
951.1Sjkunz	add	pa, pa, #0x100000	/* table. */
961.1Sjkunz	subs	n_sec, #1
971.1Sjkunz	bne	2b
981.1Sjkunz
991.1Sjkunz	ldmia	mit_p!, {va, pa, n_sec, attr}
1001.1Sjkunz	cmp	n_sec, #0
1011.1Sjkunz	bne	3b
1021.1Sjkunz
1031.1Sjkunz	/*
1041.1Sjkunz	 * The Translation Table Base Register holds the physical address of
1051.1Sjkunz	 * the page table.
1061.1Sjkunz	 */
1071.1Sjkunz	mcr	p15, 0, l1pt_p, c2, c0, 0
1081.1Sjkunz
1091.1Sjkunz	.unreq	l1pt_p
1101.1Sjkunz	.unreq	mit_p
1111.1Sjkunz	.unreq	va
1121.1Sjkunz	.unreq	pa
1131.1Sjkunz	.unreq	n_sec
1141.1Sjkunz	.unreq	attr
1151.1Sjkunz	.unreq	pte_p
1161.1Sjkunz	.unreq	sec
1171.1Sjkunz	.unreq	tmp
1181.1Sjkunz	.unreq	tmp2
1191.1Sjkunz
1201.1Sjkunz	/*
1211.1Sjkunz	 * Sections are in domain 0 and we set D0 access control to client
1221.1Sjkunz	 * mode, which means AP bits are checked. Since we are running
1231.1Sjkunz	 * privileged mode and APs are kernel read/write, access is granted.
1241.1Sjkunz	 */
1251.1Sjkunz	mov	r0, #DOMAIN_CLIENT<<(PMAP_DOMAIN_KERNEL*2)
1261.1Sjkunz	mcr	p15, 0, r0, c3, c0, 0
1271.1Sjkunz
1281.1Sjkunz	/*
1291.1Sjkunz	 * Enable the MMU.
1301.1Sjkunz	 */
1311.1Sjkunz	mrc	p15, 0, r0, c1, c0, 0
1321.1Sjkunz	ldr	r1, =(CPU_CONTROL_IC_ENABLE | CPU_CONTROL_DC_ENABLE \
1331.1Sjkunz			| CPU_CONTROL_AFLT_ENABLE | CPU_CONTROL_MMU_ENABLE)
1341.1Sjkunz	orr	r0, r0, r1
1351.1Sjkunz	mcr	p15, 0, r0, c1, c0, 0
1361.1Sjkunz	nop	/* Fetch flat. */
1371.1Sjkunz	nop	/* Fetch flat. */
1381.1Sjkunz
1391.1Sjkunz	/*
1401.2Smatt	 * Now MMU is on and instruction fetches are translated.
1411.2Smatt	 */
1421.2Smatt
1431.2Smatt	/*
1441.1Sjkunz	 * Jump to start in locore.S. start sets the sp point to DRAM, zeroes
1451.1Sjkunz	 * the .bss and calls initarm. start never returns.
1461.1Sjkunz	 */
1471.1Sjkunz	ldr	pc, =start
1481.2Smatt1:	b	1b
1491.1Sjkunz
1501.1Sjkunz	/* NOTREACHED */
1511.1Sjkunz
1521.1Sjkunz/*
1531.1Sjkunz * Initial first level translation table on a 16kB boundary located at the
1541.1Sjkunz * end of the DRAM.
1551.1Sjkunz *
1561.1Sjkunz * The translation table has 4096 32-bit section entries, each describing 1MB of
1571.1Sjkunz * virtual memory which means 4GB of virtual memory to be addressed.
1581.1Sjkunz */
1591.2Smatt.Ll1_pt:
1601.1Sjkunz	.word (DRAM_BASE + MEMSIZE * 1024 * 1024 - L1_TABLE_SIZE)
1611.1Sjkunz
1621.1Sjkunz#define MMU_INIT(va,pa,n_sec,attr)					\
1631.1Sjkunz	.word va;							\
1641.1Sjkunz	.word pa;							\
1651.1Sjkunz	.word n_sec;							\
1661.1Sjkunz	.word attr;
1671.1Sjkunz
1681.1Sjkunzmmu_init_table:
1691.1Sjkunz	/* On-chip RAM */
1701.1Sjkunz	MMU_INIT(0x00000000, 0x00000000,
1711.1Sjkunz		1,
1721.1Sjkunz		L1_S_AP(AP_KRW) | L1_S_DOM(PMAP_DOMAIN_KERNEL) | L1_S_PROTO)
1731.1Sjkunz
1741.1Sjkunz	/* On-chip ROM (Vectors) */
1751.1Sjkunz	MMU_INIT(0xFFFF0000, 0xFFFF0000,
1761.1Sjkunz		1,
1771.1Sjkunz		L1_S_AP(AP_KRW) | L1_S_DOM(PMAP_DOMAIN_KERNEL) | L1_S_PROTO)
1781.1Sjkunz
1791.1Sjkunz	/* DRAM */
1801.1Sjkunz	MMU_INIT(KERNEL_BASE_virt, KERNEL_BASE_phys,
1811.1Sjkunz		MEMSIZE,
1821.1Sjkunz		L1_S_AP(AP_KRW) | L1_S_DOM(PMAP_DOMAIN_KERNEL) | L1_S_C |\
1831.1Sjkunz			L1_S_B | L1_S_PROTO)
1841.1Sjkunz
1851.2Smatt	/* VA == PA mapping for instruction fetches just after MMU_ENABLE. */
1861.2Smatt	MMU_INIT(KERNEL_BASE_phys, KERNEL_BASE_phys,
1871.2Smatt		1,
1881.2Smatt		L1_S_AP(AP_KRW) | L1_S_DOM(PMAP_DOMAIN_KERNEL) | L1_S_C |\
1891.2Smatt			L1_S_B | L1_S_PROTO)
1901.2Smatt
1911.1Sjkunz	/* Peripherals */
1921.1Sjkunz	MMU_INIT(APBH_BASE, APBH_BASE,
1931.1Sjkunz		1,
1941.1Sjkunz		L1_S_AP(AP_KRW) | L1_S_DOM(PMAP_DOMAIN_KERNEL) | L1_S_PROTO)
1951.1Sjkunz
1961.1Sjkunz	MMU_INIT(0, 0, 0, 0)
1971.2Smatt
1981.2Smatt#ifdef DEBUG
1991.2Smatt/*
2001.2Smatt * Write character in r0 register to Debug UART.
2011.2Smatt */
2021.2Smatt.global	_C_LABEL(dbputc)
2031.2Smatt_C_LABEL(dbputc):
2041.2Smatt	stmfd	sp!, {r0, r1, r2, lr}
2051.2Smatt
2061.2Smatt        /* Wait until transmit FIFO has space for the new character. */
2071.2Smatt	ldr	r1, =(HW_UARTDBG_BASE + HW_UARTDBGFR)
2081.2Smatt1:	ldr	r2, [r1]
2091.2Smatt	ands	r2, r2, #0x20	/* HW_UARTDBGFR_TXFF */
2101.2Smatt	bne	1b
2111.2Smatt
2121.2Smatt	ldr	r1, =(HW_UARTDBG_BASE + HW_UARTDBGDR)
2131.2Smatt	strb	r0, [r1]
2141.2Smatt
2151.2Smatt	ldmfd	sp!, {r0, r1, r2, pc}
2161.2Smatt#endif
217