|
@@ -23,7 +23,7 @@ Signed-off-by: Jonas Gorski <[email protected]>
|
|
|
+
|
|
+
|
|
|
+Required properties:
|
|
+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.
|
|
+- reg: Specifies the base physical addresses and size of the registers.
|
|
|
+- interrupt-controller: identifies the node as an interrupt controller.
|
|
+- interrupt-controller: identifies the node as an interrupt controller.
|
|
|
+- #interrupt-cells: Specifies the number of cells needed to encode an interrupt
|
|
+- #interrupt-cells: Specifies the number of cells needed to encode an interrupt
|
|
@@ -73,7 +73,7 @@ Signed-off-by: Jonas Gorski <[email protected]>
|
|
|
obj-$(CONFIG_METAG) += irq-metag-ext.o
|
|
obj-$(CONFIG_METAG) += irq-metag-ext.o
|
|
|
--- /dev/null
|
|
--- /dev/null
|
|
|
+++ b/drivers/irqchip/irq-bcm6345-ext.c
|
|
+++ 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
|
|
+ * 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
|
|
+ * License. See the file "COPYING" in the main directory of this archive
|
|
@@ -119,6 +119,7 @@ Signed-off-by: Jonas Gorski <[email protected]>
|
|
|
+ int parent_irq[MAX_IRQS];
|
|
+ int parent_irq[MAX_IRQS];
|
|
|
+ void __iomem *reg;
|
|
+ void __iomem *reg;
|
|
|
+ int shift;
|
|
+ int shift;
|
|
|
|
|
++ unsigned int toggle_clear_on_ack:1;
|
|
|
+};
|
|
+};
|
|
|
+
|
|
+
|
|
|
+static void bcm6345_ext_intc_irq_handle(struct irq_desc *desc)
|
|
+static void bcm6345_ext_intc_irq_handle(struct irq_desc *desc)
|
|
@@ -148,8 +149,10 @@ Signed-off-by: Jonas Gorski <[email protected]>
|
|
|
+
|
|
+
|
|
|
+ raw_spin_lock(&priv->lock);
|
|
+ raw_spin_lock(&priv->lock);
|
|
|
+ reg = __raw_readl(priv->reg);
|
|
+ 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);
|
|
+ raw_spin_unlock(&priv->lock);
|
|
|
+}
|
|
+}
|
|
|
+
|
|
+
|
|
@@ -263,7 +266,8 @@ Signed-off-by: Jonas Gorski <[email protected]>
|
|
|
+
|
|
+
|
|
|
+static int __init __bcm6345_ext_intc_init(struct device_node *node,
|
|
+static int __init __bcm6345_ext_intc_init(struct device_node *node,
|
|
|
+ int num_irqs, int *irqs,
|
|
+ int num_irqs, int *irqs,
|
|
|
-+ void __iomem *reg, int shift)
|
|
|
|
|
|
|
++ void __iomem *reg, int shift,
|
|
|
|
|
++ bool toggle_clear_on_ack)
|
|
|
+{
|
|
+{
|
|
|
+ struct intc_data *data;
|
|
+ struct intc_data *data;
|
|
|
+ unsigned int i;
|
|
+ unsigned int i;
|
|
@@ -284,6 +288,7 @@ Signed-off-by: Jonas Gorski <[email protected]>
|
|
|
+
|
|
+
|
|
|
+ data->reg = reg;
|
|
+ data->reg = reg;
|
|
|
+ data->shift = shift;
|
|
+ data->shift = shift;
|
|
|
|
|
++ data->toggle_clear_on_ack = toggle_clear_on_ack;
|
|
|
+
|
|
+
|
|
|
+ data->chip.name = "bcm6345-ext-intc";
|
|
+ data->chip.name = "bcm6345-ext-intc";
|
|
|
+ data->chip.irq_ack = bcm6345_ext_intc_irq_ack;
|
|
+ data->chip.irq_ack = bcm6345_ext_intc_irq_ack;
|
|
@@ -314,7 +319,7 @@ Signed-off-by: Jonas Gorski <[email protected]>
|
|
|
+void __init bcm6345_ext_intc_init(int num_irqs, int *irqs, void __iomem *reg,
|
|
+void __init bcm6345_ext_intc_init(int num_irqs, int *irqs, void __iomem *reg,
|
|
|
+ int shift)
|
|
+ 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
|
|
+#ifdef CONFIG_OF
|
|
@@ -326,6 +331,7 @@ Signed-off-by: Jonas Gorski <[email protected]>
|
|
|
+ void __iomem *base;
|
|
+ void __iomem *base;
|
|
|
+ int irqs[MAX_IRQS] = { 0 };
|
|
+ int irqs[MAX_IRQS] = { 0 };
|
|
|
+ u32 shift;
|
|
+ u32 shift;
|
|
|
|
|
++ bool toggle_clear_on_ack = false;
|
|
|
+
|
|
+
|
|
|
+ num_irqs = of_irq_count(node);
|
|
+ num_irqs = of_irq_count(node);
|
|
|
+
|
|
+
|
|
@@ -335,6 +341,10 @@ Signed-off-by: Jonas Gorski <[email protected]>
|
|
|
+ if (of_property_read_u32(node, "brcm,field-width", &shift))
|
|
+ if (of_property_read_u32(node, "brcm,field-width", &shift))
|
|
|
+ shift = 4;
|
|
+ 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++) {
|
|
+ for (i = 0; i < num_irqs; i++) {
|
|
|
+ irqs[i] = irq_of_parse_and_map(node, i);
|
|
+ irqs[i] = irq_of_parse_and_map(node, i);
|
|
|
+ if (!irqs[i]) {
|
|
+ if (!irqs[i]) {
|
|
@@ -347,7 +357,8 @@ Signed-off-by: Jonas Gorski <[email protected]>
|
|
|
+ if (!base)
|
|
+ if (!base)
|
|
|
+ goto out_unmap;
|
|
+ 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)
|
|
+ if (!ret)
|
|
|
+ return 0;
|
|
+ return 0;
|
|
|
+out_unmap:
|
|
+out_unmap:
|
|
@@ -359,6 +370,8 @@ Signed-off-by: Jonas Gorski <[email protected]>
|
|
|
+ return ret;
|
|
+ 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",
|
|
+IRQCHIP_DECLARE(bcm6345_ext_intc, "brcm,bcm6345-ext-intc",
|
|
|
+ bcm6345_ext_intc_of_init);
|
|
+ bcm6345_ext_intc_of_init);
|
|
|
+#endif
|
|
+#endif
|