From d92e9c8d313134f2ebde14a393f820b2191f4011 Mon Sep 17 00:00:00 2001 From: Bin Meng Date: Tue, 25 Jul 2017 20:12:00 -0700 Subject: x86: tsc: Read all ratio bits from MSR_PLATFORM_INFO Currently we read the tsc radio like this: ratio = (MSR_PLATFORM_INFO >> 8) & 0x1f; Thus we get bit 8-12 of MSR_PLATFORM_INFO, however according to the Intel manual, the ratio bits are bit 8-15. Fix this problem by masking 0xff instead. This keeps in sync with Linux kernel commit: 886123f: x86/tsc: Read all ratio bits from MSR_PLATFORM_INFO Signed-off-by: Bin Meng Reviewed-by: Simon Glass --- drivers/timer/tsc_timer.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/timer/tsc_timer.c') diff --git a/drivers/timer/tsc_timer.c b/drivers/timer/tsc_timer.c index 5c4ec0018f6..ffbc7091fa2 100644 --- a/drivers/timer/tsc_timer.c +++ b/drivers/timer/tsc_timer.c @@ -92,7 +92,7 @@ static unsigned long __maybe_unused try_msr_calibrate_tsc(void) if (freq_desc_tables[cpu_index].msr_plat) { rdmsr(MSR_PLATFORM_INFO, lo, hi); - ratio = (lo >> 8) & 0x1f; + ratio = (lo >> 8) & 0xff; } else { rdmsr(MSR_IA32_PERF_STATUS, lo, hi); ratio = (hi >> 8) & 0x1f; -- cgit v1.2.3 From 0b992e4932303b0a379f590f67ec9759fc97275e Mon Sep 17 00:00:00 2001 From: Bin Meng Date: Tue, 25 Jul 2017 20:12:01 -0700 Subject: x86: tsc: Identify Intel-specific code try_msr_calibrate_tsc() is currently Intel-specific, and should not execute on any other vendor's parts. This keeps in sync with Linux kernel commit: ba82683: x86/tsc_msr: Identify Intel-specific code Signed-off-by: Bin Meng Reviewed-by: Simon Glass --- drivers/timer/tsc_timer.c | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'drivers/timer/tsc_timer.c') diff --git a/drivers/timer/tsc_timer.c b/drivers/timer/tsc_timer.c index ffbc7091fa2..4d01c9bce79 100644 --- a/drivers/timer/tsc_timer.c +++ b/drivers/timer/tsc_timer.c @@ -11,6 +11,7 @@ #include #include #include +#include #include #include #include @@ -86,6 +87,9 @@ static unsigned long __maybe_unused try_msr_calibrate_tsc(void) unsigned long res; int cpu_index; + if (gd->arch.x86_vendor != X86_VENDOR_INTEL) + return 0; + cpu_index = match_cpu(gd->arch.x86, gd->arch.x86_model); if (cpu_index < 0) return 0; -- cgit v1.2.3 From fde1801eaa09adcbb26b53e53a52e5067e23d1dd Mon Sep 17 00:00:00 2001 From: Bin Meng Date: Tue, 25 Jul 2017 20:12:02 -0700 Subject: x86: tsc: Remove the fail handling in try_msr_calibrate_tsc() If either ratio or freq is zero, the return value is zero. There is no need to create a fail branch and return zero there. This keeps in sync with Linux kernel commit: 14bb4e3: x86/tsc_msr: Remove debugging messages Signed-off-by: Bin Meng Reviewed-by: Simon Glass --- drivers/timer/tsc_timer.c | 9 --------- 1 file changed, 9 deletions(-) (limited to 'drivers/timer/tsc_timer.c') diff --git a/drivers/timer/tsc_timer.c b/drivers/timer/tsc_timer.c index 4d01c9bce79..bdbecac196b 100644 --- a/drivers/timer/tsc_timer.c +++ b/drivers/timer/tsc_timer.c @@ -103,9 +103,6 @@ static unsigned long __maybe_unused try_msr_calibrate_tsc(void) } debug("Maximum core-clock to bus-clock ratio: 0x%x\n", ratio); - if (!ratio) - goto fail; - if (freq_desc_tables[cpu_index].msr_plat == 2) { /* TODO: Figure out how best to deal with this */ freq = FREQ_100; @@ -118,18 +115,12 @@ static unsigned long __maybe_unused try_msr_calibrate_tsc(void) debug("Resolved frequency ID: %u, frequency: %u KHz\n", freq_id, freq); } - if (!freq) - goto fail; /* TSC frequency = maximum resolved freq * maximum resolved bus ratio */ res = freq * ratio / 1000; debug("TSC runs at %lu MHz\n", res); return res; - -fail: - debug("Fast TSC calibration using MSR failed\n"); - return 0; } /* -- cgit v1.2.3 From c6367748483049236d3ebdc389161f1ba472f266 Mon Sep 17 00:00:00 2001 From: Bin Meng Date: Tue, 25 Jul 2017 20:12:03 -0700 Subject: x86: tsc: Update comments and expand definitions in freq_desc_tables[] Some processor abbreviations in the comments of freq_desc_tables[] are obscure. This updates part of these to mention processors that are known to us. Also expand frequency definitions. This keeps in sync with Linux kernel commit: 9e0cae9: x86/tsc_msr: Update comments, expand definitions Signed-off-by: Bin Meng Reviewed-by: Simon Glass --- drivers/timer/tsc_timer.c | 24 +++++++++--------------- 1 file changed, 9 insertions(+), 15 deletions(-) (limited to 'drivers/timer/tsc_timer.c') diff --git a/drivers/timer/tsc_timer.c b/drivers/timer/tsc_timer.c index bdbecac196b..3c1b745e16a 100644 --- a/drivers/timer/tsc_timer.c +++ b/drivers/timer/tsc_timer.c @@ -18,12 +18,6 @@ #include #include -/* CPU reference clock frequency: in KHz */ -#define FREQ_83 83200 -#define FREQ_100 99840 -#define FREQ_133 133200 -#define FREQ_166 166400 - #define MAX_NUM_FREQS 8 DECLARE_GLOBAL_DATA_PTR; @@ -46,17 +40,17 @@ struct freq_desc { static struct freq_desc freq_desc_tables[] = { /* PNW */ - { 6, 0x27, 0, { 0, 0, 0, 0, 0, FREQ_100, 0, FREQ_83 } }, + { 6, 0x27, 0, { 0, 0, 0, 0, 0, 99840, 0, 83200 } }, /* CLV+ */ - { 6, 0x35, 0, { 0, FREQ_133, 0, 0, 0, FREQ_100, 0, FREQ_83 } }, - /* TNG */ - { 6, 0x4a, 1, { 0, FREQ_100, FREQ_133, 0, 0, 0, 0, 0 } }, - /* VLV2 */ - { 6, 0x37, 1, { FREQ_83, FREQ_100, FREQ_133, FREQ_166, 0, 0, 0, 0 } }, + { 6, 0x35, 0, { 0, 133200, 0, 0, 0, 99840, 0, 83200 } }, + /* TNG - Intel Atom processor Z3400 series */ + { 6, 0x4a, 1, { 0, 99840, 133200, 0, 0, 0, 0, 0 } }, + /* VLV2 - Intel Atom processor E3000, Z3600, Z3700 series */ + { 6, 0x37, 1, { 83200, 99840, 133200, 166400, 0, 0, 0, 0 } }, + /* ANN - Intel Atom processor Z3500 series */ + { 6, 0x5a, 1, { 83200, 99840, 133200, 99840, 0, 0, 0, 0 } }, /* Ivybridge */ { 6, 0x3a, 2, { 0, 0, 0, 0, 0, 0, 0, 0 } }, - /* ANN */ - { 6, 0x5a, 1, { FREQ_83, FREQ_100, FREQ_133, FREQ_100, 0, 0, 0, 0 } }, }; static int match_cpu(u8 family, u8 model) @@ -105,7 +99,7 @@ static unsigned long __maybe_unused try_msr_calibrate_tsc(void) if (freq_desc_tables[cpu_index].msr_plat == 2) { /* TODO: Figure out how best to deal with this */ - freq = FREQ_100; + freq = 99840; debug("Using frequency: %u KHz\n", freq); } else { /* Get FSB FREQ ID */ -- cgit v1.2.3 From f5757154bb2a00d529fa999da44dd18965b70738 Mon Sep 17 00:00:00 2001 From: Bin Meng Date: Tue, 25 Jul 2017 20:12:04 -0700 Subject: x86: tsc: Correct Silvermont reference clock values Atom processors use a 19.2 MHz crystal oscillator. Early processors generate 100 MHz via 19.2 MHz * 26 / 5 = 99.84 MHz. Later processors generate 100 MHz via 19.2 MHz * 125 / 24 = 100 MHz. Update the Silvermont-based tables accordingly, matching the Software Developers Manual. Also, correct a 166 MHz entry that should have been 116 MHz, and add a missing 80 MHz entry for VLV2. This keeps in sync with Linux kernel commit: 05680e7: x86/tsc_msr: Correct Silvermont reference clock values Signed-off-by: Bin Meng Reviewed-by: Simon Glass --- drivers/timer/tsc_timer.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'drivers/timer/tsc_timer.c') diff --git a/drivers/timer/tsc_timer.c b/drivers/timer/tsc_timer.c index 3c1b745e16a..b242e7488a3 100644 --- a/drivers/timer/tsc_timer.c +++ b/drivers/timer/tsc_timer.c @@ -44,11 +44,11 @@ static struct freq_desc freq_desc_tables[] = { /* CLV+ */ { 6, 0x35, 0, { 0, 133200, 0, 0, 0, 99840, 0, 83200 } }, /* TNG - Intel Atom processor Z3400 series */ - { 6, 0x4a, 1, { 0, 99840, 133200, 0, 0, 0, 0, 0 } }, + { 6, 0x4a, 1, { 0, 100000, 133300, 0, 0, 0, 0, 0 } }, /* VLV2 - Intel Atom processor E3000, Z3600, Z3700 series */ - { 6, 0x37, 1, { 83200, 99840, 133200, 166400, 0, 0, 0, 0 } }, + { 6, 0x37, 1, { 83300, 100000, 133300, 116700, 80000, 0, 0, 0 } }, /* ANN - Intel Atom processor Z3500 series */ - { 6, 0x5a, 1, { 83200, 99840, 133200, 99840, 0, 0, 0, 0 } }, + { 6, 0x5a, 1, { 83300, 100000, 133300, 100000, 0, 0, 0, 0 } }, /* Ivybridge */ { 6, 0x3a, 2, { 0, 0, 0, 0, 0, 0, 0, 0 } }, }; @@ -99,7 +99,7 @@ static unsigned long __maybe_unused try_msr_calibrate_tsc(void) if (freq_desc_tables[cpu_index].msr_plat == 2) { /* TODO: Figure out how best to deal with this */ - freq = 99840; + freq = 100000; debug("Using frequency: %u KHz\n", freq); } else { /* Get FSB FREQ ID */ -- cgit v1.2.3 From 167a40166bb116a19d23c946b6394636da34f3cf Mon Sep 17 00:00:00 2001 From: Bin Meng Date: Tue, 25 Jul 2017 20:12:05 -0700 Subject: x86: tsc: Rename try_msr_calibrate_tsc() to cpu_mhz_from_msr() Rename try_msr_calibrate_tsc() to cpu_mhz_from_msr(), as that better describes what the routine does. This keeps in sync with Linux kernel commit: 02c0cd2: x86/tsc_msr: Remove irqoff around MSR-based TSC enumeration Signed-off-by: Bin Meng Reviewed-by: Simon Glass --- drivers/timer/tsc_timer.c | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) (limited to 'drivers/timer/tsc_timer.c') diff --git a/drivers/timer/tsc_timer.c b/drivers/timer/tsc_timer.c index b242e7488a3..4d1fc9cd137 100644 --- a/drivers/timer/tsc_timer.c +++ b/drivers/timer/tsc_timer.c @@ -71,11 +71,16 @@ static int match_cpu(u8 family, u8 model) (freq_desc_tables[cpu_index].freqs[freq_id]) /* - * Do MSR calibration only for known/supported CPUs. + * TSC on Intel Atom SoCs capable of determining TSC frequency by MSR is + * reliable and the frequency is known (provided by HW). * - * Returns the calibration value or 0 if MSR calibration failed. + * On these platforms PIT/HPET is generally not available so calibration won't + * work at all and there is no other clocksource to act as a watchdog for the + * TSC, so we have no other choice than to trust it. + * + * Returns the TSC frequency in MHz or 0 if HW does not provide it. */ -static unsigned long __maybe_unused try_msr_calibrate_tsc(void) +static unsigned long __maybe_unused cpu_mhz_from_msr(void) { u32 lo, hi, ratio, freq_id, freq; unsigned long res; @@ -336,7 +341,7 @@ static int tsc_timer_probe(struct udevice *dev) if (!uc_priv->clock_rate) { unsigned long fast_calibrate; - fast_calibrate = try_msr_calibrate_tsc(); + fast_calibrate = cpu_mhz_from_msr(); if (!fast_calibrate) { fast_calibrate = quick_pit_calibrate(); if (!fast_calibrate) -- cgit v1.2.3