Home | History | Annotate | Line # | Download | only in epoc32
      1 /*	$NetBSD: epoc32_start.S,v 1.1 2013/04/28 12:11:26 kiyohara Exp $	*/
      2 /*
      3  * Copyright (c) 2012, 2013 KIYOHARA Takashi
      4  * All rights reserved.
      5  *
      6  * Redistribution and use in source and binary forms, with or without
      7  * modification, are permitted provided that the following conditions
      8  * are met:
      9  * 1. Redistributions of source code must retain the above copyright
     10  *    notice, this list of conditions and the following disclaimer.
     11  * 2. Redistributions in binary form must reproduce the above copyright
     12  *    notice, this list of conditions and the following disclaimer in the
     13  *    documentation and/or other materials provided with the distribution.
     14  *
     15  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
     16  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
     17  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
     18  * DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
     19  * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
     20  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
     21  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
     22  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
     23  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
     24  * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
     25  * POSSIBILITY OF SUCH DAMAGE.
     26  */
     27 
     28 #include <machine/asm.h>
     29 #include <machine/bootinfo.h>
     30 #include <arm/armreg.h>
     31 #include "assym.h"
     32 
     33 /*
     34  * Kernel start routine for EPOC32
     35  * this code is excuted at the very first after the kernel is loaded.
     36  */
     37 	.text
     38 
     39 	.global _C_LABEL(epoc32_start)
     40 _C_LABEL(epoc32_start):
     41 
     42 	/* copy bootinfo */
     43 	adr	r1, bootinfo
     44 	mov	r2, #BTINFO_MAX_SIZE
     45 	sub	r2, r2, #4
     46 0:
     47 	ldr	r3, [r0, r2]
     48 	str	r3, [r1, r2]
     49 	subs	r2, r2, #4
     50 	bge	0b
     51 
     52 	/*
     53 	 * Build page table from scratch.
     54 	 * Our boot-loader(e32boot) disables D-cache already.
     55 	 */
     56 	adr	r0, mmu_init_table
     57 	b	2f
     58 
     59 1:
     60 	str	r3, [r2]
     61 	add	r2, r2, #4
     62 	add	r3, r3, #L1_S_SIZE
     63 	adds	r1, r1, #-1
     64 	bhi	1b
     65 2:
     66 	ldmia	r0!, {r1, r2}		/* # of sections, VA */
     67 	ldr	r3, startup_pagetable	/* pagetable */
     68 	add	r2, r2, r3
     69 	ldr	r3, [r0], #4		/* # of PA|attr */
     70 	cmp	r1, #0
     71 	bne	1b
     72 
     73 	/*
     74 	 * Check physical memory segments. We require least 4MB for startup.
     75 	 */
     76 	adr	r0, bootinfo
     77 next_btinfo:
     78 	ldmia	r0, {r1, r2}
     79 	cmp	r2, #BTINFO_NONE
     80 	beq	99f			/* XXXX: Oops. no memory info? */
     81 	cmp	r2, #BTINFO_MEMORY
     82 	beq	btinfo_memory
     83 	add	r0, r0, r1
     84 	b	next_btinfo
     85 
     86 btinfo_memory_index:
     87 	.space	4
     88 
     89 btinfo_memory:
     90 	mov	r3, #0
     91 	str	r3, btinfo_memory_index
     92 
     93 	ldr	r3, [r0, #12]		/* Load size */
     94 	cmp	r3, #L1_S_SIZE
     95 	blt	map_l1c
     96 map_l1s:
     97 	/* Make L1 descriptor */
     98 	ldr	r3, [r0, #8]		/* Load phys address */
     99 	ldr	r2, btinfo_memory_index
    100 	add	r3, r2, r3
    101 	ldr	r2, startup_pagetable_l1s_attr
    102 	orr	r2, r2, r3
    103 
    104 	ldr	r1, startup_pagetable	/* pagetable */
    105 	ldr	r3, startup_space
    106 	add	r3, r3, #KERNEL_BASE
    107 	mov	r3, r3, lsr #(L1_S_SHIFT - 2)
    108 	add	r1, r3, r1
    109 	str	r2, [r1]
    110 
    111 	ldr	r2, btinfo_memory_index
    112 	add	r2, r2, #L1_S_SIZE
    113 	str	r2, btinfo_memory_index
    114 	ldr	r1, startup_space
    115 	add	r1, r1, #L1_S_SIZE
    116 	str	r1, startup_space
    117 	cmp	r1, #0x00400000		/* 4MB */
    118 	bge	99f
    119 	ldr	r1, [r0, #12]
    120 	cmp	r1, r2
    121 	bgt	map_l1s
    122 	ldr	r1, [r0]		/* Load size of btinfo_memory */
    123 	add	r0, r0, r1
    124 	b	next_btinfo
    125 
    126 map_l1c:
    127 	mov	r1, #1
    128 	mov	r2, r1, lsl #L1_S_SHIFT
    129 	sub	r2, r2, #1
    130 	ldr	r3, startup_space
    131 	ands	r2, r3, r2
    132 	bne	map_l2s
    133 
    134 	/* Make L1 descriptor */
    135 	ldr	r2, startup_pagetable
    136 	add	r2, r2, #L1_TABLE_SIZE	/* L2 table */
    137 	mov	r3, r3, lsr #(12 - 2)
    138 	add	r2, r2, r3
    139 	ldr	r3, startup_pagetable_l1c_attr
    140 	orr	r2, r2, r3
    141 
    142 	ldr	r1, startup_pagetable
    143 	ldr	r3, startup_space
    144 	add	r3, r3, #KERNEL_BASE
    145 	mov	r3, r3, lsr #(20 - 2)
    146 	add	r1, r1, r3
    147 	str	r2, [r1]
    148 
    149 map_l2s:
    150 	ldr	r1, [r0, #8]		/* Load phys address */
    151 	ldr	r2, btinfo_memory_index
    152 	add	r1, r1, r2
    153 	ldr	r2, startup_pagetable_l2s_attr
    154 	orr	r2, r1, r2
    155 
    156 	ldr	r1, startup_space
    157 	mov	r1, r1, lsr #(L2_S_SHIFT - 2)
    158 	ldr	r3, startup_pagetable
    159 	add	r3, r3, #L1_TABLE_SIZE	/* L2 table */
    160 	add	r1, r3, r1
    161 	str	r2, [r1]
    162 
    163 	ldr	r2, btinfo_memory_index
    164 	add	r2, r2, #L2_S_SIZE
    165 	str	r2, btinfo_memory_index
    166 	ldr	r1, startup_space
    167 	add	r1, r1, #L2_S_SIZE
    168 	str	r1, startup_space
    169 	cmp	r1, #0x00400000		/* 4MB */
    170 	bge	99f
    171 	ldr	r1, [r0, #12]
    172 	cmp	r1, r2
    173 	bgt	map_l2s
    174 	ldr	r1, [r0]		/* Load size of btinfo_memory */
    175 	add	r0, r0, r1
    176 	b	next_btinfo
    177 
    178 99:
    179 
    180 	/*
    181 	 * Set the Domain Access register.  Very important!
    182 	 * startup_pagetable puts to domain 0 now.
    183 	 */
    184 #define KERNEL_DOMAIN(x)	((x) << (PMAP_DOMAIN_KERNEL << 1))
    185 	mov	r0, #(KERNEL_DOMAIN(DOMAIN_CLIENT) | DOMAIN_CLIENT)
    186 	mcr	p15, 0, r0, c3, c0, 0
    187 
    188 	/*
    189 	 * Enable MMU and etc...
    190 	 */
    191 	ldr	r0, startup_pagetable
    192 	mcr	p15, 0, r0, c2, c0, 0	/* Set TTB */
    193 
    194 	mcr	p15, 0, r1, c0, c0, 0	/* Get ProcID */
    195 	and	r2, r1, #CPU_ID_IMPLEMENTOR_MASK
    196 	cmp	r2, #CPU_ID_DEC
    197 	beq	cpu_id_dec
    198 	ands	r2, r1, #CPU_ID_7ARCH_MASK
    199 	bne	cpu_id_7arch_v4t
    200 cpu_id_7arch_v3:	/* 7 */
    201 	mcr	p15, 0, r0, c5, c0, 0	/* Flash TLB */
    202 	b	enable_mmu
    203 
    204 cpu_id_7arch_v4t:	/* 7TDMI */
    205 cpu_id_dec:		/* SA1100 */
    206 	mov	r0, #0
    207 	mcr	p15, 0, r0, c8, c7, 0	/* Flash TLB */
    208 	nop
    209 
    210 enable_mmu:
    211 	ldr	r0, startup_control
    212 	mcr	p15, 0, r0, c1, c0, 0
    213 	nop
    214 	nop
    215 
    216 	/* Jump to kernel code in TRUE VA */
    217 	adr	r0, Lstart
    218 	ldr	pc, [r0]
    219 
    220 Lstart:
    221 	.word	start
    222 
    223 	.globl	_C_LABEL(startup_pagetable)
    224 startup_pagetable:
    225 #define STARTUP_PAGETABLE_ADDR		0xc0000000	/* aligned 16kByte */
    226 	.word	STARTUP_PAGETABLE_ADDR
    227 startup_pagetable_l1s_attr:
    228 	.word	L1_S_PROTO_generic | L1_S_C | L1_S_AP_KRW
    229 startup_pagetable_l1c_attr:
    230 	.word	L1_C_PROTO_generic
    231 startup_pagetable_l2s_attr:
    232 	.word	L2_S_PROTO_generic | L2_C | L2_AP_KRW
    233 startup_space:
    234 	.word	0x00000000
    235 startup_control:
    236 	.word	CPU_CONTROL_MMU_ENABLE  | \
    237 		CPU_CONTROL_DC_ENABLE   | \
    238 		CPU_CONTROL_WBUF_ENABLE | \
    239 		CPU_CONTROL_32BP_ENABLE | \
    240 		CPU_CONTROL_32BD_ENABLE | \
    241 		CPU_CONTROL_IC_ENABLE
    242 
    243 	.globl	_C_LABEL(bootinfo)
    244 bootinfo:
    245 	.space	BTINFO_MAX_SIZE
    246 
    247 #define MMU_INIT(va, pa, n_sec, attr)	  \
    248 	.word	n_sec			; \
    249 	.word	(va) >> (L1_S_SHIFT - 2); \
    250 	.word	(pa) | (attr)		;
    251 
    252 mmu_init_table:
    253 	/* fill all table VA==PA */
    254 	MMU_INIT(0x00000000, 0x00000000,
    255 	    1 << (32 - L1_S_SHIFT), L1_S_PROTO | L1_S_AP_KRW)
    256 	MMU_INIT(0, 0, 0, 0)		/* end of table */
    257