timer.c 2.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112
  1. /*
  2. * (C) Copyright 2016
  3. * Vikas Manocha, ST Micoelectronics, vikas.manocha@st.com.
  4. *
  5. * SPDX-License-Identifier: GPL-2.0+
  6. */
  7. #include <common.h>
  8. #include <asm/io.h>
  9. #include <asm/arch/stm32.h>
  10. #include <asm/arch/gpt.h>
  11. #include <asm/arch/rcc.h>
  12. #define READ_TIMER() (readl(&gpt1_regs_ptr->cnt) & GPT_FREE_RUNNING)
  13. #define GPT_RESOLUTION (CONFIG_SYS_HZ_CLOCK/CONFIG_STM32_HZ)
  14. DECLARE_GLOBAL_DATA_PTR;
  15. #define timestamp gd->arch.tbl
  16. #define lastdec gd->arch.lastinc
  17. int timer_init(void)
  18. {
  19. /* Timer2 clock configuration */
  20. setbits_le32(RCC_BASE + RCC_APB1ENR, RCC_APB1ENR_TIM2EN);
  21. /* Stop the timer */
  22. writel(readl(&gpt1_regs_ptr->cr1) & ~GPT_CR1_CEN, &gpt1_regs_ptr->cr1);
  23. writel((CONFIG_SYS_CLK_FREQ/CONFIG_SYS_HZ_CLOCK) - 1,
  24. &gpt1_regs_ptr->psc);
  25. /* Configure timer for auto-reload */
  26. writel(readl(&gpt1_regs_ptr->cr1) | GPT_MODE_AUTO_RELOAD,
  27. &gpt1_regs_ptr->cr1);
  28. /* load value for free running */
  29. writel(GPT_FREE_RUNNING, &gpt1_regs_ptr->arr);
  30. /* start timer */
  31. writel(readl(&gpt1_regs_ptr->cr1) | GPT_CR1_CEN, &gpt1_regs_ptr->cr1);
  32. writel(readl(&gpt1_regs_ptr->egr) | TIM_EGR_UG, &gpt1_regs_ptr->egr);
  33. /* Reset the timer */
  34. lastdec = READ_TIMER();
  35. timestamp = 0;
  36. return 0;
  37. }
  38. /*
  39. * timer without interrupts
  40. */
  41. ulong get_timer(ulong base)
  42. {
  43. return (get_timer_masked() / GPT_RESOLUTION) - base;
  44. }
  45. void __udelay(unsigned long usec)
  46. {
  47. ulong tmo;
  48. ulong start = get_timer_masked();
  49. ulong tenudelcnt = CONFIG_SYS_HZ_CLOCK / (1000 * 100);
  50. ulong rndoff;
  51. rndoff = (usec % 10) ? 1 : 0;
  52. /* tenudelcnt timer tick gives 10 microsecconds delay */
  53. tmo = ((usec / 10) + rndoff) * tenudelcnt;
  54. while ((ulong) (get_timer_masked() - start) < tmo)
  55. ;
  56. }
  57. ulong get_timer_masked(void)
  58. {
  59. ulong now = READ_TIMER();
  60. if (now >= lastdec) {
  61. /* normal mode */
  62. timestamp += now - lastdec;
  63. } else {
  64. /* we have an overflow ... */
  65. timestamp += now + GPT_FREE_RUNNING - lastdec;
  66. }
  67. lastdec = now;
  68. return timestamp;
  69. }
  70. void udelay_masked(unsigned long usec)
  71. {
  72. return udelay(usec);
  73. }
  74. /*
  75. * This function is derived from PowerPC code (read timebase as long long).
  76. * On ARM it just returns the timer value.
  77. */
  78. unsigned long long get_ticks(void)
  79. {
  80. return get_timer(0);
  81. }
  82. /*
  83. * This function is derived from PowerPC code (timebase clock frequency).
  84. * On ARM it returns the number of timer ticks per second.
  85. */
  86. ulong get_tbclk(void)
  87. {
  88. return CONFIG_STM32_HZ;
  89. }