nxp_timer.c 3.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143
  1. /*
  2. * Copyright 2021 NXP
  3. *
  4. * SPDX-License-Identifier: BSD-3-Clause
  5. *
  6. */
  7. #include <arch_helpers.h>
  8. #include <common/debug.h>
  9. #include <drivers/delay_timer.h>
  10. #include <lib/mmio.h>
  11. #include <lib/utils_def.h>
  12. #include <nxp_timer.h>
  13. #include <plat/common/platform.h>
  14. static uintptr_t g_nxp_timer_addr;
  15. static timer_ops_t ops;
  16. uint64_t get_timer_val(uint64_t start)
  17. {
  18. uint64_t cntpct;
  19. isb();
  20. cntpct = read_cntpct_el0();
  21. return (cntpct * 1000ULL / read_cntfrq_el0() - start);
  22. }
  23. static uint32_t timer_get_value(void)
  24. {
  25. uint64_t cntpct;
  26. isb();
  27. cntpct = read_cntpct_el0();
  28. #ifdef ERRATA_SOC_A008585
  29. uint8_t max_fetch_count = 10U;
  30. /* This erratum number needs to be confirmed to match ARM document */
  31. uint64_t temp;
  32. isb();
  33. temp = read_cntpct_el0();
  34. while (temp != cntpct && max_fetch_count) {
  35. isb();
  36. cntpct = read_cntpct_el0();
  37. isb();
  38. temp = read_cntpct_el0();
  39. max_fetch_count--;
  40. }
  41. #endif
  42. /*
  43. * Generic delay timer implementation expects the timer to be a down
  44. * counter. We apply bitwise NOT operator to the tick values returned
  45. * by read_cntpct_el0() to simulate the down counter. The value is
  46. * clipped from 64 to 32 bits.
  47. */
  48. return (uint32_t)(~cntpct);
  49. }
  50. static void delay_timer_init_args(uint32_t mult, uint32_t div)
  51. {
  52. ops.get_timer_value = timer_get_value;
  53. ops.clk_mult = mult;
  54. ops.clk_div = div;
  55. timer_init(&ops);
  56. VERBOSE("Generic delay timer configured with mult=%u and div=%u\n",
  57. mult, div);
  58. }
  59. /*
  60. * Initialise the nxp on-chip free rolling usec counter as the delay
  61. * timer.
  62. */
  63. void delay_timer_init(uintptr_t nxp_timer_addr)
  64. {
  65. /* Value in ticks */
  66. unsigned int mult = MHZ_TICKS_PER_SEC;
  67. unsigned int div;
  68. unsigned int counter_base_frequency = plat_get_syscnt_freq2();
  69. g_nxp_timer_addr = nxp_timer_addr;
  70. /* Rounding off the Counter Frequency to MHZ_TICKS_PER_SEC */
  71. if (counter_base_frequency > MHZ_TICKS_PER_SEC) {
  72. counter_base_frequency = (counter_base_frequency
  73. / MHZ_TICKS_PER_SEC)
  74. * MHZ_TICKS_PER_SEC;
  75. } else {
  76. counter_base_frequency = (counter_base_frequency
  77. / KHZ_TICKS_PER_SEC)
  78. * KHZ_TICKS_PER_SEC;
  79. }
  80. /* Value in ticks per second (Hz) */
  81. div = counter_base_frequency;
  82. /* Reduce multiplier and divider by dividing them repeatedly by 10 */
  83. while ((mult % 10U == 0U) && (div % 10U == 0U)) {
  84. mult /= 10U;
  85. div /= 10U;
  86. }
  87. /* Enable and initialize the System level generic timer */
  88. mmio_write_32(g_nxp_timer_addr + CNTCR_OFF,
  89. CNTCR_FCREQ(0) | CNTCR_EN);
  90. delay_timer_init_args(mult, div);
  91. }
  92. #ifdef IMAGE_BL31
  93. /*******************************************************************************
  94. * TBD: Configures access to the system counter timer module.
  95. ******************************************************************************/
  96. void ls_configure_sys_timer(uintptr_t ls_sys_timctl_base,
  97. uint8_t ls_config_cntacr,
  98. uint8_t plat_ls_ns_timer_frame_id)
  99. {
  100. unsigned int reg_val;
  101. if (ls_config_cntacr == 1U) {
  102. reg_val = (1U << CNTACR_RPCT_SHIFT) | (1U << CNTACR_RVCT_SHIFT);
  103. reg_val |= (1U << CNTACR_RFRQ_SHIFT) | (1U << CNTACR_RVOFF_SHIFT);
  104. reg_val |= (1U << CNTACR_RWVT_SHIFT) | (1U << CNTACR_RWPT_SHIFT);
  105. mmio_write_32(ls_sys_timctl_base +
  106. CNTACR_BASE(plat_ls_ns_timer_frame_id), reg_val);
  107. mmio_write_32(ls_sys_timctl_base, plat_get_syscnt_freq2());
  108. }
  109. reg_val = (1U << CNTNSAR_NS_SHIFT(plat_ls_ns_timer_frame_id));
  110. mmio_write_32(ls_sys_timctl_base + CNTNSAR, reg_val);
  111. }
  112. void enable_init_timer(void)
  113. {
  114. /* Enable and initialize the System level generic timer */
  115. mmio_write_32(g_nxp_timer_addr + CNTCR_OFF,
  116. CNTCR_FCREQ(0) | CNTCR_EN);
  117. }
  118. #endif