irq.c 3.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151
  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(struct irq_data *data)
  25. {
  26. unsigned int irq = data->irq;
  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 = __raw_readw(INTC_IPR01);
  32. val &= mask;
  33. __raw_writew(val, INTC_IPR01);
  34. /* FPGA mask set */
  35. msk0 = __raw_readw(INTMSK0);
  36. msk1 = __raw_readw(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. __raw_writew(msk0, INTMSK0);
  50. __raw_writew(msk1, INTMSK1);
  51. }
  52. static void enable_se7206_irq(struct irq_data *data)
  53. {
  54. unsigned int irq = data->irq;
  55. unsigned short val;
  56. unsigned short value = (0x0001 << 4 * (3 - (IRQ0_IRQ - irq)));
  57. unsigned short msk0,msk1;
  58. /* Set priority in IPR back to original value */
  59. val = __raw_readw(INTC_IPR01);
  60. val |= value;
  61. __raw_writew(val, INTC_IPR01);
  62. /* FPGA mask reset */
  63. msk0 = __raw_readw(INTMSK0);
  64. msk1 = __raw_readw(INTMSK1);
  65. switch (irq) {
  66. case IRQ0_IRQ:
  67. msk0 &= ~0x0010;
  68. break;
  69. case IRQ1_IRQ:
  70. msk0 &= ~0x000f;
  71. break;
  72. case IRQ3_IRQ:
  73. msk0 &= ~0x0f00;
  74. msk1 &= ~0x00ff;
  75. break;
  76. }
  77. __raw_writew(msk0, INTMSK0);
  78. __raw_writew(msk1, INTMSK1);
  79. }
  80. static void eoi_se7206_irq(struct irq_data *data)
  81. {
  82. unsigned short sts0,sts1;
  83. unsigned int irq = data->irq;
  84. if (!irqd_irq_disabled(data) && !irqd_irq_inprogress(data))
  85. enable_se7206_irq(data);
  86. /* FPGA isr clear */
  87. sts0 = __raw_readw(INTSTS0);
  88. sts1 = __raw_readw(INTSTS1);
  89. switch (irq) {
  90. case IRQ0_IRQ:
  91. sts0 &= ~0x0010;
  92. break;
  93. case IRQ1_IRQ:
  94. sts0 &= ~0x000f;
  95. break;
  96. case IRQ3_IRQ:
  97. sts0 &= ~0x0f00;
  98. sts1 &= ~0x00ff;
  99. break;
  100. }
  101. __raw_writew(sts0, INTSTS0);
  102. __raw_writew(sts1, INTSTS1);
  103. }
  104. static struct irq_chip se7206_irq_chip __read_mostly = {
  105. .name = "SE7206-FPGA",
  106. .irq_mask = disable_se7206_irq,
  107. .irq_unmask = enable_se7206_irq,
  108. .irq_eoi = eoi_se7206_irq,
  109. };
  110. static void make_se7206_irq(unsigned int irq)
  111. {
  112. disable_irq_nosync(irq);
  113. irq_set_chip_and_handler_name(irq, &se7206_irq_chip,
  114. handle_level_irq, "level");
  115. disable_se7206_irq(irq_get_irq_data(irq));
  116. }
  117. /*
  118. * Initialize IRQ setting
  119. */
  120. void __init init_se7206_IRQ(void)
  121. {
  122. make_se7206_irq(IRQ0_IRQ); /* SMC91C111 */
  123. make_se7206_irq(IRQ1_IRQ); /* ATA */
  124. make_se7206_irq(IRQ3_IRQ); /* SLOT / PCM */
  125. __raw_writew(__raw_readw(INTC_ICR1) | 0x000b, INTC_ICR1); /* ICR1 */
  126. /* FPGA System register setup*/
  127. __raw_writew(0x0000,INTSTS0); /* Clear INTSTS0 */
  128. __raw_writew(0x0000,INTSTS1); /* Clear INTSTS1 */
  129. /* IRQ0=LAN, IRQ1=ATA, IRQ3=SLT,PCM */
  130. __raw_writew(0x0001,INTSEL);
  131. }