summaryrefslogtreecommitdiff
path: root/arch/x86/lib/tsc_timer.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/x86/lib/tsc_timer.c')
-rw-r--r--arch/x86/lib/tsc_timer.c65
1 files changed, 65 insertions, 0 deletions
diff --git a/arch/x86/lib/tsc_timer.c b/arch/x86/lib/tsc_timer.c
index 5a962ce..4a95959 100644
--- a/arch/x86/lib/tsc_timer.c
+++ b/arch/x86/lib/tsc_timer.c
@@ -8,7 +8,9 @@
*/
#include <common.h>
+#include <dm.h>
#include <malloc.h>
+#include <timer.h>
#include <asm/io.h>
#include <asm/i8254.h>
#include <asm/ibmpc.h>
@@ -278,6 +280,7 @@ success:
return delta / 1000;
}
+#ifndef CONFIG_TIMER
void timer_set_base(u64 base)
{
gd->arch.tsc_base = base;
@@ -297,10 +300,14 @@ u64 notrace get_ticks(void)
panic("No tick base available");
return now_tick - gd->arch.tsc_base;
}
+#endif /* CONFIG_TIMER */
/* Get the speed of the TSC timer in MHz */
unsigned notrace long get_tbclk_mhz(void)
{
+#ifdef CONFIG_TIMER
+ return get_tbclk() / 1000000;
+#else
unsigned long fast_calibrate;
if (gd->arch.tsc_mhz)
@@ -320,12 +327,15 @@ unsigned notrace long get_tbclk_mhz(void)
gd->arch.tsc_mhz = fast_calibrate;
return fast_calibrate;
+#endif
}
+#ifndef CONFIG_TIMER
unsigned long get_tbclk(void)
{
return get_tbclk_mhz() * 1000 * 1000;
}
+#endif
static ulong get_ms_timer(void)
{
@@ -375,3 +385,58 @@ int timer_init(void)
return 0;
}
+
+#ifdef CONFIG_TIMER
+static int tsc_timer_get_count(struct udevice *dev, u64 *count)
+{
+ u64 now_tick = rdtsc();
+
+ *count = now_tick - gd->arch.tsc_base;
+
+ return 0;
+}
+
+static int tsc_timer_probe(struct udevice *dev)
+{
+ struct timer_dev_priv *uc_priv = dev_get_uclass_priv(dev);
+
+ gd->arch.tsc_base = rdtsc();
+
+ /*
+ * If there is no clock frequency specified in the device tree,
+ * calibrate it by ourselves.
+ */
+ if (!uc_priv->clock_rate) {
+ unsigned long fast_calibrate;
+
+ fast_calibrate = try_msr_calibrate_tsc();
+ if (!fast_calibrate) {
+ fast_calibrate = quick_pit_calibrate();
+ if (!fast_calibrate)
+ panic("TSC frequency is ZERO");
+ }
+
+ uc_priv->clock_rate = fast_calibrate * 1000000;
+ }
+
+ return 0;
+}
+
+static const struct timer_ops tsc_timer_ops = {
+ .get_count = tsc_timer_get_count,
+};
+
+static const struct udevice_id tsc_timer_ids[] = {
+ { .compatible = "x86,tsc-timer", },
+ { }
+};
+
+U_BOOT_DRIVER(tsc_timer) = {
+ .name = "tsc_timer",
+ .id = UCLASS_TIMER,
+ .of_match = tsc_timer_ids,
+ .probe = tsc_timer_probe,
+ .ops = &tsc_timer_ops,
+ .flags = DM_FLAG_PRE_RELOC,
+};
+#endif /* CONFIG_TIMER */