interrupts.c 5.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264
  1. /*
  2. * (C) Copyright 2000-2002
  3. * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
  4. *
  5. * (C) Copyright 2004, Psyent Corporation <www.psyent.com>
  6. * Scott McNutt <smcnutt@psyent.com>
  7. *
  8. * SPDX-License-Identifier: GPL-2.0+
  9. */
  10. #include <nios2.h>
  11. #include <nios2-io.h>
  12. #include <asm/types.h>
  13. #include <asm/io.h>
  14. #include <asm/ptrace.h>
  15. #include <common.h>
  16. #include <command.h>
  17. #include <watchdog.h>
  18. #ifdef CONFIG_STATUS_LED
  19. #include <status_led.h>
  20. #endif
  21. #if defined(CONFIG_SYS_NIOS_TMRBASE) && !defined(CONFIG_SYS_NIOS_TMRIRQ)
  22. #error CONFIG_SYS_NIOS_TMRIRQ not defined (see documentation)
  23. #endif
  24. /****************************************************************************/
  25. struct irq_action {
  26. interrupt_handler_t *handler;
  27. void *arg;
  28. int count;
  29. };
  30. static struct irq_action vecs[32];
  31. /*************************************************************************/
  32. volatile ulong timestamp = 0;
  33. void reset_timer (void)
  34. {
  35. nios_timer_t *tmr =(nios_timer_t *)CONFIG_SYS_NIOS_TMRBASE;
  36. /* From Embedded Peripherals Handbook:
  37. *
  38. * "When the hardware is configured with Writeable period
  39. * disabled, writing to one of the period_n registers causes
  40. * the counter to reset to the fixed Timeout Period specified
  41. * at system generation time."
  42. *
  43. * Here we force a reload to prevent early timeouts from
  44. * get_timer() when the interrupt period is greater than
  45. * than 1 msec.
  46. *
  47. * Simply write to periodl with its own value to force an
  48. * internal counter reload, THEN reset the timestamp.
  49. */
  50. writel (readl (&tmr->periodl), &tmr->periodl);
  51. timestamp = 0;
  52. /* From Embedded Peripherals Handbook:
  53. *
  54. * "Writing to one of the period_n registers stops the internal
  55. * counter, except when the hardware is configured with Start/Stop
  56. * control bits off. If Start/Stop control bits is off, writing
  57. * either register does not stop the counter."
  58. *
  59. * In order to accomodate either configuration, the control
  60. * register is re-written. If the counter is stopped, it will
  61. * be restarted. If it is running, the write is essentially
  62. * a nop.
  63. */
  64. writel (NIOS_TIMER_ITO | NIOS_TIMER_CONT | NIOS_TIMER_START,
  65. &tmr->control);
  66. }
  67. ulong get_timer (ulong base)
  68. {
  69. WATCHDOG_RESET ();
  70. return (timestamp - base);
  71. }
  72. /*
  73. * This function is derived from Blackfin code (read timebase as long long).
  74. * On Nios2 it just returns the timer value.
  75. */
  76. unsigned long long get_ticks(void)
  77. {
  78. return get_timer(0);
  79. }
  80. /*
  81. * This function is derived from Blackfin code.
  82. * On Nios2 it returns the number of timer ticks per second.
  83. */
  84. ulong get_tbclk(void)
  85. {
  86. ulong tbclk;
  87. tbclk = CONFIG_SYS_HZ;
  88. return tbclk;
  89. }
  90. /* The board must handle this interrupt if a timer is not
  91. * provided.
  92. */
  93. #if defined(CONFIG_SYS_NIOS_TMRBASE)
  94. void tmr_isr (void *arg)
  95. {
  96. nios_timer_t *tmr = (nios_timer_t *)arg;
  97. /* Interrupt is cleared by writing anything to the
  98. * status register.
  99. */
  100. writel (0, &tmr->status);
  101. timestamp += CONFIG_SYS_NIOS_TMRMS;
  102. #ifdef CONFIG_STATUS_LED
  103. status_led_tick(timestamp);
  104. #endif
  105. }
  106. static void tmr_init (void)
  107. {
  108. nios_timer_t *tmr =(nios_timer_t *)CONFIG_SYS_NIOS_TMRBASE;
  109. writel (0, &tmr->status);
  110. writel (0, &tmr->control);
  111. writel (NIOS_TIMER_STOP, &tmr->control);
  112. #if defined(CONFIG_SYS_NIOS_TMRCNT)
  113. writel (CONFIG_SYS_NIOS_TMRCNT & 0xffff, &tmr->periodl);
  114. writel ((CONFIG_SYS_NIOS_TMRCNT >> 16) & 0xffff, &tmr->periodh);
  115. #endif
  116. writel (NIOS_TIMER_ITO | NIOS_TIMER_CONT | NIOS_TIMER_START,
  117. &tmr->control);
  118. irq_install_handler (CONFIG_SYS_NIOS_TMRIRQ, tmr_isr, (void *)tmr);
  119. }
  120. #endif /* CONFIG_SYS_NIOS_TMRBASE */
  121. /*************************************************************************/
  122. int disable_interrupts (void)
  123. {
  124. int val = rdctl (CTL_STATUS);
  125. wrctl (CTL_STATUS, val & ~STATUS_IE);
  126. return (val & STATUS_IE);
  127. }
  128. void enable_interrupts( void )
  129. {
  130. int val = rdctl (CTL_STATUS);
  131. wrctl (CTL_STATUS, val | STATUS_IE);
  132. }
  133. void external_interrupt (struct pt_regs *regs)
  134. {
  135. unsigned irqs;
  136. struct irq_action *act;
  137. /* Evaluate only irqs that are both enabled AND pending */
  138. irqs = rdctl (CTL_IENABLE) & rdctl (CTL_IPENDING);
  139. act = vecs;
  140. /* Assume (as does the Nios2 HAL) that bit 0 is highest
  141. * priority. NOTE: There is ALWAYS a handler assigned
  142. * (the default if no other).
  143. */
  144. while (irqs) {
  145. if (irqs & 1) {
  146. act->handler (act->arg);
  147. act->count++;
  148. }
  149. irqs >>=1;
  150. act++;
  151. }
  152. }
  153. static void def_hdlr (void *arg)
  154. {
  155. unsigned irqs = rdctl (CTL_IENABLE);
  156. /* Disable the individual interrupt -- with gratuitous
  157. * warning.
  158. */
  159. irqs &= ~(1 << (int)arg);
  160. wrctl (CTL_IENABLE, irqs);
  161. printf ("WARNING: Disabling unhandled interrupt: %d\n",
  162. (int)arg);
  163. }
  164. /*************************************************************************/
  165. void irq_install_handler (int irq, interrupt_handler_t *hdlr, void *arg)
  166. {
  167. int flag;
  168. struct irq_action *act;
  169. unsigned ena = rdctl (CTL_IENABLE);
  170. if ((irq < 0) || (irq > 31))
  171. return;
  172. act = &vecs[irq];
  173. flag = disable_interrupts ();
  174. if (hdlr) {
  175. act->handler = hdlr;
  176. act->arg = arg;
  177. ena |= (1 << irq); /* enable */
  178. } else {
  179. act->handler = def_hdlr;
  180. act->arg = (void *)irq;
  181. ena &= ~(1 << irq); /* disable */
  182. }
  183. wrctl (CTL_IENABLE, ena);
  184. if (flag) enable_interrupts ();
  185. }
  186. int interrupt_init (void)
  187. {
  188. int i;
  189. /* Assign the default handler to all */
  190. for (i = 0; i < 32; i++) {
  191. vecs[i].handler = def_hdlr;
  192. vecs[i].arg = (void *)i;
  193. vecs[i].count = 0;
  194. }
  195. #if defined(CONFIG_SYS_NIOS_TMRBASE)
  196. tmr_init ();
  197. #endif
  198. enable_interrupts ();
  199. return (0);
  200. }
  201. /*************************************************************************/
  202. #if defined(CONFIG_CMD_IRQ)
  203. int do_irqinfo (cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
  204. {
  205. int i;
  206. struct irq_action *act = vecs;
  207. printf ("\nInterrupt-Information:\n\n");
  208. printf ("Nr Routine Arg Count\n");
  209. printf ("-----------------------------\n");
  210. for (i=0; i<32; i++) {
  211. if (act->handler != def_hdlr) {
  212. printf ("%02d %08lx %08lx %d\n",
  213. i,
  214. (ulong)act->handler,
  215. (ulong)act->arg,
  216. act->count);
  217. }
  218. act++;
  219. }
  220. printf ("\n");
  221. return (0);
  222. }
  223. #endif