1 /* 2 * (C) Copyright 2000-2009 3 * Wolfgang Denk, DENX Software Engineering, wd@denx.de. 4 * 5 * SPDX-License-Identifier: GPL-2.0+ 6 */ 7 8 #include <common.h> 9 #include <dm.h> 10 #include <errno.h> 11 #include <timer.h> 12 #include <watchdog.h> 13 #include <div64.h> 14 #include <asm/io.h> 15 16 #ifndef CONFIG_WD_PERIOD 17 # define CONFIG_WD_PERIOD (10 * 1000 * 1000) /* 10 seconds default */ 18 #endif 19 20 DECLARE_GLOBAL_DATA_PTR; 21 22 #ifdef CONFIG_SYS_TIMER_RATE 23 /* Returns tick rate in ticks per second */ 24 ulong notrace get_tbclk(void) 25 { 26 return CONFIG_SYS_TIMER_RATE; 27 } 28 #endif 29 30 #ifdef CONFIG_SYS_TIMER_COUNTER 31 unsigned long notrace timer_read_counter(void) 32 { 33 #ifdef CONFIG_SYS_TIMER_COUNTS_DOWN 34 return ~readl(CONFIG_SYS_TIMER_COUNTER); 35 #else 36 return readl(CONFIG_SYS_TIMER_COUNTER); 37 #endif 38 } 39 #else 40 extern unsigned long __weak timer_read_counter(void); 41 #endif 42 43 #ifdef CONFIG_TIMER 44 ulong notrace get_tbclk(void) 45 { 46 int ret; 47 48 ret = dm_timer_init(); 49 if (ret) 50 return ret; 51 52 return timer_get_rate(gd->timer); 53 } 54 55 uint64_t notrace get_ticks(void) 56 { 57 u64 count; 58 int ret; 59 60 ret = dm_timer_init(); 61 if (ret) 62 return ret; 63 64 ret = timer_get_count(gd->timer, &count); 65 if (ret) 66 return ret; 67 68 return count; 69 } 70 71 #else /* !CONFIG_TIMER */ 72 73 uint64_t __weak notrace get_ticks(void) 74 { 75 unsigned long now = timer_read_counter(); 76 77 /* increment tbu if tbl has rolled over */ 78 if (now < gd->timebase_l) 79 gd->timebase_h++; 80 gd->timebase_l = now; 81 return ((uint64_t)gd->timebase_h << 32) | gd->timebase_l; 82 } 83 84 #endif /* CONFIG_TIMER */ 85 86 /* Returns time in milliseconds */ 87 static uint64_t notrace tick_to_time(uint64_t tick) 88 { 89 ulong div = get_tbclk(); 90 91 tick *= CONFIG_SYS_HZ; 92 do_div(tick, div); 93 return tick; 94 } 95 96 int __weak timer_init(void) 97 { 98 return 0; 99 } 100 101 /* Returns time in milliseconds */ 102 ulong __weak get_timer(ulong base) 103 { 104 return tick_to_time(get_ticks()) - base; 105 } 106 107 unsigned long __weak notrace timer_get_us(void) 108 { 109 return tick_to_time(get_ticks() * 1000); 110 } 111 112 static uint64_t usec_to_tick(unsigned long usec) 113 { 114 uint64_t tick = usec; 115 tick *= get_tbclk(); 116 do_div(tick, 1000000); 117 return tick; 118 } 119 120 void __weak __udelay(unsigned long usec) 121 { 122 uint64_t tmp; 123 124 tmp = get_ticks() + usec_to_tick(usec); /* get current timestamp */ 125 126 while (get_ticks() < tmp+1) /* loop till event */ 127 /*NOP*/; 128 } 129 130 /* ------------------------------------------------------------------------- */ 131 132 void udelay(unsigned long usec) 133 { 134 ulong kv; 135 136 do { 137 WATCHDOG_RESET(); 138 kv = usec > CONFIG_WD_PERIOD ? CONFIG_WD_PERIOD : usec; 139 __udelay (kv); 140 usec -= kv; 141 } while(usec); 142 } 143 144 void mdelay(unsigned long msec) 145 { 146 while (msec--) 147 udelay(1000); 148 } 149