]> xenbits.xensource.com Git - people/julieng/linux-arm.git/commitdiff
irqchip, gicv3-its: Add HW revision detection and configuration
authorRobert Richter <rrichter@cavium.com>
Mon, 29 Jun 2015 16:25:45 +0000 (18:25 +0200)
committerJulien Grall <julien.grall@citrix.com>
Mon, 28 Sep 2015 11:05:07 +0000 (12:05 +0100)
Some GIC revisions require an individual configuration to esp. add
workarounds for HW bugs. This patch implements generic code to parse
the hw revision provided by an IIDR register value and runs specific
code if hw matches. There are functions that read the IIDR registers
for GICV3 and ITS (GICD_IIDR/GITS_IIDR) and then go through a list of
init functions to be called for specific versions.

A MIDR register value may also be used, this is especially useful for
hw detection from a guest.

The patch is needed to implement workarounds for HW errata in Cavium's
ThunderX GICV3.

v4:
 * only enable hw detection for its in its_enable_quirks()
 * removed gicv3_check_capabilities()

v3:
 * use arm64 errata framework for midr check

v2:
 * adding MIDR check

Signed-off-by: Robert Richter <rrichter@cavium.com>
Signed-off-by: Vadim Lomovtsev <Vadim.Lomovtsev@caviumnetworks.com>
drivers/irqchip/irq-gic-common.c
drivers/irqchip/irq-gic-common.h
drivers/irqchip/irq-gic-v3-its.c

index 9448e391cb710363d18df4c3079ae0504b0cbd44..ee789b07f2d1d452cf0d5aff539a3c292eda8663 100644 (file)
 
 #include "irq-gic-common.h"
 
+void gic_check_capabilities(u32 iidr, const struct gic_capabilities *cap,
+                       void *data)
+{
+       for (; cap->desc; cap++) {
+               if (cap->iidr != (cap->mask & iidr))
+                       continue;
+               cap->init(data);
+               pr_info("%s\n", cap->desc);
+       }
+}
+
 int gic_configure_irq(unsigned int irq, unsigned int type,
                       void __iomem *base, void (*sync_access)(void))
 {
index 35a9884778bd5f337f43041f9a24b88b0371734c..ca12635bbe3cfe44fe4e34a8f68ba53b4578b6eb 100644 (file)
 #include <linux/of.h>
 #include <linux/irqdomain.h>
 
+struct gic_capabilities {
+       const char *desc;
+       void (*init)(void *data);
+       u32 iidr;
+       u32 mask;
+};
+
 int gic_configure_irq(unsigned int irq, unsigned int type,
                        void __iomem *base, void (*sync_access)(void));
 void gic_dist_config(void __iomem *base, int gic_irqs,
                     void (*sync_access)(void));
 void gic_cpu_config(void __iomem *base, void (*sync_access)(void));
+void gic_check_capabilities(u32 iidr, const struct gic_capabilities *cap,
+                       void *data);
 
 #endif /* _IRQ_GIC_COMMON_H */
index 32ef94892ca05206b6634b419770a544c7621b9e..0f15ee6ec677f4ea5beed243a8d85f10b8b22da6 100644 (file)
@@ -36,6 +36,7 @@
 #include <asm/cputype.h>
 #include <asm/exception.h>
 
+#include "irq-gic-common.h"
 #include "irqchip.h"
 
 #define ITS_FLAGS_CMDQ_NEEDS_FLUSHING          (1 << 0)
@@ -1429,6 +1430,18 @@ static int its_force_quiescent(void __iomem *base)
        }
 }
 
+static const struct gic_capabilities its_errata[] = {
+       {
+       }
+};
+
+static void its_enable_quirks(struct its_node *its)
+{
+       u32 iidr = readl_relaxed(its->base + GITS_IIDR);
+
+       gic_check_capabilities(iidr, its_errata, its);
+}
+
 static int its_probe(struct device_node *node, struct irq_domain *parent)
 {
        struct resource res;
@@ -1487,6 +1500,8 @@ static int its_probe(struct device_node *node, struct irq_domain *parent)
        }
        its->cmd_write = its->cmd_base;
 
+       its_enable_quirks(its);
+
        err = its_alloc_tables(its);
        if (err)
                goto out_free_cmd;