diff options
author | Florian Fainelli <florian@openwrt.org> | 2015-01-10 20:12:02 +0000 |
---|---|---|
committer | Florian Fainelli <florian@openwrt.org> | 2015-01-10 20:12:02 +0000 |
commit | dd4ee63fa43cf13190891a5df62676054942b52e (patch) | |
tree | 961871e70f77414e4bc647923a07119390b4676e /target/linux/mcs814x/files-3.14/arch/arm/mach-mcs814x/irq.c | |
parent | 3b523f6780113b0f55a2362ab093145dfa2a7c75 (diff) | |
download | upstream-dd4ee63fa43cf13190891a5df62676054942b52e.tar.gz upstream-dd4ee63fa43cf13190891a5df62676054942b52e.tar.bz2 upstream-dd4ee63fa43cf13190891a5df62676054942b52e.zip |
mcs814x: add 3.14 kernel support
Signed-off-by: Florian Fainelli <florian@openwrt.org>
SVN-Revision: 43926
Diffstat (limited to 'target/linux/mcs814x/files-3.14/arch/arm/mach-mcs814x/irq.c')
-rw-r--r-- | target/linux/mcs814x/files-3.14/arch/arm/mach-mcs814x/irq.c | 89 |
1 files changed, 89 insertions, 0 deletions
diff --git a/target/linux/mcs814x/files-3.14/arch/arm/mach-mcs814x/irq.c b/target/linux/mcs814x/files-3.14/arch/arm/mach-mcs814x/irq.c new file mode 100644 index 0000000000..f84c412839 --- /dev/null +++ b/target/linux/mcs814x/files-3.14/arch/arm/mach-mcs814x/irq.c @@ -0,0 +1,89 @@ +/* + * Moschip MCS814x generic interrupt controller routines + * + * Copyright (C) 2012, Florian Fainelli <florian@openwrt.org> + * + * Licensed under the GPLv2 + */ +#include <linux/init.h> +#include <linux/irq.h> +#include <linux/io.h> +#include <linux/of.h> +#include <linux/of_address.h> +#include <linux/irqdomain.h> + +#include <asm/exception.h> +#include <asm/mach/irq.h> +#include <mach/mcs814x.h> + +static void __iomem *mcs814x_intc_base; + +static void __init mcs814x_alloc_gc(void __iomem *base, unsigned int irq_start, + unsigned int num) +{ + 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 (!gc) + panic("unable to allocate generic irq chip"); + + ct = gc->chip_types; + ct->chip.irq_ack = irq_gc_unmask_enable_reg; + ct->chip.irq_mask = irq_gc_mask_clr_bit; + ct->chip.irq_unmask = irq_gc_mask_set_bit; + 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); +} + +asmlinkage void __exception_irq_entry mcs814x_handle_irq(struct pt_regs *regs) +{ + u32 status, irq; + + do { + /* read the status register */ + status = __raw_readl(mcs814x_intc_base + MCS814X_IRQ_STS0); + if (!status) + break; + + irq = ffs(status) - 1; + status |= (1 << irq); + /* clear the interrupt */ + __raw_writel(status, mcs814x_intc_base + MCS814X_IRQ_STS0); + /* call the generic handler */ + handle_IRQ(irq, regs); + + } while (1); +} + +static const struct of_device_id mcs814x_intc_ids[] = { + { .compatible = "moschip,mcs814x-intc" }, + { /* sentinel */ }, +}; + +void __init mcs814x_of_irq_init(void) +{ + struct device_node *np; + + np = of_find_matching_node(NULL, mcs814x_intc_ids); + if (!np) + panic("unable to find compatible intc node in dtb\n"); + + mcs814x_intc_base = of_iomap(np, 0); + if (!mcs814x_intc_base) + panic("unable to map intc cpu registers\n"); + + irq_domain_add_simple(np, 32, 0, &irq_generic_chip_ops, NULL); + + of_node_put(np); + + mcs814x_alloc_gc(mcs814x_intc_base, 0, 32); +} + |