timer.c 5.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210
  1. /*
  2. * (C) Copyright 2010
  3. * Marvell Semiconductor <www.marvell.com>
  4. * Written-by: Prafulla Wadaskar <prafulla@marvell.com>
  5. * Contributor: Mahavir Jain <mjain@marvell.com>
  6. *
  7. * See file CREDITS for list of people who contributed to this
  8. * project.
  9. *
  10. * This program is free software; you can redistribute it and/or
  11. * modify it under the terms of the GNU General Public License as
  12. * published by the Free Software Foundation; either version 2 of
  13. * the License, or (at your option) any later version.
  14. *
  15. * This program is distributed in the hope that it will be useful,
  16. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  17. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  18. * GNU General Public License for more details.
  19. *
  20. * You should have received a copy of the GNU General Public License
  21. * along with this program; if not, write to the Free Software
  22. * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
  23. * MA 02110-1301 USA
  24. */
  25. #include <common.h>
  26. #include <asm/arch/cpu.h>
  27. #include <asm/arch/armada100.h>
  28. /*
  29. * Timer registers
  30. * Refer Section A.6 in Datasheet
  31. */
  32. struct armd1tmr_registers {
  33. u32 clk_ctrl; /* Timer clk control reg */
  34. u32 match[9]; /* Timer match registers */
  35. u32 count[3]; /* Timer count registers */
  36. u32 status[3];
  37. u32 ie[3];
  38. u32 preload[3]; /* Timer preload value */
  39. u32 preload_ctrl[3];
  40. u32 wdt_match_en;
  41. u32 wdt_match_r;
  42. u32 wdt_val;
  43. u32 wdt_sts;
  44. u32 icr[3];
  45. u32 wdt_icr;
  46. u32 cer; /* Timer count enable reg */
  47. u32 cmr;
  48. u32 ilr[3];
  49. u32 wcr;
  50. u32 wfar;
  51. u32 wsar;
  52. u32 cvwr;
  53. };
  54. #define TIMER 0 /* Use TIMER 0 */
  55. /* Each timer has 3 match registers */
  56. #define MATCH_CMP(x) ((3 * TIMER) + x)
  57. #define TIMER_LOAD_VAL 0xffffffff
  58. #define COUNT_RD_REQ 0x1
  59. DECLARE_GLOBAL_DATA_PTR;
  60. /* Using gd->arch.tbu from timestamp and gd->tbl for lastdec */
  61. /* For preventing risk of instability in reading counter value,
  62. * first set read request to register cvwr and then read same
  63. * register after it captures counter value.
  64. */
  65. ulong read_timer(void)
  66. {
  67. struct armd1tmr_registers *armd1timers =
  68. (struct armd1tmr_registers *) ARMD1_TIMER_BASE;
  69. volatile int loop=100;
  70. writel(COUNT_RD_REQ, &armd1timers->cvwr);
  71. while (loop--);
  72. return(readl(&armd1timers->cvwr));
  73. }
  74. ulong get_timer_masked(void)
  75. {
  76. ulong now = read_timer();
  77. if (now >= gd->tbl) {
  78. /* normal mode */
  79. gd->arch.tbu += now - gd->tbl;
  80. } else {
  81. /* we have an overflow ... */
  82. gd->arch.tbu += now + TIMER_LOAD_VAL - gd->tbl;
  83. }
  84. gd->tbl = now;
  85. return gd->arch.tbu;
  86. }
  87. ulong get_timer(ulong base)
  88. {
  89. return ((get_timer_masked() / (CONFIG_SYS_HZ_CLOCK / 1000)) -
  90. base);
  91. }
  92. void __udelay(unsigned long usec)
  93. {
  94. ulong delayticks;
  95. ulong endtime;
  96. delayticks = (usec * (CONFIG_SYS_HZ_CLOCK / 1000000));
  97. endtime = get_timer_masked() + delayticks;
  98. while (get_timer_masked() < endtime);
  99. }
  100. /*
  101. * init the Timer
  102. */
  103. int timer_init(void)
  104. {
  105. struct armd1apb1_registers *apb1clkres =
  106. (struct armd1apb1_registers *) ARMD1_APBC1_BASE;
  107. struct armd1tmr_registers *armd1timers =
  108. (struct armd1tmr_registers *) ARMD1_TIMER_BASE;
  109. /* Enable Timer clock at 3.25 MHZ */
  110. writel(APBC_APBCLK | APBC_FNCLK | APBC_FNCLKSEL(3), &apb1clkres->timers);
  111. /* load value into timer */
  112. writel(0x0, &armd1timers->clk_ctrl);
  113. /* Use Timer 0 Match Resiger 0 */
  114. writel(TIMER_LOAD_VAL, &armd1timers->match[MATCH_CMP(0)]);
  115. /* Preload value is 0 */
  116. writel(0x0, &armd1timers->preload[TIMER]);
  117. /* Enable match comparator 0 for Timer 0 */
  118. writel(0x1, &armd1timers->preload_ctrl[TIMER]);
  119. /* Enable timer 0 */
  120. writel(0x1, &armd1timers->cer);
  121. /* init the gd->arch.tbu and gd->tbl value */
  122. gd->tbl = read_timer();
  123. gd->arch.tbu = 0;
  124. return 0;
  125. }
  126. #define MPMU_APRR_WDTR (1<<4)
  127. #define TMR_WFAR 0xbaba /* WDT Register First key */
  128. #define TMP_WSAR 0xeb10 /* WDT Register Second key */
  129. /*
  130. * This function uses internal Watchdog Timer
  131. * based reset mechanism.
  132. * Steps to write watchdog registers (protected access)
  133. * 1. Write key value to TMR_WFAR reg.
  134. * 2. Write key value to TMP_WSAR reg.
  135. * 3. Perform write operation.
  136. */
  137. void reset_cpu (unsigned long ignored)
  138. {
  139. struct armd1mpmu_registers *mpmu =
  140. (struct armd1mpmu_registers *) ARMD1_MPMU_BASE;
  141. struct armd1tmr_registers *armd1timers =
  142. (struct armd1tmr_registers *) ARMD1_TIMER_BASE;
  143. u32 val;
  144. /* negate hardware reset to the WDT after system reset */
  145. val = readl(&mpmu->aprr);
  146. val = val | MPMU_APRR_WDTR;
  147. writel(val, &mpmu->aprr);
  148. /* reset/enable WDT clock */
  149. writel(APBC_APBCLK | APBC_FNCLK | APBC_RST, &mpmu->wdtpcr);
  150. readl(&mpmu->wdtpcr);
  151. writel(APBC_APBCLK | APBC_FNCLK, &mpmu->wdtpcr);
  152. readl(&mpmu->wdtpcr);
  153. /* clear previous WDT status */
  154. writel(TMR_WFAR, &armd1timers->wfar);
  155. writel(TMP_WSAR, &armd1timers->wsar);
  156. writel(0, &armd1timers->wdt_sts);
  157. /* set match counter */
  158. writel(TMR_WFAR, &armd1timers->wfar);
  159. writel(TMP_WSAR, &armd1timers->wsar);
  160. writel(0xf, &armd1timers->wdt_match_r);
  161. /* enable WDT reset */
  162. writel(TMR_WFAR, &armd1timers->wfar);
  163. writel(TMP_WSAR, &armd1timers->wsar);
  164. writel(0x3, &armd1timers->wdt_match_en);
  165. while(1);
  166. }
  167. /*
  168. * This function is derived from PowerPC code (read timebase as long long).
  169. * On ARM it just returns the timer value.
  170. */
  171. unsigned long long get_ticks(void)
  172. {
  173. return get_timer(0);
  174. }
  175. /*
  176. * This function is derived from PowerPC code (timebase clock frequency).
  177. * On ARM it returns the number of timer ticks per second.
  178. */
  179. ulong get_tbclk (void)
  180. {
  181. return (ulong)CONFIG_SYS_HZ;
  182. }