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