0001
0002
0003
0004
0005
0006 #include <linux/interrupt.h>
0007 #include <linux/io.h>
0008 #include <linux/irq.h>
0009 #include <linux/irqchip/arm-gic.h>
0010
0011 #include "irq-gic-common.h"
0012
0013 static DEFINE_RAW_SPINLOCK(irq_controller_lock);
0014
0015 void gic_enable_of_quirks(const struct device_node *np,
0016 const struct gic_quirk *quirks, void *data)
0017 {
0018 for (; quirks->desc; quirks++) {
0019 if (!of_device_is_compatible(np, quirks->compatible))
0020 continue;
0021 if (quirks->init(data))
0022 pr_info("GIC: enabling workaround for %s\n",
0023 quirks->desc);
0024 }
0025 }
0026
0027 void gic_enable_quirks(u32 iidr, const struct gic_quirk *quirks,
0028 void *data)
0029 {
0030 for (; quirks->desc; quirks++) {
0031 if (quirks->compatible)
0032 continue;
0033 if (quirks->iidr != (quirks->mask & iidr))
0034 continue;
0035 if (quirks->init(data))
0036 pr_info("GIC: enabling workaround for %s\n",
0037 quirks->desc);
0038 }
0039 }
0040
0041 int gic_configure_irq(unsigned int irq, unsigned int type,
0042 void __iomem *base, void (*sync_access)(void))
0043 {
0044 u32 confmask = 0x2 << ((irq % 16) * 2);
0045 u32 confoff = (irq / 16) * 4;
0046 u32 val, oldval;
0047 int ret = 0;
0048 unsigned long flags;
0049
0050
0051
0052
0053
0054 raw_spin_lock_irqsave(&irq_controller_lock, flags);
0055 val = oldval = readl_relaxed(base + confoff);
0056 if (type & IRQ_TYPE_LEVEL_MASK)
0057 val &= ~confmask;
0058 else if (type & IRQ_TYPE_EDGE_BOTH)
0059 val |= confmask;
0060
0061
0062 if (val == oldval) {
0063 raw_spin_unlock_irqrestore(&irq_controller_lock, flags);
0064 return 0;
0065 }
0066
0067
0068
0069
0070
0071
0072
0073
0074
0075 writel_relaxed(val, base + confoff);
0076 if (readl_relaxed(base + confoff) != val)
0077 ret = -EINVAL;
0078
0079 raw_spin_unlock_irqrestore(&irq_controller_lock, flags);
0080
0081 if (sync_access)
0082 sync_access();
0083
0084 return ret;
0085 }
0086
0087 void gic_dist_config(void __iomem *base, int gic_irqs,
0088 void (*sync_access)(void))
0089 {
0090 unsigned int i;
0091
0092
0093
0094
0095 for (i = 32; i < gic_irqs; i += 16)
0096 writel_relaxed(GICD_INT_ACTLOW_LVLTRIG,
0097 base + GIC_DIST_CONFIG + i / 4);
0098
0099
0100
0101
0102 for (i = 32; i < gic_irqs; i += 4)
0103 writel_relaxed(GICD_INT_DEF_PRI_X4, base + GIC_DIST_PRI + i);
0104
0105
0106
0107
0108
0109 for (i = 32; i < gic_irqs; i += 32) {
0110 writel_relaxed(GICD_INT_EN_CLR_X32,
0111 base + GIC_DIST_ACTIVE_CLEAR + i / 8);
0112 writel_relaxed(GICD_INT_EN_CLR_X32,
0113 base + GIC_DIST_ENABLE_CLEAR + i / 8);
0114 }
0115
0116 if (sync_access)
0117 sync_access();
0118 }
0119
0120 void gic_cpu_config(void __iomem *base, int nr, void (*sync_access)(void))
0121 {
0122 int i;
0123
0124
0125
0126
0127
0128 for (i = 0; i < nr; i += 32) {
0129 writel_relaxed(GICD_INT_EN_CLR_X32,
0130 base + GIC_DIST_ACTIVE_CLEAR + i / 8);
0131 writel_relaxed(GICD_INT_EN_CLR_X32,
0132 base + GIC_DIST_ENABLE_CLEAR + i / 8);
0133 }
0134
0135
0136
0137
0138 for (i = 0; i < nr; i += 4)
0139 writel_relaxed(GICD_INT_DEF_PRI_X4,
0140 base + GIC_DIST_PRI + i * 4 / 4);
0141
0142 if (sync_access)
0143 sync_access();
0144 }