diff options
-rw-r--r-- | arch/arm/mach-s3c2412/irq.c | 58 | ||||
-rw-r--r-- | arch/arm/mach-s3c2412/s3c2412.c | 5 | ||||
-rw-r--r-- | include/asm-arm/arch-s3c2410/irqs.h | 7 |
3 files changed, 70 insertions, 0 deletions
diff --git a/arch/arm/mach-s3c2412/irq.c b/arch/arm/mach-s3c2412/irq.c index f0d66828f96..e9d0c769f5d 100644 --- a/arch/arm/mach-s3c2412/irq.c +++ b/arch/arm/mach-s3c2412/irq.c @@ -38,6 +38,9 @@ #include <asm/plat-s3c24xx/irq.h> #include <asm/plat-s3c24xx/pm.h> +#define INTMSK(start, end) ((1 << ((end) + 1 - (start))) - 1) +#define INTMSK_SUB(start, end) (INTMSK(start, end) << ((start - S3C2410_IRQSUB(0)))) + /* the s3c2412 changes the behaviour of IRQ_EINT0 through IRQ_EINT3 by * having them turn up in both the INT* and the EINT* registers. Whilst * both show the status, they both now need to be acked when the IRQs @@ -105,6 +108,51 @@ static struct irq_chip s3c2412_irq_eint0t4 = { .set_type = s3c_irqext_type, }; +#define INTBIT(x) (1 << ((x) - S3C2410_IRQSUB(0))) + +/* CF and SDI sub interrupts */ + +static void s3c2412_irq_demux_cfsdi(unsigned int irq, struct irq_desc *desc) +{ + unsigned int subsrc, submsk; + + subsrc = __raw_readl(S3C2410_SUBSRCPND); + submsk = __raw_readl(S3C2410_INTSUBMSK); + + subsrc &= ~submsk; + + if (subsrc & INTBIT(IRQ_S3C2412_SDI)) + desc_handle_irq(IRQ_S3C2412_SDI, irq_desc + IRQ_S3C2412_SDI); + + if (subsrc & INTBIT(IRQ_S3C2412_CF)) + desc_handle_irq(IRQ_S3C2412_CF, irq_desc + IRQ_S3C2412_CF); +} + +#define INTMSK_CFSDI (1UL << (IRQ_S3C2412_CFSDI - IRQ_EINT0)) +#define SUBMSK_CFSDI INTMSK_SUB(IRQ_S3C2412_SDI, IRQ_S3C2412_CF) + +static void s3c2412_irq_cfsdi_mask(unsigned int irqno) +{ + s3c_irqsub_mask(irqno, INTMSK_CFSDI, SUBMSK_CFSDI); +} + +static void s3c2412_irq_cfsdi_unmask(unsigned int irqno) +{ + s3c_irqsub_unmask(irqno, INTMSK_CFSDI); +} + +static void s3c2412_irq_cfsdi_ack(unsigned int irqno) +{ + s3c_irqsub_maskack(irqno, INTMSK_CFSDI, SUBMSK_CFSDI); +} + +static struct irq_chip s3c2412_irq_cfsdi = { + .name = "s3c2412-cfsdi", + .ack = s3c2412_irq_cfsdi_ack, + .mask = s3c2412_irq_cfsdi_mask, + .unmask = s3c2412_irq_cfsdi_unmask, +}; + static int s3c2412_irq_add(struct sys_device *sysdev) { unsigned int irqno; @@ -115,6 +163,16 @@ static int s3c2412_irq_add(struct sys_device *sysdev) set_irq_flags(irqno, IRQF_VALID); } + /* add demux support for CF/SDI */ + + set_irq_chained_handler(IRQ_S3C2412_CFSDI, s3c2412_irq_demux_cfsdi); + + for (irqno = IRQ_S3C2412_SDI; irqno <= IRQ_S3C2412_CF; irqno++) { + set_irq_chip(irqno, &s3c2412_irq_cfsdi); + set_irq_handler(irqno, handle_level_irq); + set_irq_flags(irqno, IRQF_VALID); + } + return 0; } diff --git a/arch/arm/mach-s3c2412/s3c2412.c b/arch/arm/mach-s3c2412/s3c2412.c index e0ccb404623..4f92a1562d7 100644 --- a/arch/arm/mach-s3c2412/s3c2412.c +++ b/arch/arm/mach-s3c2412/s3c2412.c @@ -78,6 +78,11 @@ void __init s3c2412_init_uarts(struct s3c2410_uartcfg *cfg, int no) s3c_device_lcd.name = "s3c2412-lcd"; s3c_device_nand.name = "s3c2412-nand"; + /* alter IRQ of SDI controller */ + + s3c_device_sdi.resource[1].start = IRQ_S3C2412_SDI; + s3c_device_sdi.resource[1].end = IRQ_S3C2412_SDI; + /* spi channel related changes, s3c2412/13 specific */ s3c_device_spi0.name = "s3c2412-spi"; s3c_device_spi0.resource[0].end = S3C24XX_PA_SPI + 0x24; diff --git a/include/asm-arm/arch-s3c2410/irqs.h b/include/asm-arm/arch-s3c2410/irqs.h index 3b49cd1c345..996f65488d2 100644 --- a/include/asm-arm/arch-s3c2410/irqs.h +++ b/include/asm-arm/arch-s3c2410/irqs.h @@ -112,6 +112,13 @@ #define IRQ_TC S3C2410_IRQSUB(9) #define IRQ_ADC S3C2410_IRQSUB(10) +/* extra irqs for s3c2412 */ + +#define IRQ_S3C2412_CFSDI S3C2410_IRQ(21) + +#define IRQ_S3C2412_SDI S3C2410_IRQSUB(13) +#define IRQ_S3C2412_CF S3C2410_IRQSUB(14) + /* extra irqs for s3c2440 */ #define IRQ_S3C2440_CAM_C S3C2410_IRQSUB(11) /* S3C2443 too */ |