time.c 4.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195
  1. // SPDX-License-Identifier: GPL-2.0+
  2. /*
  3. * (C) Copyright 2003 Josef Baumgartner <josef.baumgartner@telex.de>
  4. *
  5. * (C) Copyright 2000
  6. * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
  7. */
  8. #include <common.h>
  9. #include <asm/timer.h>
  10. #include <asm/immap.h>
  11. #include <watchdog.h>
  12. DECLARE_GLOBAL_DATA_PTR;
  13. static volatile ulong timestamp = 0;
  14. #ifndef CONFIG_SYS_WATCHDOG_FREQ
  15. #define CONFIG_SYS_WATCHDOG_FREQ (CONFIG_SYS_HZ / 2)
  16. #endif
  17. #if defined(CONFIG_MCFTMR)
  18. #ifndef CONFIG_SYS_UDELAY_BASE
  19. # error "uDelay base not defined!"
  20. #endif
  21. #if !defined(CONFIG_SYS_TMR_BASE) || !defined(CONFIG_SYS_INTR_BASE) || !defined(CONFIG_SYS_TMRINTR_NO) || !defined(CONFIG_SYS_TMRINTR_MASK)
  22. # error "TMR_BASE, INTR_BASE, TMRINTR_NO or TMRINTR_MASk not defined!"
  23. #endif
  24. extern void dtimer_intr_setup(void);
  25. void __udelay(unsigned long usec)
  26. {
  27. volatile dtmr_t *timerp = (dtmr_t *) (CONFIG_SYS_UDELAY_BASE);
  28. uint start, now, tmp;
  29. while (usec > 0) {
  30. if (usec > 65000)
  31. tmp = 65000;
  32. else
  33. tmp = usec;
  34. usec = usec - tmp;
  35. /* Set up TIMER 3 as timebase clock */
  36. timerp->tmr = DTIM_DTMR_RST_RST;
  37. timerp->tcn = 0;
  38. /* set period to 1 us */
  39. timerp->tmr =
  40. CONFIG_SYS_TIMER_PRESCALER | DTIM_DTMR_CLK_DIV1 | DTIM_DTMR_FRR |
  41. DTIM_DTMR_RST_EN;
  42. start = now = timerp->tcn;
  43. while (now < start + tmp)
  44. now = timerp->tcn;
  45. }
  46. }
  47. void dtimer_interrupt(void *not_used)
  48. {
  49. volatile dtmr_t *timerp = (dtmr_t *) (CONFIG_SYS_TMR_BASE);
  50. /* check for timer interrupt asserted */
  51. if ((CONFIG_SYS_TMRPND_REG & CONFIG_SYS_TMRINTR_MASK) == CONFIG_SYS_TMRINTR_PEND) {
  52. timerp->ter = (DTIM_DTER_CAP | DTIM_DTER_REF);
  53. timestamp++;
  54. #if defined(CONFIG_WATCHDOG) || defined (CONFIG_HW_WATCHDOG)
  55. if ((timestamp % (CONFIG_SYS_WATCHDOG_FREQ)) == 0) {
  56. WATCHDOG_RESET ();
  57. }
  58. #endif /* CONFIG_WATCHDOG || CONFIG_HW_WATCHDOG */
  59. return;
  60. }
  61. }
  62. int timer_init(void)
  63. {
  64. volatile dtmr_t *timerp = (dtmr_t *) (CONFIG_SYS_TMR_BASE);
  65. timestamp = 0;
  66. timerp->tcn = 0;
  67. timerp->trr = 0;
  68. /* Set up TIMER 4 as clock */
  69. timerp->tmr = DTIM_DTMR_RST_RST;
  70. /* initialize and enable timer interrupt */
  71. irq_install_handler(CONFIG_SYS_TMRINTR_NO, dtimer_interrupt, 0);
  72. timerp->tcn = 0;
  73. timerp->trr = 1000; /* Interrupt every ms */
  74. dtimer_intr_setup();
  75. /* set a period of 1us, set timer mode to restart and enable timer and interrupt */
  76. timerp->tmr = CONFIG_SYS_TIMER_PRESCALER | DTIM_DTMR_CLK_DIV1 |
  77. DTIM_DTMR_FRR | DTIM_DTMR_ORRI | DTIM_DTMR_RST_EN;
  78. return 0;
  79. }
  80. ulong get_timer(ulong base)
  81. {
  82. return (timestamp - base);
  83. }
  84. #endif /* CONFIG_MCFTMR */
  85. #if defined(CONFIG_MCFPIT)
  86. #if !defined(CONFIG_SYS_PIT_BASE)
  87. # error "CONFIG_SYS_PIT_BASE not defined!"
  88. #endif
  89. static unsigned short lastinc;
  90. void __udelay(unsigned long usec)
  91. {
  92. volatile pit_t *timerp = (pit_t *) (CONFIG_SYS_UDELAY_BASE);
  93. uint tmp;
  94. while (usec > 0) {
  95. if (usec > 65000)
  96. tmp = 65000;
  97. else
  98. tmp = usec;
  99. usec = usec - tmp;
  100. /* Set up TIMER 3 as timebase clock */
  101. timerp->pcsr = PIT_PCSR_OVW;
  102. timerp->pmr = 0;
  103. /* set period to 1 us */
  104. timerp->pcsr |= PIT_PCSR_PRE(CONFIG_SYS_PIT_PRESCALE) | PIT_PCSR_EN;
  105. timerp->pmr = tmp;
  106. while (timerp->pcntr > 0) ;
  107. }
  108. }
  109. void timer_init(void)
  110. {
  111. volatile pit_t *timerp = (pit_t *) (CONFIG_SYS_PIT_BASE);
  112. timestamp = 0;
  113. /* Set up TIMER 4 as poll clock */
  114. timerp->pcsr = PIT_PCSR_OVW;
  115. timerp->pmr = lastinc = 0;
  116. timerp->pcsr |= PIT_PCSR_PRE(CONFIG_SYS_PIT_PRESCALE) | PIT_PCSR_EN;
  117. return 0;
  118. }
  119. ulong get_timer(ulong base)
  120. {
  121. unsigned short now, diff;
  122. volatile pit_t *timerp = (pit_t *) (CONFIG_SYS_PIT_BASE);
  123. now = timerp->pcntr;
  124. diff = -(now - lastinc);
  125. timestamp += diff;
  126. lastinc = now;
  127. return timestamp - base;
  128. }
  129. void wait_ticks(unsigned long ticks)
  130. {
  131. u32 start = get_timer(0);
  132. while (get_timer(start) < ticks) ;
  133. }
  134. #endif /* CONFIG_MCFPIT */
  135. /*
  136. * This function is derived from PowerPC code (read timebase as long long).
  137. * On M68K it just returns the timer value.
  138. */
  139. unsigned long long get_ticks(void)
  140. {
  141. return get_timer(0);
  142. }
  143. unsigned long usec2ticks(unsigned long usec)
  144. {
  145. return get_timer(usec);
  146. }
  147. /*
  148. * This function is derived from PowerPC code (timebase clock frequency).
  149. * On M68K it returns the number of timer ticks per second.
  150. */
  151. ulong get_tbclk(void)
  152. {
  153. return CONFIG_SYS_HZ;
  154. }