blob: 4104d5783e2c1a4ad80b633f123e7c1dc219c459 [file] [log] [blame]
Robin Getz96f10502009-09-24 14:11:24 +00001/*
2 * Copyright 2004-2009 Analog Devices Inc.
3 *
4 * Licensed under the GPL-2 or later.
5 */
6
Bryan Wu1394f032007-05-06 14:50:22 -07007#ifndef __BFIN_ENTRY_H
8#define __BFIN_ENTRY_H
9
10#include <asm/setup.h>
11#include <asm/page.h>
12
13#ifdef __ASSEMBLY__
14
15#define LFLUSH_I_AND_D 0x00000808
16#define LSIGTRAP 5
17
Bernd Schmidt0893f122008-05-07 11:41:26 +080018/*
19 * NOTE! The single-stepping code assumes that all interrupt handlers
20 * start by saving SYSCFG on the stack with their first instruction.
21 */
22
Bryan Wu1394f032007-05-06 14:50:22 -070023/* This one is used for exceptions, emulation, and NMI. It doesn't push
24 RETI and doesn't do cli. */
25#define SAVE_ALL_SYS save_context_no_interrupts
26/* This is used for all normal interrupts. It saves a minimum of registers
27 to the stack, loads the IRQ number, and jumps to common code. */
Yi Li6a01f232009-01-07 23:14:39 +080028#ifdef CONFIG_IPIPE
29# define LOAD_IPIPE_IPEND \
30 P0.l = lo(IPEND); \
31 P0.h = hi(IPEND); \
32 R1 = [P0];
33#else
34# define LOAD_IPIPE_IPEND
35#endif
Robin Getzb9a38992009-05-18 18:33:26 +000036
Robin Getzdedfd5d2009-08-26 15:54:10 +000037/*
38 * Workaround for anomalies 05000283 and 05000315
39 */
40#if ANOMALY_05000283 || ANOMALY_05000315
41# define ANOMALY_283_315_WORKAROUND(preg, dreg) \
42 cc = dreg == dreg; \
43 preg.h = HI(CHIPID); \
44 preg.l = LO(CHIPID); \
45 if cc jump 1f; \
46 dreg.l = W[preg]; \
471:
48#else
49# define ANOMALY_283_315_WORKAROUND(preg, dreg)
50#endif /* ANOMALY_05000283 || ANOMALY_05000315 */
51
Robin Getzb9a38992009-05-18 18:33:26 +000052#ifndef CONFIG_EXACT_HWERR
53/* As a debugging aid - we save IPEND when DEBUG_KERNEL is on,
54 * otherwise it is a waste of cycles.
55 */
56# ifndef CONFIG_DEBUG_KERNEL
Bryan Wu1394f032007-05-06 14:50:22 -070057#define INTERRUPT_ENTRY(N) \
58 [--sp] = SYSCFG; \
Bryan Wu1394f032007-05-06 14:50:22 -070059 [--sp] = P0; /*orig_p0*/ \
60 [--sp] = R0; /*orig_r0*/ \
61 [--sp] = (R7:0,P5:0); \
62 R0 = (N); \
Yi Li6a01f232009-01-07 23:14:39 +080063 LOAD_IPIPE_IPEND \
Bryan Wu1394f032007-05-06 14:50:22 -070064 jump __common_int_entry;
Robin Getzb9a38992009-05-18 18:33:26 +000065# else /* CONFIG_DEBUG_KERNEL */
66#define INTERRUPT_ENTRY(N) \
67 [--sp] = SYSCFG; \
68 [--sp] = P0; /*orig_p0*/ \
69 [--sp] = R0; /*orig_r0*/ \
70 [--sp] = (R7:0,P5:0); \
71 p0.l = lo(IPEND); \
72 p0.h = hi(IPEND); \
73 r1 = [p0]; \
74 R0 = (N); \
75 LOAD_IPIPE_IPEND \
76 jump __common_int_entry;
77# endif /* CONFIG_DEBUG_KERNEL */
Bryan Wu1394f032007-05-06 14:50:22 -070078
79/* For timer interrupts, we need to save IPEND, since the user_mode
Robin Getzb9a38992009-05-18 18:33:26 +000080 *macro accesses it to determine where to account time.
81 */
Bryan Wu1394f032007-05-06 14:50:22 -070082#define TIMER_INTERRUPT_ENTRY(N) \
83 [--sp] = SYSCFG; \
Bryan Wu1394f032007-05-06 14:50:22 -070084 [--sp] = P0; /*orig_p0*/ \
85 [--sp] = R0; /*orig_r0*/ \
86 [--sp] = (R7:0,P5:0); \
87 p0.l = lo(IPEND); \
88 p0.h = hi(IPEND); \
89 r1 = [p0]; \
90 R0 = (N); \
91 jump __common_int_entry;
Robin Getzb9a38992009-05-18 18:33:26 +000092#else /* CONFIG_EXACT_HWERR is defined */
93
94/* if we want hardware error to be exact, we need to do a SSYNC (which forces
95 * read/writes to complete to the memory controllers), and check to see that
96 * caused a pending HW error condition. If so, we assume it was caused by user
97 * space, by setting the same interrupt that we are in (so it goes off again)
98 * and context restore, and a RTI (without servicing anything). This should
99 * cause the pending HWERR to fire, and when that is done, this interrupt will
100 * be re-serviced properly.
101 * As you can see by the code - we actually need to do two SSYNCS - one to
102 * make sure the read/writes complete, and another to make sure the hardware
103 * error is recognized by the core.
Robin Getzdedfd5d2009-08-26 15:54:10 +0000104 *
105 * The extra nop before the SSYNC is to make sure we work around 05000244,
106 * since the 283/315 workaround includes a branch to the end
Robin Getzb9a38992009-05-18 18:33:26 +0000107 */
108#define INTERRUPT_ENTRY(N) \
Robin Getzb9a38992009-05-18 18:33:26 +0000109 [--sp] = SYSCFG; \
110 [--sp] = P0; /*orig_p0*/ \
111 [--sp] = R0; /*orig_r0*/ \
112 [--sp] = (R7:0,P5:0); \
113 R1 = ASTAT; \
Robin Getzdedfd5d2009-08-26 15:54:10 +0000114 ANOMALY_283_315_WORKAROUND(p0, r0) \
Robin Getzb9a38992009-05-18 18:33:26 +0000115 P0.L = LO(ILAT); \
116 P0.H = HI(ILAT); \
Robin Getzdedfd5d2009-08-26 15:54:10 +0000117 NOP; \
118 SSYNC; \
119 SSYNC; \
Robin Getzb9a38992009-05-18 18:33:26 +0000120 R0 = [P0]; \
121 CC = BITTST(R0, EVT_IVHW_P); \
122 IF CC JUMP 1f; \
123 ASTAT = R1; \
124 p0.l = lo(IPEND); \
125 p0.h = hi(IPEND); \
126 r1 = [p0]; \
127 R0 = (N); \
128 LOAD_IPIPE_IPEND \
129 jump __common_int_entry; \
1301: ASTAT = R1; \
131 RAISE N; \
132 (R7:0, P5:0) = [SP++]; \
133 SP += 0x8; \
134 SYSCFG = [SP++]; \
135 CSYNC; \
136 RTI;
137
138#define TIMER_INTERRUPT_ENTRY(N) \
Robin Getzb9a38992009-05-18 18:33:26 +0000139 [--sp] = SYSCFG; \
140 [--sp] = P0; /*orig_p0*/ \
141 [--sp] = R0; /*orig_r0*/ \
142 [--sp] = (R7:0,P5:0); \
143 R1 = ASTAT; \
Robin Getzdedfd5d2009-08-26 15:54:10 +0000144 ANOMALY_283_315_WORKAROUND(p0, r0) \
Robin Getzb9a38992009-05-18 18:33:26 +0000145 P0.L = LO(ILAT); \
146 P0.H = HI(ILAT); \
Robin Getzdedfd5d2009-08-26 15:54:10 +0000147 NOP; \
148 SSYNC; \
149 SSYNC; \
Robin Getzb9a38992009-05-18 18:33:26 +0000150 R0 = [P0]; \
151 CC = BITTST(R0, EVT_IVHW_P); \
152 IF CC JUMP 1f; \
153 ASTAT = R1; \
154 p0.l = lo(IPEND); \
155 p0.h = hi(IPEND); \
156 r1 = [p0]; \
157 R0 = (N); \
158 jump __common_int_entry; \
1591: ASTAT = R1; \
160 RAISE N; \
161 (R7:0, P5:0) = [SP++]; \
162 SP += 0x8; \
163 SYSCFG = [SP++]; \
164 CSYNC; \
165 RTI;
166#endif /* CONFIG_EXACT_HWERR */
Bryan Wu1394f032007-05-06 14:50:22 -0700167
168/* This one pushes RETI without using CLI. Interrupts are enabled. */
169#define SAVE_CONTEXT_SYSCALL save_context_syscall
170#define SAVE_CONTEXT save_context_with_interrupts
Bernd Schmidtdbdf20d2009-01-07 23:14:38 +0800171#define SAVE_CONTEXT_CPLB save_context_cplb
Bryan Wu1394f032007-05-06 14:50:22 -0700172
173#define RESTORE_ALL_SYS restore_context_no_interrupts
174#define RESTORE_CONTEXT restore_context_with_interrupts
Bernd Schmidtdbdf20d2009-01-07 23:14:38 +0800175#define RESTORE_CONTEXT_CPLB restore_context_cplb
Bryan Wu1394f032007-05-06 14:50:22 -0700176
177#endif /* __ASSEMBLY__ */
178#endif /* __BFIN_ENTRY_H */