irq.c
上传用户:jlfgdled
上传日期:2013-04-10
资源大小:33168k
文件大小:6k
源码类别:

Linux/Unix编程

开发平台:

Unix_Linux

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