aboutsummaryrefslogtreecommitdiff
path: root/arch/arm/mach-s3c2440/fiq_c_isr.h
blob: 0c45eb780ed9289df9a6f8929ec6bce610525585 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
#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;
extern int _fiq_timer_index;
extern u16 _fiq_timer_divisor;

/* 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 */