mipsIRQ.S 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155
  1. /*
  2. * Carsten Langgaard, carstenl@mips.com
  3. * Copyright (C) 1999, 2000 MIPS Technologies, Inc. All rights reserved.
  4. *
  5. * ########################################################################
  6. *
  7. * This program is free software; you can distribute it and/or modify it
  8. * under the terms of the GNU General Public License (Version 2) as
  9. * published by the Free Software Foundation.
  10. *
  11. * This program is distributed in the hope it will be useful, but WITHOUT
  12. * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  13. * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
  14. * for more details.
  15. *
  16. * You should have received a copy of the GNU General Public License along
  17. * with this program; if not, write to the Free Software Foundation, Inc.,
  18. * 59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
  19. *
  20. * ########################################################################
  21. *
  22. * Interrupt exception dispatch code.
  23. *
  24. */
  25. #include <linux/config.h>
  26. #include <asm/asm.h>
  27. #include <asm/mipsregs.h>
  28. #include <asm/regdef.h>
  29. #include <asm/stackframe.h>
  30. #ifdef CONFIG_MIPS_ATLAS
  31. #include <asm/mips-boards/atlasint.h>
  32. #define CASCADE_IRQ MIPSCPU_INT_ATLAS
  33. #define CASCADE_DISPATCH atlas_hw0_irqdispatch
  34. #endif
  35. #ifdef CONFIG_MIPS_MALTA
  36. #include <asm/mips-boards/maltaint.h>
  37. #define CASCADE_IRQ MIPSCPU_INT_I8259A
  38. #define CASCADE_DISPATCH malta_hw0_irqdispatch
  39. #endif
  40. #ifdef CONFIG_MIPS_SEAD
  41. #include <asm/mips-boards/seadint.h>
  42. #endif
  43. /* A lot of complication here is taken away because:
  44. *
  45. * 1) We handle one interrupt and return, sitting in a loop and moving across
  46. * all the pending IRQ bits in the cause register is _NOT_ the answer, the
  47. * common case is one pending IRQ so optimize in that direction.
  48. *
  49. * 2) We need not check against bits in the status register IRQ mask, that
  50. * would make this routine slow as hell.
  51. *
  52. * 3) Linux only thinks in terms of all IRQs on or all IRQs off, nothing in
  53. * between like BSD spl() brain-damage.
  54. *
  55. * Furthermore, the IRQs on the MIPS board look basically (barring software
  56. * IRQs which we don't use at all and all external interrupt sources are
  57. * combined together on hardware interrupt 0 (MIPS IRQ 2)) like:
  58. *
  59. * MIPS IRQ Source
  60. * -------- ------
  61. * 0 Software (ignored)
  62. * 1 Software (ignored)
  63. * 2 Combined hardware interrupt (hw0)
  64. * 3 Hardware (ignored)
  65. * 4 Hardware (ignored)
  66. * 5 Hardware (ignored)
  67. * 6 Hardware (ignored)
  68. * 7 R4k timer (what we use)
  69. *
  70. * Note: On the SEAD board thing are a little bit different.
  71. * Here IRQ 2 (hw0) is wired to the UART0 and IRQ 3 (hw1) is wired
  72. * wired to UART1.
  73. *
  74. * We handle the IRQ according to _our_ priority which is:
  75. *
  76. * Highest ---- R4k Timer
  77. * Lowest ---- Combined hardware interrupt
  78. *
  79. * then we just return, if multiple IRQs are pending then we will just take
  80. * another exception, big deal.
  81. */
  82. .text
  83. .set noreorder
  84. .set noat
  85. .align 5
  86. NESTED(mipsIRQ, PT_SIZE, sp)
  87. SAVE_ALL
  88. CLI
  89. .set at
  90. mfc0 s0, CP0_CAUSE # get irq bits
  91. mfc0 s1, CP0_STATUS # get irq mask
  92. andi s0, ST0_IM # CAUSE.CE may be non-zero!
  93. and s0, s1
  94. #if defined(CONFIG_CPU_MIPS32) || defined(CONFIG_CPU_MIPS64)
  95. .set mips32
  96. clz a0, s0
  97. .set mips0
  98. negu a0
  99. addu a0, 31-CAUSEB_IP
  100. bltz a0, spurious
  101. #else
  102. beqz s0, spurious
  103. li a0, 7
  104. and t0, s0, 0xf000
  105. sltiu t0, t0, 1
  106. sll t0, 2
  107. subu a0, t0
  108. sll s0, t0
  109. and t0, s0, 0xc000
  110. sltiu t0, t0, 1
  111. sll t0, 1
  112. subu a0, t0
  113. sll s0, t0
  114. and t0, s0, 0x8000
  115. sltiu t0, t0, 1
  116. # sll t0, 0
  117. subu a0, t0
  118. # sll s0, t0
  119. #endif
  120. #ifdef CASCADE_IRQ
  121. li a1, CASCADE_IRQ
  122. bne a0, a1, 1f
  123. addu a0, MIPSCPU_INT_BASE
  124. jal CASCADE_DISPATCH
  125. move a0, sp
  126. j ret_from_irq
  127. nop
  128. 1:
  129. #else
  130. addu a0, MIPSCPU_INT_BASE
  131. #endif
  132. jal do_IRQ
  133. move a1, sp
  134. j ret_from_irq
  135. nop
  136. spurious:
  137. j spurious_interrupt
  138. nop
  139. END(mipsIRQ)