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 460: 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 591: 60 str r3, [r2] 61 add r2, r2, #4 62 add r3, r3, #L1_S_SIZE 63 adds r1, r1, #-1 64 bhi 1b 652: 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 77next_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 86btinfo_memory_index: 87 .space 4 88 89btinfo_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 96map_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 126map_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 149map_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 17899: 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 200cpu_id_7arch_v3: /* 7 */ 201 mcr p15, 0, r0, c5, c0, 0 /* Flash TLB */ 202 b enable_mmu 203 204cpu_id_7arch_v4t: /* 7TDMI */ 205cpu_id_dec: /* SA1100 */ 206 mov r0, #0 207 mcr p15, 0, r0, c8, c7, 0 /* Flash TLB */ 208 nop 209 210enable_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 220Lstart: 221 .word start 222 223 .globl _C_LABEL(startup_pagetable) 224startup_pagetable: 225#define STARTUP_PAGETABLE_ADDR 0xc0000000 /* aligned 16kByte */ 226 .word STARTUP_PAGETABLE_ADDR 227startup_pagetable_l1s_attr: 228 .word L1_S_PROTO_generic | L1_S_C | L1_S_AP_KRW 229startup_pagetable_l1c_attr: 230 .word L1_C_PROTO_generic 231startup_pagetable_l2s_attr: 232 .word L2_S_PROTO_generic | L2_C | L2_AP_KRW 233startup_space: 234 .word 0x00000000 235startup_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) 244bootinfo: 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 252mmu_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