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