interrupts.c 4.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207
  1. /*
  2. * (C) Copyright 2000-2002 Wolfgang Denk, DENX Software Engineering, wd@denx.de.
  3. * (C) Copyright 2003 Martin Winistoerfer, martinwinistoerfer@gmx.ch.
  4. *
  5. * See file CREDITS for list of people who contributed to this
  6. * project.
  7. *
  8. * This program is free software; you can redistribute it and/or
  9. * modify it under the terms of the GNU General Public License as
  10. * published by the Free Software Foundation; either version 2 of
  11. * the License, or (at your option) any later version.
  12. *
  13. * This program is distributed in the hope that it will be useful,
  14. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  15. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  16. * GNU General Public License for more details.
  17. *
  18. * You should have received a copy of the GNU General Public License
  19. * along with this program; if not, write to the Free Software
  20. * Foundation,
  21. */
  22. /*
  23. * File: interrupt.c
  24. *
  25. * Discription: Contains interrupt routines needed by U-Boot
  26. *
  27. */
  28. #include <common.h>
  29. #include <command.h>
  30. #include <mpc5xx.h>
  31. #include <asm/processor.h>
  32. #if defined(CONFIG_PATI)
  33. /* PATI uses IRQs for PCI doorbell */
  34. #undef NR_IRQS
  35. #define NR_IRQS 16
  36. #endif
  37. struct interrupt_action {
  38. interrupt_handler_t *handler;
  39. void *arg;
  40. int count;
  41. };
  42. static struct interrupt_action irq_vecs[NR_IRQS];
  43. /*
  44. * Initialise interrupts
  45. */
  46. int interrupt_init_cpu (ulong *decrementer_count)
  47. {
  48. volatile immap_t *immr = (immap_t *) CONFIG_SYS_IMMR;
  49. int vec;
  50. /* Decrementer used here for status led */
  51. *decrementer_count = get_tbclk () / CONFIG_SYS_HZ;
  52. /* Disable all interrupts */
  53. immr->im_siu_conf.sc_simask = 0;
  54. for (vec=0; vec<NR_IRQS; vec++) {
  55. irq_vecs[vec].handler = NULL;
  56. irq_vecs[vec].arg = NULL;
  57. irq_vecs[vec].count = 0;
  58. }
  59. return (0);
  60. }
  61. /*
  62. * Handle external interrupts
  63. */
  64. void external_interrupt (struct pt_regs *regs)
  65. {
  66. volatile immap_t *immr = (immap_t *) CONFIG_SYS_IMMR;
  67. int irq;
  68. ulong simask, newmask;
  69. ulong vec, v_bit;
  70. /*
  71. * read the SIVEC register and shift the bits down
  72. * to get the irq number
  73. */
  74. vec = immr->im_siu_conf.sc_sivec;
  75. irq = vec >> 26;
  76. v_bit = 0x80000000UL >> irq;
  77. /*
  78. * Read Interrupt Mask Register and Mask Interrupts
  79. */
  80. simask = immr->im_siu_conf.sc_simask;
  81. newmask = simask & (~(0xFFFF0000 >> irq));
  82. immr->im_siu_conf.sc_simask = newmask;
  83. if (!(irq & 0x1)) { /* External Interrupt ? */
  84. ulong siel;
  85. /*
  86. * Read Interrupt Edge/Level Register
  87. */
  88. siel = immr->im_siu_conf.sc_siel;
  89. if (siel & v_bit) { /* edge triggered interrupt ? */
  90. /*
  91. * Rewrite SIPEND Register to clear interrupt
  92. */
  93. immr->im_siu_conf.sc_sipend = v_bit;
  94. }
  95. }
  96. if (irq_vecs[irq].handler != NULL) {
  97. irq_vecs[irq].handler (irq_vecs[irq].arg);
  98. } else {
  99. printf ("\nBogus External Interrupt IRQ %d Vector %ld\n",
  100. irq, vec);
  101. /* turn off the bogus interrupt to avoid it from now */
  102. simask &= ~v_bit;
  103. }
  104. /*
  105. * Re-Enable old Interrupt Mask
  106. */
  107. immr->im_siu_conf.sc_simask = simask;
  108. }
  109. /*
  110. * Install and free an interrupt handler
  111. */
  112. void irq_install_handler (int vec, interrupt_handler_t * handler,
  113. void *arg)
  114. {
  115. volatile immap_t *immr = (immap_t *) CONFIG_SYS_IMMR;
  116. /* SIU interrupt */
  117. if (irq_vecs[vec].handler != NULL) {
  118. printf ("SIU interrupt %d 0x%x\n",
  119. vec,
  120. (uint) handler);
  121. }
  122. irq_vecs[vec].handler = handler;
  123. irq_vecs[vec].arg = arg;
  124. immr->im_siu_conf.sc_simask |= 1 << (31 - vec);
  125. #if 0
  126. printf ("Install SIU interrupt for vector %d ==> %p\n",
  127. vec, handler);
  128. #endif
  129. }
  130. void irq_free_handler (int vec)
  131. {
  132. volatile immap_t *immr = (immap_t *) CONFIG_SYS_IMMR;
  133. /* SIU interrupt */
  134. #if 0
  135. printf ("Free CPM interrupt for vector %d\n",
  136. vec);
  137. #endif
  138. immr->im_siu_conf.sc_simask &= ~(1 << (31 - vec));
  139. irq_vecs[vec].handler = NULL;
  140. irq_vecs[vec].arg = NULL;
  141. }
  142. /*
  143. * Timer interrupt - gets called when bit 0 of DEC changes from
  144. * 0. Decrementer is enabled with bit TBE in TBSCR.
  145. */
  146. void timer_interrupt_cpu (struct pt_regs *regs)
  147. {
  148. volatile immap_t *immr = (immap_t *) CONFIG_SYS_IMMR;
  149. #if 0
  150. printf ("*** Timer Interrupt *** ");
  151. #endif
  152. /* Reset Timer Status Bit and Timers Interrupt Status */
  153. immr->im_clkrstk.cark_plprcrk = KAPWR_KEY;
  154. __asm__ ("nop");
  155. immr->im_clkrst.car_plprcr |= PLPRCR_TEXPS | PLPRCR_TMIST;
  156. return;
  157. }
  158. #if defined(CONFIG_CMD_IRQ)
  159. /*******************************************************************************
  160. *
  161. * irqinfo - print information about IRQs
  162. *
  163. */
  164. int do_irqinfo(cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
  165. {
  166. int vec;
  167. printf ("\nInterrupt-Information:\n");
  168. printf ("Nr Routine Arg Count\n");
  169. for (vec=0; vec<NR_IRQS; vec++) {
  170. if (irq_vecs[vec].handler != NULL) {
  171. printf ("%02d %08lx %08lx %d\n",
  172. vec,
  173. (ulong)irq_vecs[vec].handler,
  174. (ulong)irq_vecs[vec].arg,
  175. irq_vecs[vec].count);
  176. }
  177. }
  178. return 0;
  179. }
  180. #endif