mcs814x: fix interrupt handling
authorJohn Crispin <john@openwrt.org>
Thu, 15 Oct 2015 14:38:14 +0000 (14:38 +0000)
committerJohn Crispin <john@openwrt.org>
Thu, 15 Oct 2015 14:38:14 +0000 (14:38 +0000)
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 <guenther.kelleter@devolo.de>
Backport of r46647

SVN-Revision: 47193

target/linux/mcs814x/files-3.18/arch/arm/mach-mcs814x/irq.c
target/linux/mcs814x/files-3.18/arch/arm/mach-mcs814x/timer.c

index f84c412839ad2acf66ab5a4bbc9f4185e3fc0cc1..d1cab682e4a37b21b561a55b73aa4566950d357f 100644 (file)
@@ -17,6 +17,7 @@
 #include <mach/mcs814x.h>
 
 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);
 
index ff9d44aa6ee27ede0e354cfcefe4998742c57ba0..31d0ba65a73d8348ef6c5225bce6f54a1f53adb2 100644 (file)
@@ -15,6 +15,7 @@
 #include <linux/io.h>
 #include <linux/of.h>
 #include <linux/of_address.h>
+#include <linux/of_irq.h>
 
 #include <asm/mach/time.h>
 #include <mach/mcs814x.h>
@@ -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);