irqflags.h 3.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196
  1. /* MN10300 IRQ flag handling
  2. *
  3. * Copyright (C) 2010 Red Hat, Inc. All Rights Reserved.
  4. * Written by David Howells (dhowells@redhat.com)
  5. *
  6. * This program is free software; you can redistribute it and/or
  7. * modify it under the terms of the GNU General Public Licence
  8. * as published by the Free Software Foundation; either version
  9. * 2 of the Licence, or (at your option) any later version.
  10. */
  11. #ifndef _ASM_IRQFLAGS_H
  12. #define _ASM_IRQFLAGS_H
  13. #include <asm/cpu-regs.h>
  14. /*
  15. * interrupt control
  16. * - "disabled": run in IM1/2
  17. * - level 0 - GDB stub
  18. * - level 1 - virtual serial DMA (if present)
  19. * - level 5 - normal interrupt priority
  20. * - level 6 - timer interrupt
  21. * - "enabled": run in IM7
  22. */
  23. #define MN10300_CLI_LEVEL (CONFIG_LINUX_CLI_LEVEL << EPSW_IM_SHIFT)
  24. #ifndef __ASSEMBLY__
  25. static inline unsigned long arch_local_save_flags(void)
  26. {
  27. unsigned long flags;
  28. asm volatile("mov epsw,%0" : "=d"(flags));
  29. return flags;
  30. }
  31. static inline void arch_local_irq_disable(void)
  32. {
  33. asm volatile(
  34. " and %0,epsw \n"
  35. " or %1,epsw \n"
  36. " nop \n"
  37. " nop \n"
  38. " nop \n"
  39. :
  40. : "i"(~EPSW_IM), "i"(EPSW_IE | MN10300_CLI_LEVEL)
  41. : "memory");
  42. }
  43. static inline unsigned long arch_local_irq_save(void)
  44. {
  45. unsigned long flags;
  46. flags = arch_local_save_flags();
  47. arch_local_irq_disable();
  48. return flags;
  49. }
  50. /*
  51. * we make sure arch_irq_enable() doesn't cause priority inversion
  52. */
  53. extern unsigned long __mn10300_irq_enabled_epsw;
  54. static inline void arch_local_irq_enable(void)
  55. {
  56. unsigned long tmp;
  57. asm volatile(
  58. " mov epsw,%0 \n"
  59. " and %1,%0 \n"
  60. " or %2,%0 \n"
  61. " mov %0,epsw \n"
  62. : "=&d"(tmp)
  63. : "i"(~EPSW_IM), "r"(__mn10300_irq_enabled_epsw)
  64. : "memory");
  65. }
  66. static inline void arch_local_irq_restore(unsigned long flags)
  67. {
  68. asm volatile(
  69. " mov %0,epsw \n"
  70. " nop \n"
  71. " nop \n"
  72. " nop \n"
  73. :
  74. : "d"(flags)
  75. : "memory", "cc");
  76. }
  77. static inline bool arch_irqs_disabled_flags(unsigned long flags)
  78. {
  79. return (flags & (EPSW_IE | EPSW_IM)) != (EPSW_IE | EPSW_IM_7);
  80. }
  81. static inline bool arch_irqs_disabled(void)
  82. {
  83. return arch_irqs_disabled_flags(arch_local_save_flags());
  84. }
  85. /*
  86. * Hook to save power by halting the CPU
  87. * - called from the idle loop
  88. * - must reenable interrupts (which takes three instruction cycles to complete)
  89. */
  90. static inline void arch_safe_halt(void)
  91. {
  92. asm volatile(
  93. " or %0,epsw \n"
  94. " nop \n"
  95. " nop \n"
  96. " bset %2,(%1) \n"
  97. :
  98. : "i"(EPSW_IE|EPSW_IM), "n"(&CPUM), "i"(CPUM_SLEEP)
  99. : "cc");
  100. }
  101. static inline void arch_local_cli(void)
  102. {
  103. asm volatile(
  104. " and %0,epsw \n"
  105. " nop \n"
  106. " nop \n"
  107. " nop \n"
  108. :
  109. : "i"(~EPSW_IE)
  110. : "memory"
  111. );
  112. }
  113. static inline unsigned long arch_local_cli_save(void)
  114. {
  115. unsigned long flags = arch_local_save_flags();
  116. arch_local_cli();
  117. return flags;
  118. }
  119. static inline void arch_local_sti(void)
  120. {
  121. asm volatile(
  122. " or %0,epsw \n"
  123. :
  124. : "i"(EPSW_IE)
  125. : "memory");
  126. }
  127. static inline void arch_local_change_intr_mask_level(unsigned long level)
  128. {
  129. asm volatile(
  130. " and %0,epsw \n"
  131. " or %1,epsw \n"
  132. :
  133. : "i"(~EPSW_IM), "i"(EPSW_IE | level)
  134. : "cc", "memory");
  135. }
  136. #else /* !__ASSEMBLY__ */
  137. #define LOCAL_SAVE_FLAGS(reg) \
  138. mov epsw,reg
  139. #define LOCAL_IRQ_DISABLE \
  140. and ~EPSW_IM,epsw; \
  141. or EPSW_IE|MN10300_CLI_LEVEL,epsw; \
  142. nop; \
  143. nop; \
  144. nop
  145. #define LOCAL_IRQ_ENABLE \
  146. or EPSW_IE|EPSW_IM_7,epsw
  147. #define LOCAL_IRQ_RESTORE(reg) \
  148. mov reg,epsw
  149. #define LOCAL_CLI_SAVE(reg) \
  150. mov epsw,reg; \
  151. and ~EPSW_IE,epsw; \
  152. nop; \
  153. nop; \
  154. nop
  155. #define LOCAL_CLI \
  156. and ~EPSW_IE,epsw; \
  157. nop; \
  158. nop; \
  159. nop
  160. #define LOCAL_STI \
  161. or EPSW_IE,epsw
  162. #define LOCAL_CHANGE_INTR_MASK_LEVEL(level) \
  163. and ~EPSW_IM,epsw; \
  164. or EPSW_IE|(level),epsw
  165. #endif /* __ASSEMBLY__ */
  166. #endif /* _ASM_IRQFLAGS_H */