mirror of
https://github.com/AsahiLinux/u-boot
synced 2024-11-24 21:54:01 +00:00
x86: apl: Add core init for the SoC
Set up MSRs required for Apollo Lake. This enables Linux to use the timers correctly. Also write the fixed MSRs for this platform. Signed-off-by: Simon Glass <sjg@chromium.org> Reviewed-by: Bin Meng <bmeng.cn@gmail.com>
This commit is contained in:
parent
1779b8a96a
commit
6571d87315
7 changed files with 170 additions and 21 deletions
|
@ -13,6 +13,9 @@
|
|||
#include <asm/cpu_x86.h>
|
||||
#include <asm/intel_acpi.h>
|
||||
#include <asm/msr.h>
|
||||
#include <asm/mtrr.h>
|
||||
#include <asm/arch/cpu.h>
|
||||
#include <asm/arch/iomap.h>
|
||||
#include <dm/acpi.h>
|
||||
|
||||
#define CSTATE_RES(address_space, width, offset, address) \
|
||||
|
@ -86,6 +89,86 @@ static int acpi_cpu_fill_ssdt(const struct udevice *dev, struct acpi_ctx *ctx)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static void update_fixed_mtrrs(void)
|
||||
{
|
||||
native_write_msr(MTRR_FIX_64K_00000_MSR,
|
||||
MTRR_FIX_TYPE(MTRR_TYPE_WRBACK),
|
||||
MTRR_FIX_TYPE(MTRR_TYPE_WRBACK));
|
||||
native_write_msr(MTRR_FIX_16K_80000_MSR,
|
||||
MTRR_FIX_TYPE(MTRR_TYPE_WRBACK),
|
||||
MTRR_FIX_TYPE(MTRR_TYPE_WRBACK));
|
||||
native_write_msr(MTRR_FIX_4K_E0000_MSR,
|
||||
MTRR_FIX_TYPE(MTRR_TYPE_WRBACK),
|
||||
MTRR_FIX_TYPE(MTRR_TYPE_WRBACK));
|
||||
native_write_msr(MTRR_FIX_4K_E8000_MSR,
|
||||
MTRR_FIX_TYPE(MTRR_TYPE_WRBACK),
|
||||
MTRR_FIX_TYPE(MTRR_TYPE_WRBACK));
|
||||
native_write_msr(MTRR_FIX_4K_F0000_MSR,
|
||||
MTRR_FIX_TYPE(MTRR_TYPE_WRBACK),
|
||||
MTRR_FIX_TYPE(MTRR_TYPE_WRBACK));
|
||||
native_write_msr(MTRR_FIX_4K_F8000_MSR,
|
||||
MTRR_FIX_TYPE(MTRR_TYPE_WRBACK),
|
||||
MTRR_FIX_TYPE(MTRR_TYPE_WRBACK));
|
||||
}
|
||||
|
||||
static void setup_core_msrs(void)
|
||||
{
|
||||
wrmsrl(MSR_PMG_CST_CONFIG_CONTROL,
|
||||
PKG_C_STATE_LIMIT_C2_MASK | CORE_C_STATE_LIMIT_C10_MASK |
|
||||
IO_MWAIT_REDIRECT_MASK | CST_CFG_LOCK_MASK);
|
||||
/* Power Management I/O base address for I/O trapping to C-states */
|
||||
wrmsrl(MSR_PMG_IO_CAPTURE_ADR, ACPI_PMIO_CST_REG |
|
||||
(PMG_IO_BASE_CST_RNG_BLK_SIZE << 16));
|
||||
/* Disable C1E */
|
||||
msr_clrsetbits_64(MSR_POWER_CTL, 0x2, 0);
|
||||
/* Disable support for MONITOR and MWAIT instructions */
|
||||
msr_clrsetbits_64(MSR_IA32_MISC_ENABLE, MISC_ENABLE_MWAIT, 0);
|
||||
/*
|
||||
* Enable and Lock the Advanced Encryption Standard (AES-NI)
|
||||
* feature register
|
||||
*/
|
||||
msr_clrsetbits_64(MSR_FEATURE_CONFIG, FEATURE_CONFIG_RESERVED_MASK,
|
||||
FEATURE_CONFIG_LOCK);
|
||||
|
||||
update_fixed_mtrrs();
|
||||
}
|
||||
|
||||
static int soc_core_init(void)
|
||||
{
|
||||
struct udevice *pmc;
|
||||
int ret;
|
||||
|
||||
/* Clear out pending MCEs */
|
||||
cpu_mca_configure();
|
||||
|
||||
/* Set core MSRs */
|
||||
setup_core_msrs();
|
||||
/*
|
||||
* Enable ACPI PM timer emulation, which also lets microcode know
|
||||
* location of ACPI_BASE_ADDRESS. This also enables other features
|
||||
* implemented in microcode.
|
||||
*/
|
||||
ret = uclass_first_device_err(UCLASS_ACPI_PMC, &pmc);
|
||||
if (ret)
|
||||
return log_msg_ret("PMC", ret);
|
||||
enable_pm_timer_emulation(pmc);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int cpu_apl_probe(struct udevice *dev)
|
||||
{
|
||||
if (gd->flags & GD_FLG_RELOC) {
|
||||
int ret;
|
||||
|
||||
ret = soc_core_init();
|
||||
if (ret)
|
||||
return log_ret(ret);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
struct acpi_ops apl_cpu_acpi_ops = {
|
||||
.fill_ssdt = acpi_cpu_fill_ssdt,
|
||||
};
|
||||
|
@ -107,6 +190,7 @@ U_BOOT_DRIVER(intel_apl_cpu) = {
|
|||
.id = UCLASS_CPU,
|
||||
.of_match = cpu_x86_apl_ids,
|
||||
.bind = cpu_x86_bind,
|
||||
.probe = cpu_apl_probe,
|
||||
.ops = &cpu_x86_apl_ops,
|
||||
ACPI_OPS_PTR(&apl_cpu_acpi_ops)
|
||||
.flags = DM_FLAG_PRE_RELOC,
|
||||
|
|
|
@ -4,8 +4,13 @@
|
|||
*/
|
||||
|
||||
#include <common.h>
|
||||
#include <dm.h>
|
||||
#include <log.h>
|
||||
#include <asm/cpu_common.h>
|
||||
#include <asm/msr.h>
|
||||
#include <asm/arch/cpu.h>
|
||||
#include <asm/arch/iomap.h>
|
||||
#include <power/acpi_pmc.h>
|
||||
|
||||
void cpu_flush_l1d_to_l2(void)
|
||||
{
|
||||
|
@ -15,3 +20,23 @@ void cpu_flush_l1d_to_l2(void)
|
|||
msr.lo |= FLUSH_DL1_L2;
|
||||
msr_write(MSR_POWER_MISC, msr);
|
||||
}
|
||||
|
||||
void enable_pm_timer_emulation(const struct udevice *pmc)
|
||||
{
|
||||
struct acpi_pmc_upriv *upriv = dev_get_uclass_priv(pmc);
|
||||
msr_t msr;
|
||||
|
||||
/*
|
||||
* The derived frequency is calculated as follows:
|
||||
* (CTC_FREQ * msr[63:32]) >> 32 = target frequency.
|
||||
*
|
||||
* Back-solve the multiplier so the 3.579545MHz ACPI timer frequency is
|
||||
* used.
|
||||
*/
|
||||
msr.hi = (3579545ULL << 32) / CTC_FREQ;
|
||||
|
||||
/* Set PM1 timer IO port and enable */
|
||||
msr.lo = EMULATE_PM_TMR_EN | (upriv->acpi_base + R_ACPI_PM1_TMR);
|
||||
debug("PM timer %x %x\n", msr.hi, msr.lo);
|
||||
msr_write(MSR_EMULATE_PM_TIMER, msr);
|
||||
}
|
||||
|
|
|
@ -114,26 +114,6 @@ static int fast_spi_cache_bios_region(void)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static void enable_pm_timer_emulation(struct udevice *pmc)
|
||||
{
|
||||
struct acpi_pmc_upriv *upriv = dev_get_uclass_priv(pmc);
|
||||
msr_t msr;
|
||||
|
||||
/*
|
||||
* The derived frequency is calculated as follows:
|
||||
* (CTC_FREQ * msr[63:32]) >> 32 = target frequency.
|
||||
*
|
||||
* Back-solve the multiplier so the 3.579545MHz ACPI timer frequency is
|
||||
* used.
|
||||
*/
|
||||
msr.hi = (3579545ULL << 32) / CTC_FREQ;
|
||||
|
||||
/* Set PM1 timer IO port and enable */
|
||||
msr.lo = EMULATE_PM_TMR_EN | (upriv->acpi_base + R_ACPI_PM1_TMR);
|
||||
debug("PM timer %x %x\n", msr.hi, msr.lo);
|
||||
msr_write(MSR_EMULATE_PM_TIMER, msr);
|
||||
}
|
||||
|
||||
static void google_chromeec_ioport_range(uint *out_basep, uint *out_sizep)
|
||||
{
|
||||
uint base;
|
||||
|
|
|
@ -306,3 +306,22 @@ int cpu_get_cores_per_package(void)
|
|||
|
||||
return cores;
|
||||
}
|
||||
|
||||
void cpu_mca_configure(void)
|
||||
{
|
||||
msr_t msr;
|
||||
int i;
|
||||
int num_banks;
|
||||
|
||||
msr = msr_read(MSR_IA32_MCG_CAP);
|
||||
num_banks = msr.lo & 0xff;
|
||||
msr.lo = 0;
|
||||
msr.hi = 0;
|
||||
for (i = 0; i < num_banks; i++) {
|
||||
/* Clear the machine check status */
|
||||
msr_write(MSR_IA32_MC0_STATUS + (i * 4), msr);
|
||||
/* Initialise machine checks */
|
||||
msr_write(MSR_IA32_MC0_CTL + i * 4,
|
||||
(msr_t) {.lo = 0xffffffff, .hi = 0xffffffff});
|
||||
}
|
||||
}
|
||||
|
|
|
@ -15,6 +15,20 @@
|
|||
#ifndef __ASSEMBLY__
|
||||
/* Flush L1D to L2 */
|
||||
void cpu_flush_l1d_to_l2(void);
|
||||
|
||||
/**
|
||||
* Enable emulation of the PM timer
|
||||
*
|
||||
* Some legacy OSes cannot tolerate the ACPI timer stoping during idle states,
|
||||
* and this results in higher power consumption. ACPI timer emulation allows
|
||||
* disabling of the ACPI Timer (PM1_TMR) to have no impact on the system, with
|
||||
* the exception that TMR_STS will not be set on an overflow condition. All
|
||||
* aligned 32-bit reads from the ACPI Timer port are valid and will behave as if
|
||||
* the ACPI timer remains enabled.
|
||||
*
|
||||
* @pmc: PMC device
|
||||
*/
|
||||
void enable_pm_timer_emulation(const struct udevice *pmc);
|
||||
#endif
|
||||
|
||||
#endif /* _ASM_ARCH_CPU_H */
|
||||
|
|
|
@ -184,4 +184,13 @@ int cpu_get_max_turbo_ratio(void);
|
|||
*/
|
||||
int cpu_get_cores_per_package(void);
|
||||
|
||||
/**
|
||||
* cpu_mca_configure() - Set up machine-check exceptions ready for use
|
||||
*
|
||||
* These allow the SoC to report errors while running. See here for details:
|
||||
*
|
||||
* https://www.intel.com/content/dam/www/public/us/en/documents/white-papers/machine-check-exceptions-debug-paper.pdf
|
||||
*/
|
||||
void cpu_mca_configure(void);
|
||||
|
||||
#endif
|
||||
|
|
|
@ -68,7 +68,18 @@
|
|||
#define MSR_BSEL_CR_OVERCLOCK_CONTROL 0x000000cd
|
||||
#define MSR_PLATFORM_INFO 0x000000ce
|
||||
#define MSR_PMG_CST_CONFIG_CONTROL 0x000000e2
|
||||
#define SINGLE_PCTL (1 << 11)
|
||||
/* Set MSR_PMG_CST_CONFIG_CONTROL[3:0] for Package C-State limit */
|
||||
#define PKG_C_STATE_LIMIT_C2_MASK BIT(1)
|
||||
/* Set MSR_PMG_CST_CONFIG_CONTROL[7:4] for Core C-State limit*/
|
||||
#define CORE_C_STATE_LIMIT_C10_MASK 0x70
|
||||
/* Set MSR_PMG_CST_CONFIG_CONTROL[10] to IO redirect to MWAIT */
|
||||
#define IO_MWAIT_REDIRECT_MASK BIT(10)
|
||||
/* Set MSR_PMG_CST_CONFIG_CONTROL[15] to lock CST_CFG [0-15] bits */
|
||||
#define CST_CFG_LOCK_MASK BIT(15)
|
||||
#define SINGLE_PCTL BIT(11)
|
||||
|
||||
/* ACPI PMIO Offset to C-state register */
|
||||
#define ACPI_PMIO_CST_REG (ACPI_BASE_ADDRESS + 0x14)
|
||||
|
||||
#define MSR_MTRRcap 0x000000fe
|
||||
#define MSR_IA32_BBL_CR_CTL 0x00000119
|
||||
|
@ -83,6 +94,10 @@
|
|||
#define EMULATE_PM_TMR_EN (1 << 16)
|
||||
#define EMULATE_DELAY_VALUE 0x13
|
||||
|
||||
#define MSR_FEATURE_CONFIG 0x13c
|
||||
#define FEATURE_CONFIG_RESERVED_MASK 0x3ULL
|
||||
#define FEATURE_CONFIG_LOCK (1 << 0)
|
||||
|
||||
#define MSR_IA32_SYSENTER_CS 0x00000174
|
||||
#define MSR_IA32_SYSENTER_ESP 0x00000175
|
||||
#define MSR_IA32_SYSENTER_EIP 0x00000176
|
||||
|
@ -453,6 +468,9 @@
|
|||
#define MSR_AMD_PERF_CTL 0xc0010062
|
||||
|
||||
#define MSR_PMG_CST_CONFIG_CTL 0x000000e2
|
||||
/* CST Range (R/W) IO port block size */
|
||||
#define PMG_IO_BASE_CST_RNG_BLK_SIZE 0x5
|
||||
|
||||
#define MSR_PMG_IO_CAPTURE_ADR 0x000000e4
|
||||
#define MSR_IA32_MPERF 0x000000e7
|
||||
#define MSR_IA32_APERF 0x000000e8
|
||||
|
|
Loading…
Reference in a new issue