time.c 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169
  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 <init.h>
  10. #include <irq_func.h>
  11. #include <time.h>
  12. #include <asm/global_data.h>
  13. #include <linux/delay.h>
  14. #include <asm/timer.h>
  15. #include <asm/immap.h>
  16. #include <watchdog.h>
  17. DECLARE_GLOBAL_DATA_PTR;
  18. static volatile ulong timestamp = 0;
  19. #ifndef CFG_SYS_WATCHDOG_FREQ
  20. #define CFG_SYS_WATCHDOG_FREQ (CONFIG_SYS_HZ / 2)
  21. #endif
  22. #if CONFIG_IS_ENABLED(MCFTMR)
  23. #ifndef CFG_SYS_UDELAY_BASE
  24. # error "uDelay base not defined!"
  25. #endif
  26. #if !defined(CFG_SYS_TMR_BASE) || !defined(CFG_SYS_INTR_BASE) || !defined(CFG_SYS_TMRINTR_NO) || !defined(CFG_SYS_TMRINTR_MASK)
  27. # error "TMR_BASE, INTR_BASE, TMRINTR_NO or TMRINTR_MASk not defined!"
  28. #endif
  29. extern void dtimer_intr_setup(void);
  30. void __udelay(unsigned long usec)
  31. {
  32. volatile dtmr_t *timerp = (dtmr_t *) (CFG_SYS_UDELAY_BASE);
  33. uint start, now, tmp;
  34. while (usec > 0) {
  35. if (usec > 65000)
  36. tmp = 65000;
  37. else
  38. tmp = usec;
  39. usec = usec - tmp;
  40. /* Set up TIMER 3 as timebase clock */
  41. timerp->tmr = DTIM_DTMR_RST_RST;
  42. timerp->tcn = 0;
  43. /* set period to 1 us */
  44. timerp->tmr =
  45. CFG_SYS_TIMER_PRESCALER | DTIM_DTMR_CLK_DIV1 | DTIM_DTMR_FRR |
  46. DTIM_DTMR_RST_EN;
  47. start = now = timerp->tcn;
  48. while (now < start + tmp)
  49. now = timerp->tcn;
  50. }
  51. }
  52. void dtimer_interrupt(void *not_used)
  53. {
  54. volatile dtmr_t *timerp = (dtmr_t *) (CFG_SYS_TMR_BASE);
  55. /* check for timer interrupt asserted */
  56. if ((CFG_SYS_TMRPND_REG & CFG_SYS_TMRINTR_MASK) == CFG_SYS_TMRINTR_PEND) {
  57. timerp->ter = (DTIM_DTER_CAP | DTIM_DTER_REF);
  58. timestamp++;
  59. #if defined(CONFIG_WATCHDOG) || defined (CONFIG_HW_WATCHDOG)
  60. if (CFG_SYS_WATCHDOG_FREQ && (timestamp % (CFG_SYS_WATCHDOG_FREQ)) == 0) {
  61. schedule();
  62. }
  63. #endif /* CONFIG_WATCHDOG || CONFIG_HW_WATCHDOG */
  64. return;
  65. }
  66. }
  67. int timer_init(void)
  68. {
  69. volatile dtmr_t *timerp = (dtmr_t *) (CFG_SYS_TMR_BASE);
  70. timestamp = 0;
  71. timerp->tcn = 0;
  72. timerp->trr = 0;
  73. /* Set up TIMER 4 as clock */
  74. timerp->tmr = DTIM_DTMR_RST_RST;
  75. /* initialize and enable timer interrupt */
  76. irq_install_handler(CFG_SYS_TMRINTR_NO, dtimer_interrupt, 0);
  77. timerp->tcn = 0;
  78. timerp->trr = 1000; /* Interrupt every ms */
  79. dtimer_intr_setup();
  80. /* set a period of 1us, set timer mode to restart and enable timer and interrupt */
  81. timerp->tmr = CFG_SYS_TIMER_PRESCALER | DTIM_DTMR_CLK_DIV1 |
  82. DTIM_DTMR_FRR | DTIM_DTMR_ORRI | DTIM_DTMR_RST_EN;
  83. return 0;
  84. }
  85. ulong get_timer(ulong base)
  86. {
  87. return (timestamp - base);
  88. }
  89. /*
  90. * This function is derived from PowerPC code (read timebase as long long).
  91. * On M68K it just returns the timer value.
  92. */
  93. unsigned long long get_ticks(void)
  94. {
  95. return get_timer(0);
  96. }
  97. #else
  98. static u64 timer64 __section(".data");
  99. static u16 timer16 __section(".data");
  100. uint64_t __weak get_ticks(void)
  101. {
  102. volatile pit_t *timerp = (pit_t *) (CFG_SYS_UDELAY_BASE);
  103. u16 val = ~timerp->pcntr;
  104. if (timer16 > val)
  105. timer64 += 0xffff - timer16 + val;
  106. else
  107. timer64 += val - timer16;
  108. timer16 = val;
  109. return timer64;
  110. }
  111. /* PIT timer */
  112. int timer_init(void)
  113. {
  114. volatile pit_t *timerp = (pit_t *) (CFG_SYS_UDELAY_BASE);
  115. timer16 = 0;
  116. timer64 = 0;
  117. /* Set up PIT as timebase clock */
  118. timerp->pmr = 0xffff;
  119. timerp->pcsr = PIT_PCSR_EN | PIT_PCSR_OVW;
  120. return 0;
  121. }
  122. #endif /* CONFIG_MCFTMR */
  123. unsigned long usec2ticks(unsigned long usec)
  124. {
  125. return get_timer(usec);
  126. }
  127. /*
  128. * This function is derived from PowerPC code (timebase clock frequency).
  129. * On M68K it returns the number of timer ticks per second.
  130. */
  131. ulong get_tbclk(void)
  132. {
  133. return CONFIG_SYS_HZ;
  134. }