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