irq.c 5.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239
  1. /*
  2. * Copyright (C) 2001 MontaVista Software Inc.
  3. * Author: Jun Sun, jsun@mvista.com or jsun@junsun.net
  4. * Copyright (C) 2005 Ralf Baechle (ralf@linux-mips.org)
  5. *
  6. * linux/arch/mips/vr4181/common/irq.c
  7. * Completely re-written to use the new irq.c
  8. *
  9. * Credits to Bradley D. LaRonde and Michael Klar for writing the original
  10. * irq.c file which was derived from the common irq.c file.
  11. *
  12. * This file is subject to the terms and conditions of the GNU General Public
  13. * License. See the file "COPYING" in the main directory of this archive
  14. * for more details.
  15. */
  16. #include <linux/types.h>
  17. #include <linux/init.h>
  18. #include <linux/kernel_stat.h>
  19. #include <linux/signal.h>
  20. #include <linux/sched.h>
  21. #include <linux/interrupt.h>
  22. #include <linux/slab.h>
  23. #include <linux/random.h>
  24. #include <asm/irq.h>
  25. #include <asm/mipsregs.h>
  26. #include <asm/gdb-stub.h>
  27. #include <asm/vr4181/vr4181.h>
  28. /*
  29. * Strategy:
  30. *
  31. * We essentially have three irq controllers, CPU, system, and gpio.
  32. *
  33. * CPU irq controller is taken care by arch/mips/kernel/irq_cpu.c and
  34. * CONFIG_IRQ_CPU config option.
  35. *
  36. * We here provide sys_irq and gpio_irq controller code.
  37. */
  38. static int sys_irq_base;
  39. static int gpio_irq_base;
  40. /* ---------------------- sys irq ------------------------ */
  41. static void
  42. sys_irq_enable(unsigned int irq)
  43. {
  44. irq -= sys_irq_base;
  45. if (irq < 16) {
  46. *VR4181_MSYSINT1REG |= (u16)(1 << irq);
  47. } else {
  48. irq -= 16;
  49. *VR4181_MSYSINT2REG |= (u16)(1 << irq);
  50. }
  51. }
  52. static void
  53. sys_irq_disable(unsigned int irq)
  54. {
  55. irq -= sys_irq_base;
  56. if (irq < 16) {
  57. *VR4181_MSYSINT1REG &= ~((u16)(1 << irq));
  58. } else {
  59. irq -= 16;
  60. *VR4181_MSYSINT2REG &= ~((u16)(1 << irq));
  61. }
  62. }
  63. static unsigned int
  64. sys_irq_startup(unsigned int irq)
  65. {
  66. sys_irq_enable(irq);
  67. return 0;
  68. }
  69. #define sys_irq_shutdown sys_irq_disable
  70. #define sys_irq_ack sys_irq_disable
  71. static void
  72. sys_irq_end(unsigned int irq)
  73. {
  74. if(!(irq_desc[irq].status & (IRQ_DISABLED | IRQ_INPROGRESS)))
  75. sys_irq_enable(irq);
  76. }
  77. static hw_irq_controller sys_irq_controller = {
  78. "vr4181_sys_irq",
  79. sys_irq_startup,
  80. sys_irq_shutdown,
  81. sys_irq_enable,
  82. sys_irq_disable,
  83. sys_irq_ack,
  84. sys_irq_end,
  85. NULL /* no affinity stuff for UP */
  86. };
  87. /* ---------------------- gpio irq ------------------------ */
  88. /* gpio irq lines use reverse logic */
  89. static void
  90. gpio_irq_enable(unsigned int irq)
  91. {
  92. irq -= gpio_irq_base;
  93. *VR4181_GPINTMSK &= ~((u16)(1 << irq));
  94. }
  95. static void
  96. gpio_irq_disable(unsigned int irq)
  97. {
  98. irq -= gpio_irq_base;
  99. *VR4181_GPINTMSK |= (u16)(1 << irq);
  100. }
  101. static unsigned int
  102. gpio_irq_startup(unsigned int irq)
  103. {
  104. gpio_irq_enable(irq);
  105. irq -= gpio_irq_base;
  106. *VR4181_GPINTEN |= (u16)(1 << irq );
  107. return 0;
  108. }
  109. static void
  110. gpio_irq_shutdown(unsigned int irq)
  111. {
  112. gpio_irq_disable(irq);
  113. irq -= gpio_irq_base;
  114. *VR4181_GPINTEN &= ~((u16)(1 << irq ));
  115. }
  116. static void
  117. gpio_irq_ack(unsigned int irq)
  118. {
  119. u16 irqtype;
  120. u16 irqshift;
  121. gpio_irq_disable(irq);
  122. /* we clear interrupt if it is edge triggered */
  123. irq -= gpio_irq_base;
  124. if (irq < 8) {
  125. irqtype = *VR4181_GPINTTYPL;
  126. irqshift = 2 << (irq*2);
  127. } else {
  128. irqtype = *VR4181_GPINTTYPH;
  129. irqshift = 2 << ((irq-8)*2);
  130. }
  131. if ( ! (irqtype & irqshift) ) {
  132. *VR4181_GPINTSTAT = (u16) (1 << irq);
  133. }
  134. }
  135. static void
  136. gpio_irq_end(unsigned int irq)
  137. {
  138. if(!(irq_desc[irq].status & (IRQ_DISABLED | IRQ_INPROGRESS)))
  139. gpio_irq_enable(irq);
  140. }
  141. static hw_irq_controller gpio_irq_controller = {
  142. "vr4181_gpio_irq",
  143. gpio_irq_startup,
  144. gpio_irq_shutdown,
  145. gpio_irq_enable,
  146. gpio_irq_disable,
  147. gpio_irq_ack,
  148. gpio_irq_end,
  149. NULL /* no affinity stuff for UP */
  150. };
  151. /* --------------------- IRQ init stuff ---------------------- */
  152. extern asmlinkage void vr4181_handle_irq(void);
  153. extern void breakpoint(void);
  154. extern int setup_irq(unsigned int irq, struct irqaction *irqaction);
  155. extern void mips_cpu_irq_init(u32 irq_base);
  156. static struct irqaction cascade =
  157. { no_action, SA_INTERRUPT, CPU_MASK_NONE, "cascade", NULL, NULL };
  158. static struct irqaction reserved =
  159. { no_action, SA_INTERRUPT, CPU_MASK_NONE, "cascade", NULL, NULL };
  160. void __init arch_init_irq(void)
  161. {
  162. int i;
  163. set_except_vector(0, vr4181_handle_irq);
  164. /* init CPU irqs */
  165. mips_cpu_irq_init(VR4181_CPU_IRQ_BASE);
  166. /* init sys irqs */
  167. sys_irq_base = VR4181_SYS_IRQ_BASE;
  168. for (i=sys_irq_base; i < sys_irq_base + VR4181_NUM_SYS_IRQ; i++) {
  169. irq_desc[i].status = IRQ_DISABLED;
  170. irq_desc[i].action = NULL;
  171. irq_desc[i].depth = 1;
  172. irq_desc[i].handler = &sys_irq_controller;
  173. }
  174. /* init gpio irqs */
  175. gpio_irq_base = VR4181_GPIO_IRQ_BASE;
  176. for (i=gpio_irq_base; i < gpio_irq_base + VR4181_NUM_GPIO_IRQ; i++) {
  177. irq_desc[i].status = IRQ_DISABLED;
  178. irq_desc[i].action = NULL;
  179. irq_desc[i].depth = 1;
  180. irq_desc[i].handler = &gpio_irq_controller;
  181. }
  182. /* Default all ICU IRQs to off ... */
  183. *VR4181_MSYSINT1REG = 0;
  184. *VR4181_MSYSINT2REG = 0;
  185. /* We initialize the level 2 ICU registers to all bits disabled. */
  186. *VR4181_MPIUINTREG = 0;
  187. *VR4181_MAIUINTREG = 0;
  188. *VR4181_MKIUINTREG = 0;
  189. /* disable all GPIO intrs */
  190. *VR4181_GPINTMSK = 0xffff;
  191. /* vector handler. What these do is register the IRQ as non-sharable */
  192. setup_irq(VR4181_IRQ_INT0, &cascade);
  193. setup_irq(VR4181_IRQ_GIU, &cascade);
  194. /*
  195. * RTC interrupts are interesting. They have two destinations.
  196. * One is at sys irq controller, and the other is at CPU IP3 and IP4.
  197. * RTC timer is used as system timer.
  198. * We enable them here, but timer routine will register later
  199. * with CPU IP3/IP4.
  200. */
  201. setup_irq(VR4181_IRQ_RTCL1, &reserved);
  202. setup_irq(VR4181_IRQ_RTCL2, &reserved);
  203. }