change prefix for kernelpatchbase 2.6.26
[openwrt/svn-archive/archive.git] / target / linux / s3c24xx / patches-2.6.26 / 1045-introduce-fiq-basis.patch.patch
1 From 6a2c7de90f47b7eb74f3cb2d181f950ece22b3fb Mon Sep 17 00:00:00 2001
2 From: mokopatches <mokopatches@openmoko.org>
3 Date: Fri, 25 Jul 2008 22:21:22 +0100
4 Subject: [PATCH] introduce-fiq-basis.patch
5 Adds a C-based FIQ ISR which is very convenient (and unusual --
6 normally you have to do FIQ ISR in assembler only).
7 Based on my article:
8
9 http://warmcat.com/_wp/2007/09/17/at91rm9200-fiq-faq-and-simple-example-code-patch/
10
11 Implemented as a platform device and driver.
12
13 Suspend / resume is tested and works.
14
15 Signed-off-by: Andy Green <andy@warmcat.com>
16 ---
17 arch/arm/mach-s3c2440/Kconfig | 7 +
18 arch/arm/mach-s3c2440/Makefile | 1 +
19 arch/arm/mach-s3c2440/fiq_c_isr.c | 250 ++++++++++++++++++++++++++
20 arch/arm/mach-s3c2440/fiq_c_isr.h | 64 +++++++
21 arch/arm/mach-s3c2440/mach-gta02.c | 22 +++
22 arch/arm/plat-s3c24xx/irq.c | 32 +++-
23 include/asm-arm/arch-s3c2410/fiq_ipc_gta02.h | 28 +++
24 include/asm-arm/plat-s3c24xx/irq.h | 20 ++
25 8 files changed, 422 insertions(+), 2 deletions(-)
26 create mode 100644 arch/arm/mach-s3c2440/fiq_c_isr.c
27 create mode 100644 arch/arm/mach-s3c2440/fiq_c_isr.h
28 create mode 100644 include/asm-arm/arch-s3c2410/fiq_ipc_gta02.h
29
30 diff --git a/arch/arm/mach-s3c2440/Kconfig b/arch/arm/mach-s3c2440/Kconfig
31 index 6b317d1..3015aaf 100644
32 --- a/arch/arm/mach-s3c2440/Kconfig
33 +++ b/arch/arm/mach-s3c2440/Kconfig
34 @@ -22,6 +22,13 @@ config S3C2440_DMA
35 help
36 Support for S3C2440 specific DMA code5A
37
38 +config S3C2440_C_FIQ
39 + bool "FIQ ISR support in C"
40 + depends on ARCH_S3C2410
41 + select FIQ
42 + help
43 + Support for S3C2440 FIQ support in C -- see
44 + ./arch/arm/macs3c2440/fiq_c_isr.c
45
46 menu "S3C2440 Machines"
47
48 diff --git a/arch/arm/mach-s3c2440/Makefile b/arch/arm/mach-s3c2440/Makefile
49 index 1a4defd..4932232 100644
50 --- a/arch/arm/mach-s3c2440/Makefile
51 +++ b/arch/arm/mach-s3c2440/Makefile
52 @@ -13,6 +13,7 @@ obj-$(CONFIG_CPU_S3C2440) += s3c2440.o dsc.o
53 obj-$(CONFIG_CPU_S3C2440) += irq.o
54 obj-$(CONFIG_CPU_S3C2440) += clock.o
55 obj-$(CONFIG_S3C2440_DMA) += dma.o
56 +obj-$(CONFIG_S3C2440_C_FIQ) += fiq_c_isr.o
57
58 # Machine support
59
60 diff --git a/arch/arm/mach-s3c2440/fiq_c_isr.c b/arch/arm/mach-s3c2440/fiq_c_isr.c
61 new file mode 100644
62 index 0000000..12f4527
63 --- /dev/null
64 +++ b/arch/arm/mach-s3c2440/fiq_c_isr.c
65 @@ -0,0 +1,250 @@
66 +/*
67 + * Copyright 2007 Andy Green <andy@warmcat.com>
68 + * S3C modfifications
69 + * Copyright 2008 Andy Green <andy@openmoko.com>
70 + */
71 +
72 +#include <linux/module.h>
73 +#include <linux/kernel.h>
74 +#include <asm/hardware.h>
75 +#include <asm/fiq.h>
76 +#include "fiq_c_isr.h"
77 +#include <linux/sysfs.h>
78 +#include <linux/device.h>
79 +#include <linux/platform_device.h>
80 +
81 +#include <asm/io.h>
82 +
83 +#include <asm/plat-s3c24xx/cpu.h>
84 +#include <asm/plat-s3c24xx/irq.h>
85 +
86 +/*
87 + * Major Caveats for using FIQ
88 + * ---------------------------
89 + *
90 + * 1) it CANNOT touch any vmalloc()'d memory, only memory
91 + * that was kmalloc()'d. Static allocations in the monolithic kernel
92 + * are kmalloc()'d so they are okay. You can touch memory-mapped IO, but
93 + * the pointer for it has to have been stored in kmalloc'd memory. The
94 + * reason for this is simple: every now and then Linux turns off interrupts
95 + * and reorders the paging tables. If a FIQ happens during this time, the
96 + * virtual memory space can be partly or entirely disordered or missing.
97 + *
98 + * 2) Because vmalloc() is used when a module is inserted, THIS FIQ
99 + * ISR HAS TO BE IN THE MONOLITHIC KERNEL, not a module. But the way
100 + * it is set up, you can all to enable and disable it from your module
101 + * and intercommunicate with it through struct fiq_ipc
102 + * fiq_ipc which you can define in
103 + * asm/archfiq_ipc_type.h. The reason is the same as above, a
104 + * FIQ could happen while even the ISR is not present in virtual memory
105 + * space due to pagetables being changed at the time.
106 + *
107 + * 3) You can't call any Linux API code except simple macros
108 + * - understand that FIQ can come in at any time, no matter what
109 + * state of undress the kernel may privately be in, thinking it
110 + * locked the door by turning off interrupts... FIQ is an
111 + * unstoppable monster force (which is its value)
112 + * - they are not vmalloc()'d memory safe
113 + * - they might do crazy stuff like sleep: FIQ pisses fire and
114 + * is not interested in 'sleep' that the weak seem to need
115 + * - calling APIs from FIQ can re-enter un-renterable things
116 + * - summary: you cannot interoperate with linux APIs directly in the FIQ ISR
117 + *
118 + * If you follow these rules, it is fantastic, an extremely powerful, solid,
119 + * genuine hard realtime feature.
120 + *
121 + */
122 +
123 +/* more than enough to cover our jump instruction to the isr */
124 +#define SIZEOF_FIQ_JUMP 8
125 +/* more than enough to cover s3c2440_fiq_isr() in 4K blocks */
126 +#define SIZEOF_FIQ_ISR 0x2000
127 +/* increase the size of the stack that is active during FIQ as needed */
128 +static u8 u8aFiqStack[4096];
129 +
130 +/* only one FIQ ISR possible, okay to do these here */
131 +u32 _fiq_ack_mask; /* used by isr exit define */
132 +unsigned long _fiq_count_fiqs; /* used by isr exit define */
133 +static int _fiq_irq; /* private ; irq index we were started with, or 0 */
134 +
135 +/* this function must live in the monolithic kernel somewhere! A module is
136 + * NOT good enough!
137 + */
138 +extern void __attribute__ ((naked)) s3c2440_fiq_isr(void);
139 +
140 +/* this is copied into the hard FIQ vector during init */
141 +
142 +static void __attribute__ ((naked)) s3c2440_FIQ_Branch(void)
143 +{
144 + asm __volatile__ (
145 + "mov pc, r8 ; "
146 + );
147 +}
148 +
149 +/* sysfs */
150 +
151 +static ssize_t show_count(struct device *dev, struct device_attribute *attr,
152 + char *buf)
153 +{
154 + return sprintf(buf, "%ld\n", _fiq_count_fiqs);
155 +}
156 +
157 +static DEVICE_ATTR(count, 0444, show_count, NULL);
158 +
159 +static struct attribute *s3c2440_fiq_sysfs_entries[] = {
160 + &dev_attr_count.attr,
161 + NULL
162 +};
163 +
164 +static struct attribute_group s3c2440_fiq_attr_group = {
165 + .name = "fiq",
166 + .attrs = s3c2440_fiq_sysfs_entries,
167 +};
168 +
169 +/*
170 + * call this from your kernel module to set up the FIQ ISR to service FIQs,
171 + * You need to have configured your FIQ input pin before anything will happen
172 + *
173 + * call it with, eg, IRQ_TIMER3 from asm-arm/arch-s3c2410/irqs.h
174 + *
175 + * you still need to clear the source interrupt in S3C2410_INTMSK to get
176 + * anything good happening
177 + */
178 +static void fiq_init_irq_source(int irq_index_fiq)
179 +{
180 + if (!irq_index_fiq) /* no interrupt */
181 + return;
182 +
183 + printk(KERN_INFO"Enabling FIQ using int idx %d\n",
184 + irq_index_fiq - S3C2410_CPUIRQ_OFFSET);
185 + local_fiq_disable();
186 +
187 + _fiq_irq = irq_index_fiq;
188 + _fiq_ack_mask = 1 << (irq_index_fiq - S3C2410_CPUIRQ_OFFSET);
189 +
190 + /* let our selected interrupt be a magic FIQ interrupt */
191 + __raw_writel(_fiq_ack_mask, S3C2410_INTMOD);
192 +
193 + /* it's ready to go as soon as we unmask the source in S3C2410_INTMSK */
194 + local_fiq_enable();
195 +}
196 +
197 +
198 +/* call this from your kernel module to disable generation of FIQ actions */
199 +static void fiq_disable_irq_source(void)
200 +{
201 + /* nothing makes FIQ any more */
202 + __raw_writel(0, S3C2410_INTMOD);
203 + local_fiq_disable();
204 + _fiq_irq = 0; /* no active source interrupt now either */
205 +}
206 +
207 +/* this starts FIQ timer events... they continue until the FIQ ISR sees that
208 + * its work is done and it turns off the timer. After setting up the fiq_ipc
209 + * struct with new work, you call this to start FIQ timer actions up again.
210 + * Only the FIQ ISR decides when it is done and controls turning off the
211 + * timer events.
212 + */
213 +void fiq_kick(void)
214 +{
215 + unsigned long flags;
216 +
217 + /* we have to take care about FIQ because this modification is
218 + * non-atomic, FIQ could come in after the read and before the
219 + * writeback and its changes to the register would be lost
220 + * (platform INTMSK mod code is taken care of already)
221 + */
222 + local_save_flags(flags);
223 + local_fiq_disable();
224 + __raw_writel(__raw_readl(S3C2410_INTMSK) &
225 + ~(1 << (_fiq_irq - S3C2410_CPUIRQ_OFFSET)),
226 + S3C2410_INTMSK);
227 + local_irq_restore(flags);
228 +}
229 +EXPORT_SYMBOL_GPL(fiq_kick);
230 +
231 +
232 +
233 +static int __init sc32440_fiq_probe(struct platform_device *pdev)
234 +{
235 + struct resource *r = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
236 +
237 + if (!r)
238 + return -EIO;
239 + /* configure for the interrupt we are meant to use */
240 + fiq_init_irq_source(r->start);
241 +
242 + return sysfs_create_group(&pdev->dev.kobj, &s3c2440_fiq_attr_group);
243 +}
244 +
245 +static int sc32440_fiq_remove(struct platform_device *pdev)
246 +{
247 + fiq_disable_irq_source();
248 + sysfs_remove_group(&pdev->dev.kobj, &s3c2440_fiq_attr_group);
249 + return 0;
250 +}
251 +
252 +static void fiq_set_vector_and_regs(void)
253 +{
254 + struct pt_regs regs;
255 +
256 + /* prep the special FIQ mode regs */
257 + memset(&regs, 0, sizeof(regs));
258 + regs.ARM_r8 = (unsigned long)s3c2440_fiq_isr;
259 + regs.ARM_sp = (unsigned long)u8aFiqStack + sizeof(u8aFiqStack) - 4;
260 + /* set up the special FIQ-mode-only registers from our regs */
261 + set_fiq_regs(&regs);
262 + /* copy our jump to the real ISR into the hard vector address */
263 + set_fiq_handler(s3c2440_FIQ_Branch, SIZEOF_FIQ_JUMP);
264 +}
265 +
266 +#ifdef CONFIG_PM
267 +static int sc32440_fiq_suspend(struct platform_device *pdev, pm_message_t state)
268 +{
269 + /* nothing makes FIQ any more */
270 + __raw_writel(0, S3C2410_INTMOD);
271 + local_fiq_disable();
272 +
273 + return 0;
274 +}
275 +
276 +static int sc32440_fiq_resume(struct platform_device *pdev)
277 +{
278 + fiq_set_vector_and_regs();
279 + fiq_init_irq_source(_fiq_irq);
280 + return 0;
281 +}
282 +#else
283 +#define sc32440_fiq_suspend NULL
284 +#define sc32440_fiq_resume NULL
285 +#endif
286 +
287 +static struct platform_driver sc32440_fiq_driver = {
288 + .driver = {
289 + .name = "sc32440_fiq",
290 + .owner = THIS_MODULE,
291 + },
292 +
293 + .probe = sc32440_fiq_probe,
294 + .remove = __devexit_p(sc32440_fiq_remove),
295 + .suspend = sc32440_fiq_suspend,
296 + .resume = sc32440_fiq_resume,
297 +};
298 +
299 +static int __init sc32440_fiq_init(void)
300 +{
301 + fiq_set_vector_and_regs();
302 +
303 + return platform_driver_register(&sc32440_fiq_driver);
304 +}
305 +
306 +static void __exit sc32440_fiq_exit(void)
307 +{
308 + fiq_disable_irq_source();
309 +}
310 +
311 +MODULE_AUTHOR("Andy Green <andy@openmoko.com>");
312 +MODULE_LICENSE("GPL");
313 +
314 +module_init(sc32440_fiq_init);
315 +module_exit(sc32440_fiq_exit);
316 diff --git a/arch/arm/mach-s3c2440/fiq_c_isr.h b/arch/arm/mach-s3c2440/fiq_c_isr.h
317 new file mode 100644
318 index 0000000..f08740e
319 --- /dev/null
320 +++ b/arch/arm/mach-s3c2440/fiq_c_isr.h
321 @@ -0,0 +1,64 @@
322 +#ifndef _LINUX_FIQ_C_ISR_H
323 +#define _LINUX_FIQ_C_ISR_H
324 +
325 +#include <asm/arch-s3c2410/regs-irq.h>
326 +
327 +extern unsigned long _fiq_count_fiqs;
328 +extern u32 _fiq_ack_mask;
329 +
330 +/* This CANNOT be implemented in a module -- it has to be used in code
331 + * included in the monolithic kernel
332 + */
333 +
334 +#define FIQ_HANDLER_START() \
335 +void __attribute__ ((naked)) s3c2440_fiq_isr(void) \
336 +{\
337 + /*\
338 + * you can declare local vars here, take care to set the frame size\
339 + * below accordingly if there are more than a few dozen bytes of them\
340 + */\
341 +
342 +/* stick your locals here :-)
343 + * Do NOT initialize them here! define them and initialize them after
344 + * FIQ_HANDLER_ENTRY() is done.
345 + */
346 +
347 +#define FIQ_HANDLER_ENTRY(LOCALS, FRAME) \
348 + const int _FIQ_FRAME_SIZE = FRAME; \
349 + /* entry takes care to store registers we will be treading on here */\
350 + asm __volatile__ (\
351 + "mov ip, sp ;"\
352 + /* stash FIQ and r0-r8 normal regs */\
353 + "stmdb sp!, {r0-r12, lr};"\
354 + /* allow SP to get some space */\
355 + "sub sp, sp, %1 ;"\
356 + /* !! THIS SETS THE FRAME, adjust to > sizeof locals */\
357 + "sub fp, sp, %0 ;"\
358 + :\
359 + : "rI" (LOCALS), "rI" (FRAME)\
360 + :"r9"\
361 + );
362 +
363 +/* stick your ISR code here and then end with... */
364 +
365 +#define FIQ_HANDLER_END() \
366 + _fiq_count_fiqs++;\
367 + __raw_writel(_fiq_ack_mask, S3C2410_SRCPND);\
368 +\
369 + /* exit back to normal mode restoring everything */\
370 + asm __volatile__ (\
371 + /* pop our allocation */\
372 + "add sp, sp, %0 ;"\
373 + /* return FIQ regs back to pristine state\
374 + * and get normal regs back\
375 + */\
376 + "ldmia sp!, {r0-r12, lr};"\
377 +\
378 + /* return */\
379 + "subs pc, lr, #4;"\
380 + : \
381 + : "rI" (_FIQ_FRAME_SIZE) \
382 + );\
383 +}
384 +
385 +#endif /* _LINUX_FIQ_C_ISR_H */
386 diff --git a/arch/arm/mach-s3c2440/mach-gta02.c b/arch/arm/mach-s3c2440/mach-gta02.c
387 index 46acede..0bdd0e0 100644
388 --- a/arch/arm/mach-s3c2440/mach-gta02.c
389 +++ b/arch/arm/mach-s3c2440/mach-gta02.c
390 @@ -78,9 +78,31 @@
391
392 #include <linux/glamofb.h>
393
394 +#include <asm/arch/fiq_ipc_gta02.h>
395 +#include "fiq_c_isr.h"
396 +
397 /* arbitrates which sensor IRQ owns the shared SPI bus */
398 static spinlock_t motion_irq_lock;
399
400 +/* define FIQ IPC struct */
401 +/*
402 + * contains stuff FIQ ISR modifies and normal kernel code can see and use
403 + * this is defined in <asm/arch/fiq_ipc_gta02.h>, you should customize
404 + * the definition in there and include the same definition in your kernel
405 + * module that wants to interoperate with your FIQ code.
406 + */
407 +struct fiq_ipc fiq_ipc;
408 +EXPORT_SYMBOL(fiq_ipc);
409 +
410 +/* define FIQ ISR */
411 +
412 +FIQ_HANDLER_START()
413 +/* define your locals here -- no initializers though */
414 +FIQ_HANDLER_ENTRY(256, 512)
415 +/* Your ISR here :-) */
416 +FIQ_HANDLER_END()
417 +
418 +
419 static struct map_desc gta02_iodesc[] __initdata = {
420 {
421 .virtual = 0xe0000000,
422 diff --git a/arch/arm/plat-s3c24xx/irq.c b/arch/arm/plat-s3c24xx/irq.c
423 index ae2c5d7..9887db1 100644
424 --- a/arch/arm/plat-s3c24xx/irq.c
425 +++ b/arch/arm/plat-s3c24xx/irq.c
426 @@ -133,12 +133,20 @@ static void
427 s3c_irq_mask(unsigned int irqno)
428 {
429 unsigned long mask;
430 -
431 +#ifdef CONFIG_S3C2440_C_FIQ
432 + unsigned long flags;
433 +#endif
434 irqno -= IRQ_EINT0;
435 -
436 +#ifdef CONFIG_S3C2440_C_FIQ
437 + local_save_flags(flags);
438 + local_fiq_disable();
439 +#endif
440 mask = __raw_readl(S3C2410_INTMSK);
441 mask |= 1UL << irqno;
442 __raw_writel(mask, S3C2410_INTMSK);
443 +#ifdef CONFIG_S3C2440_C_FIQ
444 + local_irq_restore(flags);
445 +#endif
446 }
447
448 static inline void
449 @@ -155,9 +163,19 @@ s3c_irq_maskack(unsigned int irqno)
450 {
451 unsigned long bitval = 1UL << (irqno - IRQ_EINT0);
452 unsigned long mask;
453 +#ifdef CONFIG_S3C2440_C_FIQ
454 + unsigned long flags;
455 +#endif
456
457 +#ifdef CONFIG_S3C2440_C_FIQ
458 + local_save_flags(flags);
459 + local_fiq_disable();
460 +#endif
461 mask = __raw_readl(S3C2410_INTMSK);
462 __raw_writel(mask|bitval, S3C2410_INTMSK);
463 +#ifdef CONFIG_S3C2440_C_FIQ
464 + local_irq_restore(flags);
465 +#endif
466
467 __raw_writel(bitval, S3C2410_SRCPND);
468 __raw_writel(bitval, S3C2410_INTPND);
469 @@ -168,15 +186,25 @@ static void
470 s3c_irq_unmask(unsigned int irqno)
471 {
472 unsigned long mask;
473 +#ifdef CONFIG_S3C2440_C_FIQ
474 + unsigned long flags;
475 +#endif
476
477 if (irqno != IRQ_TIMER4 && irqno != IRQ_EINT8t23)
478 irqdbf2("s3c_irq_unmask %d\n", irqno);
479
480 irqno -= IRQ_EINT0;
481
482 +#ifdef CONFIG_S3C2440_C_FIQ
483 + local_save_flags(flags);
484 + local_fiq_disable();
485 +#endif
486 mask = __raw_readl(S3C2410_INTMSK);
487 mask &= ~(1UL << irqno);
488 __raw_writel(mask, S3C2410_INTMSK);
489 +#ifdef CONFIG_S3C2440_C_FIQ
490 + local_irq_restore(flags);
491 +#endif
492 }
493
494 struct irq_chip s3c_irq_level_chip = {
495 diff --git a/include/asm-arm/arch-s3c2410/fiq_ipc_gta02.h b/include/asm-arm/arch-s3c2410/fiq_ipc_gta02.h
496 new file mode 100644
497 index 0000000..341f2bb
498 --- /dev/null
499 +++ b/include/asm-arm/arch-s3c2410/fiq_ipc_gta02.h
500 @@ -0,0 +1,28 @@
501 +#ifndef _LINUX_FIQ_IPC_H
502 +#define _LINUX_FIQ_IPC_H
503 +
504 +/*
505 + * this defines the struct which is used to communicate between the FIQ
506 + * world and the normal linux kernel world. One of these structs is
507 + * statically defined for you in the monolithic kernel so the FIQ ISR code
508 + * can safely touch it any any time.
509 + *
510 + * You also want to include this file in your kernel module that wants to
511 + * communicate with your FIQ code. Add any kinds of vars that are used by
512 + * the FIQ ISR and the module in here.
513 + *
514 + * To get you started there is just an int that is incremented every FIQ
515 + * you can remove this when you are ready to customize, but it is useful
516 + * for testing
517 + */
518 +
519 +struct fiq_ipc {
520 + u8 u8a[0]; /* placeholder */
521 +};
522 +
523 +/* actual definition lives in arch/arm/mach-s3c2440/fiq_c_isr.c */
524 +extern struct fiq_ipc fiq_ipc;
525 +
526 +extern void fiq_kick(void); /* provoke a FIQ "immediately" */
527 +
528 +#endif /* _LINUX_FIQ_IPC_H */
529 diff --git a/include/asm-arm/plat-s3c24xx/irq.h b/include/asm-arm/plat-s3c24xx/irq.h
530 index 45746a9..bf15e1c 100644
531 --- a/include/asm-arm/plat-s3c24xx/irq.h
532 +++ b/include/asm-arm/plat-s3c24xx/irq.h
533 @@ -25,8 +25,15 @@ s3c_irqsub_mask(unsigned int irqno, unsigned int parentbit,
534 {
535 unsigned long mask;
536 unsigned long submask;
537 +#ifdef CONFIG_S3C2440_C_FIQ
538 + unsigned long flags;
539 +#endif
540
541 submask = __raw_readl(S3C2410_INTSUBMSK);
542 +#ifdef CONFIG_S3C2440_C_FIQ
543 + local_save_flags(flags);
544 + local_fiq_disable();
545 +#endif
546 mask = __raw_readl(S3C2410_INTMSK);
547
548 submask |= (1UL << (irqno - IRQ_S3CUART_RX0));
549 @@ -39,6 +46,9 @@ s3c_irqsub_mask(unsigned int irqno, unsigned int parentbit,
550
551 /* write back masks */
552 __raw_writel(submask, S3C2410_INTSUBMSK);
553 +#ifdef CONFIG_S3C2440_C_FIQ
554 + local_irq_restore(flags);
555 +#endif
556
557 }
558
559 @@ -47,8 +57,15 @@ s3c_irqsub_unmask(unsigned int irqno, unsigned int parentbit)
560 {
561 unsigned long mask;
562 unsigned long submask;
563 +#ifdef CONFIG_S3C2440_C_FIQ
564 + unsigned long flags;
565 +#endif
566
567 submask = __raw_readl(S3C2410_INTSUBMSK);
568 +#ifdef CONFIG_S3C2440_C_FIQ
569 + local_save_flags(flags);
570 + local_fiq_disable();
571 +#endif
572 mask = __raw_readl(S3C2410_INTMSK);
573
574 submask &= ~(1UL << (irqno - IRQ_S3CUART_RX0));
575 @@ -57,6 +74,9 @@ s3c_irqsub_unmask(unsigned int irqno, unsigned int parentbit)
576 /* write back masks */
577 __raw_writel(submask, S3C2410_INTSUBMSK);
578 __raw_writel(mask, S3C2410_INTMSK);
579 +#ifdef CONFIG_S3C2440_C_FIQ
580 + local_irq_restore(flags);
581 +#endif
582 }
583
584
585 --
586 1.5.6.3
587