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