1c62a0ac4Smatt/* 2c62a0ac4Smatt * mpcsa_start.S 3c62a0ac4Smatt * Copyright (c) 2007, S. Kantoluoto <sami.kantoluoto@iki.fi> 4c62a0ac4Smatt * All rights reserved. 5c62a0ac4Smatt * 6c62a0ac4Smatt * Based on vx115_vep_start.S 7c62a0ac4Smatt * Copyright (c) 2007, J. Sevy <jsevy@cs.drexel.edu> 8c62a0ac4Smatt * 9c62a0ac4Smatt * Based on g42xxeb_start.S 10c62a0ac4Smatt * Copyright (c) 2002, 2003 Genetec Corporation. All rights reserved. 11c62a0ac4Smatt * Written by Hiroyuki Bessho for Genetec Corporation. 12c62a0ac4Smatt * 13c62a0ac4Smatt * Redistribution and use in source and binary forms, with or without 14c62a0ac4Smatt * modification, are permitted provided that the following conditions 15c62a0ac4Smatt * are met: 16c62a0ac4Smatt * 1. Redistributions of source code must retain the above copyright 17c62a0ac4Smatt * notice, this list of conditions and the following disclaimer. 18c62a0ac4Smatt * 2. Redistributions in binary form must reproduce the above copyright 19c62a0ac4Smatt * notice, this list of conditions and the following disclaimer in the 20c62a0ac4Smatt * documentation and/or other materials provided with the distribution. 21c62a0ac4Smatt * 3. The name of Genetec Corporation may not be used to endorse or 22c62a0ac4Smatt * promote products derived from this software without specific prior 23c62a0ac4Smatt * written permission. 24c62a0ac4Smatt * 25c62a0ac4Smatt * THIS SOFTWARE IS PROVIDED BY GENETEC CORPORATION ``AS IS'' AND 26c62a0ac4Smatt * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 27c62a0ac4Smatt * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 28c62a0ac4Smatt * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL GENETEC CORPORATION 29c62a0ac4Smatt * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 30c62a0ac4Smatt * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 31c62a0ac4Smatt * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 32c62a0ac4Smatt * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 33c62a0ac4Smatt * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 34c62a0ac4Smatt * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 35c62a0ac4Smatt * POSSIBILITY OF SUCH DAMAGE. 36c62a0ac4Smatt */ 37c62a0ac4Smatt 38c62a0ac4Smatt#include <machine/asm.h> 39c62a0ac4Smatt#include <arm/armreg.h> 40*497ddd31Smatt#include "assym.h" 41*497ddd31Smatt 42*497ddd31SmattRCSID("$NetBSD: mpcsa_start.S,v 1.3 2011/01/31 06:28:04 matt Exp $") 43c62a0ac4Smatt 44c62a0ac4Smatt#ifndef FLASH_START 45c62a0ac4Smatt#define FLASH_START 0x10020000 46c62a0ac4Smatt#endif 47c62a0ac4Smatt 48c62a0ac4Smatt#ifndef SDRAM_START 49c62a0ac4Smatt#define SDRAM_START 0x20000000 50c62a0ac4Smatt#endif 51c62a0ac4Smatt 52c62a0ac4Smatt#define MODBASE 0x20200000 53c62a0ac4Smatt 54c62a0ac4Smatt/* 55c62a0ac4Smatt * CPWAIT -- Canonical method to wait for CP15 update. 56c62a0ac4Smatt * NOTE: Clobbers the specified temp reg. 57c62a0ac4Smatt * copied from arm/arm/cpufunc_asm_xscale.S 58c62a0ac4Smatt * XXX: better be in a common header file. 59c62a0ac4Smatt */ 60c62a0ac4Smatt#define CPWAIT_BRANCH \ 61c62a0ac4Smatt sub pc, pc, #4 62c62a0ac4Smatt 63c62a0ac4Smatt#define CPWAIT(tmp) \ 64c62a0ac4Smatt mrc p15, 0, tmp, c2, c0, 0 /* arbitrary read of CP15 */ ;\ 65c62a0ac4Smatt mov tmp, tmp /* wait for it to complete */ ;\ 66c62a0ac4Smatt CPWAIT_BRANCH /* branch to next insn */ 67c62a0ac4Smatt 68c62a0ac4Smatt/* 69c62a0ac4Smatt * Kernel start routine for MPCSA board. 70c62a0ac4Smatt * This code is executed from Flash when the bootloader jumps to it. 71c62a0ac4Smatt */ 72c62a0ac4Smatt .text 73c62a0ac4Smatt 74c62a0ac4Smatt .global _C_LABEL(mpcsa_start) 75c62a0ac4Smatt_C_LABEL(mpcsa_start): 76c62a0ac4Smatt 77c62a0ac4Smatt /* make sure we're in supervisor mode */ 78c62a0ac4Smatt mov r0,sp 79c62a0ac4Smatt msr CPSR_c,#I32_bit | F32_bit | PSR_SVC32_MODE 80c62a0ac4Smatt mov sp,r0 81c62a0ac4Smatt 82c62a0ac4Smatt /* move code to RAM */ 83c62a0ac4Smatt ldr r1, Lcopy_size 84c62a0ac4Smatt adr r0, _C_LABEL(mpcsa_start) 85c62a0ac4Smatt add r1, r1, #3 86c62a0ac4Smatt mov r1, r1, LSR #2 /* get size of code in words */ 87c62a0ac4Smatt mov r2, #SDRAM_START 88c62a0ac4Smatt add r2, r2, #0x200000 /* code placed 2MB above kernel base */ 89c62a0ac4Smatt mov r4, r2 90c62a0ac4Smatt 91c62a0ac4Smatt /* copy kernel to RAM */ 92c62a0ac4Smatt5: ldr r3, [r0], #4 93c62a0ac4Smatt subs r1, r1, #1 94c62a0ac4Smatt str r3, [r2], #4 95c62a0ac4Smatt bhi 5b 96c62a0ac4Smatt 97c62a0ac4Smatt /* jump to RAM */ 98c62a0ac4Smatt ldr r0, Lstart_off 99c62a0ac4Smatt add pc, r4, r0 100c62a0ac4Smatt 101c62a0ac4Smatt 102c62a0ac4SmattLcopy_size: .word _edata-_C_LABEL(mpcsa_start) 103c62a0ac4SmattLstart_off: .word mpcsa_start_ram-_C_LABEL(mpcsa_start) 104c62a0ac4Smatt 105c62a0ac4Smattmpcsa_start_ram: 106c62a0ac4Smatt /* 107c62a0ac4Smatt * Kernel is loaded in SDRAM (0x20200000), and is expected to run 108c62a0ac4Smatt * in VA 0xc0200000. 109c62a0ac4Smatt */ 110c62a0ac4Smatt 111c62a0ac4Smatt /* build page table from scratch */ 112c62a0ac4Smatt ldr r0, Lstartup_pagetable 113c62a0ac4Smatt adr r4, mmu_init_table 114c62a0ac4Smatt b 3f 115c62a0ac4Smatt 116c62a0ac4Smatt2: 117c62a0ac4Smatt str r3, [r0, r2] 118c62a0ac4Smatt add r2, r2, #4 119c62a0ac4Smatt add r3, r3, #(L1_S_SIZE) 120c62a0ac4Smatt adds r1, r1, #-1 121c62a0ac4Smatt bhi 2b 122c62a0ac4Smatt3: 123c62a0ac4Smatt ldmia r4!, {r1,r2,r3} /* # of sections, PA|attr, VA */ 124c62a0ac4Smatt cmp r1, #0 125c62a0ac4Smatt bne 2b 126c62a0ac4Smatt 127c62a0ac4Smatt 128c62a0ac4Smatt mcr p15, 0, r0, c2, c0, 0 /* Set TTB */ 129c62a0ac4Smatt mcr p15, 0, r0, c8, c7, 0 /* Flush TLB */ 130c62a0ac4Smatt 131c62a0ac4Smatt /* Set the Domain Access register. Very important! */ 132c62a0ac4Smatt mov r0, #((DOMAIN_CLIENT << (PMAP_DOMAIN_KERNEL*2)) | DOMAIN_CLIENT) 133c62a0ac4Smatt mcr p15, 0, r0, c3, c0, 0 134c62a0ac4Smatt 135c62a0ac4Smatt /* Enable MMU */ 136c62a0ac4Smatt mrc p15, 0, r0, c1, c0, 0 137c62a0ac4Smatt orr r0, r0, #CPU_CONTROL_MMU_ENABLE 138c62a0ac4Smatt mcr p15, 0, r0, c1, c0, 0 139c62a0ac4Smatt CPWAIT(r0) 140c62a0ac4Smatt 141c62a0ac4Smatt /* Jump to kernel code in TRUE VA */ 142c62a0ac4Smatt adr r0, Lstart 143c62a0ac4Smatt ldr pc, [r0] 144c62a0ac4Smatt 145c62a0ac4SmattLstart: 146c62a0ac4Smatt .word start 147c62a0ac4Smatt 148c62a0ac4Smatt 149c62a0ac4Smatt#define MMU_INIT(va,pa,n_sec,attr) \ 150c62a0ac4Smatt .word n_sec ;\ 151c62a0ac4Smatt .word 4*((va)>>L1_S_SHIFT) ;\ 152c62a0ac4Smatt .word (pa) | (attr) 153c62a0ac4Smatt 154c62a0ac4Smatt#define STARTUP_PAGETABLE_ADDR 0x20100000 + 0x4000 155c62a0ac4Smatt 156c62a0ac4SmattLstartup_pagetable: 157c62a0ac4Smatt .word STARTUP_PAGETABLE_ADDR 158c62a0ac4Smatt 159c62a0ac4Smattmmu_init_table: 160c62a0ac4Smatt /* fill all table VA==PA */ 161*497ddd31Smatt MMU_INIT(0x00000000, 0x00000000, 1<<(32-L1_S_SHIFT), L1_TYPE_S|L1_S_AP_KRW) 162c62a0ac4Smatt /* map in peripheral space */ 163*497ddd31Smatt MMU_INIT(0xfff00000, 0xfff00000, 1, L1_TYPE_S|L1_S_AP_KRW) 164c62a0ac4Smatt /* map SDRAM VA==PA, WT cacheable */ 165*497ddd31Smatt MMU_INIT(0x20100000, 0x20100000, 63, L1_TYPE_S|L1_S_C|L1_S_AP_KRW) 166c62a0ac4Smatt /* map VA 0xc0000000..0xc0efffff to PA 0x20100000..0x23ffffff */ 167*497ddd31Smatt MMU_INIT(0xc0000000, 0x20000000, 63, L1_TYPE_S|L1_S_C|L1_S_AP_KRW) 168c62a0ac4Smatt .word 0 /* end of table */ 169c62a0ac4Smatt 170c62a0ac4Smatt .align 7 171c62a0ac4Smattjme_module_header: 172c62a0ac4Smatt .word 0xe990510e /* magic number */ 173c62a0ac4Smatt .string "NetBSD/mpcsa\0\0\0" /* module name */ 174c62a0ac4Smatt .short 0 /* build flags */ 175c62a0ac4Smatt .short 0 /* flags */ 176c62a0ac4Smatt .word 0 /* version */ 177c62a0ac4Smatt .word 0 /* compile / link timestamp */ 178c62a0ac4Smatt .word MODBASE /* pointer to init routine */ 179c62a0ac4Smatt .word MODBASE /* start address */ 180c62a0ac4Smatt .word (_edata-(_C_LABEL(mpcsa_start))) /* length of module */ 181c62a0ac4Smatt .word (jme_module_header-_C_LABEL(mpcsa_start)+MODBASE) /* back pointer to module struct*/ 182c62a0ac4Smatt .word 0 /* data pointer (ignored but SBZ)*/ 183c62a0ac4Smatt .word 0 /* data length (ignored but SBZ)*/ 184c62a0ac4Smatt .word 0x20200000 /* alternate address */ 185c62a0ac4Smatt .word 0 /* reserved, SBZ */ 186c62a0ac4Smatt 187c62a0ac4Smattjme_kmodule_header: 188c62a0ac4Smatt .word 0xe000301e /* magic number */ 189c62a0ac4Smatt .string "JME kernel\0\0\0\0\0" /* module name */ 190c62a0ac4Smatt .short 0 /* build flags */ 191c62a0ac4Smatt .short 0 /* flags */ 192c62a0ac4Smatt .word 0 /* version */ 193c62a0ac4Smatt .word 0 /* compile / link timestamp */ 194c62a0ac4Smatt .word MODBASE /* pointer to init routine */ 195c62a0ac4Smatt .word MODBASE /* start address */ 196c62a0ac4Smatt .word (_edata-(_C_LABEL(mpcsa_start))) /* length of module */ 197c62a0ac4Smatt .word (jme_kmodule_header-_C_LABEL(mpcsa_start)+MODBASE) /* back pointer to module struct*/ 198c62a0ac4Smatt .word 0 /* data pointer (ignored but SBZ)*/ 199c62a0ac4Smatt .word 0 /* data length (ignored but SBZ)*/ 200c62a0ac4Smatt .word 0x20200000 /* alternate address */ 201c62a0ac4Smatt .word 0 /* reserved, SBZ */ 202