+
+Required properties:
+
-+- compatible: Should be "brcm,bcm6345-ext-intc".
++- compatible: Should be "brcm,bcm6345-ext-intc" or "brcm,bcm6318-ext-intc".
+- reg: Specifies the base physical addresses and size of the registers.
+- interrupt-controller: identifies the node as an interrupt controller.
+- #interrupt-cells: Specifies the number of cells needed to encode an interrupt
obj-$(CONFIG_METAG) += irq-metag-ext.o
--- /dev/null
+++ b/drivers/irqchip/irq-bcm6345-ext.c
-@@ -0,0 +1,288 @@
+@@ -0,0 +1,301 @@
+/*
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file "COPYING" in the main directory of this archive
+ int parent_irq[MAX_IRQS];
+ void __iomem *reg;
+ int shift;
++ unsigned int toggle_clear_on_ack:1;
+};
+
+static void bcm6345_ext_intc_irq_handle(struct irq_desc *desc)
+
+ raw_spin_lock(&priv->lock);
+ reg = __raw_readl(priv->reg);
-+ reg |= 1 << (hwirq + EXTIRQ_CFG_CLEAR * priv->shift);
-+ __raw_writel(reg, priv->reg);
++ __raw_writel(reg | (1 << (hwirq + EXTIRQ_CFG_CLEAR * priv->shift)),
++ priv->reg);
++ if (priv->toggle_clear_on_ack)
++ __raw_writel(reg, priv->reg);
+ raw_spin_unlock(&priv->lock);
+}
+
+
+static int __init __bcm6345_ext_intc_init(struct device_node *node,
+ int num_irqs, int *irqs,
-+ void __iomem *reg, int shift)
++ void __iomem *reg, int shift,
++ bool toggle_clear_on_ack)
+{
+ struct intc_data *data;
+ unsigned int i;
+
+ data->reg = reg;
+ data->shift = shift;
++ data->toggle_clear_on_ack = toggle_clear_on_ack;
+
+ data->chip.name = "bcm6345-ext-intc";
+ data->chip.irq_ack = bcm6345_ext_intc_irq_ack;
+void __init bcm6345_ext_intc_init(int num_irqs, int *irqs, void __iomem *reg,
+ int shift)
+{
-+ __bcm6345_ext_intc_init(NULL, num_irqs, irqs, reg, shift);
++ __bcm6345_ext_intc_init(NULL, num_irqs, irqs, reg, shift, false);
+}
+
+#ifdef CONFIG_OF
+ void __iomem *base;
+ int irqs[MAX_IRQS] = { 0 };
+ u32 shift;
++ bool toggle_clear_on_ack = false;
+
+ num_irqs = of_irq_count(node);
+
+ if (of_property_read_u32(node, "brcm,field-width", &shift))
+ shift = 4;
+
++ /* on BCM6318 setting CLEAR seems to continuously mask interrupts */
++ if (of_device_is_compatible(node, "brcm,bcm6318-ext-intc"))
++ toggle_clear_on_ack = true;
++
+ for (i = 0; i < num_irqs; i++) {
+ irqs[i] = irq_of_parse_and_map(node, i);
+ if (!irqs[i]) {
+ if (!base)
+ goto out_unmap;
+
-+ ret = __bcm6345_ext_intc_init(node, num_irqs, irqs, base, shift);
++ ret = __bcm6345_ext_intc_init(node, num_irqs, irqs, base, shift,
++ toggle_clear_on_ack);
+ if (!ret)
+ return 0;
+out_unmap:
+ return ret;
+}
+
++IRQCHIP_DECLARE(bcm6318_ext_intc, "brcm,bcm6318-ext-intc",
++ bcm6345_ext_intc_of_init);
+IRQCHIP_DECLARE(bcm6345_ext_intc, "brcm,bcm6345-ext-intc",
+ bcm6345_ext_intc_of_init);
+#endif