diff options
Diffstat (limited to 'drivers/irqchip/irq-gic-common.c')
-rw-r--r-- | drivers/irqchip/irq-gic-common.c | 24 |
1 files changed, 20 insertions, 4 deletions
diff --git a/drivers/irqchip/irq-gic-common.c b/drivers/irqchip/irq-gic-common.c index 9448e391c..f174ce0ca 100644 --- a/drivers/irqchip/irq-gic-common.c +++ b/drivers/irqchip/irq-gic-common.c @@ -21,6 +21,17 @@ #include "irq-gic-common.h" +void gic_enable_quirks(u32 iidr, const struct gic_quirk *quirks, + void *data) +{ + for (; quirks->desc; quirks++) { + if (quirks->iidr != (quirks->mask & iidr)) + continue; + quirks->init(data); + pr_info("GIC: enabling workaround for %s\n", quirks->desc); + } +} + int gic_configure_irq(unsigned int irq, unsigned int type, void __iomem *base, void (*sync_access)(void)) { @@ -73,12 +84,15 @@ void __init gic_dist_config(void __iomem *base, int gic_irqs, writel_relaxed(GICD_INT_DEF_PRI_X4, base + GIC_DIST_PRI + i); /* - * Disable all interrupts. Leave the PPI and SGIs alone - * as they are enabled by redistributor registers. + * Deactivate and disable all SPIs. Leave the PPI and SGIs + * alone as they are in the redistributor registers on GICv3. */ - for (i = 32; i < gic_irqs; i += 32) + for (i = 32; i < gic_irqs; i += 32) { + writel_relaxed(GICD_INT_EN_CLR_X32, + base + GIC_DIST_ACTIVE_CLEAR + i / 8); writel_relaxed(GICD_INT_EN_CLR_X32, - base + GIC_DIST_ENABLE_CLEAR + i / 8); + base + GIC_DIST_ENABLE_CLEAR + i / 8); + } if (sync_access) sync_access(); @@ -91,7 +105,9 @@ void gic_cpu_config(void __iomem *base, void (*sync_access)(void)) /* * Deal with the banked PPI and SGI interrupts - disable all * PPI interrupts, ensure all SGI interrupts are enabled. + * Make sure everything is deactivated. */ + writel_relaxed(GICD_INT_EN_CLR_X32, base + GIC_DIST_ACTIVE_CLEAR); writel_relaxed(GICD_INT_EN_CLR_PPI, base + GIC_DIST_ENABLE_CLEAR); writel_relaxed(GICD_INT_EN_SET_SGI, base + GIC_DIST_ENABLE_SET); |