boot.S revision 11258
1955SN/A/* 2955SN/A * boot.S - simple register setup code for stand-alone Linux booting 31762SN/A * 4955SN/A * Copyright (C) 2012 ARM Limited. All rights reserved. 5955SN/A * 6955SN/A * Use of this source code is governed by a BSD-style license that can be 7955SN/A * found in the LICENSE.txt file. 8955SN/A */ 9955SN/A 10955SN/A .text 11955SN/A 12955SN/A .globl _start 13955SN/A_start: 14955SN/A /* 15955SN/A * EL3 initialisation 16955SN/A */ 17955SN/A mrs x0, CurrentEL 18955SN/A cmp x0, #0xc // EL3? 19955SN/A b.ne start_ns // skip EL3 initialisation 20955SN/A 21955SN/A mov x0, #0x30 // RES1 22955SN/A orr x0, x0, #(1 << 0) // Non-secure EL1 23955SN/A orr x0, x0, #(1 << 8) // HVC enable 24955SN/A orr x0, x0, #(1 << 10) // 64-bit EL2 25955SN/A msr scr_el3, x0 26955SN/A 27955SN/A msr cptr_el3, xzr // Disable copro. traps to EL3 28955SN/A 29955SN/A ldr x0, =CNTFRQ 30955SN/A msr cntfrq_el0, x0 31955SN/A 32955SN/A /* 332632Sstever@eecs.umich.edu * Check for the primary CPU to avoid a race on the distributor 342632Sstever@eecs.umich.edu * registers. 352632Sstever@eecs.umich.edu */ 362632Sstever@eecs.umich.edu mrs x0, mpidr_el1 37955SN/A // ARM MPIDR_EL1 bytes: Aff3 (AArch64), Stuff, Aff2, Aff1, Aff0 382632Sstever@eecs.umich.edu // Test the the MPIDR_EL1 register against 0xff00ffffff to 392632Sstever@eecs.umich.edu // extract the primary CPU. 402632Sstever@eecs.umich.edu ldr x1, =0xff00ffffff 412632Sstever@eecs.umich.edu tst x0, x1 // check for cpuid==zero 422632Sstever@eecs.umich.edu b.ne 1f // secondary CPU 432632Sstever@eecs.umich.edu 442632Sstever@eecs.umich.edu ldr x1, =GIC_DIST_BASE // GICD_CTLR 452632Sstever@eecs.umich.edu mov w0, #3 // EnableGrp0 | EnableGrp1 462632Sstever@eecs.umich.edu str w0, [x1] 472632Sstever@eecs.umich.edu 482632Sstever@eecs.umich.edu1: ldr x1, =GIC_DIST_BASE + 0x80 // GICD_IGROUPR 492632Sstever@eecs.umich.edu mov w0, #~0 // Grp1 interrupts 502632Sstever@eecs.umich.edu str w0, [x1], #4 512632Sstever@eecs.umich.edu b.ne 2f // Only local interrupts for secondary CPUs 522632Sstever@eecs.umich.edu str w0, [x1], #4 532632Sstever@eecs.umich.edu str w0, [x1], #4 542632Sstever@eecs.umich.edu 552632Sstever@eecs.umich.edu2: ldr x1, =GIC_CPU_BASE // GICC_CTLR 562632Sstever@eecs.umich.edu ldr w0, [x1] 572632Sstever@eecs.umich.edu mov w0, #3 // EnableGrp0 | EnableGrp1 58955SN/A str w0, [x1] 59955SN/A 60955SN/A mov w0, #1 << 7 // allow NS access to GICC_PMR 61955SN/A str w0, [x1, #4] // GICC_PMR 62955SN/A 63955SN/A msr sctlr_el2, xzr 64955SN/A 651858SN/A /* 661858SN/A * Prepare the switch to the EL2_SP1 mode from EL3 672653Sstever@eecs.umich.edu */ 682653Sstever@eecs.umich.edu ldr x0, =start_ns // Return after mode switch 692653Sstever@eecs.umich.edu mov x1, #0x3c9 // EL2_SP1 | D | A | I | F 702653Sstever@eecs.umich.edu msr elr_el3, x0 712653Sstever@eecs.umich.edu msr spsr_el3, x1 722653Sstever@eecs.umich.edu eret 732653Sstever@eecs.umich.edu 742653Sstever@eecs.umich.edustart_ns: 752653Sstever@eecs.umich.edu /* 762653Sstever@eecs.umich.edu * Kernel parameters 772653Sstever@eecs.umich.edu */ 781852SN/A mov x0, xzr 79955SN/A mov x1, xzr 80955SN/A mov x2, xzr 81955SN/A mov x3, xzr 822632Sstever@eecs.umich.edu 832632Sstever@eecs.umich.edu mrs x4, mpidr_el1 84955SN/A // ARM MPIDR_EL1 bytes: Aff3 (AArch64), Stuff, Aff2, Aff1, Aff0 851533SN/A // Test the the MPIDR_EL1 register against 0xff00ffffff to 862632Sstever@eecs.umich.edu // extract the primary CPU. 871533SN/A ldr x1, =0xff00ffffff 88955SN/A tst x4, x1 // check for cpuid==zero 89955SN/A mov x1, xzr // load previous 'xzr' value back to x1 902632Sstever@eecs.umich.edu b.eq 2f // secondary CPU 912632Sstever@eecs.umich.edu 92955SN/A /* 93955SN/A * Secondary CPUs 94955SN/A */ 95955SN/A1: wfe 962632Sstever@eecs.umich.edu ldr x4, =PHYS_OFFSET + 0xfff8 97955SN/A ldr x4, [x4] 982632Sstever@eecs.umich.edu cbz x4, 1b 99955SN/A br x4 // branch to the given address 100955SN/A 1012632Sstever@eecs.umich.edu2: 1022632Sstever@eecs.umich.edu /* 1032632Sstever@eecs.umich.edu * UART initialisation (38400 8N1) 1042632Sstever@eecs.umich.edu */ 1052632Sstever@eecs.umich.edu ldr x4, =UART_BASE // UART base 1062632Sstever@eecs.umich.edu mov w5, #0x10 // ibrd 1072632Sstever@eecs.umich.edu str w5, [x4, #0x24] 1082632Sstever@eecs.umich.edu mov w5, #0xc300 1092632Sstever@eecs.umich.edu orr w5, w5, #0x0001 // cr 1102632Sstever@eecs.umich.edu str w5, [x4, #0x30] 1112632Sstever@eecs.umich.edu 1122632Sstever@eecs.umich.edu /* 1132632Sstever@eecs.umich.edu * CLCD output site MB 1142632Sstever@eecs.umich.edu */ 1152632Sstever@eecs.umich.edu ldr x4, =SYSREGS_BASE 1162632Sstever@eecs.umich.edu ldr w5, =(1 << 31) | (1 << 30) | (7 << 20) | (0 << 16) // START|WRITE|MUXFPGA|SITE_MB 1172632Sstever@eecs.umich.edu str wzr, [x4, #0xa0] // V2M_SYS_CFGDATA 1182634Sstever@eecs.umich.edu str w5, [x4, #0xa4] // V2M_SYS_CFGCTRL 1192634Sstever@eecs.umich.edu 1202632Sstever@eecs.umich.edu // set up the arch timer frequency 1212638Sstever@eecs.umich.edu //ldr x0, =CNTFRQ 1222632Sstever@eecs.umich.edu //msr cntfrq_el0, x0 1232632Sstever@eecs.umich.edu 1242632Sstever@eecs.umich.edu /* 1252632Sstever@eecs.umich.edu * Primary CPU 1262632Sstever@eecs.umich.edu */ 1272632Sstever@eecs.umich.edu ldr x0, =PHYS_OFFSET + 0x8000000 // device tree blob 1281858SN/A ldr x6, =PHYS_OFFSET + 0x80000 // kernel start address 1292638Sstever@eecs.umich.edu br x6 1302638Sstever@eecs.umich.edu 1312638Sstever@eecs.umich.edu .ltorg 1322638Sstever@eecs.umich.edu 1332638Sstever@eecs.umich.edu .org 0x200 1342638Sstever@eecs.umich.edu