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 <watchdog.h> 10 #include <div64.h> 11 #include <asm/io.h> 12 13 #ifndef CONFIG_WD_PERIOD 14 # define CONFIG_WD_PERIOD (10 * 1000 * 1000) /* 10 seconds default */ 15 #endif 16 17 DECLARE_GLOBAL_DATA_PTR; 18 19 #ifdef CONFIG_SYS_TIMER_RATE 20 /* Returns tick rate in ticks per second */ 21 ulong notrace get_tbclk(void) 22 { 23 return CONFIG_SYS_TIMER_RATE; 24 } 25 #endif 26 27 #ifdef CONFIG_SYS_TIMER_COUNTER 28 unsigned long notrace timer_read_counter(void) 29 { 30 #ifdef CONFIG_SYS_TIMER_COUNTS_DOWN 31 return ~readl(CONFIG_SYS_TIMER_COUNTER); 32 #else 33 return readl(CONFIG_SYS_TIMER_COUNTER); 34 #endif 35 } 36 #else 37 extern unsigned long __weak timer_read_counter(void); 38 #endif 39 40 uint64_t __weak notrace get_ticks(void) 41 { 42 unsigned long now = timer_read_counter(); 43 44 /* increment tbu if tbl has rolled over */ 45 if (now < gd->timebase_l) 46 gd->timebase_h++; 47 gd->timebase_l = now; 48 return ((uint64_t)gd->timebase_h << 32) | gd->timebase_l; 49 } 50 51 /* Returns time in milliseconds */ 52 static uint64_t notrace tick_to_time(uint64_t tick) 53 { 54 ulong div = get_tbclk(); 55 56 tick *= CONFIG_SYS_HZ; 57 do_div(tick, div); 58 return tick; 59 } 60 61 int __weak timer_init(void) 62 { 63 return 0; 64 } 65 66 /* Returns time in milliseconds */ 67 ulong __weak get_timer(ulong base) 68 { 69 return tick_to_time(get_ticks()) - base; 70 } 71 72 unsigned long __weak notrace timer_get_us(void) 73 { 74 return tick_to_time(get_ticks() * 1000); 75 } 76 77 static uint64_t usec_to_tick(unsigned long usec) 78 { 79 uint64_t tick = usec; 80 tick *= get_tbclk(); 81 do_div(tick, 1000000); 82 return tick; 83 } 84 85 void __weak __udelay(unsigned long usec) 86 { 87 uint64_t tmp; 88 89 tmp = get_ticks() + usec_to_tick(usec); /* get current timestamp */ 90 91 while (get_ticks() < tmp+1) /* loop till event */ 92 /*NOP*/; 93 } 94 95 /* ------------------------------------------------------------------------- */ 96 97 void udelay(unsigned long usec) 98 { 99 ulong kv; 100 101 do { 102 WATCHDOG_RESET(); 103 kv = usec > CONFIG_WD_PERIOD ? CONFIG_WD_PERIOD : usec; 104 __udelay (kv); 105 usec -= kv; 106 } while(usec); 107 } 108 109 void mdelay(unsigned long msec) 110 { 111 while (msec--) 112 udelay(1000); 113 } 114