xref: /openbmc/u-boot/lib/time.c (revision 19ea4678)
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 
1378acc472SPeter Tyser #ifndef CONFIG_WD_PERIOD
1478acc472SPeter Tyser # define CONFIG_WD_PERIOD	(10 * 1000 * 1000)	/* 10 seconds default */
1578acc472SPeter Tyser #endif
1678acc472SPeter Tyser 
178dfafddeSRob Herring DECLARE_GLOBAL_DATA_PTR;
188dfafddeSRob Herring 
198dfafddeSRob Herring #ifdef CONFIG_SYS_TIMER_RATE
20fccacd3bSPavel Machek /* Returns tick rate in ticks per second */
218dfafddeSRob Herring ulong notrace get_tbclk(void)
228dfafddeSRob Herring {
238dfafddeSRob Herring 	return CONFIG_SYS_TIMER_RATE;
248dfafddeSRob Herring }
258dfafddeSRob Herring #endif
268dfafddeSRob Herring 
278dfafddeSRob Herring #ifdef CONFIG_SYS_TIMER_COUNTER
288dfafddeSRob Herring unsigned long notrace timer_read_counter(void)
298dfafddeSRob Herring {
308dfafddeSRob Herring #ifdef CONFIG_SYS_TIMER_COUNTS_DOWN
318dfafddeSRob Herring 	return ~readl(CONFIG_SYS_TIMER_COUNTER);
328dfafddeSRob Herring #else
338dfafddeSRob Herring 	return readl(CONFIG_SYS_TIMER_COUNTER);
348dfafddeSRob Herring #endif
358dfafddeSRob Herring }
368dfafddeSRob Herring #else
3765ba7addSRob Herring extern unsigned long __weak timer_read_counter(void);
388dfafddeSRob Herring #endif
398dfafddeSRob Herring 
40*19ea4678SSimon Glass uint64_t __weak notrace get_ticks(void)
418dfafddeSRob Herring {
428dfafddeSRob Herring 	unsigned long now = timer_read_counter();
438dfafddeSRob Herring 
448dfafddeSRob Herring 	/* increment tbu if tbl has rolled over */
458dfafddeSRob Herring 	if (now < gd->timebase_l)
468dfafddeSRob Herring 		gd->timebase_h++;
478dfafddeSRob Herring 	gd->timebase_l = now;
48*19ea4678SSimon Glass 	return ((uint64_t)gd->timebase_h << 32) | gd->timebase_l;
498dfafddeSRob Herring }
508dfafddeSRob Herring 
51fccacd3bSPavel Machek /* Returns time in milliseconds */
52*19ea4678SSimon Glass static uint64_t notrace tick_to_time(uint64_t tick)
538dfafddeSRob Herring {
54fccacd3bSPavel Machek 	ulong div = get_tbclk();
558dfafddeSRob Herring 
568dfafddeSRob Herring 	tick *= CONFIG_SYS_HZ;
578dfafddeSRob Herring 	do_div(tick, div);
588dfafddeSRob Herring 	return tick;
598dfafddeSRob Herring }
608dfafddeSRob Herring 
61de351d6bSDarwin Rambo int __weak timer_init(void)
62de351d6bSDarwin Rambo {
63de351d6bSDarwin Rambo 	return 0;
64de351d6bSDarwin Rambo }
65de351d6bSDarwin Rambo 
66fccacd3bSPavel Machek /* Returns time in milliseconds */
678dfafddeSRob Herring ulong __weak get_timer(ulong base)
688dfafddeSRob Herring {
698dfafddeSRob Herring 	return tick_to_time(get_ticks()) - base;
708dfafddeSRob Herring }
718dfafddeSRob Herring 
728dfafddeSRob Herring unsigned long __weak notrace timer_get_us(void)
738dfafddeSRob Herring {
748dfafddeSRob Herring 	return tick_to_time(get_ticks() * 1000);
758dfafddeSRob Herring }
76fccacd3bSPavel Machek 
77*19ea4678SSimon Glass static uint64_t usec_to_tick(unsigned long usec)
788dfafddeSRob Herring {
79*19ea4678SSimon Glass 	uint64_t tick = usec;
802cd1b572SStephen Warren 	tick *= get_tbclk();
818dfafddeSRob Herring 	do_div(tick, 1000000);
828dfafddeSRob Herring 	return tick;
838dfafddeSRob Herring }
848dfafddeSRob Herring 
858dfafddeSRob Herring void __weak __udelay(unsigned long usec)
868dfafddeSRob Herring {
87*19ea4678SSimon Glass 	uint64_t tmp;
888dfafddeSRob Herring 
89fccacd3bSPavel Machek 	tmp = get_ticks() + usec_to_tick(usec);	/* get current timestamp */
908dfafddeSRob Herring 
91fccacd3bSPavel Machek 	while (get_ticks() < tmp+1)	/* loop till event */
928dfafddeSRob Herring 		 /*NOP*/;
938dfafddeSRob Herring }
948dfafddeSRob Herring 
9578acc472SPeter Tyser /* ------------------------------------------------------------------------- */
9678acc472SPeter Tyser 
9778acc472SPeter Tyser void udelay(unsigned long usec)
9878acc472SPeter Tyser {
9978acc472SPeter Tyser 	ulong kv;
10078acc472SPeter Tyser 
10178acc472SPeter Tyser 	do {
10278acc472SPeter Tyser 		WATCHDOG_RESET();
10378acc472SPeter Tyser 		kv = usec > CONFIG_WD_PERIOD ? CONFIG_WD_PERIOD : usec;
10478acc472SPeter Tyser 		__udelay (kv);
10578acc472SPeter Tyser 		usec -= kv;
10678acc472SPeter Tyser 	} while(usec);
10778acc472SPeter Tyser }
108c4c9fbebSAnatolij Gustschin 
109c4c9fbebSAnatolij Gustschin void mdelay(unsigned long msec)
110c4c9fbebSAnatolij Gustschin {
111c4c9fbebSAnatolij Gustschin 	while (msec--)
112c4c9fbebSAnatolij Gustschin 		udelay(1000);
113c4c9fbebSAnatolij Gustschin }
114