irq.c 2.9 KB

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