From 4a67355de6a807ca3a679d445d4ed2403e78eb28 Mon Sep 17 00:00:00 2001 From: John Crispin Date: Thu, 15 Oct 2015 14:38:14 +0000 Subject: [PATCH] mcs814x: fix interrupt handling MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit Switch to generich chip irqs/irq domains. Interrupts were broken since kernel 3.14. dLAN USB extender is now booting again. Signed-off-by: Günther Kelleter Backport of r46647 SVN-Revision: 47193 --- .../files-3.18/arch/arm/mach-mcs814x/irq.c | 21 ++++++++------ .../files-3.18/arch/arm/mach-mcs814x/timer.c | 28 +++++++++---------- 2 files changed, 27 insertions(+), 22 deletions(-) diff --git a/target/linux/mcs814x/files-3.18/arch/arm/mach-mcs814x/irq.c b/target/linux/mcs814x/files-3.18/arch/arm/mach-mcs814x/irq.c index f84c412839..d1cab682e4 100644 --- a/target/linux/mcs814x/files-3.18/arch/arm/mach-mcs814x/irq.c +++ b/target/linux/mcs814x/files-3.18/arch/arm/mach-mcs814x/irq.c @@ -17,6 +17,7 @@ #include static void __iomem *mcs814x_intc_base; +static struct irq_domain *domain; static void __init mcs814x_alloc_gc(void __iomem *base, unsigned int irq_start, unsigned int num) @@ -24,11 +25,15 @@ static void __init mcs814x_alloc_gc(void __iomem *base, unsigned int irq_start, struct irq_chip_generic *gc; struct irq_chip_type *ct; - gc = irq_alloc_generic_chip("mcs814x-intc", 1, - irq_start, base, handle_level_irq); + if (irq_alloc_domain_generic_chips(domain, num, 1, "mcs814x-intc", handle_level_irq, + IRQ_GC_INIT_MASK_CACHE, IRQ_NOREQUEST, 0)) + panic("unable to allocate domain generic irq chip"); + + gc = irq_get_domain_generic_chip(domain, irq_start); if (!gc) - panic("unable to allocate generic irq chip"); + panic("unable to get generic irq chip"); + gc->reg_base = base; ct = gc->chip_types; ct->chip.irq_ack = irq_gc_unmask_enable_reg; ct->chip.irq_mask = irq_gc_mask_clr_bit; @@ -36,9 +41,6 @@ static void __init mcs814x_alloc_gc(void __iomem *base, unsigned int irq_start, ct->regs.mask = MCS814X_IRQ_MASK; ct->regs.enable = MCS814X_IRQ_ICR; - irq_setup_generic_chip(gc, IRQ_MSK(num), IRQ_GC_INIT_MASK_CACHE, - IRQ_NOREQUEST, 0); - /* Clear all interrupts */ writel_relaxed(0xffffffff, base + MCS814X_IRQ_ICR); } @@ -58,7 +60,7 @@ asmlinkage void __exception_irq_entry mcs814x_handle_irq(struct pt_regs *regs) /* clear the interrupt */ __raw_writel(status, mcs814x_intc_base + MCS814X_IRQ_STS0); /* call the generic handler */ - handle_IRQ(irq, regs); + handle_domain_irq(domain, irq, regs); } while (1); } @@ -80,7 +82,10 @@ void __init mcs814x_of_irq_init(void) if (!mcs814x_intc_base) panic("unable to map intc cpu registers\n"); - irq_domain_add_simple(np, 32, 0, &irq_generic_chip_ops, NULL); + domain = irq_domain_add_linear(np, 32, &irq_generic_chip_ops, NULL); + if (!domain) + panic("unable to add irq domain\n"); + irq_set_default_host(domain); of_node_put(np); diff --git a/target/linux/mcs814x/files-3.18/arch/arm/mach-mcs814x/timer.c b/target/linux/mcs814x/files-3.18/arch/arm/mach-mcs814x/timer.c index ff9d44aa6e..31d0ba65a7 100644 --- a/target/linux/mcs814x/files-3.18/arch/arm/mach-mcs814x/timer.c +++ b/target/linux/mcs814x/files-3.18/arch/arm/mach-mcs814x/timer.c @@ -15,6 +15,7 @@ #include #include #include +#include #include #include @@ -71,21 +72,15 @@ static irqreturn_t mcs814x_timer_interrupt(int irq, void *dev_id) return IRQ_HANDLED; } -static struct irqaction mcs814x_timer_irq = { - .name = "mcs814x-timer", - .flags = IRQF_DISABLED | IRQF_TIMER | IRQF_IRQPOLL, - .handler = mcs814x_timer_interrupt, -}; - static struct of_device_id mcs814x_timer_ids[] = { { .compatible = "moschip,mcs814x-timer" }, { /* sentinel */ }, }; -static void __init mcs814x_of_timer_init(void) +static int __init mcs814x_of_timer_init(void) { struct device_node *np; - const unsigned int *intspec; + int irq; np = of_find_matching_node(NULL, mcs814x_timer_ids); if (!np) @@ -95,16 +90,17 @@ static void __init mcs814x_of_timer_init(void) if (!mcs814x_timer_base) panic("unable to remap timer cpu registers"); - intspec = of_get_property(np, "interrupts", NULL); - if (!intspec) - panic("no interrupts property for timer"); + irq = irq_of_parse_and_map(np, 0); + if (!irq) + panic("no interrupts property/mapping failed for timer"); - mcs814x_timer_irq.irq = be32_to_cpup(intspec); + return irq; } void __init mcs814x_timer_init(void) { struct clk *clk; + int irq; arch_gettimeoffset = mcs814x_gettimeoffset; @@ -114,7 +110,7 @@ void __init mcs814x_timer_init(void) clock_rate = clk_get_rate(clk); - mcs814x_of_timer_init(); + irq = mcs814x_of_timer_init(); pr_info("Timer frequency: %d (kHz)\n", clock_rate / 1000); @@ -125,7 +121,11 @@ void __init mcs814x_timer_init(void) writel_relaxed(timer_reload_value, mcs814x_timer_base + TIMER_VAL); last_reload = timer_reload_value; - setup_irq(mcs814x_timer_irq.irq, &mcs814x_timer_irq); + if (request_irq(irq, mcs814x_timer_interrupt, + IRQF_DISABLED | IRQF_TIMER | IRQF_IRQPOLL, + "mcs814x-timer", NULL)) + panic("unable to request timer0 irq %d", irq); + /* enable timer, stop timer in debug mode */ writel_relaxed(TIMER_CTL_EN | TIMER_CTL_DBG, mcs814x_timer_base + TIMER_CTL); -- 2.30.2