cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

irq-s3c24xx.c (43073B)


      1// SPDX-License-Identifier: GPL-2.0-or-later
      2/*
      3 * S3C24XX IRQ handling
      4 *
      5 * Copyright (c) 2003-2004 Simtec Electronics
      6 *	Ben Dooks <ben@simtec.co.uk>
      7 * Copyright (c) 2012 Heiko Stuebner <heiko@sntech.de>
      8*/
      9
     10#include <linux/init.h>
     11#include <linux/slab.h>
     12#include <linux/module.h>
     13#include <linux/io.h>
     14#include <linux/err.h>
     15#include <linux/interrupt.h>
     16#include <linux/ioport.h>
     17#include <linux/device.h>
     18#include <linux/irqdomain.h>
     19#include <linux/irqchip.h>
     20#include <linux/irqchip/chained_irq.h>
     21#include <linux/of.h>
     22#include <linux/of_irq.h>
     23#include <linux/of_address.h>
     24#include <linux/spi/s3c24xx.h>
     25
     26#include <asm/exception.h>
     27#include <asm/mach/irq.h>
     28
     29#include "irqs.h"
     30#include "regs-irq.h"
     31#include "regs-gpio.h"
     32
     33#include "cpu.h"
     34#include "regs-irqtype.h"
     35#include "pm.h"
     36#include "s3c24xx.h"
     37
     38#define S3C_IRQTYPE_NONE	0
     39#define S3C_IRQTYPE_EINT	1
     40#define S3C_IRQTYPE_EDGE	2
     41#define S3C_IRQTYPE_LEVEL	3
     42
     43struct s3c_irq_data {
     44	unsigned int type;
     45	unsigned long offset;
     46	unsigned long parent_irq;
     47
     48	/* data gets filled during init */
     49	struct s3c_irq_intc *intc;
     50	unsigned long sub_bits;
     51	struct s3c_irq_intc *sub_intc;
     52};
     53
     54/*
     55 * Structure holding the controller data
     56 * @reg_pending		register holding pending irqs
     57 * @reg_intpnd		special register intpnd in main intc
     58 * @reg_mask		mask register
     59 * @domain		irq_domain of the controller
     60 * @parent		parent controller for ext and sub irqs
     61 * @irqs		irq-data, always s3c_irq_data[32]
     62 */
     63struct s3c_irq_intc {
     64	void __iomem		*reg_pending;
     65	void __iomem		*reg_intpnd;
     66	void __iomem		*reg_mask;
     67	struct irq_domain	*domain;
     68	struct s3c_irq_intc	*parent;
     69	struct s3c_irq_data	*irqs;
     70};
     71
     72/*
     73 * Array holding pointers to the global controller structs
     74 * [0] ... main_intc
     75 * [1] ... sub_intc
     76 * [2] ... main_intc2 on s3c2416
     77 */
     78static struct s3c_irq_intc *s3c_intc[3];
     79
     80static void s3c_irq_mask(struct irq_data *data)
     81{
     82	struct s3c_irq_data *irq_data = irq_data_get_irq_chip_data(data);
     83	struct s3c_irq_intc *intc = irq_data->intc;
     84	struct s3c_irq_intc *parent_intc = intc->parent;
     85	struct s3c_irq_data *parent_data;
     86	unsigned long mask;
     87	unsigned int irqno;
     88
     89	mask = readl_relaxed(intc->reg_mask);
     90	mask |= (1UL << irq_data->offset);
     91	writel_relaxed(mask, intc->reg_mask);
     92
     93	if (parent_intc) {
     94		parent_data = &parent_intc->irqs[irq_data->parent_irq];
     95
     96		/* check to see if we need to mask the parent IRQ
     97		 * The parent_irq is always in main_intc, so the hwirq
     98		 * for find_mapping does not need an offset in any case.
     99		 */
    100		if ((mask & parent_data->sub_bits) == parent_data->sub_bits) {
    101			irqno = irq_find_mapping(parent_intc->domain,
    102					 irq_data->parent_irq);
    103			s3c_irq_mask(irq_get_irq_data(irqno));
    104		}
    105	}
    106}
    107
    108static void s3c_irq_unmask(struct irq_data *data)
    109{
    110	struct s3c_irq_data *irq_data = irq_data_get_irq_chip_data(data);
    111	struct s3c_irq_intc *intc = irq_data->intc;
    112	struct s3c_irq_intc *parent_intc = intc->parent;
    113	unsigned long mask;
    114	unsigned int irqno;
    115
    116	mask = readl_relaxed(intc->reg_mask);
    117	mask &= ~(1UL << irq_data->offset);
    118	writel_relaxed(mask, intc->reg_mask);
    119
    120	if (parent_intc) {
    121		irqno = irq_find_mapping(parent_intc->domain,
    122					 irq_data->parent_irq);
    123		s3c_irq_unmask(irq_get_irq_data(irqno));
    124	}
    125}
    126
    127static inline void s3c_irq_ack(struct irq_data *data)
    128{
    129	struct s3c_irq_data *irq_data = irq_data_get_irq_chip_data(data);
    130	struct s3c_irq_intc *intc = irq_data->intc;
    131	unsigned long bitval = 1UL << irq_data->offset;
    132
    133	writel_relaxed(bitval, intc->reg_pending);
    134	if (intc->reg_intpnd)
    135		writel_relaxed(bitval, intc->reg_intpnd);
    136}
    137
    138static int s3c_irq_type(struct irq_data *data, unsigned int type)
    139{
    140	switch (type) {
    141	case IRQ_TYPE_NONE:
    142		break;
    143	case IRQ_TYPE_EDGE_RISING:
    144	case IRQ_TYPE_EDGE_FALLING:
    145	case IRQ_TYPE_EDGE_BOTH:
    146		irq_set_handler(data->irq, handle_edge_irq);
    147		break;
    148	case IRQ_TYPE_LEVEL_LOW:
    149	case IRQ_TYPE_LEVEL_HIGH:
    150		irq_set_handler(data->irq, handle_level_irq);
    151		break;
    152	default:
    153		pr_err("No such irq type %d\n", type);
    154		return -EINVAL;
    155	}
    156
    157	return 0;
    158}
    159
    160static int s3c_irqext_type_set(void __iomem *gpcon_reg,
    161			       void __iomem *extint_reg,
    162			       unsigned long gpcon_offset,
    163			       unsigned long extint_offset,
    164			       unsigned int type)
    165{
    166	unsigned long newvalue = 0, value;
    167
    168	/* Set the GPIO to external interrupt mode */
    169	value = readl_relaxed(gpcon_reg);
    170	value = (value & ~(3 << gpcon_offset)) | (0x02 << gpcon_offset);
    171	writel_relaxed(value, gpcon_reg);
    172
    173	/* Set the external interrupt to pointed trigger type */
    174	switch (type)
    175	{
    176		case IRQ_TYPE_NONE:
    177			pr_warn("No edge setting!\n");
    178			break;
    179
    180		case IRQ_TYPE_EDGE_RISING:
    181			newvalue = S3C2410_EXTINT_RISEEDGE;
    182			break;
    183
    184		case IRQ_TYPE_EDGE_FALLING:
    185			newvalue = S3C2410_EXTINT_FALLEDGE;
    186			break;
    187
    188		case IRQ_TYPE_EDGE_BOTH:
    189			newvalue = S3C2410_EXTINT_BOTHEDGE;
    190			break;
    191
    192		case IRQ_TYPE_LEVEL_LOW:
    193			newvalue = S3C2410_EXTINT_LOWLEV;
    194			break;
    195
    196		case IRQ_TYPE_LEVEL_HIGH:
    197			newvalue = S3C2410_EXTINT_HILEV;
    198			break;
    199
    200		default:
    201			pr_err("No such irq type %d\n", type);
    202			return -EINVAL;
    203	}
    204
    205	value = readl_relaxed(extint_reg);
    206	value = (value & ~(7 << extint_offset)) | (newvalue << extint_offset);
    207	writel_relaxed(value, extint_reg);
    208
    209	return 0;
    210}
    211
    212static int s3c_irqext_type(struct irq_data *data, unsigned int type)
    213{
    214	void __iomem *extint_reg;
    215	void __iomem *gpcon_reg;
    216	unsigned long gpcon_offset, extint_offset;
    217
    218	if ((data->hwirq >= 4) && (data->hwirq <= 7)) {
    219		gpcon_reg = S3C2410_GPFCON;
    220		extint_reg = S3C24XX_EXTINT0;
    221		gpcon_offset = (data->hwirq) * 2;
    222		extint_offset = (data->hwirq) * 4;
    223	} else if ((data->hwirq >= 8) && (data->hwirq <= 15)) {
    224		gpcon_reg = S3C2410_GPGCON;
    225		extint_reg = S3C24XX_EXTINT1;
    226		gpcon_offset = (data->hwirq - 8) * 2;
    227		extint_offset = (data->hwirq - 8) * 4;
    228	} else if ((data->hwirq >= 16) && (data->hwirq <= 23)) {
    229		gpcon_reg = S3C2410_GPGCON;
    230		extint_reg = S3C24XX_EXTINT2;
    231		gpcon_offset = (data->hwirq - 8) * 2;
    232		extint_offset = (data->hwirq - 16) * 4;
    233	} else {
    234		return -EINVAL;
    235	}
    236
    237	return s3c_irqext_type_set(gpcon_reg, extint_reg, gpcon_offset,
    238				   extint_offset, type);
    239}
    240
    241static int s3c_irqext0_type(struct irq_data *data, unsigned int type)
    242{
    243	void __iomem *extint_reg;
    244	void __iomem *gpcon_reg;
    245	unsigned long gpcon_offset, extint_offset;
    246
    247	if (data->hwirq <= 3) {
    248		gpcon_reg = S3C2410_GPFCON;
    249		extint_reg = S3C24XX_EXTINT0;
    250		gpcon_offset = (data->hwirq) * 2;
    251		extint_offset = (data->hwirq) * 4;
    252	} else {
    253		return -EINVAL;
    254	}
    255
    256	return s3c_irqext_type_set(gpcon_reg, extint_reg, gpcon_offset,
    257				   extint_offset, type);
    258}
    259
    260static struct irq_chip s3c_irq_chip = {
    261	.name		= "s3c",
    262	.irq_ack	= s3c_irq_ack,
    263	.irq_mask	= s3c_irq_mask,
    264	.irq_unmask	= s3c_irq_unmask,
    265	.irq_set_type	= s3c_irq_type,
    266	.irq_set_wake	= s3c_irq_wake
    267};
    268
    269static struct irq_chip s3c_irq_level_chip = {
    270	.name		= "s3c-level",
    271	.irq_mask	= s3c_irq_mask,
    272	.irq_unmask	= s3c_irq_unmask,
    273	.irq_ack	= s3c_irq_ack,
    274	.irq_set_type	= s3c_irq_type,
    275};
    276
    277static struct irq_chip s3c_irqext_chip = {
    278	.name		= "s3c-ext",
    279	.irq_mask	= s3c_irq_mask,
    280	.irq_unmask	= s3c_irq_unmask,
    281	.irq_ack	= s3c_irq_ack,
    282	.irq_set_type	= s3c_irqext_type,
    283	.irq_set_wake	= s3c_irqext_wake
    284};
    285
    286static struct irq_chip s3c_irq_eint0t4 = {
    287	.name		= "s3c-ext0",
    288	.irq_ack	= s3c_irq_ack,
    289	.irq_mask	= s3c_irq_mask,
    290	.irq_unmask	= s3c_irq_unmask,
    291	.irq_set_wake	= s3c_irq_wake,
    292	.irq_set_type	= s3c_irqext0_type,
    293};
    294
    295static void s3c_irq_demux(struct irq_desc *desc)
    296{
    297	struct irq_chip *chip = irq_desc_get_chip(desc);
    298	struct s3c_irq_data *irq_data = irq_desc_get_chip_data(desc);
    299	struct s3c_irq_intc *intc = irq_data->intc;
    300	struct s3c_irq_intc *sub_intc = irq_data->sub_intc;
    301	unsigned int n, offset;
    302	unsigned long src, msk;
    303
    304	/* we're using individual domains for the non-dt case
    305	 * and one big domain for the dt case where the subintc
    306	 * starts at hwirq number 32.
    307	 */
    308	offset = irq_domain_get_of_node(intc->domain) ? 32 : 0;
    309
    310	chained_irq_enter(chip, desc);
    311
    312	src = readl_relaxed(sub_intc->reg_pending);
    313	msk = readl_relaxed(sub_intc->reg_mask);
    314
    315	src &= ~msk;
    316	src &= irq_data->sub_bits;
    317
    318	while (src) {
    319		n = __ffs(src);
    320		src &= ~(1 << n);
    321		generic_handle_domain_irq(sub_intc->domain, offset + n);
    322	}
    323
    324	chained_irq_exit(chip, desc);
    325}
    326
    327static inline int s3c24xx_handle_intc(struct s3c_irq_intc *intc,
    328				      struct pt_regs *regs, int intc_offset)
    329{
    330	int pnd;
    331	int offset;
    332
    333	pnd = readl_relaxed(intc->reg_intpnd);
    334	if (!pnd)
    335		return false;
    336
    337	/* non-dt machines use individual domains */
    338	if (!irq_domain_get_of_node(intc->domain))
    339		intc_offset = 0;
    340
    341	/* We have a problem that the INTOFFSET register does not always
    342	 * show one interrupt. Occasionally we get two interrupts through
    343	 * the prioritiser, and this causes the INTOFFSET register to show
    344	 * what looks like the logical-or of the two interrupt numbers.
    345	 *
    346	 * Thanks to Klaus, Shannon, et al for helping to debug this problem
    347	 */
    348	offset = readl_relaxed(intc->reg_intpnd + 4);
    349
    350	/* Find the bit manually, when the offset is wrong.
    351	 * The pending register only ever contains the one bit of the next
    352	 * interrupt to handle.
    353	 */
    354	if (!(pnd & (1 << offset)))
    355		offset =  __ffs(pnd);
    356
    357	generic_handle_domain_irq(intc->domain, intc_offset + offset);
    358	return true;
    359}
    360
    361static asmlinkage void __exception_irq_entry s3c24xx_handle_irq(struct pt_regs *regs)
    362{
    363	do {
    364		/*
    365		 * For platform based machines, neither ERR nor NULL can happen here.
    366		 * The s3c24xx_handle_irq() will be set as IRQ handler iff this succeeds:
    367		 *
    368		 *    s3c_intc[0] = s3c24xx_init_intc()
    369		 *
    370		 * If this fails, the next calls to s3c24xx_init_intc() won't be executed.
    371		 *
    372		 * For DT machine, s3c_init_intc_of() could set the IRQ handler without
    373		 * setting s3c_intc[0] only if it was called with num_ctrl=0. There is no
    374		 * such code path, so again the s3c_intc[0] will have a valid pointer if
    375		 * set_handle_irq() is called.
    376		 *
    377		 * Therefore in s3c24xx_handle_irq(), the s3c_intc[0] is always something.
    378		 */
    379		if (s3c24xx_handle_intc(s3c_intc[0], regs, 0))
    380			continue;
    381
    382		if (!IS_ERR_OR_NULL(s3c_intc[2]))
    383			if (s3c24xx_handle_intc(s3c_intc[2], regs, 64))
    384				continue;
    385
    386		break;
    387	} while (1);
    388}
    389
    390#ifdef CONFIG_FIQ
    391/**
    392 * s3c24xx_set_fiq - set the FIQ routing
    393 * @irq: IRQ number to route to FIQ on processor.
    394 * @ack_ptr: pointer to a location for storing the bit mask
    395 * @on: Whether to route @irq to the FIQ, or to remove the FIQ routing.
    396 *
    397 * Change the state of the IRQ to FIQ routing depending on @irq and @on. If
    398 * @on is true, the @irq is checked to see if it can be routed and the
    399 * interrupt controller updated to route the IRQ. If @on is false, the FIQ
    400 * routing is cleared, regardless of which @irq is specified.
    401 *
    402 * returns the mask value for the register.
    403 */
    404int s3c24xx_set_fiq(unsigned int irq, u32 *ack_ptr, bool on)
    405{
    406	u32 intmod;
    407	unsigned offs;
    408
    409	if (on) {
    410		offs = irq - FIQ_START;
    411		if (offs > 31)
    412			return 0;
    413
    414		intmod = 1 << offs;
    415	} else {
    416		intmod = 0;
    417	}
    418
    419	if (ack_ptr)
    420		*ack_ptr = intmod;
    421	writel_relaxed(intmod, S3C2410_INTMOD);
    422
    423	return intmod;
    424}
    425
    426EXPORT_SYMBOL_GPL(s3c24xx_set_fiq);
    427#endif
    428
    429static int s3c24xx_irq_map(struct irq_domain *h, unsigned int virq,
    430							irq_hw_number_t hw)
    431{
    432	struct s3c_irq_intc *intc = h->host_data;
    433	struct s3c_irq_data *irq_data = &intc->irqs[hw];
    434	struct s3c_irq_intc *parent_intc;
    435	struct s3c_irq_data *parent_irq_data;
    436	unsigned int irqno;
    437
    438	/* attach controller pointer to irq_data */
    439	irq_data->intc = intc;
    440	irq_data->offset = hw;
    441
    442	parent_intc = intc->parent;
    443
    444	/* set handler and flags */
    445	switch (irq_data->type) {
    446	case S3C_IRQTYPE_NONE:
    447		return 0;
    448	case S3C_IRQTYPE_EINT:
    449		/* On the S3C2412, the EINT0to3 have a parent irq
    450		 * but need the s3c_irq_eint0t4 chip
    451		 */
    452		if (parent_intc && (!soc_is_s3c2412() || hw >= 4))
    453			irq_set_chip_and_handler(virq, &s3c_irqext_chip,
    454						 handle_edge_irq);
    455		else
    456			irq_set_chip_and_handler(virq, &s3c_irq_eint0t4,
    457						 handle_edge_irq);
    458		break;
    459	case S3C_IRQTYPE_EDGE:
    460		if (parent_intc || intc->reg_pending == S3C2416_SRCPND2)
    461			irq_set_chip_and_handler(virq, &s3c_irq_level_chip,
    462						 handle_edge_irq);
    463		else
    464			irq_set_chip_and_handler(virq, &s3c_irq_chip,
    465						 handle_edge_irq);
    466		break;
    467	case S3C_IRQTYPE_LEVEL:
    468		if (parent_intc)
    469			irq_set_chip_and_handler(virq, &s3c_irq_level_chip,
    470						 handle_level_irq);
    471		else
    472			irq_set_chip_and_handler(virq, &s3c_irq_chip,
    473						 handle_level_irq);
    474		break;
    475	default:
    476		pr_err("irq-s3c24xx: unsupported irqtype %d\n", irq_data->type);
    477		return -EINVAL;
    478	}
    479
    480	irq_set_chip_data(virq, irq_data);
    481
    482	if (parent_intc && irq_data->type != S3C_IRQTYPE_NONE) {
    483		if (irq_data->parent_irq > 31) {
    484			pr_err("irq-s3c24xx: parent irq %lu is out of range\n",
    485			       irq_data->parent_irq);
    486			return -EINVAL;
    487		}
    488
    489		parent_irq_data = &parent_intc->irqs[irq_data->parent_irq];
    490		parent_irq_data->sub_intc = intc;
    491		parent_irq_data->sub_bits |= (1UL << hw);
    492
    493		/* attach the demuxer to the parent irq */
    494		irqno = irq_find_mapping(parent_intc->domain,
    495					 irq_data->parent_irq);
    496		if (!irqno) {
    497			pr_err("irq-s3c24xx: could not find mapping for parent irq %lu\n",
    498			       irq_data->parent_irq);
    499			return -EINVAL;
    500		}
    501		irq_set_chained_handler(irqno, s3c_irq_demux);
    502	}
    503
    504	return 0;
    505}
    506
    507static const struct irq_domain_ops s3c24xx_irq_ops = {
    508	.map = s3c24xx_irq_map,
    509	.xlate = irq_domain_xlate_twocell,
    510};
    511
    512static void s3c24xx_clear_intc(struct s3c_irq_intc *intc)
    513{
    514	void __iomem *reg_source;
    515	unsigned long pend;
    516	unsigned long last;
    517	int i;
    518
    519	/* if intpnd is set, read the next pending irq from there */
    520	reg_source = intc->reg_intpnd ? intc->reg_intpnd : intc->reg_pending;
    521
    522	last = 0;
    523	for (i = 0; i < 4; i++) {
    524		pend = readl_relaxed(reg_source);
    525
    526		if (pend == 0 || pend == last)
    527			break;
    528
    529		writel_relaxed(pend, intc->reg_pending);
    530		if (intc->reg_intpnd)
    531			writel_relaxed(pend, intc->reg_intpnd);
    532
    533		pr_info("irq: clearing pending status %08x\n", (int)pend);
    534		last = pend;
    535	}
    536}
    537
    538static struct s3c_irq_intc * __init s3c24xx_init_intc(struct device_node *np,
    539				       struct s3c_irq_data *irq_data,
    540				       struct s3c_irq_intc *parent,
    541				       unsigned long address)
    542{
    543	struct s3c_irq_intc *intc;
    544	void __iomem *base = (void *)0xf6000000; /* static mapping */
    545	int irq_num;
    546	int irq_start;
    547	int ret;
    548
    549	intc = kzalloc(sizeof(struct s3c_irq_intc), GFP_KERNEL);
    550	if (!intc)
    551		return ERR_PTR(-ENOMEM);
    552
    553	intc->irqs = irq_data;
    554
    555	if (parent)
    556		intc->parent = parent;
    557
    558	/* select the correct data for the controller.
    559	 * Need to hard code the irq num start and offset
    560	 * to preserve the static mapping for now
    561	 */
    562	switch (address) {
    563	case 0x4a000000:
    564		pr_debug("irq: found main intc\n");
    565		intc->reg_pending = base;
    566		intc->reg_mask = base + 0x08;
    567		intc->reg_intpnd = base + 0x10;
    568		irq_num = 32;
    569		irq_start = S3C2410_IRQ(0);
    570		break;
    571	case 0x4a000018:
    572		pr_debug("irq: found subintc\n");
    573		intc->reg_pending = base + 0x18;
    574		intc->reg_mask = base + 0x1c;
    575		irq_num = 29;
    576		irq_start = S3C2410_IRQSUB(0);
    577		break;
    578	case 0x4a000040:
    579		pr_debug("irq: found intc2\n");
    580		intc->reg_pending = base + 0x40;
    581		intc->reg_mask = base + 0x48;
    582		intc->reg_intpnd = base + 0x50;
    583		irq_num = 8;
    584		irq_start = S3C2416_IRQ(0);
    585		break;
    586	case 0x560000a4:
    587		pr_debug("irq: found eintc\n");
    588		base = (void *)0xfd000000;
    589
    590		intc->reg_mask = base + 0xa4;
    591		intc->reg_pending = base + 0xa8;
    592		irq_num = 24;
    593		irq_start = S3C2410_IRQ(32);
    594		break;
    595	default:
    596		pr_err("irq: unsupported controller address\n");
    597		ret = -EINVAL;
    598		goto err;
    599	}
    600
    601	/* now that all the data is complete, init the irq-domain */
    602	s3c24xx_clear_intc(intc);
    603	intc->domain = irq_domain_add_legacy(np, irq_num, irq_start,
    604					     0, &s3c24xx_irq_ops,
    605					     intc);
    606	if (!intc->domain) {
    607		pr_err("irq: could not create irq-domain\n");
    608		ret = -EINVAL;
    609		goto err;
    610	}
    611
    612	set_handle_irq(s3c24xx_handle_irq);
    613
    614	return intc;
    615
    616err:
    617	kfree(intc);
    618	return ERR_PTR(ret);
    619}
    620
    621static struct s3c_irq_data __maybe_unused init_eint[32] = {
    622	{ .type = S3C_IRQTYPE_NONE, }, /* reserved */
    623	{ .type = S3C_IRQTYPE_NONE, }, /* reserved */
    624	{ .type = S3C_IRQTYPE_NONE, }, /* reserved */
    625	{ .type = S3C_IRQTYPE_NONE, }, /* reserved */
    626	{ .type = S3C_IRQTYPE_EINT, .parent_irq = 4 }, /* EINT4 */
    627	{ .type = S3C_IRQTYPE_EINT, .parent_irq = 4 }, /* EINT5 */
    628	{ .type = S3C_IRQTYPE_EINT, .parent_irq = 4 }, /* EINT6 */
    629	{ .type = S3C_IRQTYPE_EINT, .parent_irq = 4 }, /* EINT7 */
    630	{ .type = S3C_IRQTYPE_EINT, .parent_irq = 5 }, /* EINT8 */
    631	{ .type = S3C_IRQTYPE_EINT, .parent_irq = 5 }, /* EINT9 */
    632	{ .type = S3C_IRQTYPE_EINT, .parent_irq = 5 }, /* EINT10 */
    633	{ .type = S3C_IRQTYPE_EINT, .parent_irq = 5 }, /* EINT11 */
    634	{ .type = S3C_IRQTYPE_EINT, .parent_irq = 5 }, /* EINT12 */
    635	{ .type = S3C_IRQTYPE_EINT, .parent_irq = 5 }, /* EINT13 */
    636	{ .type = S3C_IRQTYPE_EINT, .parent_irq = 5 }, /* EINT14 */
    637	{ .type = S3C_IRQTYPE_EINT, .parent_irq = 5 }, /* EINT15 */
    638	{ .type = S3C_IRQTYPE_EINT, .parent_irq = 5 }, /* EINT16 */
    639	{ .type = S3C_IRQTYPE_EINT, .parent_irq = 5 }, /* EINT17 */
    640	{ .type = S3C_IRQTYPE_EINT, .parent_irq = 5 }, /* EINT18 */
    641	{ .type = S3C_IRQTYPE_EINT, .parent_irq = 5 }, /* EINT19 */
    642	{ .type = S3C_IRQTYPE_EINT, .parent_irq = 5 }, /* EINT20 */
    643	{ .type = S3C_IRQTYPE_EINT, .parent_irq = 5 }, /* EINT21 */
    644	{ .type = S3C_IRQTYPE_EINT, .parent_irq = 5 }, /* EINT22 */
    645	{ .type = S3C_IRQTYPE_EINT, .parent_irq = 5 }, /* EINT23 */
    646};
    647
    648#ifdef CONFIG_CPU_S3C2410
    649static struct s3c_irq_data init_s3c2410base[32] = {
    650	{ .type = S3C_IRQTYPE_EINT, }, /* EINT0 */
    651	{ .type = S3C_IRQTYPE_EINT, }, /* EINT1 */
    652	{ .type = S3C_IRQTYPE_EINT, }, /* EINT2 */
    653	{ .type = S3C_IRQTYPE_EINT, }, /* EINT3 */
    654	{ .type = S3C_IRQTYPE_LEVEL, }, /* EINT4to7 */
    655	{ .type = S3C_IRQTYPE_LEVEL, }, /* EINT8to23 */
    656	{ .type = S3C_IRQTYPE_NONE, }, /* reserved */
    657	{ .type = S3C_IRQTYPE_EDGE, }, /* nBATT_FLT */
    658	{ .type = S3C_IRQTYPE_EDGE, }, /* TICK */
    659	{ .type = S3C_IRQTYPE_EDGE, }, /* WDT */
    660	{ .type = S3C_IRQTYPE_EDGE, }, /* TIMER0 */
    661	{ .type = S3C_IRQTYPE_EDGE, }, /* TIMER1 */
    662	{ .type = S3C_IRQTYPE_EDGE, }, /* TIMER2 */
    663	{ .type = S3C_IRQTYPE_EDGE, }, /* TIMER3 */
    664	{ .type = S3C_IRQTYPE_EDGE, }, /* TIMER4 */
    665	{ .type = S3C_IRQTYPE_LEVEL, }, /* UART2 */
    666	{ .type = S3C_IRQTYPE_EDGE, }, /* LCD */
    667	{ .type = S3C_IRQTYPE_EDGE, }, /* DMA0 */
    668	{ .type = S3C_IRQTYPE_EDGE, }, /* DMA1 */
    669	{ .type = S3C_IRQTYPE_EDGE, }, /* DMA2 */
    670	{ .type = S3C_IRQTYPE_EDGE, }, /* DMA3 */
    671	{ .type = S3C_IRQTYPE_EDGE, }, /* SDI */
    672	{ .type = S3C_IRQTYPE_EDGE, }, /* SPI0 */
    673	{ .type = S3C_IRQTYPE_LEVEL, }, /* UART1 */
    674	{ .type = S3C_IRQTYPE_NONE, }, /* reserved */
    675	{ .type = S3C_IRQTYPE_EDGE, }, /* USBD */
    676	{ .type = S3C_IRQTYPE_EDGE, }, /* USBH */
    677	{ .type = S3C_IRQTYPE_EDGE, }, /* IIC */
    678	{ .type = S3C_IRQTYPE_LEVEL, }, /* UART0 */
    679	{ .type = S3C_IRQTYPE_EDGE, }, /* SPI1 */
    680	{ .type = S3C_IRQTYPE_EDGE, }, /* RTC */
    681	{ .type = S3C_IRQTYPE_LEVEL, }, /* ADCPARENT */
    682};
    683
    684static struct s3c_irq_data init_s3c2410subint[32] = {
    685	{ .type = S3C_IRQTYPE_LEVEL, .parent_irq = 28 }, /* UART0-RX */
    686	{ .type = S3C_IRQTYPE_LEVEL, .parent_irq = 28 }, /* UART0-TX */
    687	{ .type = S3C_IRQTYPE_LEVEL, .parent_irq = 28 }, /* UART0-ERR */
    688	{ .type = S3C_IRQTYPE_LEVEL, .parent_irq = 23 }, /* UART1-RX */
    689	{ .type = S3C_IRQTYPE_LEVEL, .parent_irq = 23 }, /* UART1-TX */
    690	{ .type = S3C_IRQTYPE_LEVEL, .parent_irq = 23 }, /* UART1-ERR */
    691	{ .type = S3C_IRQTYPE_LEVEL, .parent_irq = 15 }, /* UART2-RX */
    692	{ .type = S3C_IRQTYPE_LEVEL, .parent_irq = 15 }, /* UART2-TX */
    693	{ .type = S3C_IRQTYPE_LEVEL, .parent_irq = 15 }, /* UART2-ERR */
    694	{ .type = S3C_IRQTYPE_EDGE, .parent_irq = 31 }, /* TC */
    695	{ .type = S3C_IRQTYPE_EDGE, .parent_irq = 31 }, /* ADC */
    696};
    697
    698void __init s3c2410_init_irq(void)
    699{
    700#ifdef CONFIG_FIQ
    701	init_FIQ(FIQ_START);
    702#endif
    703
    704	s3c_intc[0] = s3c24xx_init_intc(NULL, &init_s3c2410base[0], NULL,
    705					0x4a000000);
    706	if (IS_ERR(s3c_intc[0])) {
    707		pr_err("irq: could not create main interrupt controller\n");
    708		return;
    709	}
    710
    711	s3c_intc[1] = s3c24xx_init_intc(NULL, &init_s3c2410subint[0],
    712					s3c_intc[0], 0x4a000018);
    713	s3c24xx_init_intc(NULL, &init_eint[0], s3c_intc[0], 0x560000a4);
    714}
    715#endif
    716
    717#ifdef CONFIG_CPU_S3C2412
    718static struct s3c_irq_data init_s3c2412base[32] = {
    719	{ .type = S3C_IRQTYPE_LEVEL, }, /* EINT0 */
    720	{ .type = S3C_IRQTYPE_LEVEL, }, /* EINT1 */
    721	{ .type = S3C_IRQTYPE_LEVEL, }, /* EINT2 */
    722	{ .type = S3C_IRQTYPE_LEVEL, }, /* EINT3 */
    723	{ .type = S3C_IRQTYPE_LEVEL, }, /* EINT4to7 */
    724	{ .type = S3C_IRQTYPE_LEVEL, }, /* EINT8to23 */
    725	{ .type = S3C_IRQTYPE_NONE, }, /* reserved */
    726	{ .type = S3C_IRQTYPE_EDGE, }, /* nBATT_FLT */
    727	{ .type = S3C_IRQTYPE_EDGE, }, /* TICK */
    728	{ .type = S3C_IRQTYPE_EDGE, }, /* WDT */
    729	{ .type = S3C_IRQTYPE_EDGE, }, /* TIMER0 */
    730	{ .type = S3C_IRQTYPE_EDGE, }, /* TIMER1 */
    731	{ .type = S3C_IRQTYPE_EDGE, }, /* TIMER2 */
    732	{ .type = S3C_IRQTYPE_EDGE, }, /* TIMER3 */
    733	{ .type = S3C_IRQTYPE_EDGE, }, /* TIMER4 */
    734	{ .type = S3C_IRQTYPE_LEVEL, }, /* UART2 */
    735	{ .type = S3C_IRQTYPE_EDGE, }, /* LCD */
    736	{ .type = S3C_IRQTYPE_EDGE, }, /* DMA0 */
    737	{ .type = S3C_IRQTYPE_EDGE, }, /* DMA1 */
    738	{ .type = S3C_IRQTYPE_EDGE, }, /* DMA2 */
    739	{ .type = S3C_IRQTYPE_EDGE, }, /* DMA3 */
    740	{ .type = S3C_IRQTYPE_LEVEL, }, /* SDI/CF */
    741	{ .type = S3C_IRQTYPE_EDGE, }, /* SPI0 */
    742	{ .type = S3C_IRQTYPE_LEVEL, }, /* UART1 */
    743	{ .type = S3C_IRQTYPE_NONE, }, /* reserved */
    744	{ .type = S3C_IRQTYPE_EDGE, }, /* USBD */
    745	{ .type = S3C_IRQTYPE_EDGE, }, /* USBH */
    746	{ .type = S3C_IRQTYPE_EDGE, }, /* IIC */
    747	{ .type = S3C_IRQTYPE_LEVEL, }, /* UART0 */
    748	{ .type = S3C_IRQTYPE_EDGE, }, /* SPI1 */
    749	{ .type = S3C_IRQTYPE_EDGE, }, /* RTC */
    750	{ .type = S3C_IRQTYPE_LEVEL, }, /* ADCPARENT */
    751};
    752
    753static struct s3c_irq_data init_s3c2412eint[32] = {
    754	{ .type = S3C_IRQTYPE_EINT, .parent_irq = 0 }, /* EINT0 */
    755	{ .type = S3C_IRQTYPE_EINT, .parent_irq = 1 }, /* EINT1 */
    756	{ .type = S3C_IRQTYPE_EINT, .parent_irq = 2 }, /* EINT2 */
    757	{ .type = S3C_IRQTYPE_EINT, .parent_irq = 3 }, /* EINT3 */
    758	{ .type = S3C_IRQTYPE_EINT, .parent_irq = 4 }, /* EINT4 */
    759	{ .type = S3C_IRQTYPE_EINT, .parent_irq = 4 }, /* EINT5 */
    760	{ .type = S3C_IRQTYPE_EINT, .parent_irq = 4 }, /* EINT6 */
    761	{ .type = S3C_IRQTYPE_EINT, .parent_irq = 4 }, /* EINT7 */
    762	{ .type = S3C_IRQTYPE_EINT, .parent_irq = 5 }, /* EINT8 */
    763	{ .type = S3C_IRQTYPE_EINT, .parent_irq = 5 }, /* EINT9 */
    764	{ .type = S3C_IRQTYPE_EINT, .parent_irq = 5 }, /* EINT10 */
    765	{ .type = S3C_IRQTYPE_EINT, .parent_irq = 5 }, /* EINT11 */
    766	{ .type = S3C_IRQTYPE_EINT, .parent_irq = 5 }, /* EINT12 */
    767	{ .type = S3C_IRQTYPE_EINT, .parent_irq = 5 }, /* EINT13 */
    768	{ .type = S3C_IRQTYPE_EINT, .parent_irq = 5 }, /* EINT14 */
    769	{ .type = S3C_IRQTYPE_EINT, .parent_irq = 5 }, /* EINT15 */
    770	{ .type = S3C_IRQTYPE_EINT, .parent_irq = 5 }, /* EINT16 */
    771	{ .type = S3C_IRQTYPE_EINT, .parent_irq = 5 }, /* EINT17 */
    772	{ .type = S3C_IRQTYPE_EINT, .parent_irq = 5 }, /* EINT18 */
    773	{ .type = S3C_IRQTYPE_EINT, .parent_irq = 5 }, /* EINT19 */
    774	{ .type = S3C_IRQTYPE_EINT, .parent_irq = 5 }, /* EINT20 */
    775	{ .type = S3C_IRQTYPE_EINT, .parent_irq = 5 }, /* EINT21 */
    776	{ .type = S3C_IRQTYPE_EINT, .parent_irq = 5 }, /* EINT22 */
    777	{ .type = S3C_IRQTYPE_EINT, .parent_irq = 5 }, /* EINT23 */
    778};
    779
    780static struct s3c_irq_data init_s3c2412subint[32] = {
    781	{ .type = S3C_IRQTYPE_LEVEL, .parent_irq = 28 }, /* UART0-RX */
    782	{ .type = S3C_IRQTYPE_LEVEL, .parent_irq = 28 }, /* UART0-TX */
    783	{ .type = S3C_IRQTYPE_LEVEL, .parent_irq = 28 }, /* UART0-ERR */
    784	{ .type = S3C_IRQTYPE_LEVEL, .parent_irq = 23 }, /* UART1-RX */
    785	{ .type = S3C_IRQTYPE_LEVEL, .parent_irq = 23 }, /* UART1-TX */
    786	{ .type = S3C_IRQTYPE_LEVEL, .parent_irq = 23 }, /* UART1-ERR */
    787	{ .type = S3C_IRQTYPE_LEVEL, .parent_irq = 15 }, /* UART2-RX */
    788	{ .type = S3C_IRQTYPE_LEVEL, .parent_irq = 15 }, /* UART2-TX */
    789	{ .type = S3C_IRQTYPE_LEVEL, .parent_irq = 15 }, /* UART2-ERR */
    790	{ .type = S3C_IRQTYPE_EDGE, .parent_irq = 31 }, /* TC */
    791	{ .type = S3C_IRQTYPE_EDGE, .parent_irq = 31 }, /* ADC */
    792	{ .type = S3C_IRQTYPE_NONE, },
    793	{ .type = S3C_IRQTYPE_NONE, },
    794	{ .type = S3C_IRQTYPE_LEVEL, .parent_irq = 21 }, /* SDI */
    795	{ .type = S3C_IRQTYPE_LEVEL, .parent_irq = 21 }, /* CF */
    796};
    797
    798void __init s3c2412_init_irq(void)
    799{
    800	pr_info("S3C2412: IRQ Support\n");
    801
    802#ifdef CONFIG_FIQ
    803	init_FIQ(FIQ_START);
    804#endif
    805
    806	s3c_intc[0] = s3c24xx_init_intc(NULL, &init_s3c2412base[0], NULL,
    807					0x4a000000);
    808	if (IS_ERR(s3c_intc[0])) {
    809		pr_err("irq: could not create main interrupt controller\n");
    810		return;
    811	}
    812
    813	s3c24xx_init_intc(NULL, &init_s3c2412eint[0], s3c_intc[0], 0x560000a4);
    814	s3c_intc[1] = s3c24xx_init_intc(NULL, &init_s3c2412subint[0],
    815					s3c_intc[0], 0x4a000018);
    816}
    817#endif
    818
    819#ifdef CONFIG_CPU_S3C2416
    820static struct s3c_irq_data init_s3c2416base[32] = {
    821	{ .type = S3C_IRQTYPE_EINT, }, /* EINT0 */
    822	{ .type = S3C_IRQTYPE_EINT, }, /* EINT1 */
    823	{ .type = S3C_IRQTYPE_EINT, }, /* EINT2 */
    824	{ .type = S3C_IRQTYPE_EINT, }, /* EINT3 */
    825	{ .type = S3C_IRQTYPE_LEVEL, }, /* EINT4to7 */
    826	{ .type = S3C_IRQTYPE_LEVEL, }, /* EINT8to23 */
    827	{ .type = S3C_IRQTYPE_NONE, }, /* reserved */
    828	{ .type = S3C_IRQTYPE_EDGE, }, /* nBATT_FLT */
    829	{ .type = S3C_IRQTYPE_EDGE, }, /* TICK */
    830	{ .type = S3C_IRQTYPE_LEVEL, }, /* WDT/AC97 */
    831	{ .type = S3C_IRQTYPE_EDGE, }, /* TIMER0 */
    832	{ .type = S3C_IRQTYPE_EDGE, }, /* TIMER1 */
    833	{ .type = S3C_IRQTYPE_EDGE, }, /* TIMER2 */
    834	{ .type = S3C_IRQTYPE_EDGE, }, /* TIMER3 */
    835	{ .type = S3C_IRQTYPE_EDGE, }, /* TIMER4 */
    836	{ .type = S3C_IRQTYPE_LEVEL, }, /* UART2 */
    837	{ .type = S3C_IRQTYPE_LEVEL, }, /* LCD */
    838	{ .type = S3C_IRQTYPE_LEVEL, }, /* DMA */
    839	{ .type = S3C_IRQTYPE_LEVEL, }, /* UART3 */
    840	{ .type = S3C_IRQTYPE_NONE, }, /* reserved */
    841	{ .type = S3C_IRQTYPE_EDGE, }, /* SDI1 */
    842	{ .type = S3C_IRQTYPE_EDGE, }, /* SDI0 */
    843	{ .type = S3C_IRQTYPE_EDGE, }, /* SPI0 */
    844	{ .type = S3C_IRQTYPE_LEVEL, }, /* UART1 */
    845	{ .type = S3C_IRQTYPE_EDGE, }, /* NAND */
    846	{ .type = S3C_IRQTYPE_EDGE, }, /* USBD */
    847	{ .type = S3C_IRQTYPE_EDGE, }, /* USBH */
    848	{ .type = S3C_IRQTYPE_EDGE, }, /* IIC */
    849	{ .type = S3C_IRQTYPE_LEVEL, }, /* UART0 */
    850	{ .type = S3C_IRQTYPE_NONE, },
    851	{ .type = S3C_IRQTYPE_EDGE, }, /* RTC */
    852	{ .type = S3C_IRQTYPE_LEVEL, }, /* ADCPARENT */
    853};
    854
    855static struct s3c_irq_data init_s3c2416subint[32] = {
    856	{ .type = S3C_IRQTYPE_LEVEL, .parent_irq = 28 }, /* UART0-RX */
    857	{ .type = S3C_IRQTYPE_LEVEL, .parent_irq = 28 }, /* UART0-TX */
    858	{ .type = S3C_IRQTYPE_LEVEL, .parent_irq = 28 }, /* UART0-ERR */
    859	{ .type = S3C_IRQTYPE_LEVEL, .parent_irq = 23 }, /* UART1-RX */
    860	{ .type = S3C_IRQTYPE_LEVEL, .parent_irq = 23 }, /* UART1-TX */
    861	{ .type = S3C_IRQTYPE_LEVEL, .parent_irq = 23 }, /* UART1-ERR */
    862	{ .type = S3C_IRQTYPE_LEVEL, .parent_irq = 15 }, /* UART2-RX */
    863	{ .type = S3C_IRQTYPE_LEVEL, .parent_irq = 15 }, /* UART2-TX */
    864	{ .type = S3C_IRQTYPE_LEVEL, .parent_irq = 15 }, /* UART2-ERR */
    865	{ .type = S3C_IRQTYPE_EDGE, .parent_irq = 31 }, /* TC */
    866	{ .type = S3C_IRQTYPE_EDGE, .parent_irq = 31 }, /* ADC */
    867	{ .type = S3C_IRQTYPE_NONE }, /* reserved */
    868	{ .type = S3C_IRQTYPE_NONE }, /* reserved */
    869	{ .type = S3C_IRQTYPE_NONE }, /* reserved */
    870	{ .type = S3C_IRQTYPE_NONE }, /* reserved */
    871	{ .type = S3C_IRQTYPE_LEVEL, .parent_irq = 16 }, /* LCD2 */
    872	{ .type = S3C_IRQTYPE_LEVEL, .parent_irq = 16 }, /* LCD3 */
    873	{ .type = S3C_IRQTYPE_LEVEL, .parent_irq = 16 }, /* LCD4 */
    874	{ .type = S3C_IRQTYPE_LEVEL, .parent_irq = 17 }, /* DMA0 */
    875	{ .type = S3C_IRQTYPE_LEVEL, .parent_irq = 17 }, /* DMA1 */
    876	{ .type = S3C_IRQTYPE_LEVEL, .parent_irq = 17 }, /* DMA2 */
    877	{ .type = S3C_IRQTYPE_LEVEL, .parent_irq = 17 }, /* DMA3 */
    878	{ .type = S3C_IRQTYPE_LEVEL, .parent_irq = 17 }, /* DMA4 */
    879	{ .type = S3C_IRQTYPE_LEVEL, .parent_irq = 17 }, /* DMA5 */
    880	{ .type = S3C_IRQTYPE_LEVEL, .parent_irq = 18 }, /* UART3-RX */
    881	{ .type = S3C_IRQTYPE_LEVEL, .parent_irq = 18 }, /* UART3-TX */
    882	{ .type = S3C_IRQTYPE_LEVEL, .parent_irq = 18 }, /* UART3-ERR */
    883	{ .type = S3C_IRQTYPE_LEVEL, .parent_irq = 9 }, /* WDT */
    884	{ .type = S3C_IRQTYPE_LEVEL, .parent_irq = 9 }, /* AC97 */
    885};
    886
    887static struct s3c_irq_data init_s3c2416_second[32] = {
    888	{ .type = S3C_IRQTYPE_EDGE }, /* 2D */
    889	{ .type = S3C_IRQTYPE_NONE }, /* reserved */
    890	{ .type = S3C_IRQTYPE_NONE }, /* reserved */
    891	{ .type = S3C_IRQTYPE_NONE }, /* reserved */
    892	{ .type = S3C_IRQTYPE_EDGE }, /* PCM0 */
    893	{ .type = S3C_IRQTYPE_NONE }, /* reserved */
    894	{ .type = S3C_IRQTYPE_EDGE }, /* I2S0 */
    895};
    896
    897void __init s3c2416_init_irq(void)
    898{
    899	pr_info("S3C2416: IRQ Support\n");
    900
    901#ifdef CONFIG_FIQ
    902	init_FIQ(FIQ_START);
    903#endif
    904
    905	s3c_intc[0] = s3c24xx_init_intc(NULL, &init_s3c2416base[0], NULL,
    906					0x4a000000);
    907	if (IS_ERR(s3c_intc[0])) {
    908		pr_err("irq: could not create main interrupt controller\n");
    909		return;
    910	}
    911
    912	s3c24xx_init_intc(NULL, &init_eint[0], s3c_intc[0], 0x560000a4);
    913	s3c_intc[1] = s3c24xx_init_intc(NULL, &init_s3c2416subint[0],
    914					s3c_intc[0], 0x4a000018);
    915
    916	s3c_intc[2] = s3c24xx_init_intc(NULL, &init_s3c2416_second[0],
    917					NULL, 0x4a000040);
    918}
    919
    920#endif
    921
    922#ifdef CONFIG_CPU_S3C2440
    923static struct s3c_irq_data init_s3c2440base[32] = {
    924	{ .type = S3C_IRQTYPE_EINT, }, /* EINT0 */
    925	{ .type = S3C_IRQTYPE_EINT, }, /* EINT1 */
    926	{ .type = S3C_IRQTYPE_EINT, }, /* EINT2 */
    927	{ .type = S3C_IRQTYPE_EINT, }, /* EINT3 */
    928	{ .type = S3C_IRQTYPE_LEVEL, }, /* EINT4to7 */
    929	{ .type = S3C_IRQTYPE_LEVEL, }, /* EINT8to23 */
    930	{ .type = S3C_IRQTYPE_LEVEL, }, /* CAM */
    931	{ .type = S3C_IRQTYPE_EDGE, }, /* nBATT_FLT */
    932	{ .type = S3C_IRQTYPE_EDGE, }, /* TICK */
    933	{ .type = S3C_IRQTYPE_LEVEL, }, /* WDT/AC97 */
    934	{ .type = S3C_IRQTYPE_EDGE, }, /* TIMER0 */
    935	{ .type = S3C_IRQTYPE_EDGE, }, /* TIMER1 */
    936	{ .type = S3C_IRQTYPE_EDGE, }, /* TIMER2 */
    937	{ .type = S3C_IRQTYPE_EDGE, }, /* TIMER3 */
    938	{ .type = S3C_IRQTYPE_EDGE, }, /* TIMER4 */
    939	{ .type = S3C_IRQTYPE_LEVEL, }, /* UART2 */
    940	{ .type = S3C_IRQTYPE_EDGE, }, /* LCD */
    941	{ .type = S3C_IRQTYPE_EDGE, }, /* DMA0 */
    942	{ .type = S3C_IRQTYPE_EDGE, }, /* DMA1 */
    943	{ .type = S3C_IRQTYPE_EDGE, }, /* DMA2 */
    944	{ .type = S3C_IRQTYPE_EDGE, }, /* DMA3 */
    945	{ .type = S3C_IRQTYPE_EDGE, }, /* SDI */
    946	{ .type = S3C_IRQTYPE_EDGE, }, /* SPI0 */
    947	{ .type = S3C_IRQTYPE_LEVEL, }, /* UART1 */
    948	{ .type = S3C_IRQTYPE_LEVEL, }, /* NFCON */
    949	{ .type = S3C_IRQTYPE_EDGE, }, /* USBD */
    950	{ .type = S3C_IRQTYPE_EDGE, }, /* USBH */
    951	{ .type = S3C_IRQTYPE_EDGE, }, /* IIC */
    952	{ .type = S3C_IRQTYPE_LEVEL, }, /* UART0 */
    953	{ .type = S3C_IRQTYPE_EDGE, }, /* SPI1 */
    954	{ .type = S3C_IRQTYPE_EDGE, }, /* RTC */
    955	{ .type = S3C_IRQTYPE_LEVEL, }, /* ADCPARENT */
    956};
    957
    958static struct s3c_irq_data init_s3c2440subint[32] = {
    959	{ .type = S3C_IRQTYPE_LEVEL, .parent_irq = 28 }, /* UART0-RX */
    960	{ .type = S3C_IRQTYPE_LEVEL, .parent_irq = 28 }, /* UART0-TX */
    961	{ .type = S3C_IRQTYPE_LEVEL, .parent_irq = 28 }, /* UART0-ERR */
    962	{ .type = S3C_IRQTYPE_LEVEL, .parent_irq = 23 }, /* UART1-RX */
    963	{ .type = S3C_IRQTYPE_LEVEL, .parent_irq = 23 }, /* UART1-TX */
    964	{ .type = S3C_IRQTYPE_LEVEL, .parent_irq = 23 }, /* UART1-ERR */
    965	{ .type = S3C_IRQTYPE_LEVEL, .parent_irq = 15 }, /* UART2-RX */
    966	{ .type = S3C_IRQTYPE_LEVEL, .parent_irq = 15 }, /* UART2-TX */
    967	{ .type = S3C_IRQTYPE_LEVEL, .parent_irq = 15 }, /* UART2-ERR */
    968	{ .type = S3C_IRQTYPE_EDGE, .parent_irq = 31 }, /* TC */
    969	{ .type = S3C_IRQTYPE_EDGE, .parent_irq = 31 }, /* ADC */
    970	{ .type = S3C_IRQTYPE_LEVEL, .parent_irq = 6 }, /* CAM_C */
    971	{ .type = S3C_IRQTYPE_LEVEL, .parent_irq = 6 }, /* CAM_P */
    972	{ .type = S3C_IRQTYPE_LEVEL, .parent_irq = 9 }, /* WDT */
    973	{ .type = S3C_IRQTYPE_LEVEL, .parent_irq = 9 }, /* AC97 */
    974};
    975
    976void __init s3c2440_init_irq(void)
    977{
    978	pr_info("S3C2440: IRQ Support\n");
    979
    980#ifdef CONFIG_FIQ
    981	init_FIQ(FIQ_START);
    982#endif
    983
    984	s3c_intc[0] = s3c24xx_init_intc(NULL, &init_s3c2440base[0], NULL,
    985					0x4a000000);
    986	if (IS_ERR(s3c_intc[0])) {
    987		pr_err("irq: could not create main interrupt controller\n");
    988		return;
    989	}
    990
    991	s3c24xx_init_intc(NULL, &init_eint[0], s3c_intc[0], 0x560000a4);
    992	s3c_intc[1] = s3c24xx_init_intc(NULL, &init_s3c2440subint[0],
    993					s3c_intc[0], 0x4a000018);
    994}
    995#endif
    996
    997#ifdef CONFIG_CPU_S3C2442
    998static struct s3c_irq_data init_s3c2442base[32] = {
    999	{ .type = S3C_IRQTYPE_EINT, }, /* EINT0 */
   1000	{ .type = S3C_IRQTYPE_EINT, }, /* EINT1 */
   1001	{ .type = S3C_IRQTYPE_EINT, }, /* EINT2 */
   1002	{ .type = S3C_IRQTYPE_EINT, }, /* EINT3 */
   1003	{ .type = S3C_IRQTYPE_LEVEL, }, /* EINT4to7 */
   1004	{ .type = S3C_IRQTYPE_LEVEL, }, /* EINT8to23 */
   1005	{ .type = S3C_IRQTYPE_LEVEL, }, /* CAM */
   1006	{ .type = S3C_IRQTYPE_EDGE, }, /* nBATT_FLT */
   1007	{ .type = S3C_IRQTYPE_EDGE, }, /* TICK */
   1008	{ .type = S3C_IRQTYPE_EDGE, }, /* WDT */
   1009	{ .type = S3C_IRQTYPE_EDGE, }, /* TIMER0 */
   1010	{ .type = S3C_IRQTYPE_EDGE, }, /* TIMER1 */
   1011	{ .type = S3C_IRQTYPE_EDGE, }, /* TIMER2 */
   1012	{ .type = S3C_IRQTYPE_EDGE, }, /* TIMER3 */
   1013	{ .type = S3C_IRQTYPE_EDGE, }, /* TIMER4 */
   1014	{ .type = S3C_IRQTYPE_LEVEL, }, /* UART2 */
   1015	{ .type = S3C_IRQTYPE_EDGE, }, /* LCD */
   1016	{ .type = S3C_IRQTYPE_EDGE, }, /* DMA0 */
   1017	{ .type = S3C_IRQTYPE_EDGE, }, /* DMA1 */
   1018	{ .type = S3C_IRQTYPE_EDGE, }, /* DMA2 */
   1019	{ .type = S3C_IRQTYPE_EDGE, }, /* DMA3 */
   1020	{ .type = S3C_IRQTYPE_EDGE, }, /* SDI */
   1021	{ .type = S3C_IRQTYPE_EDGE, }, /* SPI0 */
   1022	{ .type = S3C_IRQTYPE_LEVEL, }, /* UART1 */
   1023	{ .type = S3C_IRQTYPE_LEVEL, }, /* NFCON */
   1024	{ .type = S3C_IRQTYPE_EDGE, }, /* USBD */
   1025	{ .type = S3C_IRQTYPE_EDGE, }, /* USBH */
   1026	{ .type = S3C_IRQTYPE_EDGE, }, /* IIC */
   1027	{ .type = S3C_IRQTYPE_LEVEL, }, /* UART0 */
   1028	{ .type = S3C_IRQTYPE_EDGE, }, /* SPI1 */
   1029	{ .type = S3C_IRQTYPE_EDGE, }, /* RTC */
   1030	{ .type = S3C_IRQTYPE_LEVEL, }, /* ADCPARENT */
   1031};
   1032
   1033static struct s3c_irq_data init_s3c2442subint[32] = {
   1034	{ .type = S3C_IRQTYPE_LEVEL, .parent_irq = 28 }, /* UART0-RX */
   1035	{ .type = S3C_IRQTYPE_LEVEL, .parent_irq = 28 }, /* UART0-TX */
   1036	{ .type = S3C_IRQTYPE_LEVEL, .parent_irq = 28 }, /* UART0-ERR */
   1037	{ .type = S3C_IRQTYPE_LEVEL, .parent_irq = 23 }, /* UART1-RX */
   1038	{ .type = S3C_IRQTYPE_LEVEL, .parent_irq = 23 }, /* UART1-TX */
   1039	{ .type = S3C_IRQTYPE_LEVEL, .parent_irq = 23 }, /* UART1-ERR */
   1040	{ .type = S3C_IRQTYPE_LEVEL, .parent_irq = 15 }, /* UART2-RX */
   1041	{ .type = S3C_IRQTYPE_LEVEL, .parent_irq = 15 }, /* UART2-TX */
   1042	{ .type = S3C_IRQTYPE_LEVEL, .parent_irq = 15 }, /* UART2-ERR */
   1043	{ .type = S3C_IRQTYPE_EDGE, .parent_irq = 31 }, /* TC */
   1044	{ .type = S3C_IRQTYPE_EDGE, .parent_irq = 31 }, /* ADC */
   1045	{ .type = S3C_IRQTYPE_LEVEL, .parent_irq = 6 }, /* CAM_C */
   1046	{ .type = S3C_IRQTYPE_LEVEL, .parent_irq = 6 }, /* CAM_P */
   1047};
   1048
   1049void __init s3c2442_init_irq(void)
   1050{
   1051	pr_info("S3C2442: IRQ Support\n");
   1052
   1053#ifdef CONFIG_FIQ
   1054	init_FIQ(FIQ_START);
   1055#endif
   1056
   1057	s3c_intc[0] = s3c24xx_init_intc(NULL, &init_s3c2442base[0], NULL,
   1058					0x4a000000);
   1059	if (IS_ERR(s3c_intc[0])) {
   1060		pr_err("irq: could not create main interrupt controller\n");
   1061		return;
   1062	}
   1063
   1064	s3c24xx_init_intc(NULL, &init_eint[0], s3c_intc[0], 0x560000a4);
   1065	s3c_intc[1] = s3c24xx_init_intc(NULL, &init_s3c2442subint[0],
   1066					s3c_intc[0], 0x4a000018);
   1067}
   1068#endif
   1069
   1070#ifdef CONFIG_CPU_S3C2443
   1071static struct s3c_irq_data init_s3c2443base[32] = {
   1072	{ .type = S3C_IRQTYPE_EINT, }, /* EINT0 */
   1073	{ .type = S3C_IRQTYPE_EINT, }, /* EINT1 */
   1074	{ .type = S3C_IRQTYPE_EINT, }, /* EINT2 */
   1075	{ .type = S3C_IRQTYPE_EINT, }, /* EINT3 */
   1076	{ .type = S3C_IRQTYPE_LEVEL, }, /* EINT4to7 */
   1077	{ .type = S3C_IRQTYPE_LEVEL, }, /* EINT8to23 */
   1078	{ .type = S3C_IRQTYPE_LEVEL, }, /* CAM */
   1079	{ .type = S3C_IRQTYPE_EDGE, }, /* nBATT_FLT */
   1080	{ .type = S3C_IRQTYPE_EDGE, }, /* TICK */
   1081	{ .type = S3C_IRQTYPE_LEVEL, }, /* WDT/AC97 */
   1082	{ .type = S3C_IRQTYPE_EDGE, }, /* TIMER0 */
   1083	{ .type = S3C_IRQTYPE_EDGE, }, /* TIMER1 */
   1084	{ .type = S3C_IRQTYPE_EDGE, }, /* TIMER2 */
   1085	{ .type = S3C_IRQTYPE_EDGE, }, /* TIMER3 */
   1086	{ .type = S3C_IRQTYPE_EDGE, }, /* TIMER4 */
   1087	{ .type = S3C_IRQTYPE_LEVEL, }, /* UART2 */
   1088	{ .type = S3C_IRQTYPE_LEVEL, }, /* LCD */
   1089	{ .type = S3C_IRQTYPE_LEVEL, }, /* DMA */
   1090	{ .type = S3C_IRQTYPE_LEVEL, }, /* UART3 */
   1091	{ .type = S3C_IRQTYPE_EDGE, }, /* CFON */
   1092	{ .type = S3C_IRQTYPE_EDGE, }, /* SDI1 */
   1093	{ .type = S3C_IRQTYPE_EDGE, }, /* SDI0 */
   1094	{ .type = S3C_IRQTYPE_EDGE, }, /* SPI0 */
   1095	{ .type = S3C_IRQTYPE_LEVEL, }, /* UART1 */
   1096	{ .type = S3C_IRQTYPE_EDGE, }, /* NAND */
   1097	{ .type = S3C_IRQTYPE_EDGE, }, /* USBD */
   1098	{ .type = S3C_IRQTYPE_EDGE, }, /* USBH */
   1099	{ .type = S3C_IRQTYPE_EDGE, }, /* IIC */
   1100	{ .type = S3C_IRQTYPE_LEVEL, }, /* UART0 */
   1101	{ .type = S3C_IRQTYPE_EDGE, }, /* SPI1 */
   1102	{ .type = S3C_IRQTYPE_EDGE, }, /* RTC */
   1103	{ .type = S3C_IRQTYPE_LEVEL, }, /* ADCPARENT */
   1104};
   1105
   1106
   1107static struct s3c_irq_data init_s3c2443subint[32] = {
   1108	{ .type = S3C_IRQTYPE_LEVEL, .parent_irq = 28 }, /* UART0-RX */
   1109	{ .type = S3C_IRQTYPE_LEVEL, .parent_irq = 28 }, /* UART0-TX */
   1110	{ .type = S3C_IRQTYPE_LEVEL, .parent_irq = 28 }, /* UART0-ERR */
   1111	{ .type = S3C_IRQTYPE_LEVEL, .parent_irq = 23 }, /* UART1-RX */
   1112	{ .type = S3C_IRQTYPE_LEVEL, .parent_irq = 23 }, /* UART1-TX */
   1113	{ .type = S3C_IRQTYPE_LEVEL, .parent_irq = 23 }, /* UART1-ERR */
   1114	{ .type = S3C_IRQTYPE_LEVEL, .parent_irq = 15 }, /* UART2-RX */
   1115	{ .type = S3C_IRQTYPE_LEVEL, .parent_irq = 15 }, /* UART2-TX */
   1116	{ .type = S3C_IRQTYPE_LEVEL, .parent_irq = 15 }, /* UART2-ERR */
   1117	{ .type = S3C_IRQTYPE_EDGE, .parent_irq = 31 }, /* TC */
   1118	{ .type = S3C_IRQTYPE_EDGE, .parent_irq = 31 }, /* ADC */
   1119	{ .type = S3C_IRQTYPE_LEVEL, .parent_irq = 6 }, /* CAM_C */
   1120	{ .type = S3C_IRQTYPE_LEVEL, .parent_irq = 6 }, /* CAM_P */
   1121	{ .type = S3C_IRQTYPE_NONE }, /* reserved */
   1122	{ .type = S3C_IRQTYPE_LEVEL, .parent_irq = 16 }, /* LCD1 */
   1123	{ .type = S3C_IRQTYPE_LEVEL, .parent_irq = 16 }, /* LCD2 */
   1124	{ .type = S3C_IRQTYPE_LEVEL, .parent_irq = 16 }, /* LCD3 */
   1125	{ .type = S3C_IRQTYPE_LEVEL, .parent_irq = 16 }, /* LCD4 */
   1126	{ .type = S3C_IRQTYPE_LEVEL, .parent_irq = 17 }, /* DMA0 */
   1127	{ .type = S3C_IRQTYPE_LEVEL, .parent_irq = 17 }, /* DMA1 */
   1128	{ .type = S3C_IRQTYPE_LEVEL, .parent_irq = 17 }, /* DMA2 */
   1129	{ .type = S3C_IRQTYPE_LEVEL, .parent_irq = 17 }, /* DMA3 */
   1130	{ .type = S3C_IRQTYPE_LEVEL, .parent_irq = 17 }, /* DMA4 */
   1131	{ .type = S3C_IRQTYPE_LEVEL, .parent_irq = 17 }, /* DMA5 */
   1132	{ .type = S3C_IRQTYPE_LEVEL, .parent_irq = 18 }, /* UART3-RX */
   1133	{ .type = S3C_IRQTYPE_LEVEL, .parent_irq = 18 }, /* UART3-TX */
   1134	{ .type = S3C_IRQTYPE_LEVEL, .parent_irq = 18 }, /* UART3-ERR */
   1135	{ .type = S3C_IRQTYPE_LEVEL, .parent_irq = 9 }, /* WDT */
   1136	{ .type = S3C_IRQTYPE_LEVEL, .parent_irq = 9 }, /* AC97 */
   1137};
   1138
   1139void __init s3c2443_init_irq(void)
   1140{
   1141	pr_info("S3C2443: IRQ Support\n");
   1142
   1143#ifdef CONFIG_FIQ
   1144	init_FIQ(FIQ_START);
   1145#endif
   1146
   1147	s3c_intc[0] = s3c24xx_init_intc(NULL, &init_s3c2443base[0], NULL,
   1148					0x4a000000);
   1149	if (IS_ERR(s3c_intc[0])) {
   1150		pr_err("irq: could not create main interrupt controller\n");
   1151		return;
   1152	}
   1153
   1154	s3c24xx_init_intc(NULL, &init_eint[0], s3c_intc[0], 0x560000a4);
   1155	s3c_intc[1] = s3c24xx_init_intc(NULL, &init_s3c2443subint[0],
   1156					s3c_intc[0], 0x4a000018);
   1157}
   1158#endif
   1159
   1160#ifdef CONFIG_OF
   1161static int s3c24xx_irq_map_of(struct irq_domain *h, unsigned int virq,
   1162							irq_hw_number_t hw)
   1163{
   1164	unsigned int ctrl_num = hw / 32;
   1165	unsigned int intc_hw = hw % 32;
   1166	struct s3c_irq_intc *intc = s3c_intc[ctrl_num];
   1167	struct s3c_irq_intc *parent_intc = intc->parent;
   1168	struct s3c_irq_data *irq_data = &intc->irqs[intc_hw];
   1169
   1170	/* attach controller pointer to irq_data */
   1171	irq_data->intc = intc;
   1172	irq_data->offset = intc_hw;
   1173
   1174	if (!parent_intc)
   1175		irq_set_chip_and_handler(virq, &s3c_irq_chip, handle_edge_irq);
   1176	else
   1177		irq_set_chip_and_handler(virq, &s3c_irq_level_chip,
   1178					 handle_edge_irq);
   1179
   1180	irq_set_chip_data(virq, irq_data);
   1181
   1182	return 0;
   1183}
   1184
   1185/* Translate our of irq notation
   1186 * format: <ctrl_num ctrl_irq parent_irq type>
   1187 */
   1188static int s3c24xx_irq_xlate_of(struct irq_domain *d, struct device_node *n,
   1189			const u32 *intspec, unsigned int intsize,
   1190			irq_hw_number_t *out_hwirq, unsigned int *out_type)
   1191{
   1192	struct s3c_irq_intc *intc;
   1193	struct s3c_irq_intc *parent_intc;
   1194	struct s3c_irq_data *irq_data;
   1195	struct s3c_irq_data *parent_irq_data;
   1196	int irqno;
   1197
   1198	if (WARN_ON(intsize < 4))
   1199		return -EINVAL;
   1200
   1201	if (intspec[0] > 2 || !s3c_intc[intspec[0]]) {
   1202		pr_err("controller number %d invalid\n", intspec[0]);
   1203		return -EINVAL;
   1204	}
   1205	intc = s3c_intc[intspec[0]];
   1206
   1207	*out_hwirq = intspec[0] * 32 + intspec[2];
   1208	*out_type = intspec[3] & IRQ_TYPE_SENSE_MASK;
   1209
   1210	parent_intc = intc->parent;
   1211	if (parent_intc) {
   1212		irq_data = &intc->irqs[intspec[2]];
   1213		irq_data->parent_irq = intspec[1];
   1214		parent_irq_data = &parent_intc->irqs[irq_data->parent_irq];
   1215		parent_irq_data->sub_intc = intc;
   1216		parent_irq_data->sub_bits |= (1UL << intspec[2]);
   1217
   1218		/* parent_intc is always s3c_intc[0], so no offset */
   1219		irqno = irq_create_mapping(parent_intc->domain, intspec[1]);
   1220		if (irqno < 0) {
   1221			pr_err("irq: could not map parent interrupt\n");
   1222			return irqno;
   1223		}
   1224
   1225		irq_set_chained_handler(irqno, s3c_irq_demux);
   1226	}
   1227
   1228	return 0;
   1229}
   1230
   1231static const struct irq_domain_ops s3c24xx_irq_ops_of = {
   1232	.map = s3c24xx_irq_map_of,
   1233	.xlate = s3c24xx_irq_xlate_of,
   1234};
   1235
   1236struct s3c24xx_irq_of_ctrl {
   1237	char			*name;
   1238	unsigned long		offset;
   1239	struct s3c_irq_intc	**handle;
   1240	struct s3c_irq_intc	**parent;
   1241	struct irq_domain_ops	*ops;
   1242};
   1243
   1244static int __init s3c_init_intc_of(struct device_node *np,
   1245			struct device_node *interrupt_parent,
   1246			struct s3c24xx_irq_of_ctrl *s3c_ctrl, int num_ctrl)
   1247{
   1248	struct s3c_irq_intc *intc;
   1249	struct s3c24xx_irq_of_ctrl *ctrl;
   1250	struct irq_domain *domain;
   1251	void __iomem *reg_base;
   1252	int i;
   1253
   1254	reg_base = of_iomap(np, 0);
   1255	if (!reg_base) {
   1256		pr_err("irq-s3c24xx: could not map irq registers\n");
   1257		return -EINVAL;
   1258	}
   1259
   1260	domain = irq_domain_add_linear(np, num_ctrl * 32,
   1261						     &s3c24xx_irq_ops_of, NULL);
   1262	if (!domain) {
   1263		pr_err("irq: could not create irq-domain\n");
   1264		return -EINVAL;
   1265	}
   1266
   1267	for (i = 0; i < num_ctrl; i++) {
   1268		ctrl = &s3c_ctrl[i];
   1269
   1270		pr_debug("irq: found controller %s\n", ctrl->name);
   1271
   1272		intc = kzalloc(sizeof(struct s3c_irq_intc), GFP_KERNEL);
   1273		if (!intc)
   1274			return -ENOMEM;
   1275
   1276		intc->domain = domain;
   1277		intc->irqs = kcalloc(32, sizeof(struct s3c_irq_data),
   1278				     GFP_KERNEL);
   1279		if (!intc->irqs) {
   1280			kfree(intc);
   1281			return -ENOMEM;
   1282		}
   1283
   1284		if (ctrl->parent) {
   1285			intc->reg_pending = reg_base + ctrl->offset;
   1286			intc->reg_mask = reg_base + ctrl->offset + 0x4;
   1287
   1288			if (*(ctrl->parent)) {
   1289				intc->parent = *(ctrl->parent);
   1290			} else {
   1291				pr_warn("irq: parent of %s missing\n",
   1292					ctrl->name);
   1293				kfree(intc->irqs);
   1294				kfree(intc);
   1295				continue;
   1296			}
   1297		} else {
   1298			intc->reg_pending = reg_base + ctrl->offset;
   1299			intc->reg_mask = reg_base + ctrl->offset + 0x08;
   1300			intc->reg_intpnd = reg_base + ctrl->offset + 0x10;
   1301		}
   1302
   1303		s3c24xx_clear_intc(intc);
   1304		s3c_intc[i] = intc;
   1305	}
   1306
   1307	set_handle_irq(s3c24xx_handle_irq);
   1308
   1309	return 0;
   1310}
   1311
   1312static struct s3c24xx_irq_of_ctrl s3c2410_ctrl[] = {
   1313	{
   1314		.name = "intc",
   1315		.offset = 0,
   1316	}, {
   1317		.name = "subintc",
   1318		.offset = 0x18,
   1319		.parent = &s3c_intc[0],
   1320	}
   1321};
   1322
   1323static int __init s3c2410_init_intc_of(struct device_node *np,
   1324			struct device_node *interrupt_parent)
   1325{
   1326	return s3c_init_intc_of(np, interrupt_parent,
   1327				s3c2410_ctrl, ARRAY_SIZE(s3c2410_ctrl));
   1328}
   1329IRQCHIP_DECLARE(s3c2410_irq, "samsung,s3c2410-irq", s3c2410_init_intc_of);
   1330
   1331static struct s3c24xx_irq_of_ctrl s3c2416_ctrl[] = {
   1332	{
   1333		.name = "intc",
   1334		.offset = 0,
   1335	}, {
   1336		.name = "subintc",
   1337		.offset = 0x18,
   1338		.parent = &s3c_intc[0],
   1339	}, {
   1340		.name = "intc2",
   1341		.offset = 0x40,
   1342	}
   1343};
   1344
   1345static int __init s3c2416_init_intc_of(struct device_node *np,
   1346			struct device_node *interrupt_parent)
   1347{
   1348	return s3c_init_intc_of(np, interrupt_parent,
   1349				s3c2416_ctrl, ARRAY_SIZE(s3c2416_ctrl));
   1350}
   1351IRQCHIP_DECLARE(s3c2416_irq, "samsung,s3c2416-irq", s3c2416_init_intc_of);
   1352#endif