irq.c 2.8 KB

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