irq_handler.S 4.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147
  1. /*
  2. * Copyright (C) 2000, 2001, 2002, 2003 Broadcom Corporation
  3. *
  4. * This program is free software; you can redistribute it and/or
  5. * modify it under the terms of the GNU General Public License
  6. * as published by the Free Software Foundation; either version 2
  7. * of the License, or (at your option) any later version.
  8. *
  9. * This program is distributed in the hope that it will be useful,
  10. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. * GNU General Public License for more details.
  13. *
  14. * You should have received a copy of the GNU General Public License
  15. * along with this program; if not, write to the Free Software
  16. * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
  17. */
  18. /*
  19. * sb1250_handle_int() is the routine that is actually called when an interrupt
  20. * occurs. It is installed as the exception vector handler in arch_init_irq()
  21. * in arch/mips/sibyte/sb1250/irq.c
  22. *
  23. * In the handle we figure out which interrupts need handling, and use that to
  24. * call the dispatcher, which will take care of actually calling registered
  25. * handlers
  26. *
  27. * Note that we take care of all raised interrupts in one go at the handler.
  28. * This is more BSDish than the Indy code, and also, IMHO, more sane.
  29. */
  30. #include <linux/config.h>
  31. #include <asm/addrspace.h>
  32. #include <asm/asm.h>
  33. #include <asm/mipsregs.h>
  34. #include <asm/regdef.h>
  35. #include <asm/stackframe.h>
  36. #include <asm/sibyte/sb1250_defs.h>
  37. #include <asm/sibyte/sb1250_regs.h>
  38. #include <asm/sibyte/sb1250_int.h>
  39. /*
  40. * What a pain. We have to be really careful saving the upper 32 bits of any
  41. * register across function calls if we don't want them trashed--since were
  42. * running in -o32, the calling routing never saves the full 64 bits of a
  43. * register across a function call. Being the interrupt handler, we're
  44. * guaranteed that interrupts are disabled during this code so we don't have
  45. * to worry about random interrupts blasting the high 32 bits.
  46. */
  47. .text
  48. .set push
  49. .set noreorder
  50. .set noat
  51. .set mips64
  52. .align 5
  53. NESTED(sb1250_irq_handler, PT_SIZE, sp)
  54. SAVE_ALL
  55. CLI
  56. #ifdef CONFIG_SIBYTE_SB1250_PROF
  57. /* Set compare to count to silence count/compare timer interrupts */
  58. mfc0 t1, CP0_COUNT
  59. mtc0 t1, CP0_COMPARE /* pause to clear IP[7] bit of cause ? */
  60. #endif
  61. /* Read cause */
  62. mfc0 s0, CP0_CAUSE
  63. #ifdef CONFIG_SIBYTE_SB1250_PROF
  64. /* Cpu performance counter interrupt is routed to IP[7] */
  65. andi t1, s0, CAUSEF_IP7
  66. beqz t1, 0f
  67. srl t1, s0, (CAUSEB_BD-2) /* Shift BD bit to bit 2 */
  68. and t1, t1, 0x4 /* mask to get just BD bit */
  69. mfc0 a0, CP0_EPC
  70. jal sbprof_cpu_intr
  71. addu a0, a0, t1 /* a0 = EPC + (BD ? 4 : 0) */
  72. j ret_from_irq
  73. nop
  74. 0:
  75. #endif
  76. /* Timer interrupt is routed to IP[4] */
  77. andi t1, s0, CAUSEF_IP4
  78. beqz t1, 1f
  79. nop
  80. jal sb1250_timer_interrupt
  81. move a0, sp /* Pass the registers along */
  82. j ret_from_irq
  83. nop # delay slot
  84. 1:
  85. #ifdef CONFIG_SMP
  86. /* Mailbox interrupt is routed to IP[3] */
  87. andi t1, s0, CAUSEF_IP3
  88. beqz t1, 2f
  89. nop
  90. jal sb1250_mailbox_interrupt
  91. move a0, sp
  92. j ret_from_irq
  93. nop # delay slot
  94. 2:
  95. #endif
  96. #ifdef CONFIG_KGDB
  97. /* KGDB (uart 1) interrupt is routed to IP[6] */
  98. andi t1, s0, CAUSEF_IP6
  99. beqz t1, 1f
  100. nop # delay slot
  101. jal sb1250_kgdb_interrupt
  102. move a0, sp
  103. j ret_from_irq
  104. nop # delay slot
  105. 1:
  106. #endif
  107. and t1, s0, CAUSEF_IP2
  108. beqz t1, 4f
  109. nop
  110. /*
  111. * Default...we've hit an IP[2] interrupt, which means we've got to
  112. * check the 1250 interrupt registers to figure out what to do
  113. * Need to detect which CPU we're on, now that smp_affinity is supported.
  114. */
  115. PTR_LA v0, CKSEG1 + A_IMR_CPU0_BASE
  116. #ifdef CONFIG_SMP
  117. lw t1, TI_CPU($28)
  118. sll t1, IMR_REGISTER_SPACING_SHIFT
  119. addu v0, t1
  120. #endif
  121. ld s0, R_IMR_INTERRUPT_STATUS_BASE(v0) /* read IP[2] status */
  122. beqz s0, 4f /* No interrupts. Return */
  123. move a1, sp
  124. 3: dclz s1, s0 /* Find the next interrupt */
  125. dsubu a0, zero, s1
  126. daddiu a0, a0, 63
  127. jal do_IRQ
  128. nop
  129. 4: j ret_from_irq
  130. nop
  131. .set pop
  132. END(sb1250_irq_handler)