irq.c 3.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147
  1. /*
  2. * linux/arch/sh/boards/se/7206/irq.c
  3. *
  4. * Copyright (C) 2005,2006 Yoshinori Sato
  5. *
  6. * Hitachi SolutionEngine Support.
  7. *
  8. */
  9. #include <linux/init.h>
  10. #include <linux/irq.h>
  11. #include <linux/io.h>
  12. #include <linux/irq.h>
  13. #include <linux/interrupt.h>
  14. #include <asm/se7206.h>
  15. #define INTSTS0 0x31800000
  16. #define INTSTS1 0x31800002
  17. #define INTMSK0 0x31800004
  18. #define INTMSK1 0x31800006
  19. #define INTSEL 0x31800008
  20. #define IRQ0_IRQ 64
  21. #define IRQ1_IRQ 65
  22. #define IRQ3_IRQ 67
  23. #define INTC_IPR01 0xfffe0818
  24. #define INTC_ICR1 0xfffe0802
  25. static void disable_se7206_irq(unsigned int irq)
  26. {
  27. unsigned short val;
  28. unsigned short mask = 0xffff ^ (0x0f << 4 * (3 - (IRQ0_IRQ - irq)));
  29. unsigned short msk0,msk1;
  30. /* Set the priority in IPR to 0 */
  31. val = ctrl_inw(INTC_IPR01);
  32. val &= mask;
  33. ctrl_outw(val, INTC_IPR01);
  34. /* FPGA mask set */
  35. msk0 = ctrl_inw(INTMSK0);
  36. msk1 = ctrl_inw(INTMSK1);
  37. switch (irq) {
  38. case IRQ0_IRQ:
  39. msk0 |= 0x0010;
  40. break;
  41. case IRQ1_IRQ:
  42. msk0 |= 0x000f;
  43. break;
  44. case IRQ3_IRQ:
  45. msk0 |= 0x0f00;
  46. msk1 |= 0x00ff;
  47. break;
  48. }
  49. ctrl_outw(msk0, INTMSK0);
  50. ctrl_outw(msk1, INTMSK1);
  51. }
  52. static void enable_se7206_irq(unsigned int irq)
  53. {
  54. unsigned short val;
  55. unsigned short value = (0x0001 << 4 * (3 - (IRQ0_IRQ - irq)));
  56. unsigned short msk0,msk1;
  57. /* Set priority in IPR back to original value */
  58. val = ctrl_inw(INTC_IPR01);
  59. val |= value;
  60. ctrl_outw(val, INTC_IPR01);
  61. /* FPGA mask reset */
  62. msk0 = ctrl_inw(INTMSK0);
  63. msk1 = ctrl_inw(INTMSK1);
  64. switch (irq) {
  65. case IRQ0_IRQ:
  66. msk0 &= ~0x0010;
  67. break;
  68. case IRQ1_IRQ:
  69. msk0 &= ~0x000f;
  70. break;
  71. case IRQ3_IRQ:
  72. msk0 &= ~0x0f00;
  73. msk1 &= ~0x00ff;
  74. break;
  75. }
  76. ctrl_outw(msk0, INTMSK0);
  77. ctrl_outw(msk1, INTMSK1);
  78. }
  79. static void eoi_se7206_irq(unsigned int irq)
  80. {
  81. unsigned short sts0,sts1;
  82. if (!(irq_desc[irq].status & (IRQ_DISABLED|IRQ_INPROGRESS)))
  83. enable_se7206_irq(irq);
  84. /* FPGA isr clear */
  85. sts0 = ctrl_inw(INTSTS0);
  86. sts1 = ctrl_inw(INTSTS1);
  87. switch (irq) {
  88. case IRQ0_IRQ:
  89. sts0 &= ~0x0010;
  90. break;
  91. case IRQ1_IRQ:
  92. sts0 &= ~0x000f;
  93. break;
  94. case IRQ3_IRQ:
  95. sts0 &= ~0x0f00;
  96. sts1 &= ~0x00ff;
  97. break;
  98. }
  99. ctrl_outw(sts0, INTSTS0);
  100. ctrl_outw(sts1, INTSTS1);
  101. }
  102. static struct irq_chip se7206_irq_chip __read_mostly = {
  103. .name = "SE7206-FPGA",
  104. .mask = disable_se7206_irq,
  105. .unmask = enable_se7206_irq,
  106. .mask_ack = disable_se7206_irq,
  107. .eoi = eoi_se7206_irq,
  108. };
  109. static void make_se7206_irq(unsigned int irq)
  110. {
  111. disable_irq_nosync(irq);
  112. set_irq_chip_and_handler_name(irq, &se7206_irq_chip,
  113. handle_level_irq, "level");
  114. disable_se7206_irq(irq);
  115. }
  116. /*
  117. * Initialize IRQ setting
  118. */
  119. void __init init_se7206_IRQ(void)
  120. {
  121. make_se7206_irq(IRQ0_IRQ); /* SMC91C111 */
  122. make_se7206_irq(IRQ1_IRQ); /* ATA */
  123. make_se7206_irq(IRQ3_IRQ); /* SLOT / PCM */
  124. ctrl_outw(inw(INTC_ICR1) | 0x000b ,INTC_ICR1 ) ; /* ICR1 */
  125. /* FPGA System register setup*/
  126. ctrl_outw(0x0000,INTSTS0); /* Clear INTSTS0 */
  127. ctrl_outw(0x0000,INTSTS1); /* Clear INTSTS1 */
  128. /* IRQ0=LAN, IRQ1=ATA, IRQ3=SLT,PCM */
  129. ctrl_outw(0x0001,INTSEL);
  130. }