Commit ca7db866fead1d01ecf018343a99e3cd0d095d51

Authored by Bernhard Messerklinger
Committed by Bin Meng
1 parent 2436396a11

x86: tsc: Add support for native calibration of TSC freq

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.

Signed-off-by: Bernhard Messerklinger <bernhard.messerklinger@br-automation.com>
Reviewed-by: Andy Shevchenko <andy.shevchenko@gmail.com>
Reviewed-by: Bin Meng <bmeng.cn@gmail.com>

Showing 1 changed file with 55 additions and 0 deletions Side-by-side Diff

drivers/timer/tsc_timer.c
... ... @@ -19,8 +19,59 @@
19 19  
20 20 #define MAX_NUM_FREQS 9
21 21  
  22 +#define INTEL_FAM6_SKYLAKE_MOBILE 0x4E
  23 +#define INTEL_FAM6_ATOM_GOLDMONT 0x5C /* Apollo Lake */
  24 +#define INTEL_FAM6_SKYLAKE_DESKTOP 0x5E
  25 +#define INTEL_FAM6_ATOM_GOLDMONT_X 0x5F /* Denverton */
  26 +#define INTEL_FAM6_KABYLAKE_MOBILE 0x8E
  27 +#define INTEL_FAM6_KABYLAKE_DESKTOP 0x9E
  28 +
22 29 DECLARE_GLOBAL_DATA_PTR;
23 30  
  31 +/*
  32 + * native_calibrate_tsc
  33 + * Determine TSC frequency via CPUID, else return 0.
  34 + */
  35 +static unsigned long native_calibrate_tsc(void)
  36 +{
  37 + struct cpuid_result tsc_info;
  38 + unsigned int crystal_freq;
  39 +
  40 + if (gd->arch.x86_vendor != X86_VENDOR_INTEL)
  41 + return 0;
  42 +
  43 + if (cpuid_eax(0) < 0x15)
  44 + return 0;
  45 +
  46 + tsc_info = cpuid(0x15);
  47 +
  48 + if (tsc_info.ebx == 0 || tsc_info.eax == 0)
  49 + return 0;
  50 +
  51 + crystal_freq = tsc_info.ecx / 1000;
  52 +
  53 + if (!crystal_freq) {
  54 + switch (gd->arch.x86_model) {
  55 + case INTEL_FAM6_SKYLAKE_MOBILE:
  56 + case INTEL_FAM6_SKYLAKE_DESKTOP:
  57 + case INTEL_FAM6_KABYLAKE_MOBILE:
  58 + case INTEL_FAM6_KABYLAKE_DESKTOP:
  59 + crystal_freq = 24000; /* 24.0 MHz */
  60 + break;
  61 + case INTEL_FAM6_ATOM_GOLDMONT_X:
  62 + crystal_freq = 25000; /* 25.0 MHz */
  63 + break;
  64 + case INTEL_FAM6_ATOM_GOLDMONT:
  65 + crystal_freq = 19200; /* 19.2 MHz */
  66 + break;
  67 + default:
  68 + return 0;
  69 + }
  70 + }
  71 +
  72 + return (crystal_freq * tsc_info.ebx / tsc_info.eax) / 1000;
  73 +}
  74 +
24 75 static unsigned long cpu_mhz_from_cpuid(void)
25 76 {
26 77 if (gd->arch.x86_vendor != X86_VENDOR_INTEL)
... ... @@ -349,6 +400,10 @@
349 400  
350 401 if (!gd->arch.clock_rate) {
351 402 unsigned long fast_calibrate;
  403 +
  404 + fast_calibrate = native_calibrate_tsc();
  405 + if (fast_calibrate)
  406 + goto done;
352 407  
353 408 fast_calibrate = cpu_mhz_from_cpuid();
354 409 if (fast_calibrate)