timer.c 3.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160
  1. /*
  2. * (C) Copyright 2002
  3. * Sysgo Real-Time Solutions, GmbH <www.elinos.com>
  4. * Marius Groeger <mgroeger@sysgo.de>
  5. *
  6. * (C) Copyright 2002
  7. * Sysgo Real-Time Solutions, GmbH <www.elinos.com>
  8. * Alex Zuepke <azu@sysgo.de>
  9. *
  10. * (C) Copyright 2002
  11. * Gary Jennejohn, DENX Software Engineering, <garyj@denx.de>
  12. *
  13. * SPDX-License-Identifier: GPL-2.0+
  14. */
  15. #include <common.h>
  16. #ifdef CONFIG_S3C24X0
  17. #include <asm/io.h>
  18. #include <asm/arch/s3c24x0_cpu.h>
  19. DECLARE_GLOBAL_DATA_PTR;
  20. int timer_init(void)
  21. {
  22. struct s3c24x0_timers *timers = s3c24x0_get_base_timers();
  23. ulong tmr;
  24. /* use PWM Timer 4 because it has no output */
  25. /* prescaler for Timer 4 is 16 */
  26. writel(0x0f00, &timers->tcfg0);
  27. if (gd->arch.tbu == 0) {
  28. /*
  29. * for 10 ms clock period @ PCLK with 4 bit divider = 1/2
  30. * (default) and prescaler = 16. Should be 10390
  31. * @33.25MHz and 15625 @ 50 MHz
  32. */
  33. gd->arch.tbu = get_PCLK() / (2 * 16 * 100);
  34. gd->arch.timer_rate_hz = get_PCLK() / (2 * 16);
  35. }
  36. /* load value for 10 ms timeout */
  37. writel(gd->arch.tbu, &timers->tcntb4);
  38. /* auto load, manual update of timer 4 */
  39. tmr = (readl(&timers->tcon) & ~0x0700000) | 0x0600000;
  40. writel(tmr, &timers->tcon);
  41. /* auto load, start timer 4 */
  42. tmr = (tmr & ~0x0700000) | 0x0500000;
  43. writel(tmr, &timers->tcon);
  44. gd->arch.lastinc = 0;
  45. gd->arch.tbl = 0;
  46. return 0;
  47. }
  48. /*
  49. * timer without interrupts
  50. */
  51. ulong get_timer(ulong base)
  52. {
  53. return get_timer_masked() - base;
  54. }
  55. void __udelay (unsigned long usec)
  56. {
  57. ulong tmo;
  58. ulong start = get_ticks();
  59. tmo = usec / 1000;
  60. tmo *= (gd->arch.tbu * 100);
  61. tmo /= 1000;
  62. while ((ulong) (get_ticks() - start) < tmo)
  63. /*NOP*/;
  64. }
  65. ulong get_timer_masked(void)
  66. {
  67. ulong tmr = get_ticks();
  68. return tmr / (gd->arch.timer_rate_hz / CONFIG_SYS_HZ);
  69. }
  70. void udelay_masked(unsigned long usec)
  71. {
  72. ulong tmo;
  73. ulong endtime;
  74. signed long diff;
  75. if (usec >= 1000) {
  76. tmo = usec / 1000;
  77. tmo *= (gd->arch.tbu * 100);
  78. tmo /= 1000;
  79. } else {
  80. tmo = usec * (gd->arch.tbu * 100);
  81. tmo /= (1000 * 1000);
  82. }
  83. endtime = get_ticks() + tmo;
  84. do {
  85. ulong now = get_ticks();
  86. diff = endtime - now;
  87. } while (diff >= 0);
  88. }
  89. /*
  90. * This function is derived from PowerPC code (read timebase as long long).
  91. * On ARM it just returns the timer value.
  92. */
  93. unsigned long long get_ticks(void)
  94. {
  95. struct s3c24x0_timers *timers = s3c24x0_get_base_timers();
  96. ulong now = readl(&timers->tcnto4) & 0xffff;
  97. if (gd->arch.lastinc >= now) {
  98. /* normal mode */
  99. gd->arch.tbl += gd->arch.lastinc - now;
  100. } else {
  101. /* we have an overflow ... */
  102. gd->arch.tbl += gd->arch.lastinc + gd->arch.tbu - now;
  103. }
  104. gd->arch.lastinc = now;
  105. return gd->arch.tbl;
  106. }
  107. /*
  108. * This function is derived from PowerPC code (timebase clock frequency).
  109. * On ARM it returns the number of timer ticks per second.
  110. */
  111. ulong get_tbclk(void)
  112. {
  113. return CONFIG_SYS_HZ;
  114. }
  115. /*
  116. * reset the cpu by setting up the watchdog timer and let him time out
  117. */
  118. void reset_cpu(ulong ignored)
  119. {
  120. struct s3c24x0_watchdog *watchdog;
  121. watchdog = s3c24x0_get_base_watchdog();
  122. /* Disable watchdog */
  123. writel(0x0000, &watchdog->wtcon);
  124. /* Initialize watchdog timer count register */
  125. writel(0x0001, &watchdog->wtcnt);
  126. /* Enable watchdog timer; assert reset at timer timeout */
  127. writel(0x0021, &watchdog->wtcon);
  128. while (1)
  129. /* loop forever and wait for reset to happen */;
  130. /*NOTREACHED*/
  131. }
  132. #endif /* CONFIG_S3C24X0 */