xref: /openbmc/u-boot/lib/time.c (revision 8dfafdde)
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>
10*8dfafddeSRob Herring #include <div64.h>
11*8dfafddeSRob 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 
21*8dfafddeSRob Herring DECLARE_GLOBAL_DATA_PTR;
22*8dfafddeSRob Herring 
23*8dfafddeSRob Herring #ifdef CONFIG_SYS_TIMER_RATE
24*8dfafddeSRob Herring ulong notrace get_tbclk(void)
25*8dfafddeSRob Herring {
26*8dfafddeSRob Herring 	return CONFIG_SYS_TIMER_RATE;
27*8dfafddeSRob Herring }
28*8dfafddeSRob Herring #endif
29*8dfafddeSRob Herring 
30*8dfafddeSRob Herring #ifdef CONFIG_SYS_TIMER_COUNTER
31*8dfafddeSRob Herring unsigned long notrace timer_read_counter(void)
32*8dfafddeSRob Herring {
33*8dfafddeSRob Herring #ifdef CONFIG_SYS_TIMER_COUNTS_DOWN
34*8dfafddeSRob Herring 	return ~readl(CONFIG_SYS_TIMER_COUNTER);
35*8dfafddeSRob Herring #else
36*8dfafddeSRob Herring 	return readl(CONFIG_SYS_TIMER_COUNTER);
37*8dfafddeSRob Herring #endif
38*8dfafddeSRob Herring }
39*8dfafddeSRob Herring #else
40*8dfafddeSRob Herring extern unsigned long timer_read_counter(void);
41*8dfafddeSRob Herring #endif
42*8dfafddeSRob Herring 
43*8dfafddeSRob Herring unsigned long long __weak notrace get_ticks(void)
44*8dfafddeSRob Herring {
45*8dfafddeSRob Herring 	unsigned long now = timer_read_counter();
46*8dfafddeSRob Herring 
47*8dfafddeSRob Herring 	/* increment tbu if tbl has rolled over */
48*8dfafddeSRob Herring 	if (now < gd->timebase_l)
49*8dfafddeSRob Herring 		gd->timebase_h++;
50*8dfafddeSRob Herring 	gd->timebase_l = now;
51*8dfafddeSRob Herring 	return ((unsigned long long)gd->timebase_h << 32) | gd->timebase_l;
52*8dfafddeSRob Herring }
53*8dfafddeSRob Herring 
54*8dfafddeSRob Herring static unsigned long long notrace tick_to_time(unsigned long long tick)
55*8dfafddeSRob Herring {
56*8dfafddeSRob Herring 	unsigned int div = get_tbclk();
57*8dfafddeSRob Herring 
58*8dfafddeSRob Herring 	tick *= CONFIG_SYS_HZ;
59*8dfafddeSRob Herring 	do_div(tick, div);
60*8dfafddeSRob Herring 	return tick;
61*8dfafddeSRob Herring }
62*8dfafddeSRob Herring 
63*8dfafddeSRob Herring ulong __weak get_timer(ulong base)
64*8dfafddeSRob Herring {
65*8dfafddeSRob Herring 	return tick_to_time(get_ticks()) - base;
66*8dfafddeSRob Herring }
67*8dfafddeSRob Herring 
68*8dfafddeSRob Herring unsigned long __weak notrace timer_get_us(void)
69*8dfafddeSRob Herring {
70*8dfafddeSRob Herring 	return tick_to_time(get_ticks() * 1000);
71*8dfafddeSRob Herring }
72*8dfafddeSRob Herring static unsigned long long usec_to_tick(unsigned long usec)
73*8dfafddeSRob Herring {
74*8dfafddeSRob Herring 	unsigned long long tick = usec * get_tbclk();
75*8dfafddeSRob Herring 	usec *= get_tbclk();
76*8dfafddeSRob Herring 	do_div(tick, 1000000);
77*8dfafddeSRob Herring 	return tick;
78*8dfafddeSRob Herring }
79*8dfafddeSRob Herring 
80*8dfafddeSRob Herring void __weak __udelay(unsigned long usec)
81*8dfafddeSRob Herring {
82*8dfafddeSRob Herring 	unsigned long long tmp;
83*8dfafddeSRob Herring 	ulong tmo;
84*8dfafddeSRob Herring 
85*8dfafddeSRob Herring 	tmo = usec_to_tick(usec);
86*8dfafddeSRob Herring 	tmp = get_ticks() + tmo;	/* get current timestamp */
87*8dfafddeSRob Herring 
88*8dfafddeSRob Herring 	while (get_ticks() < tmp)	/* loop till event */
89*8dfafddeSRob Herring 		 /*NOP*/;
90*8dfafddeSRob Herring }
91*8dfafddeSRob Herring 
9278acc472SPeter Tyser /* ------------------------------------------------------------------------- */
9378acc472SPeter Tyser 
9478acc472SPeter Tyser void udelay(unsigned long usec)
9578acc472SPeter Tyser {
9678acc472SPeter Tyser 	ulong kv;
9778acc472SPeter Tyser 
9878acc472SPeter Tyser 	do {
9978acc472SPeter Tyser 		WATCHDOG_RESET();
10078acc472SPeter Tyser 		kv = usec > CONFIG_WD_PERIOD ? CONFIG_WD_PERIOD : usec;
10178acc472SPeter Tyser 		__udelay (kv);
10278acc472SPeter Tyser 		usec -= kv;
10378acc472SPeter Tyser 	} while(usec);
10478acc472SPeter Tyser }
105c4c9fbebSAnatolij Gustschin 
106c4c9fbebSAnatolij Gustschin void mdelay(unsigned long msec)
107c4c9fbebSAnatolij Gustschin {
108c4c9fbebSAnatolij Gustschin 	while (msec--)
109c4c9fbebSAnatolij Gustschin 		udelay(1000);
110c4c9fbebSAnatolij Gustschin }
111