1/* 2 * code for switching cores into non-secure state 3 * 4 * Copyright (c) 2013 Andre Przywara <andre.przywara@linaro.org> 5 * 6 * See file CREDITS for list of people who contributed to this 7 * project. 8 * 9 * This program is free software; you can redistribute it and/or 10 * modify it under the terms of the GNU General Public License as 11 * published by the Free Software Foundation; either version 2 of 12 * the License, or (at your option) any later version. 13 * 14 * This program is distributed in the hope that it will be useful, 15 * but WITHOUT ANY WARRANTY; without even the implied warranty of 16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 17 * GNU General Public License for more details. 18 * 19 * You should have received a copy of the GNU General Public License 20 * along with this program; if not, write to the Free Software 21 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, 22 * MA 02111-1307 USA 23 */ 24 25#include <config.h> 26#include <linux/linkage.h> 27#include <asm/gic.h> 28#include <asm/armv7.h> 29 30.arch_extension sec 31 32/* the vector table for secure state */ 33_monitor_vectors: 34 .word 0 /* reset */ 35 .word 0 /* undef */ 36 adr pc, _secure_monitor 37 .word 0 38 .word 0 39 .word 0 40 .word 0 41 .word 0 42 43/* 44 * secure monitor handler 45 * U-boot calls this "software interrupt" in start.S 46 * This is executed on a "smc" instruction, we use a "smc #0" to switch 47 * to non-secure state. 48 * We use only r0 and r1 here, due to constraints in the caller. 49 */ 50 .align 5 51_secure_monitor: 52 mrc p15, 0, r1, c1, c1, 0 @ read SCR 53 bic r1, r1, #0x4e @ clear IRQ, FIQ, EA, nET bits 54 orr r1, r1, #0x31 @ enable NS, AW, FW bits 55 56 mcr p15, 0, r1, c1, c1, 0 @ write SCR (with NS bit set) 57 58 movs pc, lr @ return to non-secure SVC 59 60/* 61 * Switch a core to non-secure state. 62 * 63 * 1. initialize the GIC per-core interface 64 * 2. allow coprocessor access in non-secure modes 65 * 3. switch the cpu mode (by calling "smc #0") 66 * 67 * Called from smp_pen by secondary cores and directly by the BSP. 68 * Do not assume that the stack is available and only use registers 69 * r0-r3 and r12. 70 * 71 * PERIPHBASE is used to get the GIC address. This could be 40 bits long, 72 * though, but we check this in C before calling this function. 73 */ 74ENTRY(_nonsec_init) 75#ifdef CONFIG_ARM_GIC_BASE_ADDRESS 76 ldr r2, =CONFIG_ARM_GIC_BASE_ADDRESS 77#else 78 mrc p15, 4, r2, c15, c0, 0 @ read CBAR 79 bfc r2, #0, #15 @ clear reserved bits 80#endif 81 add r3, r2, #GIC_DIST_OFFSET @ GIC dist i/f offset 82 mvn r1, #0 @ all bits to 1 83 str r1, [r3, #GICD_IGROUPRn] @ allow private interrupts 84 85 mrc p15, 0, r0, c0, c0, 0 @ read MIDR 86 ldr r1, =MIDR_PRIMARY_PART_MASK 87 and r0, r0, r1 @ mask out variant and revision 88 89 ldr r1, =MIDR_CORTEX_A7_R0P0 & MIDR_PRIMARY_PART_MASK 90 cmp r0, r1 @ check for Cortex-A7 91 92 ldr r1, =MIDR_CORTEX_A15_R0P0 & MIDR_PRIMARY_PART_MASK 93 cmpne r0, r1 @ check for Cortex-A15 94 95 movne r1, #GIC_CPU_OFFSET_A9 @ GIC CPU offset for A9 96 moveq r1, #GIC_CPU_OFFSET_A15 @ GIC CPU offset for A15/A7 97 add r3, r2, r1 @ r3 = GIC CPU i/f addr 98 99 mov r1, #1 @ set GICC_CTLR[enable] 100 str r1, [r3, #GICC_CTLR] @ and clear all other bits 101 mov r1, #0xff 102 str r1, [r3, #GICC_PMR] @ set priority mask register 103 104 movw r1, #0x3fff 105 movt r1, #0x0006 106 mcr p15, 0, r1, c1, c1, 2 @ NSACR = all copros to non-sec 107 108/* The CNTFRQ register of the generic timer needs to be 109 * programmed in secure state. Some primary bootloaders / firmware 110 * omit this, so if the frequency is provided in the configuration, 111 * we do this here instead. 112 * But first check if we have the generic timer. 113 */ 114#ifdef CONFIG_SYS_CLK_FREQ 115 mrc p15, 0, r0, c0, c1, 1 @ read ID_PFR1 116 and r0, r0, #CPUID_ARM_GENTIMER_MASK @ mask arch timer bits 117 cmp r0, #(1 << CPUID_ARM_GENTIMER_SHIFT) 118 ldreq r1, =CONFIG_SYS_CLK_FREQ 119 mcreq p15, 0, r1, c14, c0, 0 @ write CNTFRQ 120#endif 121 122 adr r1, _monitor_vectors 123 mcr p15, 0, r1, c12, c0, 1 @ set MVBAR to secure vectors 124 125 mrc p15, 0, ip, c12, c0, 0 @ save secure copy of VBAR 126 127 isb 128 smc #0 @ call into MONITOR mode 129 130 mcr p15, 0, ip, c12, c0, 0 @ write non-secure copy of VBAR 131 132 mov r1, #1 133 str r1, [r3, #GICC_CTLR] @ enable non-secure CPU i/f 134 add r2, r2, #GIC_DIST_OFFSET 135 str r1, [r2, #GICD_CTLR] @ allow private interrupts 136 137 mov r0, r3 @ return GICC address 138 139 bx lr 140ENDPROC(_nonsec_init) 141