2 * arch/arm/mach-s3c24a0/irq.c
4 * Generic S3C24A0 IRQ handling.
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License version 2 as
9 * published by the Free Software Foundation.
12 #include <linux/init.h>
13 #include <linux/module.h>
14 #include <linux/sched.h>
15 #include <linux/interrupt.h>
17 #include <asm/hardware.h>
19 #include <asm/mach/irq.h>
20 #include <linux/sysdev.h>
25 * SUBINTPND 0x40200018
28 static const unsigned long p_regs
[3] = { 0x40200010, 0x40200018, 0x44800038 };
33 * SUBINTMSK 0x4020001c
37 static const unsigned long m_regs
[3] = { 0x40200008, 0x4020001c, 0x44800034 };
42 static const int r_irqs
[NR_IRQS
] = {
43 96, 96, 96, 96, 96, 5, 6, 7, 8, 9, 10, 11, 12, 96, 96, 15,
44 96, 96, 18, 19, 96, 21, 22, 96, 96, 25, 26, 27, 96, 29, 30, 96,
45 17, 17, 17, 23, 23, 23, 28, 28, 96, 96, 96, 13, 13, 16, 16, 14,
46 14, 31, 31, 31, 14, 24, 24, 29, 29, 20, 20, 20, 20, 96, 96, 96,
47 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 4,
48 4, 4, 4, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96
51 static inline void clear_pending(int irq
)
57 *(volatile unsigned long *)(io_p2v(p_regs
[irq
>> 5])) = (1 << (irq
% 32));
63 static inline int read_pending(int irq
)
65 return ((*(volatile unsigned long *)(io_p2v(p_regs
[irq
>> 5]))) & (1 << (irq
% 32)));
68 static inline void mask_irq(int irq
)
70 *(volatile unsigned long *)(io_p2v(m_regs
[irq
>> 5])) |= (1 << (irq
% 32));
73 static inline void unmask_irq(int irq
)
75 *(volatile unsigned long *)(io_p2v(m_regs
[irq
>> 5])) &= ~(1 << (irq
% 32));
78 //#define DEBUG // hcyun
81 static inline int find_irq(int irq
)
86 if ( irq
== 4 || irq
== 3 ) printk("find_irq: irq=%d\n", irq
);
89 for (i
= IRQ_GRP1_START
; i
< NR_IRQS
; i
++) {
90 if (r_irqs
[i
] == irq
) {
92 if ( i
>= 64 ) printk("Externel IRQ %d\n", i
);
93 else if ( i
>= 32 ) printk("Sub IRQ %d\n", i
);
96 if (read_pending(i
)) {
98 if ( i
>= 64 ) printk("OK there's external pending IRQ %d\n", i
);
99 else if ( i
>= 32 ) printk("OK there's sub pending IRQ %d\n", i
);
108 int fixup_irq(int irq
)
110 int retval
= NR_IRQS
;
112 if (irq
>= IRQ_GRP1_START
)
115 if ((r_irqs
[irq
]) == NR_IRQS
) {
116 retval
= find_irq(irq
);
124 static void elfin_mask_ack_irq(unsigned int irq
)
130 static void elfin_ack_irq(unsigned int irq
)
135 static void elfin_mask_irq(unsigned int irq
)
140 static void elfin_unmask_irq(unsigned int irq
)
145 static struct irqchip s3c24a0_irq_chip
= {
146 .ack
= elfin_ack_irq
, // irq_ack
147 .mask
= elfin_mask_irq
, // irq_mask
148 .unmask
= elfin_unmask_irq
// irq_unmak
154 static unsigned long ic_irq_enable
;
156 static int irq_suspend(struct sys_device
*dev
, u32 state
)
161 static int irq_resume(struct sys_device
*dev
)
163 /* disable all irq sources */
167 #define irq_suspend NULL
168 #define irq_resume NULL
171 static struct sysdev_class irq_class
= {
172 set_kset_name("irq"),
173 .suspend
= irq_suspend
,
174 .resume
= irq_resume
,
177 static struct sys_device irq_device
= {
182 static int __init
irq_init_sysfs(void)
184 int ret
= sysdev_class_register(&irq_class
);
186 ret
= sysdev_register(&irq_device
);
190 device_initcall(irq_init_sysfs
);
192 void __init
elfin_init_irq(void)
198 /* disable all interrupts */
199 INTSUBMSK
= 0xffffffff;
200 EINTMASK
= 0xffffffff;
203 /* clear status registers */
205 SUBSRCPND
= SUBSRCPND
;
209 /* all interrupts set as IRQ */
212 /* we have three groups */
213 for (irq
= 0; irq
< NR_IRQS
; irq
++) {
217 if ((r_irqs
[irq
]) == NR_IRQS
) {
218 if (irq
< IRQ_GRP1_START
)
219 INTMSK
&= ~(1 << irq
);
222 else if ( irq
< IRQ_GRP2_START
)
225 set_irq_chip(irq
, &s3c24a0_irq_chip
);
226 set_irq_handler(irq
, do_edge_IRQ
);
227 set_irq_flags(irq
, flags
);
232 * S3C24A0 , External Interrupt setting interface
234 * 1) GPIO\e-A\x0e8\x0f: external irq\e$)C
236 * |<--ECTRL-->|<--GPIO--->|
239 * +-----+-----+-----+-----+-----+-----+-----+-----+
240 * |4-bit|4-bit|4-bit|4-bit|4-bit|4-bit|4-bit|4-bit|
241 * +-----+-----+-----+-----+-----+-----+-----+-----+
244 static const unsigned long garbage
[] = {
245 0xffff0000, /* EINT 0 */
246 0xffff1010, /* EINT 1 */
247 0xffff2020, /* EINT 2 */
248 0xffff0130, /* EINT 3 */
249 0xffff1140, /* EINT 4 */
250 0xffff2150, /* EINT 5 */
251 0xffff3160, /* EINT 6 */
252 0xffff4170, /* EINT 7 */
253 0xffff5180, /* EINT 8 */
254 0xffff6190, /* EINT 9 */
255 0xffff71a0, /* EINT 10 */
256 0xffff0201, /* EINT 11 */
257 0xffff1211, /* EINT 12 */
258 0xffff2221, /* EINT 13 */
259 0xffff3231, /* EINT 14 */
260 0xffff4241, /* EINT 15 */
261 0xffff5251, /* EINT 16 */
262 0xffff6261, /* EINT 17 */
263 0xffff7271, /* EINT 18 */
266 int set_external_irq(int irq
, int edge
, int pullup
)
268 int phy_irq
= EINTIRQ_DEC(irq
); /* physical irq number */
270 struct irqdesc
*desc
;
276 g
= garbage
[phy_irq
];
279 *(volatile unsigned long *)(io_p2v(0x44800008 - (0x4 * (g
& 0x0000000f)))) &= ~(0x3 << (((g
& 0x000000f0) >> 0x4) * 0x2));
280 *(volatile unsigned long *)(io_p2v(0x44800008 - (0x4 * (g
& 0x0000000f)))) |= (0x2 << (((g
& 0x000000f0) >> 0x4) * 0x2));
283 printk("GPIO(0x%x) = 0x%x\n", io_p2v(0x44800008), *(volatile unsigned long *)io_p2v(0x44800008));
284 printk("GPIO(0x%x) = 0x%x\n", io_p2v(0x44800004), *(volatile unsigned long *)io_p2v(0x44800004));
288 *(volatile unsigned long *)(io_p2v(0x44800018 + (0x4 * ((g
& 0x00000f00) >> 0x8)))) &= ~(0x7 << (((g
& 0x0000f000) >> 0xc) * 0x4));
289 *(volatile unsigned long *)(io_p2v(0x44800018 + (0x4 * ((g
& 0x00000f00) >> 0x8)))) |= (edge
<< (((g
& 0x0000f000) >> 0xc) * 0x4));
292 GPUP
&= ~(1 << phy_irq
);
295 desc
= irq_desc
+ irq
;
299 case EINT_FALLING_EDGE
:
300 case EINT_RISING_EDGE
:
301 case EINT_BOTH_EDGES
:
302 set_irq_handler(irq
, do_edge_IRQ
);
305 case EINT_HIGH_LEVEL
:
306 set_irq_handler(irq
, do_level_IRQ
);
313 EXPORT_SYMBOL(set_external_irq
);