aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJonas Gorski <jonas.gorski@gmail.com>2016-12-19 13:02:21 +0100
committerJonas Gorski <jonas.gorski@gmail.com>2017-02-10 10:51:09 +0100
commit921cecbdf859df4a8df4e1005ce58e1c9672d6a8 (patch)
treec47852e39ab7260c2b0459548c458119c32bb3a0
parentb8567cb44e9e4f55b7529e16b64a85d492a162f1 (diff)
downloadupstream-921cecbdf859df4a8df4e1005ce58e1c9672d6a8.tar.gz
upstream-921cecbdf859df4a8df4e1005ce58e1c9672d6a8.tar.bz2
upstream-921cecbdf859df4a8df4e1005ce58e1c9672d6a8.zip
brcm63xx: fix external interrupts on BCM6318
Setting the clear bit for an interrupt seems to cause interrupts to be deasserted again immediately. So unset the bit for BCM6318 to allow subsequent interrupts to still work. Signed-off-by: Jonas Gorski <jonas.gorski@gmail.com>
-rw-r--r--target/linux/brcm63xx/dts/bcm6318.dtsi2
-rw-r--r--target/linux/brcm63xx/patches-4.4/321-irqchip-add-support-for-bcm6345-style-external-inter.patch27
2 files changed, 21 insertions, 8 deletions
diff --git a/target/linux/brcm63xx/dts/bcm6318.dtsi b/target/linux/brcm63xx/dts/bcm6318.dtsi
index 115b15c7fe..776698068d 100644
--- a/target/linux/brcm63xx/dts/bcm6318.dtsi
+++ b/target/linux/brcm63xx/dts/bcm6318.dtsi
@@ -36,7 +36,7 @@
compatible = "simple-bus";
ext_intc: interrupt-controller@10000018 {
- compatible = "brcm,bcm6345-ext-intc";
+ compatible = "brcm,bcm6318-ext-intc";
reg = <0x10000018 0x4>;
interrupt-controller;
diff --git a/target/linux/brcm63xx/patches-4.4/321-irqchip-add-support-for-bcm6345-style-external-inter.patch b/target/linux/brcm63xx/patches-4.4/321-irqchip-add-support-for-bcm6345-style-external-inter.patch
index 252645695f..2271b66f0e 100644
--- a/target/linux/brcm63xx/patches-4.4/321-irqchip-add-support-for-bcm6345-style-external-inter.patch
+++ b/target/linux/brcm63xx/patches-4.4/321-irqchip-add-support-for-bcm6345-style-external-inter.patch
@@ -23,7 +23,7 @@ Signed-off-by: Jonas Gorski <jogo@openwrt.org>
+
+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
@@ -73,7 +73,7 @@ Signed-off-by: Jonas Gorski <jogo@openwrt.org>
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
@@ -119,6 +119,7 @@ Signed-off-by: Jonas Gorski <jogo@openwrt.org>
+ 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)
@@ -148,8 +149,10 @@ Signed-off-by: Jonas Gorski <jogo@openwrt.org>
+
+ 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);
+}
+
@@ -263,7 +266,8 @@ Signed-off-by: Jonas Gorski <jogo@openwrt.org>
+
+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;
@@ -284,6 +288,7 @@ Signed-off-by: Jonas Gorski <jogo@openwrt.org>
+
+ 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;
@@ -314,7 +319,7 @@ Signed-off-by: Jonas Gorski <jogo@openwrt.org>
+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
@@ -326,6 +331,7 @@ Signed-off-by: Jonas Gorski <jogo@openwrt.org>
+ void __iomem *base;
+ int irqs[MAX_IRQS] = { 0 };
+ u32 shift;
++ bool toggle_clear_on_ack = false;
+
+ num_irqs = of_irq_count(node);
+
@@ -335,6 +341,10 @@ Signed-off-by: Jonas Gorski <jogo@openwrt.org>
+ 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]) {
@@ -347,7 +357,8 @@ Signed-off-by: Jonas Gorski <jogo@openwrt.org>
+ 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:
@@ -359,6 +370,8 @@ Signed-off-by: Jonas Gorski <jogo@openwrt.org>
+ 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