drv_timer.c 3.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172
  1. /*
  2. * Copyright (c) 2006-2021, RT-Thread Development Team
  3. *
  4. * SPDX-License-Identifier: Apache-2.0
  5. *
  6. * Change Logs:
  7. * Date Author Notes
  8. * 2018-11-22 Jesven first version
  9. */
  10. #include <rthw.h>
  11. #include <rtthread.h>
  12. #include <stdint.h>
  13. #include <board.h>
  14. #include "mmu.h"
  15. #define TICK_PERIOD (g_sys_freq / RT_TICK_PER_SECOND)
  16. static int g_sys_freq;
  17. #define IRQ_SECURE_PHY_TIMER 29 /* Secure physical timer event */
  18. #define IRQ_NOSECURE_PHY_TIMER 30 /* No-Secure physical timer event */
  19. #define IRQ_SYS_TICK IRQ_SECURE_PHY_TIMER
  20. /* System Counter */
  21. struct sctr_regs {
  22. rt_uint32_t cntcr;
  23. rt_uint32_t cntsr;
  24. rt_uint32_t cntcv1;
  25. rt_uint32_t cntcv2;
  26. rt_uint32_t resv1[4];
  27. rt_uint32_t cntfid0;
  28. rt_uint32_t cntfid1;
  29. rt_uint32_t cntfid2;
  30. rt_uint32_t resv2[1001];
  31. rt_uint32_t counterid[1];
  32. };
  33. #define SC_CNTCR_ENABLE (1 << 0)
  34. #define SC_CNTCR_HDBG (1 << 1)
  35. #define SC_CNTCR_FREQ0 (1 << 8)
  36. #define SC_CNTCR_FREQ1 (1 << 9)
  37. #define isb() __asm__ __volatile__ ("" : : : "memory")
  38. #define dsb() __asm__ __volatile__ ("" : : : "memory")
  39. #define dmb() __asm__ __volatile__ ("" : : : "memory")
  40. static inline void enable_cntp(void)
  41. {
  42. rt_uint32_t cntv_ctl;
  43. cntv_ctl = 1;
  44. asm volatile ("mcr p15, 0, %0, c14, c2, 1" :: "r"(cntv_ctl)); // write CNTP_CTL
  45. isb();
  46. }
  47. static inline void disable_cntp(void)
  48. {
  49. rt_uint32_t cntv_ctl;
  50. cntv_ctl = 0;
  51. asm volatile ("mcr p15, 0, %0, c14, c2, 1" :: "r"(cntv_ctl)); // write CNTP_CTL
  52. isb();
  53. }
  54. static inline rt_uint32_t read_cntfrq(void)
  55. {
  56. rt_uint32_t val;
  57. asm volatile ("mrc p15, 0, %0, c14, c0, 0" : "=r"(val));
  58. return val;
  59. }
  60. static inline void write_cntp_tval(rt_uint32_t val)
  61. {
  62. asm volatile ("mcr p15, 0, %0, c14, c2, 0" :: "r"(val));
  63. isb();
  64. return;
  65. }
  66. static inline void write_cntp_cval(rt_uint64_t val)
  67. {
  68. asm volatile ("mcrr p15, 2, %Q0, %R0, c14" :: "r" (val));
  69. isb();
  70. return;
  71. }
  72. static inline rt_uint64_t read_cntp_cval(void)
  73. {
  74. rt_uint64_t val;
  75. asm volatile ("mrrc p15, 2, %Q0, %R0, c14" : "=r" (val));
  76. return (val);
  77. }
  78. volatile unsigned int *CCM_CLPCR;
  79. static void imx6ull_enable_clk_in_waitmode(void)
  80. {
  81. CCM_CLPCR = rt_ioremap((void*)0x20C4054, 4);
  82. *CCM_CLPCR &= ~((1 << 5) | 0x3);
  83. }
  84. static void system_counter_clk_source_init(void)
  85. {
  86. /* to do */
  87. }
  88. static void system_counter_init(void)
  89. {
  90. /* enable system_counter */
  91. #define SCTR_BASE_ADDR 0x021DC000
  92. #define CONFIG_SC_TIMER_CLK 8000000
  93. /* imx6ull, enable system counter */
  94. struct sctr_regs *sctr = (struct sctr_regs *)rt_ioremap((void*)SCTR_BASE_ADDR, sizeof(struct sctr_regs));
  95. unsigned long val, freq;
  96. freq = CONFIG_SC_TIMER_CLK;
  97. asm volatile("mcr p15, 0, %0, c14, c0, 0" : : "r" (freq));
  98. sctr->cntfid0 = freq;
  99. /* Enable system counter */
  100. val = sctr->cntcr;
  101. val &= ~(SC_CNTCR_FREQ0 | SC_CNTCR_FREQ1);
  102. val |= SC_CNTCR_FREQ0 | SC_CNTCR_ENABLE | SC_CNTCR_HDBG;
  103. sctr->cntcr = val;
  104. imx6ull_enable_clk_in_waitmode();
  105. }
  106. static void arch_timer_init(void)
  107. {
  108. g_sys_freq = read_cntfrq();
  109. /* set timeout val */
  110. disable_cntp();
  111. write_cntp_tval(TICK_PERIOD);
  112. /* start timer */
  113. enable_cntp();
  114. /* enable irq */
  115. }
  116. static void rt_hw_timer_isr(int vector, void *param)
  117. {
  118. rt_tick_increase();
  119. /* setup for next irq */
  120. /* clear interrupt */
  121. disable_cntp();
  122. write_cntp_cval(read_cntp_cval() + TICK_PERIOD);
  123. enable_cntp();
  124. }
  125. int rt_hw_timer_init(void)
  126. {
  127. /* Setup Timer for generating irq */
  128. /* enable timer */
  129. system_counter_clk_source_init();
  130. system_counter_init();
  131. arch_timer_init();
  132. /* insall irq, enable irq */
  133. rt_hw_interrupt_install(IRQ_SYS_TICK, rt_hw_timer_isr, RT_NULL, "tick");
  134. rt_hw_interrupt_umask(IRQ_SYS_TICK);
  135. return 0;
  136. }
  137. INIT_BOARD_EXPORT(rt_hw_timer_init);