2
0
Эх сурвалжийг харах

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 <[email protected]>
Jonas Gorski 9 жил өмнө
parent
commit
94bbd1f057

+ 1 - 1
target/linux/brcm63xx/dts/bcm6318.dtsi

@@ -36,7 +36,7 @@
 		compatible = "simple-bus";
 		compatible = "simple-bus";
 
 
 		ext_intc: interrupt-controller@10000018 {
 		ext_intc: interrupt-controller@10000018 {
-			compatible = "brcm,bcm6345-ext-intc";
+			compatible = "brcm,bcm6318-ext-intc";
 			reg = <0x10000018 0x4>;
 			reg = <0x10000018 0x4>;
 
 
 			interrupt-controller;
 			interrupt-controller;

+ 20 - 7
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 <[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