timer-arke.c 3.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144
  1. /*
  2. * (C) Copyright 2012, ASTRI
  3. * Ho Ka Leung <kalho@astri.org>
  4. *
  5. * See file CREDITS for list of people who contributed to this
  6. * project.
  7. *
  8. * This program is free software; you can redistribute it and/or
  9. * modify it under the terms of the GNU General Public License as
  10. * published by the Free Software Foundation; either version 2 of
  11. * the License, or (at your option) any later version.
  12. *
  13. * This program is distributed in the hope that it will be useful,
  14. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  15. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  16. * GNU General Public License for more details.
  17. *
  18. * You should have received a copy of the GNU General Public License
  19. * along with this program; if not, write to the Free Software
  20. * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
  21. * MA 02111-1307 USA
  22. */
  23. #include <common.h>
  24. #include <asm/io.h>
  25. #include <asm/arch/clock.h>
  26. #include <div64.h>
  27. #include <linux/math64.h>
  28. #define APBTMR_N_LOAD_COUNT 0x00
  29. #define APBTMR_N_CURRENT_VALUE 0x04
  30. #define APBTMR_N_CONTROL 0x08
  31. #define APBTMR_N_EOI 0x0c
  32. #define APBTMR_N_INT_STATUS 0x10
  33. #define APBTMRS_INT_STATUS 0xa0
  34. #define APBTMRS_EOI 0xa4
  35. #define APBTMRS_RAW_INT_STATUS 0xa8
  36. #define APBTMRS_COMP_VERSION 0xac
  37. #define APBTMR_CONTROL_ENABLE (1 << 0)
  38. /* 1: periodic, 0:free running. */
  39. #define APBTMR_CONTROL_MODE_PERIODIC (1 << 1)
  40. #define APBTMR_CONTROL_INT (1 << 2)
  41. static void __iomem *timer_reg = (void*)CONFIG_SYS_TIMERBASE;
  42. static unsigned long long timestamp;
  43. static unsigned long lastdec;
  44. #define TIMER_PERIOD 1000000 /* 1MHz counter plus 1 = 1us */
  45. #define TIMER_LOAD_VAL 0xffffffff
  46. void reset_timer_masked (void)
  47. {
  48. /* reset time */
  49. lastdec = readl(timer_reg + APBTMR_N_CURRENT_VALUE); /* capure current decrementer value time */
  50. timestamp = 0; /* start "advancing" time stamp from 0 */
  51. }
  52. ulong get_timer_masked (void)
  53. {
  54. unsigned long now = readl(timer_reg + APBTMR_N_CURRENT_VALUE); /* current tick value */
  55. if (lastdec >= now) { /* normal mode (non roll) */
  56. /* normal mode */
  57. timestamp += lastdec - now; /* move stamp fordward with absoulte diff ticks */
  58. } else { /* we have overflow of the count down timer */
  59. /* nts = ts + ld + (TLV - now)
  60. * ts=old stamp, ld=time that passed before passing through -1
  61. * (TLV-now) amount of time after passing though -1
  62. * nts = new "advancing time stamp"...it could also roll and cause problems.
  63. */
  64. timestamp += lastdec + (TIMER_LOAD_VAL - now);
  65. }
  66. lastdec = now;
  67. return div_u64(div_u64(timestamp, DIV_ROUND_UP(ark_get_timer_clock(), TIMER_PERIOD)), 1000);
  68. }
  69. int timer_init(void)
  70. {
  71. writel(0, timer_reg + APBTMR_N_CONTROL);
  72. writel(TIMER_LOAD_VAL, timer_reg + APBTMR_N_LOAD_COUNT);
  73. /* No timer interrupt */
  74. writel(APBTMR_CONTROL_MODE_PERIODIC | APBTMR_CONTROL_ENABLE, timer_reg + APBTMR_N_CONTROL);
  75. return 0;
  76. }
  77. unsigned long long get_ticks(void)
  78. {
  79. return 0;
  80. }
  81. ulong get_timer(ulong base)
  82. {
  83. return get_timer_masked () - base;
  84. }
  85. void __udelay(unsigned long usec)
  86. {
  87. long tmo = usec * DIV_ROUND_UP(ark_get_timer_clock(), TIMER_PERIOD);
  88. unsigned long last = readl(timer_reg + APBTMR_N_CURRENT_VALUE);
  89. unsigned long now;
  90. while (tmo > 0) {
  91. now = readl(timer_reg + APBTMR_N_CURRENT_VALUE);
  92. if (last >= now)
  93. tmo -= last - now;
  94. else
  95. tmo -= last + (TIMER_LOAD_VAL - now);
  96. last = now;
  97. }
  98. }
  99. ulong get_tbclk(void)
  100. {
  101. return CONFIG_SYS_HZ;
  102. }
  103. #ifdef CONFIG_SPL_BUILD
  104. void timer_init_24M(void)
  105. {
  106. /* writel(0, timer_reg + TIMER_CTL0);
  107. writel(23, timer_reg + TIMER_PRS0);
  108. writel(TIMER_LOAD_VAL, timer_reg + APBTMR_N_LOAD_COUNT);
  109. writel(3, timer_reg + TIMER_CTL0); */
  110. }
  111. void timer_uninit(void)
  112. {
  113. /* writel(0, timer_reg + TIMER_CTL0); */
  114. }
  115. void timer_delay_us(unsigned int us)
  116. {
  117. __udelay(us);
  118. }
  119. #endif