interrupts.c 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193
  1. /*
  2. * (C) Copyright 2000-2002
  3. * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
  4. *
  5. * (C) Copyright 2002 (440 port)
  6. * Scott McNutt, Artesyn Communication Producs, smcnutt@artsyncp.com
  7. *
  8. * (C) Copyright 2003 (440GX port)
  9. * Travis B. Sawyer, Sandburst Corporation, tsawyer@sandburst.com
  10. *
  11. * (C) Copyright 2008 (PPC440X05 port for Virtex 5 FX)
  12. * Ricardo Ribalda-Universidad Autonoma de Madrid-ricardo.ribalda@gmail.com
  13. * Work supported by Qtechnology (htpp://qtec.com)
  14. *
  15. * SPDX-License-Identifier: GPL-2.0+
  16. */
  17. #include <common.h>
  18. #include <watchdog.h>
  19. #include <command.h>
  20. #include <asm/processor.h>
  21. #include <asm/interrupt.h>
  22. #include <asm/ppc4xx.h>
  23. #include <ppc_asm.tmpl>
  24. #include <commproc.h>
  25. DECLARE_GLOBAL_DATA_PTR;
  26. /*
  27. * CPM interrupt vector functions.
  28. */
  29. struct irq_action {
  30. interrupt_handler_t *handler;
  31. void *arg;
  32. int count;
  33. };
  34. static struct irq_action irq_vecs[IRQ_MAX];
  35. #if defined(CONFIG_440)
  36. /* SPRN changed in 440 */
  37. static __inline__ void set_evpr(unsigned long val)
  38. {
  39. asm volatile("mtspr 0x03f,%0" : : "r" (val));
  40. }
  41. #else /* !defined(CONFIG_440) */
  42. static __inline__ void set_pit(unsigned long val)
  43. {
  44. asm volatile("mtpit %0" : : "r" (val));
  45. }
  46. static __inline__ void set_evpr(unsigned long val)
  47. {
  48. asm volatile("mtevpr %0" : : "r" (val));
  49. }
  50. #endif /* defined(CONFIG_440 */
  51. int interrupt_init_cpu (unsigned *decrementer_count)
  52. {
  53. int vec;
  54. unsigned long val;
  55. /* decrementer is automatically reloaded */
  56. *decrementer_count = 0;
  57. /*
  58. * Mark all irqs as free
  59. */
  60. for (vec = 0; vec < IRQ_MAX; vec++) {
  61. irq_vecs[vec].handler = NULL;
  62. irq_vecs[vec].arg = NULL;
  63. irq_vecs[vec].count = 0;
  64. }
  65. #ifdef CONFIG_4xx
  66. /*
  67. * Init PIT
  68. */
  69. #if defined(CONFIG_440)
  70. val = mfspr( SPRN_TCR );
  71. val &= (~0x04400000); /* clear DIS & ARE */
  72. mtspr( SPRN_TCR, val );
  73. mtspr( SPRN_DEC, 0 ); /* Prevent exception after TSR clear*/
  74. mtspr( SPRN_DECAR, 0 ); /* clear reload */
  75. mtspr( SPRN_TSR, 0x08000000 ); /* clear DEC status */
  76. val = gd->bd->bi_intfreq/1000; /* 1 msec */
  77. mtspr( SPRN_DECAR, val ); /* Set auto-reload value */
  78. mtspr( SPRN_DEC, val ); /* Set inital val */
  79. #else
  80. set_pit(gd->bd->bi_intfreq / 1000);
  81. #endif
  82. #endif /* CONFIG_4xx */
  83. #ifdef CONFIG_ADCIOP
  84. /*
  85. * Init PIT
  86. */
  87. set_pit(66000);
  88. #endif
  89. /*
  90. * Enable PIT
  91. */
  92. val = mfspr(SPRN_TCR);
  93. val |= 0x04400000;
  94. mtspr(SPRN_TCR, val);
  95. /*
  96. * Set EVPR to 0
  97. */
  98. set_evpr(0x00000000);
  99. /*
  100. * Call uic or xilinx_irq pic_enable
  101. */
  102. pic_enable();
  103. return (0);
  104. }
  105. void timer_interrupt_cpu(struct pt_regs *regs)
  106. {
  107. /* nothing to do here */
  108. return;
  109. }
  110. void interrupt_run_handler(int vec)
  111. {
  112. irq_vecs[vec].count++;
  113. if (irq_vecs[vec].handler != NULL) {
  114. /* call isr */
  115. (*irq_vecs[vec].handler) (irq_vecs[vec].arg);
  116. } else {
  117. pic_irq_disable(vec);
  118. printf("Masking bogus interrupt vector %d\n", vec);
  119. }
  120. pic_irq_ack(vec);
  121. return;
  122. }
  123. void irq_install_handler(int vec, interrupt_handler_t * handler, void *arg)
  124. {
  125. /*
  126. * Print warning when replacing with a different irq vector
  127. */
  128. if ((irq_vecs[vec].handler != NULL) && (irq_vecs[vec].handler != handler)) {
  129. printf("Interrupt vector %d: handler 0x%x replacing 0x%x\n",
  130. vec, (uint) handler, (uint) irq_vecs[vec].handler);
  131. }
  132. irq_vecs[vec].handler = handler;
  133. irq_vecs[vec].arg = arg;
  134. pic_irq_enable(vec);
  135. return;
  136. }
  137. void irq_free_handler(int vec)
  138. {
  139. debug("Free interrupt for vector %d ==> %p\n",
  140. vec, irq_vecs[vec].handler);
  141. pic_irq_disable(vec);
  142. irq_vecs[vec].handler = NULL;
  143. irq_vecs[vec].arg = NULL;
  144. return;
  145. }
  146. #if defined(CONFIG_CMD_IRQ)
  147. int do_irqinfo(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
  148. {
  149. int vec;
  150. printf ("Interrupt-Information:\n");
  151. printf ("Nr Routine Arg Count\n");
  152. for (vec = 0; vec < IRQ_MAX; vec++) {
  153. if (irq_vecs[vec].handler != NULL) {
  154. printf ("%02d %08lx %08lx %d\n",
  155. vec,
  156. (ulong)irq_vecs[vec].handler,
  157. (ulong)irq_vecs[vec].arg,
  158. irq_vecs[vec].count);
  159. }
  160. }
  161. return 0;
  162. }
  163. #endif