aboutsummaryrefslogtreecommitdiff
path: root/arch/arm/mach-s3c2412/irq.c
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@woody.linux-foundation.org>2007-10-15 16:08:50 -0700
committerLinus Torvalds <torvalds@woody.linux-foundation.org>2007-10-15 16:08:50 -0700
commit65a6ec0d72a07f16719e9b7a96e1c4bae044b591 (patch)
tree344e03a5039a44982c1b78d6113633b21b434820 /arch/arm/mach-s3c2412/irq.c
parent541010e4b8921cd781ff02ae68028501457045b6 (diff)
parent0181b61a988424b5cc44fe09e6968142359c815e (diff)
Merge branch 'devel' of master.kernel.org:/home/rmk/linux-2.6-arm
* 'devel' of master.kernel.org:/home/rmk/linux-2.6-arm: (95 commits) [ARM] 4578/1: CM-x270: PCMCIA support [ARM] 4577/1: ITE 8152 PCI bridge support [ARM] 4576/1: CM-X270 machine support [ARM] pxa: Avoid pxa_gpio_mode() in gpio_direction_{in,out}put() [ARM] pxa: move pxa_set_mode() from pxa2xx_mainstone.c to mainstone.c [ARM] pxa: move pxa_set_mode() from pxa2xx_lubbock.c to lubbock.c [ARM] pxa: Make cpu_is_pxaXXX dependent on configuration symbols [ARM] pxa: PXA3xx base support [NET] smc91x: fix PXA DMA support code [SERIAL] Fix console initialisation ordering [ARM] pxa: tidy up arch/arm/mach-pxa/Makefile [ARM] Update arch/arm/Kconfig for drivers/Kconfig changes [ARM] 4600/1: fix kernel build failure with build-id-supporting binutils [ARM] 4599/1: Preserve ATAG list for use with kexec (2.6.23) [ARM] Rename consistent_sync() as dma_cache_maint() [ARM] 4572/1: ep93xx: add cirrus logic edb9307 support [ARM] 4596/1: S3C2412: Correct IRQs for SDI+CF and add decoding support [ARM] 4595/1: ns9xxx: define registers as void __iomem * instead of volatile u32 [ARM] 4594/1: ns9xxx: use the new gpio functions [ARM] 4593/1: ns9xxx: implement generic clockevents ...
Diffstat (limited to 'arch/arm/mach-s3c2412/irq.c')
-rw-r--r--arch/arm/mach-s3c2412/irq.c58
1 files changed, 58 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;
}