[U-Boot] [PATCH 1/6] 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 bmeng.cn@gmail.com ---
drivers/timer/tsc_timer.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/timer/tsc_timer.c b/drivers/timer/tsc_timer.c index 5c4ec00..ffbc709 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;

cpu_mhz_from_msr() 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 bmeng.cn@gmail.com ---
drivers/timer/tsc_timer.c | 4 ++++ 1 file changed, 4 insertions(+)
diff --git a/drivers/timer/tsc_timer.c b/drivers/timer/tsc_timer.c index ffbc709..4d01c9b 100644 --- a/drivers/timer/tsc_timer.c +++ b/drivers/timer/tsc_timer.c @@ -11,6 +11,7 @@ #include <dm.h> #include <malloc.h> #include <timer.h> +#include <asm/cpu.h> #include <asm/io.h> #include <asm/i8254.h> #include <asm/ibmpc.h> @@ -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;

On Wed, Jul 26, 2017 at 11:12 AM, Bin Meng bmeng.cn@gmail.com wrote:
cpu_mhz_from_msr() is currently Intel-specific, and should not
oops: patch ordering issue :)
It should be: try_msr_calibrate_tsc()... as try_msr_calibrate_tsc() is renamed to cpu_mhz_from_msr() in patch [6/6]
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 bmeng.cn@gmail.com
drivers/timer/tsc_timer.c | 4 ++++ 1 file changed, 4 insertions(+)
Regards, Bin

On 25 July 2017 at 21:12, Bin Meng bmeng.cn@gmail.com wrote:
cpu_mhz_from_msr() 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 bmeng.cn@gmail.com
drivers/timer/tsc_timer.c | 4 ++++ 1 file changed, 4 insertions(+)
Reviewed-by: Simon Glass sjg@chromium.org

On Tue, Aug 1, 2017 at 5:11 PM, Simon Glass sjg@chromium.org wrote:
On 25 July 2017 at 21:12, Bin Meng bmeng.cn@gmail.com wrote:
cpu_mhz_from_msr() is currently Intel-specific, and should not
Fixed the commit message, and
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 bmeng.cn@gmail.com
drivers/timer/tsc_timer.c | 4 ++++ 1 file changed, 4 insertions(+)
Reviewed-by: Simon Glass sjg@chromium.org
applied to u-boot-x86, thanks!

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 bmeng.cn@gmail.com ---
drivers/timer/tsc_timer.c | 9 --------- 1 file changed, 9 deletions(-)
diff --git a/drivers/timer/tsc_timer.c b/drivers/timer/tsc_timer.c index 4d01c9b..bdbecac 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; }
/*

On 25 July 2017 at 21:12, Bin Meng bmeng.cn@gmail.com wrote:
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 bmeng.cn@gmail.com
drivers/timer/tsc_timer.c | 9 --------- 1 file changed, 9 deletions(-)
Reviewed-by: Simon Glass sjg@chromium.org

On Tue, Aug 1, 2017 at 5:11 PM, Simon Glass sjg@chromium.org wrote:
On 25 July 2017 at 21:12, Bin Meng bmeng.cn@gmail.com wrote:
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 bmeng.cn@gmail.com
drivers/timer/tsc_timer.c | 9 --------- 1 file changed, 9 deletions(-)
Reviewed-by: Simon Glass sjg@chromium.org
applied to u-boot-x86, thanks!

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 bmeng.cn@gmail.com ---
drivers/timer/tsc_timer.c | 24 +++++++++--------------- 1 file changed, 9 insertions(+), 15 deletions(-)
diff --git a/drivers/timer/tsc_timer.c b/drivers/timer/tsc_timer.c index bdbecac..3c1b745 100644 --- a/drivers/timer/tsc_timer.c +++ b/drivers/timer/tsc_timer.c @@ -18,12 +18,6 @@ #include <asm/msr.h> #include <asm/u-boot-x86.h>
-/* 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 */

On 25 July 2017 at 21:12, Bin Meng bmeng.cn@gmail.com wrote:
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 bmeng.cn@gmail.com
drivers/timer/tsc_timer.c | 24 +++++++++--------------- 1 file changed, 9 insertions(+), 15 deletions(-)
Reviewed-by: Simon Glass sjg@chromium.org

On Tue, Aug 1, 2017 at 5:11 PM, Simon Glass sjg@chromium.org wrote:
On 25 July 2017 at 21:12, Bin Meng bmeng.cn@gmail.com wrote:
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 bmeng.cn@gmail.com
drivers/timer/tsc_timer.c | 24 +++++++++--------------- 1 file changed, 9 insertions(+), 15 deletions(-)
Reviewed-by: Simon Glass sjg@chromium.org
applied to u-boot-x86, thanks!

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 bmeng.cn@gmail.com ---
drivers/timer/tsc_timer.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-)
diff --git a/drivers/timer/tsc_timer.c b/drivers/timer/tsc_timer.c index 3c1b745..b242e74 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 */

On 25 July 2017 at 21:12, Bin Meng bmeng.cn@gmail.com wrote:
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 bmeng.cn@gmail.com
drivers/timer/tsc_timer.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-)
Reviewed-by: Simon Glass sjg@chromium.org

On Tue, Aug 1, 2017 at 5:11 PM, Simon Glass sjg@chromium.org wrote:
On 25 July 2017 at 21:12, Bin Meng bmeng.cn@gmail.com wrote:
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 bmeng.cn@gmail.com
drivers/timer/tsc_timer.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-)
Reviewed-by: Simon Glass sjg@chromium.org
applied to u-boot-x86, thanks!

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 bmeng.cn@gmail.com ---
drivers/timer/tsc_timer.c | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-)
diff --git a/drivers/timer/tsc_timer.c b/drivers/timer/tsc_timer.c index b242e74..4d1fc9c 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)

On 25 July 2017 at 21:12, Bin Meng bmeng.cn@gmail.com wrote:
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 bmeng.cn@gmail.com
drivers/timer/tsc_timer.c | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-)
Reviewed-by: Simon Glass sjg@chromium.org

On Tue, Aug 1, 2017 at 5:11 PM, Simon Glass sjg@chromium.org wrote:
On 25 July 2017 at 21:12, Bin Meng bmeng.cn@gmail.com wrote:
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 bmeng.cn@gmail.com
drivers/timer/tsc_timer.c | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-)
Reviewed-by: Simon Glass sjg@chromium.org
applied to u-boot-x86, thanks!

On 25 July 2017 at 21:12, Bin Meng bmeng.cn@gmail.com wrote:
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 bmeng.cn@gmail.com
drivers/timer/tsc_timer.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
Reviewed-by: Simon Glass sjg@chromium.org

On Tue, Aug 1, 2017 at 5:10 PM, Simon Glass sjg@chromium.org wrote:
On 25 July 2017 at 21:12, Bin Meng bmeng.cn@gmail.com wrote:
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 bmeng.cn@gmail.com
drivers/timer/tsc_timer.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
Reviewed-by: Simon Glass sjg@chromium.org
applied to u-boot-x86, thanks!
participants (2)
-
Bin Meng
-
Simon Glass