aboutsummaryrefslogtreecommitdiffstats
path: root/arch/arm/mach-s3c2412/irq.c
diff options
context:
space:
mode:
authorBen Dooks <ben-linux@fluff.org>2007-10-04 16:41:20 -0400
committerRussell King <rmk+kernel@arm.linux.org.uk>2007-10-12 18:43:42 -0400
commitf3fb5a556c99118186581e6546a9c41e1f73cf6f (patch)
treec5a79ca0dd682f91d2c25ae4eeba064e95a98892 /arch/arm/mach-s3c2412/irq.c
parent361c7ad607bc0e84ef0fef8c3f11c47b33c06e41 (diff)
[ARM] 4596/1: S3C2412: Correct IRQs for SDI+CF and add decoding support
Fix the IRQ numbers of the CF and SDI interface on the S3C2412 and S3C2413. Add support to handle these IRQs properly and ensure that the SDI controller platform device is correctly renumbered. Signed-off-by: Ben Dooks <ben-linux@fluff.org> Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
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 f0d66828f965..e9d0c769f5da 100644
--- a/arch/arm/mach-s3c2412/irq.c
+++ b/arch/arm/mach-s3c2412/irq.c
@@ -38,6 +38,9 @@
38#include <asm/plat-s3c24xx/irq.h> 38#include <asm/plat-s3c24xx/irq.h>
39#include <asm/plat-s3c24xx/pm.h> 39#include <asm/plat-s3c24xx/pm.h>
40 40
41#define INTMSK(start, end) ((1 << ((end) + 1 - (start))) - 1)
42#define INTMSK_SUB(start, end) (INTMSK(start, end) << ((start - S3C2410_IRQSUB(0))))
43
41/* the s3c2412 changes the behaviour of IRQ_EINT0 through IRQ_EINT3 by 44/* the s3c2412 changes the behaviour of IRQ_EINT0 through IRQ_EINT3 by
42 * having them turn up in both the INT* and the EINT* registers. Whilst 45 * having them turn up in both the INT* and the EINT* registers. Whilst
43 * both show the status, they both now need to be acked when the IRQs 46 * 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 = {
105 .set_type = s3c_irqext_type, 108 .set_type = s3c_irqext_type,
106}; 109};
107 110
111#define INTBIT(x) (1 << ((x) - S3C2410_IRQSUB(0)))
112
113/* CF and SDI sub interrupts */
114
115static void s3c2412_irq_demux_cfsdi(unsigned int irq, struct irq_desc *desc)
116{
117 unsigned int subsrc, submsk;
118
119 subsrc = __raw_readl(S3C2410_SUBSRCPND);
120 submsk = __raw_readl(S3C2410_INTSUBMSK);
121
122 subsrc &= ~submsk;
123
124 if (subsrc & INTBIT(IRQ_S3C2412_SDI))
125 desc_handle_irq(IRQ_S3C2412_SDI, irq_desc + IRQ_S3C2412_SDI);
126
127 if (subsrc & INTBIT(IRQ_S3C2412_CF))
128 desc_handle_irq(IRQ_S3C2412_CF, irq_desc + IRQ_S3C2412_CF);
129}
130
131#define INTMSK_CFSDI (1UL << (IRQ_S3C2412_CFSDI - IRQ_EINT0))
132#define SUBMSK_CFSDI INTMSK_SUB(IRQ_S3C2412_SDI, IRQ_S3C2412_CF)
133
134static void s3c2412_irq_cfsdi_mask(unsigned int irqno)
135{
136 s3c_irqsub_mask(irqno, INTMSK_CFSDI, SUBMSK_CFSDI);
137}
138
139static void s3c2412_irq_cfsdi_unmask(unsigned int irqno)
140{
141 s3c_irqsub_unmask(irqno, INTMSK_CFSDI);
142}
143
144static void s3c2412_irq_cfsdi_ack(unsigned int irqno)
145{
146 s3c_irqsub_maskack(irqno, INTMSK_CFSDI, SUBMSK_CFSDI);
147}
148
149static struct irq_chip s3c2412_irq_cfsdi = {
150 .name = "s3c2412-cfsdi",
151 .ack = s3c2412_irq_cfsdi_ack,
152 .mask = s3c2412_irq_cfsdi_mask,
153 .unmask = s3c2412_irq_cfsdi_unmask,
154};
155
108static int s3c2412_irq_add(struct sys_device *sysdev) 156static int s3c2412_irq_add(struct sys_device *sysdev)
109{ 157{
110 unsigned int irqno; 158 unsigned int irqno;
@@ -115,6 +163,16 @@ static int s3c2412_irq_add(struct sys_device *sysdev)
115 set_irq_flags(irqno, IRQF_VALID); 163 set_irq_flags(irqno, IRQF_VALID);
116 } 164 }
117 165
166 /* add demux support for CF/SDI */
167
168 set_irq_chained_handler(IRQ_S3C2412_CFSDI, s3c2412_irq_demux_cfsdi);
169
170 for (irqno = IRQ_S3C2412_SDI; irqno <= IRQ_S3C2412_CF; irqno++) {
171 set_irq_chip(irqno, &s3c2412_irq_cfsdi);
172 set_irq_handler(irqno, handle_level_irq);
173 set_irq_flags(irqno, IRQF_VALID);
174 }
175
118 return 0; 176 return 0;
119} 177}
120 178