1/* $NetBSD: armadillo9_start.S,v 1.5 2011/01/31 06:28:02 matt Exp $ */ 2 3/* 4 * Copyright (c) 2003 5 * Ichiro FUKUHARA <ichiro@ichiro.org>. 6 * All rights reserved. 7 * 8 * Redistribution and use in source and binary forms, with or without 9 * modification, are permitted provided that the following conditions 10 * are met: 11 * 1. Redistributions of source code must retain the above copyright 12 * notice, this list of conditions and the following disclaimer. 13 * 2. Redistributions in binary form must reproduce the above copyright 14 * notice, this list of conditions and the following disclaimer in the 15 * documentation and/or other materials provided with the distribution. 16 * 17 * THIS SOFTWARE IS PROVIDED BY ICHIRO FUKUHARA ``AS IS'' AND ANY EXPRESS OR 18 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 19 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 20 * IN NO EVENT SHALL ICHIRO FUKUHARA OR THE VOICES IN HIS HEAD BE LIABLE FOR 21 * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 22 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 23 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 24 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 25 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 26 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 27 * SUCH DAMAGE. 28 */ 29#include "epcom.h" 30 31#include <machine/asm.h> 32#include <arm/armreg.h> 33#include "assym.h" 34 35RCSID("$NetBSD: armadillo9_start.S,v 1.5 2011/01/31 06:28:02 matt Exp $") 36 37 .section .start,"ax",%progbits 38 39 .global _C_LABEL(armadillo9_start) 40_C_LABEL(armadillo9_start): 41 42 /* make sure svc mode and all fiqs&irqs disabled */ 43 mov r0, #(PSR_SVC32_MODE | I32_bit | F32_bit) 44 msr cpsr_c, r0 45 46 /* 47 * We will go ahead and disable the MMU here so that we don't 48 * have to worry about flushing caches, etc. 49 * 50 * Note that we may not currently be running VA==PA, which means 51 * we'll need to leap to the next insn after disabing the MMU. 52 */ 53 adr r8, Lunmapped 54 bic r8, r8, #0xff000000 /* clear upper 8 bits */ 55 orr r8, r8, #0xc0000000 /* OR in physical base address */ 56 57 /* 58 * Setup coprocessor 15. 59 */ 60 mrc p15, 0, r2, c1, c0, 0 61 bic r2, r2, #CPU_CONTROL_MMU_ENABLE 62 bic r2, r2, #CPU_CONTROL_DC_ENABLE 63 bic r2, r2, #CPU_CONTROL_IC_ENABLE 64 mcr p15, 0, r2, c1, c0, 0 65 66 nop 67 nop 68 nop 69 mov pc, r8 /* Heave-ho! */ 70 71Lunmapped: 72 /* set temporary stack pointer */ 73 ldr sp, Ltable 74 75#ifdef VERBOSE_INIT_ARM 76 /* initialize UART */ 77 bl init_UART 78#endif 79 /* copy bootparam */ 80 bl copy_bootparam 81 82 /* copy myself to virtual address */ 83 bl copy_myself 84 85 /* 86 * We want to construct a memory map that maps us 87 * VA==PA (SDRAM at 0xc0000000). We create these 88 * mappings uncached and unbuffered to be safe. 89 */ 90 /* 91 * Step 1: Map the entire address space VA==PA. 92 */ 93 adr r4, Ltable 94 ldr r0, [r4] /* r0 = &l1table */ 95 mov r1, #(L1_TABLE_SIZE / 4) /* 4096 entry */ 96 mov r2, #(L1_S_SIZE) /* 1MB / section */ 97 mov r3, #(L1_S_AP_KRW) /* kernel read/write */ 98 orr r3, r3, #(L1_TYPE_S) /* L1 entry is section */ 991: 100 str r3, [r0], #0x04 101 add r3, r3, r2 102 subs r1, r1, #1 103 bgt 1b 104 105 /* 106 * Step 2: Map VA 0xf0000000->0xf00fffff to PA 0x80000000->0x800fffff. 107 */ 108 ldr r0, [r4] 109 add r0, r0, #(0xf00 * 4) /* offset to 0xf0000000 */ 110 mov r3, #(L1_S_AP_KRW) /* kernel read/write */ 111 orr r3, r3, #(L1_TYPE_S) /* L1 entry is section */ 112 orr r3, r3, #0x80000000 113 str r3, [r0], #4 114 115 /* 116 * Step 3: Map VA 0xf0100000->0xf02fffff to PA 0x80800000->0x809fffff. 117 */ 118 mov r3, #(L1_S_AP_KRW) /* kernel read/write */ 119 orr r3, r3, #(L1_TYPE_S) /* L1 entry is section */ 120 orr r3, r3, #0x80000000 121 orr r3, r3, #0x00800000 122 str r3, [r0], #0x4 123 add r3, r3, r2 124 str r3, [r0], #0x4 125 126 /* OK! Page table is set up. Give it to the CPU. */ 127 adr r0, Ltable 128 ldr r0, [r0] 129 mcr p15, 0, r0, c2, c0, 0 130 131 /* Flush the old TLBs, just in case. */ 132 mcr p15, 0, r0, c8, c7, 0 133 134 /* Set the Domain Access register. Very important! */ 135 mov r0, #1 136 mcr p15, 0, r0, c3, c0, 0 137 138 /* Get ready to jump to the "real" kernel entry point... */ 139 ldr r1, Lstart 140 mov r1, r1 /* Make sure the load completes! */ 141 142 /* OK, let's enable the MMU. */ 143 mrc p15, 0, r2, c1, c0, 0 144 orr r2, r2, #CPU_CONTROL_MMU_ENABLE 145 mcr p15, 0, r2, c1, c0, 0 146 147 nop 148 nop 149 nop 150 151 /* CPWAIT sequence to make sure the MMU is on... */ 152 mrc p15, 0, r2, c2, c0, 0 /* arbitrary read of CP15 */ 153 mov r2, r2 /* force it to complete */ 154 mov pc, r1 /* leap to kernel entry point! */ 155 156#define BOOTPARAM_ADDRESS 0xc0000100 157#define BOOTPARAM_SIZE 0x0f00 158 159Ltable: 160 .word armadillo9_start - L1_TABLE_SIZE 161Lstart: 162 .word start 163 164Lsection: 165 .word .start 166 .word 0xc0200000 167 .word __bss_start 168 169Lbootparam_address: 170 .word BOOTPARAM_ADDRESS 171 172copy_myself: 173 stmfd sp!, {r0-r5, lr} 174 adr r0, Lsection 175 ldmia r0, {r1, r2, r4} /* r1: kernel(load) start address */ 176 /* r2: kernel(virtual) start address */ 177 /* r3: kernel size */ 178 sub r3, r4, r2 /* r4: kernel(virtual) end address */ 179 add r5, r1, r3 /* r5: kernel(load) end address */ 180#ifdef VERBOSE_INIT_ARM 181 adr r0, Lmsg1 /* "copy kernel from " */ 182 bl print_str 183 bl print_r1 184 adr r0, Lmsg2 /* " to " */ 185 bl print_str 186 bl print_r2 187 adr r0, Lmsg3 /* " size " */ 188 bl print_str 189 bl print_r3 190 bl print_cr 191#endif 1921: 193 ldr r0, [r5], #-4 194 str r0, [r4], #-4 195 cmp r5, r1 196 bge 1b 197 ldmfd sp!, {r0-r5, pc} 198 199copy_bootparam: 200 stmfd sp!, {r0-r3, lr} 201 mov r1, #BOOTPARAM_SIZE 202 ldr r2, Lbootparam_address 203 adr r3, _C_LABEL(bootparam) 204#ifdef VERBOSE_INIT_ARM 205 adr r0, Lmsg0 /* "copy bootparam from " */ 206 bl print_str 207 bl print_r2 208 adr r0, Lmsg2 /* " to " */ 209 bl print_str 210 bl print_r3 211 adr r0, Lmsg3 /* " size " */ 212 bl print_str 213 bl print_r1 214 bl print_cr 215#endif 2161: 217 ldr r0, [r2], #4 218 str r0, [r3], #4 219 subs r1, r1, #4 220 bne 1b 221 ldmfd sp!, {r0-r3, pc} 222 223#ifdef VERBOSE_INIT_ARM 224Lmsg0: 225 .asciz "copy bootparam from " 226 .align 0 227Lmsg1: 228 .asciz "copy kernel from " 229 .align 0 230Lmsg2: 231 .asciz " to " 232 .align 0 233Lmsg3: 234 .asciz " size " 235 .align 0 236 237#if NEPCOM > 0 238#define EP93XX_APB_UART1 0x808c0000 239#define EP93XX_APB_UART2 0x808d0000 240 241#ifndef CONUNIT 242#define CONUNIT 0 243#endif 244 245Lcomaddr: 246 .word EP93XX_APB_UART1 247 .word EP93XX_APB_UART2 248#endif 249 250init_UART: 251 stmfd sp!, {r4-r5, lr} 252#if NEPCOM > 0 253 ldr r4, Lcomaddr+(CONUNIT*4) 254 ldr r5, [r4, #0x08] 255 orr r5, r5, #0x10 256 str r5, [r4, #0x08] /* enable FIFO */ 257 mov r5, #0x01 258 str r5, [r4, #0x14] /* disable interrupt */ 259#endif 260 ldmfd sp!, {r4-r5, pc} 261 262print_char: /* char = r0 */ 263 stmfd sp!, {r4-r5, lr} 264#if NEPCOM > 0 265 ldr r4, Lcomaddr+(CONUNIT*4) 2661: 267 ldr r5, [r4, #0x18] 268 tst r5, #0x20 /* check TXFF */ 269 bne 1b 270 str r0, [r4, #0x00] 271#endif 272 ldmfd sp!, {r4-r5, pc} 273 274print_cr: 275 stmfd sp!, {r0, lr} 276#if NEPCOM > 0 277 mov r0, #0x0d /* cr */ 278 bl print_char 279 mov r0, #0x0a /* lf */ 280 bl print_char 281#endif 282 ldmfd sp!, {r0, pc} 283 284print_str: 285 stmfd sp!, {r0, r4, lr} 286#if NEPCOM > 0 287 mov r4, r0 2881: 289 ldrb r0, [r4], #1 290 cmp r0, #0 291 beq 2f 292 bl print_char 293 b 1b 2942: 295#endif 296 ldmfd sp!, {r0, r4, pc} 297 298print_r3: 299 stmfd sp!, {r0, r3-r6, lr} 300#if NEPCOM > 0 301 mov r4, #28 302 mov r5, #0xf 3031: 304 and r6, r5, r3, ROR r4 305 cmp r6, #10 306 addlt r0, r6, #'0' 307 addge r0, r6, #('a' - 0x0a) 308 bl print_char 309 subs r4, r4, #4 310 bge 1b 311#endif 312 ldmfd sp!, {r0, r3-r6, pc} 313 314#define print_register(reg) \ 315 stmfd sp!, {r3, lr} ;\ 316 mov r3, reg ;\ 317 bl print_r3 ;\ 318 ldmfd sp!, {r3, pc} 319 320print_r0: 321 print_register(r0) 322 323print_r1: 324 print_register(r1) 325 326print_r2: 327 print_register(r2) 328#endif 329 330 .global _C_LABEL(bootparam) 331_C_LABEL(bootparam): 332 .space BOOTPARAM_SIZE 333