gt-irq.c 5.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213
  1. /*
  2. *
  3. * Copyright 2002 Momentum Computer
  4. * Author: mdharm@momenco.com
  5. *
  6. * arch/mips/momentum/ocelot_g/gt_irq.c
  7. * Interrupt routines for gt64240. 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/sched.h>
  19. #include <linux/kernel_stat.h>
  20. #include <asm/gt64240.h>
  21. #include <asm/io.h>
  22. unsigned long bus_clock;
  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 successful, 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 successful, 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 via P0_INT#.
  93. *
  94. * We route the timer interrupt to P0_INT# (IRQ 6), and that's all this
  95. * routine can handle, for now.
  96. *
  97. * In the future, we'll route more interrupts to this pin, and that's why
  98. * we keep this particular structure in the function.
  99. */
  100. static irqreturn_t gt64240_p0int_irq(int irq, void *dev, struct pt_regs *regs)
  101. {
  102. uint32_t irq_src, irq_src_mask;
  103. int handled;
  104. /* get the low interrupt cause register */
  105. irq_src = MV_READ(LOW_INTERRUPT_CAUSE_REGISTER);
  106. /* get the mask register for this pin */
  107. irq_src_mask = MV_READ(PCI_0INTERRUPT_CAUSE_MASK_REGISTER_LOW);
  108. /* mask off only the interrupts we're interested in */
  109. irq_src = irq_src & irq_src_mask;
  110. handled = IRQ_NONE;
  111. /* Check for timer interrupt */
  112. if (irq_src & 0x00000100) {
  113. handled = IRQ_HANDLED;
  114. irq_src &= ~0x00000100;
  115. /* Clear any pending cause bits */
  116. MV_WRITE(TIMER_COUNTER_0_3_INTERRUPT_CAUSE, 0x0);
  117. /* handle the timer call */
  118. do_timer(regs);
  119. #ifndef CONFIG_SMP
  120. update_process_times(user_mode(regs));
  121. #endif
  122. }
  123. if (irq_src) {
  124. printk(KERN_INFO
  125. "UNKNOWN P0_INT# interrupt received, irq_src=0x%x\n",
  126. irq_src);
  127. }
  128. return handled;
  129. }
  130. /*
  131. * Initializes timer using galileo's built in timer.
  132. */
  133. /*
  134. * This will ignore the standard MIPS timer interrupt handler
  135. * that is passed in as *irq (=irq0 in ../kernel/time.c).
  136. * We will do our own timer interrupt handling.
  137. */
  138. void gt64240_time_init(void)
  139. {
  140. static struct irqaction timer;
  141. /* Stop the timer -- we'll use timer #0 */
  142. MV_WRITE(TIMER_COUNTER_0_3_CONTROL, 0x0);
  143. /* Load timer value for 100 Hz */
  144. MV_WRITE(TIMER_COUNTER0, bus_clock / 100);
  145. /*
  146. * Create the IRQ structure entry for the timer. Since we're too early
  147. * in the boot process to use the "request_irq()" call, we'll hard-code
  148. * the values to the correct interrupt line.
  149. */
  150. timer.handler = &gt64240_p0int_irq;
  151. timer.flags = IRQF_SHARED | IRQF_DISABLED;
  152. timer.name = "timer";
  153. timer.dev_id = NULL;
  154. timer.next = NULL;
  155. timer.mask = CPU_MASK_NONE;
  156. irq_desc[6].action = &timer;
  157. enable_irq(6);
  158. /* Clear any pending cause bits */
  159. MV_WRITE(TIMER_COUNTER_0_3_INTERRUPT_CAUSE, 0x0);
  160. /* Enable the interrupt for timer 0 */
  161. MV_WRITE(TIMER_COUNTER_0_3_INTERRUPT_MASK, 0x1);
  162. /* Enable the timer interrupt for GT-64240 pin P0_INT# */
  163. MV_WRITE (PCI_0INTERRUPT_CAUSE_MASK_REGISTER_LOW, 0x100);
  164. /* Configure and start the timer */
  165. MV_WRITE(TIMER_COUNTER_0_3_CONTROL, 0x3);
  166. }
  167. void gt64240_irq_init(void)
  168. {
  169. #if CURRENTLY_UNUSED
  170. int i, j;
  171. /* Reset irq handlers pointers to NULL */
  172. for (i = 0; i < MAX_CAUSE_REGS; i++) {
  173. for (j = 0; j < MAX_CAUSE_REG_WIDTH; j++) {
  174. irq_handlers[i][j].next = NULL;
  175. irq_handlers[i][j].sync = 0;
  176. irq_handlers[i][j].routine = NULL;
  177. irq_handlers[i][j].data = NULL;
  178. }
  179. }
  180. #endif
  181. }