|
1 | 1 | /*
|
2 |
| -Copyright (c) 2016 Raspberry Pi (Trading) Ltd. |
| 2 | +Copyright (c) 2016-2020 Raspberry Pi (Trading) Ltd. |
3 | 3 | All rights reserved.
|
4 | 4 |
|
5 | 5 | Redistribution and use in source and binary forms, with or without
|
@@ -27,146 +27,167 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
27 | 27 |
|
28 | 28 | .arch_extension sec
|
29 | 29 | .arch_extension virt
|
| 30 | +.syntax unified |
30 | 31 |
|
31 |
| -.section .init |
32 |
| -.globl _start |
33 |
| -/* the vector table for secure state and HYP mode */ |
34 |
| -_start: |
35 |
| - b jmp_loader /* reset */ |
36 |
| -#if defined(BCM2711) && (BCM2711 == 1) |
37 |
| -osc: .word 54000000 |
| 32 | +#define MACHINE_ID 3138 |
| 33 | + |
| 34 | +#if BCM2711 |
| 35 | +#define OSC_FREQ 54000000 |
| 36 | +#define LOCAL_BASE 0xff800000 |
38 | 37 | #else
|
39 |
| -osc: .word 19200000 |
| 38 | +#define OSC_FREQ 19200000 |
| 39 | +#define LOCAL_BASE 0x40000000 |
40 | 40 | #endif
|
41 | 41 |
|
42 |
| -/* |
43 |
| - * secure monitor handler |
44 |
| - * U-boot calls this "software interrupt" in start.S |
45 |
| - * This is executed on a "smc" instruction, we use a "smc #0" to switch |
46 |
| - * to non-secure state. |
47 |
| - * We use only r0 and r1 here, due to constraints in the caller. |
48 |
| - */ |
49 |
| -_secure_monitor: |
50 |
| - movw r1, #0x131 @ set NS, AW, FW, HVC |
51 |
| - mcr p15, 0, r1, c1, c1, 0 @ write SCR (with NS bit set) |
| 42 | +#define ARML_PRESCALER 0x08 |
| 43 | +#define ARML_MBOX_CLR03 0xcc |
52 | 44 |
|
53 |
| - movw r0, #0x1da @ Set HYP_MODE | F_BIT | I_BIT | A_BIT |
54 |
| - msr spsr_cxfs, r0 @ Set full SPSR |
| 45 | +#ifdef GIC |
| 46 | +/* Distributor */ |
| 47 | +#define GIC_DISTB 0x41000 |
| 48 | +#define GICD_CTLR 0x0 |
| 49 | +#define GICD_IGROUPR 0x80 |
| 50 | +#define IT_NR 0x8 /* Number of interrupt enable registers (256 total irqs) */ |
55 | 51 |
|
56 |
| -#if defined(BCM2711) && (BCM2711 == 1) |
57 |
| - mov r1, #0x22 @ Set L2 read/write latency to 3 |
58 |
| - mcr p15, 1, r1, c9, c0, 2 @ Write L2CTLR |
| 52 | +/* CPU interface */ |
| 53 | +#define GIC_CPUB 0x42000 |
| 54 | +#define GICC_CTRLR 0x0 |
| 55 | +#define GICC_PMR 0x4 |
59 | 56 | #endif
|
60 | 57 |
|
61 |
| - movs pc, lr @ return to non-secure SVC |
62 |
| - |
63 |
| -value: .word 0x63fff |
64 |
| -#define machid 3138 |
65 |
| -#if defined(BCM2711) && (BCM2711 == 1) |
66 |
| - |
67 |
| -#define PRESCALER_2711 0xff800008 |
68 |
| -#define MBOX_2711 0xff8000cc |
69 |
| - |
70 |
| -mbox: .word MBOX_2711 |
71 |
| -GIC_DISTB: .word 0xff841000 |
| 58 | +#if BCM2710 |
| 59 | +#define NSACR_VAL 0xc00 |
72 | 60 | #else
|
73 |
| -mbox: .word 0x400000cc |
| 61 | +#define NSACR_VAL 0x60c00 |
74 | 62 | #endif
|
75 |
| -jmp_loader: |
76 |
| -@ Check which proc we are and run proc 0 only |
77 |
| - |
78 |
| -.if !BCM2710 |
79 |
| - mrc p15, 0, r0, c1, c0, 1 @ Read Auxiliary Control Register |
80 |
| - orr r0, r0, #(1<<6) @ SMP |
81 |
| - mcr p15, 0, r0, c1, c0, 1 @ Write Auxiliary Control Register |
82 |
| -.else |
83 |
| - mrrc p15, 1, r0, r1, c15 @ CPU Extended Control Register |
84 |
| - orr r0, r0, #(1<<6) @ SMP |
85 |
| - and r1, r1, #(~3) @ Set L2 load data prefetch to 0b00 = 16 |
86 |
| - mcrr p15, 1, r0, r1, c15 @ CPU Extended Control Register |
87 |
| -.endif |
88 |
| - mrc p15, 0, r0, c1, c0, 0 @ Read System Control Register |
89 |
| - /* Cortex A72 manual 4.3.67 says SMP must be set before enabling the cache. */ |
90 |
| - orr r0, r0, #(1<<12) @ icache enable |
91 |
| - mcr p15, 0, r0, c1, c0, 0 @ Write System Control Register |
92 |
| - |
93 |
| - mrc p15, 0, r7, c0, c0, 5 @ Put core number into R7 |
94 | 63 |
|
95 |
| -#ifdef GIC |
| 64 | +.section .init |
| 65 | +.global _start |
96 | 66 |
|
97 |
| -#define GIC_CPUB_offset 0x1000 |
| 67 | +/* Vector table for secure state and HYP mode */ |
| 68 | +_start: |
| 69 | + mrc p15, 0, r6, c0, c0, 5 @ Read MPIDR into r6 |
| 70 | + blx _main @ Jump to bootstub entrypoint (Thumb-2) |
98 | 71 |
|
99 |
| -#define GICC_CTRLR 0x0 |
100 |
| -#define GICC_PMR 0x4 |
101 |
| -#define IT_NR 0x8 @ Number of interrupt enable registers (256 total irqs) |
102 |
| -#define GICD_CTRLR 0x0 |
103 |
| -#define GICD_IGROUPR 0x80 |
| 72 | +/* |
| 73 | + * Secure monitor handler |
| 74 | + * This is executed on a "smc" instruction, we use a "smc #0" to switch |
| 75 | + * to non-secure state. |
| 76 | + * We only clobber ip (r12) here, so that the caller's r0-r7 remain valid. |
| 77 | + */ |
| 78 | +_secure_monitor: |
| 79 | +#if BCM2710 |
| 80 | + mcr p15, 0, r1, c1, c0, 1 @ Write ACTLR (Secure) |
| 81 | +#endif |
| 82 | + mov ip, #0x1b1 @ Set NS, AW, FW, SCD, HVC |
| 83 | + mcr p15, 0, ip, c1, c1, 0 @ Write SCR (which sets the NS bit) |
| 84 | + mov ip, #0x1fa @ Set HYP_MODE | T_BIT | F_BIT | I_BIT | A_BIT |
| 85 | + msr spsr_cxfs, ip @ Set full SPSR |
| 86 | + movs pc, lr @ Return to non-secure HYP |
104 | 87 |
|
105 |
| -setup_gic: @ Called from secure mode - set all interrupts to group 1 and enable. |
106 |
| - ldr r2, GIC_DISTB |
| 88 | +/* |
| 89 | + * Main bootstub entrypoint (entered in secure SVC mode) |
| 90 | + * This code is Thumb-2 in order to save space. |
| 91 | + */ |
| 92 | +.thumb_func |
| 93 | +_main: |
| 94 | + movs r0, #0 @ Set r0 to zero (used by code below and also as a kernel argument) |
| 95 | + lsls r6, r6, #30 @ Extract processor number field from MPIDR (shifted left by 30) |
| 96 | + ldr r7, =LOCAL_BASE @ Load ARM local peripherals base address for later use |
| 97 | + |
| 98 | +#if !BCM2710 |
| 99 | + mrc p15, 0, r1, c1, c0, 1 @ Read Auxiliary Control Register |
| 100 | + orr r1, r1, #(1<<6) @ Enable SMP |
| 101 | + mcr p15, 0, r1, c1, c0, 1 @ Write Auxiliary Control Register |
| 102 | +#else |
| 103 | + mrrc p15, 1, r1, r2, c15 @ CPU Extended Control Register |
| 104 | + orr r1, r1, #(1<<6) @ Enable SMP |
| 105 | +#if BCM2711 |
| 106 | + bic r2, r2, #3 @ Set L2 load data prefetch to 0b00 = 16 requests (A72-specific) |
| 107 | +#endif |
| 108 | + mcrr p15, 1, r1, r2, c15 @ CPU Extended Control Register |
| 109 | +#endif |
107 | 110 |
|
108 |
| - ands r7,r7, #3 @ primary core |
| 111 | + mrc p15, 0, r1, c1, c0, 0 @ Read System Control Register |
| 112 | + /* Cortex A72 manual 4.3.67 says SMP must be set before enabling the cache. */ |
| 113 | + orr r1, r1, #(1<<12) @ Enable icache |
| 114 | + mcr p15, 0, r1, c1, c0, 0 @ Write System Control Register |
109 | 115 |
|
110 |
| - movne r0, #3 @ Enable group 0 and 1 IRQs from distributor |
111 |
| - strne r0, [r2, #GICD_CTRLR] |
| 116 | +#ifdef GIC |
112 | 117 |
|
113 |
| - mov r0, #~0 |
114 |
| - mov r1, #~0 @ group 1 all the things |
115 |
| - strd r0, r1, [r2,#(GICD_IGROUPR)]! @ update to bring the CPU registers within range |
116 |
| - strd r0, r1, [r2,#8] |
117 |
| - strd r0, r1, [r2,#16] |
118 |
| - strd r0, r1, [r2,#24] |
| 118 | +@ Configure the GIC Distributor |
| 119 | + add r5, r7, #GIC_DISTB @ Get base address of GIC_DISTB |
| 120 | + cbnz r6, 9f @ Skip setting GICD_CTLR if we are not core 0 |
| 121 | + movs r1, #3 |
| 122 | + str r1, [r5, #GICD_CTLR] @ Enable group 0 and 1 IRQs from distributor |
| 123 | +9: |
| 124 | + mov r1, #~0 @ Route all interrupts to group 1 |
| 125 | + movs r2, #IT_NR |
| 126 | + add r5, r5, #GICD_IGROUPR @ Note: GICD_IGROUPR0 is banked for each core so all cores must set it |
| 127 | +0: str r1, [r5], #4 |
| 128 | + subs r2, r2, #1 |
| 129 | + bne 0b |
119 | 130 |
|
120 |
| - movw r1, #0x1e7 |
121 |
| - str r1, [r2, #(GIC_CPUB_offset - GICD_IGROUPR) ]! @ Enable group 1 IRQs from CPU interface |
| 131 | +@ Enable all interrupts coming from group 1 on this core |
| 132 | + add r5, r7, #GIC_CPUB @ Get base address of GIC_CPUB |
| 133 | + mov r1, #0x1e7 |
| 134 | + str r1, [r5, #GICC_CTRLR] @ Enable group 1 IRQs from CPU interface |
122 | 135 |
|
123 |
| - movw r1, #0xff |
124 |
| - str r1, [r2, #GICC_PMR] @ priority mask |
| 136 | + movs r1, #0xff |
| 137 | + str r1, [r5, #GICC_PMR] @ Set priority mask |
125 | 138 |
|
126 | 139 | #endif
|
127 | 140 |
|
128 |
| - mov r0, #1 |
129 |
| - mcr p15, 0, r0, c14, c3, 1 @ CNTV_CTL (enable=1, imask=0) |
130 |
| - |
131 |
| -@ set to non-sec |
132 |
| - ldr r1, value @ value = 0x63fff |
| 141 | +@ Allow non-secure access to coprocessors |
| 142 | + ldr r1, =NSACR_VAL |
133 | 143 | mcr p15, 0, r1, c1, c1, 2 @ NSACR = all copros to non-sec
|
134 |
| -@ timer frequency |
135 |
| - ldr r1, osc @ osc = 19.2 / 54MHz |
136 |
| - mcr p15, 0, r1, c14, c0, 0 @ write CNTFRQ |
137 |
| -#if defined(BCM2711) && (BCM2711 == 1) |
| 144 | + |
| 145 | +@ Initialize the architectural timer |
| 146 | + ldr r1, =OSC_FREQ @ osc = 19.2 or 54MHz |
| 147 | + mcr p15, 0, r1, c14, c0, 0 @ Write CNTFRQ |
| 148 | +#if BCM2711 |
138 | 149 | mov r1, #0x80000000 @ Set ARM_LOCAL_TIMER_PRE_ADD to 1
|
139 |
| - ldr r2, mbox |
140 |
| - str r1, [r2, #(PRESCALER_2711 - MBOX_2711)] |
| 150 | + str r1, [r7, #ARML_PRESCALER] |
141 | 151 | #endif
|
| 152 | + movs r1, #1 |
| 153 | + mcr p15, 0, r1, c14, c3, 1 @ CNTV_CTL (enable=1, imask=0) |
142 | 154 |
|
143 |
| - adr ip, _start |
144 |
| - mcr p15, 0, ip, c12, c0, 1 @ set MVBAR to secure vectors |
145 |
| - |
| 155 | +@ Initialize exception vectors and switch to non-secure HYP mode |
| 156 | + mcr p15, 0, r0, c12, c0, 1 @ Set MVBAR to secure vectors (i.e. zero) |
146 | 157 | isb
|
147 |
| - smc #0 @ call into MONITOR mode |
148 |
| - |
149 |
| - mcr p15, 0, ip, c12, c0, 0 @ write non-secure copy of VBAR |
150 |
| - |
151 |
| - ldrd r2,r3, atags @ ATAGS and kernel |
152 |
| - |
153 |
| - ands r7,r7, #3 @ primary core |
154 |
| - beq 9f |
| 158 | +#if BCM2710 |
| 159 | + movs r1, #0x73 @ Value for ACTLR: enable non-secure access to CPUACTLR/CPUECTLR/L2CTLR/L2ECTLR/L2ACTLR |
| 160 | +#endif |
| 161 | + smc #0 @ Call into MONITOR mode |
| 162 | + mcr p15, 0, r0, c12, c0, 0 @ Write non-secure copy of VBAR |
| 163 | + mcrr p15, 4, r0, r0, c14 @ Reset CNTVOFF to zero (must be done now in non-secure HYP mode) |
155 | 164 |
|
156 |
| - ldr r5, mbox @ mbox |
| 165 | +#if BCM2711 |
| 166 | + movs r1, #0x22 @ Value for L2CTLR: set L2 read/write latency to 3 |
| 167 | + mcr p15, 1, r1, c9, c0, 2 @ Write L2CTLR |
| 168 | +#endif |
157 | 169 |
|
158 |
| -1: |
159 |
| - wfe |
160 |
| - ldr r3, [r5, r7, lsl #4] |
161 |
| - cmp r3, #0 @ magic |
162 |
| - beq 1b |
163 |
| -@ clear mailbox |
164 |
| - str r3, [r5, r7, lsl #4] |
| 170 | +@ Set kernel entrypoint arguments |
| 171 | + mov r1, #MACHINE_ID @ BCM2708 machine id |
| 172 | + ldrd r2, r3, atags @ ATAGS and kernel |
| 173 | + |
| 174 | +@ Secondary cores only: synchronize with core 0 using the mailbox |
| 175 | + cbz r6, 9f @ Skip this section if we are core 0 |
| 176 | + lsrs r6, r6, #(30-4) @ Calculate offset to mailbox register (i.e. ARML_MBOX_CLR03 + coreid*0x10) |
| 177 | + adds r6, r6, #ARML_MBOX_CLR03 |
| 178 | +0: wfe |
| 179 | + ldr r3, [r7, r6] @ Read message (secondary kernel entrypoint) |
| 180 | + cmp r3, #0 @ If zero, there is no message |
| 181 | + beq 0b |
| 182 | + str r3, [r7, r6] @ Clear mailbox |
165 | 183 | 9:
|
166 |
| - mov r0, #0 |
167 |
| - movw r1, #machid @ BCM2708 machine id |
| 184 | + |
| 185 | +@ Jump to kernel |
168 | 186 | bx r3
|
169 | 187 |
|
| 188 | +@ Assembler generated constant pool goes here |
| 189 | +.pool |
| 190 | + |
170 | 191 | .org 0xf0
|
171 | 192 | .word 0x5afe570b @ magic value to indicate firmware should overwrite atags and kernel
|
172 | 193 | .word 0 @ version
|
|
0 commit comments