]> git.karo-electronics.de Git - karo-tx-linux.git/commitdiff
ARM: sirf: move irq driver to drivers/irqchip
authorArnd Bergmann <arnd@arndb.de>
Tue, 19 Mar 2013 10:21:44 +0000 (11:21 +0100)
committerArnd Bergmann <arnd@arndb.de>
Mon, 25 Mar 2013 11:29:39 +0000 (12:29 +0100)
This updates the irqchip drier for prima2 to the current practices by
moving it into drivers/irqchip and integrating it into the irqchip_init
infrastructure. We also now use a linear irq domain as a preparation
for sparse IRQ suport.

Signed-off-by: Arnd Bergmann <arnd@arndb.de>
Cc: Thomas Gleixner <tglx@linutronix.de>
arch/arm/mach-prima2/Makefile
arch/arm/mach-prima2/common.c
arch/arm/mach-prima2/irq.c [deleted file]
drivers/irqchip/Makefile
drivers/irqchip/irq-sirfsoc.c [new file with mode: 0644]

index bfe360cbd1774e27ba80d849273cf5be571f9248..5fdff7e322907399d0c2824f63667067ac28a411 100644 (file)
@@ -4,7 +4,6 @@ obj-y += rtciobrg.o
 obj-$(CONFIG_DEBUG_LL) += lluart.o
 obj-$(CONFIG_CACHE_L2X0) += l2x0.o
 obj-$(CONFIG_SUSPEND) += pm.o sleep.o
-obj-$(CONFIG_SIRF_IRQ) += irq.o
 obj-$(CONFIG_SMP) += platsmp.o headsmp.o
 obj-$(CONFIG_HOTPLUG_CPU)  += hotplug.o
 obj-$(CONFIG_ARCH_PRIMA2) += timer-prima2.o
index 72efb4ff2803c37e0ffc348d549eeababcdc1e55..15c14dfb47a0e213624fc44de702266ff0f77dad 100644 (file)
@@ -46,11 +46,8 @@ static const char *atlas6_dt_match[] __initdata = {
 DT_MACHINE_START(ATLAS6_DT, "Generic ATLAS6 (Flattened Device Tree)")
        /* Maintainer: Barry Song <baohua.song@csr.com> */
        .map_io         = sirfsoc_map_io,
-       .init_irq       = sirfsoc_of_irq_init,
+       .init_irq       = irqchip_init,
        .init_time      = sirfsoc_prima2_timer_init,
-#ifdef CONFIG_MULTI_IRQ_HANDLER
-       .handle_irq     = sirfsoc_handle_irq,
-#endif
        .init_machine   = sirfsoc_mach_init,
        .init_late      = sirfsoc_init_late,
        .dt_compat      = atlas6_dt_match,
@@ -67,11 +64,8 @@ static const char *prima2_dt_match[] __initdata = {
 DT_MACHINE_START(PRIMA2_DT, "Generic PRIMA2 (Flattened Device Tree)")
        /* Maintainer: Barry Song <baohua.song@csr.com> */
        .map_io         = sirfsoc_map_io,
-       .init_irq       = sirfsoc_of_irq_init,
+       .init_irq       = irqchip_init,
        .init_time      = sirfsoc_prima2_timer_init,
-#ifdef CONFIG_MULTI_IRQ_HANDLER
-       .handle_irq     = sirfsoc_handle_irq,
-#endif
        .dma_zone_size  = SZ_256M,
        .init_machine   = sirfsoc_mach_init,
        .init_late      = sirfsoc_init_late,
diff --git a/arch/arm/mach-prima2/irq.c b/arch/arm/mach-prima2/irq.c
deleted file mode 100644 (file)
index 6c0f3e9..0000000
+++ /dev/null
@@ -1,129 +0,0 @@
-/*
- * interrupt controller support for CSR SiRFprimaII
- *
- * Copyright (c) 2011 Cambridge Silicon Radio Limited, a CSR plc group company.
- *
- * Licensed under GPLv2 or later.
- */
-
-#include <linux/init.h>
-#include <linux/io.h>
-#include <linux/irq.h>
-#include <linux/of.h>
-#include <linux/of_address.h>
-#include <linux/irqdomain.h>
-#include <linux/syscore_ops.h>
-#include <asm/mach/irq.h>
-#include <asm/exception.h>
-#include <mach/hardware.h>
-
-#define SIRFSOC_INT_RISC_MASK0          0x0018
-#define SIRFSOC_INT_RISC_MASK1          0x001C
-#define SIRFSOC_INT_RISC_LEVEL0         0x0020
-#define SIRFSOC_INT_RISC_LEVEL1         0x0024
-#define SIRFSOC_INIT_IRQ_ID            0x0038
-
-void __iomem *sirfsoc_intc_base;
-
-static __init void
-sirfsoc_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("SIRFINTC", 1, irq_start, base, handle_level_irq);
-       ct = gc->chip_types;
-
-       ct->chip.irq_mask = irq_gc_mask_clr_bit;
-       ct->chip.irq_unmask = irq_gc_mask_set_bit;
-       ct->regs.mask = SIRFSOC_INT_RISC_MASK0;
-
-       irq_setup_generic_chip(gc, IRQ_MSK(num), IRQ_GC_INIT_MASK_CACHE, IRQ_NOREQUEST, 0);
-}
-
-static __init void sirfsoc_irq_init(void)
-{
-       sirfsoc_alloc_gc(sirfsoc_intc_base, 0, 32);
-       sirfsoc_alloc_gc(sirfsoc_intc_base + 4, 32,
-                       SIRFSOC_INTENAL_IRQ_END + 1 - 32);
-
-       writel_relaxed(0, sirfsoc_intc_base + SIRFSOC_INT_RISC_LEVEL0);
-       writel_relaxed(0, sirfsoc_intc_base + SIRFSOC_INT_RISC_LEVEL1);
-
-       writel_relaxed(0, sirfsoc_intc_base + SIRFSOC_INT_RISC_MASK0);
-       writel_relaxed(0, sirfsoc_intc_base + SIRFSOC_INT_RISC_MASK1);
-}
-
-asmlinkage void __exception_irq_entry sirfsoc_handle_irq(struct pt_regs *regs)
-{
-       u32 irqstat, irqnr;
-
-       irqstat = readl_relaxed(sirfsoc_intc_base + SIRFSOC_INIT_IRQ_ID);
-       irqnr = irqstat & 0xff;
-
-       handle_IRQ(irqnr, regs);
-}
-
-static struct of_device_id intc_ids[]  = {
-       { .compatible = "sirf,prima2-intc" },
-       {},
-};
-
-void __init sirfsoc_of_irq_init(void)
-{
-       struct device_node *np;
-
-       np = of_find_matching_node(NULL, intc_ids);
-       if (!np)
-               return;
-
-       sirfsoc_intc_base = of_iomap(np, 0);
-       if (!sirfsoc_intc_base)
-               panic("unable to map intc cpu registers\n");
-
-       irq_domain_add_legacy(np, SIRFSOC_INTENAL_IRQ_END + 1, 0, 0,
-               &irq_domain_simple_ops, NULL);
-
-       of_node_put(np);
-
-       sirfsoc_irq_init();
-}
-
-struct sirfsoc_irq_status {
-       u32 mask0;
-       u32 mask1;
-       u32 level0;
-       u32 level1;
-};
-
-static struct sirfsoc_irq_status sirfsoc_irq_st;
-
-static int sirfsoc_irq_suspend(void)
-{
-       sirfsoc_irq_st.mask0 = readl_relaxed(sirfsoc_intc_base + SIRFSOC_INT_RISC_MASK0);
-       sirfsoc_irq_st.mask1 = readl_relaxed(sirfsoc_intc_base + SIRFSOC_INT_RISC_MASK1);
-       sirfsoc_irq_st.level0 = readl_relaxed(sirfsoc_intc_base + SIRFSOC_INT_RISC_LEVEL0);
-       sirfsoc_irq_st.level1 = readl_relaxed(sirfsoc_intc_base + SIRFSOC_INT_RISC_LEVEL1);
-
-       return 0;
-}
-
-static void sirfsoc_irq_resume(void)
-{
-       writel_relaxed(sirfsoc_irq_st.mask0, sirfsoc_intc_base + SIRFSOC_INT_RISC_MASK0);
-       writel_relaxed(sirfsoc_irq_st.mask1, sirfsoc_intc_base + SIRFSOC_INT_RISC_MASK1);
-       writel_relaxed(sirfsoc_irq_st.level0, sirfsoc_intc_base + SIRFSOC_INT_RISC_LEVEL0);
-       writel_relaxed(sirfsoc_irq_st.level1, sirfsoc_intc_base + SIRFSOC_INT_RISC_LEVEL1);
-}
-
-static struct syscore_ops sirfsoc_irq_syscore_ops = {
-       .suspend        = sirfsoc_irq_suspend,
-       .resume         = sirfsoc_irq_resume,
-};
-
-static int __init sirfsoc_irq_pm_init(void)
-{
-       register_syscore_ops(&sirfsoc_irq_syscore_ops);
-       return 0;
-}
-device_initcall(sirfsoc_irq_pm_init);
index 98e3b87bdf1b48761df4320a9c588af26f38bb2c..5cb6bd24d8bf8f70b6d49705a5beae1befb6416a 100644 (file)
@@ -8,4 +8,5 @@ obj-$(CONFIG_ARCH_SUNXI)                += irq-sunxi.o
 obj-$(CONFIG_ARCH_SPEAR3XX)            += spear-shirq.o
 obj-$(CONFIG_ARM_GIC)                  += irq-gic.o
 obj-$(CONFIG_ARM_VIC)                  += irq-vic.o
+obj-$(CONFIG_SIRF_IRQ)                 += irq-sirfsoc.o
 obj-$(CONFIG_VERSATILE_FPGA_IRQ)       += irq-versatile-fpga.o
diff --git a/drivers/irqchip/irq-sirfsoc.c b/drivers/irqchip/irq-sirfsoc.c
new file mode 100644 (file)
index 0000000..69ea44e
--- /dev/null
@@ -0,0 +1,126 @@
+/*
+ * interrupt controller support for CSR SiRFprimaII
+ *
+ * Copyright (c) 2011 Cambridge Silicon Radio Limited, a CSR plc group company.
+ *
+ * Licensed under GPLv2 or later.
+ */
+
+#include <linux/init.h>
+#include <linux/io.h>
+#include <linux/irq.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include <linux/irqdomain.h>
+#include <linux/syscore_ops.h>
+#include <asm/mach/irq.h>
+#include <asm/exception.h>
+#include "irqchip.h"
+
+#define SIRFSOC_INT_RISC_MASK0          0x0018
+#define SIRFSOC_INT_RISC_MASK1          0x001C
+#define SIRFSOC_INT_RISC_LEVEL0         0x0020
+#define SIRFSOC_INT_RISC_LEVEL1         0x0024
+#define SIRFSOC_INIT_IRQ_ID            0x0038
+
+#define SIRFSOC_NUM_IRQS               128
+
+static struct irq_domain *sirfsoc_irqdomain;
+
+static __init void
+sirfsoc_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("SIRFINTC", 1, irq_start, base, handle_level_irq);
+       ct = gc->chip_types;
+
+       ct->chip.irq_mask = irq_gc_mask_clr_bit;
+       ct->chip.irq_unmask = irq_gc_mask_set_bit;
+       ct->regs.mask = SIRFSOC_INT_RISC_MASK0;
+
+       irq_setup_generic_chip(gc, IRQ_MSK(num), IRQ_GC_INIT_MASK_CACHE, IRQ_NOREQUEST, 0);
+}
+
+static asmlinkage void __exception_irq_entry sirfsoc_handle_irq(struct pt_regs *regs)
+{
+       void __iomem *base = sirfsoc_irqdomain->host_data;
+       u32 irqstat, irqnr;
+
+       irqstat = readl_relaxed(base + SIRFSOC_INIT_IRQ_ID);
+       irqnr = irq_find_mapping(sirfsoc_irqdomain, irqstat & 0xff);
+
+       handle_IRQ(irqnr, regs);
+}
+
+static int __init sirfsoc_irq_init(struct device_node *np, struct device_node *parent)
+{
+       void __iomem *base = of_iomap(np, 0);
+       if (!base)
+               panic("unable to map intc cpu registers\n");
+
+       /* using legacy because irqchip_generic does not work with linear */
+       sirfsoc_irqdomain = irq_domain_add_legacy(np, SIRFSOC_NUM_IRQS, 0, 0,
+                                &irq_domain_simple_ops, base);
+
+       sirfsoc_alloc_gc(base, 0, 32);
+       sirfsoc_alloc_gc(base + 4, 32, SIRFSOC_NUM_IRQS - 32);
+
+       writel_relaxed(0, base + SIRFSOC_INT_RISC_LEVEL0);
+       writel_relaxed(0, base + SIRFSOC_INT_RISC_LEVEL1);
+
+       writel_relaxed(0, base + SIRFSOC_INT_RISC_MASK0);
+       writel_relaxed(0, base + SIRFSOC_INT_RISC_MASK1);
+
+       set_handle_irq(sirfsoc_handle_irq);
+
+       return 0;
+}
+IRQCHIP_DECLARE(sirfsoc_intc, "sirf,prima2-intc", sirfsoc_irq_init);
+
+struct sirfsoc_irq_status {
+       u32 mask0;
+       u32 mask1;
+       u32 level0;
+       u32 level1;
+};
+
+static struct sirfsoc_irq_status sirfsoc_irq_st;
+
+static int sirfsoc_irq_suspend(void)
+{
+       void __iomem *base = sirfsoc_irqdomain->host_data;
+
+       sirfsoc_irq_st.mask0 = readl_relaxed(base + SIRFSOC_INT_RISC_MASK0);
+       sirfsoc_irq_st.mask1 = readl_relaxed(base + SIRFSOC_INT_RISC_MASK1);
+       sirfsoc_irq_st.level0 = readl_relaxed(base + SIRFSOC_INT_RISC_LEVEL0);
+       sirfsoc_irq_st.level1 = readl_relaxed(base + SIRFSOC_INT_RISC_LEVEL1);
+
+       return 0;
+}
+
+static void sirfsoc_irq_resume(void)
+{
+       void __iomem *base = sirfsoc_irqdomain->host_data;
+
+       writel_relaxed(sirfsoc_irq_st.mask0, base + SIRFSOC_INT_RISC_MASK0);
+       writel_relaxed(sirfsoc_irq_st.mask1, base + SIRFSOC_INT_RISC_MASK1);
+       writel_relaxed(sirfsoc_irq_st.level0, base + SIRFSOC_INT_RISC_LEVEL0);
+       writel_relaxed(sirfsoc_irq_st.level1, base + SIRFSOC_INT_RISC_LEVEL1);
+}
+
+static struct syscore_ops sirfsoc_irq_syscore_ops = {
+       .suspend        = sirfsoc_irq_suspend,
+       .resume         = sirfsoc_irq_resume,
+};
+
+static int __init sirfsoc_irq_pm_init(void)
+{
+       if (!sirfsoc_irqdomain)
+               return 0;
+
+       register_syscore_ops(&sirfsoc_irq_syscore_ops);
+       return 0;
+}
+device_initcall(sirfsoc_irq_pm_init);