Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit ec79b577 authored by Thomas Gleixner's avatar Thomas Gleixner
Browse files

Merge tag 'irqchip-mvebu-fixes-3.14' of git://git.infradead.org/linux-mvebu into irq/urgent



irqchip mvebu fixes for v3.14

 - orion:
    - fixes for clearing bridge cause register, and clearing stale interrupts

Signed-off-by: default avatarThomas Gleixner <tglx@linutronix.de>
parents 2c45aada d86e9af6
Loading
Loading
Loading
Loading
+19 −3
Original line number Original line Diff line number Diff line
@@ -111,7 +111,8 @@ IRQCHIP_DECLARE(orion_intc, "marvell,orion-intc", orion_irq_init);
static void orion_bridge_irq_handler(unsigned int irq, struct irq_desc *desc)
static void orion_bridge_irq_handler(unsigned int irq, struct irq_desc *desc)
{
{
	struct irq_domain *d = irq_get_handler_data(irq);
	struct irq_domain *d = irq_get_handler_data(irq);
	struct irq_chip_generic *gc = irq_get_domain_generic_chip(d, irq);

	struct irq_chip_generic *gc = irq_get_domain_generic_chip(d, 0);
	u32 stat = readl_relaxed(gc->reg_base + ORION_BRIDGE_IRQ_CAUSE) &
	u32 stat = readl_relaxed(gc->reg_base + ORION_BRIDGE_IRQ_CAUSE) &
		   gc->mask_cache;
		   gc->mask_cache;


@@ -123,6 +124,19 @@ static void orion_bridge_irq_handler(unsigned int irq, struct irq_desc *desc)
	}
	}
}
}


/*
 * Bridge IRQ_CAUSE is asserted regardless of IRQ_MASK register.
 * To avoid interrupt events on stale irqs, we clear them before unmask.
 */
static unsigned int orion_bridge_irq_startup(struct irq_data *d)
{
	struct irq_chip_type *ct = irq_data_get_chip_type(d);

	ct->chip.irq_ack(d);
	ct->chip.irq_unmask(d);
	return 0;
}

static int __init orion_bridge_irq_init(struct device_node *np,
static int __init orion_bridge_irq_init(struct device_node *np,
					struct device_node *parent)
					struct device_node *parent)
{
{
@@ -143,7 +157,7 @@ static int __init orion_bridge_irq_init(struct device_node *np,
	}
	}


	ret = irq_alloc_domain_generic_chips(domain, nrirqs, 1, np->name,
	ret = irq_alloc_domain_generic_chips(domain, nrirqs, 1, np->name,
			     handle_level_irq, clr, 0, IRQ_GC_INIT_MASK_CACHE);
			     handle_edge_irq, clr, 0, IRQ_GC_INIT_MASK_CACHE);
	if (ret) {
	if (ret) {
		pr_err("%s: unable to alloc irq domain gc\n", np->name);
		pr_err("%s: unable to alloc irq domain gc\n", np->name);
		return ret;
		return ret;
@@ -176,12 +190,14 @@ static int __init orion_bridge_irq_init(struct device_node *np,


	gc->chip_types[0].regs.ack = ORION_BRIDGE_IRQ_CAUSE;
	gc->chip_types[0].regs.ack = ORION_BRIDGE_IRQ_CAUSE;
	gc->chip_types[0].regs.mask = ORION_BRIDGE_IRQ_MASK;
	gc->chip_types[0].regs.mask = ORION_BRIDGE_IRQ_MASK;
	gc->chip_types[0].chip.irq_startup = orion_bridge_irq_startup;
	gc->chip_types[0].chip.irq_ack = irq_gc_ack_clr_bit;
	gc->chip_types[0].chip.irq_ack = irq_gc_ack_clr_bit;
	gc->chip_types[0].chip.irq_mask = irq_gc_mask_clr_bit;
	gc->chip_types[0].chip.irq_mask = irq_gc_mask_clr_bit;
	gc->chip_types[0].chip.irq_unmask = irq_gc_mask_set_bit;
	gc->chip_types[0].chip.irq_unmask = irq_gc_mask_set_bit;


	/* mask all interrupts */
	/* mask and clear all interrupts */
	writel(0, gc->reg_base + ORION_BRIDGE_IRQ_MASK);
	writel(0, gc->reg_base + ORION_BRIDGE_IRQ_MASK);
	writel(0, gc->reg_base + ORION_BRIDGE_IRQ_CAUSE);


	irq_set_handler_data(irq, domain);
	irq_set_handler_data(irq, domain);
	irq_set_chained_handler(irq, orion_bridge_irq_handler);
	irq_set_chained_handler(irq, orion_bridge_irq_handler);