Branch data Line data Source code
1 : : // SPDX-License-Identifier: GPL-2.0-only 2 : : /* 3 : : * Copyright (C) 2002 ARM Limited, All Rights Reserved. 4 : : */ 5 : : 6 : : #include <linux/interrupt.h> 7 : : #include <linux/io.h> 8 : : #include <linux/irq.h> 9 : : #include <linux/irqchip/arm-gic.h> 10 : : 11 : : #include "irq-gic-common.h" 12 : : 13 : : static DEFINE_RAW_SPINLOCK(irq_controller_lock); 14 : : 15 : : static const struct gic_kvm_info *gic_kvm_info; 16 : : 17 : 0 : const struct gic_kvm_info *gic_get_kvm_info(void) 18 : : { 19 : 0 : return gic_kvm_info; 20 : : } 21 : : 22 : 0 : void gic_set_kvm_info(const struct gic_kvm_info *info) 23 : : { 24 [ # # ]: 0 : BUG_ON(gic_kvm_info != NULL); 25 : 0 : gic_kvm_info = info; 26 : 0 : } 27 : : 28 : 0 : void gic_enable_of_quirks(const struct device_node *np, 29 : : const struct gic_quirk *quirks, void *data) 30 : : { 31 [ # # ]: 0 : for (; quirks->desc; quirks++) { 32 [ # # ]: 0 : if (!of_device_is_compatible(np, quirks->compatible)) 33 : 0 : continue; 34 [ # # ]: 0 : if (quirks->init(data)) 35 : 0 : pr_info("GIC: enabling workaround for %s\n", 36 : : quirks->desc); 37 : : } 38 : 0 : } 39 : : 40 : 0 : void gic_enable_quirks(u32 iidr, const struct gic_quirk *quirks, 41 : : void *data) 42 : : { 43 [ # # ]: 0 : for (; quirks->desc; quirks++) { 44 [ # # ]: 0 : if (quirks->compatible) 45 : 0 : continue; 46 [ # # ]: 0 : if (quirks->iidr != (quirks->mask & iidr)) 47 : 0 : continue; 48 [ # # ]: 0 : if (quirks->init(data)) 49 : 0 : pr_info("GIC: enabling workaround for %s\n", 50 : : quirks->desc); 51 : : } 52 : 0 : } 53 : : 54 : 0 : int gic_configure_irq(unsigned int irq, unsigned int type, 55 : : void __iomem *base, void (*sync_access)(void)) 56 : : { 57 : 0 : u32 confmask = 0x2 << ((irq % 16) * 2); 58 : 0 : u32 confoff = (irq / 16) * 4; 59 : : u32 val, oldval; 60 : : int ret = 0; 61 : : unsigned long flags; 62 : : 63 : : /* 64 : : * Read current configuration register, and insert the config 65 : : * for "irq", depending on "type". 66 : : */ 67 : 0 : raw_spin_lock_irqsave(&irq_controller_lock, flags); 68 : 0 : val = oldval = readl_relaxed(base + confoff); 69 [ # # ]: 0 : if (type & IRQ_TYPE_LEVEL_MASK) 70 : 0 : val &= ~confmask; 71 [ # # ]: 0 : else if (type & IRQ_TYPE_EDGE_BOTH) 72 : 0 : val |= confmask; 73 : : 74 : : /* If the current configuration is the same, then we are done */ 75 [ # # ]: 0 : if (val == oldval) { 76 : 0 : raw_spin_unlock_irqrestore(&irq_controller_lock, flags); 77 : 0 : return 0; 78 : : } 79 : : 80 : : /* 81 : : * Write back the new configuration, and possibly re-enable 82 : : * the interrupt. If we fail to write a new configuration for 83 : : * an SPI then WARN and return an error. If we fail to write the 84 : : * configuration for a PPI this is most likely because the GIC 85 : : * does not allow us to set the configuration or we are in a 86 : : * non-secure mode, and hence it may not be catastrophic. 87 : : */ 88 : : writel_relaxed(val, base + confoff); 89 [ # # ]: 0 : if (readl_relaxed(base + confoff) != val) 90 : : ret = -EINVAL; 91 : : 92 : 0 : raw_spin_unlock_irqrestore(&irq_controller_lock, flags); 93 : : 94 [ # # ]: 0 : if (sync_access) 95 : 0 : sync_access(); 96 : : 97 : 0 : return ret; 98 : : } 99 : : 100 : 0 : void gic_dist_config(void __iomem *base, int gic_irqs, 101 : : void (*sync_access)(void)) 102 : : { 103 : : unsigned int i; 104 : : 105 : : /* 106 : : * Set all global interrupts to be level triggered, active low. 107 : : */ 108 [ # # ]: 0 : for (i = 32; i < gic_irqs; i += 16) 109 : 0 : writel_relaxed(GICD_INT_ACTLOW_LVLTRIG, 110 : : base + GIC_DIST_CONFIG + i / 4); 111 : : 112 : : /* 113 : : * Set priority on all global interrupts. 114 : : */ 115 [ # # ]: 0 : for (i = 32; i < gic_irqs; i += 4) 116 : 0 : writel_relaxed(GICD_INT_DEF_PRI_X4, base + GIC_DIST_PRI + i); 117 : : 118 : : /* 119 : : * Deactivate and disable all SPIs. Leave the PPI and SGIs 120 : : * alone as they are in the redistributor registers on GICv3. 121 : : */ 122 [ # # ]: 0 : for (i = 32; i < gic_irqs; i += 32) { 123 : 0 : writel_relaxed(GICD_INT_EN_CLR_X32, 124 : : base + GIC_DIST_ACTIVE_CLEAR + i / 8); 125 : 0 : writel_relaxed(GICD_INT_EN_CLR_X32, 126 : : base + GIC_DIST_ENABLE_CLEAR + i / 8); 127 : : } 128 : : 129 [ # # ]: 0 : if (sync_access) 130 : 0 : sync_access(); 131 : 0 : } 132 : : 133 : 0 : void gic_cpu_config(void __iomem *base, int nr, void (*sync_access)(void)) 134 : : { 135 : : int i; 136 : : 137 : : /* 138 : : * Deal with the banked PPI and SGI interrupts - disable all 139 : : * private interrupts. Make sure everything is deactivated. 140 : : */ 141 [ # # ]: 0 : for (i = 0; i < nr; i += 32) { 142 : 0 : writel_relaxed(GICD_INT_EN_CLR_X32, 143 : : base + GIC_DIST_ACTIVE_CLEAR + i / 8); 144 : 0 : writel_relaxed(GICD_INT_EN_CLR_X32, 145 : : base + GIC_DIST_ENABLE_CLEAR + i / 8); 146 : : } 147 : : 148 : : /* 149 : : * Set priority on PPI and SGI interrupts 150 : : */ 151 [ # # ]: 0 : for (i = 0; i < nr; i += 4) 152 : 0 : writel_relaxed(GICD_INT_DEF_PRI_X4, 153 : : base + GIC_DIST_PRI + i * 4 / 4); 154 : : 155 : : /* Ensure all SGI interrupts are now enabled */ 156 : 0 : writel_relaxed(GICD_INT_EN_SET_SGI, base + GIC_DIST_ENABLE_SET); 157 : : 158 [ # # ]: 0 : if (sync_access) 159 : 0 : sync_access(); 160 : 0 : }