mirror of
https://source.denx.de/u-boot/u-boot.git
synced 2025-12-16 06:51:41 +01:00
x86: Add a CPU driver for baytrail
This driver supports multi-core init and sets up the CPU frequencies correctly. Signed-off-by: Simon Glass <sjg@chromium.org> Reviewed-by: Bin Meng <bmeng.cn@gmail.com>
This commit is contained in:
parent
bcb0c61e1a
commit
ede9709316
@ -4,6 +4,7 @@
|
|||||||
# SPDX-License-Identifier: GPL-2.0+
|
# SPDX-License-Identifier: GPL-2.0+
|
||||||
#
|
#
|
||||||
|
|
||||||
|
obj-y += cpu.o
|
||||||
obj-y += early_uart.o
|
obj-y += early_uart.o
|
||||||
obj-y += fsp_configs.o
|
obj-y += fsp_configs.o
|
||||||
obj-y += pci.o
|
obj-y += pci.o
|
||||||
|
|||||||
205
arch/x86/cpu/baytrail/cpu.c
Normal file
205
arch/x86/cpu/baytrail/cpu.c
Normal file
@ -0,0 +1,205 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2015 Google, Inc
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: GPL-2.0+
|
||||||
|
*
|
||||||
|
* Based on code from coreboot
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <common.h>
|
||||||
|
#include <cpu.h>
|
||||||
|
#include <dm.h>
|
||||||
|
#include <asm/cpu.h>
|
||||||
|
#include <asm/lapic.h>
|
||||||
|
#include <asm/mp.h>
|
||||||
|
#include <asm/msr.h>
|
||||||
|
#include <asm/turbo.h>
|
||||||
|
|
||||||
|
#ifdef CONFIG_SMP
|
||||||
|
static int enable_smis(struct udevice *cpu, void *unused)
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static struct mp_flight_record mp_steps[] = {
|
||||||
|
MP_FR_BLOCK_APS(mp_init_cpu, NULL, mp_init_cpu, NULL),
|
||||||
|
/* Wait for APs to finish initialization before proceeding. */
|
||||||
|
MP_FR_BLOCK_APS(NULL, NULL, enable_smis, NULL),
|
||||||
|
};
|
||||||
|
|
||||||
|
static int detect_num_cpus(void)
|
||||||
|
{
|
||||||
|
int ecx = 0;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Use the algorithm described in Intel 64 and IA-32 Architectures
|
||||||
|
* Software Developer's Manual Volume 3 (3A, 3B & 3C): System
|
||||||
|
* Programming Guide, Jan-2015. Section 8.9.2: Hierarchical Mapping
|
||||||
|
* of CPUID Extended Topology Leaf.
|
||||||
|
*/
|
||||||
|
while (1) {
|
||||||
|
struct cpuid_result leaf_b;
|
||||||
|
|
||||||
|
leaf_b = cpuid_ext(0xb, ecx);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Bay Trail doesn't have hyperthreading so just determine the
|
||||||
|
* number of cores by from level type (ecx[15:8] == * 2)
|
||||||
|
*/
|
||||||
|
if ((leaf_b.ecx & 0xff00) == 0x0200)
|
||||||
|
return leaf_b.ebx & 0xffff;
|
||||||
|
ecx++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static int baytrail_init_cpus(void)
|
||||||
|
{
|
||||||
|
struct mp_params mp_params;
|
||||||
|
|
||||||
|
lapic_setup();
|
||||||
|
|
||||||
|
mp_params.num_cpus = detect_num_cpus();
|
||||||
|
mp_params.parallel_microcode_load = 0,
|
||||||
|
mp_params.flight_plan = &mp_steps[0];
|
||||||
|
mp_params.num_records = ARRAY_SIZE(mp_steps);
|
||||||
|
mp_params.microcode_pointer = 0;
|
||||||
|
|
||||||
|
if (mp_init(&mp_params)) {
|
||||||
|
printf("Warning: MP init failure\n");
|
||||||
|
return -EIO;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
int x86_init_cpus(void)
|
||||||
|
{
|
||||||
|
#ifdef CONFIG_SMP
|
||||||
|
debug("Init additional CPUs\n");
|
||||||
|
baytrail_init_cpus();
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void set_max_freq(void)
|
||||||
|
{
|
||||||
|
msr_t perf_ctl;
|
||||||
|
msr_t msr;
|
||||||
|
|
||||||
|
/* Enable speed step */
|
||||||
|
msr = msr_read(MSR_IA32_MISC_ENABLES);
|
||||||
|
msr.lo |= (1 << 16);
|
||||||
|
msr_write(MSR_IA32_MISC_ENABLES, msr);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Set guaranteed ratio [21:16] from IACORE_RATIOS to bits [15:8] of
|
||||||
|
* the PERF_CTL
|
||||||
|
*/
|
||||||
|
msr = msr_read(MSR_IACORE_RATIOS);
|
||||||
|
perf_ctl.lo = (msr.lo & 0x3f0000) >> 8;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Set guaranteed vid [21:16] from IACORE_VIDS to bits [7:0] of
|
||||||
|
* the PERF_CTL
|
||||||
|
*/
|
||||||
|
msr = msr_read(MSR_IACORE_VIDS);
|
||||||
|
perf_ctl.lo |= (msr.lo & 0x7f0000) >> 16;
|
||||||
|
perf_ctl.hi = 0;
|
||||||
|
|
||||||
|
msr_write(MSR_IA32_PERF_CTL, perf_ctl);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int cpu_x86_baytrail_probe(struct udevice *dev)
|
||||||
|
{
|
||||||
|
debug("Init BayTrail core\n");
|
||||||
|
|
||||||
|
/*
|
||||||
|
* On BayTrail the turbo disable bit is actually scoped at the
|
||||||
|
* building-block level, not package. For non-BSP cores that are
|
||||||
|
* within a building block, enable turbo. The cores within the BSP's
|
||||||
|
* building block will just see it already enabled and move on.
|
||||||
|
*/
|
||||||
|
if (lapicid())
|
||||||
|
turbo_enable();
|
||||||
|
|
||||||
|
/* Dynamic L2 shrink enable and threshold */
|
||||||
|
msr_clrsetbits_64(MSR_PMG_CST_CONFIG_CONTROL, 0x3f000f, 0xe0008),
|
||||||
|
|
||||||
|
/* Disable C1E */
|
||||||
|
msr_clrsetbits_64(MSR_POWER_CTL, 2, 0);
|
||||||
|
msr_setbits_64(MSR_POWER_MISC, 0x44);
|
||||||
|
|
||||||
|
/* Set this core to max frequency ratio */
|
||||||
|
set_max_freq();
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static unsigned bus_freq(void)
|
||||||
|
{
|
||||||
|
msr_t clk_info = msr_read(MSR_BSEL_CR_OVERCLOCK_CONTROL);
|
||||||
|
switch (clk_info.lo & 0x3) {
|
||||||
|
case 0:
|
||||||
|
return 83333333;
|
||||||
|
case 1:
|
||||||
|
return 100000000;
|
||||||
|
case 2:
|
||||||
|
return 133333333;
|
||||||
|
case 3:
|
||||||
|
return 116666666;
|
||||||
|
default:
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static unsigned long tsc_freq(void)
|
||||||
|
{
|
||||||
|
msr_t platform_info;
|
||||||
|
ulong bclk = bus_freq();
|
||||||
|
|
||||||
|
if (!bclk)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
platform_info = msr_read(MSR_PLATFORM_INFO);
|
||||||
|
|
||||||
|
return bclk * ((platform_info.lo >> 8) & 0xff);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int baytrail_get_info(struct udevice *dev, struct cpu_info *info)
|
||||||
|
{
|
||||||
|
info->cpu_freq = tsc_freq();
|
||||||
|
info->features = 1 << CPU_FEAT_L1_CACHE | 1 << CPU_FEAT_MMU;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int cpu_x86_baytrail_bind(struct udevice *dev)
|
||||||
|
{
|
||||||
|
struct cpu_platdata *plat = dev_get_parent_platdata(dev);
|
||||||
|
|
||||||
|
plat->cpu_id = fdtdec_get_int(gd->fdt_blob, dev->of_offset,
|
||||||
|
"intel,apic-id", -1);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static const struct cpu_ops cpu_x86_baytrail_ops = {
|
||||||
|
.get_desc = x86_cpu_get_desc,
|
||||||
|
.get_info = baytrail_get_info,
|
||||||
|
};
|
||||||
|
|
||||||
|
static const struct udevice_id cpu_x86_baytrail_ids[] = {
|
||||||
|
{ .compatible = "intel,baytrail-cpu" },
|
||||||
|
{ }
|
||||||
|
};
|
||||||
|
|
||||||
|
U_BOOT_DRIVER(cpu_x86_baytrail_drv) = {
|
||||||
|
.name = "cpu_x86_baytrail",
|
||||||
|
.id = UCLASS_CPU,
|
||||||
|
.of_match = cpu_x86_baytrail_ids,
|
||||||
|
.bind = cpu_x86_baytrail_bind,
|
||||||
|
.probe = cpu_x86_baytrail_probe,
|
||||||
|
.ops = &cpu_x86_baytrail_ops,
|
||||||
|
};
|
||||||
@ -37,7 +37,6 @@
|
|||||||
#define MSR_MISC_PWR_MGMT 0x1aa
|
#define MSR_MISC_PWR_MGMT 0x1aa
|
||||||
#define MISC_PWR_MGMT_EIST_HW_DIS (1 << 0)
|
#define MISC_PWR_MGMT_EIST_HW_DIS (1 << 0)
|
||||||
#define MSR_TURBO_RATIO_LIMIT 0x1ad
|
#define MSR_TURBO_RATIO_LIMIT 0x1ad
|
||||||
#define MSR_POWER_CTL 0x1fc
|
|
||||||
|
|
||||||
#define MSR_PKGC3_IRTL 0x60a
|
#define MSR_PKGC3_IRTL 0x60a
|
||||||
#define MSR_PKGC6_IRTL 0x60b
|
#define MSR_PKGC6_IRTL 0x60b
|
||||||
@ -63,7 +62,6 @@
|
|||||||
#define MSR_PP1_CURRENT_CONFIG 0x602
|
#define MSR_PP1_CURRENT_CONFIG 0x602
|
||||||
#define PP1_CURRENT_LIMIT_SNB (35 << 3) /* 35 A */
|
#define PP1_CURRENT_LIMIT_SNB (35 << 3) /* 35 A */
|
||||||
#define PP1_CURRENT_LIMIT_IVB (50 << 3) /* 50 A */
|
#define PP1_CURRENT_LIMIT_IVB (50 << 3) /* 50 A */
|
||||||
#define MSR_PKG_POWER_SKU_UNIT 0x606
|
|
||||||
#define MSR_PKG_POWER_SKU 0x614
|
#define MSR_PKG_POWER_SKU 0x614
|
||||||
|
|
||||||
#define IVB_CONFIG_TDP_MIN_CPUID 0x306a2
|
#define IVB_CONFIG_TDP_MIN_CPUID 0x306a2
|
||||||
|
|||||||
@ -53,10 +53,17 @@
|
|||||||
#define SNB_C1_AUTO_UNDEMOTE (1UL << 27)
|
#define SNB_C1_AUTO_UNDEMOTE (1UL << 27)
|
||||||
#define SNB_C3_AUTO_UNDEMOTE (1UL << 28)
|
#define SNB_C3_AUTO_UNDEMOTE (1UL << 28)
|
||||||
|
|
||||||
|
#define MSR_BSEL_CR_OVERCLOCK_CONTROL 0x000000cd
|
||||||
#define MSR_PLATFORM_INFO 0x000000ce
|
#define MSR_PLATFORM_INFO 0x000000ce
|
||||||
|
#define MSR_PMG_CST_CONFIG_CONTROL 0x000000e2
|
||||||
|
#define SINGLE_PCTL (1 << 11)
|
||||||
|
|
||||||
#define MSR_MTRRcap 0x000000fe
|
#define MSR_MTRRcap 0x000000fe
|
||||||
#define MSR_IA32_BBL_CR_CTL 0x00000119
|
#define MSR_IA32_BBL_CR_CTL 0x00000119
|
||||||
#define MSR_IA32_BBL_CR_CTL3 0x0000011e
|
#define MSR_IA32_BBL_CR_CTL3 0x0000011e
|
||||||
|
#define MSR_POWER_MISC 0x00000120
|
||||||
|
#define ENABLE_ULFM_AUTOCM_MASK (1 << 2)
|
||||||
|
#define ENABLE_INDP_AUTOCM_MASK (1 << 3)
|
||||||
|
|
||||||
#define MSR_IA32_SYSENTER_CS 0x00000174
|
#define MSR_IA32_SYSENTER_CS 0x00000174
|
||||||
#define MSR_IA32_SYSENTER_ESP 0x00000175
|
#define MSR_IA32_SYSENTER_ESP 0x00000175
|
||||||
@ -66,6 +73,7 @@
|
|||||||
#define MSR_IA32_MCG_STATUS 0x0000017a
|
#define MSR_IA32_MCG_STATUS 0x0000017a
|
||||||
#define MSR_IA32_MCG_CTL 0x0000017b
|
#define MSR_IA32_MCG_CTL 0x0000017b
|
||||||
|
|
||||||
|
#define MSR_IA32_MISC_ENABLES 0x000001a0
|
||||||
#define MSR_OFFCORE_RSP_0 0x000001a6
|
#define MSR_OFFCORE_RSP_0 0x000001a6
|
||||||
#define MSR_OFFCORE_RSP_1 0x000001a7
|
#define MSR_OFFCORE_RSP_1 0x000001a7
|
||||||
#define MSR_NHM_TURBO_RATIO_LIMIT 0x000001ad
|
#define MSR_NHM_TURBO_RATIO_LIMIT 0x000001ad
|
||||||
@ -73,6 +81,7 @@
|
|||||||
|
|
||||||
#define MSR_LBR_SELECT 0x000001c8
|
#define MSR_LBR_SELECT 0x000001c8
|
||||||
#define MSR_LBR_TOS 0x000001c9
|
#define MSR_LBR_TOS 0x000001c9
|
||||||
|
#define MSR_POWER_CTL 0x000001fc
|
||||||
#define MSR_LBR_NHM_FROM 0x00000680
|
#define MSR_LBR_NHM_FROM 0x00000680
|
||||||
#define MSR_LBR_NHM_TO 0x000006c0
|
#define MSR_LBR_NHM_TO 0x000006c0
|
||||||
#define MSR_LBR_CORE_FROM 0x00000040
|
#define MSR_LBR_CORE_FROM 0x00000040
|
||||||
@ -136,7 +145,7 @@
|
|||||||
|
|
||||||
/* Run Time Average Power Limiting (RAPL) Interface */
|
/* Run Time Average Power Limiting (RAPL) Interface */
|
||||||
|
|
||||||
#define MSR_RAPL_POWER_UNIT 0x00000606
|
#define MSR_PKG_POWER_SKU_UNIT 0x00000606
|
||||||
|
|
||||||
#define MSR_PKG_POWER_LIMIT 0x00000610
|
#define MSR_PKG_POWER_LIMIT 0x00000610
|
||||||
#define MSR_PKG_ENERGY_STATUS 0x00000611
|
#define MSR_PKG_ENERGY_STATUS 0x00000611
|
||||||
@ -158,6 +167,16 @@
|
|||||||
#define MSR_PP1_POLICY 0x00000642
|
#define MSR_PP1_POLICY 0x00000642
|
||||||
|
|
||||||
#define MSR_CORE_C1_RES 0x00000660
|
#define MSR_CORE_C1_RES 0x00000660
|
||||||
|
#define MSR_IACORE_RATIOS 0x0000066a
|
||||||
|
#define MSR_IACORE_TURBO_RATIOS 0x0000066c
|
||||||
|
#define MSR_IACORE_VIDS 0x0000066b
|
||||||
|
#define MSR_IACORE_TURBO_VIDS 0x0000066d
|
||||||
|
#define MSR_PKG_TURBO_CFG1 0x00000670
|
||||||
|
#define MSR_CPU_TURBO_WKLD_CFG1 0x00000671
|
||||||
|
#define MSR_CPU_TURBO_WKLD_CFG2 0x00000672
|
||||||
|
#define MSR_CPU_THERM_CFG1 0x00000673
|
||||||
|
#define MSR_CPU_THERM_CFG2 0x00000674
|
||||||
|
#define MSR_CPU_THERM_SENS_CFG 0x00000675
|
||||||
|
|
||||||
#define MSR_AMD64_MC0_MASK 0xc0010044
|
#define MSR_AMD64_MC0_MASK 0xc0010044
|
||||||
|
|
||||||
@ -348,6 +367,7 @@
|
|||||||
#define MSR_THERM2_CTL_TM_SELECT (1ULL << 16)
|
#define MSR_THERM2_CTL_TM_SELECT (1ULL << 16)
|
||||||
|
|
||||||
#define MSR_IA32_MISC_ENABLE 0x000001a0
|
#define MSR_IA32_MISC_ENABLE 0x000001a0
|
||||||
|
#define H_MISC_DISABLE_TURBO (1 << 6)
|
||||||
|
|
||||||
#define MSR_IA32_TEMPERATURE_TARGET 0x000001a2
|
#define MSR_IA32_TEMPERATURE_TARGET 0x000001a2
|
||||||
|
|
||||||
|
|||||||
@ -12,9 +12,6 @@
|
|||||||
#define CPUID_LEAF_PM 6
|
#define CPUID_LEAF_PM 6
|
||||||
#define PM_CAP_TURBO_MODE (1 << 1)
|
#define PM_CAP_TURBO_MODE (1 << 1)
|
||||||
|
|
||||||
#define MSR_IA32_MISC_ENABLES 0x1a0
|
|
||||||
#define H_MISC_DISABLE_TURBO (1 << 6)
|
|
||||||
|
|
||||||
enum {
|
enum {
|
||||||
TURBO_UNKNOWN,
|
TURBO_UNKNOWN,
|
||||||
TURBO_UNAVAILABLE,
|
TURBO_UNAVAILABLE,
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user