X-Git-Url: https://git.sur5r.net/?a=blobdiff_plain;f=drivers%2Ftimer%2Ftsc_timer.c;h=cf869998bf9cc1da3e3d5f1a28c732996bbc8f63;hb=425daac481c1374313f8eae6c159368e12dc4043;hp=4d1fc9cd13707c8a1caa5d2a3be96d5969c23ce6;hpb=167a40166bb116a19d23c946b6394636da34f3cf;p=u-boot diff --git a/drivers/timer/tsc_timer.c b/drivers/timer/tsc_timer.c index 4d1fc9cd13..cf869998bf 100644 --- a/drivers/timer/tsc_timer.c +++ b/drivers/timer/tsc_timer.c @@ -1,10 +1,9 @@ +// SPDX-License-Identifier: GPL-2.0+ /* * Copyright (c) 2012 The Chromium OS Authors. * * TSC calibration codes are adapted from Linux kernel * arch/x86/kernel/tsc_msr.c and arch/x86/kernel/tsc.c - * - * SPDX-License-Identifier: GPL-2.0+ */ #include @@ -18,10 +17,21 @@ #include #include -#define MAX_NUM_FREQS 8 +#define MAX_NUM_FREQS 9 DECLARE_GLOBAL_DATA_PTR; +static unsigned long cpu_mhz_from_cpuid(void) +{ + if (gd->arch.x86_vendor != X86_VENDOR_INTEL) + return 0; + + if (cpuid_eax(0) < 0x16) + return 0; + + return cpuid_eax(0x16); +} + /* * According to Intel 64 and IA-32 System Programming Guide, * if MSR_PERF_STAT[31] is set, the maximum resolved bus ratio can be @@ -40,17 +50,20 @@ struct freq_desc { static struct freq_desc freq_desc_tables[] = { /* PNW */ - { 6, 0x27, 0, { 0, 0, 0, 0, 0, 99840, 0, 83200 } }, + { 6, 0x27, 0, { 0, 0, 0, 0, 0, 99840, 0, 83200, 0 } }, /* CLV+ */ - { 6, 0x35, 0, { 0, 133200, 0, 0, 0, 99840, 0, 83200 } }, + { 6, 0x35, 0, { 0, 133200, 0, 0, 0, 99840, 0, 83200, 0 } }, /* TNG - Intel Atom processor Z3400 series */ - { 6, 0x4a, 1, { 0, 100000, 133300, 0, 0, 0, 0, 0 } }, + { 6, 0x4a, 1, { 0, 100000, 133300, 0, 0, 0, 0, 0, 0 } }, /* VLV2 - Intel Atom processor E3000, Z3600, Z3700 series */ - { 6, 0x37, 1, { 83300, 100000, 133300, 116700, 80000, 0, 0, 0 } }, + { 6, 0x37, 1, { 83300, 100000, 133300, 116700, 80000, 0, 0, 0, 0 } }, /* ANN - Intel Atom processor Z3500 series */ - { 6, 0x5a, 1, { 83300, 100000, 133300, 100000, 0, 0, 0, 0 } }, + { 6, 0x5a, 1, { 83300, 100000, 133300, 100000, 0, 0, 0, 0, 0 } }, + /* AMT - Intel Atom processor X7-Z8000 and X5-Z8000 series */ + { 6, 0x4c, 1, { 83300, 100000, 133300, 116700, + 80000, 93300, 90000, 88900, 87500 } }, /* Ivybridge */ - { 6, 0x3a, 2, { 0, 0, 0, 0, 0, 0, 0, 0 } }, + { 6, 0x3a, 2, { 0, 0, 0, 0, 0, 0, 0, 0, 0 } }, }; static int match_cpu(u8 family, u8 model) @@ -328,32 +341,60 @@ static int tsc_timer_get_count(struct udevice *dev, u64 *count) return 0; } -static int tsc_timer_probe(struct udevice *dev) +static void tsc_timer_ensure_setup(void) { - struct timer_dev_priv *uc_priv = dev_get_uclass_priv(dev); - + if (gd->arch.tsc_base) + return; 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) { + if (!gd->arch.clock_rate) { unsigned long fast_calibrate; + fast_calibrate = cpu_mhz_from_cpuid(); + if (fast_calibrate) + goto done; + fast_calibrate = cpu_mhz_from_msr(); - if (!fast_calibrate) { - fast_calibrate = quick_pit_calibrate(); - if (!fast_calibrate) - panic("TSC frequency is ZERO"); - } + if (fast_calibrate) + goto done; + + fast_calibrate = quick_pit_calibrate(); + if (fast_calibrate) + goto done; - uc_priv->clock_rate = fast_calibrate * 1000000; + panic("TSC frequency is ZERO"); + +done: + gd->arch.clock_rate = fast_calibrate * 1000000; } +} + +static int tsc_timer_probe(struct udevice *dev) +{ + struct timer_dev_priv *uc_priv = dev_get_uclass_priv(dev); + + tsc_timer_ensure_setup(); + uc_priv->clock_rate = gd->arch.clock_rate; return 0; } +unsigned long notrace timer_early_get_rate(void) +{ + tsc_timer_ensure_setup(); + + return gd->arch.clock_rate; +} + +u64 notrace timer_early_get_count(void) +{ + return rdtsc() - gd->arch.tsc_base; +} + static const struct timer_ops tsc_timer_ops = { .get_count = tsc_timer_get_count, };