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