irqflags.h 4.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216
  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. #ifndef __ASSEMBLY__
  15. #include <linux/smp.h>
  16. #endif
  17. /*
  18. * interrupt control
  19. * - "disabled": run in IM1/2
  20. * - level 0 - kernel debugger
  21. * - level 1 - virtual serial DMA (if present)
  22. * - level 5 - normal interrupt priority
  23. * - level 6 - timer interrupt
  24. * - "enabled": run in IM7
  25. */
  26. #define MN10300_CLI_LEVEL (CONFIG_LINUX_CLI_LEVEL << EPSW_IM_SHIFT)
  27. #ifndef __ASSEMBLY__
  28. static inline unsigned long arch_local_save_flags(void)
  29. {
  30. unsigned long flags;
  31. asm volatile("mov epsw,%0" : "=d"(flags));
  32. return flags;
  33. }
  34. static inline void arch_local_irq_disable(void)
  35. {
  36. asm volatile(
  37. " and %0,epsw \n"
  38. " or %1,epsw \n"
  39. " nop \n"
  40. " nop \n"
  41. " nop \n"
  42. :
  43. : "i"(~EPSW_IM), "i"(EPSW_IE | MN10300_CLI_LEVEL)
  44. : "memory");
  45. }
  46. static inline unsigned long arch_local_irq_save(void)
  47. {
  48. unsigned long flags;
  49. flags = arch_local_save_flags();
  50. arch_local_irq_disable();
  51. return flags;
  52. }
  53. /*
  54. * we make sure arch_irq_enable() doesn't cause priority inversion
  55. */
  56. extern unsigned long __mn10300_irq_enabled_epsw[];
  57. static inline void arch_local_irq_enable(void)
  58. {
  59. unsigned long tmp;
  60. int cpu = raw_smp_processor_id();
  61. asm volatile(
  62. " mov epsw,%0 \n"
  63. " and %1,%0 \n"
  64. " or %2,%0 \n"
  65. " mov %0,epsw \n"
  66. : "=&d"(tmp)
  67. : "i"(~EPSW_IM), "r"(__mn10300_irq_enabled_epsw[cpu])
  68. : "memory", "cc");
  69. }
  70. static inline void arch_local_irq_restore(unsigned long flags)
  71. {
  72. asm volatile(
  73. " mov %0,epsw \n"
  74. " nop \n"
  75. " nop \n"
  76. " nop \n"
  77. :
  78. : "d"(flags)
  79. : "memory", "cc");
  80. }
  81. static inline bool arch_irqs_disabled_flags(unsigned long flags)
  82. {
  83. return (flags & (EPSW_IE | EPSW_IM)) != (EPSW_IE | EPSW_IM_7);
  84. }
  85. static inline bool arch_irqs_disabled(void)
  86. {
  87. return arch_irqs_disabled_flags(arch_local_save_flags());
  88. }
  89. /*
  90. * Hook to save power by halting the CPU
  91. * - called from the idle loop
  92. * - must reenable interrupts (which takes three instruction cycles to complete)
  93. */
  94. static inline void arch_safe_halt(void)
  95. {
  96. #ifdef CONFIG_SMP
  97. arch_local_irq_enable();
  98. #else
  99. asm volatile(
  100. " or %0,epsw \n"
  101. " nop \n"
  102. " nop \n"
  103. " bset %2,(%1) \n"
  104. :
  105. : "i"(EPSW_IE|EPSW_IM), "n"(&CPUM), "i"(CPUM_SLEEP)
  106. : "cc");
  107. #endif
  108. }
  109. #define __sleep_cpu() \
  110. do { \
  111. asm volatile( \
  112. " bset %1,(%0)\n" \
  113. "1: btst %1,(%0)\n" \
  114. " bne 1b\n" \
  115. : \
  116. : "i"(&CPUM), "i"(CPUM_SLEEP) \
  117. : "cc" \
  118. ); \
  119. } while (0)
  120. static inline void arch_local_cli(void)
  121. {
  122. asm volatile(
  123. " and %0,epsw \n"
  124. " nop \n"
  125. " nop \n"
  126. " nop \n"
  127. :
  128. : "i"(~EPSW_IE)
  129. : "memory"
  130. );
  131. }
  132. static inline unsigned long arch_local_cli_save(void)
  133. {
  134. unsigned long flags = arch_local_save_flags();
  135. arch_local_cli();
  136. return flags;
  137. }
  138. static inline void arch_local_sti(void)
  139. {
  140. asm volatile(
  141. " or %0,epsw \n"
  142. :
  143. : "i"(EPSW_IE)
  144. : "memory");
  145. }
  146. static inline void arch_local_change_intr_mask_level(unsigned long level)
  147. {
  148. asm volatile(
  149. " and %0,epsw \n"
  150. " or %1,epsw \n"
  151. :
  152. : "i"(~EPSW_IM), "i"(EPSW_IE | level)
  153. : "cc", "memory");
  154. }
  155. #else /* !__ASSEMBLY__ */
  156. #define LOCAL_SAVE_FLAGS(reg) \
  157. mov epsw,reg
  158. #define LOCAL_IRQ_DISABLE \
  159. and ~EPSW_IM,epsw; \
  160. or EPSW_IE|MN10300_CLI_LEVEL,epsw; \
  161. nop; \
  162. nop; \
  163. nop
  164. #define LOCAL_IRQ_ENABLE \
  165. or EPSW_IE|EPSW_IM_7,epsw
  166. #define LOCAL_IRQ_RESTORE(reg) \
  167. mov reg,epsw
  168. #define LOCAL_CLI_SAVE(reg) \
  169. mov epsw,reg; \
  170. and ~EPSW_IE,epsw; \
  171. nop; \
  172. nop; \
  173. nop
  174. #define LOCAL_CLI \
  175. and ~EPSW_IE,epsw; \
  176. nop; \
  177. nop; \
  178. nop
  179. #define LOCAL_STI \
  180. or EPSW_IE,epsw
  181. #define LOCAL_CHANGE_INTR_MASK_LEVEL(level) \
  182. and ~EPSW_IM,epsw; \
  183. or EPSW_IE|(level),epsw
  184. #endif /* __ASSEMBLY__ */
  185. #endif /* _ASM_IRQFLAGS_H */