irq.h 6.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181
  1. /*
  2. * Interrupt handling assembler and defines for Linux/CRISv10
  3. */
  4. #ifndef _ASM_ARCH_IRQ_H
  5. #define _ASM_ARCH_IRQ_H
  6. #include <asm/arch/sv_addr_ag.h>
  7. #define NR_IRQS 32
  8. /* The first vector number used for IRQs in v10 is really 0x20 */
  9. /* but all the code and constants are offseted to make 0 the first */
  10. #define FIRST_IRQ 0
  11. #define SOME_IRQ_NBR IO_BITNR(R_VECT_MASK_RD, some) /* 0 ? */
  12. #define NMI_IRQ_NBR IO_BITNR(R_VECT_MASK_RD, nmi) /* 1 */
  13. #define TIMER0_IRQ_NBR IO_BITNR(R_VECT_MASK_RD, timer0) /* 2 */
  14. #define TIMER1_IRQ_NBR IO_BITNR(R_VECT_MASK_RD, timer1) /* 3 */
  15. /* mio, ata, par0, scsi0 on 4 */
  16. /* par1, scsi1 on 5 */
  17. #define NETWORK_STATUS_IRQ_NBR IO_BITNR(R_VECT_MASK_RD, network) /* 6 */
  18. #define SERIAL_IRQ_NBR IO_BITNR(R_VECT_MASK_RD, serial) /* 8 */
  19. #define PA_IRQ_NBR IO_BITNR(R_VECT_MASK_RD, pa) /* 11 */
  20. /* extdma0 and extdma1 is at irq 12 and 13 and/or same as dma5 and dma6 ? */
  21. #define EXTDMA0_IRQ_NBR IO_BITNR(R_VECT_MASK_RD, ext_dma0)
  22. #define EXTDMA1_IRQ_NBR IO_BITNR(R_VECT_MASK_RD, ext_dma1)
  23. /* dma0-9 is irq 16..25 */
  24. /* 16,17: network */
  25. #define DMA0_TX_IRQ_NBR IO_BITNR(R_VECT_MASK_RD, dma0)
  26. #define DMA1_RX_IRQ_NBR IO_BITNR(R_VECT_MASK_RD, dma1)
  27. #define NETWORK_DMA_TX_IRQ_NBR DMA0_TX_IRQ_NBR
  28. #define NETWORK_DMA_RX_IRQ_NBR DMA1_RX_IRQ_NBR
  29. /* 18,19: dma2 and dma3 shared by par0, scsi0, ser2 and ata */
  30. #define DMA2_TX_IRQ_NBR IO_BITNR(R_VECT_MASK_RD, dma2)
  31. #define DMA3_RX_IRQ_NBR IO_BITNR(R_VECT_MASK_RD, dma3)
  32. #define SER2_DMA_TX_IRQ_NBR DMA2_TX_IRQ_NBR
  33. #define SER2_DMA_RX_IRQ_NBR DMA3_RX_IRQ_NBR
  34. /* 20,21: dma4 and dma5 shared by par1, scsi1, ser3 and extdma0 */
  35. #define DMA4_TX_IRQ_NBR IO_BITNR(R_VECT_MASK_RD, dma4)
  36. #define DMA5_RX_IRQ_NBR IO_BITNR(R_VECT_MASK_RD, dma5)
  37. #define SER3_DMA_TX_IRQ_NBR DMA4_TX_IRQ_NBR
  38. #define SER3_DMA_RX_IRQ_NBR DMA5_RX_IRQ_NBR
  39. /* 22,23: dma6 and dma7 shared by ser0, extdma1 and mem2mem */
  40. #define DMA6_TX_IRQ_NBR IO_BITNR(R_VECT_MASK_RD, dma6)
  41. #define DMA7_RX_IRQ_NBR IO_BITNR(R_VECT_MASK_RD, dma7)
  42. #define SER0_DMA_TX_IRQ_NBR DMA6_TX_IRQ_NBR
  43. #define SER0_DMA_RX_IRQ_NBR DMA7_RX_IRQ_NBR
  44. #define MEM2MEM_DMA_TX_IRQ_NBR DMA6_TX_IRQ_NBR
  45. #define MEM2MEM_DMA_RX_IRQ_NBR DMA7_RX_IRQ_NBR
  46. /* 24,25: dma8 and dma9 shared by ser1 and usb */
  47. #define DMA8_TX_IRQ_NBR IO_BITNR(R_VECT_MASK_RD, dma8)
  48. #define DMA9_RX_IRQ_NBR IO_BITNR(R_VECT_MASK_RD, dma9)
  49. #define SER1_DMA_TX_IRQ_NBR DMA8_TX_IRQ_NBR
  50. #define SER1_DMA_RX_IRQ_NBR DMA9_RX_IRQ_NBR
  51. #define USB_DMA_TX_IRQ_NBR DMA8_TX_IRQ_NBR
  52. #define USB_DMA_RX_IRQ_NBR DMA9_RX_IRQ_NBR
  53. /* usb: controller at irq 31 + uses DMA8 and DMA9 */
  54. #define USB_HC_IRQ_NBR IO_BITNR(R_VECT_MASK_RD, usb)
  55. /* our fine, global, etrax irq vector! the pointer lives in the head.S file. */
  56. typedef void (*irqvectptr)(void);
  57. struct etrax_interrupt_vector {
  58. irqvectptr v[256];
  59. };
  60. extern struct etrax_interrupt_vector *etrax_irv;
  61. void set_int_vector(int n, irqvectptr addr, irqvectptr saddr);
  62. void set_break_vector(int n, irqvectptr addr);
  63. #define mask_irq(irq_nr) (*R_VECT_MASK_CLR = 1 << (irq_nr));
  64. #define unmask_irq(irq_nr) (*R_VECT_MASK_SET = 1 << (irq_nr));
  65. #define __STR(x) #x
  66. #define STR(x) __STR(x)
  67. /* SAVE_ALL saves registers so they match pt_regs */
  68. #define SAVE_ALL \
  69. "move $irp,[$sp=$sp-16]\n\t" /* push instruction pointer and fake SBFS struct */ \
  70. "push $srp\n\t" /* push subroutine return pointer */ \
  71. "push $dccr\n\t" /* push condition codes */ \
  72. "push $mof\n\t" /* push multiply overflow reg */ \
  73. "di\n\t" /* need to disable irq's at this point */\
  74. "subq 14*4,$sp\n\t" /* make room for r0-r13 */ \
  75. "movem $r13,[$sp]\n\t" /* push the r0-r13 registers */ \
  76. "push $r10\n\t" /* push orig_r10 */ \
  77. "clear.d [$sp=$sp-4]\n\t" /* frametype - this is a normal stackframe */
  78. /* BLOCK_IRQ and UNBLOCK_IRQ do the same as mask_irq and unmask_irq */
  79. #define BLOCK_IRQ(mask,nr) \
  80. "move.d " #mask ",$r0\n\t" \
  81. "move.d $r0,[0xb00000d8]\n\t"
  82. #define UNBLOCK_IRQ(mask) \
  83. "move.d " #mask ",$r0\n\t" \
  84. "move.d $r0,[0xb00000dc]\n\t"
  85. #define IRQ_NAME2(nr) nr##_interrupt(void)
  86. #define IRQ_NAME(nr) IRQ_NAME2(IRQ##nr)
  87. #define sIRQ_NAME(nr) IRQ_NAME2(sIRQ##nr)
  88. #define BAD_IRQ_NAME(nr) IRQ_NAME2(bad_IRQ##nr)
  89. /* the asm IRQ handler makes sure the causing IRQ is blocked, then it calls
  90. * do_IRQ (with irq disabled still). after that it unblocks and jumps to
  91. * ret_from_intr (entry.S)
  92. *
  93. * The reason the IRQ is blocked is to allow an sti() before the handler which
  94. * will acknowledge the interrupt is run.
  95. */
  96. #define BUILD_IRQ(nr,mask) \
  97. void IRQ_NAME(nr); \
  98. void sIRQ_NAME(nr); \
  99. void BAD_IRQ_NAME(nr); \
  100. __asm__ ( \
  101. ".text\n\t" \
  102. "IRQ" #nr "_interrupt:\n\t" \
  103. SAVE_ALL \
  104. "sIRQ" #nr "_interrupt:\n\t" /* shortcut for the multiple irq handler */ \
  105. BLOCK_IRQ(mask,nr) /* this must be done to prevent irq loops when we ei later */ \
  106. "moveq "#nr",$r10\n\t" \
  107. "move.d $sp,$r11\n\t" \
  108. "jsr do_IRQ\n\t" /* irq.c, r10 and r11 are arguments */ \
  109. UNBLOCK_IRQ(mask) \
  110. "moveq 0,$r9\n\t" /* make ret_from_intr realise we came from an irq */ \
  111. "jump ret_from_intr\n\t" \
  112. "bad_IRQ" #nr "_interrupt:\n\t" \
  113. "push $r0\n\t" \
  114. BLOCK_IRQ(mask,nr) \
  115. "pop $r0\n\t" \
  116. "reti\n\t" \
  117. "nop\n");
  118. /* This is subtle. The timer interrupt is crucial and it should not be disabled for
  119. * too long. However, if it had been a normal interrupt as per BUILD_IRQ, it would
  120. * have been BLOCK'ed, and then softirq's are run before we return here to UNBLOCK.
  121. * If the softirq's take too much time to run, the timer irq won't run and the
  122. * watchdog will kill us.
  123. *
  124. * Furthermore, if a lot of other irq's occur before we return here, the multiple_irq
  125. * handler is run and it prioritizes the timer interrupt. However if we had BLOCK'ed
  126. * it here, we would not get the multiple_irq at all.
  127. *
  128. * The non-blocking here is based on the knowledge that the timer interrupt is
  129. * registred as a fast interrupt (SA_INTERRUPT) so that we _know_ there will not
  130. * be an sti() before the timer irq handler is run to acknowledge the interrupt.
  131. */
  132. #define BUILD_TIMER_IRQ(nr,mask) \
  133. void IRQ_NAME(nr); \
  134. void sIRQ_NAME(nr); \
  135. void BAD_IRQ_NAME(nr); \
  136. __asm__ ( \
  137. ".text\n\t" \
  138. "IRQ" #nr "_interrupt:\n\t" \
  139. SAVE_ALL \
  140. "sIRQ" #nr "_interrupt:\n\t" /* shortcut for the multiple irq handler */ \
  141. "moveq "#nr",$r10\n\t" \
  142. "move.d $sp,$r11\n\t" \
  143. "jsr do_IRQ\n\t" /* irq.c, r10 and r11 are arguments */ \
  144. "moveq 0,$r9\n\t" /* make ret_from_intr realise we came from an irq */ \
  145. "jump ret_from_intr\n\t" \
  146. "bad_IRQ" #nr "_interrupt:\n\t" \
  147. "push $r0\n\t" \
  148. BLOCK_IRQ(mask,nr) \
  149. "pop $r0\n\t" \
  150. "reti\n\t" \
  151. "nop\n");
  152. #endif