[PATCH v6 02/11] irqchip: loongson-liointc: Workaround LPC IRQ Errata

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



The 1.0 version of that controller has a bug that status bit
of LPC IRQ sometimes doesn't get set correctly.

So we can always blame LPC IRQ when spurious interrupt happens
at the parent interrupt line which LPC IRQ supposed to route
to.

Co-developed-by: Huacai Chen <chenhc@xxxxxxxxxx>
Signed-off-by: Jiaxun Yang <jiaxun.yang@xxxxxxxxxxx>
---
 drivers/irqchip/irq-loongson-liointc.c | 16 ++++++++++++++--
 1 file changed, 14 insertions(+), 2 deletions(-)

diff --git a/drivers/irqchip/irq-loongson-liointc.c b/drivers/irqchip/irq-loongson-liointc.c
index 8b6d7b8ddaca..d5054e90eab8 100644
--- a/drivers/irqchip/irq-loongson-liointc.c
+++ b/drivers/irqchip/irq-loongson-liointc.c
@@ -32,6 +32,8 @@
 
 #define LIOINTC_SHIFT_INTx	4
 
+#define LIOINTC_ERRATA_IRQ	10
+
 struct liointc_handler_data {
 	struct liointc_priv	*priv;
 	u32			parent_int_map;
@@ -41,6 +43,7 @@ struct liointc_priv {
 	struct irq_chip_generic		*gc;
 	struct liointc_handler_data	handler[LIOINTC_NUM_PARENT];
 	u8				map_cache[LIOINTC_CHIP_IRQ];
+	bool				have_lpc_irq_errata;
 };
 
 static void liointc_chained_handle_irq(struct irq_desc *desc)
@@ -54,8 +57,14 @@ static void liointc_chained_handle_irq(struct irq_desc *desc)
 
 	pending = readl(gc->reg_base + LIOINTC_REG_INTC_STATUS);
 
-	if (!pending)
-		spurious_interrupt();
+	if (!pending) {
+		/* Always blame LPC IRQ if we have that bug and LPC IRQ is enabled */
+		if (handler->priv->have_lpc_irq_errata &&
+			(handler->parent_int_map & ~gc->mask_cache & BIT(LIOINTC_ERRATA_IRQ)))
+			pending = BIT(LIOINTC_ERRATA_IRQ);
+		else
+			spurious_interrupt();
+	}
 
 	while (pending) {
 		int bit = __ffs(pending);
@@ -164,6 +173,9 @@ int __init liointc_of_init(struct device_node *node,
 		goto out_iounmap;
 	}
 
+	if (of_device_is_compatible(node, "loongson,liointc-1.0"))
+		priv->have_lpc_irq_errata = true;
+
 	sz = of_property_read_variable_u32_array(node, "loongson,parent_int_map",
 						&of_parent_int_map[0], LIOINTC_NUM_PARENT,
 						LIOINTC_NUM_PARENT);
-- 
2.26.0.rc2






[Index of Archives]     [Device Tree Compilter]     [Device Tree Spec]     [Linux Driver Backports]     [Video for Linux]     [Linux USB Devel]     [Linux PCI Devel]     [Linux Audio Users]     [Linux Kernel]     [Linux SCSI]     [XFree86]     [Yosemite Backpacking]


  Powered by Linux