interrupts.c 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165
  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 <mpc5xx.h>
  30. #include <asm/processor.h>
  31. struct interrupt_action {
  32. interrupt_handler_t *handler;
  33. void *arg;
  34. };
  35. static struct interrupt_action irq_vecs[NR_IRQS];
  36. /*
  37. * Initialise interrupts
  38. */
  39. int interrupt_init_cpu (ulong *decrementer_count)
  40. {
  41. volatile immap_t *immr = (immap_t *) CFG_IMMR;
  42. /* Decrementer used here for status led */
  43. *decrementer_count = get_tbclk () / CFG_HZ;
  44. /* Disable all interrupts */
  45. immr->im_siu_conf.sc_simask = 0;
  46. return (0);
  47. }
  48. /*
  49. * Handle external interrupts
  50. */
  51. void external_interrupt (struct pt_regs *regs)
  52. {
  53. volatile immap_t *immr = (immap_t *) CFG_IMMR;
  54. int irq;
  55. ulong simask, newmask;
  56. ulong vec, v_bit;
  57. /*
  58. * read the SIVEC register and shift the bits down
  59. * to get the irq number
  60. */
  61. vec = immr->im_siu_conf.sc_sivec;
  62. irq = vec >> 26;
  63. v_bit = 0x80000000UL >> irq;
  64. /*
  65. * Read Interrupt Mask Register and Mask Interrupts
  66. */
  67. simask = immr->im_siu_conf.sc_simask;
  68. newmask = simask & (~(0xFFFF0000 >> irq));
  69. immr->im_siu_conf.sc_simask = newmask;
  70. if (!(irq & 0x1)) { /* External Interrupt ? */
  71. ulong siel;
  72. /*
  73. * Read Interrupt Edge/Level Register
  74. */
  75. siel = immr->im_siu_conf.sc_siel;
  76. if (siel & v_bit) { /* edge triggered interrupt ? */
  77. /*
  78. * Rewrite SIPEND Register to clear interrupt
  79. */
  80. immr->im_siu_conf.sc_sipend = v_bit;
  81. }
  82. }
  83. if (irq_vecs[irq].handler != NULL) {
  84. irq_vecs[irq].handler (irq_vecs[irq].arg);
  85. } else {
  86. printf ("\nBogus External Interrupt IRQ %d Vector %ld\n",
  87. irq, vec);
  88. /* turn off the bogus interrupt to avoid it from now */
  89. simask &= ~v_bit;
  90. }
  91. /*
  92. * Re-Enable old Interrupt Mask
  93. */
  94. immr->im_siu_conf.sc_simask = simask;
  95. }
  96. /*
  97. * Install and free an interrupt handler
  98. */
  99. void irq_install_handler (int vec, interrupt_handler_t * handler,
  100. void *arg)
  101. {
  102. volatile immap_t *immr = (immap_t *) CFG_IMMR;
  103. /* SIU interrupt */
  104. if (irq_vecs[vec].handler != NULL) {
  105. printf ("SIU interrupt %d 0x%x\n",
  106. vec,
  107. (uint) handler);
  108. }
  109. irq_vecs[vec].handler = handler;
  110. irq_vecs[vec].arg = arg;
  111. immr->im_siu_conf.sc_simask |= 1 << (31 - vec);
  112. #if 0
  113. printf ("Install SIU interrupt for vector %d ==> %p\n",
  114. vec, handler);
  115. #endif
  116. }
  117. void irq_free_handler (int vec)
  118. {
  119. volatile immap_t *immr = (immap_t *) CFG_IMMR;
  120. /* SIU interrupt */
  121. #if 0
  122. printf ("Free CPM interrupt for vector %d\n",
  123. vec);
  124. #endif
  125. immr->im_siu_conf.sc_simask &= ~(1 << (31 - vec));
  126. irq_vecs[vec].handler = NULL;
  127. irq_vecs[vec].arg = NULL;
  128. }
  129. /*
  130. * Timer interrupt - gets called when bit 0 of DEC changes from
  131. * 0. Decrementer is enabled with bit TBE in TBSCR.
  132. */
  133. void timer_interrupt_cpu (struct pt_regs *regs)
  134. {
  135. volatile immap_t *immr = (immap_t *) CFG_IMMR;
  136. #if 0
  137. printf ("*** Timer Interrupt *** ");
  138. #endif
  139. /* Reset Timer Status Bit and Timers Interrupt Status */
  140. immr->im_clkrstk.cark_plprcrk = KAPWR_KEY;
  141. __asm__ ("nop");
  142. immr->im_clkrst.car_plprcr |= PLPRCR_TEXPS | PLPRCR_TMIST;
  143. return;
  144. }