1/* linux/arch/arm/plat-s3c24xx/irq.c 2 * 3 * Copyright (c) 2003-2004 Simtec Electronics 4 * Ben Dooks <ben@simtec.co.uk> 5 * 6 * This program is free software; you can redistribute it and/or modify 7 * it under the terms of the GNU General Public License as published by 8 * the Free Software Foundation; either version 2 of the License, or 9 * (at your option) any later version. 10 * 11 * This program is distributed in the hope that it will be useful, 12 * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 * GNU General Public License for more details. 15 * 16 * You should have received a copy of the GNU General Public License 17 * along with this program; if not, write to the Free Software 18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 19*/ 20 21#include <linux/init.h> 22#include <linux/module.h> 23#include <linux/interrupt.h> 24#include <linux/ioport.h> 25#include <linux/sysdev.h> 26 27#include <asm/irq.h> 28#include <asm/mach/irq.h> 29 30#include <plat/regs-irqtype.h> 31 32#include <plat/cpu.h> 33#include <plat/pm.h> 34#include <plat/irq.h> 35 36static void 37s3c_irq_mask(unsigned int irqno) 38{ 39 unsigned long mask; 40 41 irqno -= IRQ_EINT0; 42 43 mask = __raw_readl(S3C2410_INTMSK); 44 mask |= 1UL << irqno; 45 __raw_writel(mask, S3C2410_INTMSK); 46} 47 48static inline void 49s3c_irq_ack(unsigned int irqno) 50{ 51 unsigned long bitval = 1UL << (irqno - IRQ_EINT0); 52 53 __raw_writel(bitval, S3C2410_SRCPND); 54 __raw_writel(bitval, S3C2410_INTPND); 55} 56 57static inline void 58s3c_irq_maskack(unsigned int irqno) 59{ 60 unsigned long bitval = 1UL << (irqno - IRQ_EINT0); 61 unsigned long mask; 62 63 mask = __raw_readl(S3C2410_INTMSK); 64 __raw_writel(mask|bitval, S3C2410_INTMSK); 65 66 __raw_writel(bitval, S3C2410_SRCPND); 67 __raw_writel(bitval, S3C2410_INTPND); 68} 69 70 71static void 72s3c_irq_unmask(unsigned int irqno) 73{ 74 unsigned long mask; 75 76 if (irqno != IRQ_TIMER4 && irqno != IRQ_EINT8t23) 77 irqdbf2("s3c_irq_unmask %d\n", irqno); 78 79 irqno -= IRQ_EINT0; 80 81 mask = __raw_readl(S3C2410_INTMSK); 82 mask &= ~(1UL << irqno); 83 __raw_writel(mask, S3C2410_INTMSK); 84} 85 86struct irq_chip s3c_irq_level_chip = { 87 .name = "s3c-level", 88 .ack = s3c_irq_maskack, 89 .mask = s3c_irq_mask, 90 .unmask = s3c_irq_unmask, 91 .set_wake = s3c_irq_wake 92}; 93 94struct irq_chip s3c_irq_chip = { 95 .name = "s3c", 96 .ack = s3c_irq_ack, 97 .mask = s3c_irq_mask, 98 .unmask = s3c_irq_unmask, 99 .set_wake = s3c_irq_wake 100}; 101 102static void 103s3c_irqext_mask(unsigned int irqno) 104{ 105 unsigned long mask; 106 107 irqno -= EXTINT_OFF; 108 109 mask = __raw_readl(S3C24XX_EINTMASK); 110 mask |= ( 1UL << irqno); 111 __raw_writel(mask, S3C24XX_EINTMASK); 112} 113 114static void 115s3c_irqext_ack(unsigned int irqno) 116{ 117 unsigned long req; 118 unsigned long bit; 119 unsigned long mask; 120 121 bit = 1UL << (irqno - EXTINT_OFF); 122 123 mask = __raw_readl(S3C24XX_EINTMASK); 124 125 __raw_writel(bit, S3C24XX_EINTPEND); 126 127 req = __raw_readl(S3C24XX_EINTPEND); 128 req &= ~mask; 129 130 /* not sure if we should be acking the parent irq... */ 131 132 if (irqno <= IRQ_EINT7 ) { 133 if ((req & 0xf0) == 0) 134 s3c_irq_ack(IRQ_EINT4t7); 135 } else { 136 if ((req >> 8) == 0) 137 s3c_irq_ack(IRQ_EINT8t23); 138 } 139} 140 141static void 142s3c_irqext_unmask(unsigned int irqno) 143{ 144 unsigned long mask; 145 146 irqno -= EXTINT_OFF; 147 148 mask = __raw_readl(S3C24XX_EINTMASK); 149 mask &= ~( 1UL << irqno); 150 __raw_writel(mask, S3C24XX_EINTMASK); 151} 152 153int 154s3c_irqext_type(unsigned int irq, unsigned int type) 155{ 156 void __iomem *extint_reg; 157 void __iomem *gpcon_reg; 158 unsigned long gpcon_offset, extint_offset; 159 unsigned long newvalue = 0, value; 160 161 if ((irq >= IRQ_EINT0) && (irq <= IRQ_EINT3)) 162 { 163 gpcon_reg = S3C2410_GPFCON; 164 extint_reg = S3C24XX_EXTINT0; 165 gpcon_offset = (irq - IRQ_EINT0) * 2; 166 extint_offset = (irq - IRQ_EINT0) * 4; 167 } 168 else if ((irq >= IRQ_EINT4) && (irq <= IRQ_EINT7)) 169 { 170 gpcon_reg = S3C2410_GPFCON; 171 extint_reg = S3C24XX_EXTINT0; 172 gpcon_offset = (irq - (EXTINT_OFF)) * 2; 173 extint_offset = (irq - (EXTINT_OFF)) * 4; 174 } 175 else if ((irq >= IRQ_EINT8) && (irq <= IRQ_EINT15)) 176 { 177 gpcon_reg = S3C2410_GPGCON; 178 extint_reg = S3C24XX_EXTINT1; 179 gpcon_offset = (irq - IRQ_EINT8) * 2; 180 extint_offset = (irq - IRQ_EINT8) * 4; 181 } 182 else if ((irq >= IRQ_EINT16) && (irq <= IRQ_EINT23)) 183 { 184 gpcon_reg = S3C2410_GPGCON; 185 extint_reg = S3C24XX_EXTINT2; 186 gpcon_offset = (irq - IRQ_EINT8) * 2; 187 extint_offset = (irq - IRQ_EINT16) * 4; 188 } else 189 return -1; 190 191 /* Set the GPIO to external interrupt mode */ 192 value = __raw_readl(gpcon_reg); 193 value = (value & ~(3 << gpcon_offset)) | (0x02 << gpcon_offset); 194 __raw_writel(value, gpcon_reg); 195 196 /* Set the external interrupt to pointed trigger type */ 197 switch (type) 198 { 199 case IRQ_TYPE_NONE: 200 printk(KERN_WARNING "No edge setting!\n"); 201 break; 202 203 case IRQ_TYPE_EDGE_RISING: 204 newvalue = S3C2410_EXTINT_RISEEDGE; 205 break; 206 207 case IRQ_TYPE_EDGE_FALLING: 208 newvalue = S3C2410_EXTINT_FALLEDGE; 209 break; 210 211 case IRQ_TYPE_EDGE_BOTH: 212 newvalue = S3C2410_EXTINT_BOTHEDGE; 213 break; 214 215 case IRQ_TYPE_LEVEL_LOW: 216 newvalue = S3C2410_EXTINT_LOWLEV; 217 break; 218 219 case IRQ_TYPE_LEVEL_HIGH: 220 newvalue = S3C2410_EXTINT_HILEV; 221 break; 222 223 default: 224 printk(KERN_ERR "No such irq type %d", type); 225 return -1; 226 } 227 228 value = __raw_readl(extint_reg); 229 value = (value & ~(7 << extint_offset)) | (newvalue << extint_offset); 230 __raw_writel(value, extint_reg); 231 232 return 0; 233} 234 235static struct irq_chip s3c_irqext_chip = { 236 .name = "s3c-ext", 237 .mask = s3c_irqext_mask, 238 .unmask = s3c_irqext_unmask, 239 .ack = s3c_irqext_ack, 240 .set_type = s3c_irqext_type, 241 .set_wake = s3c_irqext_wake 242}; 243 244static struct irq_chip s3c_irq_eint0t4 = { 245 .name = "s3c-ext0", 246 .ack = s3c_irq_ack, 247 .mask = s3c_irq_mask, 248 .unmask = s3c_irq_unmask, 249 .set_wake = s3c_irq_wake, 250 .set_type = s3c_irqext_type, 251}; 252 253/* mask values for the parent registers for each of the interrupt types */ 254 255#define INTMSK_UART0 (1UL << (IRQ_UART0 - IRQ_EINT0)) 256#define INTMSK_UART1 (1UL << (IRQ_UART1 - IRQ_EINT0)) 257#define INTMSK_UART2 (1UL << (IRQ_UART2 - IRQ_EINT0)) 258#define INTMSK_ADCPARENT (1UL << (IRQ_ADCPARENT - IRQ_EINT0)) 259 260 261/* UART0 */ 262 263static void 264s3c_irq_uart0_mask(unsigned int irqno) 265{ 266 s3c_irqsub_mask(irqno, INTMSK_UART0, 7); 267} 268 269static void 270s3c_irq_uart0_unmask(unsigned int irqno) 271{ 272 s3c_irqsub_unmask(irqno, INTMSK_UART0); 273} 274 275static void 276s3c_irq_uart0_ack(unsigned int irqno) 277{ 278 s3c_irqsub_maskack(irqno, INTMSK_UART0, 7); 279} 280 281static struct irq_chip s3c_irq_uart0 = { 282 .name = "s3c-uart0", 283 .mask = s3c_irq_uart0_mask, 284 .unmask = s3c_irq_uart0_unmask, 285 .ack = s3c_irq_uart0_ack, 286}; 287 288/* UART1 */ 289 290static void 291s3c_irq_uart1_mask(unsigned int irqno) 292{ 293 s3c_irqsub_mask(irqno, INTMSK_UART1, 7 << 3); 294} 295 296static void 297s3c_irq_uart1_unmask(unsigned int irqno) 298{ 299 s3c_irqsub_unmask(irqno, INTMSK_UART1); 300} 301 302static void 303s3c_irq_uart1_ack(unsigned int irqno) 304{ 305 s3c_irqsub_maskack(irqno, INTMSK_UART1, 7 << 3); 306} 307 308static struct irq_chip s3c_irq_uart1 = { 309 .name = "s3c-uart1", 310 .mask = s3c_irq_uart1_mask, 311 .unmask = s3c_irq_uart1_unmask, 312 .ack = s3c_irq_uart1_ack, 313}; 314 315/* UART2 */ 316 317static void 318s3c_irq_uart2_mask(unsigned int irqno) 319{ 320 s3c_irqsub_mask(irqno, INTMSK_UART2, 7 << 6); 321} 322 323static void 324s3c_irq_uart2_unmask(unsigned int irqno) 325{ 326 s3c_irqsub_unmask(irqno, INTMSK_UART2); 327} 328 329static void 330s3c_irq_uart2_ack(unsigned int irqno) 331{ 332 s3c_irqsub_maskack(irqno, INTMSK_UART2, 7 << 6); 333} 334 335static struct irq_chip s3c_irq_uart2 = { 336 .name = "s3c-uart2", 337 .mask = s3c_irq_uart2_mask, 338 .unmask = s3c_irq_uart2_unmask, 339 .ack = s3c_irq_uart2_ack, 340}; 341 342/* ADC and Touchscreen */ 343 344static void 345s3c_irq_adc_mask(unsigned int irqno) 346{ 347 s3c_irqsub_mask(irqno, INTMSK_ADCPARENT, 3 << 9); 348} 349 350static void 351s3c_irq_adc_unmask(unsigned int irqno) 352{ 353 s3c_irqsub_unmask(irqno, INTMSK_ADCPARENT); 354} 355 356static void 357s3c_irq_adc_ack(unsigned int irqno) 358{ 359 s3c_irqsub_ack(irqno, INTMSK_ADCPARENT, 3 << 9); 360} 361 362static struct irq_chip s3c_irq_adc = { 363 .name = "s3c-adc", 364 .mask = s3c_irq_adc_mask, 365 .unmask = s3c_irq_adc_unmask, 366 .ack = s3c_irq_adc_ack, 367}; 368 369/* irq demux for adc */ 370static void s3c_irq_demux_adc(unsigned int irq, 371 struct irq_desc *desc) 372{ 373 unsigned int subsrc, submsk; 374 unsigned int offset = 9; 375 376 /* read the current pending interrupts, and the mask 377 * for what it is available */ 378 379 subsrc = __raw_readl(S3C2410_SUBSRCPND); 380 submsk = __raw_readl(S3C2410_INTSUBMSK); 381 382 subsrc &= ~submsk; 383 subsrc >>= offset; 384 subsrc &= 3; 385 386 if (subsrc != 0) { 387 if (subsrc & 1) { 388 generic_handle_irq(IRQ_TC); 389 } 390 if (subsrc & 2) { 391 generic_handle_irq(IRQ_ADC); 392 } 393 } 394} 395 396static void s3c_irq_demux_uart(unsigned int start) 397{ 398 unsigned int subsrc, submsk; 399 unsigned int offset = start - IRQ_S3CUART_RX0; 400 401 /* read the current pending interrupts, and the mask 402 * for what it is available */ 403 404 subsrc = __raw_readl(S3C2410_SUBSRCPND); 405 submsk = __raw_readl(S3C2410_INTSUBMSK); 406 407 irqdbf2("s3c_irq_demux_uart: start=%d (%d), subsrc=0x%08x,0x%08x\n", 408 start, offset, subsrc, submsk); 409 410 subsrc &= ~submsk; 411 subsrc >>= offset; 412 subsrc &= 7; 413 414 if (subsrc != 0) { 415 if (subsrc & 1) 416 generic_handle_irq(start); 417 418 if (subsrc & 2) 419 generic_handle_irq(start+1); 420 421 if (subsrc & 4) 422 generic_handle_irq(start+2); 423 } 424} 425 426/* uart demux entry points */ 427 428static void 429s3c_irq_demux_uart0(unsigned int irq, 430 struct irq_desc *desc) 431{ 432 irq = irq; 433 s3c_irq_demux_uart(IRQ_S3CUART_RX0); 434} 435 436static void 437s3c_irq_demux_uart1(unsigned int irq, 438 struct irq_desc *desc) 439{ 440 irq = irq; 441 s3c_irq_demux_uart(IRQ_S3CUART_RX1); 442} 443 444static void 445s3c_irq_demux_uart2(unsigned int irq, 446 struct irq_desc *desc) 447{ 448 irq = irq; 449 s3c_irq_demux_uart(IRQ_S3CUART_RX2); 450} 451 452static void 453s3c_irq_demux_extint8(unsigned int irq, 454 struct irq_desc *desc) 455{ 456 unsigned long eintpnd = __raw_readl(S3C24XX_EINTPEND); 457 unsigned long eintmsk = __raw_readl(S3C24XX_EINTMASK); 458 459 eintpnd &= ~eintmsk; 460 eintpnd &= ~0xff; /* ignore lower irqs */ 461 462 /* we may as well handle all the pending IRQs here */ 463 464 while (eintpnd) { 465 irq = __ffs(eintpnd); 466 eintpnd &= ~(1<<irq); 467 468 irq += (IRQ_EINT4 - 4); 469 generic_handle_irq(irq); 470 } 471 472} 473 474static void 475s3c_irq_demux_extint4t7(unsigned int irq, 476 struct irq_desc *desc) 477{ 478 unsigned long eintpnd = __raw_readl(S3C24XX_EINTPEND); 479 unsigned long eintmsk = __raw_readl(S3C24XX_EINTMASK); 480 481 eintpnd &= ~eintmsk; 482 eintpnd &= 0xff; /* only lower irqs */ 483 484 /* we may as well handle all the pending IRQs here */ 485 486 while (eintpnd) { 487 irq = __ffs(eintpnd); 488 eintpnd &= ~(1<<irq); 489 490 irq += (IRQ_EINT4 - 4); 491 492 generic_handle_irq(irq); 493 } 494} 495 496#ifdef CONFIG_FIQ 497/** 498 * s3c24xx_set_fiq - set the FIQ routing 499 * @irq: IRQ number to route to FIQ on processor. 500 * @on: Whether to route @irq to the FIQ, or to remove the FIQ routing. 501 * 502 * Change the state of the IRQ to FIQ routing depending on @irq and @on. If 503 * @on is true, the @irq is checked to see if it can be routed and the 504 * interrupt controller updated to route the IRQ. If @on is false, the FIQ 505 * routing is cleared, regardless of which @irq is specified. 506 */ 507int s3c24xx_set_fiq(unsigned int irq, bool on) 508{ 509 u32 intmod; 510 unsigned offs; 511 512 if (on) { 513 offs = irq - FIQ_START; 514 if (offs > 31) 515 return -EINVAL; 516 517 intmod = 1 << offs; 518 } else { 519 intmod = 0; 520 } 521 522 __raw_writel(intmod, S3C2410_INTMOD); 523 return 0; 524} 525 526EXPORT_SYMBOL_GPL(s3c24xx_set_fiq); 527#endif 528 529 530/* s3c24xx_init_irq 531 * 532 * Initialise S3C2410 IRQ system 533*/ 534 535void __init s3c24xx_init_irq(void) 536{ 537 unsigned long pend; 538 unsigned long last; 539 int irqno; 540 int i; 541 542#ifdef CONFIG_FIQ 543 init_FIQ(); 544#endif 545 546 irqdbf("s3c2410_init_irq: clearing interrupt status flags\n"); 547 548 /* first, clear all interrupts pending... */ 549 550 last = 0; 551 for (i = 0; i < 4; i++) { 552 pend = __raw_readl(S3C24XX_EINTPEND); 553 554 if (pend == 0 || pend == last) 555 break; 556 557 __raw_writel(pend, S3C24XX_EINTPEND); 558 printk("irq: clearing pending ext status %08x\n", (int)pend); 559 last = pend; 560 } 561 562 last = 0; 563 for (i = 0; i < 4; i++) { 564 pend = __raw_readl(S3C2410_INTPND); 565 566 if (pend == 0 || pend == last) 567 break; 568 569 __raw_writel(pend, S3C2410_SRCPND); 570 __raw_writel(pend, S3C2410_INTPND); 571 printk("irq: clearing pending status %08x\n", (int)pend); 572 last = pend; 573 } 574 575 last = 0; 576 for (i = 0; i < 4; i++) { 577 pend = __raw_readl(S3C2410_SUBSRCPND); 578 579 if (pend == 0 || pend == last) 580 break; 581 582 printk("irq: clearing subpending status %08x\n", (int)pend); 583 __raw_writel(pend, S3C2410_SUBSRCPND); 584 last = pend; 585 } 586 587 /* register the main interrupts */ 588 589 irqdbf("s3c2410_init_irq: registering s3c2410 interrupt handlers\n"); 590 591 for (irqno = IRQ_EINT4t7; irqno <= IRQ_ADCPARENT; irqno++) { 592 /* set all the s3c2410 internal irqs */ 593 594 switch (irqno) { 595 /* deal with the special IRQs (cascaded) */ 596 597 case IRQ_EINT4t7: 598 case IRQ_EINT8t23: 599 case IRQ_UART0: 600 case IRQ_UART1: 601 case IRQ_UART2: 602 case IRQ_ADCPARENT: 603 set_irq_chip(irqno, &s3c_irq_level_chip); 604 set_irq_handler(irqno, handle_level_irq); 605 break; 606 607 case IRQ_RESERVED6: 608 case IRQ_RESERVED24: 609 /* no IRQ here */ 610 break; 611 612 default: 613 //irqdbf("registering irq %d (s3c irq)\n", irqno); 614 set_irq_chip(irqno, &s3c_irq_chip); 615 set_irq_handler(irqno, handle_edge_irq); 616 set_irq_flags(irqno, IRQF_VALID); 617 } 618 } 619 620 /* setup the cascade irq handlers */ 621 622 set_irq_chained_handler(IRQ_EINT4t7, s3c_irq_demux_extint4t7); 623 set_irq_chained_handler(IRQ_EINT8t23, s3c_irq_demux_extint8); 624 625 set_irq_chained_handler(IRQ_UART0, s3c_irq_demux_uart0); 626 set_irq_chained_handler(IRQ_UART1, s3c_irq_demux_uart1); 627 set_irq_chained_handler(IRQ_UART2, s3c_irq_demux_uart2); 628 set_irq_chained_handler(IRQ_ADCPARENT, s3c_irq_demux_adc); 629 630 /* external interrupts */ 631 632 for (irqno = IRQ_EINT0; irqno <= IRQ_EINT3; irqno++) { 633 irqdbf("registering irq %d (ext int)\n", irqno); 634 set_irq_chip(irqno, &s3c_irq_eint0t4); 635 set_irq_handler(irqno, handle_edge_irq); 636 set_irq_flags(irqno, IRQF_VALID); 637 } 638 639 for (irqno = IRQ_EINT4; irqno <= IRQ_EINT23; irqno++) { 640 irqdbf("registering irq %d (extended s3c irq)\n", irqno); 641 set_irq_chip(irqno, &s3c_irqext_chip); 642 set_irq_handler(irqno, handle_edge_irq); 643 set_irq_flags(irqno, IRQF_VALID); 644 } 645 646 /* register the uart interrupts */ 647 648 irqdbf("s3c2410: registering external interrupts\n"); 649 650 for (irqno = IRQ_S3CUART_RX0; irqno <= IRQ_S3CUART_ERR0; irqno++) { 651 irqdbf("registering irq %d (s3c uart0 irq)\n", irqno); 652 set_irq_chip(irqno, &s3c_irq_uart0); 653 set_irq_handler(irqno, handle_level_irq); 654 set_irq_flags(irqno, IRQF_VALID); 655 } 656 657 for (irqno = IRQ_S3CUART_RX1; irqno <= IRQ_S3CUART_ERR1; irqno++) { 658 irqdbf("registering irq %d (s3c uart1 irq)\n", irqno); 659 set_irq_chip(irqno, &s3c_irq_uart1); 660 set_irq_handler(irqno, handle_level_irq); 661 set_irq_flags(irqno, IRQF_VALID); 662 } 663 664 for (irqno = IRQ_S3CUART_RX2; irqno <= IRQ_S3CUART_ERR2; irqno++) { 665 irqdbf("registering irq %d (s3c uart2 irq)\n", irqno); 666 set_irq_chip(irqno, &s3c_irq_uart2); 667 set_irq_handler(irqno, handle_level_irq); 668 set_irq_flags(irqno, IRQF_VALID); 669 } 670 671 for (irqno = IRQ_TC; irqno <= IRQ_ADC; irqno++) { 672 irqdbf("registering irq %d (s3c adc irq)\n", irqno); 673 set_irq_chip(irqno, &s3c_irq_adc); 674 set_irq_handler(irqno, handle_edge_irq); 675 set_irq_flags(irqno, IRQF_VALID); 676 } 677 678 irqdbf("s3c2410: registered interrupt handlers\n"); 679} 680