| irq-fix3.patch | | Files affected: | arch/arm/mach-s3c2410/irq.c | 62 45 + 17 - 0 ! | 1 files changed, 45 insertions(+), 17 deletions(-) | | Ben Dooks, Thu, 07 Oct 2004 15:45:34 +0100 --- linux-2.6.9-rc3-bk5/arch/arm/mach-s3c2410/irq.c 2004-10-04 22:57:06.000000000 +0100 +++ linux-2.6.9-rc3-bk5-irqfix1/arch/arm/mach-s3c2410/irq.c 2004-10-05 15:13:58.000000000 +0100 @@ -1,7 +1,7 @@ /* linux/arch/arm/mach-s3c2410/irq.c * * Copyright (c) 2003,2004 Simtec Electronics - * Ben Dooks + * Ben Dooks * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -27,7 +27,13 @@ * * 21-Jul-2004 Arnaud Patard (Rtp) * Addition of ADC/TC demux - */ + * + * 04-Oct-2004 Klaus Fetscher + * Fix for set_irq_type() on low EINT numbers + * + * 05-Oct-2004 Ben Dooks + * Tidy up KF's patch and sort out new release +*/ #include @@ -46,9 +52,6 @@ #include #include -#if 0 -#include -#endif #define irqdbf(x...) #define irqdbf2(x...) @@ -195,13 +198,20 @@ unsigned long gpcon_offset, extint_offset; unsigned long newvalue = 0, value; - if ((irq >= IRQ_EINT0) && (irq <= IRQ_EINT7)) + if ((irq >= IRQ_EINT0) && (irq <= IRQ_EINT3)) { gpcon_reg = S3C2410_GPFCON; extint_reg = S3C2410_EXTINT0; gpcon_offset = (irq - IRQ_EINT0) * 2; extint_offset = (irq - IRQ_EINT0) * 4; } + else if ((irq >= IRQ_EINT4) && (irq <= IRQ_EINT7)) + { + gpcon_reg = S3C2410_GPFCON; + extint_reg = S3C2410_EXTINT0; + gpcon_offset = (irq - (EXTINT_OFF)) * 2; + extint_offset = (irq - (EXTINT_OFF)) * 4; + } else if ((irq >= IRQ_EINT8) && (irq <= IRQ_EINT15)) { gpcon_reg = S3C2410_GPGCON; @@ -269,6 +279,13 @@ .type = s3c_irqext_type }; +static struct irqchip s3c_irq_eint0t4 = { + .ack = s3c_irq_ack, + .mask = s3c_irq_mask, + .unmask = s3c_irq_unmask, + .type = s3c_irqext_type +}; + /* mask values for the parent registers for each of the interrupt types */ #define INTMSK_UART0 (1UL << (IRQ_UART0 - IRQ_EINT0)) @@ -549,6 +566,7 @@ void __init s3c2410_init_irq(void) { unsigned long pend; + unsigned long last; int irqno; int i; @@ -556,48 +574,51 @@ /* first, clear all interrupts pending... */ + last = 0; for (i = 0; i < 4; i++) { pend = __raw_readl(S3C2410_EINTPEND); - if (pend == 0) + + if (pend == 0 || pend == last) break; + __raw_writel(pend, S3C2410_EINTPEND); printk("irq: clearing pending ext status %08x\n", (int)pend); + last = pend; } + last = 0; for (i = 0; i < 4; i++) { pend = __raw_readl(S3C2410_INTPND); - if (pend == 0) + + if (pend == 0 || pend == last) break; + __raw_writel(pend, S3C2410_SRCPND); __raw_writel(pend, S3C2410_INTPND); printk("irq: clearing pending status %08x\n", (int)pend); + last = pend; } + last = 0; for (i = 0; i < 4; i++) { pend = __raw_readl(S3C2410_SUBSRCPND); - if (pend == 0) + if (pend == 0 || pend == last) break; printk("irq: clearing subpending status %08x\n", (int)pend); __raw_writel(pend, S3C2410_SUBSRCPND); + last = pend; } /* register the main interrupts */ irqdbf("s3c2410_init_irq: registering s3c2410 interrupt handlers\n"); - for (irqno = IRQ_EINT0; irqno <= IRQ_ADCPARENT; irqno++) { + for (irqno = IRQ_BATT_FLT; irqno <= IRQ_ADCPARENT; irqno++) { /* set all the s3c2410 internal irqs */ switch (irqno) { - - case IRQ_EINT4t7: - case IRQ_EINT8t23: - /* these are already dealt with, so should never - * appear */ - break; - /* deal with the special IRQs (cascaded) */ case IRQ_UART0: @@ -632,6 +653,13 @@ /* external interrupts */ + for (irqno = IRQ_EINT0; irqno <= IRQ_EINT3; irqno++) { + irqdbf("registering irq %d (ext int)\n", irqno); + set_irq_chip(irqno, &s3c_irq_eint0t4); + set_irq_handler(irqno, do_edge_IRQ); + set_irq_flags(irqno, IRQF_VALID); + } + for (irqno = IRQ_EINT4; irqno <= IRQ_EINT23; irqno++) { irqdbf("registering irq %d (extended s3c irq)\n", irqno); set_irq_chip(irqno, &s3c_irqext_chip);