BACKPORT: x86: add TSC_CONSTANT_RATE option
Some boards use the local apic for udelay(), but they also provide their own implementation of udelay() for SMM. The reason for using the local apic for udelay() in ramstage is to not have to pay the penalty of calibrating the TSC frequency. Therefore provide a TSC_CONSTANT_RATE option to indicate that TSC calibration is not needed. Instead rely on the presence of a tsc_freq_mhz() function provided by the cpu/board. Additionally, assume that if TSC_CONSTANT_RATE is selected the udelay() function in SMM will be the tsc. BUG=None BRANCH=None TEST=Compiled and booted Change-Id: Ic7096b7f5c9dec26a3f0441e6715fe02b15d44db Signed-off-by: Aaron Durbin <adurbin@chromium.org> Reviewed-on: https://gerrit.chromium.org/gerrit/50453 Reviewed-by: Stefan Reinauer <reinauer@google.com>
This commit is contained in:
parent
60a09eac23
commit
f024361729
4 changed files with 39 additions and 3 deletions
|
|
@ -25,6 +25,13 @@ config UDELAY_TSC
|
|||
bool
|
||||
default n
|
||||
|
||||
config TSC_CONSTANT_RATE
|
||||
def_bool n
|
||||
depends on UDELAY_TSC
|
||||
help
|
||||
This option asserts that the TSC ticks at a known constant rate.
|
||||
Therefore, no TSC calibration is required.
|
||||
|
||||
config TSC_MONOTONIC_TIMER
|
||||
def_bool n
|
||||
depends on UDELAY_TSC
|
||||
|
|
|
|||
|
|
@ -1,2 +1,6 @@
|
|||
ramstage-$(CONFIG_UDELAY_TSC) += delay_tsc.c
|
||||
romstage-$(CONFIG_TSC_CONSTANT_RATE) += delay_tsc.c
|
||||
ifeq ($(CONFIG_HAVE_SMI_HANDLER),y)
|
||||
smm-$(CONFIG_TSC_CONSTANT_RATE) += delay_tsc.c
|
||||
endif
|
||||
|
||||
|
|
|
|||
|
|
@ -5,8 +5,16 @@
|
|||
#include <smp/spinlock.h>
|
||||
#include <delay.h>
|
||||
|
||||
#if !defined(__PRE_RAM__)
|
||||
|
||||
static unsigned long clocks_per_usec;
|
||||
|
||||
#if CONFIG_TSC_CONSTANT_RATE
|
||||
static unsigned long calibrate_tsc(void)
|
||||
{
|
||||
return tsc_freq_mhz();
|
||||
}
|
||||
#else /* CONFIG_TSC_CONSTANT_RATE */
|
||||
#if !CONFIG_TSC_CALIBRATE_WITH_IO
|
||||
#define CLOCK_TICK_RATE 1193180U /* Underlying HZ */
|
||||
|
||||
|
|
@ -139,6 +147,7 @@ static unsigned long long calibrate_tsc(void)
|
|||
|
||||
|
||||
#endif /* CONFIG_TSC_CALIBRATE_WITH_IO */
|
||||
#endif /* CONFIG_TSC_CONSTANT_RATE */
|
||||
|
||||
void init_timer(void)
|
||||
{
|
||||
|
|
@ -148,15 +157,27 @@ void init_timer(void)
|
|||
}
|
||||
}
|
||||
|
||||
static inline unsigned long get_clocks_per_usec(void)
|
||||
{
|
||||
init_timer();
|
||||
return clocks_per_usec;
|
||||
}
|
||||
#else /* !defined(__PRE_RAM__) */
|
||||
/* romstage calls into cpu/board specific function every time. */
|
||||
static inline unsigned long get_clocks_per_usec(void)
|
||||
{
|
||||
return tsc_freq_mhz();
|
||||
}
|
||||
#endif /* !defined(__PRE_RAM__) */
|
||||
|
||||
void udelay(unsigned us)
|
||||
{
|
||||
unsigned long long count;
|
||||
unsigned long long stop;
|
||||
unsigned long long clocks;
|
||||
|
||||
init_timer();
|
||||
clocks = us;
|
||||
clocks *= clocks_per_usec;
|
||||
clocks *= get_clocks_per_usec();
|
||||
count = rdtscll();
|
||||
stop = clocks + count;
|
||||
while(stop > count) {
|
||||
|
|
@ -165,7 +186,7 @@ void udelay(unsigned us)
|
|||
}
|
||||
}
|
||||
|
||||
#if CONFIG_TSC_MONOTONIC_TIMER
|
||||
#if CONFIG_TSC_MONOTONIC_TIMER && !defined(__PRE_RAM__) && !defined(__SMM__)
|
||||
#include <timer.h>
|
||||
|
||||
static struct monotonic_counter {
|
||||
|
|
|
|||
|
|
@ -40,4 +40,8 @@ static inline unsigned long long rdtscll(void)
|
|||
}
|
||||
#endif
|
||||
|
||||
#if CONFIG_TSC_CONSTANT_RATE
|
||||
unsigned long tsc_freq_mhz(void);
|
||||
#endif
|
||||
|
||||
#endif /* CPU_X86_TSC_H */
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue