timer.c 3.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130
  1. /*
  2. * (C) Copyright 2007
  3. * Sascha Hauer, Pengutronix
  4. *
  5. * (C) Copyright 2008-2009 Freescale Semiconductor, Inc.
  6. *
  7. * SPDX-License-Identifier: GPL-2.0+
  8. */
  9. #include <common.h>
  10. #include <asm/io.h>
  11. #include <div64.h>
  12. #include <asm/arch/imx-regs.h>
  13. #include <asm/arch/crm_regs.h>
  14. #include <asm/arch/clock.h>
  15. DECLARE_GLOBAL_DATA_PTR;
  16. #define timestamp (gd->arch.tbl)
  17. #define lastinc (gd->arch.lastinc)
  18. /* General purpose timers bitfields */
  19. #define GPTCR_SWR (1<<15) /* Software reset */
  20. #define GPTCR_FRR (1<<9) /* Freerun / restart */
  21. #define GPTCR_CLKSOURCE_32 (4<<6) /* Clock source */
  22. #define GPTCR_TEN (1) /* Timer enable */
  23. /*
  24. * "time" is measured in 1 / CONFIG_SYS_HZ seconds,
  25. * "tick" is internal timer period
  26. */
  27. /* ~0.4% error - measured with stop-watch on 100s boot-delay */
  28. static inline unsigned long long tick_to_time(unsigned long long tick)
  29. {
  30. tick *= CONFIG_SYS_HZ;
  31. do_div(tick, MXC_CLK32);
  32. return tick;
  33. }
  34. static inline unsigned long long us_to_tick(unsigned long long us)
  35. {
  36. us = us * MXC_CLK32 + 999999;
  37. do_div(us, 1000000);
  38. return us;
  39. }
  40. /*
  41. * nothing really to do with interrupts, just starts up a counter.
  42. * The 32KHz 32-bit timer overruns in 134217 seconds
  43. */
  44. int timer_init(void)
  45. {
  46. int i;
  47. struct gpt_regs *gpt = (struct gpt_regs *)GPT1_BASE_ADDR;
  48. struct ccm_regs *ccm = (struct ccm_regs *)CCM_BASE_ADDR;
  49. /* setup GP Timer 1 */
  50. writel(GPTCR_SWR, &gpt->ctrl);
  51. writel(readl(&ccm->cgr1) | 3 << MXC_CCM_CGR1_GPT_OFFSET, &ccm->cgr1);
  52. for (i = 0; i < 100; i++)
  53. writel(0, &gpt->ctrl); /* We have no udelay by now */
  54. writel(0, &gpt->pre); /* prescaler = 1 */
  55. /* Freerun Mode, 32KHz input */
  56. writel(readl(&gpt->ctrl) | GPTCR_CLKSOURCE_32 | GPTCR_FRR,
  57. &gpt->ctrl);
  58. writel(readl(&gpt->ctrl) | GPTCR_TEN, &gpt->ctrl);
  59. return 0;
  60. }
  61. unsigned long long get_ticks(void)
  62. {
  63. struct gpt_regs *gpt = (struct gpt_regs *)GPT1_BASE_ADDR;
  64. ulong now = readl(&gpt->counter); /* current tick value */
  65. if (now >= lastinc) {
  66. /*
  67. * normal mode (non roll)
  68. * move stamp forward with absolut diff ticks
  69. */
  70. timestamp += (now - lastinc);
  71. } else {
  72. /* we have rollover of incrementer */
  73. timestamp += (0xFFFFFFFF - lastinc) + now;
  74. }
  75. lastinc = now;
  76. return timestamp;
  77. }
  78. ulong get_timer_masked(void)
  79. {
  80. /*
  81. * get_ticks() returns a long long (64 bit), it wraps in
  82. * 2^64 / MXC_CLK32 = 2^64 / 2^15 = 2^49 ~ 5 * 10^14 (s) ~
  83. * 5 * 10^9 days... and get_ticks() * CONFIG_SYS_HZ wraps in
  84. * 5 * 10^6 days - long enough.
  85. */
  86. return tick_to_time(get_ticks());
  87. }
  88. ulong get_timer(ulong base)
  89. {
  90. return get_timer_masked() - base;
  91. }
  92. /* delay x useconds AND preserve advance timstamp value */
  93. void __udelay(unsigned long usec)
  94. {
  95. unsigned long long tmp;
  96. ulong tmo;
  97. tmo = us_to_tick(usec);
  98. tmp = get_ticks() + tmo; /* get current timestamp */
  99. while (get_ticks() < tmp) /* loop till event */
  100. /*NOP*/;
  101. }
  102. /*
  103. * This function is derived from PowerPC code (timebase clock frequency).
  104. * On ARM it returns the number of timer ticks per second.
  105. */
  106. ulong get_tbclk(void)
  107. {
  108. return MXC_CLK32;
  109. }