interrupts.c 7.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334
  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. * See file CREDITS for list of people who contributed to this
  12. * project.
  13. *
  14. * This program is free software; you can redistribute it and/or
  15. * modify it under the terms of the GNU General Public License as
  16. * published by the Free Software Foundation; either version 2 of
  17. * the License, or (at your option) any later version.
  18. *
  19. * This program is distributed in the hope that it will be useful,
  20. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  21. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  22. * GNU General Public License for more details.
  23. *
  24. * You should have received a copy of the GNU General Public License
  25. * along with this program; if not, write to the Free Software
  26. * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
  27. * MA 02111-1307 USA
  28. */
  29. #include <common.h>
  30. #include <watchdog.h>
  31. #include <command.h>
  32. #include <asm/processor.h>
  33. #include <ppc4xx.h>
  34. #include <ppc_asm.tmpl>
  35. #include <commproc.h>
  36. #if (UIC_MAX > 3)
  37. #define UICB0_ALL (UIC_MASK(VECNUM_UIC1CI) | UIC_MASK(VECNUM_UIC1NCI) | \
  38. UIC_MASK(VECNUM_UIC2CI) | UIC_MASK(VECNUM_UIC2NCI) | \
  39. UIC_MASK(VECNUM_UIC3CI) | UIC_MASK(VECNUM_UIC3NCI))
  40. #elif (UIC_MAX > 2)
  41. #define UICB0_ALL (UIC_MASK(VECNUM_UIC1CI) | UIC_MASK(VECNUM_UIC1NCI) | \
  42. UIC_MASK(VECNUM_UIC2CI) | UIC_MASK(VECNUM_UIC2NCI))
  43. #elif (UIC_MAX > 1)
  44. #define UICB0_ALL (UIC_MASK(VECNUM_UIC1CI) | UIC_MASK(VECNUM_UIC1NCI))
  45. #else
  46. #define UICB0_ALL 0
  47. #endif
  48. DECLARE_GLOBAL_DATA_PTR;
  49. /*
  50. * CPM interrupt vector functions.
  51. */
  52. struct irq_action {
  53. interrupt_handler_t *handler;
  54. void *arg;
  55. int count;
  56. };
  57. static struct irq_action irq_vecs[UIC_MAX * 32];
  58. u32 get_dcr(u16);
  59. void set_dcr(u16, u32);
  60. #if defined(CONFIG_440)
  61. /* SPRN changed in 440 */
  62. static __inline__ void set_evpr(unsigned long val)
  63. {
  64. asm volatile("mtspr 0x03f,%0" : : "r" (val));
  65. }
  66. #else /* !defined(CONFIG_440) */
  67. static __inline__ void set_pit(unsigned long val)
  68. {
  69. asm volatile("mtpit %0" : : "r" (val));
  70. }
  71. static __inline__ void set_tcr(unsigned long val)
  72. {
  73. asm volatile("mttcr %0" : : "r" (val));
  74. }
  75. static __inline__ void set_evpr(unsigned long val)
  76. {
  77. asm volatile("mtevpr %0" : : "r" (val));
  78. }
  79. #endif /* defined(CONFIG_440 */
  80. int interrupt_init_cpu (unsigned *decrementer_count)
  81. {
  82. int vec;
  83. unsigned long val;
  84. /* decrementer is automatically reloaded */
  85. *decrementer_count = 0;
  86. /*
  87. * Mark all irqs as free
  88. */
  89. for (vec = 0; vec < (UIC_MAX * 32); vec++) {
  90. irq_vecs[vec].handler = NULL;
  91. irq_vecs[vec].arg = NULL;
  92. irq_vecs[vec].count = 0;
  93. }
  94. #ifdef CONFIG_4xx
  95. /*
  96. * Init PIT
  97. */
  98. #if defined(CONFIG_440)
  99. val = mfspr( tcr );
  100. val &= (~0x04400000); /* clear DIS & ARE */
  101. mtspr( tcr, val );
  102. mtspr( dec, 0 ); /* Prevent exception after TSR clear*/
  103. mtspr( decar, 0 ); /* clear reload */
  104. mtspr( tsr, 0x08000000 ); /* clear DEC status */
  105. val = gd->bd->bi_intfreq/1000; /* 1 msec */
  106. mtspr( decar, val ); /* Set auto-reload value */
  107. mtspr( dec, val ); /* Set inital val */
  108. #else
  109. set_pit(gd->bd->bi_intfreq / 1000);
  110. #endif
  111. #endif /* CONFIG_4xx */
  112. #ifdef CONFIG_ADCIOP
  113. /*
  114. * Init PIT
  115. */
  116. set_pit(66000);
  117. #endif
  118. /*
  119. * Enable PIT
  120. */
  121. val = mfspr(tcr);
  122. val |= 0x04400000;
  123. mtspr(tcr, val);
  124. /*
  125. * Set EVPR to 0
  126. */
  127. set_evpr(0x00000000);
  128. #if (UIC_MAX > 1)
  129. /* Install the UIC1 handlers */
  130. irq_install_handler(VECNUM_UIC1NCI, (void *)(void *)external_interrupt, 0);
  131. irq_install_handler(VECNUM_UIC1CI, (void *)(void *)external_interrupt, 0);
  132. #endif
  133. #if (UIC_MAX > 2)
  134. irq_install_handler(VECNUM_UIC2NCI, (void *)(void *)external_interrupt, 0);
  135. irq_install_handler(VECNUM_UIC2CI, (void *)(void *)external_interrupt, 0);
  136. #endif
  137. #if (UIC_MAX > 3)
  138. irq_install_handler(VECNUM_UIC3NCI, (void *)(void *)external_interrupt, 0);
  139. irq_install_handler(VECNUM_UIC3CI, (void *)(void *)external_interrupt, 0);
  140. #endif
  141. return (0);
  142. }
  143. /* Handler for UIC interrupt */
  144. static void uic_interrupt(u32 uic_base, int vec_base)
  145. {
  146. u32 uic_msr;
  147. u32 msr_shift;
  148. int vec;
  149. /*
  150. * Read masked interrupt status register to determine interrupt source
  151. */
  152. uic_msr = get_dcr(uic_base + UIC_MSR);
  153. msr_shift = uic_msr;
  154. vec = vec_base;
  155. while (msr_shift != 0) {
  156. if (msr_shift & 0x80000000) {
  157. /*
  158. * Increment irq counter (for debug purpose only)
  159. */
  160. irq_vecs[vec].count++;
  161. if (irq_vecs[vec].handler != NULL) {
  162. /* call isr */
  163. (*irq_vecs[vec].handler)(irq_vecs[vec].arg);
  164. } else {
  165. set_dcr(uic_base + UIC_ER,
  166. get_dcr(uic_base + UIC_ER) & ~UIC_MASK(vec));
  167. printf("Masking bogus interrupt vector %d"
  168. " (UIC_BASE=0x%x)\n", vec, uic_base);
  169. }
  170. /*
  171. * After servicing the interrupt, we have to remove the
  172. * status indicator
  173. */
  174. set_dcr(uic_base + UIC_SR, UIC_MASK(vec));
  175. }
  176. /*
  177. * Shift msr to next position and increment vector
  178. */
  179. msr_shift <<= 1;
  180. vec++;
  181. }
  182. }
  183. /*
  184. * Handle external interrupts
  185. */
  186. void external_interrupt(struct pt_regs *regs)
  187. {
  188. u32 uic_msr;
  189. /*
  190. * Read masked interrupt status register to determine interrupt source
  191. */
  192. uic_msr = mfdcr(uic0msr);
  193. #if (UIC_MAX > 1)
  194. if ((UIC_MASK(VECNUM_UIC1CI) & uic_msr) ||
  195. (UIC_MASK(VECNUM_UIC1NCI) & uic_msr))
  196. uic_interrupt(UIC1_DCR_BASE, 32);
  197. #endif
  198. #if (UIC_MAX > 2)
  199. if ((UIC_MASK(VECNUM_UIC2CI) & uic_msr) ||
  200. (UIC_MASK(VECNUM_UIC2NCI) & uic_msr))
  201. uic_interrupt(UIC2_DCR_BASE, 64);
  202. #endif
  203. #if (UIC_MAX > 3)
  204. if ((UIC_MASK(VECNUM_UIC3CI) & uic_msr) ||
  205. (UIC_MASK(VECNUM_UIC3NCI) & uic_msr))
  206. uic_interrupt(UIC3_DCR_BASE, 96);
  207. #endif
  208. if (uic_msr & ~(UICB0_ALL))
  209. uic_interrupt(UIC0_DCR_BASE, 0);
  210. mtdcr(uic0sr, uic_msr);
  211. return;
  212. }
  213. /*
  214. * Install and free a interrupt handler.
  215. */
  216. void irq_install_handler(int vec, interrupt_handler_t * handler, void *arg)
  217. {
  218. /*
  219. * Print warning when replacing with a different irq vector
  220. */
  221. if ((irq_vecs[vec].handler != NULL) && (irq_vecs[vec].handler != handler)) {
  222. printf("Interrupt vector %d: handler 0x%x replacing 0x%x\n",
  223. vec, (uint) handler, (uint) irq_vecs[vec].handler);
  224. }
  225. irq_vecs[vec].handler = handler;
  226. irq_vecs[vec].arg = arg;
  227. if ((vec >= 0) && (vec < 32))
  228. mtdcr(uicer, mfdcr(uicer) | UIC_MASK(vec));
  229. #if (UIC_MAX > 1)
  230. else if ((vec >= 32) && (vec < 64))
  231. mtdcr(uic1er, mfdcr(uic1er) | UIC_MASK(vec));
  232. #endif
  233. #if (UIC_MAX > 2)
  234. else if ((vec >= 64) && (vec < 96))
  235. mtdcr(uic2er, mfdcr(uic2er) | UIC_MASK(vec));
  236. #endif
  237. #if (UIC_MAX > 3)
  238. else if (vec >= 96)
  239. mtdcr(uic3er, mfdcr(uic3er) | UIC_MASK(vec));
  240. #endif
  241. debug("Install interrupt for vector %d ==> %p\n", vec, handler);
  242. }
  243. void irq_free_handler (int vec)
  244. {
  245. debug("Free interrupt for vector %d ==> %p\n",
  246. vec, irq_vecs[vec].handler);
  247. if ((vec >= 0) && (vec < 32))
  248. mtdcr(uicer, mfdcr(uicer) & ~UIC_MASK(vec));
  249. #if (UIC_MAX > 1)
  250. else if ((vec >= 32) && (vec < 64))
  251. mtdcr(uic1er, mfdcr(uic1er) & ~UIC_MASK(vec));
  252. #endif
  253. #if (UIC_MAX > 2)
  254. else if ((vec >= 64) && (vec < 96))
  255. mtdcr(uic2er, mfdcr(uic2er) & ~UIC_MASK(vec));
  256. #endif
  257. #if (UIC_MAX > 3)
  258. else if (vec >= 96)
  259. mtdcr(uic3er, mfdcr(uic3er) & ~UIC_MASK(vec));
  260. #endif
  261. irq_vecs[vec].handler = NULL;
  262. irq_vecs[vec].arg = NULL;
  263. }
  264. void timer_interrupt_cpu (struct pt_regs *regs)
  265. {
  266. /* nothing to do here */
  267. return;
  268. }
  269. #if defined(CONFIG_CMD_IRQ)
  270. int do_irqinfo(cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
  271. {
  272. int vec;
  273. printf ("Interrupt-Information:\n");
  274. printf ("Nr Routine Arg Count\n");
  275. for (vec = 0; vec < (UIC_MAX * 32); vec++) {
  276. if (irq_vecs[vec].handler != NULL) {
  277. printf ("%02d %08lx %08lx %d\n",
  278. vec,
  279. (ulong)irq_vecs[vec].handler,
  280. (ulong)irq_vecs[vec].arg,
  281. irq_vecs[vec].count);
  282. }
  283. }
  284. return 0;
  285. }
  286. #endif