[U-Boot] [PATCH v3] x86: tsc: Add support for native calibration of TSC freq

Andy Shevchenko andy.shevchenko at gmail.com
Mon Jan 7 14:31:17 UTC 2019


On Mon, Jan 7, 2019 at 1:14 PM Bernhard Messerklinger
<bernhard.messerklinger at br-automation.com> wrote:
>
> Add native tsc calibration function. Calibrate the tsc timer the same
> way as linux does in arch/x86/kernel/tsc.c.
> Fixes booting for Apollo Lake processors.
>

LGTM
Reviewed-by: Andy Shevchenko <andy.shevchenko at gmail.com>

P.S. Though I didn't test it.

> Signed-off-by: Bernhard Messerklinger <bernhard.messerklinger at br-automation.com>
> ---
> I hope this patch won't break other x86 board.
> I only can test it with APL board.
>
> Changes in v4:
> - Fix commit message
> - Update macro names
> - Order macro numbers
> - Check cpuid eax and ebx return value
>
>  drivers/timer/tsc_timer.c | 55 +++++++++++++++++++++++++++++++++++++++
>  1 file changed, 55 insertions(+)
>
> diff --git a/drivers/timer/tsc_timer.c b/drivers/timer/tsc_timer.c
> index ba940ebf1c..919caba8a1 100644
> --- a/drivers/timer/tsc_timer.c
> +++ b/drivers/timer/tsc_timer.c
> @@ -19,8 +19,59 @@
>
>  #define MAX_NUM_FREQS  9
>
> +#define INTEL_FAM6_SKYLAKE_MOBILE      0x4E
> +#define INTEL_FAM6_ATOM_GOLDMONT       0x5C /* Apollo Lake */
> +#define INTEL_FAM6_SKYLAKE_DESKTOP     0x5E
> +#define INTEL_FAM6_ATOM_GOLDMONT_X     0x5F /* Denverton */
> +#define INTEL_FAM6_KABYLAKE_MOBILE     0x8E
> +#define INTEL_FAM6_KABYLAKE_DESKTOP    0x9E
> +
>  DECLARE_GLOBAL_DATA_PTR;
>
> +/*
> + * native_calibrate_tsc
> + * Determine TSC frequency via CPUID, else return 0.
> + */
> +static unsigned long native_calibrate_tsc(void)
> +{
> +       struct cpuid_result tsc_info;
> +       unsigned int crystal_freq;
> +
> +       if (gd->arch.x86_vendor != X86_VENDOR_INTEL)
> +               return 0;
> +
> +       if (cpuid_eax(0) < 0x15)
> +               return 0;
> +
> +       tsc_info = cpuid(0x15);
> +
> +       if (tsc_info.ebx == 0 || tsc_info.eax == 0)
> +               return 0;
> +
> +       crystal_freq = tsc_info.ecx / 1000;
> +
> +       if (!crystal_freq) {
> +               switch (gd->arch.x86_model) {
> +               case INTEL_FAM6_SKYLAKE_MOBILE:
> +               case INTEL_FAM6_SKYLAKE_DESKTOP:
> +               case INTEL_FAM6_KABYLAKE_MOBILE:
> +               case INTEL_FAM6_KABYLAKE_DESKTOP:
> +                       crystal_freq = 24000;   /* 24.0 MHz */
> +                       break;
> +               case INTEL_FAM6_ATOM_GOLDMONT_X:
> +                       crystal_freq = 25000;   /* 25.0 MHz */
> +                       break;
> +               case INTEL_FAM6_ATOM_GOLDMONT:
> +                       crystal_freq = 19200;   /* 19.2 MHz */
> +                       break;
> +               default:
> +                       return 0;
> +               }
> +       }
> +
> +       return (crystal_freq * tsc_info.ebx / tsc_info.eax) / 1000;
> +}
> +
>  static unsigned long cpu_mhz_from_cpuid(void)
>  {
>         if (gd->arch.x86_vendor != X86_VENDOR_INTEL)
> @@ -350,6 +401,10 @@ static void tsc_timer_ensure_setup(bool early)
>         if (!gd->arch.clock_rate) {
>                 unsigned long fast_calibrate;
>
> +               fast_calibrate = native_calibrate_tsc();
> +               if (fast_calibrate)
> +                       goto done;
> +
>                 fast_calibrate = cpu_mhz_from_cpuid();
>                 if (fast_calibrate)
>                         goto done;
> --
> 2.20.1
>
>


-- 
With Best Regards,
Andy Shevchenko


More information about the U-Boot mailing list