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