irqflags.h 4.1 KB

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