Commit c95fec31 authored by Simon Glass's avatar Simon Glass

timer: Provide an early timer

In some cases the timer must be accessible before driver model is active.
Examples include when using CONFIG_TRACE to trace U-Boot's execution before
driver model is set up. Enable this option to use an early timer. These
functions must be supported by your timer driver: timer_early_get_count()
and timer_early_get_rate().
Signed-off-by: default avatarSimon Glass <sjg@chromium.org>
parent 4f051824
......@@ -9,6 +9,16 @@ config TIMER
will be used. The timer is usually a 32 bits free-running up
counter. There may be no real tick, and no timer interrupt.
config TIMER_EARLY
bool "Allow timer to be used early in U-Boot"
depends on TIMER
help
In some cases the timer must be accessible before driver model is
active. Examples include when using CONFIG_TRACE to trace U-Boot's
execution before driver model is set up. Enable this option to
use an early timer. These functions must be supported by your timer
driver: timer_early_get_count() and timer_early_get_rate().
config ALTERA_TIMER
bool "Altera timer support"
depends on TIMER
......
......@@ -67,4 +67,25 @@ struct timer_dev_priv {
unsigned long clock_rate;
};
/**
* timer_early_get_count() - Implement timer_get_count() before driver model
*
* If CONFIG_TIMER_EARLY is enabled, this function wil be called to return
* the current timer value before the proper driver model timer is ready.
* It should be implemented by one of the timer values. This is mostly useful
* for tracing.
*/
u64 timer_early_get_count(void);
/**
* timer_early_get_rate() - Get the timer rate before driver model
*
* If CONFIG_TIMER_EARLY is enabled, this function wil be called to return
* the current timer rate in Hz before the proper driver model timer is ready.
* It should be implemented by one of the timer values. This is mostly useful
* for tracing. This corresponds to the clock_rate value in struct
* timer_dev_priv.
*/
unsigned long timer_early_get_rate(void);
#endif /* _TIMER_H_ */
......@@ -43,11 +43,17 @@ extern unsigned long __weak timer_read_counter(void);
#ifdef CONFIG_TIMER
ulong notrace get_tbclk(void)
{
int ret;
if (!gd->timer) {
#ifdef CONFIG_TIMER_EARLY
return timer_early_get_rate();
#else
int ret;
ret = dm_timer_init();
if (ret)
return ret;
ret = dm_timer_init();
if (ret)
return ret;
#endif
}
return timer_get_rate(gd->timer);
}
......@@ -57,9 +63,17 @@ uint64_t notrace get_ticks(void)
u64 count;
int ret;
ret = dm_timer_init();
if (ret)
return ret;
if (!gd->timer) {
#ifdef CONFIG_TIMER_EARLY
return timer_early_get_count();
#else
int ret;
ret = dm_timer_init();
if (ret)
return ret;
#endif
}
ret = timer_get_count(gd->timer, &count);
if (ret)
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment