int_handler.S 3.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206
  1. /*
  2. * arch/mips/vr4181/common/int_handler.S
  3. *
  4. * Adapted to the VR4181 and almost entirely rewritten:
  5. * Copyright (C) 1999 Bradley D. LaRonde and Michael Klar
  6. *
  7. * Clean up to conform to the new IRQ
  8. * Copyright (C) 2001 MontaVista Software Inc.
  9. * Author: Jun Sun, jsun@mvista.com or jsun@junsun.net
  10. *
  11. * This file is subject to the terms and conditions of the GNU General Public
  12. * License. See the file "COPYING" in the main directory of this archive
  13. * for more details.
  14. *
  15. */
  16. #include <asm/asm.h>
  17. #include <asm/regdef.h>
  18. #include <asm/mipsregs.h>
  19. #include <asm/stackframe.h>
  20. #include <asm/vr4181/vr4181.h>
  21. /*
  22. * [jsun]
  23. * See include/asm/vr4181/irq.h for IRQ assignment and strategy.
  24. */
  25. .text
  26. .set noreorder
  27. .align 5
  28. NESTED(vr4181_handle_irq, PT_SIZE, ra)
  29. .set noat
  30. SAVE_ALL
  31. CLI
  32. .set at
  33. .set noreorder
  34. mfc0 t0, CP0_CAUSE
  35. mfc0 t2, CP0_STATUS
  36. and t0, t2
  37. /* we check IP3 first; it happens most frequently */
  38. andi t1, t0, STATUSF_IP3
  39. bnez t1, ll_cpu_ip3
  40. andi t1, t0, STATUSF_IP2
  41. bnez t1, ll_cpu_ip2
  42. andi t1, t0, STATUSF_IP7 /* cpu timer */
  43. bnez t1, ll_cputimer_irq
  44. andi t1, t0, STATUSF_IP4
  45. bnez t1, ll_cpu_ip4
  46. andi t1, t0, STATUSF_IP5
  47. bnez t1, ll_cpu_ip5
  48. andi t1, t0, STATUSF_IP6
  49. bnez t1, ll_cpu_ip6
  50. andi t1, t0, STATUSF_IP0 /* software int 0 */
  51. bnez t1, ll_cpu_ip0
  52. andi t1, t0, STATUSF_IP1 /* software int 1 */
  53. bnez t1, ll_cpu_ip1
  54. nop
  55. .set reorder
  56. do_spurious:
  57. j spurious_interrupt
  58. /*
  59. * regular CPU irqs
  60. */
  61. ll_cputimer_irq:
  62. li a0, VR4181_IRQ_TIMER
  63. move a1, sp
  64. jal do_IRQ
  65. j ret_from_irq
  66. ll_cpu_ip0:
  67. li a0, VR4181_IRQ_SW1
  68. move a1, sp
  69. jal do_IRQ
  70. j ret_from_irq
  71. ll_cpu_ip1:
  72. li a0, VR4181_IRQ_SW2
  73. move a1, sp
  74. jal do_IRQ
  75. j ret_from_irq
  76. ll_cpu_ip3:
  77. li a0, VR4181_IRQ_INT1
  78. move a1, sp
  79. jal do_IRQ
  80. j ret_from_irq
  81. ll_cpu_ip4:
  82. li a0, VR4181_IRQ_INT2
  83. move a1, sp
  84. jal do_IRQ
  85. j ret_from_irq
  86. ll_cpu_ip5:
  87. li a0, VR4181_IRQ_INT3
  88. move a1, sp
  89. jal do_IRQ
  90. j ret_from_irq
  91. ll_cpu_ip6:
  92. li a0, VR4181_IRQ_INT4
  93. move a1, sp
  94. jal do_IRQ
  95. j ret_from_irq
  96. /*
  97. * One of the sys irq has happend.
  98. *
  99. * In the interest of speed, we first determine in the following order
  100. * which 16-irq block have pending interrupts:
  101. * sysint1 (16 sources, including cascading intrs from GPIO)
  102. * sysint2
  103. * gpio (16 intr sources)
  104. *
  105. * Then we do binary search to find the exact interrupt source.
  106. */
  107. ll_cpu_ip2:
  108. lui t3,%hi(VR4181_SYSINT1REG)
  109. lhu t0,%lo(VR4181_SYSINT1REG)(t3)
  110. lhu t2,%lo(VR4181_MSYSINT1REG)(t3)
  111. and t0, 0xfffb /* hack - remove RTC Long 1 intr */
  112. and t0, t2
  113. beqz t0, check_sysint2
  114. /* check for GPIO interrupts */
  115. andi t1, t0, 0x0100
  116. bnez t1, check_gpio_int
  117. /* so we have an interrupt in sysint1 which is not gpio int */
  118. li a0, VR4181_SYS_IRQ_BASE - 1
  119. j check_16
  120. check_sysint2:
  121. lhu t0,%lo(VR4181_SYSINT2REG)(t3)
  122. lhu t2,%lo(VR4181_MSYSINT2REG)(t3)
  123. and t0, 0xfffe /* hack - remove RTC Long 2 intr */
  124. and t0, t2
  125. li a0, VR4181_SYS_IRQ_BASE + 16 - 1
  126. j check_16
  127. check_gpio_int:
  128. lui t3,%hi(VR4181_GPINTMSK)
  129. lhu t0,%lo(VR4181_GPINTMSK)(t3)
  130. lhu t2,%lo(VR4181_GPINTSTAT)(t3)
  131. xori t0, 0xffff /* why? reverse logic? */
  132. and t0, t2
  133. li a0, VR4181_GPIO_IRQ_BASE - 1
  134. j check_16
  135. /*
  136. * When we reach check_16, we have 16-bit status in t0 and base irq number
  137. * in a0.
  138. */
  139. check_16:
  140. andi t1, t0, 0xff
  141. bnez t1, check_8
  142. srl t0, 8
  143. addi a0, 8
  144. j check_8
  145. /*
  146. * When we reach check_8, we have 8-bit status in t0 and base irq number
  147. * in a0.
  148. */
  149. check_8:
  150. andi t1, t0, 0xf
  151. bnez t1, check_4
  152. srl t0, 4
  153. addi a0, 4
  154. j check_4
  155. /*
  156. * When we reach check_4, we have 4-bit status in t0 and base irq number
  157. * in a0.
  158. */
  159. check_4:
  160. andi t0, t0, 0xf
  161. beqz t0, do_spurious
  162. loop:
  163. andi t2, t0, 0x1
  164. srl t0, 1
  165. addi a0, 1
  166. beqz t2, loop
  167. found_it:
  168. move a1, sp
  169. jal do_IRQ
  170. j ret_from_irq
  171. END(vr4181_handle_irq)