blob: c2205eb78dc1cc253e6840b7d5af5e585e885068 [file] [log] [blame]
Heiko Stuebner1f629b72013-01-29 10:25:22 -08001/*
2 * S3C24XX IRQ handling
Ben Dooksa21765a2007-02-11 18:31:01 +01003 *
Ben Dookse02f8662009-11-13 22:54:13 +00004 * Copyright (c) 2003-2004 Simtec Electronics
Ben Dooksa21765a2007-02-11 18:31:01 +01005 * Ben Dooks <ben@simtec.co.uk>
Heiko Stuebner1f629b72013-01-29 10:25:22 -08006 * Copyright (c) 2012 Heiko Stuebner <heiko@sntech.de>
Ben Dooksa21765a2007-02-11 18:31:01 +01007 *
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.
Ben Dooksa21765a2007-02-11 18:31:01 +010017*/
18
19#include <linux/init.h>
Heiko Stuebner1f629b72013-01-29 10:25:22 -080020#include <linux/slab.h>
Ben Dooksa21765a2007-02-11 18:31:01 +010021#include <linux/module.h>
Heiko Stuebner1f629b72013-01-29 10:25:22 -080022#include <linux/io.h>
23#include <linux/err.h>
Ben Dooksa21765a2007-02-11 18:31:01 +010024#include <linux/interrupt.h>
25#include <linux/ioport.h>
Kay Sieversedbaa602011-12-21 16:26:03 -080026#include <linux/device.h>
Heiko Stuebner1f629b72013-01-29 10:25:22 -080027#include <linux/irqdomain.h>
Ben Dooksa21765a2007-02-11 18:31:01 +010028
Ben Dooksa21765a2007-02-11 18:31:01 +010029#include <asm/mach/irq.h>
30
Heiko Stuebner1f629b72013-01-29 10:25:22 -080031#include <mach/regs-irq.h>
32#include <mach/regs-gpio.h>
Ben Dooksa21765a2007-02-11 18:31:01 +010033
Ben Dooksa2b7ba92008-10-07 22:26:09 +010034#include <plat/cpu.h>
Heiko Stuebner1f629b72013-01-29 10:25:22 -080035#include <plat/regs-irqtype.h>
Ben Dooksa2b7ba92008-10-07 22:26:09 +010036#include <plat/pm.h>
Ben Dooksa21765a2007-02-11 18:31:01 +010037
Heiko Stuebner1f629b72013-01-29 10:25:22 -080038#define S3C_IRQTYPE_NONE 0
39#define S3C_IRQTYPE_EINT 1
40#define S3C_IRQTYPE_EDGE 2
41#define S3C_IRQTYPE_LEVEL 3
Ben Dooksa21765a2007-02-11 18:31:01 +010042
Heiko Stuebner1f629b72013-01-29 10:25:22 -080043struct s3c_irq_data {
44 unsigned int type;
45 unsigned long parent_irq;
Ben Dooksa21765a2007-02-11 18:31:01 +010046
Heiko Stuebner1f629b72013-01-29 10:25:22 -080047 /* data gets filled during init */
48 struct s3c_irq_intc *intc;
49 unsigned long sub_bits;
50 struct s3c_irq_intc *sub_intc;
Ben Dooksa21765a2007-02-11 18:31:01 +010051};
52
Heiko Stuebner1f629b72013-01-29 10:25:22 -080053/*
54 * Sructure holding the controller data
55 * @reg_pending register holding pending irqs
56 * @reg_intpnd special register intpnd in main intc
57 * @reg_mask mask register
58 * @domain irq_domain of the controller
59 * @parent parent controller for ext and sub irqs
60 * @irqs irq-data, always s3c_irq_data[32]
61 */
62struct s3c_irq_intc {
63 void __iomem *reg_pending;
64 void __iomem *reg_intpnd;
65 void __iomem *reg_mask;
66 struct irq_domain *domain;
67 struct s3c_irq_intc *parent;
68 struct s3c_irq_data *irqs;
Ben Dooksa21765a2007-02-11 18:31:01 +010069};
70
Heiko Stuebner1f629b72013-01-29 10:25:22 -080071static void s3c_irq_mask(struct irq_data *data)
Ben Dooksa21765a2007-02-11 18:31:01 +010072{
Heiko Stuebner1f629b72013-01-29 10:25:22 -080073 struct s3c_irq_intc *intc = data->domain->host_data;
74 struct s3c_irq_intc *parent_intc = intc->parent;
75 struct s3c_irq_data *irq_data = &intc->irqs[data->hwirq];
76 struct s3c_irq_data *parent_data;
Ben Dooksa21765a2007-02-11 18:31:01 +010077 unsigned long mask;
Heiko Stuebner1f629b72013-01-29 10:25:22 -080078 unsigned int irqno;
Ben Dooksa21765a2007-02-11 18:31:01 +010079
Heiko Stuebner1f629b72013-01-29 10:25:22 -080080 mask = __raw_readl(intc->reg_mask);
81 mask |= (1UL << data->hwirq);
82 __raw_writel(mask, intc->reg_mask);
Ben Dooksa21765a2007-02-11 18:31:01 +010083
Heiko Stuebner1f629b72013-01-29 10:25:22 -080084 if (parent_intc && irq_data->parent_irq) {
85 parent_data = &parent_intc->irqs[irq_data->parent_irq];
Ben Dooksa21765a2007-02-11 18:31:01 +010086
Heiko Stuebner1f629b72013-01-29 10:25:22 -080087 /* check to see if we need to mask the parent IRQ */
88 if ((mask & parent_data->sub_bits) == parent_data->sub_bits) {
89 irqno = irq_find_mapping(parent_intc->domain,
90 irq_data->parent_irq);
91 s3c_irq_mask(irq_get_irq_data(irqno));
92 }
Ben Dooksa21765a2007-02-11 18:31:01 +010093 }
94}
95
Heiko Stuebner1f629b72013-01-29 10:25:22 -080096static void s3c_irq_unmask(struct irq_data *data)
Ben Dooksa21765a2007-02-11 18:31:01 +010097{
Heiko Stuebner1f629b72013-01-29 10:25:22 -080098 struct s3c_irq_intc *intc = data->domain->host_data;
99 struct s3c_irq_intc *parent_intc = intc->parent;
100 struct s3c_irq_data *irq_data = &intc->irqs[data->hwirq];
Ben Dooksa21765a2007-02-11 18:31:01 +0100101 unsigned long mask;
Heiko Stuebner1f629b72013-01-29 10:25:22 -0800102 unsigned int irqno;
Ben Dooksa21765a2007-02-11 18:31:01 +0100103
Heiko Stuebner1f629b72013-01-29 10:25:22 -0800104 mask = __raw_readl(intc->reg_mask);
105 mask &= ~(1UL << data->hwirq);
106 __raw_writel(mask, intc->reg_mask);
107
108 if (parent_intc && irq_data->parent_irq) {
109 irqno = irq_find_mapping(parent_intc->domain,
110 irq_data->parent_irq);
111 s3c_irq_unmask(irq_get_irq_data(irqno));
112 }
Ben Dooksa21765a2007-02-11 18:31:01 +0100113}
114
Heiko Stuebner1f629b72013-01-29 10:25:22 -0800115static inline void s3c_irq_ack(struct irq_data *data)
Ben Dooksa21765a2007-02-11 18:31:01 +0100116{
Heiko Stuebner1f629b72013-01-29 10:25:22 -0800117 struct s3c_irq_intc *intc = data->domain->host_data;
118 unsigned long bitval = 1UL << data->hwirq;
119
120 __raw_writel(bitval, intc->reg_pending);
121 if (intc->reg_intpnd)
122 __raw_writel(bitval, intc->reg_intpnd);
123}
124
125static int s3c_irqext_type_set(void __iomem *gpcon_reg,
126 void __iomem *extint_reg,
127 unsigned long gpcon_offset,
128 unsigned long extint_offset,
129 unsigned int type)
130{
Ben Dooksa21765a2007-02-11 18:31:01 +0100131 unsigned long newvalue = 0, value;
132
Ben Dooksa21765a2007-02-11 18:31:01 +0100133 /* Set the GPIO to external interrupt mode */
134 value = __raw_readl(gpcon_reg);
135 value = (value & ~(3 << gpcon_offset)) | (0x02 << gpcon_offset);
136 __raw_writel(value, gpcon_reg);
137
138 /* Set the external interrupt to pointed trigger type */
139 switch (type)
140 {
Dmitry Baryshkov6cab4862008-07-27 04:23:31 +0100141 case IRQ_TYPE_NONE:
Heiko Stuebner1f629b72013-01-29 10:25:22 -0800142 pr_warn("No edge setting!\n");
Ben Dooksa21765a2007-02-11 18:31:01 +0100143 break;
144
Dmitry Baryshkov6cab4862008-07-27 04:23:31 +0100145 case IRQ_TYPE_EDGE_RISING:
Ben Dooksa21765a2007-02-11 18:31:01 +0100146 newvalue = S3C2410_EXTINT_RISEEDGE;
147 break;
148
Dmitry Baryshkov6cab4862008-07-27 04:23:31 +0100149 case IRQ_TYPE_EDGE_FALLING:
Ben Dooksa21765a2007-02-11 18:31:01 +0100150 newvalue = S3C2410_EXTINT_FALLEDGE;
151 break;
152
Dmitry Baryshkov6cab4862008-07-27 04:23:31 +0100153 case IRQ_TYPE_EDGE_BOTH:
Ben Dooksa21765a2007-02-11 18:31:01 +0100154 newvalue = S3C2410_EXTINT_BOTHEDGE;
155 break;
156
Dmitry Baryshkov6cab4862008-07-27 04:23:31 +0100157 case IRQ_TYPE_LEVEL_LOW:
Ben Dooksa21765a2007-02-11 18:31:01 +0100158 newvalue = S3C2410_EXTINT_LOWLEV;
159 break;
160
Dmitry Baryshkov6cab4862008-07-27 04:23:31 +0100161 case IRQ_TYPE_LEVEL_HIGH:
Ben Dooksa21765a2007-02-11 18:31:01 +0100162 newvalue = S3C2410_EXTINT_HILEV;
163 break;
164
165 default:
Heiko Stuebner1f629b72013-01-29 10:25:22 -0800166 pr_err("No such irq type %d", type);
167 return -EINVAL;
Ben Dooksa21765a2007-02-11 18:31:01 +0100168 }
169
170 value = __raw_readl(extint_reg);
171 value = (value & ~(7 << extint_offset)) | (newvalue << extint_offset);
172 __raw_writel(value, extint_reg);
173
174 return 0;
175}
176
Heiko Stuebnerdc1a3532013-02-12 14:23:01 -0800177static int s3c_irqext_type(struct irq_data *data, unsigned int type)
Heiko Stuebner1f629b72013-01-29 10:25:22 -0800178{
179 void __iomem *extint_reg;
180 void __iomem *gpcon_reg;
181 unsigned long gpcon_offset, extint_offset;
182
183 if ((data->hwirq >= 4) && (data->hwirq <= 7)) {
184 gpcon_reg = S3C2410_GPFCON;
185 extint_reg = S3C24XX_EXTINT0;
186 gpcon_offset = (data->hwirq) * 2;
187 extint_offset = (data->hwirq) * 4;
188 } else if ((data->hwirq >= 8) && (data->hwirq <= 15)) {
189 gpcon_reg = S3C2410_GPGCON;
190 extint_reg = S3C24XX_EXTINT1;
191 gpcon_offset = (data->hwirq - 8) * 2;
192 extint_offset = (data->hwirq - 8) * 4;
193 } else if ((data->hwirq >= 16) && (data->hwirq <= 23)) {
194 gpcon_reg = S3C2410_GPGCON;
195 extint_reg = S3C24XX_EXTINT2;
196 gpcon_offset = (data->hwirq - 8) * 2;
197 extint_offset = (data->hwirq - 16) * 4;
198 } else {
199 return -EINVAL;
200 }
201
202 return s3c_irqext_type_set(gpcon_reg, extint_reg, gpcon_offset,
203 extint_offset, type);
204}
205
206static int s3c_irqext0_type(struct irq_data *data, unsigned int type)
207{
208 void __iomem *extint_reg;
209 void __iomem *gpcon_reg;
210 unsigned long gpcon_offset, extint_offset;
211
212 if ((data->hwirq >= 0) && (data->hwirq <= 3)) {
213 gpcon_reg = S3C2410_GPFCON;
214 extint_reg = S3C24XX_EXTINT0;
215 gpcon_offset = (data->hwirq) * 2;
216 extint_offset = (data->hwirq) * 4;
217 } else {
218 return -EINVAL;
219 }
220
221 return s3c_irqext_type_set(gpcon_reg, extint_reg, gpcon_offset,
222 extint_offset, type);
223}
224
Heiko Stuebnerdc1a3532013-02-12 14:23:01 -0800225static struct irq_chip s3c_irq_chip = {
Heiko Stuebner1f629b72013-01-29 10:25:22 -0800226 .name = "s3c",
227 .irq_ack = s3c_irq_ack,
228 .irq_mask = s3c_irq_mask,
229 .irq_unmask = s3c_irq_unmask,
230 .irq_set_wake = s3c_irq_wake
231};
232
Heiko Stuebnerdc1a3532013-02-12 14:23:01 -0800233static struct irq_chip s3c_irq_level_chip = {
Heiko Stuebner1f629b72013-01-29 10:25:22 -0800234 .name = "s3c-level",
235 .irq_mask = s3c_irq_mask,
236 .irq_unmask = s3c_irq_unmask,
237 .irq_ack = s3c_irq_ack,
238};
239
Ben Dooksa21765a2007-02-11 18:31:01 +0100240static struct irq_chip s3c_irqext_chip = {
241 .name = "s3c-ext",
Heiko Stuebner1f629b72013-01-29 10:25:22 -0800242 .irq_mask = s3c_irq_mask,
243 .irq_unmask = s3c_irq_unmask,
244 .irq_ack = s3c_irq_ack,
Lennert Buytenhek57436c2d2011-01-03 19:15:54 +0900245 .irq_set_type = s3c_irqext_type,
Mark Brownf5aeffb2010-12-02 14:35:38 +0900246 .irq_set_wake = s3c_irqext_wake
Ben Dooksa21765a2007-02-11 18:31:01 +0100247};
248
249static struct irq_chip s3c_irq_eint0t4 = {
250 .name = "s3c-ext0",
Lennert Buytenhek57436c2d2011-01-03 19:15:54 +0900251 .irq_ack = s3c_irq_ack,
252 .irq_mask = s3c_irq_mask,
253 .irq_unmask = s3c_irq_unmask,
254 .irq_set_wake = s3c_irq_wake,
Heiko Stuebner1f629b72013-01-29 10:25:22 -0800255 .irq_set_type = s3c_irqext0_type,
Ben Dooksa21765a2007-02-11 18:31:01 +0100256};
257
Heiko Stuebner1f629b72013-01-29 10:25:22 -0800258static void s3c_irq_demux(unsigned int irq, struct irq_desc *desc)
Ben Dooksa21765a2007-02-11 18:31:01 +0100259{
Heiko Stuebner1f629b72013-01-29 10:25:22 -0800260 struct irq_chip *chip = irq_desc_get_chip(desc);
261 struct s3c_irq_intc *intc = desc->irq_data.domain->host_data;
262 struct s3c_irq_data *irq_data = &intc->irqs[desc->irq_data.hwirq];
263 struct s3c_irq_intc *sub_intc = irq_data->sub_intc;
264 unsigned long src;
265 unsigned long msk;
266 unsigned int n;
Ben Dooksa21765a2007-02-11 18:31:01 +0100267
Heiko Stuebner1f629b72013-01-29 10:25:22 -0800268 chained_irq_enter(chip, desc);
Ben Dooksa21765a2007-02-11 18:31:01 +0100269
Heiko Stuebner1f629b72013-01-29 10:25:22 -0800270 src = __raw_readl(sub_intc->reg_pending);
271 msk = __raw_readl(sub_intc->reg_mask);
Ben Dooksa21765a2007-02-11 18:31:01 +0100272
Heiko Stuebner1f629b72013-01-29 10:25:22 -0800273 src &= ~msk;
274 src &= irq_data->sub_bits;
Ben Dooksa21765a2007-02-11 18:31:01 +0100275
Heiko Stuebner1f629b72013-01-29 10:25:22 -0800276 while (src) {
277 n = __ffs(src);
278 src &= ~(1 << n);
279 generic_handle_irq(irq_find_mapping(sub_intc->domain, n));
Ben Dooksa21765a2007-02-11 18:31:01 +0100280 }
281
Heiko Stuebner1f629b72013-01-29 10:25:22 -0800282 chained_irq_exit(chip, desc);
Ben Dooksa21765a2007-02-11 18:31:01 +0100283}
284
Ben Dooks229fd8f2009-08-03 17:26:57 +0100285#ifdef CONFIG_FIQ
286/**
287 * s3c24xx_set_fiq - set the FIQ routing
288 * @irq: IRQ number to route to FIQ on processor.
289 * @on: Whether to route @irq to the FIQ, or to remove the FIQ routing.
290 *
291 * Change the state of the IRQ to FIQ routing depending on @irq and @on. If
292 * @on is true, the @irq is checked to see if it can be routed and the
293 * interrupt controller updated to route the IRQ. If @on is false, the FIQ
294 * routing is cleared, regardless of which @irq is specified.
295 */
296int s3c24xx_set_fiq(unsigned int irq, bool on)
297{
298 u32 intmod;
299 unsigned offs;
300
301 if (on) {
302 offs = irq - FIQ_START;
303 if (offs > 31)
304 return -EINVAL;
305
306 intmod = 1 << offs;
307 } else {
308 intmod = 0;
309 }
310
311 __raw_writel(intmod, S3C2410_INTMOD);
312 return 0;
313}
Ben Dooks0f13c822009-12-07 14:51:38 +0000314
315EXPORT_SYMBOL_GPL(s3c24xx_set_fiq);
Ben Dooks229fd8f2009-08-03 17:26:57 +0100316#endif
317
Heiko Stuebner1f629b72013-01-29 10:25:22 -0800318static int s3c24xx_irq_map(struct irq_domain *h, unsigned int virq,
319 irq_hw_number_t hw)
320{
321 struct s3c_irq_intc *intc = h->host_data;
322 struct s3c_irq_data *irq_data = &intc->irqs[hw];
323 struct s3c_irq_intc *parent_intc;
324 struct s3c_irq_data *parent_irq_data;
325 unsigned int irqno;
326
327 if (!intc) {
328 pr_err("irq-s3c24xx: no controller found for hwirq %lu\n", hw);
329 return -EINVAL;
330 }
331
332 if (!irq_data) {
333 pr_err("irq-s3c24xx: no irq data found for hwirq %lu\n", hw);
334 return -EINVAL;
335 }
336
337 /* attach controller pointer to irq_data */
338 irq_data->intc = intc;
339
340 /* set handler and flags */
341 switch (irq_data->type) {
342 case S3C_IRQTYPE_NONE:
343 return 0;
344 case S3C_IRQTYPE_EINT:
345 if (irq_data->parent_irq)
346 irq_set_chip_and_handler(virq, &s3c_irqext_chip,
347 handle_edge_irq);
348 else
349 irq_set_chip_and_handler(virq, &s3c_irq_eint0t4,
350 handle_edge_irq);
351 break;
352 case S3C_IRQTYPE_EDGE:
Heiko Stuebner20f6c782013-01-29 10:25:22 -0800353 if (irq_data->parent_irq ||
354 intc->reg_pending == S3C2416_SRCPND2)
Heiko Stuebner1f629b72013-01-29 10:25:22 -0800355 irq_set_chip_and_handler(virq, &s3c_irq_level_chip,
356 handle_edge_irq);
357 else
358 irq_set_chip_and_handler(virq, &s3c_irq_chip,
359 handle_edge_irq);
360 break;
361 case S3C_IRQTYPE_LEVEL:
362 if (irq_data->parent_irq)
363 irq_set_chip_and_handler(virq, &s3c_irq_level_chip,
364 handle_level_irq);
365 else
366 irq_set_chip_and_handler(virq, &s3c_irq_chip,
367 handle_level_irq);
368 break;
369 default:
370 pr_err("irq-s3c24xx: unsupported irqtype %d\n", irq_data->type);
371 return -EINVAL;
372 }
373 set_irq_flags(virq, IRQF_VALID);
374
375 if (irq_data->parent_irq) {
376 parent_intc = intc->parent;
377 if (!parent_intc) {
378 pr_err("irq-s3c24xx: no parent controller found for hwirq %lu\n",
379 hw);
380 goto err;
381 }
382
383 parent_irq_data = &parent_intc->irqs[irq_data->parent_irq];
384 if (!irq_data) {
385 pr_err("irq-s3c24xx: no irq data found for hwirq %lu\n",
386 hw);
387 goto err;
388 }
389
390 parent_irq_data->sub_intc = intc;
391 parent_irq_data->sub_bits |= (1UL << hw);
392
393 /* attach the demuxer to the parent irq */
394 irqno = irq_find_mapping(parent_intc->domain,
395 irq_data->parent_irq);
396 if (!irqno) {
397 pr_err("irq-s3c24xx: could not find mapping for parent irq %lu\n",
398 irq_data->parent_irq);
399 goto err;
400 }
401 irq_set_chained_handler(irqno, s3c_irq_demux);
402 }
403
404 return 0;
405
406err:
407 set_irq_flags(virq, 0);
408
409 /* the only error can result from bad mapping data*/
410 return -EINVAL;
411}
412
413static struct irq_domain_ops s3c24xx_irq_ops = {
414 .map = s3c24xx_irq_map,
415 .xlate = irq_domain_xlate_twocell,
416};
417
418static void s3c24xx_clear_intc(struct s3c_irq_intc *intc)
419{
420 void __iomem *reg_source;
421 unsigned long pend;
422 unsigned long last;
423 int i;
424
425 /* if intpnd is set, read the next pending irq from there */
426 reg_source = intc->reg_intpnd ? intc->reg_intpnd : intc->reg_pending;
427
428 last = 0;
429 for (i = 0; i < 4; i++) {
430 pend = __raw_readl(reg_source);
431
432 if (pend == 0 || pend == last)
433 break;
434
435 __raw_writel(pend, intc->reg_pending);
436 if (intc->reg_intpnd)
437 __raw_writel(pend, intc->reg_intpnd);
438
439 pr_info("irq: clearing pending status %08x\n", (int)pend);
440 last = pend;
441 }
442}
443
444struct s3c_irq_intc *s3c24xx_init_intc(struct device_node *np,
445 struct s3c_irq_data *irq_data,
446 struct s3c_irq_intc *parent,
447 unsigned long address)
448{
449 struct s3c_irq_intc *intc;
450 void __iomem *base = (void *)0xf6000000; /* static mapping */
451 int irq_num;
452 int irq_start;
Heiko Stuebner1f629b72013-01-29 10:25:22 -0800453 int ret;
454
455 intc = kzalloc(sizeof(struct s3c_irq_intc), GFP_KERNEL);
456 if (!intc)
457 return ERR_PTR(-ENOMEM);
458
459 intc->irqs = irq_data;
460
461 if (parent)
462 intc->parent = parent;
463
464 /* select the correct data for the controller.
465 * Need to hard code the irq num start and offset
466 * to preserve the static mapping for now
467 */
468 switch (address) {
469 case 0x4a000000:
470 pr_debug("irq: found main intc\n");
471 intc->reg_pending = base;
472 intc->reg_mask = base + 0x08;
473 intc->reg_intpnd = base + 0x10;
474 irq_num = 32;
475 irq_start = S3C2410_IRQ(0);
Heiko Stuebner1f629b72013-01-29 10:25:22 -0800476 break;
477 case 0x4a000018:
478 pr_debug("irq: found subintc\n");
479 intc->reg_pending = base + 0x18;
480 intc->reg_mask = base + 0x1c;
481 irq_num = 29;
482 irq_start = S3C2410_IRQSUB(0);
Heiko Stuebner1f629b72013-01-29 10:25:22 -0800483 break;
484 case 0x4a000040:
485 pr_debug("irq: found intc2\n");
486 intc->reg_pending = base + 0x40;
487 intc->reg_mask = base + 0x48;
488 intc->reg_intpnd = base + 0x50;
489 irq_num = 8;
490 irq_start = S3C2416_IRQ(0);
Heiko Stuebner1f629b72013-01-29 10:25:22 -0800491 break;
492 case 0x560000a4:
493 pr_debug("irq: found eintc\n");
494 base = (void *)0xfd000000;
495
496 intc->reg_mask = base + 0xa4;
497 intc->reg_pending = base + 0x08;
Heiko Stuebner5424f212013-02-12 10:12:04 -0800498 irq_num = 24;
Heiko Stuebner1f629b72013-01-29 10:25:22 -0800499 irq_start = S3C2410_IRQ(32);
Heiko Stuebner1f629b72013-01-29 10:25:22 -0800500 break;
501 default:
502 pr_err("irq: unsupported controller address\n");
503 ret = -EINVAL;
504 goto err;
505 }
506
507 /* now that all the data is complete, init the irq-domain */
508 s3c24xx_clear_intc(intc);
509 intc->domain = irq_domain_add_legacy(np, irq_num, irq_start,
Heiko Stuebner5424f212013-02-12 10:12:04 -0800510 0, &s3c24xx_irq_ops,
Heiko Stuebner1f629b72013-01-29 10:25:22 -0800511 intc);
512 if (!intc->domain) {
513 pr_err("irq: could not create irq-domain\n");
514 ret = -EINVAL;
515 goto err;
516 }
517
518 return intc;
519
520err:
521 kfree(intc);
522 return ERR_PTR(ret);
523}
Ben Dooks229fd8f2009-08-03 17:26:57 +0100524
Ben Dooksa21765a2007-02-11 18:31:01 +0100525/* s3c24xx_init_irq
526 *
527 * Initialise S3C2410 IRQ system
528*/
529
Heiko Stuebner1f629b72013-01-29 10:25:22 -0800530static struct s3c_irq_data init_base[32] = {
531 { .type = S3C_IRQTYPE_EINT, }, /* EINT0 */
532 { .type = S3C_IRQTYPE_EINT, }, /* EINT1 */
533 { .type = S3C_IRQTYPE_EINT, }, /* EINT2 */
534 { .type = S3C_IRQTYPE_EINT, }, /* EINT3 */
535 { .type = S3C_IRQTYPE_LEVEL, }, /* EINT4to7 */
536 { .type = S3C_IRQTYPE_LEVEL, }, /* EINT8to23 */
537 { .type = S3C_IRQTYPE_NONE, }, /* reserved */
538 { .type = S3C_IRQTYPE_EDGE, }, /* nBATT_FLT */
539 { .type = S3C_IRQTYPE_EDGE, }, /* TICK */
540 { .type = S3C_IRQTYPE_EDGE, }, /* WDT */
541 { .type = S3C_IRQTYPE_EDGE, }, /* TIMER0 */
542 { .type = S3C_IRQTYPE_EDGE, }, /* TIMER1 */
543 { .type = S3C_IRQTYPE_EDGE, }, /* TIMER2 */
544 { .type = S3C_IRQTYPE_EDGE, }, /* TIMER3 */
545 { .type = S3C_IRQTYPE_EDGE, }, /* TIMER4 */
546 { .type = S3C_IRQTYPE_LEVEL, }, /* UART2 */
547 { .type = S3C_IRQTYPE_EDGE, }, /* LCD */
548 { .type = S3C_IRQTYPE_EDGE, }, /* DMA0 */
549 { .type = S3C_IRQTYPE_EDGE, }, /* DMA1 */
550 { .type = S3C_IRQTYPE_EDGE, }, /* DMA2 */
551 { .type = S3C_IRQTYPE_EDGE, }, /* DMA3 */
552 { .type = S3C_IRQTYPE_EDGE, }, /* SDI */
553 { .type = S3C_IRQTYPE_EDGE, }, /* SPI0 */
554 { .type = S3C_IRQTYPE_LEVEL, }, /* UART1 */
555 { .type = S3C_IRQTYPE_NONE, }, /* reserved */
556 { .type = S3C_IRQTYPE_EDGE, }, /* USBD */
557 { .type = S3C_IRQTYPE_EDGE, }, /* USBH */
558 { .type = S3C_IRQTYPE_EDGE, }, /* IIC */
559 { .type = S3C_IRQTYPE_LEVEL, }, /* UART0 */
560 { .type = S3C_IRQTYPE_EDGE, }, /* SPI1 */
561 { .type = S3C_IRQTYPE_EDGE, }, /* RTC */
562 { .type = S3C_IRQTYPE_LEVEL, }, /* ADCPARENT */
563};
564
565static struct s3c_irq_data init_eint[32] = {
566 { .type = S3C_IRQTYPE_NONE, }, /* reserved */
567 { .type = S3C_IRQTYPE_NONE, }, /* reserved */
568 { .type = S3C_IRQTYPE_NONE, }, /* reserved */
569 { .type = S3C_IRQTYPE_NONE, }, /* reserved */
570 { .type = S3C_IRQTYPE_EINT, .parent_irq = 4 }, /* EINT4 */
571 { .type = S3C_IRQTYPE_EINT, .parent_irq = 4 }, /* EINT5 */
572 { .type = S3C_IRQTYPE_EINT, .parent_irq = 4 }, /* EINT6 */
573 { .type = S3C_IRQTYPE_EINT, .parent_irq = 4 }, /* EINT7 */
574 { .type = S3C_IRQTYPE_EINT, .parent_irq = 5 }, /* EINT8 */
575 { .type = S3C_IRQTYPE_EINT, .parent_irq = 5 }, /* EINT9 */
576 { .type = S3C_IRQTYPE_EINT, .parent_irq = 5 }, /* EINT10 */
577 { .type = S3C_IRQTYPE_EINT, .parent_irq = 5 }, /* EINT11 */
578 { .type = S3C_IRQTYPE_EINT, .parent_irq = 5 }, /* EINT12 */
579 { .type = S3C_IRQTYPE_EINT, .parent_irq = 5 }, /* EINT13 */
580 { .type = S3C_IRQTYPE_EINT, .parent_irq = 5 }, /* EINT14 */
581 { .type = S3C_IRQTYPE_EINT, .parent_irq = 5 }, /* EINT15 */
582 { .type = S3C_IRQTYPE_EINT, .parent_irq = 5 }, /* EINT16 */
583 { .type = S3C_IRQTYPE_EINT, .parent_irq = 5 }, /* EINT17 */
584 { .type = S3C_IRQTYPE_EINT, .parent_irq = 5 }, /* EINT18 */
585 { .type = S3C_IRQTYPE_EINT, .parent_irq = 5 }, /* EINT19 */
586 { .type = S3C_IRQTYPE_EINT, .parent_irq = 5 }, /* EINT20 */
587 { .type = S3C_IRQTYPE_EINT, .parent_irq = 5 }, /* EINT21 */
588 { .type = S3C_IRQTYPE_EINT, .parent_irq = 5 }, /* EINT22 */
589 { .type = S3C_IRQTYPE_EINT, .parent_irq = 5 }, /* EINT23 */
590};
591
592static struct s3c_irq_data init_subint[32] = {
593 { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 28 }, /* UART0-RX */
594 { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 28 }, /* UART0-TX */
595 { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 28 }, /* UART0-ERR */
596 { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 23 }, /* UART1-RX */
597 { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 23 }, /* UART1-TX */
598 { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 23 }, /* UART1-ERR */
599 { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 15 }, /* UART2-RX */
600 { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 15 }, /* UART2-TX */
601 { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 15 }, /* UART2-ERR */
602 { .type = S3C_IRQTYPE_EDGE, .parent_irq = 31 }, /* TC */
603 { .type = S3C_IRQTYPE_EDGE, .parent_irq = 31 }, /* ADC */
604};
605
Ben Dooksa21765a2007-02-11 18:31:01 +0100606void __init s3c24xx_init_irq(void)
607{
Heiko Stuebner1f629b72013-01-29 10:25:22 -0800608 struct s3c_irq_intc *main_intc;
Ben Dooksa21765a2007-02-11 18:31:01 +0100609
Ben Dooks229fd8f2009-08-03 17:26:57 +0100610#ifdef CONFIG_FIQ
Shawn Guobc896632012-06-28 14:42:08 +0800611 init_FIQ(FIQ_START);
Ben Dooks229fd8f2009-08-03 17:26:57 +0100612#endif
613
Heiko Stuebner1f629b72013-01-29 10:25:22 -0800614 main_intc = s3c24xx_init_intc(NULL, &init_base[0], NULL, 0x4a000000);
615 if (IS_ERR(main_intc)) {
616 pr_err("irq: could not create main interrupt controller\n");
617 return;
Ben Dooksa21765a2007-02-11 18:31:01 +0100618 }
619
Heiko Stuebner1f629b72013-01-29 10:25:22 -0800620 s3c24xx_init_intc(NULL, &init_subint[0], main_intc, 0x4a000018);
621 s3c24xx_init_intc(NULL, &init_eint[0], main_intc, 0x560000a4);
Ben Dooksa21765a2007-02-11 18:31:01 +0100622}
Heiko Stuebneref602eb2013-01-29 10:25:22 -0800623
Heiko Stuebnerd3d5a2c2013-02-12 10:09:13 -0800624#ifdef CONFIG_CPU_S3C2412
Heiko Stuebner42459442013-02-12 10:09:21 -0800625static struct s3c_irq_data init_s3c2412base[32] = {
626 { .type = S3C_IRQTYPE_EINT, }, /* EINT0 */
627 { .type = S3C_IRQTYPE_EINT, }, /* EINT1 */
628 { .type = S3C_IRQTYPE_EINT, }, /* EINT2 */
629 { .type = S3C_IRQTYPE_EINT, }, /* EINT3 */
630 { .type = S3C_IRQTYPE_LEVEL, }, /* EINT4to7 */
631 { .type = S3C_IRQTYPE_LEVEL, }, /* EINT8to23 */
632 { .type = S3C_IRQTYPE_NONE, }, /* reserved */
633 { .type = S3C_IRQTYPE_EDGE, }, /* nBATT_FLT */
634 { .type = S3C_IRQTYPE_EDGE, }, /* TICK */
635 { .type = S3C_IRQTYPE_EDGE, }, /* WDT */
636 { .type = S3C_IRQTYPE_EDGE, }, /* TIMER0 */
637 { .type = S3C_IRQTYPE_EDGE, }, /* TIMER1 */
638 { .type = S3C_IRQTYPE_EDGE, }, /* TIMER2 */
639 { .type = S3C_IRQTYPE_EDGE, }, /* TIMER3 */
640 { .type = S3C_IRQTYPE_EDGE, }, /* TIMER4 */
641 { .type = S3C_IRQTYPE_LEVEL, }, /* UART2 */
642 { .type = S3C_IRQTYPE_EDGE, }, /* LCD */
643 { .type = S3C_IRQTYPE_EDGE, }, /* DMA0 */
644 { .type = S3C_IRQTYPE_EDGE, }, /* DMA1 */
645 { .type = S3C_IRQTYPE_EDGE, }, /* DMA2 */
646 { .type = S3C_IRQTYPE_EDGE, }, /* DMA3 */
647 { .type = S3C_IRQTYPE_LEVEL, }, /* SDI/CF */
648 { .type = S3C_IRQTYPE_EDGE, }, /* SPI0 */
649 { .type = S3C_IRQTYPE_LEVEL, }, /* UART1 */
650 { .type = S3C_IRQTYPE_NONE, }, /* reserved */
651 { .type = S3C_IRQTYPE_EDGE, }, /* USBD */
652 { .type = S3C_IRQTYPE_EDGE, }, /* USBH */
653 { .type = S3C_IRQTYPE_EDGE, }, /* IIC */
654 { .type = S3C_IRQTYPE_LEVEL, }, /* UART0 */
655 { .type = S3C_IRQTYPE_EDGE, }, /* SPI1 */
656 { .type = S3C_IRQTYPE_EDGE, }, /* RTC */
657 { .type = S3C_IRQTYPE_LEVEL, }, /* ADCPARENT */
658};
Heiko Stuebnerd3d5a2c2013-02-12 10:09:13 -0800659
Heiko Stuebner42459442013-02-12 10:09:21 -0800660static struct s3c_irq_data init_s3c2412subint[32] = {
661 { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 28 }, /* UART0-RX */
662 { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 28 }, /* UART0-TX */
663 { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 28 }, /* UART0-ERR */
664 { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 23 }, /* UART1-RX */
665 { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 23 }, /* UART1-TX */
666 { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 23 }, /* UART1-ERR */
667 { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 15 }, /* UART2-RX */
668 { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 15 }, /* UART2-TX */
669 { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 15 }, /* UART2-ERR */
670 { .type = S3C_IRQTYPE_EDGE, .parent_irq = 31 }, /* TC */
671 { .type = S3C_IRQTYPE_EDGE, .parent_irq = 31 }, /* ADC */
672 { .type = S3C_IRQTYPE_NONE, },
673 { .type = S3C_IRQTYPE_NONE, },
674 { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 21 }, /* SDI */
675 { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 21 }, /* CF */
676};
Heiko Stuebnerd3d5a2c2013-02-12 10:09:13 -0800677
678/* the s3c2412 changes the behaviour of IRQ_EINT0 through IRQ_EINT3 by
679 * having them turn up in both the INT* and the EINT* registers. Whilst
680 * both show the status, they both now need to be acked when the IRQs
681 * go off.
682*/
683
684static void
685s3c2412_irq_mask(struct irq_data *data)
686{
687 unsigned long bitval = 1UL << (data->irq - IRQ_EINT0);
688 unsigned long mask;
689
690 mask = __raw_readl(S3C2410_INTMSK);
691 __raw_writel(mask | bitval, S3C2410_INTMSK);
692
693 mask = __raw_readl(S3C2412_EINTMASK);
694 __raw_writel(mask | bitval, S3C2412_EINTMASK);
695}
696
697static inline void
698s3c2412_irq_ack(struct irq_data *data)
699{
700 unsigned long bitval = 1UL << (data->irq - IRQ_EINT0);
701
702 __raw_writel(bitval, S3C2412_EINTPEND);
703 __raw_writel(bitval, S3C2410_SRCPND);
704 __raw_writel(bitval, S3C2410_INTPND);
705}
706
707static inline void
708s3c2412_irq_maskack(struct irq_data *data)
709{
710 unsigned long bitval = 1UL << (data->irq - IRQ_EINT0);
711 unsigned long mask;
712
713 mask = __raw_readl(S3C2410_INTMSK);
714 __raw_writel(mask|bitval, S3C2410_INTMSK);
715
716 mask = __raw_readl(S3C2412_EINTMASK);
717 __raw_writel(mask | bitval, S3C2412_EINTMASK);
718
719 __raw_writel(bitval, S3C2412_EINTPEND);
720 __raw_writel(bitval, S3C2410_SRCPND);
721 __raw_writel(bitval, S3C2410_INTPND);
722}
723
724static void
725s3c2412_irq_unmask(struct irq_data *data)
726{
727 unsigned long bitval = 1UL << (data->irq - IRQ_EINT0);
728 unsigned long mask;
729
730 mask = __raw_readl(S3C2412_EINTMASK);
731 __raw_writel(mask & ~bitval, S3C2412_EINTMASK);
732
733 mask = __raw_readl(S3C2410_INTMSK);
734 __raw_writel(mask & ~bitval, S3C2410_INTMSK);
735}
736
737static struct irq_chip s3c2412_irq_eint0t4 = {
738 .irq_ack = s3c2412_irq_ack,
739 .irq_mask = s3c2412_irq_mask,
740 .irq_unmask = s3c2412_irq_unmask,
741 .irq_set_wake = s3c_irq_wake,
742 .irq_set_type = s3c_irqext_type,
743};
744
Heiko Stuebner0da09932013-02-12 10:09:18 -0800745void s3c2412_init_irq(void)
Heiko Stuebnerd3d5a2c2013-02-12 10:09:13 -0800746{
Heiko Stuebner42459442013-02-12 10:09:21 -0800747 struct s3c_irq_intc *main_intc;
Heiko Stuebnerd3d5a2c2013-02-12 10:09:13 -0800748 unsigned int irqno;
749
Heiko Stuebner42459442013-02-12 10:09:21 -0800750 pr_info("S3C2412: IRQ Support\n");
751
752#ifdef CONFIG_FIQ
753 init_FIQ(FIQ_START);
754#endif
755
756 main_intc = s3c24xx_init_intc(NULL, &init_s3c2412base[0], NULL, 0x4a000000);
757 if (IS_ERR(main_intc)) {
758 pr_err("irq: could not create main interrupt controller\n");
759 return;
760 }
761
762 s3c24xx_init_intc(NULL, &init_eint[0], main_intc, 0x560000a4);
763 s3c24xx_init_intc(NULL, &init_s3c2412subint[0], main_intc, 0x4a000018);
764
765 /* special handling for eints 0 to 3 */
Heiko Stuebner0da09932013-02-12 10:09:18 -0800766
Heiko Stuebnerd3d5a2c2013-02-12 10:09:13 -0800767 for (irqno = IRQ_EINT0; irqno <= IRQ_EINT3; irqno++) {
768 irq_set_chip_and_handler(irqno, &s3c2412_irq_eint0t4,
769 handle_edge_irq);
770 set_irq_flags(irqno, IRQF_VALID);
771 }
Heiko Stuebnerd3d5a2c2013-02-12 10:09:13 -0800772}
Heiko Stuebnerd3d5a2c2013-02-12 10:09:13 -0800773#endif
774
Heiko Stuebneref602eb2013-01-29 10:25:22 -0800775#ifdef CONFIG_CPU_S3C2416
Heiko Stuebner20f6c782013-01-29 10:25:22 -0800776static struct s3c_irq_data init_s3c2416base[32] = {
777 { .type = S3C_IRQTYPE_EINT, }, /* EINT0 */
778 { .type = S3C_IRQTYPE_EINT, }, /* EINT1 */
779 { .type = S3C_IRQTYPE_EINT, }, /* EINT2 */
780 { .type = S3C_IRQTYPE_EINT, }, /* EINT3 */
781 { .type = S3C_IRQTYPE_LEVEL, }, /* EINT4to7 */
782 { .type = S3C_IRQTYPE_LEVEL, }, /* EINT8to23 */
783 { .type = S3C_IRQTYPE_NONE, }, /* reserved */
784 { .type = S3C_IRQTYPE_EDGE, }, /* nBATT_FLT */
785 { .type = S3C_IRQTYPE_EDGE, }, /* TICK */
786 { .type = S3C_IRQTYPE_LEVEL, }, /* WDT/AC97 */
787 { .type = S3C_IRQTYPE_EDGE, }, /* TIMER0 */
788 { .type = S3C_IRQTYPE_EDGE, }, /* TIMER1 */
789 { .type = S3C_IRQTYPE_EDGE, }, /* TIMER2 */
790 { .type = S3C_IRQTYPE_EDGE, }, /* TIMER3 */
791 { .type = S3C_IRQTYPE_EDGE, }, /* TIMER4 */
792 { .type = S3C_IRQTYPE_LEVEL, }, /* UART2 */
793 { .type = S3C_IRQTYPE_LEVEL, }, /* LCD */
794 { .type = S3C_IRQTYPE_LEVEL, }, /* DMA */
795 { .type = S3C_IRQTYPE_LEVEL, }, /* UART3 */
796 { .type = S3C_IRQTYPE_NONE, }, /* reserved */
797 { .type = S3C_IRQTYPE_EDGE, }, /* SDI1 */
798 { .type = S3C_IRQTYPE_EDGE, }, /* SDI0 */
799 { .type = S3C_IRQTYPE_EDGE, }, /* SPI0 */
800 { .type = S3C_IRQTYPE_LEVEL, }, /* UART1 */
801 { .type = S3C_IRQTYPE_EDGE, }, /* NAND */
802 { .type = S3C_IRQTYPE_EDGE, }, /* USBD */
803 { .type = S3C_IRQTYPE_EDGE, }, /* USBH */
804 { .type = S3C_IRQTYPE_EDGE, }, /* IIC */
805 { .type = S3C_IRQTYPE_LEVEL, }, /* UART0 */
806 { .type = S3C_IRQTYPE_NONE, },
807 { .type = S3C_IRQTYPE_EDGE, }, /* RTC */
808 { .type = S3C_IRQTYPE_LEVEL, }, /* ADCPARENT */
Heiko Stuebneref602eb2013-01-29 10:25:22 -0800809};
810
Heiko Stuebner20f6c782013-01-29 10:25:22 -0800811static struct s3c_irq_data init_s3c2416subint[32] = {
812 { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 28 }, /* UART0-RX */
813 { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 28 }, /* UART0-TX */
814 { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 28 }, /* UART0-ERR */
815 { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 23 }, /* UART1-RX */
816 { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 23 }, /* UART1-TX */
817 { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 23 }, /* UART1-ERR */
818 { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 15 }, /* UART2-RX */
819 { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 15 }, /* UART2-TX */
820 { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 15 }, /* UART2-ERR */
821 { .type = S3C_IRQTYPE_EDGE, .parent_irq = 31 }, /* TC */
822 { .type = S3C_IRQTYPE_EDGE, .parent_irq = 31 }, /* ADC */
823 { .type = S3C_IRQTYPE_NONE }, /* reserved */
824 { .type = S3C_IRQTYPE_NONE }, /* reserved */
825 { .type = S3C_IRQTYPE_NONE }, /* reserved */
826 { .type = S3C_IRQTYPE_NONE }, /* reserved */
827 { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 16 }, /* LCD2 */
828 { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 16 }, /* LCD3 */
829 { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 16 }, /* LCD4 */
830 { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 17 }, /* DMA0 */
831 { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 17 }, /* DMA1 */
832 { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 17 }, /* DMA2 */
833 { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 17 }, /* DMA3 */
834 { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 17 }, /* DMA4 */
835 { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 17 }, /* DMA5 */
836 { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 18 }, /* UART3-RX */
837 { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 18 }, /* UART3-TX */
838 { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 18 }, /* UART3-ERR */
839 { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 9 }, /* WDT */
840 { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 9 }, /* AC97 */
Heiko Stuebneref602eb2013-01-29 10:25:22 -0800841};
842
Heiko Stuebner20f6c782013-01-29 10:25:22 -0800843static struct s3c_irq_data init_s3c2416_second[32] = {
844 { .type = S3C_IRQTYPE_EDGE }, /* 2D */
845 { .type = S3C_IRQTYPE_EDGE }, /* IIC1 */
846 { .type = S3C_IRQTYPE_NONE }, /* reserved */
847 { .type = S3C_IRQTYPE_NONE }, /* reserved */
848 { .type = S3C_IRQTYPE_EDGE }, /* PCM0 */
849 { .type = S3C_IRQTYPE_EDGE }, /* PCM1 */
850 { .type = S3C_IRQTYPE_EDGE }, /* I2S0 */
851 { .type = S3C_IRQTYPE_EDGE }, /* I2S1 */
Heiko Stuebneref602eb2013-01-29 10:25:22 -0800852};
853
Heiko Stuebner4a282dd2013-01-29 10:25:22 -0800854void __init s3c2416_init_irq(void)
Heiko Stuebneref602eb2013-01-29 10:25:22 -0800855{
Heiko Stuebner20f6c782013-01-29 10:25:22 -0800856 struct s3c_irq_intc *main_intc;
857
Heiko Stuebner4a282dd2013-01-29 10:25:22 -0800858 pr_info("S3C2416: IRQ Support\n");
859
Heiko Stuebner20f6c782013-01-29 10:25:22 -0800860#ifdef CONFIG_FIQ
861 init_FIQ(FIQ_START);
862#endif
Heiko Stuebneref602eb2013-01-29 10:25:22 -0800863
Heiko Stuebner20f6c782013-01-29 10:25:22 -0800864 main_intc = s3c24xx_init_intc(NULL, &init_s3c2416base[0], NULL, 0x4a000000);
865 if (IS_ERR(main_intc)) {
866 pr_err("irq: could not create main interrupt controller\n");
867 return;
868 }
Heiko Stuebneref602eb2013-01-29 10:25:22 -0800869
Heiko Stuebner20f6c782013-01-29 10:25:22 -0800870 s3c24xx_init_intc(NULL, &init_eint[0], main_intc, 0x560000a4);
871 s3c24xx_init_intc(NULL, &init_s3c2416subint[0], main_intc, 0x4a000018);
Heiko Stuebneref602eb2013-01-29 10:25:22 -0800872
Heiko Stuebner20f6c782013-01-29 10:25:22 -0800873 s3c24xx_init_intc(NULL, &init_s3c2416_second[0], NULL, 0x4a000040);
Heiko Stuebneref602eb2013-01-29 10:25:22 -0800874}
875
Heiko Stuebneref602eb2013-01-29 10:25:22 -0800876#endif
Heiko Stuebner6b628912013-01-29 10:25:22 -0800877
Heiko Stuebnerf0301672013-02-12 09:59:35 -0800878#ifdef CONFIG_CPU_S3C2440
879static struct s3c_irq_data init_s3c2440base[32] = {
880 { .type = S3C_IRQTYPE_EINT, }, /* EINT0 */
881 { .type = S3C_IRQTYPE_EINT, }, /* EINT1 */
882 { .type = S3C_IRQTYPE_EINT, }, /* EINT2 */
883 { .type = S3C_IRQTYPE_EINT, }, /* EINT3 */
884 { .type = S3C_IRQTYPE_LEVEL, }, /* EINT4to7 */
885 { .type = S3C_IRQTYPE_LEVEL, }, /* EINT8to23 */
886 { .type = S3C_IRQTYPE_LEVEL, }, /* CAM */
887 { .type = S3C_IRQTYPE_EDGE, }, /* nBATT_FLT */
888 { .type = S3C_IRQTYPE_EDGE, }, /* TICK */
889 { .type = S3C_IRQTYPE_LEVEL, }, /* WDT/AC97 */
890 { .type = S3C_IRQTYPE_EDGE, }, /* TIMER0 */
891 { .type = S3C_IRQTYPE_EDGE, }, /* TIMER1 */
892 { .type = S3C_IRQTYPE_EDGE, }, /* TIMER2 */
893 { .type = S3C_IRQTYPE_EDGE, }, /* TIMER3 */
894 { .type = S3C_IRQTYPE_EDGE, }, /* TIMER4 */
895 { .type = S3C_IRQTYPE_LEVEL, }, /* UART2 */
896 { .type = S3C_IRQTYPE_EDGE, }, /* LCD */
897 { .type = S3C_IRQTYPE_EDGE, }, /* DMA0 */
898 { .type = S3C_IRQTYPE_EDGE, }, /* DMA1 */
899 { .type = S3C_IRQTYPE_EDGE, }, /* DMA2 */
900 { .type = S3C_IRQTYPE_EDGE, }, /* DMA3 */
901 { .type = S3C_IRQTYPE_EDGE, }, /* SDI */
902 { .type = S3C_IRQTYPE_EDGE, }, /* SPI0 */
903 { .type = S3C_IRQTYPE_LEVEL, }, /* UART1 */
904 { .type = S3C_IRQTYPE_LEVEL, }, /* NFCON */
905 { .type = S3C_IRQTYPE_EDGE, }, /* USBD */
906 { .type = S3C_IRQTYPE_EDGE, }, /* USBH */
907 { .type = S3C_IRQTYPE_EDGE, }, /* IIC */
908 { .type = S3C_IRQTYPE_LEVEL, }, /* UART0 */
909 { .type = S3C_IRQTYPE_EDGE, }, /* SPI1 */
910 { .type = S3C_IRQTYPE_EDGE, }, /* RTC */
911 { .type = S3C_IRQTYPE_LEVEL, }, /* ADCPARENT */
Heiko Stuebner6f8d7ea2013-02-12 09:59:17 -0800912};
913
Heiko Stuebnerf0301672013-02-12 09:59:35 -0800914static struct s3c_irq_data init_s3c2440subint[32] = {
915 { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 28 }, /* UART0-RX */
916 { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 28 }, /* UART0-TX */
917 { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 28 }, /* UART0-ERR */
918 { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 23 }, /* UART1-RX */
919 { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 23 }, /* UART1-TX */
920 { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 23 }, /* UART1-ERR */
921 { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 15 }, /* UART2-RX */
922 { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 15 }, /* UART2-TX */
923 { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 15 }, /* UART2-ERR */
924 { .type = S3C_IRQTYPE_EDGE, .parent_irq = 31 }, /* TC */
925 { .type = S3C_IRQTYPE_EDGE, .parent_irq = 31 }, /* ADC */
926 { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 6 }, /* TC */
927 { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 6 }, /* ADC */
928 { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 9 }, /* WDT */
929 { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 9 }, /* AC97 */
Heiko Stuebner2286cf42013-02-12 09:59:24 -0800930};
931
Heiko Stuebner7cefed52013-02-12 09:59:27 -0800932void __init s3c2440_init_irq(void)
Heiko Stuebner2286cf42013-02-12 09:59:24 -0800933{
Heiko Stuebnerf0301672013-02-12 09:59:35 -0800934 struct s3c_irq_intc *main_intc;
Heiko Stuebner2286cf42013-02-12 09:59:24 -0800935
Heiko Stuebnerf0301672013-02-12 09:59:35 -0800936 pr_info("S3C2440: IRQ Support\n");
Heiko Stuebner2286cf42013-02-12 09:59:24 -0800937
Heiko Stuebnerf0301672013-02-12 09:59:35 -0800938#ifdef CONFIG_FIQ
939 init_FIQ(FIQ_START);
940#endif
Heiko Stuebnerce6c1642013-02-12 09:59:20 -0800941
Heiko Stuebnerf0301672013-02-12 09:59:35 -0800942 main_intc = s3c24xx_init_intc(NULL, &init_s3c2440base[0], NULL, 0x4a000000);
943 if (IS_ERR(main_intc)) {
944 pr_err("irq: could not create main interrupt controller\n");
945 return;
Heiko Stuebner6f8d7ea2013-02-12 09:59:17 -0800946 }
Heiko Stuebner7cefed52013-02-12 09:59:27 -0800947
Heiko Stuebnerf0301672013-02-12 09:59:35 -0800948 s3c24xx_init_intc(NULL, &init_eint[0], main_intc, 0x560000a4);
949 s3c24xx_init_intc(NULL, &init_s3c2440subint[0], main_intc, 0x4a000018);
Heiko Stuebner6f8d7ea2013-02-12 09:59:17 -0800950}
Heiko Stuebnerce6c1642013-02-12 09:59:20 -0800951#endif
Heiko Stuebner6f8d7ea2013-02-12 09:59:17 -0800952
Heiko Stuebnerce6c1642013-02-12 09:59:20 -0800953#ifdef CONFIG_CPU_S3C2442
Heiko Stuebner70644ad2013-02-12 09:59:31 -0800954static struct s3c_irq_data init_s3c2442base[32] = {
955 { .type = S3C_IRQTYPE_EINT, }, /* EINT0 */
956 { .type = S3C_IRQTYPE_EINT, }, /* EINT1 */
957 { .type = S3C_IRQTYPE_EINT, }, /* EINT2 */
958 { .type = S3C_IRQTYPE_EINT, }, /* EINT3 */
959 { .type = S3C_IRQTYPE_LEVEL, }, /* EINT4to7 */
960 { .type = S3C_IRQTYPE_LEVEL, }, /* EINT8to23 */
961 { .type = S3C_IRQTYPE_LEVEL, }, /* CAM */
962 { .type = S3C_IRQTYPE_EDGE, }, /* nBATT_FLT */
963 { .type = S3C_IRQTYPE_EDGE, }, /* TICK */
964 { .type = S3C_IRQTYPE_EDGE, }, /* WDT */
965 { .type = S3C_IRQTYPE_EDGE, }, /* TIMER0 */
966 { .type = S3C_IRQTYPE_EDGE, }, /* TIMER1 */
967 { .type = S3C_IRQTYPE_EDGE, }, /* TIMER2 */
968 { .type = S3C_IRQTYPE_EDGE, }, /* TIMER3 */
969 { .type = S3C_IRQTYPE_EDGE, }, /* TIMER4 */
970 { .type = S3C_IRQTYPE_LEVEL, }, /* UART2 */
971 { .type = S3C_IRQTYPE_EDGE, }, /* LCD */
972 { .type = S3C_IRQTYPE_EDGE, }, /* DMA0 */
973 { .type = S3C_IRQTYPE_EDGE, }, /* DMA1 */
974 { .type = S3C_IRQTYPE_EDGE, }, /* DMA2 */
975 { .type = S3C_IRQTYPE_EDGE, }, /* DMA3 */
976 { .type = S3C_IRQTYPE_EDGE, }, /* SDI */
977 { .type = S3C_IRQTYPE_EDGE, }, /* SPI0 */
978 { .type = S3C_IRQTYPE_LEVEL, }, /* UART1 */
979 { .type = S3C_IRQTYPE_LEVEL, }, /* NFCON */
980 { .type = S3C_IRQTYPE_EDGE, }, /* USBD */
981 { .type = S3C_IRQTYPE_EDGE, }, /* USBH */
982 { .type = S3C_IRQTYPE_EDGE, }, /* IIC */
983 { .type = S3C_IRQTYPE_LEVEL, }, /* UART0 */
984 { .type = S3C_IRQTYPE_EDGE, }, /* SPI1 */
985 { .type = S3C_IRQTYPE_EDGE, }, /* RTC */
986 { .type = S3C_IRQTYPE_LEVEL, }, /* ADCPARENT */
987};
988
989static struct s3c_irq_data init_s3c2442subint[32] = {
990 { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 28 }, /* UART0-RX */
991 { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 28 }, /* UART0-TX */
992 { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 28 }, /* UART0-ERR */
993 { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 23 }, /* UART1-RX */
994 { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 23 }, /* UART1-TX */
995 { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 23 }, /* UART1-ERR */
996 { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 15 }, /* UART2-RX */
997 { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 15 }, /* UART2-TX */
998 { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 15 }, /* UART2-ERR */
999 { .type = S3C_IRQTYPE_EDGE, .parent_irq = 31 }, /* TC */
1000 { .type = S3C_IRQTYPE_EDGE, .parent_irq = 31 }, /* ADC */
1001 { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 6 }, /* TC */
1002 { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 6 }, /* ADC */
1003};
1004
Heiko Stuebnerce6c1642013-02-12 09:59:20 -08001005void __init s3c2442_init_irq(void)
Heiko Stuebner6f8d7ea2013-02-12 09:59:17 -08001006{
Heiko Stuebner70644ad2013-02-12 09:59:31 -08001007 struct s3c_irq_intc *main_intc;
Heiko Stuebnerce6c1642013-02-12 09:59:20 -08001008
Heiko Stuebner70644ad2013-02-12 09:59:31 -08001009 pr_info("S3C2442: IRQ Support\n");
Heiko Stuebnerce6c1642013-02-12 09:59:20 -08001010
Heiko Stuebner70644ad2013-02-12 09:59:31 -08001011#ifdef CONFIG_FIQ
1012 init_FIQ(FIQ_START);
1013#endif
Heiko Stuebnerce6c1642013-02-12 09:59:20 -08001014
Heiko Stuebner70644ad2013-02-12 09:59:31 -08001015 main_intc = s3c24xx_init_intc(NULL, &init_s3c2442base[0], NULL, 0x4a000000);
1016 if (IS_ERR(main_intc)) {
1017 pr_err("irq: could not create main interrupt controller\n");
1018 return;
Heiko Stuebnerce6c1642013-02-12 09:59:20 -08001019 }
Heiko Stuebner70644ad2013-02-12 09:59:31 -08001020
1021 s3c24xx_init_intc(NULL, &init_eint[0], main_intc, 0x560000a4);
1022 s3c24xx_init_intc(NULL, &init_s3c2442subint[0], main_intc, 0x4a000018);
Heiko Stuebner6f8d7ea2013-02-12 09:59:17 -08001023}
Heiko Stuebnerce6c1642013-02-12 09:59:20 -08001024#endif
Heiko Stuebner6f8d7ea2013-02-12 09:59:17 -08001025
Heiko Stuebner6b628912013-01-29 10:25:22 -08001026#ifdef CONFIG_CPU_S3C2443
Heiko Stuebnerf44ddba2013-01-29 10:25:23 -08001027static struct s3c_irq_data init_s3c2443base[32] = {
1028 { .type = S3C_IRQTYPE_EINT, }, /* EINT0 */
1029 { .type = S3C_IRQTYPE_EINT, }, /* EINT1 */
1030 { .type = S3C_IRQTYPE_EINT, }, /* EINT2 */
1031 { .type = S3C_IRQTYPE_EINT, }, /* EINT3 */
1032 { .type = S3C_IRQTYPE_LEVEL, }, /* EINT4to7 */
1033 { .type = S3C_IRQTYPE_LEVEL, }, /* EINT8to23 */
1034 { .type = S3C_IRQTYPE_LEVEL, }, /* CAM */
1035 { .type = S3C_IRQTYPE_EDGE, }, /* nBATT_FLT */
1036 { .type = S3C_IRQTYPE_EDGE, }, /* TICK */
1037 { .type = S3C_IRQTYPE_LEVEL, }, /* WDT/AC97 */
1038 { .type = S3C_IRQTYPE_EDGE, }, /* TIMER0 */
1039 { .type = S3C_IRQTYPE_EDGE, }, /* TIMER1 */
1040 { .type = S3C_IRQTYPE_EDGE, }, /* TIMER2 */
1041 { .type = S3C_IRQTYPE_EDGE, }, /* TIMER3 */
1042 { .type = S3C_IRQTYPE_EDGE, }, /* TIMER4 */
1043 { .type = S3C_IRQTYPE_LEVEL, }, /* UART2 */
1044 { .type = S3C_IRQTYPE_LEVEL, }, /* LCD */
1045 { .type = S3C_IRQTYPE_LEVEL, }, /* DMA */
1046 { .type = S3C_IRQTYPE_LEVEL, }, /* UART3 */
1047 { .type = S3C_IRQTYPE_EDGE, }, /* CFON */
1048 { .type = S3C_IRQTYPE_EDGE, }, /* SDI1 */
1049 { .type = S3C_IRQTYPE_EDGE, }, /* SDI0 */
1050 { .type = S3C_IRQTYPE_EDGE, }, /* SPI0 */
1051 { .type = S3C_IRQTYPE_LEVEL, }, /* UART1 */
1052 { .type = S3C_IRQTYPE_EDGE, }, /* NAND */
1053 { .type = S3C_IRQTYPE_EDGE, }, /* USBD */
1054 { .type = S3C_IRQTYPE_EDGE, }, /* USBH */
1055 { .type = S3C_IRQTYPE_EDGE, }, /* IIC */
1056 { .type = S3C_IRQTYPE_LEVEL, }, /* UART0 */
1057 { .type = S3C_IRQTYPE_EDGE, }, /* SPI1 */
1058 { .type = S3C_IRQTYPE_EDGE, }, /* RTC */
1059 { .type = S3C_IRQTYPE_LEVEL, }, /* ADCPARENT */
Heiko Stuebner6b628912013-01-29 10:25:22 -08001060};
1061
Heiko Stuebner6b628912013-01-29 10:25:22 -08001062
Heiko Stuebnerf44ddba2013-01-29 10:25:23 -08001063static struct s3c_irq_data init_s3c2443subint[32] = {
1064 { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 28 }, /* UART0-RX */
1065 { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 28 }, /* UART0-TX */
1066 { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 28 }, /* UART0-ERR */
1067 { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 23 }, /* UART1-RX */
1068 { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 23 }, /* UART1-TX */
1069 { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 23 }, /* UART1-ERR */
1070 { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 15 }, /* UART2-RX */
1071 { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 15 }, /* UART2-TX */
1072 { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 15 }, /* UART2-ERR */
1073 { .type = S3C_IRQTYPE_EDGE, .parent_irq = 31 }, /* TC */
1074 { .type = S3C_IRQTYPE_EDGE, .parent_irq = 31 }, /* ADC */
1075 { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 6 }, /* CAM_C */
1076 { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 6 }, /* CAM_P */
1077 { .type = S3C_IRQTYPE_NONE }, /* reserved */
1078 { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 16 }, /* LCD1 */
1079 { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 16 }, /* LCD2 */
1080 { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 16 }, /* LCD3 */
1081 { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 16 }, /* LCD4 */
1082 { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 17 }, /* DMA0 */
1083 { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 17 }, /* DMA1 */
1084 { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 17 }, /* DMA2 */
1085 { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 17 }, /* DMA3 */
1086 { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 17 }, /* DMA4 */
1087 { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 17 }, /* DMA5 */
1088 { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 18 }, /* UART3-RX */
1089 { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 18 }, /* UART3-TX */
1090 { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 18 }, /* UART3-ERR */
1091 { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 9 }, /* WDT */
1092 { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 9 }, /* AC97 */
Heiko Stuebner6b628912013-01-29 10:25:22 -08001093};
1094
Heiko Stuebnerb499b7a2013-01-29 10:25:23 -08001095void __init s3c2443_init_irq(void)
Heiko Stuebner6b628912013-01-29 10:25:22 -08001096{
Heiko Stuebnerf44ddba2013-01-29 10:25:23 -08001097 struct s3c_irq_intc *main_intc;
1098
Heiko Stuebnerb499b7a2013-01-29 10:25:23 -08001099 pr_info("S3C2443: IRQ Support\n");
1100
Heiko Stuebnerf44ddba2013-01-29 10:25:23 -08001101#ifdef CONFIG_FIQ
1102 init_FIQ(FIQ_START);
1103#endif
Heiko Stuebner6b628912013-01-29 10:25:22 -08001104
Heiko Stuebnerf44ddba2013-01-29 10:25:23 -08001105 main_intc = s3c24xx_init_intc(NULL, &init_s3c2443base[0], NULL, 0x4a000000);
1106 if (IS_ERR(main_intc)) {
1107 pr_err("irq: could not create main interrupt controller\n");
1108 return;
1109 }
Heiko Stuebner6b628912013-01-29 10:25:22 -08001110
Heiko Stuebnerf44ddba2013-01-29 10:25:23 -08001111 s3c24xx_init_intc(NULL, &init_eint[0], main_intc, 0x560000a4);
1112 s3c24xx_init_intc(NULL, &init_s3c2443subint[0], main_intc, 0x4a000018);
Heiko Stuebner6b628912013-01-29 10:25:22 -08001113}
Heiko Stuebner6b628912013-01-29 10:25:22 -08001114#endif