Commit be09ef09 authored by Jiaxun Yang's avatar Jiaxun Yang Committed by Thomas Bogendoerfer
Browse files

irqchip: loongson-liointc: Workaround LPC IRQ Errata



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.

Signed-off-by: default avatarJiaxun Yang <jiaxun.yang@flygoat.com>
Co-developed-by: default avatarHuacai Chen <chenhc@lemote.com>
Signed-off-by: default avatarHuacai Chen <chenhc@lemote.com>
Reviewed-by: default avatarMarc Zyngier <maz@kernel.org>
Signed-off-by: default avatarThomas Bogendoerfer <tsbogend@alpha.franken.de>
parent dbb15226
Loading
Loading
Loading
Loading
+12 −2
Original line number Diff line number Diff line
@@ -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				has_lpc_irq_errata;
};

static void liointc_chained_handle_irq(struct irq_desc *desc)
@@ -54,8 +57,15 @@ static void liointc_chained_handle_irq(struct irq_desc *desc)

	pending = readl(gc->reg_base + LIOINTC_REG_INTC_STATUS);

	if (!pending)
	if (!pending) {
		/* Always blame LPC IRQ if we have that bug */
		if (handler->priv->has_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);