summaryrefslogtreecommitdiffstats
path: root/target/linux/mcs814x/files-3.3/arch/arm/mach-mcs814x/irq.c
diff options
context:
space:
mode:
authorFlorian Fainelli <florian@openwrt.org>2012-06-19 14:48:56 +0000
committerFlorian Fainelli <florian@openwrt.org>2012-06-19 14:48:56 +0000
commitf4afa00862b7db8a2da8c012843a286716c0a534 (patch)
tree9c15efab8fd398654de98648e07f26c51d6eec66 /target/linux/mcs814x/files-3.3/arch/arm/mach-mcs814x/irq.c
parent7c87391c55a713a9ef9df169ab23e79177184b1a (diff)
downloadmaster-31e0f0ae-f4afa00862b7db8a2da8c012843a286716c0a534.tar.gz
master-31e0f0ae-f4afa00862b7db8a2da8c012843a286716c0a534.tar.bz2
master-31e0f0ae-f4afa00862b7db8a2da8c012843a286716c0a534.zip
add Moschip MSC814x support
This target currently only supports Moschip's MCS8140 SoC, but support for other chips in the same family (MCS8142, MCS8144) will be easy to add. Target support is entirely using Device Tree for probing peripherals. Drivers support include: - PCI - USB 1 & 2 - watchdog - random number generator - UART - timer - internal Ethernet PHY - Ethernet MAC core Support for the following boards is included using Device Tree - Devolo dLAN USB Extender - Tigal RBT-832 SVN-Revision: 32462
Diffstat (limited to 'target/linux/mcs814x/files-3.3/arch/arm/mach-mcs814x/irq.c')
-rw-r--r--target/linux/mcs814x/files-3.3/arch/arm/mach-mcs814x/irq.c93
1 files changed, 93 insertions, 0 deletions
diff --git a/target/linux/mcs814x/files-3.3/arch/arm/mach-mcs814x/irq.c b/target/linux/mcs814x/files-3.3/arch/arm/mach-mcs814x/irq.c
new file mode 100644
index 0000000000..cf86734afb
--- /dev/null
+++ b/target/linux/mcs814x/files-3.3/arch/arm/mach-mcs814x/irq.c
@@ -0,0 +1,93 @@
+/*
+ * 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>
+
+#define MCS814X_IRQ_ICR 0x00
+#define MCS814X_IRQ_ISR 0x04
+#define MCS814X_IRQ_MASK 0x20
+#define MCS814X_IRQ_STS0 0x40
+
+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 */
+ __raw_writel(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_ICR);
+ /* 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, 0);
+
+ of_node_put(np);
+
+ mcs814x_alloc_gc(mcs814x_intc_base, 0, 32);
+}
+