x86: Move common CPU code to its own place
Some of the Intel CPU code is common to several Intel CPUs. Move it into a common location along with required declarations. Signed-off-by: Simon Glass <sjg@chromium.org> Reviewed-by: Bin Meng <bmeng.cn@gmail.com>
This commit is contained in:
parent
8c30b57130
commit
50dd3da004
|
@ -5,6 +5,7 @@
|
||||||
#
|
#
|
||||||
|
|
||||||
obj-$(CONFIG_HAVE_MRC) += car.o
|
obj-$(CONFIG_HAVE_MRC) += car.o
|
||||||
|
obj-y += cpu.o
|
||||||
obj-y += lpc.o
|
obj-y += lpc.o
|
||||||
ifndef CONFIG_TARGET_EFI
|
ifndef CONFIG_TARGET_EFI
|
||||||
obj-y += microcode.o
|
obj-y += microcode.o
|
||||||
|
|
|
@ -0,0 +1,111 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2016 Google, Inc
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: GPL-2.0
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <common.h>
|
||||||
|
#include <dm.h>
|
||||||
|
#include <errno.h>
|
||||||
|
#include <asm/cpu_common.h>
|
||||||
|
#include <asm/intel_regs.h>
|
||||||
|
#include <asm/lapic.h>
|
||||||
|
#include <asm/lpc_common.h>
|
||||||
|
#include <asm/msr.h>
|
||||||
|
#include <asm/mtrr.h>
|
||||||
|
#include <asm/post.h>
|
||||||
|
#include <asm/microcode.h>
|
||||||
|
|
||||||
|
DECLARE_GLOBAL_DATA_PTR;
|
||||||
|
|
||||||
|
static int report_bist_failure(void)
|
||||||
|
{
|
||||||
|
if (gd->arch.bist != 0) {
|
||||||
|
post_code(POST_BIST_FAILURE);
|
||||||
|
printf("BIST failed: %08x\n", gd->arch.bist);
|
||||||
|
return -EFAULT;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int cpu_common_init(void)
|
||||||
|
{
|
||||||
|
struct udevice *dev, *lpc;
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
/* Halt if there was a built in self test failure */
|
||||||
|
ret = report_bist_failure();
|
||||||
|
if (ret)
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
enable_lapic();
|
||||||
|
|
||||||
|
ret = microcode_update_intel();
|
||||||
|
if (ret && ret != -EEXIST)
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
/* Enable upper 128bytes of CMOS */
|
||||||
|
writel(1 << 2, RCB_REG(RC));
|
||||||
|
|
||||||
|
/* Early chipset init required before RAM init can work */
|
||||||
|
uclass_first_device(UCLASS_NORTHBRIDGE, &dev);
|
||||||
|
|
||||||
|
ret = uclass_first_device(UCLASS_LPC, &lpc);
|
||||||
|
if (ret)
|
||||||
|
return ret;
|
||||||
|
if (!lpc)
|
||||||
|
return -ENODEV;
|
||||||
|
|
||||||
|
/* Cause the SATA device to do its early init */
|
||||||
|
uclass_first_device(UCLASS_DISK, &dev);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int cpu_set_flex_ratio_to_tdp_nominal(void)
|
||||||
|
{
|
||||||
|
msr_t flex_ratio, msr;
|
||||||
|
u8 nominal_ratio;
|
||||||
|
|
||||||
|
/* Check for Flex Ratio support */
|
||||||
|
flex_ratio = msr_read(MSR_FLEX_RATIO);
|
||||||
|
if (!(flex_ratio.lo & FLEX_RATIO_EN))
|
||||||
|
return -EINVAL;
|
||||||
|
|
||||||
|
/* Check for >0 configurable TDPs */
|
||||||
|
msr = msr_read(MSR_PLATFORM_INFO);
|
||||||
|
if (((msr.hi >> 1) & 3) == 0)
|
||||||
|
return -EINVAL;
|
||||||
|
|
||||||
|
/* Use nominal TDP ratio for flex ratio */
|
||||||
|
msr = msr_read(MSR_CONFIG_TDP_NOMINAL);
|
||||||
|
nominal_ratio = msr.lo & 0xff;
|
||||||
|
|
||||||
|
/* See if flex ratio is already set to nominal TDP ratio */
|
||||||
|
if (((flex_ratio.lo >> 8) & 0xff) == nominal_ratio)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
/* Set flex ratio to nominal TDP ratio */
|
||||||
|
flex_ratio.lo &= ~0xff00;
|
||||||
|
flex_ratio.lo |= nominal_ratio << 8;
|
||||||
|
flex_ratio.lo |= FLEX_RATIO_LOCK;
|
||||||
|
msr_write(MSR_FLEX_RATIO, flex_ratio);
|
||||||
|
|
||||||
|
/* Set flex ratio in soft reset data register bits 11:6 */
|
||||||
|
clrsetbits_le32(RCB_REG(SOFT_RESET_DATA), 0x3f << 6,
|
||||||
|
(nominal_ratio & 0x3f) << 6);
|
||||||
|
|
||||||
|
debug("CPU: Soft reset to set up flex ratio\n");
|
||||||
|
|
||||||
|
/* Set soft reset control to use register value */
|
||||||
|
setbits_le32(RCB_REG(SOFT_RESET_CTRL), 1);
|
||||||
|
|
||||||
|
/* Issue warm reset, will be "CPU only" due to soft reset data */
|
||||||
|
outb(0x0, PORT_RESET);
|
||||||
|
outb(SYS_RST | RST_CPU, PORT_RESET);
|
||||||
|
cpu_hlt();
|
||||||
|
|
||||||
|
/* Not reached */
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
|
@ -17,6 +17,7 @@
|
||||||
#include <fdtdec.h>
|
#include <fdtdec.h>
|
||||||
#include <pch.h>
|
#include <pch.h>
|
||||||
#include <asm/cpu.h>
|
#include <asm/cpu.h>
|
||||||
|
#include <asm/cpu_common.h>
|
||||||
#include <asm/intel_regs.h>
|
#include <asm/intel_regs.h>
|
||||||
#include <asm/io.h>
|
#include <asm/io.h>
|
||||||
#include <asm/lapic.h>
|
#include <asm/lapic.h>
|
||||||
|
@ -34,51 +35,11 @@ DECLARE_GLOBAL_DATA_PTR;
|
||||||
|
|
||||||
static int set_flex_ratio_to_tdp_nominal(void)
|
static int set_flex_ratio_to_tdp_nominal(void)
|
||||||
{
|
{
|
||||||
msr_t flex_ratio, msr;
|
|
||||||
u8 nominal_ratio;
|
|
||||||
|
|
||||||
/* Minimum CPU revision for configurable TDP support */
|
/* Minimum CPU revision for configurable TDP support */
|
||||||
if (cpuid_eax(1) < IVB_CONFIG_TDP_MIN_CPUID)
|
if (cpuid_eax(1) < IVB_CONFIG_TDP_MIN_CPUID)
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
||||||
/* Check for Flex Ratio support */
|
return cpu_set_flex_ratio_to_tdp_nominal();
|
||||||
flex_ratio = msr_read(MSR_FLEX_RATIO);
|
|
||||||
if (!(flex_ratio.lo & FLEX_RATIO_EN))
|
|
||||||
return -EINVAL;
|
|
||||||
|
|
||||||
/* Check for >0 configurable TDPs */
|
|
||||||
msr = msr_read(MSR_PLATFORM_INFO);
|
|
||||||
if (((msr.hi >> 1) & 3) == 0)
|
|
||||||
return -EINVAL;
|
|
||||||
|
|
||||||
/* Use nominal TDP ratio for flex ratio */
|
|
||||||
msr = msr_read(MSR_CONFIG_TDP_NOMINAL);
|
|
||||||
nominal_ratio = msr.lo & 0xff;
|
|
||||||
|
|
||||||
/* See if flex ratio is already set to nominal TDP ratio */
|
|
||||||
if (((flex_ratio.lo >> 8) & 0xff) == nominal_ratio)
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
/* Set flex ratio to nominal TDP ratio */
|
|
||||||
flex_ratio.lo &= ~0xff00;
|
|
||||||
flex_ratio.lo |= nominal_ratio << 8;
|
|
||||||
flex_ratio.lo |= FLEX_RATIO_LOCK;
|
|
||||||
msr_write(MSR_FLEX_RATIO, flex_ratio);
|
|
||||||
|
|
||||||
/* Set flex ratio in soft reset data register bits 11:6 */
|
|
||||||
clrsetbits_le32(RCB_REG(SOFT_RESET_DATA), 0x3f << 6,
|
|
||||||
(nominal_ratio & 0x3f) << 6);
|
|
||||||
|
|
||||||
/* Set soft reset control to use register value */
|
|
||||||
setbits_le32(RCB_REG(SOFT_RESET_CTRL), 1);
|
|
||||||
|
|
||||||
/* Issue warm reset, will be "CPU only" due to soft reset data */
|
|
||||||
outb(0x0, PORT_RESET);
|
|
||||||
outb(SYS_RST | RST_CPU, PORT_RESET);
|
|
||||||
cpu_hlt();
|
|
||||||
|
|
||||||
/* Not reached */
|
|
||||||
return -EINVAL;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int arch_cpu_init(void)
|
int arch_cpu_init(void)
|
||||||
|
@ -163,17 +124,6 @@ static void enable_usb_bar(struct udevice *bus)
|
||||||
pci_bus_write_config(bus, usb3, PCI_COMMAND, cmd, PCI_SIZE_32);
|
pci_bus_write_config(bus, usb3, PCI_COMMAND, cmd, PCI_SIZE_32);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int report_bist_failure(void)
|
|
||||||
{
|
|
||||||
if (gd->arch.bist != 0) {
|
|
||||||
post_code(POST_BIST_FAILURE);
|
|
||||||
printf("BIST failed: %08x\n", gd->arch.bist);
|
|
||||||
return -EFAULT;
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
int print_cpuinfo(void)
|
int print_cpuinfo(void)
|
||||||
{
|
{
|
||||||
enum pei_boot_mode_t boot_mode = PEI_BOOT_NONE;
|
enum pei_boot_mode_t boot_mode = PEI_BOOT_NONE;
|
||||||
|
@ -184,20 +134,6 @@ int print_cpuinfo(void)
|
||||||
uint16_t pm1_sts;
|
uint16_t pm1_sts;
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
/* Halt if there was a built in self test failure */
|
|
||||||
ret = report_bist_failure();
|
|
||||||
if (ret)
|
|
||||||
return ret;
|
|
||||||
|
|
||||||
enable_lapic();
|
|
||||||
|
|
||||||
ret = microcode_update_intel();
|
|
||||||
if (ret)
|
|
||||||
return ret;
|
|
||||||
|
|
||||||
/* Enable upper 128bytes of CMOS */
|
|
||||||
writel(1 << 2, RCB_REG(RC));
|
|
||||||
|
|
||||||
/* TODO: cmos_post_init() */
|
/* TODO: cmos_post_init() */
|
||||||
if (readl(MCHBAR_REG(SSKPD)) == 0xCAFE) {
|
if (readl(MCHBAR_REG(SSKPD)) == 0xCAFE) {
|
||||||
debug("soft reset detected\n");
|
debug("soft reset detected\n");
|
||||||
|
@ -208,16 +144,10 @@ int print_cpuinfo(void)
|
||||||
reset_cpu(0);
|
reset_cpu(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Early chipset init required before RAM init can work */
|
ret = cpu_common_init();
|
||||||
uclass_first_device(UCLASS_NORTHBRIDGE, &dev);
|
|
||||||
|
|
||||||
ret = uclass_first_device_err(UCLASS_LPC, &lpc);
|
|
||||||
if (ret)
|
if (ret)
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
/* Cause the SATA device to do its early init */
|
|
||||||
uclass_first_device(UCLASS_DISK, &dev);
|
|
||||||
|
|
||||||
/* Check PM1_STS[15] to see if we are waking from Sx */
|
/* Check PM1_STS[15] to see if we are waking from Sx */
|
||||||
pm1_sts = inw(DEFAULT_PMBASE + PM1_STS);
|
pm1_sts = inw(DEFAULT_PMBASE + PM1_STS);
|
||||||
|
|
||||||
|
@ -240,8 +170,10 @@ int print_cpuinfo(void)
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
/* Prepare USB controller early in S3 resume */
|
/* Prepare USB controller early in S3 resume */
|
||||||
if (boot_mode == PEI_BOOT_RESUME)
|
if (boot_mode == PEI_BOOT_RESUME) {
|
||||||
|
uclass_first_device(UCLASS_LPC, &lpc);
|
||||||
enable_usb_bar(pci_get_controller(lpc->parent));
|
enable_usb_bar(pci_get_controller(lpc->parent));
|
||||||
|
}
|
||||||
|
|
||||||
gd->arch.pei_boot_mode = boot_mode;
|
gd->arch.pei_boot_mode = boot_mode;
|
||||||
|
|
||||||
|
|
|
@ -332,8 +332,6 @@
|
||||||
#define SPI_FREQ_SWSEQ 0x3893
|
#define SPI_FREQ_SWSEQ 0x3893
|
||||||
#define SPI_DESC_COMP0 0x38b0
|
#define SPI_DESC_COMP0 0x38b0
|
||||||
#define SPI_FREQ_WR_ERA 0x38b4
|
#define SPI_FREQ_WR_ERA 0x38b4
|
||||||
#define SOFT_RESET_CTRL 0x38f4
|
|
||||||
#define SOFT_RESET_DATA 0x38f8
|
|
||||||
|
|
||||||
#define DIR_ROUTE(a, b, c, d) \
|
#define DIR_ROUTE(a, b, c, d) \
|
||||||
(((d) << DIR_IDR) | ((c) << DIR_ICR) | \
|
(((d) << DIR_IDR) | ((c) << DIR_ICR) | \
|
||||||
|
|
|
@ -0,0 +1,35 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2016 Google, Inc
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: GPL-2.0
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __ASM_CPU_COMMON_H
|
||||||
|
#define __ASM_CPU_COMMON_H
|
||||||
|
|
||||||
|
#define IA32_PERF_CTL 0x199
|
||||||
|
|
||||||
|
/**
|
||||||
|
* cpu_common_init() - Set up common CPU init
|
||||||
|
*
|
||||||
|
* This reports BIST failure, enables the LAPIC, updates microcode, enables
|
||||||
|
* the upper 128-bytes of CROM RAM, probes the northbridge, PCH, LPC and SATA.
|
||||||
|
*
|
||||||
|
* @return 0 if OK, -ve on error
|
||||||
|
*/
|
||||||
|
int cpu_common_init(void);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* cpu_set_flex_ratio_to_tdp_nominal() - Set up the maximum non-turbo rate
|
||||||
|
*
|
||||||
|
* If a change is needed, this function will do a soft reset so it takes
|
||||||
|
* effect.
|
||||||
|
*
|
||||||
|
* Some details are available here:
|
||||||
|
* http://forum.hwbot.org/showthread.php?t=76092
|
||||||
|
*
|
||||||
|
* @return 0 if OK, -ve on error
|
||||||
|
*/
|
||||||
|
int cpu_set_flex_ratio_to_tdp_nominal(void);
|
||||||
|
|
||||||
|
#endif
|
|
@ -12,8 +12,17 @@
|
||||||
#define MCH_BASE_SIZE 0x8000
|
#define MCH_BASE_SIZE 0x8000
|
||||||
#define MCHBAR_REG(reg) (MCH_BASE_ADDRESS + (reg))
|
#define MCHBAR_REG(reg) (MCH_BASE_ADDRESS + (reg))
|
||||||
|
|
||||||
|
#define MCHBAR_PEI_VERSION 0x5034
|
||||||
|
#define MCH_PKG_POWER_LIMIT_LO 0x59a0
|
||||||
|
#define MCH_PKG_POWER_LIMIT_HI 0x59a4
|
||||||
|
#define MCH_DDR_POWER_LIMIT_LO 0x58e0
|
||||||
|
#define MCH_DDR_POWER_LIMIT_HI 0x58e4
|
||||||
|
|
||||||
/* Access the Root Complex Register Block */
|
/* Access the Root Complex Register Block */
|
||||||
#define RCB_BASE_ADDRESS 0xfed1c000
|
#define RCB_BASE_ADDRESS 0xfed1c000
|
||||||
#define RCB_REG(reg) (RCB_BASE_ADDRESS + (reg))
|
#define RCB_REG(reg) (RCB_BASE_ADDRESS + (reg))
|
||||||
|
|
||||||
|
#define SOFT_RESET_CTRL 0x38f4
|
||||||
|
#define SOFT_RESET_DATA 0x38f8
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
Loading…
Reference in New Issue