178acc472SPeter Tyser /* 278acc472SPeter Tyser * (C) Copyright 2000-2009 378acc472SPeter Tyser * Wolfgang Denk, DENX Software Engineering, wd@denx.de. 478acc472SPeter Tyser * 51a459660SWolfgang Denk * SPDX-License-Identifier: GPL-2.0+ 678acc472SPeter Tyser */ 778acc472SPeter Tyser 878acc472SPeter Tyser #include <common.h> 978acc472SPeter Tyser #include <watchdog.h> 108dfafddeSRob Herring #include <div64.h> 118dfafddeSRob Herring #include <asm/io.h> 1278acc472SPeter Tyser 132108f4c4SRob Herring #if CONFIG_SYS_HZ != 1000 142108f4c4SRob Herring #warning "CONFIG_SYS_HZ must be 1000 and should not be defined by platforms" 152108f4c4SRob Herring #endif 162108f4c4SRob Herring 1778acc472SPeter Tyser #ifndef CONFIG_WD_PERIOD 1878acc472SPeter Tyser # define CONFIG_WD_PERIOD (10 * 1000 * 1000) /* 10 seconds default */ 1978acc472SPeter Tyser #endif 2078acc472SPeter Tyser 218dfafddeSRob Herring DECLARE_GLOBAL_DATA_PTR; 228dfafddeSRob Herring 238dfafddeSRob Herring #ifdef CONFIG_SYS_TIMER_RATE 24*fccacd3bSPavel Machek /* Returns tick rate in ticks per second */ 258dfafddeSRob Herring ulong notrace get_tbclk(void) 268dfafddeSRob Herring { 278dfafddeSRob Herring return CONFIG_SYS_TIMER_RATE; 288dfafddeSRob Herring } 298dfafddeSRob Herring #endif 308dfafddeSRob Herring 318dfafddeSRob Herring #ifdef CONFIG_SYS_TIMER_COUNTER 328dfafddeSRob Herring unsigned long notrace timer_read_counter(void) 338dfafddeSRob Herring { 348dfafddeSRob Herring #ifdef CONFIG_SYS_TIMER_COUNTS_DOWN 358dfafddeSRob Herring return ~readl(CONFIG_SYS_TIMER_COUNTER); 368dfafddeSRob Herring #else 378dfafddeSRob Herring return readl(CONFIG_SYS_TIMER_COUNTER); 388dfafddeSRob Herring #endif 398dfafddeSRob Herring } 408dfafddeSRob Herring #else 4165ba7addSRob Herring extern unsigned long __weak timer_read_counter(void); 428dfafddeSRob Herring #endif 438dfafddeSRob Herring 448dfafddeSRob Herring unsigned long long __weak notrace get_ticks(void) 458dfafddeSRob Herring { 468dfafddeSRob Herring unsigned long now = timer_read_counter(); 478dfafddeSRob Herring 488dfafddeSRob Herring /* increment tbu if tbl has rolled over */ 498dfafddeSRob Herring if (now < gd->timebase_l) 508dfafddeSRob Herring gd->timebase_h++; 518dfafddeSRob Herring gd->timebase_l = now; 528dfafddeSRob Herring return ((unsigned long long)gd->timebase_h << 32) | gd->timebase_l; 538dfafddeSRob Herring } 548dfafddeSRob Herring 55*fccacd3bSPavel Machek /* Returns time in milliseconds */ 56*fccacd3bSPavel Machek static unsigned long long notrace tick_to_time(unsigned long long tick) 578dfafddeSRob Herring { 58*fccacd3bSPavel Machek ulong div = get_tbclk(); 598dfafddeSRob Herring 608dfafddeSRob Herring tick *= CONFIG_SYS_HZ; 618dfafddeSRob Herring do_div(tick, div); 628dfafddeSRob Herring return tick; 638dfafddeSRob Herring } 648dfafddeSRob Herring 65de351d6bSDarwin Rambo int __weak timer_init(void) 66de351d6bSDarwin Rambo { 67de351d6bSDarwin Rambo return 0; 68de351d6bSDarwin Rambo } 69de351d6bSDarwin Rambo 70*fccacd3bSPavel Machek /* Returns time in milliseconds */ 718dfafddeSRob Herring ulong __weak get_timer(ulong base) 728dfafddeSRob Herring { 738dfafddeSRob Herring return tick_to_time(get_ticks()) - base; 748dfafddeSRob Herring } 758dfafddeSRob Herring 768dfafddeSRob Herring unsigned long __weak notrace timer_get_us(void) 778dfafddeSRob Herring { 788dfafddeSRob Herring return tick_to_time(get_ticks() * 1000); 798dfafddeSRob Herring } 80*fccacd3bSPavel Machek 818dfafddeSRob Herring static unsigned long long usec_to_tick(unsigned long usec) 828dfafddeSRob Herring { 83*fccacd3bSPavel Machek unsigned long long tick = usec; 842cd1b572SStephen Warren tick *= get_tbclk(); 858dfafddeSRob Herring do_div(tick, 1000000); 868dfafddeSRob Herring return tick; 878dfafddeSRob Herring } 888dfafddeSRob Herring 898dfafddeSRob Herring void __weak __udelay(unsigned long usec) 908dfafddeSRob Herring { 918dfafddeSRob Herring unsigned long long tmp; 928dfafddeSRob Herring 93*fccacd3bSPavel Machek tmp = get_ticks() + usec_to_tick(usec); /* get current timestamp */ 948dfafddeSRob Herring 95*fccacd3bSPavel Machek while (get_ticks() < tmp+1) /* loop till event */ 968dfafddeSRob Herring /*NOP*/; 978dfafddeSRob Herring } 988dfafddeSRob Herring 9978acc472SPeter Tyser /* ------------------------------------------------------------------------- */ 10078acc472SPeter Tyser 10178acc472SPeter Tyser void udelay(unsigned long usec) 10278acc472SPeter Tyser { 10378acc472SPeter Tyser ulong kv; 10478acc472SPeter Tyser 10578acc472SPeter Tyser do { 10678acc472SPeter Tyser WATCHDOG_RESET(); 10778acc472SPeter Tyser kv = usec > CONFIG_WD_PERIOD ? CONFIG_WD_PERIOD : usec; 10878acc472SPeter Tyser __udelay (kv); 10978acc472SPeter Tyser usec -= kv; 11078acc472SPeter Tyser } while(usec); 11178acc472SPeter Tyser } 112c4c9fbebSAnatolij Gustschin 113c4c9fbebSAnatolij Gustschin void mdelay(unsigned long msec) 114c4c9fbebSAnatolij Gustschin { 115c4c9fbebSAnatolij Gustschin while (msec--) 116c4c9fbebSAnatolij Gustschin udelay(1000); 117c4c9fbebSAnatolij Gustschin } 118