irq.c 4.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199
  1. /*
  2. * arch/sh/boards/se/7343/irq.c
  3. *
  4. */
  5. #include <linux/init.h>
  6. #include <linux/interrupt.h>
  7. #include <linux/irq.h>
  8. #include <asm/irq.h>
  9. #include <asm/io.h>
  10. #include <asm/mach/se7343.h>
  11. static void
  12. disable_intreq_irq(unsigned int irq)
  13. {
  14. int bit = irq - OFFCHIP_IRQ_BASE;
  15. u16 val;
  16. val = ctrl_inw(PA_CPLD_IMSK);
  17. val |= 1 << bit;
  18. ctrl_outw(val, PA_CPLD_IMSK);
  19. }
  20. static void
  21. enable_intreq_irq(unsigned int irq)
  22. {
  23. int bit = irq - OFFCHIP_IRQ_BASE;
  24. u16 val;
  25. val = ctrl_inw(PA_CPLD_IMSK);
  26. val &= ~(1 << bit);
  27. ctrl_outw(val, PA_CPLD_IMSK);
  28. }
  29. static void
  30. mask_and_ack_intreq_irq(unsigned int irq)
  31. {
  32. disable_intreq_irq(irq);
  33. }
  34. static unsigned int
  35. startup_intreq_irq(unsigned int irq)
  36. {
  37. enable_intreq_irq(irq);
  38. return 0;
  39. }
  40. static void
  41. shutdown_intreq_irq(unsigned int irq)
  42. {
  43. disable_intreq_irq(irq);
  44. }
  45. static void
  46. end_intreq_irq(unsigned int irq)
  47. {
  48. if (!(irq_desc[irq].status & (IRQ_DISABLED | IRQ_INPROGRESS)))
  49. enable_intreq_irq(irq);
  50. }
  51. static struct hw_interrupt_type intreq_irq_type = {
  52. .typename = "FPGA-IRQ",
  53. .startup = startup_intreq_irq,
  54. .shutdown = shutdown_intreq_irq,
  55. .enable = enable_intreq_irq,
  56. .disable = disable_intreq_irq,
  57. .ack = mask_and_ack_intreq_irq,
  58. .end = end_intreq_irq
  59. };
  60. static void
  61. make_intreq_irq(unsigned int irq)
  62. {
  63. disable_irq_nosync(irq);
  64. irq_desc[irq].chip = &intreq_irq_type;
  65. disable_intreq_irq(irq);
  66. }
  67. int
  68. shmse_irq_demux(int irq)
  69. {
  70. int bit;
  71. volatile u16 val;
  72. if (irq == IRQ5_IRQ) {
  73. /* Read status Register */
  74. val = ctrl_inw(PA_CPLD_ST);
  75. bit = ffs(val);
  76. if (bit != 0)
  77. return OFFCHIP_IRQ_BASE + bit - 1;
  78. }
  79. return irq;
  80. }
  81. /* IRQ5 is multiplexed between the following sources:
  82. * 1. PC Card socket
  83. * 2. Extension slot
  84. * 3. USB Controller
  85. * 4. Serial Controller
  86. *
  87. * We configure IRQ5 as a cascade IRQ.
  88. */
  89. static struct irqaction irq5 = { no_action, 0, CPU_MASK_NONE, "IRQ5-cascade",
  90. NULL, NULL};
  91. static struct ipr_data se7343_irq5_ipr_map[] = {
  92. { IRQ5_IRQ, IRQ5_IPR_ADDR+2, IRQ5_IPR_POS, IRQ5_PRIORITY },
  93. };
  94. static struct ipr_data se7343_siof0_vpu_ipr_map[] = {
  95. { SIOF0_IRQ, SIOF0_IPR_ADDR, SIOF0_IPR_POS, SIOF0_PRIORITY },
  96. { VPU_IRQ, VPU_IPR_ADDR, VPU_IPR_POS, 8 },
  97. };
  98. static struct ipr_data se7343_other_ipr_map[] = {
  99. { DMTE0_IRQ, DMA1_IPR_ADDR, DMA1_IPR_POS, DMA1_PRIORITY },
  100. { DMTE1_IRQ, DMA1_IPR_ADDR, DMA1_IPR_POS, DMA1_PRIORITY },
  101. { DMTE2_IRQ, DMA1_IPR_ADDR, DMA1_IPR_POS, DMA1_PRIORITY },
  102. { DMTE3_IRQ, DMA1_IPR_ADDR, DMA1_IPR_POS, DMA1_PRIORITY },
  103. { DMTE4_IRQ, DMA2_IPR_ADDR, DMA2_IPR_POS, DMA2_PRIORITY },
  104. { DMTE5_IRQ, DMA2_IPR_ADDR, DMA2_IPR_POS, DMA2_PRIORITY },
  105. /* I2C block */
  106. { IIC0_ALI_IRQ, IIC0_IPR_ADDR, IIC0_IPR_POS, IIC0_PRIORITY },
  107. { IIC0_TACKI_IRQ, IIC0_IPR_ADDR, IIC0_IPR_POS, IIC0_PRIORITY },
  108. { IIC0_WAITI_IRQ, IIC0_IPR_ADDR, IIC0_IPR_POS, IIC0_PRIORITY },
  109. { IIC0_DTEI_IRQ, IIC0_IPR_ADDR, IIC0_IPR_POS, IIC0_PRIORITY },
  110. { IIC1_ALI_IRQ, IIC1_IPR_ADDR, IIC1_IPR_POS, IIC1_PRIORITY },
  111. { IIC1_TACKI_IRQ, IIC1_IPR_ADDR, IIC1_IPR_POS, IIC1_PRIORITY },
  112. { IIC1_WAITI_IRQ, IIC1_IPR_ADDR, IIC1_IPR_POS, IIC1_PRIORITY },
  113. { IIC1_DTEI_IRQ, IIC1_IPR_ADDR, IIC1_IPR_POS, IIC1_PRIORITY },
  114. /* SIOF */
  115. { SIOF0_IRQ, SIOF0_IPR_ADDR, SIOF0_IPR_POS, SIOF0_PRIORITY },
  116. /* SIU */
  117. { SIU_IRQ, SIU_IPR_ADDR, SIU_IPR_POS, SIU_PRIORITY },
  118. /* VIO interrupt */
  119. { CEU_IRQ, VIO_IPR_ADDR, VIO_IPR_POS, VIO_PRIORITY },
  120. { BEU_IRQ, VIO_IPR_ADDR, VIO_IPR_POS, VIO_PRIORITY },
  121. { VEU_IRQ, VIO_IPR_ADDR, VIO_IPR_POS, VIO_PRIORITY },
  122. /*MFI interrupt*/
  123. { MFI_IRQ, MFI_IPR_ADDR, MFI_IPR_POS, MFI_PRIORITY },
  124. /* LCD controller */
  125. { LCDC_IRQ, LCDC_IPR_ADDR, LCDC_IPR_POS, LCDC_PRIORITY },
  126. };
  127. /*
  128. * Initialize IRQ setting
  129. */
  130. void __init
  131. init_7343se_IRQ(void)
  132. {
  133. /* Setup Multiplexed interrupts */
  134. ctrl_outw(8, PA_CPLD_MODESET); /* Set all CPLD interrupts to active
  135. * low.
  136. */
  137. /* Mask all CPLD controller interrupts */
  138. ctrl_outw(0x0fff, PA_CPLD_IMSK);
  139. /* PC Card interrupts */
  140. make_intreq_irq(PC_IRQ0);
  141. make_intreq_irq(PC_IRQ1);
  142. make_intreq_irq(PC_IRQ2);
  143. make_intreq_irq(PC_IRQ3);
  144. /* Extension Slot Interrupts */
  145. make_intreq_irq(EXT_IRQ0);
  146. make_intreq_irq(EXT_IRQ1);
  147. make_intreq_irq(EXT_IRQ2);
  148. make_intreq_irq(EXT_IRQ3);
  149. /* USB Controller interrupts */
  150. make_intreq_irq(USB_IRQ0);
  151. make_intreq_irq(USB_IRQ1);
  152. /* Serial Controller interrupts */
  153. make_intreq_irq(UART_IRQ0);
  154. make_intreq_irq(UART_IRQ1);
  155. /* Setup all external interrupts to be active low */
  156. ctrl_outw(0xaaaa, INTC_ICR1);
  157. make_ipr_irq(se7343_irq5_ipr_map, ARRAY_SIZE(se7343_irq5_ipr_map));
  158. setup_irq(IRQ5_IRQ, &irq5);
  159. /* Set port control to use IRQ5 */
  160. *(u16 *)0xA4050108 &= ~0xc;
  161. make_ipr_irq(se7343_siof0_vpu_ipr_map, ARRAY_SIZE(se7343_siof0_vpu_ipr_map));
  162. ctrl_outb(0x0f, INTC_IMCR5); /* enable SCIF IRQ */
  163. make_ipr_irq(se7343_other_ipr_map, ARRAY_SIZE(se7343_other_ipr_map));
  164. ctrl_outw(0x2000, PA_MRSHPC + 0x0c); /* mrshpc irq enable */
  165. }