irq.c 5.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197
  1. /*
  2. * Copyright (c) 2011 Zhang, Keguang <keguang.zhang@gmail.com>
  3. *
  4. * This program is free software; you can redistribute it and/or modify it
  5. * under the terms of the GNU General Public License as published by the
  6. * Free Software Foundation; either version 2 of the License, or (at your
  7. * option) any later version.
  8. */
  9. #include <linux/interrupt.h>
  10. #include <linux/irq.h>
  11. #include <asm/irq_cpu.h>
  12. #include <loongson1.h>
  13. #include <irq.h>
  14. #define LS1X_INTC_REG(n, x) \
  15. ((void __iomem *)KSEG1ADDR(LS1X_INTC_BASE + (n * 0x18) + (x)))
  16. #define LS1X_INTC_INTISR(n) LS1X_INTC_REG(n, 0x0)
  17. #define LS1X_INTC_INTIEN(n) LS1X_INTC_REG(n, 0x4)
  18. #define LS1X_INTC_INTSET(n) LS1X_INTC_REG(n, 0x8)
  19. #define LS1X_INTC_INTCLR(n) LS1X_INTC_REG(n, 0xc)
  20. #define LS1X_INTC_INTPOL(n) LS1X_INTC_REG(n, 0x10)
  21. #define LS1X_INTC_INTEDGE(n) LS1X_INTC_REG(n, 0x14)
  22. static void ls1x_irq_ack(struct irq_data *d)
  23. {
  24. unsigned int bit = (d->irq - LS1X_IRQ_BASE) & 0x1f;
  25. unsigned int n = (d->irq - LS1X_IRQ_BASE) >> 5;
  26. __raw_writel(__raw_readl(LS1X_INTC_INTCLR(n))
  27. | (1 << bit), LS1X_INTC_INTCLR(n));
  28. }
  29. static void ls1x_irq_mask(struct irq_data *d)
  30. {
  31. unsigned int bit = (d->irq - LS1X_IRQ_BASE) & 0x1f;
  32. unsigned int n = (d->irq - LS1X_IRQ_BASE) >> 5;
  33. __raw_writel(__raw_readl(LS1X_INTC_INTIEN(n))
  34. & ~(1 << bit), LS1X_INTC_INTIEN(n));
  35. }
  36. static void ls1x_irq_mask_ack(struct irq_data *d)
  37. {
  38. unsigned int bit = (d->irq - LS1X_IRQ_BASE) & 0x1f;
  39. unsigned int n = (d->irq - LS1X_IRQ_BASE) >> 5;
  40. __raw_writel(__raw_readl(LS1X_INTC_INTIEN(n))
  41. & ~(1 << bit), LS1X_INTC_INTIEN(n));
  42. __raw_writel(__raw_readl(LS1X_INTC_INTCLR(n))
  43. | (1 << bit), LS1X_INTC_INTCLR(n));
  44. }
  45. static void ls1x_irq_unmask(struct irq_data *d)
  46. {
  47. unsigned int bit = (d->irq - LS1X_IRQ_BASE) & 0x1f;
  48. unsigned int n = (d->irq - LS1X_IRQ_BASE) >> 5;
  49. __raw_writel(__raw_readl(LS1X_INTC_INTIEN(n))
  50. | (1 << bit), LS1X_INTC_INTIEN(n));
  51. }
  52. static int ls1x_irq_settype(struct irq_data *d, unsigned int type)
  53. {
  54. unsigned int bit = (d->irq - LS1X_IRQ_BASE) & 0x1f;
  55. unsigned int n = (d->irq - LS1X_IRQ_BASE) >> 5;
  56. switch (type) {
  57. case IRQ_TYPE_LEVEL_HIGH:
  58. __raw_writel(__raw_readl(LS1X_INTC_INTPOL(n))
  59. | (1 << bit), LS1X_INTC_INTPOL(n));
  60. __raw_writel(__raw_readl(LS1X_INTC_INTEDGE(n))
  61. & ~(1 << bit), LS1X_INTC_INTEDGE(n));
  62. break;
  63. case IRQ_TYPE_LEVEL_LOW:
  64. __raw_writel(__raw_readl(LS1X_INTC_INTPOL(n))
  65. & ~(1 << bit), LS1X_INTC_INTPOL(n));
  66. __raw_writel(__raw_readl(LS1X_INTC_INTEDGE(n))
  67. & ~(1 << bit), LS1X_INTC_INTEDGE(n));
  68. break;
  69. case IRQ_TYPE_EDGE_RISING:
  70. __raw_writel(__raw_readl(LS1X_INTC_INTPOL(n))
  71. | (1 << bit), LS1X_INTC_INTPOL(n));
  72. __raw_writel(__raw_readl(LS1X_INTC_INTEDGE(n))
  73. | (1 << bit), LS1X_INTC_INTEDGE(n));
  74. break;
  75. case IRQ_TYPE_EDGE_FALLING:
  76. __raw_writel(__raw_readl(LS1X_INTC_INTPOL(n))
  77. & ~(1 << bit), LS1X_INTC_INTPOL(n));
  78. __raw_writel(__raw_readl(LS1X_INTC_INTEDGE(n))
  79. | (1 << bit), LS1X_INTC_INTEDGE(n));
  80. break;
  81. case IRQ_TYPE_EDGE_BOTH:
  82. __raw_writel(__raw_readl(LS1X_INTC_INTPOL(n))
  83. & ~(1 << bit), LS1X_INTC_INTPOL(n));
  84. __raw_writel(__raw_readl(LS1X_INTC_INTEDGE(n))
  85. | (1 << bit), LS1X_INTC_INTEDGE(n));
  86. break;
  87. case IRQ_TYPE_NONE:
  88. break;
  89. default:
  90. return -EINVAL;
  91. }
  92. return 0;
  93. }
  94. static struct irq_chip ls1x_irq_chip = {
  95. .name = "LS1X-INTC",
  96. .irq_ack = ls1x_irq_ack,
  97. .irq_mask = ls1x_irq_mask,
  98. .irq_mask_ack = ls1x_irq_mask_ack,
  99. .irq_unmask = ls1x_irq_unmask,
  100. .irq_set_type = ls1x_irq_settype,
  101. };
  102. static void ls1x_irq_dispatch(int n)
  103. {
  104. u32 int_status, irq;
  105. /* Get pending sources, masked by current enables */
  106. int_status = __raw_readl(LS1X_INTC_INTISR(n)) &
  107. __raw_readl(LS1X_INTC_INTIEN(n));
  108. if (int_status) {
  109. irq = LS1X_IRQ(n, __ffs(int_status));
  110. do_IRQ(irq);
  111. }
  112. }
  113. asmlinkage void plat_irq_dispatch(void)
  114. {
  115. unsigned int pending;
  116. pending = read_c0_cause() & read_c0_status() & ST0_IM;
  117. if (pending & CAUSEF_IP7)
  118. do_IRQ(TIMER_IRQ);
  119. else if (pending & CAUSEF_IP2)
  120. ls1x_irq_dispatch(0); /* INT0 */
  121. else if (pending & CAUSEF_IP3)
  122. ls1x_irq_dispatch(1); /* INT1 */
  123. else if (pending & CAUSEF_IP4)
  124. ls1x_irq_dispatch(2); /* INT2 */
  125. else if (pending & CAUSEF_IP5)
  126. ls1x_irq_dispatch(3); /* INT3 */
  127. else if (pending & CAUSEF_IP6)
  128. ls1x_irq_dispatch(4); /* INT4 */
  129. else
  130. spurious_interrupt();
  131. }
  132. static struct irqaction cascade_irqaction = {
  133. .handler = no_action,
  134. .name = "cascade",
  135. .flags = IRQF_NO_THREAD,
  136. };
  137. static void __init ls1x_irq_init(int base)
  138. {
  139. int n;
  140. /* Disable interrupts and clear pending,
  141. * setup all IRQs as high level triggered
  142. */
  143. for (n = 0; n < INTN; n++) {
  144. __raw_writel(0x0, LS1X_INTC_INTIEN(n));
  145. __raw_writel(0xffffffff, LS1X_INTC_INTCLR(n));
  146. __raw_writel(0xffffffff, LS1X_INTC_INTPOL(n));
  147. /* set DMA0, DMA1 and DMA2 to edge trigger */
  148. __raw_writel(n ? 0x0 : 0xe000, LS1X_INTC_INTEDGE(n));
  149. }
  150. for (n = base; n < NR_IRQS; n++) {
  151. irq_set_chip_and_handler(n, &ls1x_irq_chip,
  152. handle_level_irq);
  153. }
  154. setup_irq(INT0_IRQ, &cascade_irqaction);
  155. setup_irq(INT1_IRQ, &cascade_irqaction);
  156. setup_irq(INT2_IRQ, &cascade_irqaction);
  157. setup_irq(INT3_IRQ, &cascade_irqaction);
  158. #if defined(CONFIG_LOONGSON1_LS1C)
  159. setup_irq(INT4_IRQ, &cascade_irqaction);
  160. #endif
  161. }
  162. void __init arch_init_irq(void)
  163. {
  164. mips_cpu_irq_init();
  165. ls1x_irq_init(LS1X_IRQ_BASE);
  166. }