interrupts.c 3.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192
  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. DECLARE_GLOBAL_DATA_PTR;
  25. /*
  26. * CPM interrupt vector functions.
  27. */
  28. struct irq_action {
  29. interrupt_handler_t *handler;
  30. void *arg;
  31. int count;
  32. };
  33. static struct irq_action irq_vecs[IRQ_MAX];
  34. #if defined(CONFIG_440)
  35. /* SPRN changed in 440 */
  36. static __inline__ void set_evpr(unsigned long val)
  37. {
  38. asm volatile("mtspr 0x03f,%0" : : "r" (val));
  39. }
  40. #else /* !defined(CONFIG_440) */
  41. static __inline__ void set_pit(unsigned long val)
  42. {
  43. asm volatile("mtpit %0" : : "r" (val));
  44. }
  45. static __inline__ void set_evpr(unsigned long val)
  46. {
  47. asm volatile("mtevpr %0" : : "r" (val));
  48. }
  49. #endif /* defined(CONFIG_440 */
  50. int interrupt_init_cpu (unsigned *decrementer_count)
  51. {
  52. int vec;
  53. unsigned long val;
  54. /* decrementer is automatically reloaded */
  55. *decrementer_count = 0;
  56. /*
  57. * Mark all irqs as free
  58. */
  59. for (vec = 0; vec < IRQ_MAX; vec++) {
  60. irq_vecs[vec].handler = NULL;
  61. irq_vecs[vec].arg = NULL;
  62. irq_vecs[vec].count = 0;
  63. }
  64. #ifdef CONFIG_4xx
  65. /*
  66. * Init PIT
  67. */
  68. #if defined(CONFIG_440)
  69. val = mfspr( SPRN_TCR );
  70. val &= (~0x04400000); /* clear DIS & ARE */
  71. mtspr( SPRN_TCR, val );
  72. mtspr( SPRN_DEC, 0 ); /* Prevent exception after TSR clear*/
  73. mtspr( SPRN_DECAR, 0 ); /* clear reload */
  74. mtspr( SPRN_TSR, 0x08000000 ); /* clear DEC status */
  75. val = gd->bd->bi_intfreq/1000; /* 1 msec */
  76. mtspr( SPRN_DECAR, val ); /* Set auto-reload value */
  77. mtspr( SPRN_DEC, val ); /* Set inital val */
  78. #else
  79. set_pit(gd->bd->bi_intfreq / 1000);
  80. #endif
  81. #endif /* CONFIG_4xx */
  82. #ifdef CONFIG_ADCIOP
  83. /*
  84. * Init PIT
  85. */
  86. set_pit(66000);
  87. #endif
  88. /*
  89. * Enable PIT
  90. */
  91. val = mfspr(SPRN_TCR);
  92. val |= 0x04400000;
  93. mtspr(SPRN_TCR, val);
  94. /*
  95. * Set EVPR to 0
  96. */
  97. set_evpr(0x00000000);
  98. /*
  99. * Call uic or xilinx_irq pic_enable
  100. */
  101. pic_enable();
  102. return (0);
  103. }
  104. void timer_interrupt_cpu(struct pt_regs *regs)
  105. {
  106. /* nothing to do here */
  107. return;
  108. }
  109. void interrupt_run_handler(int vec)
  110. {
  111. irq_vecs[vec].count++;
  112. if (irq_vecs[vec].handler != NULL) {
  113. /* call isr */
  114. (*irq_vecs[vec].handler) (irq_vecs[vec].arg);
  115. } else {
  116. pic_irq_disable(vec);
  117. printf("Masking bogus interrupt vector %d\n", vec);
  118. }
  119. pic_irq_ack(vec);
  120. return;
  121. }
  122. void irq_install_handler(int vec, interrupt_handler_t * handler, void *arg)
  123. {
  124. /*
  125. * Print warning when replacing with a different irq vector
  126. */
  127. if ((irq_vecs[vec].handler != NULL) && (irq_vecs[vec].handler != handler)) {
  128. printf("Interrupt vector %d: handler 0x%x replacing 0x%x\n",
  129. vec, (uint) handler, (uint) irq_vecs[vec].handler);
  130. }
  131. irq_vecs[vec].handler = handler;
  132. irq_vecs[vec].arg = arg;
  133. pic_irq_enable(vec);
  134. return;
  135. }
  136. void irq_free_handler(int vec)
  137. {
  138. debug("Free interrupt for vector %d ==> %p\n",
  139. vec, irq_vecs[vec].handler);
  140. pic_irq_disable(vec);
  141. irq_vecs[vec].handler = NULL;
  142. irq_vecs[vec].arg = NULL;
  143. return;
  144. }
  145. #if defined(CONFIG_CMD_IRQ)
  146. int do_irqinfo(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
  147. {
  148. int vec;
  149. printf ("Interrupt-Information:\n");
  150. printf ("Nr Routine Arg Count\n");
  151. for (vec = 0; vec < IRQ_MAX; vec++) {
  152. if (irq_vecs[vec].handler != NULL) {
  153. printf ("%02d %08lx %08lx %d\n",
  154. vec,
  155. (ulong)irq_vecs[vec].handler,
  156. (ulong)irq_vecs[vec].arg,
  157. irq_vecs[vec].count);
  158. }
  159. }
  160. return 0;
  161. }
  162. #endif