diff options
author | mokopatches <mokopatches@openmoko.org> | 2008-11-19 17:03:18 +0000 |
---|---|---|
committer | warmcat <andy@warmcat.com> | 2008-11-19 17:03:18 +0000 |
commit | 8fd8547b742a608695823e38ca7cfc531d50f341 (patch) | |
tree | 05961aeb23ba98de4bb8d42b4552147be3f3060a /arch/arm/mach-s3c2440/fiq_c_isr.h | |
parent | ce82f1353a5b9e1466369106ba7be5eca86c5e49 (diff) |
introduce-fiq-basis.patch
Adds a C-based FIQ ISR which is very convenient (and unusual --
normally you have to do FIQ ISR in assembler only).
Based on my article:
http://warmcat.com/_wp/2007/09/17/at91rm9200-fiq-faq-and-simple-example-code-patch/
Implemented as a platform device and driver.
Suspend / resume is tested and works.
Signed-off-by: Andy Green <andy@warmcat.com>
Diffstat (limited to 'arch/arm/mach-s3c2440/fiq_c_isr.h')
-rw-r--r-- | arch/arm/mach-s3c2440/fiq_c_isr.h | 64 |
1 files changed, 64 insertions, 0 deletions
diff --git a/arch/arm/mach-s3c2440/fiq_c_isr.h b/arch/arm/mach-s3c2440/fiq_c_isr.h new file mode 100644 index 00000000000..f08740ee8d3 --- /dev/null +++ b/arch/arm/mach-s3c2440/fiq_c_isr.h @@ -0,0 +1,64 @@ +#ifndef _LINUX_FIQ_C_ISR_H +#define _LINUX_FIQ_C_ISR_H + +#include <asm/arch-s3c2410/regs-irq.h> + +extern unsigned long _fiq_count_fiqs; +extern u32 _fiq_ack_mask; + +/* This CANNOT be implemented in a module -- it has to be used in code + * included in the monolithic kernel + */ + +#define FIQ_HANDLER_START() \ +void __attribute__ ((naked)) s3c2440_fiq_isr(void) \ +{\ + /*\ + * you can declare local vars here, take care to set the frame size\ + * below accordingly if there are more than a few dozen bytes of them\ + */\ + +/* stick your locals here :-) + * Do NOT initialize them here! define them and initialize them after + * FIQ_HANDLER_ENTRY() is done. + */ + +#define FIQ_HANDLER_ENTRY(LOCALS, FRAME) \ + const int _FIQ_FRAME_SIZE = FRAME; \ + /* entry takes care to store registers we will be treading on here */\ + asm __volatile__ (\ + "mov ip, sp ;"\ + /* stash FIQ and r0-r8 normal regs */\ + "stmdb sp!, {r0-r12, lr};"\ + /* allow SP to get some space */\ + "sub sp, sp, %1 ;"\ + /* !! THIS SETS THE FRAME, adjust to > sizeof locals */\ + "sub fp, sp, %0 ;"\ + :\ + : "rI" (LOCALS), "rI" (FRAME)\ + :"r9"\ + ); + +/* stick your ISR code here and then end with... */ + +#define FIQ_HANDLER_END() \ + _fiq_count_fiqs++;\ + __raw_writel(_fiq_ack_mask, S3C2410_SRCPND);\ +\ + /* exit back to normal mode restoring everything */\ + asm __volatile__ (\ + /* pop our allocation */\ + "add sp, sp, %0 ;"\ + /* return FIQ regs back to pristine state\ + * and get normal regs back\ + */\ + "ldmia sp!, {r0-r12, lr};"\ +\ + /* return */\ + "subs pc, lr, #4;"\ + : \ + : "rI" (_FIQ_FRAME_SIZE) \ + );\ +} + +#endif /* _LINUX_FIQ_C_ISR_H */ |