Full support for Ginger Console
[linux-ginger.git] / arch / blackfin / include / asm / entry.h
bloba6886f6e48194027f529a0380feb618eb1f2abcd
1 /*
2 * Copyright 2004-2009 Analog Devices Inc.
4 * Licensed under the GPL-2 or later.
5 */
7 #ifndef __BFIN_ENTRY_H
8 #define __BFIN_ENTRY_H
10 #include <asm/setup.h>
11 #include <asm/page.h>
13 #ifdef __ASSEMBLY__
15 #define LFLUSH_I_AND_D 0x00000808
16 #define LSIGTRAP 5
18 /* process bits for task_struct.flags */
19 #define PF_TRACESYS_OFF 3
20 #define PF_TRACESYS_BIT 5
21 #define PF_PTRACED_OFF 3
22 #define PF_PTRACED_BIT 4
23 #define PF_DTRACE_OFF 1
24 #define PF_DTRACE_BIT 5
27 * NOTE! The single-stepping code assumes that all interrupt handlers
28 * start by saving SYSCFG on the stack with their first instruction.
31 /* This one is used for exceptions, emulation, and NMI. It doesn't push
32 RETI and doesn't do cli. */
33 #define SAVE_ALL_SYS save_context_no_interrupts
34 /* This is used for all normal interrupts. It saves a minimum of registers
35 to the stack, loads the IRQ number, and jumps to common code. */
36 #ifdef CONFIG_IPIPE
37 # define LOAD_IPIPE_IPEND \
38 P0.l = lo(IPEND); \
39 P0.h = hi(IPEND); \
40 R1 = [P0];
41 #else
42 # define LOAD_IPIPE_IPEND
43 #endif
46 * Workaround for anomalies 05000283 and 05000315
48 #if ANOMALY_05000283 || ANOMALY_05000315
49 # define ANOMALY_283_315_WORKAROUND(preg, dreg) \
50 cc = dreg == dreg; \
51 preg.h = HI(CHIPID); \
52 preg.l = LO(CHIPID); \
53 if cc jump 1f; \
54 dreg.l = W[preg]; \
56 #else
57 # define ANOMALY_283_315_WORKAROUND(preg, dreg)
58 #endif /* ANOMALY_05000283 || ANOMALY_05000315 */
60 #ifndef CONFIG_EXACT_HWERR
61 /* As a debugging aid - we save IPEND when DEBUG_KERNEL is on,
62 * otherwise it is a waste of cycles.
64 # ifndef CONFIG_DEBUG_KERNEL
65 #define INTERRUPT_ENTRY(N) \
66 [--sp] = SYSCFG; \
67 [--sp] = P0; /*orig_p0*/ \
68 [--sp] = R0; /*orig_r0*/ \
69 [--sp] = (R7:0,P5:0); \
70 R0 = (N); \
71 LOAD_IPIPE_IPEND \
72 jump __common_int_entry;
73 # else /* CONFIG_DEBUG_KERNEL */
74 #define INTERRUPT_ENTRY(N) \
75 [--sp] = SYSCFG; \
76 [--sp] = P0; /*orig_p0*/ \
77 [--sp] = R0; /*orig_r0*/ \
78 [--sp] = (R7:0,P5:0); \
79 p0.l = lo(IPEND); \
80 p0.h = hi(IPEND); \
81 r1 = [p0]; \
82 R0 = (N); \
83 LOAD_IPIPE_IPEND \
84 jump __common_int_entry;
85 # endif /* CONFIG_DEBUG_KERNEL */
87 /* For timer interrupts, we need to save IPEND, since the user_mode
88 *macro accesses it to determine where to account time.
90 #define TIMER_INTERRUPT_ENTRY(N) \
91 [--sp] = SYSCFG; \
92 [--sp] = P0; /*orig_p0*/ \
93 [--sp] = R0; /*orig_r0*/ \
94 [--sp] = (R7:0,P5:0); \
95 p0.l = lo(IPEND); \
96 p0.h = hi(IPEND); \
97 r1 = [p0]; \
98 R0 = (N); \
99 jump __common_int_entry;
100 #else /* CONFIG_EXACT_HWERR is defined */
102 /* if we want hardware error to be exact, we need to do a SSYNC (which forces
103 * read/writes to complete to the memory controllers), and check to see that
104 * caused a pending HW error condition. If so, we assume it was caused by user
105 * space, by setting the same interrupt that we are in (so it goes off again)
106 * and context restore, and a RTI (without servicing anything). This should
107 * cause the pending HWERR to fire, and when that is done, this interrupt will
108 * be re-serviced properly.
109 * As you can see by the code - we actually need to do two SSYNCS - one to
110 * make sure the read/writes complete, and another to make sure the hardware
111 * error is recognized by the core.
113 * The extra nop before the SSYNC is to make sure we work around 05000244,
114 * since the 283/315 workaround includes a branch to the end
116 #define INTERRUPT_ENTRY(N) \
117 [--sp] = SYSCFG; \
118 [--sp] = P0; /*orig_p0*/ \
119 [--sp] = R0; /*orig_r0*/ \
120 [--sp] = (R7:0,P5:0); \
121 R1 = ASTAT; \
122 ANOMALY_283_315_WORKAROUND(p0, r0) \
123 P0.L = LO(ILAT); \
124 P0.H = HI(ILAT); \
125 NOP; \
126 SSYNC; \
127 SSYNC; \
128 R0 = [P0]; \
129 CC = BITTST(R0, EVT_IVHW_P); \
130 IF CC JUMP 1f; \
131 ASTAT = R1; \
132 p0.l = lo(IPEND); \
133 p0.h = hi(IPEND); \
134 r1 = [p0]; \
135 R0 = (N); \
136 LOAD_IPIPE_IPEND \
137 jump __common_int_entry; \
138 1: ASTAT = R1; \
139 RAISE N; \
140 (R7:0, P5:0) = [SP++]; \
141 SP += 0x8; \
142 SYSCFG = [SP++]; \
143 CSYNC; \
144 RTI;
146 #define TIMER_INTERRUPT_ENTRY(N) \
147 [--sp] = SYSCFG; \
148 [--sp] = P0; /*orig_p0*/ \
149 [--sp] = R0; /*orig_r0*/ \
150 [--sp] = (R7:0,P5:0); \
151 R1 = ASTAT; \
152 ANOMALY_283_315_WORKAROUND(p0, r0) \
153 P0.L = LO(ILAT); \
154 P0.H = HI(ILAT); \
155 NOP; \
156 SSYNC; \
157 SSYNC; \
158 R0 = [P0]; \
159 CC = BITTST(R0, EVT_IVHW_P); \
160 IF CC JUMP 1f; \
161 ASTAT = R1; \
162 p0.l = lo(IPEND); \
163 p0.h = hi(IPEND); \
164 r1 = [p0]; \
165 R0 = (N); \
166 jump __common_int_entry; \
167 1: ASTAT = R1; \
168 RAISE N; \
169 (R7:0, P5:0) = [SP++]; \
170 SP += 0x8; \
171 SYSCFG = [SP++]; \
172 CSYNC; \
173 RTI;
174 #endif /* CONFIG_EXACT_HWERR */
176 /* This one pushes RETI without using CLI. Interrupts are enabled. */
177 #define SAVE_CONTEXT_SYSCALL save_context_syscall
178 #define SAVE_CONTEXT save_context_with_interrupts
179 #define SAVE_CONTEXT_CPLB save_context_cplb
181 #define RESTORE_ALL_SYS restore_context_no_interrupts
182 #define RESTORE_CONTEXT restore_context_with_interrupts
183 #define RESTORE_CONTEXT_CPLB restore_context_cplb
185 #endif /* __ASSEMBLY__ */
186 #endif /* __BFIN_ENTRY_H */