entry.h 5.3 KB

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