boot.S revision 11258
1/* 2 * boot.S - simple register setup code for stand-alone Linux booting 3 * 4 * Copyright (C) 2012 ARM Limited. All rights reserved. 5 * 6 * Use of this source code is governed by a BSD-style license that can be 7 * found in the LICENSE.txt file. 8 */ 9 10 .text 11 12 .globl _start 13_start: 14 /* 15 * EL3 initialisation 16 */ 17 mrs x0, CurrentEL 18 cmp x0, #0xc // EL3? 19 b.ne start_ns // skip EL3 initialisation 20 21 mov x0, #0x30 // RES1 22 orr x0, x0, #(1 << 0) // Non-secure EL1 23 orr x0, x0, #(1 << 8) // HVC enable 24 orr x0, x0, #(1 << 10) // 64-bit EL2 25 msr scr_el3, x0 26 27 msr cptr_el3, xzr // Disable copro. traps to EL3 28 29 ldr x0, =CNTFRQ 30 msr cntfrq_el0, x0 31 32 /* 33 * Check for the primary CPU to avoid a race on the distributor 34 * registers. 35 */ 36 mrs x0, mpidr_el1 37 // ARM MPIDR_EL1 bytes: Aff3 (AArch64), Stuff, Aff2, Aff1, Aff0 38 // Test the the MPIDR_EL1 register against 0xff00ffffff to 39 // extract the primary CPU. 40 ldr x1, =0xff00ffffff 41 tst x0, x1 // check for cpuid==zero 42 b.ne 1f // secondary CPU 43 44 ldr x1, =GIC_DIST_BASE // GICD_CTLR 45 mov w0, #3 // EnableGrp0 | EnableGrp1 46 str w0, [x1] 47 481: ldr x1, =GIC_DIST_BASE + 0x80 // GICD_IGROUPR 49 mov w0, #~0 // Grp1 interrupts 50 str w0, [x1], #4 51 b.ne 2f // Only local interrupts for secondary CPUs 52 str w0, [x1], #4 53 str w0, [x1], #4 54 552: ldr x1, =GIC_CPU_BASE // GICC_CTLR 56 ldr w0, [x1] 57 mov w0, #3 // EnableGrp0 | EnableGrp1 58 str w0, [x1] 59 60 mov w0, #1 << 7 // allow NS access to GICC_PMR 61 str w0, [x1, #4] // GICC_PMR 62 63 msr sctlr_el2, xzr 64 65 /* 66 * Prepare the switch to the EL2_SP1 mode from EL3 67 */ 68 ldr x0, =start_ns // Return after mode switch 69 mov x1, #0x3c9 // EL2_SP1 | D | A | I | F 70 msr elr_el3, x0 71 msr spsr_el3, x1 72 eret 73 74start_ns: 75 /* 76 * Kernel parameters 77 */ 78 mov x0, xzr 79 mov x1, xzr 80 mov x2, xzr 81 mov x3, xzr 82 83 mrs x4, mpidr_el1 84 // ARM MPIDR_EL1 bytes: Aff3 (AArch64), Stuff, Aff2, Aff1, Aff0 85 // Test the the MPIDR_EL1 register against 0xff00ffffff to 86 // extract the primary CPU. 87 ldr x1, =0xff00ffffff 88 tst x4, x1 // check for cpuid==zero 89 mov x1, xzr // load previous 'xzr' value back to x1 90 b.eq 2f // secondary CPU 91 92 /* 93 * Secondary CPUs 94 */ 951: wfe 96 ldr x4, =PHYS_OFFSET + 0xfff8 97 ldr x4, [x4] 98 cbz x4, 1b 99 br x4 // branch to the given address 100 1012: 102 /* 103 * UART initialisation (38400 8N1) 104 */ 105 ldr x4, =UART_BASE // UART base 106 mov w5, #0x10 // ibrd 107 str w5, [x4, #0x24] 108 mov w5, #0xc300 109 orr w5, w5, #0x0001 // cr 110 str w5, [x4, #0x30] 111 112 /* 113 * CLCD output site MB 114 */ 115 ldr x4, =SYSREGS_BASE 116 ldr w5, =(1 << 31) | (1 << 30) | (7 << 20) | (0 << 16) // START|WRITE|MUXFPGA|SITE_MB 117 str wzr, [x4, #0xa0] // V2M_SYS_CFGDATA 118 str w5, [x4, #0xa4] // V2M_SYS_CFGCTRL 119 120 // set up the arch timer frequency 121 //ldr x0, =CNTFRQ 122 //msr cntfrq_el0, x0 123 124 /* 125 * Primary CPU 126 */ 127 ldr x0, =PHYS_OFFSET + 0x8000000 // device tree blob 128 ldr x6, =PHYS_OFFSET + 0x80000 // kernel start address 129 br x6 130 131 .ltorg 132 133 .org 0x200 134