gt_irq.c
上传用户:lgb322
上传日期:2013-02-24
资源大小:30529k
文件大小:7k
源码类别:

嵌入式Linux

开发平台:

Unix_Linux

  1. /*
  2.  *
  3.  * Copyright 2001 MontaVista Software Inc.
  4.  * Author: jsun@mvista.com or jsun@junsun.net
  5.  *
  6.  * arch/mips/gt64120/common/gt_irq.c
  7.  *     Interrupt routines for gt64120.  Currently it only handles timer irq.
  8.  *
  9.  * This program is free software; you can redistribute  it and/or modify it
  10.  * under  the terms of  the GNU General  Public License as published by the
  11.  * Free Software Foundation;  either version 2 of the  License, or (at your
  12.  * option) any later version.
  13.  */
  14. #include <linux/module.h>
  15. #include <linux/interrupt.h>
  16. #include <linux/kernel.h>
  17. #include <asm/ptrace.h>
  18. #include <linux/config.h>
  19. #include <linux/sched.h>
  20. #include <linux/kernel_stat.h>
  21. #include <asm/io.h>
  22. #include <asm/gt64120/gt64120.h>
  23. /*
  24.  * These are interrupt handlers for the GT on-chip interrupts.  They
  25.  * all come in to the MIPS on a single interrupt line, and have to
  26.  * be handled and ack'ed differently than other MIPS interrupts.
  27.  */
  28. #if CURRENTLY_UNUSED
  29. struct tq_struct irq_handlers[MAX_CAUSE_REGS][MAX_CAUSE_REG_WIDTH];
  30. void hook_irq_handler(int int_cause, int bit_num, void *isr_ptr);
  31. /*
  32.  * Hooks IRQ handler to the system. When the system is interrupted
  33.  * the interrupt service routine is called.
  34.  *
  35.  * Inputs :
  36.  * int_cause - The interrupt cause number. In EVB64120 two parameters 
  37.  *             are declared, INT_CAUSE_MAIN and INT_CAUSE_HIGH. 
  38.  * bit_num   - Indicates which bit number in the cause register
  39.  * isr_ptr   - Pointer to the interrupt service routine
  40.  */
  41. void hook_irq_handler(int int_cause, int bit_num, void *isr_ptr)
  42. {
  43. irq_handlers[int_cause][bit_num].routine = isr_ptr;
  44. }
  45. /*
  46.  * Enables the IRQ on Galileo Chip
  47.  *
  48.  * Inputs :
  49.  * int_cause - The interrupt cause number. In EVB64120 two parameters 
  50.  *             are declared, INT_CAUSE_MAIN and INT_CAUSE_HIGH.
  51.  * bit_num   - Indicates which bit number in the cause register
  52.  *
  53.  * Outputs :
  54.  * 1 if succesful, 0 if failure
  55.  */
  56. int enable_galileo_irq(int int_cause, int bit_num)
  57. {
  58. if (int_cause == INT_CAUSE_MAIN)
  59. SET_REG_BITS(CPU_INTERRUPT_MASK_REGISTER, (1 << bit_num));
  60. else if (int_cause == INT_CAUSE_HIGH)
  61. SET_REG_BITS(CPU_HIGH_INTERRUPT_MASK_REGISTER,
  62.      (1 << bit_num));
  63. else
  64. return 0;
  65. return 1;
  66. }
  67. /*
  68.  * Disables the IRQ on Galileo Chip
  69.  *
  70.  * Inputs :
  71.  * int_cause - The interrupt cause number. In EVB64120 two parameters 
  72.  *             are declared, INT_CAUSE_MAIN and INT_CAUSE_HIGH.
  73.  * bit_num   - Indicates which bit number in the cause register
  74.  *
  75.  * Outputs :
  76.  * 1 if succesful, 0 if failure
  77.  */
  78. int disable_galileo_irq(int int_cause, int bit_num)
  79. {
  80. if (int_cause == INT_CAUSE_MAIN)
  81. RESET_REG_BITS(CPU_INTERRUPT_MASK_REGISTER,
  82.        (1 << bit_num));
  83. else if (int_cause == INT_CAUSE_HIGH)
  84. RESET_REG_BITS(CPU_HIGH_INTERRUPT_MASK_REGISTER,
  85.        (1 << bit_num));
  86. else
  87. return 0;
  88. return 1;
  89. }
  90. #endif /*  UNUSED  */
  91. /*
  92.  * Interrupt handler for interrupts coming from the Galileo chip.
  93.  * It could be timer interrupt, built in ethernet ports etc...
  94.  */
  95. static void gt64120_irq(int irq, void *dev_id, struct pt_regs *regs)
  96. {
  97. unsigned int irq_src, int_high_src, irq_src_mask,
  98.     int_high_src_mask;
  99. int handled;
  100. GT_READ(GT_INTRCAUSE_OFS, &irq_src);
  101. GT_READ(GT_INTRMASK_OFS, &irq_src_mask);
  102. GT_READ(GT_HINTRCAUSE_OFS, &int_high_src);
  103. GT_READ(GT_HINTRMASK_OFS, &int_high_src_mask);
  104. irq_src = irq_src & irq_src_mask;
  105. int_high_src = int_high_src & int_high_src_mask;
  106. handled = 0;
  107. /* Execute all interrupt handlers */
  108. /* Check for timer interrupt */
  109. if (irq_src & 0x00000800) {
  110. handled = 1;
  111. irq_src &= ~0x00000800;
  112. //    RESET_REG_BITS (INTERRUPT_CAUSE_REGISTER,BIT8);
  113. do_timer(regs);
  114. }
  115. if (irq_src) {
  116. printk(KERN_INFO
  117.        "Other Galileo interrupt received irq_src %xn",
  118.        irq_src);
  119. #if CURRENTLY_UNUSED
  120. for (count = 0; count < MAX_CAUSE_REG_WIDTH; count++) {
  121. if (irq_src & (1 << count)) {
  122. if (irq_handlers[INT_CAUSE_MAIN][count].
  123.     routine) {
  124. queue_task(&irq_handlers
  125.    [INT_CAUSE_MAIN][count],
  126.    &tq_immediate);
  127. mark_bh(IMMEDIATE_BH);
  128. handled = 1;
  129. }
  130. }
  131. }
  132. #endif /*  UNUSED  */
  133. }
  134. GT_WRITE(GT_INTRCAUSE_OFS, 0);
  135. GT_WRITE(GT_HINTRCAUSE_OFS, 0);
  136. #undef GALILEO_I2O
  137. #ifdef GALILEO_I2O
  138. /*
  139.  * Future I2O support.  We currently attach I2O interrupt handlers to
  140.  * the Galileo interrupt (int 4) and handle them in do_IRQ.
  141.  */
  142. if (isInBoundDoorBellInterruptSet()) {
  143. printk(KERN_INFO "I2O doorbell interrupt received.n");
  144. handled = 1;
  145. }
  146. if (isInBoundPostQueueInterruptSet()) {
  147. printk(KERN_INFO "I2O Queue interrupt received.n");
  148. handled = 1;
  149. }
  150. /*
  151.  * This normally would be outside of the ifdef, but since we're
  152.  * handling I2O outside of this handler, this printk shows up every
  153.  * time we get a valid I2O interrupt.  So turn this off for now.
  154.  */
  155. if (handled == 0) {
  156. if (counter < 50) {
  157. printk("Spurious Galileo interrupt...n");
  158. counter++;
  159. }
  160. }
  161. #endif
  162. }
  163. /*
  164.  * Initializes timer using galileo's built in timer.
  165.  */
  166. #ifdef CONFIG_SYSCLK_100
  167. #define Sys_clock (100 * 1000000) // 100 MHz
  168. #endif
  169. #ifdef CONFIG_SYSCLK_83
  170. #define Sys_clock (83.333 * 1000000) // 83.333 MHz
  171. #endif
  172. #ifdef CONFIG_SYSCLK_75
  173. #define Sys_clock (75 * 1000000) // 75 MHz
  174. #endif
  175. /*
  176.  * This will ignore the standard MIPS timer interrupt handler
  177.  * that is passed in as *irq (=irq0 in ../kernel/time.c).
  178.  * We will do our own timer interrupt handling.
  179.  */
  180. void gt64120_time_init(void)
  181. {
  182. extern irq_desc_t irq_desc[NR_IRQS];
  183. static struct irqaction timer;
  184. /* Disable timer first */
  185. GT_WRITE(GT_TC_CONTROL_OFS, 0);
  186. /* Load timer value for 100 Hz */
  187. GT_WRITE(GT_TC3_OFS, Sys_clock / 100);
  188. /*
  189.  * Create the IRQ structure entry for the timer.  Since we're too early
  190.  * in the boot process to use the "request_irq()" call, we'll hard-code
  191.  * the values to the correct interrupt line.
  192.  */
  193. timer.handler = &gt64120_irq;
  194. timer.flags = SA_SHIRQ | SA_INTERRUPT;
  195. timer.name = "timer";
  196. timer.dev_id = NULL;
  197. timer.next = NULL;
  198. timer.mask = 0;
  199. irq_desc[TIMER].action = &timer;
  200. enable_irq(TIMER);
  201. /* Enable timer ints */
  202. GT_WRITE(GT_TC_CONTROL_OFS, 0xc0);
  203. /* clear Cause register first */
  204. GT_WRITE(GT_INTRCAUSE_OFS, 0x0);
  205. /* Unmask timer int */
  206. GT_WRITE(GT_INTRMASK_OFS, 0x800);
  207. /* Clear High int register */
  208. GT_WRITE(GT_HINTRCAUSE_OFS, 0x0);
  209. /* Mask All interrupts at High cause interrupt */
  210. GT_WRITE(GT_HINTRMASK_OFS, 0x0);
  211. }
  212. void gt64120_irq_init(void)
  213. {
  214. #if CURRENTLY_UNUSED
  215. int i, j;
  216. /* Reset irq handlers pointers to NULL */
  217. for (i = 0; i < MAX_CAUSE_REGS; i++) {
  218. for (j = 0; j < MAX_CAUSE_REG_WIDTH; j++) {
  219. irq_handlers[i][j].next = NULL;
  220. irq_handlers[i][j].sync = 0;
  221. irq_handlers[i][j].routine = NULL;
  222. irq_handlers[i][j].data = NULL;
  223. }
  224. }
  225. #endif
  226. }