timer.c 2.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121
  1. /*
  2. * (C) Copyright 2007
  3. * Sascha Hauer, Pengutronix
  4. *
  5. * (C) Copyright 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/clock.h>
  14. /* General purpose timers registers */
  15. struct mxc_gpt {
  16. unsigned int control;
  17. unsigned int prescaler;
  18. unsigned int status;
  19. unsigned int nouse[6];
  20. unsigned int counter;
  21. };
  22. static struct mxc_gpt *cur_gpt = (struct mxc_gpt *)GPT1_BASE_ADDR;
  23. /* General purpose timers bitfields */
  24. #define GPTCR_SWR (1 << 15) /* Software reset */
  25. #define GPTCR_FRR (1 << 9) /* Freerun / restart */
  26. #define GPTCR_CLKSOURCE_32 (4 << 6) /* Clock source */
  27. #define GPTCR_TEN 1 /* Timer enable */
  28. DECLARE_GLOBAL_DATA_PTR;
  29. static inline unsigned long long tick_to_time(unsigned long long tick)
  30. {
  31. tick *= CONFIG_SYS_HZ;
  32. do_div(tick, MXC_CLK32);
  33. return tick;
  34. }
  35. static inline unsigned long long us_to_tick(unsigned long long usec)
  36. {
  37. usec = usec * MXC_CLK32 + 999999;
  38. do_div(usec, 1000000);
  39. return usec;
  40. }
  41. int timer_init(void)
  42. {
  43. int i;
  44. /* setup GP Timer 1 */
  45. __raw_writel(GPTCR_SWR, &cur_gpt->control);
  46. /* We have no udelay by now */
  47. for (i = 0; i < 100; i++)
  48. __raw_writel(0, &cur_gpt->control);
  49. __raw_writel(0, &cur_gpt->prescaler); /* 32Khz */
  50. /* Freerun Mode, PERCLK1 input */
  51. i = __raw_readl(&cur_gpt->control);
  52. __raw_writel(i | GPTCR_CLKSOURCE_32 | GPTCR_TEN, &cur_gpt->control);
  53. gd->arch.tbl = __raw_readl(&cur_gpt->counter);
  54. gd->arch.tbu = 0;
  55. return 0;
  56. }
  57. unsigned long long get_ticks(void)
  58. {
  59. ulong now = __raw_readl(&cur_gpt->counter); /* current tick value */
  60. /* increment tbu if tbl has rolled over */
  61. if (now < gd->arch.tbl)
  62. gd->arch.tbu++;
  63. gd->arch.tbl = now;
  64. return (((unsigned long long)gd->arch.tbu) << 32) | gd->arch.tbl;
  65. }
  66. ulong get_timer_masked(void)
  67. {
  68. /*
  69. * get_ticks() returns a long long (64 bit), it wraps in
  70. * 2^64 / MXC_CLK32 = 2^64 / 2^15 = 2^49 ~ 5 * 10^14 (s) ~
  71. * 5 * 10^9 days... and get_ticks() * CONFIG_SYS_HZ wraps in
  72. * 5 * 10^6 days - long enough.
  73. */
  74. return tick_to_time(get_ticks());
  75. }
  76. ulong get_timer(ulong base)
  77. {
  78. return get_timer_masked() - base;
  79. }
  80. /* delay x useconds AND preserve advance timstamp value */
  81. void __udelay(unsigned long usec)
  82. {
  83. unsigned long long tmp;
  84. ulong tmo;
  85. tmo = us_to_tick(usec);
  86. tmp = get_ticks() + tmo; /* get current timestamp */
  87. while (get_ticks() < tmp) /* loop till event */
  88. /*NOP*/;
  89. }
  90. /*
  91. * This function is derived from PowerPC code (timebase clock frequency).
  92. * On ARM it returns the number of timer ticks per second.
  93. */
  94. ulong get_tbclk(void)
  95. {
  96. return MXC_CLK32;
  97. }