1 /* 2 * Copyright (C) 2002 ARM Limited, All Rights Reserved. 3 * 4 * This program is free software; you can redistribute it and/or modify 5 * it under the terms of the GNU General Public License version 2 as 6 * published by the Free Software Foundation. 7 * 8 * This program is distributed in the hope that it will be useful, 9 * but WITHOUT ANY WARRANTY; without even the implied warranty of 10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 * GNU General Public License for more details. 12 * 13 * You should have received a copy of the GNU General Public License 14 * along with this program. If not, see <http://www.gnu.org/licenses/>. 15 */ 16 17 #include <linux/interrupt.h> 18 #include <linux/io.h> 19 #include <linux/irq.h> 20 #include <linux/irqchip/arm-gic.h> 21 22 #include "irq-gic-common.h" 23 24 static const struct gic_kvm_info *gic_kvm_info; 25 26 const struct gic_kvm_info *gic_get_kvm_info(void) 27 { 28 return gic_kvm_info; 29 } 30 31 void gic_set_kvm_info(const struct gic_kvm_info *info) 32 { 33 BUG_ON(gic_kvm_info != NULL); 34 gic_kvm_info = info; 35 } 36 37 void gic_enable_quirks(u32 iidr, const struct gic_quirk *quirks, 38 void *data) 39 { 40 for (; quirks->desc; quirks++) { 41 if (quirks->iidr != (quirks->mask & iidr)) 42 continue; 43 quirks->init(data); 44 pr_info("GIC: enabling workaround for %s\n", quirks->desc); 45 } 46 } 47 48 int gic_configure_irq(unsigned int irq, unsigned int type, 49 void __iomem *base, void (*sync_access)(void)) 50 { 51 u32 confmask = 0x2 << ((irq % 16) * 2); 52 u32 confoff = (irq / 16) * 4; 53 u32 val, oldval; 54 int ret = 0; 55 56 /* 57 * Read current configuration register, and insert the config 58 * for "irq", depending on "type". 59 */ 60 val = oldval = readl_relaxed(base + GIC_DIST_CONFIG + confoff); 61 if (type & IRQ_TYPE_LEVEL_MASK) 62 val &= ~confmask; 63 else if (type & IRQ_TYPE_EDGE_BOTH) 64 val |= confmask; 65 66 /* If the current configuration is the same, then we are done */ 67 if (val == oldval) 68 return 0; 69 70 /* 71 * Write back the new configuration, and possibly re-enable 72 * the interrupt. If we fail to write a new configuration for 73 * an SPI then WARN and return an error. If we fail to write the 74 * configuration for a PPI this is most likely because the GIC 75 * does not allow us to set the configuration or we are in a 76 * non-secure mode, and hence it may not be catastrophic. 77 */ 78 writel_relaxed(val, base + GIC_DIST_CONFIG + confoff); 79 if (readl_relaxed(base + GIC_DIST_CONFIG + confoff) != val) { 80 if (WARN_ON(irq >= 32)) 81 ret = -EINVAL; 82 else 83 pr_warn("GIC: PPI%d is secure or misconfigured\n", 84 irq - 16); 85 } 86 87 if (sync_access) 88 sync_access(); 89 90 return ret; 91 } 92 93 void gic_dist_config(void __iomem *base, int gic_irqs, 94 void (*sync_access)(void)) 95 { 96 unsigned int i; 97 98 /* 99 * Set all global interrupts to be level triggered, active low. 100 */ 101 for (i = 32; i < gic_irqs; i += 16) 102 writel_relaxed(GICD_INT_ACTLOW_LVLTRIG, 103 base + GIC_DIST_CONFIG + i / 4); 104 105 /* 106 * Set priority on all global interrupts. 107 */ 108 for (i = 32; i < gic_irqs; i += 4) 109 writel_relaxed(GICD_INT_DEF_PRI_X4, base + GIC_DIST_PRI + i); 110 111 /* 112 * Deactivate and disable all SPIs. Leave the PPI and SGIs 113 * alone as they are in the redistributor registers on GICv3. 114 */ 115 for (i = 32; i < gic_irqs; i += 32) { 116 writel_relaxed(GICD_INT_EN_CLR_X32, 117 base + GIC_DIST_ACTIVE_CLEAR + i / 8); 118 writel_relaxed(GICD_INT_EN_CLR_X32, 119 base + GIC_DIST_ENABLE_CLEAR + i / 8); 120 } 121 122 if (sync_access) 123 sync_access(); 124 } 125 126 void gic_cpu_config(void __iomem *base, void (*sync_access)(void)) 127 { 128 int i; 129 130 /* 131 * Deal with the banked PPI and SGI interrupts - disable all 132 * PPI interrupts, ensure all SGI interrupts are enabled. 133 * Make sure everything is deactivated. 134 */ 135 writel_relaxed(GICD_INT_EN_CLR_X32, base + GIC_DIST_ACTIVE_CLEAR); 136 writel_relaxed(GICD_INT_EN_CLR_PPI, base + GIC_DIST_ENABLE_CLEAR); 137 writel_relaxed(GICD_INT_EN_SET_SGI, base + GIC_DIST_ENABLE_SET); 138 139 /* 140 * Set priority on PPI and SGI interrupts 141 */ 142 for (i = 0; i < 32; i += 4) 143 writel_relaxed(GICD_INT_DEF_PRI_X4, 144 base + GIC_DIST_PRI + i * 4 / 4); 145 146 if (sync_access) 147 sync_access(); 148 } 149