Merge tag 'irq-s3c24xx-for-v3.10' of git://git.kernel.org/pub/scm/linux/kernel/git...
authorArnd Bergmann <arnd@arndb.de>
Tue, 9 Apr 2013 20:05:50 +0000 (22:05 +0200)
committerArnd Bergmann <arnd@arndb.de>
Tue, 9 Apr 2013 20:05:50 +0000 (22:05 +0200)
From Kukjin Kim <kgene.kim@samsung.com>:

s3c24xx irq cleanup and move into drivers/irqchip

* tag 'irq-s3c24xx-for-v3.10' of git://git.kernel.org/pub/scm/linux/kernel/git/kgene/linux-samsung:
  irqchip: s3c24xx: add devicetree support
  irqchip: s3c24xx: make interrupt handling independent of irq_domain structure
  irqchip: s3c24xx: globally keep track of the created intc instances
  irqchip: s3c24xx: add irq_set_type callback for basic interrupt types
  irqchip: s3c24xx: fix irqlist of second s3c2416 controller
  irqchip: s3c24xx: fix comments on some camera interrupts
  ARM: S3C24XX: move irq driver to drivers/irqchip
  ARM: S3C24XX: add handle_irq function
  ARM: S3C24XX: make s3c24xx_init_intc static
  ARM: S3C24XX: move s3c24xx_init_irq to s3c2410_init_irq
  ARM: S3C24XX: fix irq parent check
  ARM: S3C24XX: fix redundant checks in the irq mapping function

Signed-off-by: Arnd Bergmann <arnd@arndb.de>
18 files changed:
Documentation/devicetree/bindings/interrupt-controller/samsung,s3c24xx-irq.txt [new file with mode: 0644]
arch/arm/Kconfig
arch/arm/mach-s3c24xx/Makefile
arch/arm/mach-s3c24xx/common.h
arch/arm/mach-s3c24xx/include/mach/entry-macro.S [deleted file]
arch/arm/mach-s3c24xx/irq.c [deleted file]
arch/arm/mach-s3c24xx/mach-amlm5900.c
arch/arm/mach-s3c24xx/mach-bast.c
arch/arm/mach-s3c24xx/mach-h1940.c
arch/arm/mach-s3c24xx/mach-n30.c
arch/arm/mach-s3c24xx/mach-otom.c
arch/arm/mach-s3c24xx/mach-qt2410.c
arch/arm/mach-s3c24xx/mach-smdk2410.c
arch/arm/mach-s3c24xx/mach-tct_hammer.c
arch/arm/mach-s3c24xx/mach-vr1000.c
arch/arm/plat-samsung/include/plat/cpu.h
drivers/irqchip/Makefile
drivers/irqchip/irq-s3c24xx.c [new file with mode: 0644]

diff --git a/Documentation/devicetree/bindings/interrupt-controller/samsung,s3c24xx-irq.txt b/Documentation/devicetree/bindings/interrupt-controller/samsung,s3c24xx-irq.txt
new file mode 100644 (file)
index 0000000..c54c5a9
--- /dev/null
@@ -0,0 +1,53 @@
+Samsung S3C24XX Interrupt Controllers
+
+The S3C24XX SoCs contain a custom set of interrupt controllers providing a
+varying number of interrupt sources. The set consists of a main- and sub-
+controller and on newer SoCs even a second main controller.
+
+Required properties:
+- compatible: Compatible property value should be "samsung,s3c2410-irq"
+  for machines before s3c2416 and "samsung,s3c2416-irq" for s3c2416 and later.
+
+- reg: Physical base address of the controller and length of memory mapped
+  region.
+
+- interrupt-controller : Identifies the node as an interrupt controller
+
+- #interrupt-cells : Specifies the number of cells needed to encode an
+  interrupt source. The value shall be 4 and interrupt descriptor shall
+  have the following format:
+      <ctrl_num parent_irq ctrl_irq type>
+
+  ctrl_num contains the controller to use:
+      - 0 ... main controller
+      - 1 ... sub controller
+      - 2 ... second main controller on s3c2416 and s3c2450
+  parent_irq contains the parent bit in the main controller and will be
+             ignored in main controllers
+  ctrl_irq contains the interrupt bit of the controller
+  type contains the trigger type to use
+
+Example:
+
+       interrupt-controller@4a000000 {
+               compatible = "samsung,s3c2410-irq";
+               reg = <0x4a000000 0x100>;
+               interrupt-controller;
+               #interrupt-cells=<4>;
+       };
+
+       [...]
+
+       serial@50000000 {
+               compatible = "samsung,s3c2410-uart";
+               reg = <0x50000000 0x4000>;
+               interrupt-parent = <&subintc>;
+               interrupts = <1 28 0 4>, <1 28 1 4>;
+       };
+
+       rtc@57000000 {
+               compatible = "samsung,s3c2410-rtc";
+               reg = <0x57000000 0x100>;
+               interrupt-parent = <&intc>;
+               interrupts = <0 30 0 3>, <0 8 0 3>;
+       };
index ada582b15cf2cbe2e3d1aaaa9eb88416249440ba..6adf79869f8c4b9dca88a8dcced278770c88d93c 100644 (file)
@@ -778,6 +778,7 @@ config ARCH_S3C24XX
        select HAVE_S3C2410_I2C if I2C
        select HAVE_S3C2410_WATCHDOG if WATCHDOG
        select HAVE_S3C_RTC if RTC_CLASS
+       select MULTI_IRQ_HANDLER
        select NEED_MACH_GPIO_H
        select NEED_MACH_IO_H
        help
index be6e4d0e6f1aa6acdfe4abbac1cd5f4d851c8a28..6f46ecfc83967ce893ad63a01d23ca8ac498e908 100644 (file)
@@ -14,7 +14,7 @@ obj-                          :=
 
 # core
 
-obj-y                          += common.o irq.o
+obj-y                          += common.o
 
 obj-$(CONFIG_CPU_S3C2410)      += s3c2410.o
 obj-$(CONFIG_S3C2410_CPUFREQ)  += cpufreq-s3c2410.o
index abefeb38bba4dbcdc150079bc19505912d3538ea..307c3714be55d43de2b8e4b65f92fbf3a7ea2e22 100644 (file)
@@ -21,6 +21,7 @@ extern void s3c2410_map_io(void);
 extern void s3c2410_init_uarts(struct s3c2410_uartcfg *cfg, int no);
 extern void s3c2410_init_clocks(int xtal);
 extern void s3c2410_restart(char mode, const char *cmd);
+extern void s3c2410_init_irq(void);
 #else
 #define s3c2410_init_clocks NULL
 #define s3c2410_init_uarts NULL
diff --git a/arch/arm/mach-s3c24xx/include/mach/entry-macro.S b/arch/arm/mach-s3c24xx/include/mach/entry-macro.S
deleted file mode 100644 (file)
index 6a21bee..0000000
+++ /dev/null
@@ -1,70 +0,0 @@
-/*
- * arch/arm/mach-s3c2410/include/mach/entry-macro.S
- *
- * Low-level IRQ helper macros for S3C2410-based platforms
- *
- * This file is licensed under  the terms of the GNU General Public
- * License version 2. This program is licensed "as is" without any
- * warranty of any kind, whether express or implied.
-*/
-
-/* We have a problem that the INTOFFSET register does not always
- * show one interrupt. Occasionally we get two interrupts through
- * the prioritiser, and this causes the INTOFFSET register to show
- * what looks like the logical-or of the two interrupt numbers.
- *
- * Thanks to Klaus, Shannon, et al for helping to debug this problem
-*/
-
-#define INTPND         (0x10)
-#define INTOFFSET      (0x14)
-
-#include <mach/hardware.h>
-#include <asm/irq.h>
-
-       .macro  get_irqnr_preamble, base, tmp
-       .endm
-
-       .macro  get_irqnr_and_base, irqnr, irqstat, base, tmp
-
-               mov     \base, #S3C24XX_VA_IRQ
-
-               @@ try the interrupt offset register, since it is there
-
-               ldr     \irqstat, [\base, #INTPND ]
-               teq     \irqstat, #0
-               beq     1002f
-               ldr     \irqnr, [\base, #INTOFFSET ]
-               mov     \tmp, #1
-               tst     \irqstat, \tmp, lsl \irqnr
-               bne     1001f
-
-               @@ the number specified is not a valid irq, so try
-               @@ and work it out for ourselves
-
-               mov     \irqnr, #0              @@ start here
-
-               @@ work out which irq (if any) we got
-
-               movs    \tmp, \irqstat, lsl#16
-               addeq   \irqnr, \irqnr, #16
-               moveq   \irqstat, \irqstat, lsr#16
-               tst     \irqstat, #0xff
-               addeq   \irqnr, \irqnr, #8
-               moveq   \irqstat, \irqstat, lsr#8
-               tst     \irqstat, #0xf
-               addeq   \irqnr, \irqnr, #4
-               moveq   \irqstat, \irqstat, lsr#4
-               tst     \irqstat, #0x3
-               addeq   \irqnr, \irqnr, #2
-               moveq   \irqstat, \irqstat, lsr#2
-               tst     \irqstat, #0x1
-               addeq   \irqnr, \irqnr, #1
-
-               @@ we have the value
-1001:
-               adds    \irqnr, \irqnr, #IRQ_EINT0
-1002:
-               @@ exit here, Z flag unset if IRQ
-
-       .endm
diff --git a/arch/arm/mach-s3c24xx/irq.c b/arch/arm/mach-s3c24xx/irq.c
deleted file mode 100644 (file)
index 3f3de74..0000000
+++ /dev/null
@@ -1,1068 +0,0 @@
-/*
- * S3C24XX IRQ handling
- *
- * Copyright (c) 2003-2004 Simtec Electronics
- *     Ben Dooks <ben@simtec.co.uk>
- * Copyright (c) 2012 Heiko Stuebner <heiko@sntech.de>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
-*/
-
-#include <linux/init.h>
-#include <linux/slab.h>
-#include <linux/module.h>
-#include <linux/io.h>
-#include <linux/err.h>
-#include <linux/interrupt.h>
-#include <linux/ioport.h>
-#include <linux/device.h>
-#include <linux/irqdomain.h>
-
-#include <asm/mach/irq.h>
-
-#include <mach/regs-irq.h>
-#include <mach/regs-gpio.h>
-
-#include <plat/cpu.h>
-#include <plat/regs-irqtype.h>
-#include <plat/pm.h>
-
-#define S3C_IRQTYPE_NONE       0
-#define S3C_IRQTYPE_EINT       1
-#define S3C_IRQTYPE_EDGE       2
-#define S3C_IRQTYPE_LEVEL      3
-
-struct s3c_irq_data {
-       unsigned int type;
-       unsigned long parent_irq;
-
-       /* data gets filled during init */
-       struct s3c_irq_intc *intc;
-       unsigned long sub_bits;
-       struct s3c_irq_intc *sub_intc;
-};
-
-/*
- * Sructure holding the controller data
- * @reg_pending                register holding pending irqs
- * @reg_intpnd         special register intpnd in main intc
- * @reg_mask           mask register
- * @domain             irq_domain of the controller
- * @parent             parent controller for ext and sub irqs
- * @irqs               irq-data, always s3c_irq_data[32]
- */
-struct s3c_irq_intc {
-       void __iomem            *reg_pending;
-       void __iomem            *reg_intpnd;
-       void __iomem            *reg_mask;
-       struct irq_domain       *domain;
-       struct s3c_irq_intc     *parent;
-       struct s3c_irq_data     *irqs;
-};
-
-static void s3c_irq_mask(struct irq_data *data)
-{
-       struct s3c_irq_intc *intc = data->domain->host_data;
-       struct s3c_irq_intc *parent_intc = intc->parent;
-       struct s3c_irq_data *irq_data = &intc->irqs[data->hwirq];
-       struct s3c_irq_data *parent_data;
-       unsigned long mask;
-       unsigned int irqno;
-
-       mask = __raw_readl(intc->reg_mask);
-       mask |= (1UL << data->hwirq);
-       __raw_writel(mask, intc->reg_mask);
-
-       if (parent_intc && irq_data->parent_irq) {
-               parent_data = &parent_intc->irqs[irq_data->parent_irq];
-
-               /* check to see if we need to mask the parent IRQ */
-               if ((mask & parent_data->sub_bits) == parent_data->sub_bits) {
-                       irqno = irq_find_mapping(parent_intc->domain,
-                                        irq_data->parent_irq);
-                       s3c_irq_mask(irq_get_irq_data(irqno));
-               }
-       }
-}
-
-static void s3c_irq_unmask(struct irq_data *data)
-{
-       struct s3c_irq_intc *intc = data->domain->host_data;
-       struct s3c_irq_intc *parent_intc = intc->parent;
-       struct s3c_irq_data *irq_data = &intc->irqs[data->hwirq];
-       unsigned long mask;
-       unsigned int irqno;
-
-       mask = __raw_readl(intc->reg_mask);
-       mask &= ~(1UL << data->hwirq);
-       __raw_writel(mask, intc->reg_mask);
-
-       if (parent_intc && irq_data->parent_irq) {
-               irqno = irq_find_mapping(parent_intc->domain,
-                                        irq_data->parent_irq);
-               s3c_irq_unmask(irq_get_irq_data(irqno));
-       }
-}
-
-static inline void s3c_irq_ack(struct irq_data *data)
-{
-       struct s3c_irq_intc *intc = data->domain->host_data;
-       unsigned long bitval = 1UL << data->hwirq;
-
-       __raw_writel(bitval, intc->reg_pending);
-       if (intc->reg_intpnd)
-               __raw_writel(bitval, intc->reg_intpnd);
-}
-
-static int s3c_irqext_type_set(void __iomem *gpcon_reg,
-                              void __iomem *extint_reg,
-                              unsigned long gpcon_offset,
-                              unsigned long extint_offset,
-                              unsigned int type)
-{
-       unsigned long newvalue = 0, value;
-
-       /* Set the GPIO to external interrupt mode */
-       value = __raw_readl(gpcon_reg);
-       value = (value & ~(3 << gpcon_offset)) | (0x02 << gpcon_offset);
-       __raw_writel(value, gpcon_reg);
-
-       /* Set the external interrupt to pointed trigger type */
-       switch (type)
-       {
-               case IRQ_TYPE_NONE:
-                       pr_warn("No edge setting!\n");
-                       break;
-
-               case IRQ_TYPE_EDGE_RISING:
-                       newvalue = S3C2410_EXTINT_RISEEDGE;
-                       break;
-
-               case IRQ_TYPE_EDGE_FALLING:
-                       newvalue = S3C2410_EXTINT_FALLEDGE;
-                       break;
-
-               case IRQ_TYPE_EDGE_BOTH:
-                       newvalue = S3C2410_EXTINT_BOTHEDGE;
-                       break;
-
-               case IRQ_TYPE_LEVEL_LOW:
-                       newvalue = S3C2410_EXTINT_LOWLEV;
-                       break;
-
-               case IRQ_TYPE_LEVEL_HIGH:
-                       newvalue = S3C2410_EXTINT_HILEV;
-                       break;
-
-               default:
-                       pr_err("No such irq type %d", type);
-                       return -EINVAL;
-       }
-
-       value = __raw_readl(extint_reg);
-       value = (value & ~(7 << extint_offset)) | (newvalue << extint_offset);
-       __raw_writel(value, extint_reg);
-
-       return 0;
-}
-
-static int s3c_irqext_type(struct irq_data *data, unsigned int type)
-{
-       void __iomem *extint_reg;
-       void __iomem *gpcon_reg;
-       unsigned long gpcon_offset, extint_offset;
-
-       if ((data->hwirq >= 4) && (data->hwirq <= 7)) {
-               gpcon_reg = S3C2410_GPFCON;
-               extint_reg = S3C24XX_EXTINT0;
-               gpcon_offset = (data->hwirq) * 2;
-               extint_offset = (data->hwirq) * 4;
-       } else if ((data->hwirq >= 8) && (data->hwirq <= 15)) {
-               gpcon_reg = S3C2410_GPGCON;
-               extint_reg = S3C24XX_EXTINT1;
-               gpcon_offset = (data->hwirq - 8) * 2;
-               extint_offset = (data->hwirq - 8) * 4;
-       } else if ((data->hwirq >= 16) && (data->hwirq <= 23)) {
-               gpcon_reg = S3C2410_GPGCON;
-               extint_reg = S3C24XX_EXTINT2;
-               gpcon_offset = (data->hwirq - 8) * 2;
-               extint_offset = (data->hwirq - 16) * 4;
-       } else {
-               return -EINVAL;
-       }
-
-       return s3c_irqext_type_set(gpcon_reg, extint_reg, gpcon_offset,
-                                  extint_offset, type);
-}
-
-static int s3c_irqext0_type(struct irq_data *data, unsigned int type)
-{
-       void __iomem *extint_reg;
-       void __iomem *gpcon_reg;
-       unsigned long gpcon_offset, extint_offset;
-
-       if ((data->hwirq >= 0) && (data->hwirq <= 3)) {
-               gpcon_reg = S3C2410_GPFCON;
-               extint_reg = S3C24XX_EXTINT0;
-               gpcon_offset = (data->hwirq) * 2;
-               extint_offset = (data->hwirq) * 4;
-       } else {
-               return -EINVAL;
-       }
-
-       return s3c_irqext_type_set(gpcon_reg, extint_reg, gpcon_offset,
-                                  extint_offset, type);
-}
-
-static struct irq_chip s3c_irq_chip = {
-       .name           = "s3c",
-       .irq_ack        = s3c_irq_ack,
-       .irq_mask       = s3c_irq_mask,
-       .irq_unmask     = s3c_irq_unmask,
-       .irq_set_wake   = s3c_irq_wake
-};
-
-static struct irq_chip s3c_irq_level_chip = {
-       .name           = "s3c-level",
-       .irq_mask       = s3c_irq_mask,
-       .irq_unmask     = s3c_irq_unmask,
-       .irq_ack        = s3c_irq_ack,
-};
-
-static struct irq_chip s3c_irqext_chip = {
-       .name           = "s3c-ext",
-       .irq_mask       = s3c_irq_mask,
-       .irq_unmask     = s3c_irq_unmask,
-       .irq_ack        = s3c_irq_ack,
-       .irq_set_type   = s3c_irqext_type,
-       .irq_set_wake   = s3c_irqext_wake
-};
-
-static struct irq_chip s3c_irq_eint0t4 = {
-       .name           = "s3c-ext0",
-       .irq_ack        = s3c_irq_ack,
-       .irq_mask       = s3c_irq_mask,
-       .irq_unmask     = s3c_irq_unmask,
-       .irq_set_wake   = s3c_irq_wake,
-       .irq_set_type   = s3c_irqext0_type,
-};
-
-static void s3c_irq_demux(unsigned int irq, struct irq_desc *desc)
-{
-       struct irq_chip *chip = irq_desc_get_chip(desc);
-       struct s3c_irq_intc *intc = desc->irq_data.domain->host_data;
-       struct s3c_irq_data *irq_data = &intc->irqs[desc->irq_data.hwirq];
-       struct s3c_irq_intc *sub_intc = irq_data->sub_intc;
-       unsigned long src;
-       unsigned long msk;
-       unsigned int n;
-
-       chained_irq_enter(chip, desc);
-
-       src = __raw_readl(sub_intc->reg_pending);
-       msk = __raw_readl(sub_intc->reg_mask);
-
-       src &= ~msk;
-       src &= irq_data->sub_bits;
-
-       while (src) {
-               n = __ffs(src);
-               src &= ~(1 << n);
-               generic_handle_irq(irq_find_mapping(sub_intc->domain, n));
-       }
-
-       chained_irq_exit(chip, desc);
-}
-
-#ifdef CONFIG_FIQ
-/**
- * s3c24xx_set_fiq - set the FIQ routing
- * @irq: IRQ number to route to FIQ on processor.
- * @on: Whether to route @irq to the FIQ, or to remove the FIQ routing.
- *
- * Change the state of the IRQ to FIQ routing depending on @irq and @on. If
- * @on is true, the @irq is checked to see if it can be routed and the
- * interrupt controller updated to route the IRQ. If @on is false, the FIQ
- * routing is cleared, regardless of which @irq is specified.
- */
-int s3c24xx_set_fiq(unsigned int irq, bool on)
-{
-       u32 intmod;
-       unsigned offs;
-
-       if (on) {
-               offs = irq - FIQ_START;
-               if (offs > 31)
-                       return -EINVAL;
-
-               intmod = 1 << offs;
-       } else {
-               intmod = 0;
-       }
-
-       __raw_writel(intmod, S3C2410_INTMOD);
-       return 0;
-}
-
-EXPORT_SYMBOL_GPL(s3c24xx_set_fiq);
-#endif
-
-static int s3c24xx_irq_map(struct irq_domain *h, unsigned int virq,
-                                                       irq_hw_number_t hw)
-{
-       struct s3c_irq_intc *intc = h->host_data;
-       struct s3c_irq_data *irq_data = &intc->irqs[hw];
-       struct s3c_irq_intc *parent_intc;
-       struct s3c_irq_data *parent_irq_data;
-       unsigned int irqno;
-
-       if (!intc) {
-               pr_err("irq-s3c24xx: no controller found for hwirq %lu\n", hw);
-               return -EINVAL;
-       }
-
-       if (!irq_data) {
-               pr_err("irq-s3c24xx: no irq data found for hwirq %lu\n", hw);
-               return -EINVAL;
-       }
-
-       /* attach controller pointer to irq_data */
-       irq_data->intc = intc;
-
-       /* set handler and flags */
-       switch (irq_data->type) {
-       case S3C_IRQTYPE_NONE:
-               return 0;
-       case S3C_IRQTYPE_EINT:
-               /* On the S3C2412, the EINT0to3 have a parent irq
-                * but need the s3c_irq_eint0t4 chip
-                */
-               if (irq_data->parent_irq && (!soc_is_s3c2412() || hw >= 4))
-                       irq_set_chip_and_handler(virq, &s3c_irqext_chip,
-                                                handle_edge_irq);
-               else
-                       irq_set_chip_and_handler(virq, &s3c_irq_eint0t4,
-                                                handle_edge_irq);
-               break;
-       case S3C_IRQTYPE_EDGE:
-               if (irq_data->parent_irq ||
-                   intc->reg_pending == S3C2416_SRCPND2)
-                       irq_set_chip_and_handler(virq, &s3c_irq_level_chip,
-                                                handle_edge_irq);
-               else
-                       irq_set_chip_and_handler(virq, &s3c_irq_chip,
-                                                handle_edge_irq);
-               break;
-       case S3C_IRQTYPE_LEVEL:
-               if (irq_data->parent_irq)
-                       irq_set_chip_and_handler(virq, &s3c_irq_level_chip,
-                                                handle_level_irq);
-               else
-                       irq_set_chip_and_handler(virq, &s3c_irq_chip,
-                                                handle_level_irq);
-               break;
-       default:
-               pr_err("irq-s3c24xx: unsupported irqtype %d\n", irq_data->type);
-               return -EINVAL;
-       }
-       set_irq_flags(virq, IRQF_VALID);
-
-       if (irq_data->parent_irq) {
-               parent_intc = intc->parent;
-               if (!parent_intc) {
-                       pr_err("irq-s3c24xx: no parent controller found for hwirq %lu\n",
-                              hw);
-                       goto err;
-               }
-
-               parent_irq_data = &parent_intc->irqs[irq_data->parent_irq];
-               if (!irq_data) {
-                       pr_err("irq-s3c24xx: no irq data found for hwirq %lu\n",
-                              hw);
-                       goto err;
-               }
-
-               parent_irq_data->sub_intc = intc;
-               parent_irq_data->sub_bits |= (1UL << hw);
-
-               /* attach the demuxer to the parent irq */
-               irqno = irq_find_mapping(parent_intc->domain,
-                                        irq_data->parent_irq);
-               if (!irqno) {
-                       pr_err("irq-s3c24xx: could not find mapping for parent irq %lu\n",
-                              irq_data->parent_irq);
-                       goto err;
-               }
-               irq_set_chained_handler(irqno, s3c_irq_demux);
-       }
-
-       return 0;
-
-err:
-       set_irq_flags(virq, 0);
-
-       /* the only error can result from bad mapping data*/
-       return -EINVAL;
-}
-
-static struct irq_domain_ops s3c24xx_irq_ops = {
-       .map = s3c24xx_irq_map,
-       .xlate = irq_domain_xlate_twocell,
-};
-
-static void s3c24xx_clear_intc(struct s3c_irq_intc *intc)
-{
-       void __iomem *reg_source;
-       unsigned long pend;
-       unsigned long last;
-       int i;
-
-       /* if intpnd is set, read the next pending irq from there */
-       reg_source = intc->reg_intpnd ? intc->reg_intpnd : intc->reg_pending;
-
-       last = 0;
-       for (i = 0; i < 4; i++) {
-               pend = __raw_readl(reg_source);
-
-               if (pend == 0 || pend == last)
-                       break;
-
-               __raw_writel(pend, intc->reg_pending);
-               if (intc->reg_intpnd)
-                       __raw_writel(pend, intc->reg_intpnd);
-
-               pr_info("irq: clearing pending status %08x\n", (int)pend);
-               last = pend;
-       }
-}
-
-struct s3c_irq_intc *s3c24xx_init_intc(struct device_node *np,
-                                      struct s3c_irq_data *irq_data,
-                                      struct s3c_irq_intc *parent,
-                                      unsigned long address)
-{
-       struct s3c_irq_intc *intc;
-       void __iomem *base = (void *)0xf6000000; /* static mapping */
-       int irq_num;
-       int irq_start;
-       int ret;
-
-       intc = kzalloc(sizeof(struct s3c_irq_intc), GFP_KERNEL);
-       if (!intc)
-               return ERR_PTR(-ENOMEM);
-
-       intc->irqs = irq_data;
-
-       if (parent)
-               intc->parent = parent;
-
-       /* select the correct data for the controller.
-        * Need to hard code the irq num start and offset
-        * to preserve the static mapping for now
-        */
-       switch (address) {
-       case 0x4a000000:
-               pr_debug("irq: found main intc\n");
-               intc->reg_pending = base;
-               intc->reg_mask = base + 0x08;
-               intc->reg_intpnd = base + 0x10;
-               irq_num = 32;
-               irq_start = S3C2410_IRQ(0);
-               break;
-       case 0x4a000018:
-               pr_debug("irq: found subintc\n");
-               intc->reg_pending = base + 0x18;
-               intc->reg_mask = base + 0x1c;
-               irq_num = 29;
-               irq_start = S3C2410_IRQSUB(0);
-               break;
-       case 0x4a000040:
-               pr_debug("irq: found intc2\n");
-               intc->reg_pending = base + 0x40;
-               intc->reg_mask = base + 0x48;
-               intc->reg_intpnd = base + 0x50;
-               irq_num = 8;
-               irq_start = S3C2416_IRQ(0);
-               break;
-       case 0x560000a4:
-               pr_debug("irq: found eintc\n");
-               base = (void *)0xfd000000;
-
-               intc->reg_mask = base + 0xa4;
-               intc->reg_pending = base + 0x08;
-               irq_num = 24;
-               irq_start = S3C2410_IRQ(32);
-               break;
-       default:
-               pr_err("irq: unsupported controller address\n");
-               ret = -EINVAL;
-               goto err;
-       }
-
-       /* now that all the data is complete, init the irq-domain */
-       s3c24xx_clear_intc(intc);
-       intc->domain = irq_domain_add_legacy(np, irq_num, irq_start,
-                                            0, &s3c24xx_irq_ops,
-                                            intc);
-       if (!intc->domain) {
-               pr_err("irq: could not create irq-domain\n");
-               ret = -EINVAL;
-               goto err;
-       }
-
-       return intc;
-
-err:
-       kfree(intc);
-       return ERR_PTR(ret);
-}
-
-/* s3c24xx_init_irq
- *
- * Initialise S3C2410 IRQ system
-*/
-
-static struct s3c_irq_data init_base[32] = {
-       { .type = S3C_IRQTYPE_EINT, }, /* EINT0 */
-       { .type = S3C_IRQTYPE_EINT, }, /* EINT1 */
-       { .type = S3C_IRQTYPE_EINT, }, /* EINT2 */
-       { .type = S3C_IRQTYPE_EINT, }, /* EINT3 */
-       { .type = S3C_IRQTYPE_LEVEL, }, /* EINT4to7 */
-       { .type = S3C_IRQTYPE_LEVEL, }, /* EINT8to23 */
-       { .type = S3C_IRQTYPE_NONE, }, /* reserved */
-       { .type = S3C_IRQTYPE_EDGE, }, /* nBATT_FLT */
-       { .type = S3C_IRQTYPE_EDGE, }, /* TICK */
-       { .type = S3C_IRQTYPE_EDGE, }, /* WDT */
-       { .type = S3C_IRQTYPE_EDGE, }, /* TIMER0 */
-       { .type = S3C_IRQTYPE_EDGE, }, /* TIMER1 */
-       { .type = S3C_IRQTYPE_EDGE, }, /* TIMER2 */
-       { .type = S3C_IRQTYPE_EDGE, }, /* TIMER3 */
-       { .type = S3C_IRQTYPE_EDGE, }, /* TIMER4 */
-       { .type = S3C_IRQTYPE_LEVEL, }, /* UART2 */
-       { .type = S3C_IRQTYPE_EDGE, }, /* LCD */
-       { .type = S3C_IRQTYPE_EDGE, }, /* DMA0 */
-       { .type = S3C_IRQTYPE_EDGE, }, /* DMA1 */
-       { .type = S3C_IRQTYPE_EDGE, }, /* DMA2 */
-       { .type = S3C_IRQTYPE_EDGE, }, /* DMA3 */
-       { .type = S3C_IRQTYPE_EDGE, }, /* SDI */
-       { .type = S3C_IRQTYPE_EDGE, }, /* SPI0 */
-       { .type = S3C_IRQTYPE_LEVEL, }, /* UART1 */
-       { .type = S3C_IRQTYPE_NONE, }, /* reserved */
-       { .type = S3C_IRQTYPE_EDGE, }, /* USBD */
-       { .type = S3C_IRQTYPE_EDGE, }, /* USBH */
-       { .type = S3C_IRQTYPE_EDGE, }, /* IIC */
-       { .type = S3C_IRQTYPE_LEVEL, }, /* UART0 */
-       { .type = S3C_IRQTYPE_EDGE, }, /* SPI1 */
-       { .type = S3C_IRQTYPE_EDGE, }, /* RTC */
-       { .type = S3C_IRQTYPE_LEVEL, }, /* ADCPARENT */
-};
-
-static struct s3c_irq_data init_eint[32] = {
-       { .type = S3C_IRQTYPE_NONE, }, /* reserved */
-       { .type = S3C_IRQTYPE_NONE, }, /* reserved */
-       { .type = S3C_IRQTYPE_NONE, }, /* reserved */
-       { .type = S3C_IRQTYPE_NONE, }, /* reserved */
-       { .type = S3C_IRQTYPE_EINT, .parent_irq = 4 }, /* EINT4 */
-       { .type = S3C_IRQTYPE_EINT, .parent_irq = 4 }, /* EINT5 */
-       { .type = S3C_IRQTYPE_EINT, .parent_irq = 4 }, /* EINT6 */
-       { .type = S3C_IRQTYPE_EINT, .parent_irq = 4 }, /* EINT7 */
-       { .type = S3C_IRQTYPE_EINT, .parent_irq = 5 }, /* EINT8 */
-       { .type = S3C_IRQTYPE_EINT, .parent_irq = 5 }, /* EINT9 */
-       { .type = S3C_IRQTYPE_EINT, .parent_irq = 5 }, /* EINT10 */
-       { .type = S3C_IRQTYPE_EINT, .parent_irq = 5 }, /* EINT11 */
-       { .type = S3C_IRQTYPE_EINT, .parent_irq = 5 }, /* EINT12 */
-       { .type = S3C_IRQTYPE_EINT, .parent_irq = 5 }, /* EINT13 */
-       { .type = S3C_IRQTYPE_EINT, .parent_irq = 5 }, /* EINT14 */
-       { .type = S3C_IRQTYPE_EINT, .parent_irq = 5 }, /* EINT15 */
-       { .type = S3C_IRQTYPE_EINT, .parent_irq = 5 }, /* EINT16 */
-       { .type = S3C_IRQTYPE_EINT, .parent_irq = 5 }, /* EINT17 */
-       { .type = S3C_IRQTYPE_EINT, .parent_irq = 5 }, /* EINT18 */
-       { .type = S3C_IRQTYPE_EINT, .parent_irq = 5 }, /* EINT19 */
-       { .type = S3C_IRQTYPE_EINT, .parent_irq = 5 }, /* EINT20 */
-       { .type = S3C_IRQTYPE_EINT, .parent_irq = 5 }, /* EINT21 */
-       { .type = S3C_IRQTYPE_EINT, .parent_irq = 5 }, /* EINT22 */
-       { .type = S3C_IRQTYPE_EINT, .parent_irq = 5 }, /* EINT23 */
-};
-
-static struct s3c_irq_data init_subint[32] = {
-       { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 28 }, /* UART0-RX */
-       { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 28 }, /* UART0-TX */
-       { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 28 }, /* UART0-ERR */
-       { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 23 }, /* UART1-RX */
-       { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 23 }, /* UART1-TX */
-       { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 23 }, /* UART1-ERR */
-       { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 15 }, /* UART2-RX */
-       { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 15 }, /* UART2-TX */
-       { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 15 }, /* UART2-ERR */
-       { .type = S3C_IRQTYPE_EDGE, .parent_irq = 31 }, /* TC */
-       { .type = S3C_IRQTYPE_EDGE, .parent_irq = 31 }, /* ADC */
-};
-
-void __init s3c24xx_init_irq(void)
-{
-       struct s3c_irq_intc *main_intc;
-
-#ifdef CONFIG_FIQ
-       init_FIQ(FIQ_START);
-#endif
-
-       main_intc = s3c24xx_init_intc(NULL, &init_base[0], NULL, 0x4a000000);
-       if (IS_ERR(main_intc)) {
-               pr_err("irq: could not create main interrupt controller\n");
-               return;
-       }
-
-       s3c24xx_init_intc(NULL, &init_subint[0], main_intc, 0x4a000018);
-       s3c24xx_init_intc(NULL, &init_eint[0], main_intc, 0x560000a4);
-}
-
-#ifdef CONFIG_CPU_S3C2412
-static struct s3c_irq_data init_s3c2412base[32] = {
-       { .type = S3C_IRQTYPE_LEVEL, }, /* EINT0 */
-       { .type = S3C_IRQTYPE_LEVEL, }, /* EINT1 */
-       { .type = S3C_IRQTYPE_LEVEL, }, /* EINT2 */
-       { .type = S3C_IRQTYPE_LEVEL, }, /* EINT3 */
-       { .type = S3C_IRQTYPE_LEVEL, }, /* EINT4to7 */
-       { .type = S3C_IRQTYPE_LEVEL, }, /* EINT8to23 */
-       { .type = S3C_IRQTYPE_NONE, }, /* reserved */
-       { .type = S3C_IRQTYPE_EDGE, }, /* nBATT_FLT */
-       { .type = S3C_IRQTYPE_EDGE, }, /* TICK */
-       { .type = S3C_IRQTYPE_EDGE, }, /* WDT */
-       { .type = S3C_IRQTYPE_EDGE, }, /* TIMER0 */
-       { .type = S3C_IRQTYPE_EDGE, }, /* TIMER1 */
-       { .type = S3C_IRQTYPE_EDGE, }, /* TIMER2 */
-       { .type = S3C_IRQTYPE_EDGE, }, /* TIMER3 */
-       { .type = S3C_IRQTYPE_EDGE, }, /* TIMER4 */
-       { .type = S3C_IRQTYPE_LEVEL, }, /* UART2 */
-       { .type = S3C_IRQTYPE_EDGE, }, /* LCD */
-       { .type = S3C_IRQTYPE_EDGE, }, /* DMA0 */
-       { .type = S3C_IRQTYPE_EDGE, }, /* DMA1 */
-       { .type = S3C_IRQTYPE_EDGE, }, /* DMA2 */
-       { .type = S3C_IRQTYPE_EDGE, }, /* DMA3 */
-       { .type = S3C_IRQTYPE_LEVEL, }, /* SDI/CF */
-       { .type = S3C_IRQTYPE_EDGE, }, /* SPI0 */
-       { .type = S3C_IRQTYPE_LEVEL, }, /* UART1 */
-       { .type = S3C_IRQTYPE_NONE, }, /* reserved */
-       { .type = S3C_IRQTYPE_EDGE, }, /* USBD */
-       { .type = S3C_IRQTYPE_EDGE, }, /* USBH */
-       { .type = S3C_IRQTYPE_EDGE, }, /* IIC */
-       { .type = S3C_IRQTYPE_LEVEL, }, /* UART0 */
-       { .type = S3C_IRQTYPE_EDGE, }, /* SPI1 */
-       { .type = S3C_IRQTYPE_EDGE, }, /* RTC */
-       { .type = S3C_IRQTYPE_LEVEL, }, /* ADCPARENT */
-};
-
-static struct s3c_irq_data init_s3c2412eint[32] = {
-       { .type = S3C_IRQTYPE_EINT, .parent_irq = 0 }, /* EINT0 */
-       { .type = S3C_IRQTYPE_EINT, .parent_irq = 1 }, /* EINT1 */
-       { .type = S3C_IRQTYPE_EINT, .parent_irq = 2 }, /* EINT2 */
-       { .type = S3C_IRQTYPE_EINT, .parent_irq = 3 }, /* EINT3 */
-       { .type = S3C_IRQTYPE_EINT, .parent_irq = 4 }, /* EINT4 */
-       { .type = S3C_IRQTYPE_EINT, .parent_irq = 4 }, /* EINT5 */
-       { .type = S3C_IRQTYPE_EINT, .parent_irq = 4 }, /* EINT6 */
-       { .type = S3C_IRQTYPE_EINT, .parent_irq = 4 }, /* EINT7 */
-       { .type = S3C_IRQTYPE_EINT, .parent_irq = 5 }, /* EINT8 */
-       { .type = S3C_IRQTYPE_EINT, .parent_irq = 5 }, /* EINT9 */
-       { .type = S3C_IRQTYPE_EINT, .parent_irq = 5 }, /* EINT10 */
-       { .type = S3C_IRQTYPE_EINT, .parent_irq = 5 }, /* EINT11 */
-       { .type = S3C_IRQTYPE_EINT, .parent_irq = 5 }, /* EINT12 */
-       { .type = S3C_IRQTYPE_EINT, .parent_irq = 5 }, /* EINT13 */
-       { .type = S3C_IRQTYPE_EINT, .parent_irq = 5 }, /* EINT14 */
-       { .type = S3C_IRQTYPE_EINT, .parent_irq = 5 }, /* EINT15 */
-       { .type = S3C_IRQTYPE_EINT, .parent_irq = 5 }, /* EINT16 */
-       { .type = S3C_IRQTYPE_EINT, .parent_irq = 5 }, /* EINT17 */
-       { .type = S3C_IRQTYPE_EINT, .parent_irq = 5 }, /* EINT18 */
-       { .type = S3C_IRQTYPE_EINT, .parent_irq = 5 }, /* EINT19 */
-       { .type = S3C_IRQTYPE_EINT, .parent_irq = 5 }, /* EINT20 */
-       { .type = S3C_IRQTYPE_EINT, .parent_irq = 5 }, /* EINT21 */
-       { .type = S3C_IRQTYPE_EINT, .parent_irq = 5 }, /* EINT22 */
-       { .type = S3C_IRQTYPE_EINT, .parent_irq = 5 }, /* EINT23 */
-};
-
-static struct s3c_irq_data init_s3c2412subint[32] = {
-       { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 28 }, /* UART0-RX */
-       { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 28 }, /* UART0-TX */
-       { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 28 }, /* UART0-ERR */
-       { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 23 }, /* UART1-RX */
-       { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 23 }, /* UART1-TX */
-       { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 23 }, /* UART1-ERR */
-       { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 15 }, /* UART2-RX */
-       { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 15 }, /* UART2-TX */
-       { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 15 }, /* UART2-ERR */
-       { .type = S3C_IRQTYPE_EDGE, .parent_irq = 31 }, /* TC */
-       { .type = S3C_IRQTYPE_EDGE, .parent_irq = 31 }, /* ADC */
-       { .type = S3C_IRQTYPE_NONE, },
-       { .type = S3C_IRQTYPE_NONE, },
-       { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 21 }, /* SDI */
-       { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 21 }, /* CF */
-};
-
-void s3c2412_init_irq(void)
-{
-       struct s3c_irq_intc *main_intc;
-
-       pr_info("S3C2412: IRQ Support\n");
-
-#ifdef CONFIG_FIQ
-       init_FIQ(FIQ_START);
-#endif
-
-       main_intc = s3c24xx_init_intc(NULL, &init_s3c2412base[0], NULL, 0x4a000000);
-       if (IS_ERR(main_intc)) {
-               pr_err("irq: could not create main interrupt controller\n");
-               return;
-       }
-
-       s3c24xx_init_intc(NULL, &init_s3c2412eint[0], main_intc, 0x560000a4);
-       s3c24xx_init_intc(NULL, &init_s3c2412subint[0], main_intc, 0x4a000018);
-}
-#endif
-
-#ifdef CONFIG_CPU_S3C2416
-static struct s3c_irq_data init_s3c2416base[32] = {
-       { .type = S3C_IRQTYPE_EINT, }, /* EINT0 */
-       { .type = S3C_IRQTYPE_EINT, }, /* EINT1 */
-       { .type = S3C_IRQTYPE_EINT, }, /* EINT2 */
-       { .type = S3C_IRQTYPE_EINT, }, /* EINT3 */
-       { .type = S3C_IRQTYPE_LEVEL, }, /* EINT4to7 */
-       { .type = S3C_IRQTYPE_LEVEL, }, /* EINT8to23 */
-       { .type = S3C_IRQTYPE_NONE, }, /* reserved */
-       { .type = S3C_IRQTYPE_EDGE, }, /* nBATT_FLT */
-       { .type = S3C_IRQTYPE_EDGE, }, /* TICK */
-       { .type = S3C_IRQTYPE_LEVEL, }, /* WDT/AC97 */
-       { .type = S3C_IRQTYPE_EDGE, }, /* TIMER0 */
-       { .type = S3C_IRQTYPE_EDGE, }, /* TIMER1 */
-       { .type = S3C_IRQTYPE_EDGE, }, /* TIMER2 */
-       { .type = S3C_IRQTYPE_EDGE, }, /* TIMER3 */
-       { .type = S3C_IRQTYPE_EDGE, }, /* TIMER4 */
-       { .type = S3C_IRQTYPE_LEVEL, }, /* UART2 */
-       { .type = S3C_IRQTYPE_LEVEL, }, /* LCD */
-       { .type = S3C_IRQTYPE_LEVEL, }, /* DMA */
-       { .type = S3C_IRQTYPE_LEVEL, }, /* UART3 */
-       { .type = S3C_IRQTYPE_NONE, }, /* reserved */
-       { .type = S3C_IRQTYPE_EDGE, }, /* SDI1 */
-       { .type = S3C_IRQTYPE_EDGE, }, /* SDI0 */
-       { .type = S3C_IRQTYPE_EDGE, }, /* SPI0 */
-       { .type = S3C_IRQTYPE_LEVEL, }, /* UART1 */
-       { .type = S3C_IRQTYPE_EDGE, }, /* NAND */
-       { .type = S3C_IRQTYPE_EDGE, }, /* USBD */
-       { .type = S3C_IRQTYPE_EDGE, }, /* USBH */
-       { .type = S3C_IRQTYPE_EDGE, }, /* IIC */
-       { .type = S3C_IRQTYPE_LEVEL, }, /* UART0 */
-       { .type = S3C_IRQTYPE_NONE, },
-       { .type = S3C_IRQTYPE_EDGE, }, /* RTC */
-       { .type = S3C_IRQTYPE_LEVEL, }, /* ADCPARENT */
-};
-
-static struct s3c_irq_data init_s3c2416subint[32] = {
-       { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 28 }, /* UART0-RX */
-       { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 28 }, /* UART0-TX */
-       { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 28 }, /* UART0-ERR */
-       { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 23 }, /* UART1-RX */
-       { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 23 }, /* UART1-TX */
-       { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 23 }, /* UART1-ERR */
-       { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 15 }, /* UART2-RX */
-       { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 15 }, /* UART2-TX */
-       { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 15 }, /* UART2-ERR */
-       { .type = S3C_IRQTYPE_EDGE, .parent_irq = 31 }, /* TC */
-       { .type = S3C_IRQTYPE_EDGE, .parent_irq = 31 }, /* ADC */
-       { .type = S3C_IRQTYPE_NONE }, /* reserved */
-       { .type = S3C_IRQTYPE_NONE }, /* reserved */
-       { .type = S3C_IRQTYPE_NONE }, /* reserved */
-       { .type = S3C_IRQTYPE_NONE }, /* reserved */
-       { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 16 }, /* LCD2 */
-       { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 16 }, /* LCD3 */
-       { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 16 }, /* LCD4 */
-       { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 17 }, /* DMA0 */
-       { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 17 }, /* DMA1 */
-       { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 17 }, /* DMA2 */
-       { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 17 }, /* DMA3 */
-       { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 17 }, /* DMA4 */
-       { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 17 }, /* DMA5 */
-       { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 18 }, /* UART3-RX */
-       { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 18 }, /* UART3-TX */
-       { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 18 }, /* UART3-ERR */
-       { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 9 }, /* WDT */
-       { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 9 }, /* AC97 */
-};
-
-static struct s3c_irq_data init_s3c2416_second[32] = {
-       { .type = S3C_IRQTYPE_EDGE }, /* 2D */
-       { .type = S3C_IRQTYPE_EDGE }, /* IIC1 */
-       { .type = S3C_IRQTYPE_NONE }, /* reserved */
-       { .type = S3C_IRQTYPE_NONE }, /* reserved */
-       { .type = S3C_IRQTYPE_EDGE }, /* PCM0 */
-       { .type = S3C_IRQTYPE_EDGE }, /* PCM1 */
-       { .type = S3C_IRQTYPE_EDGE }, /* I2S0 */
-       { .type = S3C_IRQTYPE_EDGE }, /* I2S1 */
-};
-
-void __init s3c2416_init_irq(void)
-{
-       struct s3c_irq_intc *main_intc;
-
-       pr_info("S3C2416: IRQ Support\n");
-
-#ifdef CONFIG_FIQ
-       init_FIQ(FIQ_START);
-#endif
-
-       main_intc = s3c24xx_init_intc(NULL, &init_s3c2416base[0], NULL, 0x4a000000);
-       if (IS_ERR(main_intc)) {
-               pr_err("irq: could not create main interrupt controller\n");
-               return;
-       }
-
-       s3c24xx_init_intc(NULL, &init_eint[0], main_intc, 0x560000a4);
-       s3c24xx_init_intc(NULL, &init_s3c2416subint[0], main_intc, 0x4a000018);
-
-       s3c24xx_init_intc(NULL, &init_s3c2416_second[0], NULL, 0x4a000040);
-}
-
-#endif
-
-#ifdef CONFIG_CPU_S3C2440
-static struct s3c_irq_data init_s3c2440base[32] = {
-       { .type = S3C_IRQTYPE_EINT, }, /* EINT0 */
-       { .type = S3C_IRQTYPE_EINT, }, /* EINT1 */
-       { .type = S3C_IRQTYPE_EINT, }, /* EINT2 */
-       { .type = S3C_IRQTYPE_EINT, }, /* EINT3 */
-       { .type = S3C_IRQTYPE_LEVEL, }, /* EINT4to7 */
-       { .type = S3C_IRQTYPE_LEVEL, }, /* EINT8to23 */
-       { .type = S3C_IRQTYPE_LEVEL, }, /* CAM */
-       { .type = S3C_IRQTYPE_EDGE, }, /* nBATT_FLT */
-       { .type = S3C_IRQTYPE_EDGE, }, /* TICK */
-       { .type = S3C_IRQTYPE_LEVEL, }, /* WDT/AC97 */
-       { .type = S3C_IRQTYPE_EDGE, }, /* TIMER0 */
-       { .type = S3C_IRQTYPE_EDGE, }, /* TIMER1 */
-       { .type = S3C_IRQTYPE_EDGE, }, /* TIMER2 */
-       { .type = S3C_IRQTYPE_EDGE, }, /* TIMER3 */
-       { .type = S3C_IRQTYPE_EDGE, }, /* TIMER4 */
-       { .type = S3C_IRQTYPE_LEVEL, }, /* UART2 */
-       { .type = S3C_IRQTYPE_EDGE, }, /* LCD */
-       { .type = S3C_IRQTYPE_EDGE, }, /* DMA0 */
-       { .type = S3C_IRQTYPE_EDGE, }, /* DMA1 */
-       { .type = S3C_IRQTYPE_EDGE, }, /* DMA2 */
-       { .type = S3C_IRQTYPE_EDGE, }, /* DMA3 */
-       { .type = S3C_IRQTYPE_EDGE, }, /* SDI */
-       { .type = S3C_IRQTYPE_EDGE, }, /* SPI0 */
-       { .type = S3C_IRQTYPE_LEVEL, }, /* UART1 */
-       { .type = S3C_IRQTYPE_LEVEL, }, /* NFCON */
-       { .type = S3C_IRQTYPE_EDGE, }, /* USBD */
-       { .type = S3C_IRQTYPE_EDGE, }, /* USBH */
-       { .type = S3C_IRQTYPE_EDGE, }, /* IIC */
-       { .type = S3C_IRQTYPE_LEVEL, }, /* UART0 */
-       { .type = S3C_IRQTYPE_EDGE, }, /* SPI1 */
-       { .type = S3C_IRQTYPE_EDGE, }, /* RTC */
-       { .type = S3C_IRQTYPE_LEVEL, }, /* ADCPARENT */
-};
-
-static struct s3c_irq_data init_s3c2440subint[32] = {
-       { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 28 }, /* UART0-RX */
-       { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 28 }, /* UART0-TX */
-       { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 28 }, /* UART0-ERR */
-       { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 23 }, /* UART1-RX */
-       { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 23 }, /* UART1-TX */
-       { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 23 }, /* UART1-ERR */
-       { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 15 }, /* UART2-RX */
-       { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 15 }, /* UART2-TX */
-       { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 15 }, /* UART2-ERR */
-       { .type = S3C_IRQTYPE_EDGE, .parent_irq = 31 }, /* TC */
-       { .type = S3C_IRQTYPE_EDGE, .parent_irq = 31 }, /* ADC */
-       { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 6 }, /* TC */
-       { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 6 }, /* ADC */
-       { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 9 }, /* WDT */
-       { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 9 }, /* AC97 */
-};
-
-void __init s3c2440_init_irq(void)
-{
-       struct s3c_irq_intc *main_intc;
-
-       pr_info("S3C2440: IRQ Support\n");
-
-#ifdef CONFIG_FIQ
-       init_FIQ(FIQ_START);
-#endif
-
-       main_intc = s3c24xx_init_intc(NULL, &init_s3c2440base[0], NULL, 0x4a000000);
-       if (IS_ERR(main_intc)) {
-               pr_err("irq: could not create main interrupt controller\n");
-               return;
-       }
-
-       s3c24xx_init_intc(NULL, &init_eint[0], main_intc, 0x560000a4);
-       s3c24xx_init_intc(NULL, &init_s3c2440subint[0], main_intc, 0x4a000018);
-}
-#endif
-
-#ifdef CONFIG_CPU_S3C2442
-static struct s3c_irq_data init_s3c2442base[32] = {
-       { .type = S3C_IRQTYPE_EINT, }, /* EINT0 */
-       { .type = S3C_IRQTYPE_EINT, }, /* EINT1 */
-       { .type = S3C_IRQTYPE_EINT, }, /* EINT2 */
-       { .type = S3C_IRQTYPE_EINT, }, /* EINT3 */
-       { .type = S3C_IRQTYPE_LEVEL, }, /* EINT4to7 */
-       { .type = S3C_IRQTYPE_LEVEL, }, /* EINT8to23 */
-       { .type = S3C_IRQTYPE_LEVEL, }, /* CAM */
-       { .type = S3C_IRQTYPE_EDGE, }, /* nBATT_FLT */
-       { .type = S3C_IRQTYPE_EDGE, }, /* TICK */
-       { .type = S3C_IRQTYPE_EDGE, }, /* WDT */
-       { .type = S3C_IRQTYPE_EDGE, }, /* TIMER0 */
-       { .type = S3C_IRQTYPE_EDGE, }, /* TIMER1 */
-       { .type = S3C_IRQTYPE_EDGE, }, /* TIMER2 */
-       { .type = S3C_IRQTYPE_EDGE, }, /* TIMER3 */
-       { .type = S3C_IRQTYPE_EDGE, }, /* TIMER4 */
-       { .type = S3C_IRQTYPE_LEVEL, }, /* UART2 */
-       { .type = S3C_IRQTYPE_EDGE, }, /* LCD */
-       { .type = S3C_IRQTYPE_EDGE, }, /* DMA0 */
-       { .type = S3C_IRQTYPE_EDGE, }, /* DMA1 */
-       { .type = S3C_IRQTYPE_EDGE, }, /* DMA2 */
-       { .type = S3C_IRQTYPE_EDGE, }, /* DMA3 */
-       { .type = S3C_IRQTYPE_EDGE, }, /* SDI */
-       { .type = S3C_IRQTYPE_EDGE, }, /* SPI0 */
-       { .type = S3C_IRQTYPE_LEVEL, }, /* UART1 */
-       { .type = S3C_IRQTYPE_LEVEL, }, /* NFCON */
-       { .type = S3C_IRQTYPE_EDGE, }, /* USBD */
-       { .type = S3C_IRQTYPE_EDGE, }, /* USBH */
-       { .type = S3C_IRQTYPE_EDGE, }, /* IIC */
-       { .type = S3C_IRQTYPE_LEVEL, }, /* UART0 */
-       { .type = S3C_IRQTYPE_EDGE, }, /* SPI1 */
-       { .type = S3C_IRQTYPE_EDGE, }, /* RTC */
-       { .type = S3C_IRQTYPE_LEVEL, }, /* ADCPARENT */
-};
-
-static struct s3c_irq_data init_s3c2442subint[32] = {
-       { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 28 }, /* UART0-RX */
-       { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 28 }, /* UART0-TX */
-       { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 28 }, /* UART0-ERR */
-       { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 23 }, /* UART1-RX */
-       { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 23 }, /* UART1-TX */
-       { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 23 }, /* UART1-ERR */
-       { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 15 }, /* UART2-RX */
-       { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 15 }, /* UART2-TX */
-       { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 15 }, /* UART2-ERR */
-       { .type = S3C_IRQTYPE_EDGE, .parent_irq = 31 }, /* TC */
-       { .type = S3C_IRQTYPE_EDGE, .parent_irq = 31 }, /* ADC */
-       { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 6 }, /* TC */
-       { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 6 }, /* ADC */
-};
-
-void __init s3c2442_init_irq(void)
-{
-       struct s3c_irq_intc *main_intc;
-
-       pr_info("S3C2442: IRQ Support\n");
-
-#ifdef CONFIG_FIQ
-       init_FIQ(FIQ_START);
-#endif
-
-       main_intc = s3c24xx_init_intc(NULL, &init_s3c2442base[0], NULL, 0x4a000000);
-       if (IS_ERR(main_intc)) {
-               pr_err("irq: could not create main interrupt controller\n");
-               return;
-       }
-
-       s3c24xx_init_intc(NULL, &init_eint[0], main_intc, 0x560000a4);
-       s3c24xx_init_intc(NULL, &init_s3c2442subint[0], main_intc, 0x4a000018);
-}
-#endif
-
-#ifdef CONFIG_CPU_S3C2443
-static struct s3c_irq_data init_s3c2443base[32] = {
-       { .type = S3C_IRQTYPE_EINT, }, /* EINT0 */
-       { .type = S3C_IRQTYPE_EINT, }, /* EINT1 */
-       { .type = S3C_IRQTYPE_EINT, }, /* EINT2 */
-       { .type = S3C_IRQTYPE_EINT, }, /* EINT3 */
-       { .type = S3C_IRQTYPE_LEVEL, }, /* EINT4to7 */
-       { .type = S3C_IRQTYPE_LEVEL, }, /* EINT8to23 */
-       { .type = S3C_IRQTYPE_LEVEL, }, /* CAM */
-       { .type = S3C_IRQTYPE_EDGE, }, /* nBATT_FLT */
-       { .type = S3C_IRQTYPE_EDGE, }, /* TICK */
-       { .type = S3C_IRQTYPE_LEVEL, }, /* WDT/AC97 */
-       { .type = S3C_IRQTYPE_EDGE, }, /* TIMER0 */
-       { .type = S3C_IRQTYPE_EDGE, }, /* TIMER1 */
-       { .type = S3C_IRQTYPE_EDGE, }, /* TIMER2 */
-       { .type = S3C_IRQTYPE_EDGE, }, /* TIMER3 */
-       { .type = S3C_IRQTYPE_EDGE, }, /* TIMER4 */
-       { .type = S3C_IRQTYPE_LEVEL, }, /* UART2 */
-       { .type = S3C_IRQTYPE_LEVEL, }, /* LCD */
-       { .type = S3C_IRQTYPE_LEVEL, }, /* DMA */
-       { .type = S3C_IRQTYPE_LEVEL, }, /* UART3 */
-       { .type = S3C_IRQTYPE_EDGE, }, /* CFON */
-       { .type = S3C_IRQTYPE_EDGE, }, /* SDI1 */
-       { .type = S3C_IRQTYPE_EDGE, }, /* SDI0 */
-       { .type = S3C_IRQTYPE_EDGE, }, /* SPI0 */
-       { .type = S3C_IRQTYPE_LEVEL, }, /* UART1 */
-       { .type = S3C_IRQTYPE_EDGE, }, /* NAND */
-       { .type = S3C_IRQTYPE_EDGE, }, /* USBD */
-       { .type = S3C_IRQTYPE_EDGE, }, /* USBH */
-       { .type = S3C_IRQTYPE_EDGE, }, /* IIC */
-       { .type = S3C_IRQTYPE_LEVEL, }, /* UART0 */
-       { .type = S3C_IRQTYPE_EDGE, }, /* SPI1 */
-       { .type = S3C_IRQTYPE_EDGE, }, /* RTC */
-       { .type = S3C_IRQTYPE_LEVEL, }, /* ADCPARENT */
-};
-
-
-static struct s3c_irq_data init_s3c2443subint[32] = {
-       { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 28 }, /* UART0-RX */
-       { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 28 }, /* UART0-TX */
-       { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 28 }, /* UART0-ERR */
-       { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 23 }, /* UART1-RX */
-       { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 23 }, /* UART1-TX */
-       { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 23 }, /* UART1-ERR */
-       { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 15 }, /* UART2-RX */
-       { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 15 }, /* UART2-TX */
-       { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 15 }, /* UART2-ERR */
-       { .type = S3C_IRQTYPE_EDGE, .parent_irq = 31 }, /* TC */
-       { .type = S3C_IRQTYPE_EDGE, .parent_irq = 31 }, /* ADC */
-       { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 6 }, /* CAM_C */
-       { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 6 }, /* CAM_P */
-       { .type = S3C_IRQTYPE_NONE }, /* reserved */
-       { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 16 }, /* LCD1 */
-       { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 16 }, /* LCD2 */
-       { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 16 }, /* LCD3 */
-       { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 16 }, /* LCD4 */
-       { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 17 }, /* DMA0 */
-       { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 17 }, /* DMA1 */
-       { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 17 }, /* DMA2 */
-       { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 17 }, /* DMA3 */
-       { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 17 }, /* DMA4 */
-       { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 17 }, /* DMA5 */
-       { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 18 }, /* UART3-RX */
-       { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 18 }, /* UART3-TX */
-       { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 18 }, /* UART3-ERR */
-       { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 9 }, /* WDT */
-       { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 9 }, /* AC97 */
-};
-
-void __init s3c2443_init_irq(void)
-{
-       struct s3c_irq_intc *main_intc;
-
-       pr_info("S3C2443: IRQ Support\n");
-
-#ifdef CONFIG_FIQ
-       init_FIQ(FIQ_START);
-#endif
-
-       main_intc = s3c24xx_init_intc(NULL, &init_s3c2443base[0], NULL, 0x4a000000);
-       if (IS_ERR(main_intc)) {
-               pr_err("irq: could not create main interrupt controller\n");
-               return;
-       }
-
-       s3c24xx_init_intc(NULL, &init_eint[0], main_intc, 0x560000a4);
-       s3c24xx_init_intc(NULL, &init_s3c2443subint[0], main_intc, 0x4a000018);
-}
-#endif
index 432144cb54ae4c3ebfc6a1e9d140bd208240dabd..e27b5c91b3db230b0cc6126ebf20e6c1f73ea104 100644 (file)
@@ -238,7 +238,7 @@ static void __init amlm5900_init(void)
 MACHINE_START(AML_M5900, "AML_M5900")
        .atag_offset    = 0x100,
        .map_io         = amlm5900_map_io,
-       .init_irq       = s3c24xx_init_irq,
+       .init_irq       = s3c2410_init_irq,
        .init_machine   = amlm5900_init,
        .init_time      = samsung_timer_init,
        .restart        = s3c2410_restart,
index eabe2db42ef6100c8a815d26bd8769b10f9b007e..22d6ae926d91c996ac7bc98425a1a5aa65d872d0 100644 (file)
@@ -605,7 +605,7 @@ MACHINE_START(BAST, "Simtec-BAST")
        /* Maintainer: Ben Dooks <ben@simtec.co.uk> */
        .atag_offset    = 0x100,
        .map_io         = bast_map_io,
-       .init_irq       = s3c24xx_init_irq,
+       .init_irq       = s3c2410_init_irq,
        .init_machine   = bast_init,
        .init_time      = samsung_timer_init,
        .restart        = s3c2410_restart,
index 8dd66010284644700f8b54353b5a85319c272268..af4334d6b4d532c60937154019a7816e4276f36c 100644 (file)
@@ -667,11 +667,6 @@ static void __init h1940_reserve(void)
        memblock_reserve(0x30081000, 0x1000);
 }
 
-static void __init h1940_init_irq(void)
-{
-       s3c24xx_init_irq();
-}
-
 static void __init h1940_init(void)
 {
        u32 tmp;
@@ -740,7 +735,7 @@ MACHINE_START(H1940, "IPAQ-H1940")
        .atag_offset    = 0x100,
        .map_io         = h1940_map_io,
        .reserve        = h1940_reserve,
-       .init_irq       = h1940_init_irq,
+       .init_irq       = s3c2410_init_irq,
        .init_machine   = h1940_init,
        .init_time      = samsung_timer_init,
        .restart        = s3c2410_restart,
index 73a690f431e6a889f0e87270f35a001c30192b54..2cb46c37c92058450e7bb9ec575ec14779ff9ba7 100644 (file)
@@ -592,7 +592,7 @@ MACHINE_START(N30, "Acer-N30")
        .atag_offset    = 0x100,
        .init_time      = samsung_timer_init,
        .init_machine   = n30_init,
-       .init_irq       = s3c24xx_init_irq,
+       .init_irq       = s3c2410_init_irq,
        .map_io         = n30_map_io,
        .restart        = s3c2410_restart,
 MACHINE_END
@@ -603,7 +603,7 @@ MACHINE_START(N35, "Acer-N35")
        .atag_offset    = 0x100,
        .init_time      = samsung_timer_init,
        .init_machine   = n30_init,
-       .init_irq       = s3c24xx_init_irq,
+       .init_irq       = s3c2410_init_irq,
        .map_io         = n30_map_io,
        .restart        = s3c2410_restart,
 MACHINE_END
index 7b8670746b6a6261acb04f13a563ebf7dba14e69..7e16b0740ec1eb02208aba8a0f4dc72f13e300fc 100644 (file)
@@ -116,7 +116,7 @@ MACHINE_START(OTOM, "Nex Vision - Otom 1.1")
        .atag_offset    = 0x100,
        .map_io         = otom11_map_io,
        .init_machine   = otom11_init,
-       .init_irq       = s3c24xx_init_irq,
+       .init_irq       = s3c2410_init_irq,
        .init_time      = samsung_timer_init,
        .restart        = s3c2410_restart,
 MACHINE_END
index 71cf29b12d1f79b83085be8a4e9b1145b2babbab..f8feaeadb55a43402912bccefbcb7313881f5422 100644 (file)
@@ -343,7 +343,7 @@ static void __init qt2410_machine_init(void)
 MACHINE_START(QT2410, "QT2410")
        .atag_offset    = 0x100,
        .map_io         = qt2410_map_io,
-       .init_irq       = s3c24xx_init_irq,
+       .init_irq       = s3c2410_init_irq,
        .init_machine   = qt2410_machine_init,
        .init_time      = samsung_timer_init,
        .restart        = s3c2410_restart,
index fd96f7fc330c5eb2035091732aae03ce1368aac7..a773789e4f38ec8cd87a8b8fd80aa2afbd696fbb 100644 (file)
@@ -116,7 +116,7 @@ MACHINE_START(SMDK2410, "SMDK2410") /* @TODO: request a new identifier and switc
        /* Maintainer: Jonas Dietsche */
        .atag_offset    = 0x100,
        .map_io         = smdk2410_map_io,
-       .init_irq       = s3c24xx_init_irq,
+       .init_irq       = s3c2410_init_irq,
        .init_machine   = smdk2410_init,
        .init_time      = samsung_timer_init,
        .restart        = s3c2410_restart,
index 31dfe589e34972130ce3482cdea2f21442489900..7fad8f055cabc050b5aba9e1ecaf82c2fc1998f9 100644 (file)
@@ -149,7 +149,7 @@ static void __init tct_hammer_init(void)
 MACHINE_START(TCT_HAMMER, "TCT_HAMMER")
        .atag_offset    = 0x100,
        .map_io         = tct_hammer_map_io,
-       .init_irq       = s3c24xx_init_irq,
+       .init_irq       = s3c2410_init_irq,
        .init_machine   = tct_hammer_init,
        .init_time      = samsung_timer_init,
        .restart        = s3c2410_restart,
index deeb8a0a4034ba373b1143e781f82584e3b250d7..42e7187fed6090fbef193901984cbd9e5cc0582c 100644 (file)
@@ -355,7 +355,7 @@ MACHINE_START(VR1000, "Thorcom-VR1000")
        .atag_offset    = 0x100,
        .map_io         = vr1000_map_io,
        .init_machine   = vr1000_init,
-       .init_irq       = s3c24xx_init_irq,
+       .init_irq       = s3c2410_init_irq,
        .init_time      = samsung_timer_init,
        .restart        = s3c2410_restart,
 MACHINE_END
index 0f6c47a6475bb60872b5db222631de178e621e0e..989fefe18be6b77bee4216be31948f49582a475b 100644 (file)
@@ -183,7 +183,6 @@ extern void s3c_init_cpu(unsigned long idcode,
 
 /* core initialisation functions */
 
-extern void s3c24xx_init_irq(void);
 extern void s5p_init_irq(u32 *vic, u32 num_vic);
 
 extern void s3c24xx_init_io(struct map_desc *mach_desc, int size);
index e41ceb9bec227731c522b2203990b1316f608583..acf98953272afa1e967789f5d675fa2770c721eb 100644 (file)
@@ -2,6 +2,7 @@ obj-$(CONFIG_IRQCHIP)                   += irqchip.o
 
 obj-$(CONFIG_ARCH_BCM2835)             += irq-bcm2835.o
 obj-$(CONFIG_ARCH_EXYNOS)              += exynos-combiner.o
+obj-$(CONFIG_ARCH_S3C24XX)             += irq-s3c24xx.o
 obj-$(CONFIG_METAG)                    += irq-metag-ext.o
 obj-$(CONFIG_METAG_PERFCOUNTER_IRQS)   += irq-metag.o
 obj-$(CONFIG_ARCH_SUNXI)               += irq-sunxi.o
diff --git a/drivers/irqchip/irq-s3c24xx.c b/drivers/irqchip/irq-s3c24xx.c
new file mode 100644 (file)
index 0000000..5e40b34
--- /dev/null
@@ -0,0 +1,1355 @@
+/*
+ * S3C24XX IRQ handling
+ *
+ * Copyright (c) 2003-2004 Simtec Electronics
+ *     Ben Dooks <ben@simtec.co.uk>
+ * Copyright (c) 2012 Heiko Stuebner <heiko@sntech.de>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+*/
+
+#include <linux/init.h>
+#include <linux/slab.h>
+#include <linux/module.h>
+#include <linux/io.h>
+#include <linux/err.h>
+#include <linux/interrupt.h>
+#include <linux/ioport.h>
+#include <linux/device.h>
+#include <linux/irqdomain.h>
+#include <linux/of.h>
+#include <linux/of_irq.h>
+#include <linux/of_address.h>
+
+#include <asm/exception.h>
+#include <asm/mach/irq.h>
+
+#include <mach/regs-irq.h>
+#include <mach/regs-gpio.h>
+
+#include <plat/cpu.h>
+#include <plat/regs-irqtype.h>
+#include <plat/pm.h>
+
+#include "irqchip.h"
+
+#define S3C_IRQTYPE_NONE       0
+#define S3C_IRQTYPE_EINT       1
+#define S3C_IRQTYPE_EDGE       2
+#define S3C_IRQTYPE_LEVEL      3
+
+struct s3c_irq_data {
+       unsigned int type;
+       unsigned long offset;
+       unsigned long parent_irq;
+
+       /* data gets filled during init */
+       struct s3c_irq_intc *intc;
+       unsigned long sub_bits;
+       struct s3c_irq_intc *sub_intc;
+};
+
+/*
+ * Sructure holding the controller data
+ * @reg_pending                register holding pending irqs
+ * @reg_intpnd         special register intpnd in main intc
+ * @reg_mask           mask register
+ * @domain             irq_domain of the controller
+ * @parent             parent controller for ext and sub irqs
+ * @irqs               irq-data, always s3c_irq_data[32]
+ */
+struct s3c_irq_intc {
+       void __iomem            *reg_pending;
+       void __iomem            *reg_intpnd;
+       void __iomem            *reg_mask;
+       struct irq_domain       *domain;
+       struct s3c_irq_intc     *parent;
+       struct s3c_irq_data     *irqs;
+};
+
+/*
+ * Array holding pointers to the global controller structs
+ * [0] ... main_intc
+ * [1] ... sub_intc
+ * [2] ... main_intc2 on s3c2416
+ */
+static struct s3c_irq_intc *s3c_intc[3];
+
+static void s3c_irq_mask(struct irq_data *data)
+{
+       struct s3c_irq_data *irq_data = irq_data_get_irq_chip_data(data);
+       struct s3c_irq_intc *intc = irq_data->intc;
+       struct s3c_irq_intc *parent_intc = intc->parent;
+       struct s3c_irq_data *parent_data;
+       unsigned long mask;
+       unsigned int irqno;
+
+       mask = __raw_readl(intc->reg_mask);
+       mask |= (1UL << irq_data->offset);
+       __raw_writel(mask, intc->reg_mask);
+
+       if (parent_intc) {
+               parent_data = &parent_intc->irqs[irq_data->parent_irq];
+
+               /* check to see if we need to mask the parent IRQ
+                * The parent_irq is always in main_intc, so the hwirq
+                * for find_mapping does not need an offset in any case.
+                */
+               if ((mask & parent_data->sub_bits) == parent_data->sub_bits) {
+                       irqno = irq_find_mapping(parent_intc->domain,
+                                        irq_data->parent_irq);
+                       s3c_irq_mask(irq_get_irq_data(irqno));
+               }
+       }
+}
+
+static void s3c_irq_unmask(struct irq_data *data)
+{
+       struct s3c_irq_data *irq_data = irq_data_get_irq_chip_data(data);
+       struct s3c_irq_intc *intc = irq_data->intc;
+       struct s3c_irq_intc *parent_intc = intc->parent;
+       unsigned long mask;
+       unsigned int irqno;
+
+       mask = __raw_readl(intc->reg_mask);
+       mask &= ~(1UL << irq_data->offset);
+       __raw_writel(mask, intc->reg_mask);
+
+       if (parent_intc) {
+               irqno = irq_find_mapping(parent_intc->domain,
+                                        irq_data->parent_irq);
+               s3c_irq_unmask(irq_get_irq_data(irqno));
+       }
+}
+
+static inline void s3c_irq_ack(struct irq_data *data)
+{
+       struct s3c_irq_data *irq_data = irq_data_get_irq_chip_data(data);
+       struct s3c_irq_intc *intc = irq_data->intc;
+       unsigned long bitval = 1UL << irq_data->offset;
+
+       __raw_writel(bitval, intc->reg_pending);
+       if (intc->reg_intpnd)
+               __raw_writel(bitval, intc->reg_intpnd);
+}
+
+static int s3c_irq_type(struct irq_data *data, unsigned int type)
+{
+       switch (type) {
+       case IRQ_TYPE_NONE:
+               break;
+       case IRQ_TYPE_EDGE_RISING:
+       case IRQ_TYPE_EDGE_FALLING:
+       case IRQ_TYPE_EDGE_BOTH:
+               irq_set_handler(data->irq, handle_edge_irq);
+               break;
+       case IRQ_TYPE_LEVEL_LOW:
+       case IRQ_TYPE_LEVEL_HIGH:
+               irq_set_handler(data->irq, handle_level_irq);
+               break;
+       default:
+               pr_err("No such irq type %d", type);
+               return -EINVAL;
+       }
+
+       return 0;
+}
+
+static int s3c_irqext_type_set(void __iomem *gpcon_reg,
+                              void __iomem *extint_reg,
+                              unsigned long gpcon_offset,
+                              unsigned long extint_offset,
+                              unsigned int type)
+{
+       unsigned long newvalue = 0, value;
+
+       /* Set the GPIO to external interrupt mode */
+       value = __raw_readl(gpcon_reg);
+       value = (value & ~(3 << gpcon_offset)) | (0x02 << gpcon_offset);
+       __raw_writel(value, gpcon_reg);
+
+       /* Set the external interrupt to pointed trigger type */
+       switch (type)
+       {
+               case IRQ_TYPE_NONE:
+                       pr_warn("No edge setting!\n");
+                       break;
+
+               case IRQ_TYPE_EDGE_RISING:
+                       newvalue = S3C2410_EXTINT_RISEEDGE;
+                       break;
+
+               case IRQ_TYPE_EDGE_FALLING:
+                       newvalue = S3C2410_EXTINT_FALLEDGE;
+                       break;
+
+               case IRQ_TYPE_EDGE_BOTH:
+                       newvalue = S3C2410_EXTINT_BOTHEDGE;
+                       break;
+
+               case IRQ_TYPE_LEVEL_LOW:
+                       newvalue = S3C2410_EXTINT_LOWLEV;
+                       break;
+
+               case IRQ_TYPE_LEVEL_HIGH:
+                       newvalue = S3C2410_EXTINT_HILEV;
+                       break;
+
+               default:
+                       pr_err("No such irq type %d", type);
+                       return -EINVAL;
+       }
+
+       value = __raw_readl(extint_reg);
+       value = (value & ~(7 << extint_offset)) | (newvalue << extint_offset);
+       __raw_writel(value, extint_reg);
+
+       return 0;
+}
+
+static int s3c_irqext_type(struct irq_data *data, unsigned int type)
+{
+       void __iomem *extint_reg;
+       void __iomem *gpcon_reg;
+       unsigned long gpcon_offset, extint_offset;
+
+       if ((data->hwirq >= 4) && (data->hwirq <= 7)) {
+               gpcon_reg = S3C2410_GPFCON;
+               extint_reg = S3C24XX_EXTINT0;
+               gpcon_offset = (data->hwirq) * 2;
+               extint_offset = (data->hwirq) * 4;
+       } else if ((data->hwirq >= 8) && (data->hwirq <= 15)) {
+               gpcon_reg = S3C2410_GPGCON;
+               extint_reg = S3C24XX_EXTINT1;
+               gpcon_offset = (data->hwirq - 8) * 2;
+               extint_offset = (data->hwirq - 8) * 4;
+       } else if ((data->hwirq >= 16) && (data->hwirq <= 23)) {
+               gpcon_reg = S3C2410_GPGCON;
+               extint_reg = S3C24XX_EXTINT2;
+               gpcon_offset = (data->hwirq - 8) * 2;
+               extint_offset = (data->hwirq - 16) * 4;
+       } else {
+               return -EINVAL;
+       }
+
+       return s3c_irqext_type_set(gpcon_reg, extint_reg, gpcon_offset,
+                                  extint_offset, type);
+}
+
+static int s3c_irqext0_type(struct irq_data *data, unsigned int type)
+{
+       void __iomem *extint_reg;
+       void __iomem *gpcon_reg;
+       unsigned long gpcon_offset, extint_offset;
+
+       if ((data->hwirq >= 0) && (data->hwirq <= 3)) {
+               gpcon_reg = S3C2410_GPFCON;
+               extint_reg = S3C24XX_EXTINT0;
+               gpcon_offset = (data->hwirq) * 2;
+               extint_offset = (data->hwirq) * 4;
+       } else {
+               return -EINVAL;
+       }
+
+       return s3c_irqext_type_set(gpcon_reg, extint_reg, gpcon_offset,
+                                  extint_offset, type);
+}
+
+static struct irq_chip s3c_irq_chip = {
+       .name           = "s3c",
+       .irq_ack        = s3c_irq_ack,
+       .irq_mask       = s3c_irq_mask,
+       .irq_unmask     = s3c_irq_unmask,
+       .irq_set_type   = s3c_irq_type,
+       .irq_set_wake   = s3c_irq_wake
+};
+
+static struct irq_chip s3c_irq_level_chip = {
+       .name           = "s3c-level",
+       .irq_mask       = s3c_irq_mask,
+       .irq_unmask     = s3c_irq_unmask,
+       .irq_ack        = s3c_irq_ack,
+       .irq_set_type   = s3c_irq_type,
+};
+
+static struct irq_chip s3c_irqext_chip = {
+       .name           = "s3c-ext",
+       .irq_mask       = s3c_irq_mask,
+       .irq_unmask     = s3c_irq_unmask,
+       .irq_ack        = s3c_irq_ack,
+       .irq_set_type   = s3c_irqext_type,
+       .irq_set_wake   = s3c_irqext_wake
+};
+
+static struct irq_chip s3c_irq_eint0t4 = {
+       .name           = "s3c-ext0",
+       .irq_ack        = s3c_irq_ack,
+       .irq_mask       = s3c_irq_mask,
+       .irq_unmask     = s3c_irq_unmask,
+       .irq_set_wake   = s3c_irq_wake,
+       .irq_set_type   = s3c_irqext0_type,
+};
+
+static void s3c_irq_demux(unsigned int irq, struct irq_desc *desc)
+{
+       struct irq_chip *chip = irq_desc_get_chip(desc);
+       struct s3c_irq_data *irq_data = irq_desc_get_chip_data(desc);
+       struct s3c_irq_intc *intc = irq_data->intc;
+       struct s3c_irq_intc *sub_intc = irq_data->sub_intc;
+       unsigned long src;
+       unsigned long msk;
+       unsigned int n;
+       unsigned int offset;
+
+       /* we're using individual domains for the non-dt case
+        * and one big domain for the dt case where the subintc
+        * starts at hwirq number 32.
+        */
+       offset = (intc->domain->of_node) ? 32 : 0;
+
+       chained_irq_enter(chip, desc);
+
+       src = __raw_readl(sub_intc->reg_pending);
+       msk = __raw_readl(sub_intc->reg_mask);
+
+       src &= ~msk;
+       src &= irq_data->sub_bits;
+
+       while (src) {
+               n = __ffs(src);
+               src &= ~(1 << n);
+               irq = irq_find_mapping(sub_intc->domain, offset + n);
+               generic_handle_irq(irq);
+       }
+
+       chained_irq_exit(chip, desc);
+}
+
+static inline int s3c24xx_handle_intc(struct s3c_irq_intc *intc,
+                                     struct pt_regs *regs, int intc_offset)
+{
+       int pnd;
+       int offset;
+       int irq;
+
+       pnd = __raw_readl(intc->reg_intpnd);
+       if (!pnd)
+               return false;
+
+       /* non-dt machines use individual domains */
+       if (!intc->domain->of_node)
+               intc_offset = 0;
+
+       /* We have a problem that the INTOFFSET register does not always
+        * show one interrupt. Occasionally we get two interrupts through
+        * the prioritiser, and this causes the INTOFFSET register to show
+        * what looks like the logical-or of the two interrupt numbers.
+        *
+        * Thanks to Klaus, Shannon, et al for helping to debug this problem
+        */
+       offset = __raw_readl(intc->reg_intpnd + 4);
+
+       /* Find the bit manually, when the offset is wrong.
+        * The pending register only ever contains the one bit of the next
+        * interrupt to handle.
+        */
+       if (!(pnd & (1 << offset)))
+               offset =  __ffs(pnd);
+
+       irq = irq_find_mapping(intc->domain, intc_offset + offset);
+       handle_IRQ(irq, regs);
+       return true;
+}
+
+asmlinkage void __exception_irq_entry s3c24xx_handle_irq(struct pt_regs *regs)
+{
+       do {
+               if (likely(s3c_intc[0]))
+                       if (s3c24xx_handle_intc(s3c_intc[0], regs, 0))
+                               continue;
+
+               if (s3c_intc[2])
+                       if (s3c24xx_handle_intc(s3c_intc[2], regs, 64))
+                               continue;
+
+               break;
+       } while (1);
+}
+
+#ifdef CONFIG_FIQ
+/**
+ * s3c24xx_set_fiq - set the FIQ routing
+ * @irq: IRQ number to route to FIQ on processor.
+ * @on: Whether to route @irq to the FIQ, or to remove the FIQ routing.
+ *
+ * Change the state of the IRQ to FIQ routing depending on @irq and @on. If
+ * @on is true, the @irq is checked to see if it can be routed and the
+ * interrupt controller updated to route the IRQ. If @on is false, the FIQ
+ * routing is cleared, regardless of which @irq is specified.
+ */
+int s3c24xx_set_fiq(unsigned int irq, bool on)
+{
+       u32 intmod;
+       unsigned offs;
+
+       if (on) {
+               offs = irq - FIQ_START;
+               if (offs > 31)
+                       return -EINVAL;
+
+               intmod = 1 << offs;
+       } else {
+               intmod = 0;
+       }
+
+       __raw_writel(intmod, S3C2410_INTMOD);
+       return 0;
+}
+
+EXPORT_SYMBOL_GPL(s3c24xx_set_fiq);
+#endif
+
+static int s3c24xx_irq_map(struct irq_domain *h, unsigned int virq,
+                                                       irq_hw_number_t hw)
+{
+       struct s3c_irq_intc *intc = h->host_data;
+       struct s3c_irq_data *irq_data = &intc->irqs[hw];
+       struct s3c_irq_intc *parent_intc;
+       struct s3c_irq_data *parent_irq_data;
+       unsigned int irqno;
+
+       /* attach controller pointer to irq_data */
+       irq_data->intc = intc;
+       irq_data->offset = hw;
+
+       parent_intc = intc->parent;
+
+       /* set handler and flags */
+       switch (irq_data->type) {
+       case S3C_IRQTYPE_NONE:
+               return 0;
+       case S3C_IRQTYPE_EINT:
+               /* On the S3C2412, the EINT0to3 have a parent irq
+                * but need the s3c_irq_eint0t4 chip
+                */
+               if (parent_intc && (!soc_is_s3c2412() || hw >= 4))
+                       irq_set_chip_and_handler(virq, &s3c_irqext_chip,
+                                                handle_edge_irq);
+               else
+                       irq_set_chip_and_handler(virq, &s3c_irq_eint0t4,
+                                                handle_edge_irq);
+               break;
+       case S3C_IRQTYPE_EDGE:
+               if (parent_intc || intc->reg_pending == S3C2416_SRCPND2)
+                       irq_set_chip_and_handler(virq, &s3c_irq_level_chip,
+                                                handle_edge_irq);
+               else
+                       irq_set_chip_and_handler(virq, &s3c_irq_chip,
+                                                handle_edge_irq);
+               break;
+       case S3C_IRQTYPE_LEVEL:
+               if (parent_intc)
+                       irq_set_chip_and_handler(virq, &s3c_irq_level_chip,
+                                                handle_level_irq);
+               else
+                       irq_set_chip_and_handler(virq, &s3c_irq_chip,
+                                                handle_level_irq);
+               break;
+       default:
+               pr_err("irq-s3c24xx: unsupported irqtype %d\n", irq_data->type);
+               return -EINVAL;
+       }
+
+       irq_set_chip_data(virq, irq_data);
+
+       set_irq_flags(virq, IRQF_VALID);
+
+       if (parent_intc && irq_data->type != S3C_IRQTYPE_NONE) {
+               if (irq_data->parent_irq > 31) {
+                       pr_err("irq-s3c24xx: parent irq %lu is out of range\n",
+                              irq_data->parent_irq);
+                       goto err;
+               }
+
+               parent_irq_data = &parent_intc->irqs[irq_data->parent_irq];
+               parent_irq_data->sub_intc = intc;
+               parent_irq_data->sub_bits |= (1UL << hw);
+
+               /* attach the demuxer to the parent irq */
+               irqno = irq_find_mapping(parent_intc->domain,
+                                        irq_data->parent_irq);
+               if (!irqno) {
+                       pr_err("irq-s3c24xx: could not find mapping for parent irq %lu\n",
+                              irq_data->parent_irq);
+                       goto err;
+               }
+               irq_set_chained_handler(irqno, s3c_irq_demux);
+       }
+
+       return 0;
+
+err:
+       set_irq_flags(virq, 0);
+
+       /* the only error can result from bad mapping data*/
+       return -EINVAL;
+}
+
+static struct irq_domain_ops s3c24xx_irq_ops = {
+       .map = s3c24xx_irq_map,
+       .xlate = irq_domain_xlate_twocell,
+};
+
+static void s3c24xx_clear_intc(struct s3c_irq_intc *intc)
+{
+       void __iomem *reg_source;
+       unsigned long pend;
+       unsigned long last;
+       int i;
+
+       /* if intpnd is set, read the next pending irq from there */
+       reg_source = intc->reg_intpnd ? intc->reg_intpnd : intc->reg_pending;
+
+       last = 0;
+       for (i = 0; i < 4; i++) {
+               pend = __raw_readl(reg_source);
+
+               if (pend == 0 || pend == last)
+                       break;
+
+               __raw_writel(pend, intc->reg_pending);
+               if (intc->reg_intpnd)
+                       __raw_writel(pend, intc->reg_intpnd);
+
+               pr_info("irq: clearing pending status %08x\n", (int)pend);
+               last = pend;
+       }
+}
+
+static struct s3c_irq_intc *s3c24xx_init_intc(struct device_node *np,
+                                      struct s3c_irq_data *irq_data,
+                                      struct s3c_irq_intc *parent,
+                                      unsigned long address)
+{
+       struct s3c_irq_intc *intc;
+       void __iomem *base = (void *)0xf6000000; /* static mapping */
+       int irq_num;
+       int irq_start;
+       int ret;
+
+       intc = kzalloc(sizeof(struct s3c_irq_intc), GFP_KERNEL);
+       if (!intc)
+               return ERR_PTR(-ENOMEM);
+
+       intc->irqs = irq_data;
+
+       if (parent)
+               intc->parent = parent;
+
+       /* select the correct data for the controller.
+        * Need to hard code the irq num start and offset
+        * to preserve the static mapping for now
+        */
+       switch (address) {
+       case 0x4a000000:
+               pr_debug("irq: found main intc\n");
+               intc->reg_pending = base;
+               intc->reg_mask = base + 0x08;
+               intc->reg_intpnd = base + 0x10;
+               irq_num = 32;
+               irq_start = S3C2410_IRQ(0);
+               break;
+       case 0x4a000018:
+               pr_debug("irq: found subintc\n");
+               intc->reg_pending = base + 0x18;
+               intc->reg_mask = base + 0x1c;
+               irq_num = 29;
+               irq_start = S3C2410_IRQSUB(0);
+               break;
+       case 0x4a000040:
+               pr_debug("irq: found intc2\n");
+               intc->reg_pending = base + 0x40;
+               intc->reg_mask = base + 0x48;
+               intc->reg_intpnd = base + 0x50;
+               irq_num = 8;
+               irq_start = S3C2416_IRQ(0);
+               break;
+       case 0x560000a4:
+               pr_debug("irq: found eintc\n");
+               base = (void *)0xfd000000;
+
+               intc->reg_mask = base + 0xa4;
+               intc->reg_pending = base + 0x08;
+               irq_num = 24;
+               irq_start = S3C2410_IRQ(32);
+               break;
+       default:
+               pr_err("irq: unsupported controller address\n");
+               ret = -EINVAL;
+               goto err;
+       }
+
+       /* now that all the data is complete, init the irq-domain */
+       s3c24xx_clear_intc(intc);
+       intc->domain = irq_domain_add_legacy(np, irq_num, irq_start,
+                                            0, &s3c24xx_irq_ops,
+                                            intc);
+       if (!intc->domain) {
+               pr_err("irq: could not create irq-domain\n");
+               ret = -EINVAL;
+               goto err;
+       }
+
+       set_handle_irq(s3c24xx_handle_irq);
+
+       return intc;
+
+err:
+       kfree(intc);
+       return ERR_PTR(ret);
+}
+
+static struct s3c_irq_data init_eint[32] = {
+       { .type = S3C_IRQTYPE_NONE, }, /* reserved */
+       { .type = S3C_IRQTYPE_NONE, }, /* reserved */
+       { .type = S3C_IRQTYPE_NONE, }, /* reserved */
+       { .type = S3C_IRQTYPE_NONE, }, /* reserved */
+       { .type = S3C_IRQTYPE_EINT, .parent_irq = 4 }, /* EINT4 */
+       { .type = S3C_IRQTYPE_EINT, .parent_irq = 4 }, /* EINT5 */
+       { .type = S3C_IRQTYPE_EINT, .parent_irq = 4 }, /* EINT6 */
+       { .type = S3C_IRQTYPE_EINT, .parent_irq = 4 }, /* EINT7 */
+       { .type = S3C_IRQTYPE_EINT, .parent_irq = 5 }, /* EINT8 */
+       { .type = S3C_IRQTYPE_EINT, .parent_irq = 5 }, /* EINT9 */
+       { .type = S3C_IRQTYPE_EINT, .parent_irq = 5 }, /* EINT10 */
+       { .type = S3C_IRQTYPE_EINT, .parent_irq = 5 }, /* EINT11 */
+       { .type = S3C_IRQTYPE_EINT, .parent_irq = 5 }, /* EINT12 */
+       { .type = S3C_IRQTYPE_EINT, .parent_irq = 5 }, /* EINT13 */
+       { .type = S3C_IRQTYPE_EINT, .parent_irq = 5 }, /* EINT14 */
+       { .type = S3C_IRQTYPE_EINT, .parent_irq = 5 }, /* EINT15 */
+       { .type = S3C_IRQTYPE_EINT, .parent_irq = 5 }, /* EINT16 */
+       { .type = S3C_IRQTYPE_EINT, .parent_irq = 5 }, /* EINT17 */
+       { .type = S3C_IRQTYPE_EINT, .parent_irq = 5 }, /* EINT18 */
+       { .type = S3C_IRQTYPE_EINT, .parent_irq = 5 }, /* EINT19 */
+       { .type = S3C_IRQTYPE_EINT, .parent_irq = 5 }, /* EINT20 */
+       { .type = S3C_IRQTYPE_EINT, .parent_irq = 5 }, /* EINT21 */
+       { .type = S3C_IRQTYPE_EINT, .parent_irq = 5 }, /* EINT22 */
+       { .type = S3C_IRQTYPE_EINT, .parent_irq = 5 }, /* EINT23 */
+};
+
+#ifdef CONFIG_CPU_S3C2410
+static struct s3c_irq_data init_s3c2410base[32] = {
+       { .type = S3C_IRQTYPE_EINT, }, /* EINT0 */
+       { .type = S3C_IRQTYPE_EINT, }, /* EINT1 */
+       { .type = S3C_IRQTYPE_EINT, }, /* EINT2 */
+       { .type = S3C_IRQTYPE_EINT, }, /* EINT3 */
+       { .type = S3C_IRQTYPE_LEVEL, }, /* EINT4to7 */
+       { .type = S3C_IRQTYPE_LEVEL, }, /* EINT8to23 */
+       { .type = S3C_IRQTYPE_NONE, }, /* reserved */
+       { .type = S3C_IRQTYPE_EDGE, }, /* nBATT_FLT */
+       { .type = S3C_IRQTYPE_EDGE, }, /* TICK */
+       { .type = S3C_IRQTYPE_EDGE, }, /* WDT */
+       { .type = S3C_IRQTYPE_EDGE, }, /* TIMER0 */
+       { .type = S3C_IRQTYPE_EDGE, }, /* TIMER1 */
+       { .type = S3C_IRQTYPE_EDGE, }, /* TIMER2 */
+       { .type = S3C_IRQTYPE_EDGE, }, /* TIMER3 */
+       { .type = S3C_IRQTYPE_EDGE, }, /* TIMER4 */
+       { .type = S3C_IRQTYPE_LEVEL, }, /* UART2 */
+       { .type = S3C_IRQTYPE_EDGE, }, /* LCD */
+       { .type = S3C_IRQTYPE_EDGE, }, /* DMA0 */
+       { .type = S3C_IRQTYPE_EDGE, }, /* DMA1 */
+       { .type = S3C_IRQTYPE_EDGE, }, /* DMA2 */
+       { .type = S3C_IRQTYPE_EDGE, }, /* DMA3 */
+       { .type = S3C_IRQTYPE_EDGE, }, /* SDI */
+       { .type = S3C_IRQTYPE_EDGE, }, /* SPI0 */
+       { .type = S3C_IRQTYPE_LEVEL, }, /* UART1 */
+       { .type = S3C_IRQTYPE_NONE, }, /* reserved */
+       { .type = S3C_IRQTYPE_EDGE, }, /* USBD */
+       { .type = S3C_IRQTYPE_EDGE, }, /* USBH */
+       { .type = S3C_IRQTYPE_EDGE, }, /* IIC */
+       { .type = S3C_IRQTYPE_LEVEL, }, /* UART0 */
+       { .type = S3C_IRQTYPE_EDGE, }, /* SPI1 */
+       { .type = S3C_IRQTYPE_EDGE, }, /* RTC */
+       { .type = S3C_IRQTYPE_LEVEL, }, /* ADCPARENT */
+};
+
+static struct s3c_irq_data init_s3c2410subint[32] = {
+       { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 28 }, /* UART0-RX */
+       { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 28 }, /* UART0-TX */
+       { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 28 }, /* UART0-ERR */
+       { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 23 }, /* UART1-RX */
+       { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 23 }, /* UART1-TX */
+       { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 23 }, /* UART1-ERR */
+       { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 15 }, /* UART2-RX */
+       { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 15 }, /* UART2-TX */
+       { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 15 }, /* UART2-ERR */
+       { .type = S3C_IRQTYPE_EDGE, .parent_irq = 31 }, /* TC */
+       { .type = S3C_IRQTYPE_EDGE, .parent_irq = 31 }, /* ADC */
+};
+
+void __init s3c2410_init_irq(void)
+{
+#ifdef CONFIG_FIQ
+       init_FIQ(FIQ_START);
+#endif
+
+       s3c_intc[0] = s3c24xx_init_intc(NULL, &init_s3c2410base[0], NULL,
+                                       0x4a000000);
+       if (IS_ERR(s3c_intc[0])) {
+               pr_err("irq: could not create main interrupt controller\n");
+               return;
+       }
+
+       s3c_intc[1] = s3c24xx_init_intc(NULL, &init_s3c2410subint[0],
+                                       s3c_intc[0], 0x4a000018);
+       s3c24xx_init_intc(NULL, &init_eint[0], s3c_intc[0], 0x560000a4);
+}
+#endif
+
+#ifdef CONFIG_CPU_S3C2412
+static struct s3c_irq_data init_s3c2412base[32] = {
+       { .type = S3C_IRQTYPE_LEVEL, }, /* EINT0 */
+       { .type = S3C_IRQTYPE_LEVEL, }, /* EINT1 */
+       { .type = S3C_IRQTYPE_LEVEL, }, /* EINT2 */
+       { .type = S3C_IRQTYPE_LEVEL, }, /* EINT3 */
+       { .type = S3C_IRQTYPE_LEVEL, }, /* EINT4to7 */
+       { .type = S3C_IRQTYPE_LEVEL, }, /* EINT8to23 */
+       { .type = S3C_IRQTYPE_NONE, }, /* reserved */
+       { .type = S3C_IRQTYPE_EDGE, }, /* nBATT_FLT */
+       { .type = S3C_IRQTYPE_EDGE, }, /* TICK */
+       { .type = S3C_IRQTYPE_EDGE, }, /* WDT */
+       { .type = S3C_IRQTYPE_EDGE, }, /* TIMER0 */
+       { .type = S3C_IRQTYPE_EDGE, }, /* TIMER1 */
+       { .type = S3C_IRQTYPE_EDGE, }, /* TIMER2 */
+       { .type = S3C_IRQTYPE_EDGE, }, /* TIMER3 */
+       { .type = S3C_IRQTYPE_EDGE, }, /* TIMER4 */
+       { .type = S3C_IRQTYPE_LEVEL, }, /* UART2 */
+       { .type = S3C_IRQTYPE_EDGE, }, /* LCD */
+       { .type = S3C_IRQTYPE_EDGE, }, /* DMA0 */
+       { .type = S3C_IRQTYPE_EDGE, }, /* DMA1 */
+       { .type = S3C_IRQTYPE_EDGE, }, /* DMA2 */
+       { .type = S3C_IRQTYPE_EDGE, }, /* DMA3 */
+       { .type = S3C_IRQTYPE_LEVEL, }, /* SDI/CF */
+       { .type = S3C_IRQTYPE_EDGE, }, /* SPI0 */
+       { .type = S3C_IRQTYPE_LEVEL, }, /* UART1 */
+       { .type = S3C_IRQTYPE_NONE, }, /* reserved */
+       { .type = S3C_IRQTYPE_EDGE, }, /* USBD */
+       { .type = S3C_IRQTYPE_EDGE, }, /* USBH */
+       { .type = S3C_IRQTYPE_EDGE, }, /* IIC */
+       { .type = S3C_IRQTYPE_LEVEL, }, /* UART0 */
+       { .type = S3C_IRQTYPE_EDGE, }, /* SPI1 */
+       { .type = S3C_IRQTYPE_EDGE, }, /* RTC */
+       { .type = S3C_IRQTYPE_LEVEL, }, /* ADCPARENT */
+};
+
+static struct s3c_irq_data init_s3c2412eint[32] = {
+       { .type = S3C_IRQTYPE_EINT, .parent_irq = 0 }, /* EINT0 */
+       { .type = S3C_IRQTYPE_EINT, .parent_irq = 1 }, /* EINT1 */
+       { .type = S3C_IRQTYPE_EINT, .parent_irq = 2 }, /* EINT2 */
+       { .type = S3C_IRQTYPE_EINT, .parent_irq = 3 }, /* EINT3 */
+       { .type = S3C_IRQTYPE_EINT, .parent_irq = 4 }, /* EINT4 */
+       { .type = S3C_IRQTYPE_EINT, .parent_irq = 4 }, /* EINT5 */
+       { .type = S3C_IRQTYPE_EINT, .parent_irq = 4 }, /* EINT6 */
+       { .type = S3C_IRQTYPE_EINT, .parent_irq = 4 }, /* EINT7 */
+       { .type = S3C_IRQTYPE_EINT, .parent_irq = 5 }, /* EINT8 */
+       { .type = S3C_IRQTYPE_EINT, .parent_irq = 5 }, /* EINT9 */
+       { .type = S3C_IRQTYPE_EINT, .parent_irq = 5 }, /* EINT10 */
+       { .type = S3C_IRQTYPE_EINT, .parent_irq = 5 }, /* EINT11 */
+       { .type = S3C_IRQTYPE_EINT, .parent_irq = 5 }, /* EINT12 */
+       { .type = S3C_IRQTYPE_EINT, .parent_irq = 5 }, /* EINT13 */
+       { .type = S3C_IRQTYPE_EINT, .parent_irq = 5 }, /* EINT14 */
+       { .type = S3C_IRQTYPE_EINT, .parent_irq = 5 }, /* EINT15 */
+       { .type = S3C_IRQTYPE_EINT, .parent_irq = 5 }, /* EINT16 */
+       { .type = S3C_IRQTYPE_EINT, .parent_irq = 5 }, /* EINT17 */
+       { .type = S3C_IRQTYPE_EINT, .parent_irq = 5 }, /* EINT18 */
+       { .type = S3C_IRQTYPE_EINT, .parent_irq = 5 }, /* EINT19 */
+       { .type = S3C_IRQTYPE_EINT, .parent_irq = 5 }, /* EINT20 */
+       { .type = S3C_IRQTYPE_EINT, .parent_irq = 5 }, /* EINT21 */
+       { .type = S3C_IRQTYPE_EINT, .parent_irq = 5 }, /* EINT22 */
+       { .type = S3C_IRQTYPE_EINT, .parent_irq = 5 }, /* EINT23 */
+};
+
+static struct s3c_irq_data init_s3c2412subint[32] = {
+       { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 28 }, /* UART0-RX */
+       { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 28 }, /* UART0-TX */
+       { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 28 }, /* UART0-ERR */
+       { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 23 }, /* UART1-RX */
+       { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 23 }, /* UART1-TX */
+       { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 23 }, /* UART1-ERR */
+       { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 15 }, /* UART2-RX */
+       { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 15 }, /* UART2-TX */
+       { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 15 }, /* UART2-ERR */
+       { .type = S3C_IRQTYPE_EDGE, .parent_irq = 31 }, /* TC */
+       { .type = S3C_IRQTYPE_EDGE, .parent_irq = 31 }, /* ADC */
+       { .type = S3C_IRQTYPE_NONE, },
+       { .type = S3C_IRQTYPE_NONE, },
+       { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 21 }, /* SDI */
+       { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 21 }, /* CF */
+};
+
+void s3c2412_init_irq(void)
+{
+       pr_info("S3C2412: IRQ Support\n");
+
+#ifdef CONFIG_FIQ
+       init_FIQ(FIQ_START);
+#endif
+
+       s3c_intc[0] = s3c24xx_init_intc(NULL, &init_s3c2412base[0], NULL,
+                                       0x4a000000);
+       if (IS_ERR(s3c_intc[0])) {
+               pr_err("irq: could not create main interrupt controller\n");
+               return;
+       }
+
+       s3c24xx_init_intc(NULL, &init_s3c2412eint[0], s3c_intc[0], 0x560000a4);
+       s3c_intc[1] = s3c24xx_init_intc(NULL, &init_s3c2412subint[0],
+                                       s3c_intc[0], 0x4a000018);
+}
+#endif
+
+#ifdef CONFIG_CPU_S3C2416
+static struct s3c_irq_data init_s3c2416base[32] = {
+       { .type = S3C_IRQTYPE_EINT, }, /* EINT0 */
+       { .type = S3C_IRQTYPE_EINT, }, /* EINT1 */
+       { .type = S3C_IRQTYPE_EINT, }, /* EINT2 */
+       { .type = S3C_IRQTYPE_EINT, }, /* EINT3 */
+       { .type = S3C_IRQTYPE_LEVEL, }, /* EINT4to7 */
+       { .type = S3C_IRQTYPE_LEVEL, }, /* EINT8to23 */
+       { .type = S3C_IRQTYPE_NONE, }, /* reserved */
+       { .type = S3C_IRQTYPE_EDGE, }, /* nBATT_FLT */
+       { .type = S3C_IRQTYPE_EDGE, }, /* TICK */
+       { .type = S3C_IRQTYPE_LEVEL, }, /* WDT/AC97 */
+       { .type = S3C_IRQTYPE_EDGE, }, /* TIMER0 */
+       { .type = S3C_IRQTYPE_EDGE, }, /* TIMER1 */
+       { .type = S3C_IRQTYPE_EDGE, }, /* TIMER2 */
+       { .type = S3C_IRQTYPE_EDGE, }, /* TIMER3 */
+       { .type = S3C_IRQTYPE_EDGE, }, /* TIMER4 */
+       { .type = S3C_IRQTYPE_LEVEL, }, /* UART2 */
+       { .type = S3C_IRQTYPE_LEVEL, }, /* LCD */
+       { .type = S3C_IRQTYPE_LEVEL, }, /* DMA */
+       { .type = S3C_IRQTYPE_LEVEL, }, /* UART3 */
+       { .type = S3C_IRQTYPE_NONE, }, /* reserved */
+       { .type = S3C_IRQTYPE_EDGE, }, /* SDI1 */
+       { .type = S3C_IRQTYPE_EDGE, }, /* SDI0 */
+       { .type = S3C_IRQTYPE_EDGE, }, /* SPI0 */
+       { .type = S3C_IRQTYPE_LEVEL, }, /* UART1 */
+       { .type = S3C_IRQTYPE_EDGE, }, /* NAND */
+       { .type = S3C_IRQTYPE_EDGE, }, /* USBD */
+       { .type = S3C_IRQTYPE_EDGE, }, /* USBH */
+       { .type = S3C_IRQTYPE_EDGE, }, /* IIC */
+       { .type = S3C_IRQTYPE_LEVEL, }, /* UART0 */
+       { .type = S3C_IRQTYPE_NONE, },
+       { .type = S3C_IRQTYPE_EDGE, }, /* RTC */
+       { .type = S3C_IRQTYPE_LEVEL, }, /* ADCPARENT */
+};
+
+static struct s3c_irq_data init_s3c2416subint[32] = {
+       { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 28 }, /* UART0-RX */
+       { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 28 }, /* UART0-TX */
+       { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 28 }, /* UART0-ERR */
+       { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 23 }, /* UART1-RX */
+       { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 23 }, /* UART1-TX */
+       { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 23 }, /* UART1-ERR */
+       { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 15 }, /* UART2-RX */
+       { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 15 }, /* UART2-TX */
+       { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 15 }, /* UART2-ERR */
+       { .type = S3C_IRQTYPE_EDGE, .parent_irq = 31 }, /* TC */
+       { .type = S3C_IRQTYPE_EDGE, .parent_irq = 31 }, /* ADC */
+       { .type = S3C_IRQTYPE_NONE }, /* reserved */
+       { .type = S3C_IRQTYPE_NONE }, /* reserved */
+       { .type = S3C_IRQTYPE_NONE }, /* reserved */
+       { .type = S3C_IRQTYPE_NONE }, /* reserved */
+       { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 16 }, /* LCD2 */
+       { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 16 }, /* LCD3 */
+       { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 16 }, /* LCD4 */
+       { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 17 }, /* DMA0 */
+       { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 17 }, /* DMA1 */
+       { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 17 }, /* DMA2 */
+       { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 17 }, /* DMA3 */
+       { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 17 }, /* DMA4 */
+       { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 17 }, /* DMA5 */
+       { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 18 }, /* UART3-RX */
+       { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 18 }, /* UART3-TX */
+       { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 18 }, /* UART3-ERR */
+       { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 9 }, /* WDT */
+       { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 9 }, /* AC97 */
+};
+
+static struct s3c_irq_data init_s3c2416_second[32] = {
+       { .type = S3C_IRQTYPE_EDGE }, /* 2D */
+       { .type = S3C_IRQTYPE_NONE }, /* reserved */
+       { .type = S3C_IRQTYPE_NONE }, /* reserved */
+       { .type = S3C_IRQTYPE_NONE }, /* reserved */
+       { .type = S3C_IRQTYPE_EDGE }, /* PCM0 */
+       { .type = S3C_IRQTYPE_NONE }, /* reserved */
+       { .type = S3C_IRQTYPE_EDGE }, /* I2S0 */
+};
+
+void __init s3c2416_init_irq(void)
+{
+       pr_info("S3C2416: IRQ Support\n");
+
+#ifdef CONFIG_FIQ
+       init_FIQ(FIQ_START);
+#endif
+
+       s3c_intc[0] = s3c24xx_init_intc(NULL, &init_s3c2416base[0], NULL,
+                                       0x4a000000);
+       if (IS_ERR(s3c_intc[0])) {
+               pr_err("irq: could not create main interrupt controller\n");
+               return;
+       }
+
+       s3c24xx_init_intc(NULL, &init_eint[0], s3c_intc[0], 0x560000a4);
+       s3c_intc[1] = s3c24xx_init_intc(NULL, &init_s3c2416subint[0],
+                                       s3c_intc[0], 0x4a000018);
+
+       s3c_intc[2] = s3c24xx_init_intc(NULL, &init_s3c2416_second[0],
+                                       NULL, 0x4a000040);
+}
+
+#endif
+
+#ifdef CONFIG_CPU_S3C2440
+static struct s3c_irq_data init_s3c2440base[32] = {
+       { .type = S3C_IRQTYPE_EINT, }, /* EINT0 */
+       { .type = S3C_IRQTYPE_EINT, }, /* EINT1 */
+       { .type = S3C_IRQTYPE_EINT, }, /* EINT2 */
+       { .type = S3C_IRQTYPE_EINT, }, /* EINT3 */
+       { .type = S3C_IRQTYPE_LEVEL, }, /* EINT4to7 */
+       { .type = S3C_IRQTYPE_LEVEL, }, /* EINT8to23 */
+       { .type = S3C_IRQTYPE_LEVEL, }, /* CAM */
+       { .type = S3C_IRQTYPE_EDGE, }, /* nBATT_FLT */
+       { .type = S3C_IRQTYPE_EDGE, }, /* TICK */
+       { .type = S3C_IRQTYPE_LEVEL, }, /* WDT/AC97 */
+       { .type = S3C_IRQTYPE_EDGE, }, /* TIMER0 */
+       { .type = S3C_IRQTYPE_EDGE, }, /* TIMER1 */
+       { .type = S3C_IRQTYPE_EDGE, }, /* TIMER2 */
+       { .type = S3C_IRQTYPE_EDGE, }, /* TIMER3 */
+       { .type = S3C_IRQTYPE_EDGE, }, /* TIMER4 */
+       { .type = S3C_IRQTYPE_LEVEL, }, /* UART2 */
+       { .type = S3C_IRQTYPE_EDGE, }, /* LCD */
+       { .type = S3C_IRQTYPE_EDGE, }, /* DMA0 */
+       { .type = S3C_IRQTYPE_EDGE, }, /* DMA1 */
+       { .type = S3C_IRQTYPE_EDGE, }, /* DMA2 */
+       { .type = S3C_IRQTYPE_EDGE, }, /* DMA3 */
+       { .type = S3C_IRQTYPE_EDGE, }, /* SDI */
+       { .type = S3C_IRQTYPE_EDGE, }, /* SPI0 */
+       { .type = S3C_IRQTYPE_LEVEL, }, /* UART1 */
+       { .type = S3C_IRQTYPE_LEVEL, }, /* NFCON */
+       { .type = S3C_IRQTYPE_EDGE, }, /* USBD */
+       { .type = S3C_IRQTYPE_EDGE, }, /* USBH */
+       { .type = S3C_IRQTYPE_EDGE, }, /* IIC */
+       { .type = S3C_IRQTYPE_LEVEL, }, /* UART0 */
+       { .type = S3C_IRQTYPE_EDGE, }, /* SPI1 */
+       { .type = S3C_IRQTYPE_EDGE, }, /* RTC */
+       { .type = S3C_IRQTYPE_LEVEL, }, /* ADCPARENT */
+};
+
+static struct s3c_irq_data init_s3c2440subint[32] = {
+       { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 28 }, /* UART0-RX */
+       { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 28 }, /* UART0-TX */
+       { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 28 }, /* UART0-ERR */
+       { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 23 }, /* UART1-RX */
+       { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 23 }, /* UART1-TX */
+       { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 23 }, /* UART1-ERR */
+       { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 15 }, /* UART2-RX */
+       { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 15 }, /* UART2-TX */
+       { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 15 }, /* UART2-ERR */
+       { .type = S3C_IRQTYPE_EDGE, .parent_irq = 31 }, /* TC */
+       { .type = S3C_IRQTYPE_EDGE, .parent_irq = 31 }, /* ADC */
+       { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 6 }, /* CAM_C */
+       { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 6 }, /* CAM_P */
+       { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 9 }, /* WDT */
+       { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 9 }, /* AC97 */
+};
+
+void __init s3c2440_init_irq(void)
+{
+       pr_info("S3C2440: IRQ Support\n");
+
+#ifdef CONFIG_FIQ
+       init_FIQ(FIQ_START);
+#endif
+
+       s3c_intc[0] = s3c24xx_init_intc(NULL, &init_s3c2440base[0], NULL,
+                                       0x4a000000);
+       if (IS_ERR(s3c_intc[0])) {
+               pr_err("irq: could not create main interrupt controller\n");
+               return;
+       }
+
+       s3c24xx_init_intc(NULL, &init_eint[0], s3c_intc[0], 0x560000a4);
+       s3c_intc[1] = s3c24xx_init_intc(NULL, &init_s3c2440subint[0],
+                                       s3c_intc[0], 0x4a000018);
+}
+#endif
+
+#ifdef CONFIG_CPU_S3C2442
+static struct s3c_irq_data init_s3c2442base[32] = {
+       { .type = S3C_IRQTYPE_EINT, }, /* EINT0 */
+       { .type = S3C_IRQTYPE_EINT, }, /* EINT1 */
+       { .type = S3C_IRQTYPE_EINT, }, /* EINT2 */
+       { .type = S3C_IRQTYPE_EINT, }, /* EINT3 */
+       { .type = S3C_IRQTYPE_LEVEL, }, /* EINT4to7 */
+       { .type = S3C_IRQTYPE_LEVEL, }, /* EINT8to23 */
+       { .type = S3C_IRQTYPE_LEVEL, }, /* CAM */
+       { .type = S3C_IRQTYPE_EDGE, }, /* nBATT_FLT */
+       { .type = S3C_IRQTYPE_EDGE, }, /* TICK */
+       { .type = S3C_IRQTYPE_EDGE, }, /* WDT */
+       { .type = S3C_IRQTYPE_EDGE, }, /* TIMER0 */
+       { .type = S3C_IRQTYPE_EDGE, }, /* TIMER1 */
+       { .type = S3C_IRQTYPE_EDGE, }, /* TIMER2 */
+       { .type = S3C_IRQTYPE_EDGE, }, /* TIMER3 */
+       { .type = S3C_IRQTYPE_EDGE, }, /* TIMER4 */
+       { .type = S3C_IRQTYPE_LEVEL, }, /* UART2 */
+       { .type = S3C_IRQTYPE_EDGE, }, /* LCD */
+       { .type = S3C_IRQTYPE_EDGE, }, /* DMA0 */
+       { .type = S3C_IRQTYPE_EDGE, }, /* DMA1 */
+       { .type = S3C_IRQTYPE_EDGE, }, /* DMA2 */
+       { .type = S3C_IRQTYPE_EDGE, }, /* DMA3 */
+       { .type = S3C_IRQTYPE_EDGE, }, /* SDI */
+       { .type = S3C_IRQTYPE_EDGE, }, /* SPI0 */
+       { .type = S3C_IRQTYPE_LEVEL, }, /* UART1 */
+       { .type = S3C_IRQTYPE_LEVEL, }, /* NFCON */
+       { .type = S3C_IRQTYPE_EDGE, }, /* USBD */
+       { .type = S3C_IRQTYPE_EDGE, }, /* USBH */
+       { .type = S3C_IRQTYPE_EDGE, }, /* IIC */
+       { .type = S3C_IRQTYPE_LEVEL, }, /* UART0 */
+       { .type = S3C_IRQTYPE_EDGE, }, /* SPI1 */
+       { .type = S3C_IRQTYPE_EDGE, }, /* RTC */
+       { .type = S3C_IRQTYPE_LEVEL, }, /* ADCPARENT */
+};
+
+static struct s3c_irq_data init_s3c2442subint[32] = {
+       { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 28 }, /* UART0-RX */
+       { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 28 }, /* UART0-TX */
+       { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 28 }, /* UART0-ERR */
+       { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 23 }, /* UART1-RX */
+       { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 23 }, /* UART1-TX */
+       { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 23 }, /* UART1-ERR */
+       { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 15 }, /* UART2-RX */
+       { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 15 }, /* UART2-TX */
+       { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 15 }, /* UART2-ERR */
+       { .type = S3C_IRQTYPE_EDGE, .parent_irq = 31 }, /* TC */
+       { .type = S3C_IRQTYPE_EDGE, .parent_irq = 31 }, /* ADC */
+       { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 6 }, /* CAM_C */
+       { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 6 }, /* CAM_P */
+};
+
+void __init s3c2442_init_irq(void)
+{
+       pr_info("S3C2442: IRQ Support\n");
+
+#ifdef CONFIG_FIQ
+       init_FIQ(FIQ_START);
+#endif
+
+       s3c_intc[0] = s3c24xx_init_intc(NULL, &init_s3c2442base[0], NULL,
+                                       0x4a000000);
+       if (IS_ERR(s3c_intc[0])) {
+               pr_err("irq: could not create main interrupt controller\n");
+               return;
+       }
+
+       s3c24xx_init_intc(NULL, &init_eint[0], s3c_intc[0], 0x560000a4);
+       s3c_intc[1] = s3c24xx_init_intc(NULL, &init_s3c2442subint[0],
+                                       s3c_intc[0], 0x4a000018);
+}
+#endif
+
+#ifdef CONFIG_CPU_S3C2443
+static struct s3c_irq_data init_s3c2443base[32] = {
+       { .type = S3C_IRQTYPE_EINT, }, /* EINT0 */
+       { .type = S3C_IRQTYPE_EINT, }, /* EINT1 */
+       { .type = S3C_IRQTYPE_EINT, }, /* EINT2 */
+       { .type = S3C_IRQTYPE_EINT, }, /* EINT3 */
+       { .type = S3C_IRQTYPE_LEVEL, }, /* EINT4to7 */
+       { .type = S3C_IRQTYPE_LEVEL, }, /* EINT8to23 */
+       { .type = S3C_IRQTYPE_LEVEL, }, /* CAM */
+       { .type = S3C_IRQTYPE_EDGE, }, /* nBATT_FLT */
+       { .type = S3C_IRQTYPE_EDGE, }, /* TICK */
+       { .type = S3C_IRQTYPE_LEVEL, }, /* WDT/AC97 */
+       { .type = S3C_IRQTYPE_EDGE, }, /* TIMER0 */
+       { .type = S3C_IRQTYPE_EDGE, }, /* TIMER1 */
+       { .type = S3C_IRQTYPE_EDGE, }, /* TIMER2 */
+       { .type = S3C_IRQTYPE_EDGE, }, /* TIMER3 */
+       { .type = S3C_IRQTYPE_EDGE, }, /* TIMER4 */
+       { .type = S3C_IRQTYPE_LEVEL, }, /* UART2 */
+       { .type = S3C_IRQTYPE_LEVEL, }, /* LCD */
+       { .type = S3C_IRQTYPE_LEVEL, }, /* DMA */
+       { .type = S3C_IRQTYPE_LEVEL, }, /* UART3 */
+       { .type = S3C_IRQTYPE_EDGE, }, /* CFON */
+       { .type = S3C_IRQTYPE_EDGE, }, /* SDI1 */
+       { .type = S3C_IRQTYPE_EDGE, }, /* SDI0 */
+       { .type = S3C_IRQTYPE_EDGE, }, /* SPI0 */
+       { .type = S3C_IRQTYPE_LEVEL, }, /* UART1 */
+       { .type = S3C_IRQTYPE_EDGE, }, /* NAND */
+       { .type = S3C_IRQTYPE_EDGE, }, /* USBD */
+       { .type = S3C_IRQTYPE_EDGE, }, /* USBH */
+       { .type = S3C_IRQTYPE_EDGE, }, /* IIC */
+       { .type = S3C_IRQTYPE_LEVEL, }, /* UART0 */
+       { .type = S3C_IRQTYPE_EDGE, }, /* SPI1 */
+       { .type = S3C_IRQTYPE_EDGE, }, /* RTC */
+       { .type = S3C_IRQTYPE_LEVEL, }, /* ADCPARENT */
+};
+
+
+static struct s3c_irq_data init_s3c2443subint[32] = {
+       { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 28 }, /* UART0-RX */
+       { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 28 }, /* UART0-TX */
+       { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 28 }, /* UART0-ERR */
+       { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 23 }, /* UART1-RX */
+       { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 23 }, /* UART1-TX */
+       { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 23 }, /* UART1-ERR */
+       { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 15 }, /* UART2-RX */
+       { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 15 }, /* UART2-TX */
+       { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 15 }, /* UART2-ERR */
+       { .type = S3C_IRQTYPE_EDGE, .parent_irq = 31 }, /* TC */
+       { .type = S3C_IRQTYPE_EDGE, .parent_irq = 31 }, /* ADC */
+       { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 6 }, /* CAM_C */
+       { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 6 }, /* CAM_P */
+       { .type = S3C_IRQTYPE_NONE }, /* reserved */
+       { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 16 }, /* LCD1 */
+       { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 16 }, /* LCD2 */
+       { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 16 }, /* LCD3 */
+       { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 16 }, /* LCD4 */
+       { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 17 }, /* DMA0 */
+       { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 17 }, /* DMA1 */
+       { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 17 }, /* DMA2 */
+       { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 17 }, /* DMA3 */
+       { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 17 }, /* DMA4 */
+       { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 17 }, /* DMA5 */
+       { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 18 }, /* UART3-RX */
+       { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 18 }, /* UART3-TX */
+       { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 18 }, /* UART3-ERR */
+       { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 9 }, /* WDT */
+       { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 9 }, /* AC97 */
+};
+
+void __init s3c2443_init_irq(void)
+{
+       pr_info("S3C2443: IRQ Support\n");
+
+#ifdef CONFIG_FIQ
+       init_FIQ(FIQ_START);
+#endif
+
+       s3c_intc[0] = s3c24xx_init_intc(NULL, &init_s3c2443base[0], NULL,
+                                       0x4a000000);
+       if (IS_ERR(s3c_intc[0])) {
+               pr_err("irq: could not create main interrupt controller\n");
+               return;
+       }
+
+       s3c24xx_init_intc(NULL, &init_eint[0], s3c_intc[0], 0x560000a4);
+       s3c_intc[1] = s3c24xx_init_intc(NULL, &init_s3c2443subint[0],
+                                       s3c_intc[0], 0x4a000018);
+}
+#endif
+
+#ifdef CONFIG_OF
+static int s3c24xx_irq_map_of(struct irq_domain *h, unsigned int virq,
+                                                       irq_hw_number_t hw)
+{
+       unsigned int ctrl_num = hw / 32;
+       unsigned int intc_hw = hw % 32;
+       struct s3c_irq_intc *intc = s3c_intc[ctrl_num];
+       struct s3c_irq_intc *parent_intc = intc->parent;
+       struct s3c_irq_data *irq_data = &intc->irqs[intc_hw];
+
+       /* attach controller pointer to irq_data */
+       irq_data->intc = intc;
+       irq_data->offset = intc_hw;
+
+       if (!parent_intc)
+               irq_set_chip_and_handler(virq, &s3c_irq_chip, handle_edge_irq);
+       else
+               irq_set_chip_and_handler(virq, &s3c_irq_level_chip,
+                                        handle_edge_irq);
+
+       irq_set_chip_data(virq, irq_data);
+
+       set_irq_flags(virq, IRQF_VALID);
+
+       return 0;
+}
+
+/* Translate our of irq notation
+ * format: <ctrl_num ctrl_irq parent_irq type>
+ */
+static int s3c24xx_irq_xlate_of(struct irq_domain *d, struct device_node *n,
+                       const u32 *intspec, unsigned int intsize,
+                       irq_hw_number_t *out_hwirq, unsigned int *out_type)
+{
+       struct s3c_irq_intc *intc;
+       struct s3c_irq_intc *parent_intc;
+       struct s3c_irq_data *irq_data;
+       struct s3c_irq_data *parent_irq_data;
+       int irqno;
+
+       if (WARN_ON(intsize < 4))
+               return -EINVAL;
+
+       if (intspec[0] > 2 || !s3c_intc[intspec[0]]) {
+               pr_err("controller number %d invalid\n", intspec[0]);
+               return -EINVAL;
+       }
+       intc = s3c_intc[intspec[0]];
+
+       *out_hwirq = intspec[0] * 32 + intspec[2];
+       *out_type = intspec[3] & IRQ_TYPE_SENSE_MASK;
+
+       parent_intc = intc->parent;
+       if (parent_intc) {
+               irq_data = &intc->irqs[intspec[2]];
+               irq_data->parent_irq = intspec[1];
+               parent_irq_data = &parent_intc->irqs[irq_data->parent_irq];
+               parent_irq_data->sub_intc = intc;
+               parent_irq_data->sub_bits |= (1UL << intspec[2]);
+
+               /* parent_intc is always s3c_intc[0], so no offset */
+               irqno = irq_create_mapping(parent_intc->domain, intspec[1]);
+               if (irqno < 0) {
+                       pr_err("irq: could not map parent interrupt\n");
+                       return irqno;
+               }
+
+               irq_set_chained_handler(irqno, s3c_irq_demux);
+       }
+
+       return 0;
+}
+
+static struct irq_domain_ops s3c24xx_irq_ops_of = {
+       .map = s3c24xx_irq_map_of,
+       .xlate = s3c24xx_irq_xlate_of,
+};
+
+struct s3c24xx_irq_of_ctrl {
+       char                    *name;
+       unsigned long           offset;
+       struct s3c_irq_intc     **handle;
+       struct s3c_irq_intc     **parent;
+       struct irq_domain_ops   *ops;
+};
+
+static int __init s3c_init_intc_of(struct device_node *np,
+                       struct device_node *interrupt_parent,
+                       struct s3c24xx_irq_of_ctrl *s3c_ctrl, int num_ctrl)
+{
+       struct s3c_irq_intc *intc;
+       struct s3c24xx_irq_of_ctrl *ctrl;
+       struct irq_domain *domain;
+       void __iomem *reg_base;
+       int i;
+
+       reg_base = of_iomap(np, 0);
+       if (!reg_base) {
+               pr_err("irq-s3c24xx: could not map irq registers\n");
+               return -EINVAL;
+       }
+
+       domain = irq_domain_add_linear(np, num_ctrl * 32,
+                                                    &s3c24xx_irq_ops_of, NULL);
+       if (!domain) {
+               pr_err("irq: could not create irq-domain\n");
+               return -EINVAL;
+       }
+
+       for (i = 0; i < num_ctrl; i++) {
+               ctrl = &s3c_ctrl[i];
+
+               pr_debug("irq: found controller %s\n", ctrl->name);
+
+               intc = kzalloc(sizeof(struct s3c_irq_intc), GFP_KERNEL);
+               if (!intc)
+                       return -ENOMEM;
+
+               intc->domain = domain;
+               intc->irqs = kzalloc(sizeof(struct s3c_irq_data) * 32,
+                                    GFP_KERNEL);
+               if (!intc->irqs) {
+                       kfree(intc);
+                       return -ENOMEM;
+               }
+
+               if (ctrl->parent) {
+                       intc->reg_pending = reg_base + ctrl->offset;
+                       intc->reg_mask = reg_base + ctrl->offset + 0x4;
+
+                       if (*(ctrl->parent)) {
+                               intc->parent = *(ctrl->parent);
+                       } else {
+                               pr_warn("irq: parent of %s missing\n",
+                                       ctrl->name);
+                               kfree(intc->irqs);
+                               kfree(intc);
+                               continue;
+                       }
+               } else {
+                       intc->reg_pending = reg_base + ctrl->offset;
+                       intc->reg_mask = reg_base + ctrl->offset + 0x08;
+                       intc->reg_intpnd = reg_base + ctrl->offset + 0x10;
+               }
+
+               s3c24xx_clear_intc(intc);
+               s3c_intc[i] = intc;
+       }
+
+       set_handle_irq(s3c24xx_handle_irq);
+
+       return 0;
+}
+
+static struct s3c24xx_irq_of_ctrl s3c2410_ctrl[] = {
+       {
+               .name = "intc",
+               .offset = 0,
+       }, {
+               .name = "subintc",
+               .offset = 0x18,
+               .parent = &s3c_intc[0],
+       }
+};
+
+int __init s3c2410_init_intc_of(struct device_node *np,
+                       struct device_node *interrupt_parent,
+                       struct s3c24xx_irq_of_ctrl *ctrl, int num_ctrl)
+{
+       return s3c_init_intc_of(np, interrupt_parent,
+                               s3c2410_ctrl, ARRAY_SIZE(s3c2410_ctrl));
+}
+IRQCHIP_DECLARE(s3c2410_irq, "samsung,s3c2410-irq", s3c2410_init_intc_of);
+
+static struct s3c24xx_irq_of_ctrl s3c2416_ctrl[] = {
+       {
+               .name = "intc",
+               .offset = 0,
+       }, {
+               .name = "subintc",
+               .offset = 0x18,
+               .parent = &s3c_intc[0],
+       }, {
+               .name = "intc2",
+               .offset = 0x40,
+       }
+};
+
+int __init s3c2416_init_intc_of(struct device_node *np,
+                       struct device_node *interrupt_parent,
+                       struct s3c24xx_irq_of_ctrl *ctrl, int num_ctrl)
+{
+       return s3c_init_intc_of(np, interrupt_parent,
+                               s3c2416_ctrl, ARRAY_SIZE(s3c2416_ctrl));
+}
+IRQCHIP_DECLARE(s3c2416_irq, "samsung,s3c2416-irq", s3c2416_init_intc_of);
+#endif