1*4882a593Smuzhiyun/* 2*4882a593Smuzhiyun * GIC Initialization Routines. 3*4882a593Smuzhiyun * 4*4882a593Smuzhiyun * (C) Copyright 2013 5*4882a593Smuzhiyun * David Feng <fenghua@phytium.com.cn> 6*4882a593Smuzhiyun * 7*4882a593Smuzhiyun * SPDX-License-Identifier: GPL-2.0+ 8*4882a593Smuzhiyun */ 9*4882a593Smuzhiyun 10*4882a593Smuzhiyun#include <asm-offsets.h> 11*4882a593Smuzhiyun#include <config.h> 12*4882a593Smuzhiyun#include <linux/linkage.h> 13*4882a593Smuzhiyun#include <asm/gic.h> 14*4882a593Smuzhiyun#include <asm/macro.h> 15*4882a593Smuzhiyun 16*4882a593Smuzhiyun 17*4882a593Smuzhiyun/************************************************************************* 18*4882a593Smuzhiyun * 19*4882a593Smuzhiyun * void gic_init_secure(DistributorBase); 20*4882a593Smuzhiyun * 21*4882a593Smuzhiyun * Initialize secure copy of GIC at EL3. 22*4882a593Smuzhiyun * 23*4882a593Smuzhiyun *************************************************************************/ 24*4882a593SmuzhiyunENTRY(gic_init_secure) 25*4882a593Smuzhiyun /* 26*4882a593Smuzhiyun * Initialize Distributor 27*4882a593Smuzhiyun * x0: Distributor Base 28*4882a593Smuzhiyun */ 29*4882a593Smuzhiyun#if defined(CONFIG_GICV3) 30*4882a593Smuzhiyun mov w9, #0x37 /* EnableGrp0 | EnableGrp1NS */ 31*4882a593Smuzhiyun /* EnableGrp1S | ARE_S | ARE_NS */ 32*4882a593Smuzhiyun str w9, [x0, GICD_CTLR] /* Secure GICD_CTLR */ 33*4882a593Smuzhiyun ldr w9, [x0, GICD_TYPER] 34*4882a593Smuzhiyun and w10, w9, #0x1f /* ITLinesNumber */ 35*4882a593Smuzhiyun cbz w10, 1f /* No SPIs */ 36*4882a593Smuzhiyun add x11, x0, (GICD_IGROUPRn + 4) 37*4882a593Smuzhiyun add x12, x0, (GICD_IGROUPMODRn + 4) 38*4882a593Smuzhiyun mov w9, #~0 39*4882a593Smuzhiyun0: str w9, [x11], #0x4 40*4882a593Smuzhiyun str wzr, [x12], #0x4 /* Config SPIs as Group1NS */ 41*4882a593Smuzhiyun sub w10, w10, #0x1 42*4882a593Smuzhiyun cbnz w10, 0b 43*4882a593Smuzhiyun#elif defined(CONFIG_GICV2) 44*4882a593Smuzhiyun mov w9, #0x3 /* EnableGrp0 | EnableGrp1 */ 45*4882a593Smuzhiyun str w9, [x0, GICD_CTLR] /* Secure GICD_CTLR */ 46*4882a593Smuzhiyun ldr w9, [x0, GICD_TYPER] 47*4882a593Smuzhiyun and w10, w9, #0x1f /* ITLinesNumber */ 48*4882a593Smuzhiyun cbz w10, 1f /* No SPIs */ 49*4882a593Smuzhiyun add x11, x0, GICD_IGROUPRn 50*4882a593Smuzhiyun mov w9, #~0 /* Config SPIs as Grp1 */ 51*4882a593Smuzhiyun str w9, [x11], #0x4 52*4882a593Smuzhiyun0: str w9, [x11], #0x4 53*4882a593Smuzhiyun sub w10, w10, #0x1 54*4882a593Smuzhiyun cbnz w10, 0b 55*4882a593Smuzhiyun 56*4882a593Smuzhiyun ldr x1, =GICC_BASE /* GICC_CTLR */ 57*4882a593Smuzhiyun mov w0, #3 /* EnableGrp0 | EnableGrp1 */ 58*4882a593Smuzhiyun str w0, [x1] 59*4882a593Smuzhiyun 60*4882a593Smuzhiyun mov w0, #1 << 7 /* allow NS access to GICC_PMR */ 61*4882a593Smuzhiyun str w0, [x1, #4] /* GICC_PMR */ 62*4882a593Smuzhiyun#endif 63*4882a593Smuzhiyun1: 64*4882a593Smuzhiyun ret 65*4882a593SmuzhiyunENDPROC(gic_init_secure) 66*4882a593Smuzhiyun 67*4882a593Smuzhiyun 68*4882a593Smuzhiyun/************************************************************************* 69*4882a593Smuzhiyun * For Gicv2: 70*4882a593Smuzhiyun * void gic_init_secure_percpu(DistributorBase, CpuInterfaceBase); 71*4882a593Smuzhiyun * For Gicv3: 72*4882a593Smuzhiyun * void gic_init_secure_percpu(ReDistributorBase); 73*4882a593Smuzhiyun * 74*4882a593Smuzhiyun * Initialize secure copy of GIC at EL3. 75*4882a593Smuzhiyun * 76*4882a593Smuzhiyun *************************************************************************/ 77*4882a593SmuzhiyunENTRY(gic_init_secure_percpu) 78*4882a593Smuzhiyun#if defined(CONFIG_GICV3) 79*4882a593Smuzhiyun /* 80*4882a593Smuzhiyun * Initialize ReDistributor 81*4882a593Smuzhiyun * x0: ReDistributor Base 82*4882a593Smuzhiyun */ 83*4882a593Smuzhiyun mrs x10, mpidr_el1 84*4882a593Smuzhiyun lsr x9, x10, #32 85*4882a593Smuzhiyun bfi x10, x9, #24, #8 /* w10 is aff3:aff2:aff1:aff0 */ 86*4882a593Smuzhiyun mov x9, x0 87*4882a593Smuzhiyun1: ldr x11, [x9, GICR_TYPER] 88*4882a593Smuzhiyun lsr x11, x11, #32 /* w11 is aff3:aff2:aff1:aff0 */ 89*4882a593Smuzhiyun cmp w10, w11 90*4882a593Smuzhiyun b.eq 2f 91*4882a593Smuzhiyun add x9, x9, #(2 << 16) 92*4882a593Smuzhiyun b 1b 93*4882a593Smuzhiyun 94*4882a593Smuzhiyun /* x9: ReDistributor Base Address of Current CPU */ 95*4882a593Smuzhiyun2: mov w10, #~0x2 96*4882a593Smuzhiyun ldr w11, [x9, GICR_WAKER] 97*4882a593Smuzhiyun and w11, w11, w10 /* Clear ProcessorSleep */ 98*4882a593Smuzhiyun str w11, [x9, GICR_WAKER] 99*4882a593Smuzhiyun dsb st 100*4882a593Smuzhiyun isb 101*4882a593Smuzhiyun3: ldr w10, [x9, GICR_WAKER] 102*4882a593Smuzhiyun tbnz w10, #2, 3b /* Wait Children be Alive */ 103*4882a593Smuzhiyun 104*4882a593Smuzhiyun add x10, x9, #(1 << 16) /* SGI_Base */ 105*4882a593Smuzhiyun mov w11, #~0 106*4882a593Smuzhiyun str w11, [x10, GICR_IGROUPRn] 107*4882a593Smuzhiyun str wzr, [x10, GICR_IGROUPMODRn] /* SGIs|PPIs Group1NS */ 108*4882a593Smuzhiyun mov w11, #0x1 /* Enable SGI 0 */ 109*4882a593Smuzhiyun str w11, [x10, GICR_ISENABLERn] 110*4882a593Smuzhiyun 111*4882a593Smuzhiyun#if CONFIG_IS_ENABLED(IRQ) 112*4882a593Smuzhiyun /* Rockchip: check elx */ 113*4882a593Smuzhiyun switch_el x0, el3_sre, el2_sre, el1_sre 114*4882a593Smuzhiyun 115*4882a593Smuzhiyun /* Initialize Cpu Interface */ 116*4882a593Smuzhiyunel3_sre: 117*4882a593Smuzhiyun mrs x10, ICC_SRE_EL3 118*4882a593Smuzhiyun orr x10, x10, #0xf /* SRE & Disable IRQ/FIQ Bypass & */ 119*4882a593Smuzhiyun /* Allow EL2 access to ICC_SRE_EL2 */ 120*4882a593Smuzhiyun msr ICC_SRE_EL3, x10 121*4882a593Smuzhiyun isb 122*4882a593Smuzhiyun 123*4882a593Smuzhiyunel2_sre: 124*4882a593Smuzhiyun mrs x10, ICC_SRE_EL2 125*4882a593Smuzhiyun orr x10, x10, #0xf /* SRE & Disable IRQ/FIQ Bypass & */ 126*4882a593Smuzhiyun /* Allow EL1 access to ICC_SRE_EL1 */ 127*4882a593Smuzhiyun msr ICC_SRE_EL2, x10 128*4882a593Smuzhiyun isb 129*4882a593Smuzhiyun 130*4882a593Smuzhiyunel1_sre: 131*4882a593Smuzhiyun mrs x0, CurrentEL /* check currentEL */ 132*4882a593Smuzhiyun cmp x0, 0xC 133*4882a593Smuzhiyun b.ne el1_ctlr /* currentEL != EL3 */ 134*4882a593Smuzhiyun 135*4882a593Smuzhiyunel3_ctlr: 136*4882a593Smuzhiyun mov x10, #0x3 /* EnableGrp1NS | EnableGrp1S */ 137*4882a593Smuzhiyun msr ICC_IGRPEN1_EL3, x10 138*4882a593Smuzhiyun isb 139*4882a593Smuzhiyun 140*4882a593Smuzhiyun msr ICC_CTLR_EL3, xzr 141*4882a593Smuzhiyun isb 142*4882a593Smuzhiyun 143*4882a593Smuzhiyunel1_ctlr: 144*4882a593Smuzhiyun mov x10, #0x3 /* EnableGrp1NS | EnableGrp1S */ 145*4882a593Smuzhiyun msr ICC_IGRPEN1_EL1, x10 146*4882a593Smuzhiyun isb 147*4882a593Smuzhiyun 148*4882a593Smuzhiyun msr ICC_CTLR_EL1, xzr /* NonSecure ICC_CTLR_EL1 */ 149*4882a593Smuzhiyun isb 150*4882a593Smuzhiyun 151*4882a593Smuzhiyun mov x10, #0xf0 /* Non-Secure access to ICC_PMR_EL1 */ 152*4882a593Smuzhiyun msr ICC_PMR_EL1, x10 153*4882a593Smuzhiyun isb 154*4882a593Smuzhiyun#else 155*4882a593Smuzhiyun /* Initialize Cpu Interface */ 156*4882a593Smuzhiyun mrs x10, ICC_SRE_EL3 157*4882a593Smuzhiyun orr x10, x10, #0xf /* SRE & Disable IRQ/FIQ Bypass & */ 158*4882a593Smuzhiyun /* Allow EL2 access to ICC_SRE_EL2 */ 159*4882a593Smuzhiyun msr ICC_SRE_EL3, x10 160*4882a593Smuzhiyun isb 161*4882a593Smuzhiyun 162*4882a593Smuzhiyun mrs x10, ICC_SRE_EL2 163*4882a593Smuzhiyun orr x10, x10, #0xf /* SRE & Disable IRQ/FIQ Bypass & */ 164*4882a593Smuzhiyun /* Allow EL1 access to ICC_SRE_EL1 */ 165*4882a593Smuzhiyun msr ICC_SRE_EL2, x10 166*4882a593Smuzhiyun isb 167*4882a593Smuzhiyun 168*4882a593Smuzhiyun mov x10, #0x3 /* EnableGrp1NS | EnableGrp1S */ 169*4882a593Smuzhiyun msr ICC_IGRPEN1_EL3, x10 170*4882a593Smuzhiyun isb 171*4882a593Smuzhiyun 172*4882a593Smuzhiyun msr ICC_CTLR_EL3, xzr 173*4882a593Smuzhiyun isb 174*4882a593Smuzhiyun 175*4882a593Smuzhiyun msr ICC_CTLR_EL1, xzr /* NonSecure ICC_CTLR_EL1 */ 176*4882a593Smuzhiyun isb 177*4882a593Smuzhiyun 178*4882a593Smuzhiyun mov x10, #0x1 << 7 /* Non-Secure access to ICC_PMR_EL1 */ 179*4882a593Smuzhiyun msr ICC_PMR_EL1, x10 180*4882a593Smuzhiyun isb 181*4882a593Smuzhiyun#endif 182*4882a593Smuzhiyun 183*4882a593Smuzhiyun#elif defined(CONFIG_GICV2) 184*4882a593Smuzhiyun /* 185*4882a593Smuzhiyun * Initialize SGIs and PPIs 186*4882a593Smuzhiyun * x0: Distributor Base 187*4882a593Smuzhiyun * x1: Cpu Interface Base 188*4882a593Smuzhiyun */ 189*4882a593Smuzhiyun mov w9, #~0 /* Config SGIs and PPIs as Grp1 */ 190*4882a593Smuzhiyun str w9, [x0, GICD_IGROUPRn] /* GICD_IGROUPR0 */ 191*4882a593Smuzhiyun mov w9, #0x1 /* Enable SGI 0 */ 192*4882a593Smuzhiyun str w9, [x0, GICD_ISENABLERn] 193*4882a593Smuzhiyun 194*4882a593Smuzhiyun /* Initialize Cpu Interface */ 195*4882a593Smuzhiyun mov w9, #0x1e7 /* Disable IRQ/FIQ Bypass & */ 196*4882a593Smuzhiyun /* Enable Ack Group1 Interrupt & */ 197*4882a593Smuzhiyun /* EnableGrp0 & EnableGrp1 */ 198*4882a593Smuzhiyun str w9, [x1, GICC_CTLR] /* Secure GICC_CTLR */ 199*4882a593Smuzhiyun 200*4882a593Smuzhiyun mov w9, #0x1 << 7 /* Non-Secure access to GICC_PMR */ 201*4882a593Smuzhiyun str w9, [x1, GICC_PMR] 202*4882a593Smuzhiyun#endif 203*4882a593Smuzhiyun ret 204*4882a593SmuzhiyunENDPROC(gic_init_secure_percpu) 205*4882a593Smuzhiyun 206*4882a593Smuzhiyun 207*4882a593Smuzhiyun/************************************************************************* 208*4882a593Smuzhiyun * For Gicv2: 209*4882a593Smuzhiyun * void gic_kick_secondary_cpus(DistributorBase); 210*4882a593Smuzhiyun * For Gicv3: 211*4882a593Smuzhiyun * void gic_kick_secondary_cpus(void); 212*4882a593Smuzhiyun * 213*4882a593Smuzhiyun *************************************************************************/ 214*4882a593SmuzhiyunENTRY(gic_kick_secondary_cpus) 215*4882a593Smuzhiyun#if defined(CONFIG_GICV3) 216*4882a593Smuzhiyun mov x9, #(1 << 40) 217*4882a593Smuzhiyun msr ICC_ASGI1R_EL1, x9 218*4882a593Smuzhiyun isb 219*4882a593Smuzhiyun#elif defined(CONFIG_GICV2) 220*4882a593Smuzhiyun mov w9, #0x8000 221*4882a593Smuzhiyun movk w9, #0x100, lsl #16 222*4882a593Smuzhiyun str w9, [x0, GICD_SGIR] 223*4882a593Smuzhiyun#endif 224*4882a593Smuzhiyun ret 225*4882a593SmuzhiyunENDPROC(gic_kick_secondary_cpus) 226*4882a593Smuzhiyun 227*4882a593Smuzhiyun 228*4882a593Smuzhiyun/************************************************************************* 229*4882a593Smuzhiyun * For Gicv2: 230*4882a593Smuzhiyun * void gic_wait_for_interrupt(CpuInterfaceBase); 231*4882a593Smuzhiyun * For Gicv3: 232*4882a593Smuzhiyun * void gic_wait_for_interrupt(void); 233*4882a593Smuzhiyun * 234*4882a593Smuzhiyun * Wait for SGI 0 from master. 235*4882a593Smuzhiyun * 236*4882a593Smuzhiyun *************************************************************************/ 237*4882a593SmuzhiyunENTRY(gic_wait_for_interrupt) 238*4882a593Smuzhiyun#if defined(CONFIG_GICV3) 239*4882a593Smuzhiyun gic_wait_for_interrupt_m x9 240*4882a593Smuzhiyun#elif defined(CONFIG_GICV2) 241*4882a593Smuzhiyun gic_wait_for_interrupt_m x0, w9 242*4882a593Smuzhiyun#endif 243*4882a593Smuzhiyun ret 244*4882a593SmuzhiyunENDPROC(gic_wait_for_interrupt) 245