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