summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBin Meng <bmeng.cn@gmail.com>2015-11-13 00:11:21 -0800
committerSimon Glass <sjg@chromium.org>2015-12-01 06:23:51 -0700
commit4e51fc2351abbb2ebe42fbedccfec3bba20b1c12 (patch)
treeef1188540c4594794fadb65cd633559bce68de53
parent2f80fc50354ce9c28648a75b345a1c01d112b10f (diff)
downloadu-boot-imx-4e51fc2351abbb2ebe42fbedccfec3bba20b1c12.zip
u-boot-imx-4e51fc2351abbb2ebe42fbedccfec3bba20b1c12.tar.gz
u-boot-imx-4e51fc2351abbb2ebe42fbedccfec3bba20b1c12.tar.bz2
x86: tsc: Add driver model timer support
This adds driver model timer support to x86 tsc timer driver. Signed-off-by: Bin Meng <bmeng.cn@gmail.com> Acked-by: Simon Glass <sjg@chromium.org>
-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 */