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