mirror of
https://github.com/u-boot/u-boot.git
synced 2024-11-30 16:13:27 +08:00
Merge git://git.denx.de/u-boot-x86
- Allow x86 boards to use TPL, SPL and U-Boot proper - Update sysreset x86 driver to utilize ACPI registers to do power off - Add a new chromebook_samus_tpl board for TPL support - Several minor changes in binman tool
This commit is contained in:
commit
8c66fb88e3
1
Makefile
1
Makefile
@ -1380,6 +1380,7 @@ cmd_ldr = $(LD) $(LDFLAGS_$(@F)) \
|
||||
|
||||
u-boot.rom: u-boot-x86-16bit.bin u-boot.bin \
|
||||
$(if $(CONFIG_SPL_X86_16BIT_INIT),spl/u-boot-spl.bin) \
|
||||
$(if $(CONFIG_TPL_X86_16BIT_INIT),tpl/u-boot-tpl.bin) \
|
||||
$(if $(CONFIG_HAVE_REFCODE),refcode.bin) FORCE
|
||||
$(call if_changed,binman)
|
||||
|
||||
|
32
arch/Kconfig
32
arch/Kconfig
@ -126,6 +126,8 @@ config SH
|
||||
|
||||
config X86
|
||||
bool "x86 architecture"
|
||||
select SUPPORT_SPL
|
||||
select SUPPORT_TPL
|
||||
select CREATE_ARCH_SYMLINK
|
||||
select DM
|
||||
select DM_PCI
|
||||
@ -163,6 +165,36 @@ config X86
|
||||
imply USB_ETHER_SMSC95XX
|
||||
imply USB_HOST_ETHER
|
||||
imply PCH
|
||||
imply RTC_MC146818
|
||||
|
||||
# Thing to enable for when SPL/TPL are enabled: SPL
|
||||
imply SPL_DM
|
||||
imply SPL_OF_LIBFDT
|
||||
imply SPL_DRIVERS_MISC_SUPPORT
|
||||
imply SPL_GPIO_SUPPORT
|
||||
imply SPL_LIBCOMMON_SUPPORT
|
||||
imply SPL_LIBGENERIC_SUPPORT
|
||||
imply SPL_SERIAL_SUPPORT
|
||||
imply SPL_SPI_FLASH_SUPPORT
|
||||
imply SPL_SPI_SUPPORT
|
||||
imply SPL_OF_CONTROL
|
||||
imply SPL_TIMER
|
||||
imply SPL_REGMAP
|
||||
imply SPL_SYSCON
|
||||
# TPL
|
||||
imply TPL_DM
|
||||
imply TPL_OF_LIBFDT
|
||||
imply TPL_DRIVERS_MISC_SUPPORT
|
||||
imply TPL_GPIO_SUPPORT
|
||||
imply TPL_LIBCOMMON_SUPPORT
|
||||
imply TPL_LIBGENERIC_SUPPORT
|
||||
imply TPL_SERIAL_SUPPORT
|
||||
imply TPL_SPI_FLASH_SUPPORT
|
||||
imply TPL_SPI_SUPPORT
|
||||
imply TPL_OF_CONTROL
|
||||
imply TPL_TIMER
|
||||
imply TPL_REGMAP
|
||||
imply TPL_SYSCON
|
||||
|
||||
config XTENSA
|
||||
bool "Xtensa architecture"
|
||||
|
@ -32,7 +32,6 @@ config X86_RUN_32BIT
|
||||
config X86_RUN_64BIT
|
||||
bool "64-bit"
|
||||
select X86_64
|
||||
select SUPPORT_SPL
|
||||
select SPL
|
||||
select SPL_SEPARATE_BSS
|
||||
help
|
||||
@ -177,10 +176,17 @@ config X86_16BIT_INIT
|
||||
config SPL_X86_16BIT_INIT
|
||||
bool
|
||||
depends on X86_RESET_VECTOR
|
||||
default y if X86_RESET_VECTOR && SPL
|
||||
default y if X86_RESET_VECTOR && SPL && !TPL
|
||||
help
|
||||
This is enabled when 16-bit init is in SPL
|
||||
|
||||
config TPL_X86_16BIT_INIT
|
||||
bool
|
||||
depends on X86_RESET_VECTOR
|
||||
default y if X86_RESET_VECTOR && TPL
|
||||
help
|
||||
This is enabled when 16-bit init is in TPL
|
||||
|
||||
config X86_32BIT_INIT
|
||||
bool
|
||||
depends on X86_RESET_VECTOR
|
||||
|
@ -4,12 +4,24 @@ ifeq ($(CONFIG_EFI_APP),)
|
||||
ifdef CONFIG_$(SPL_)X86_64
|
||||
head-y := arch/x86/cpu/start64.o
|
||||
else
|
||||
ifeq ($(CONFIG_$(SPL_TPL_)X86_16BIT_INIT),y)
|
||||
head-y := arch/x86/cpu/start.o
|
||||
else
|
||||
ifndef CONFIG_SPL
|
||||
head-y := arch/x86/cpu/start.o
|
||||
else
|
||||
ifdef CONFIG_SPL_BUILD
|
||||
head-y = arch/x86/cpu/start_from_tpl.o
|
||||
else
|
||||
head-y = arch/x86/cpu/start_from_spl.o
|
||||
endif
|
||||
endif
|
||||
endif
|
||||
endif
|
||||
endif # EFI
|
||||
|
||||
head-$(CONFIG_$(SPL_)X86_16BIT_INIT) += arch/x86/cpu/start16.o
|
||||
head-$(CONFIG_$(SPL_)X86_16BIT_INIT) += arch/x86/cpu/resetvec.o
|
||||
head-$(CONFIG_$(SPL_TPL_)X86_16BIT_INIT) += arch/x86/cpu/start16.o
|
||||
head-$(CONFIG_$(SPL_TPL_)X86_16BIT_INIT) += arch/x86/cpu/resetvec.o
|
||||
|
||||
libs-y += arch/x86/cpu/
|
||||
libs-y += arch/x86/lib/
|
||||
|
@ -9,9 +9,22 @@
|
||||
ifeq ($(CONFIG_$(SPL_)X86_64),y)
|
||||
extra-y = start64.o
|
||||
else
|
||||
ifeq ($(CONFIG_$(SPL_TPL_)X86_16BIT_INIT),y)
|
||||
extra-y = start.o
|
||||
else
|
||||
ifndef CONFIG_SPL
|
||||
extra-y = start.o
|
||||
else
|
||||
ifdef CONFIG_SPL_BUILD
|
||||
extra-y = start_from_tpl.o
|
||||
else
|
||||
extra-y = start_from_spl.o
|
||||
endif
|
||||
extra-$(CONFIG_$(SPL_)X86_16BIT_INIT) += resetvec.o start16.o
|
||||
endif
|
||||
endif
|
||||
endif
|
||||
|
||||
extra-$(CONFIG_$(SPL_TPL_)X86_16BIT_INIT) += resetvec.o start16.o
|
||||
|
||||
obj-y += cpu.o cpu_x86.o
|
||||
|
||||
|
@ -3,7 +3,24 @@
|
||||
# Copyright (c) 2016 Google, Inc
|
||||
|
||||
obj-y += adsp.o
|
||||
obj-y += cpu.o
|
||||
obj-$(CONFIG_$(SPL_TPL_)X86_16BIT_INIT) += cpu.o
|
||||
obj-$(CONFIG_$(SPL_TPL_)X86_32BIT_INIT) += cpu_full.o
|
||||
|
||||
ifdef CONFIG_SPL
|
||||
ifndef CONFIG_SPL_BUILD
|
||||
obj-y += cpu_from_spl.o
|
||||
obj-y += cpu_full.o
|
||||
obj-y += refcode.o
|
||||
endif
|
||||
ifndef CONFIG_SPL_BUILD
|
||||
# obj-y += cpu_from_spl.o
|
||||
endif
|
||||
endif
|
||||
|
||||
ifeq ($(CONFIG_$(SPL_TPL_)X86_32BIT_INIT),)
|
||||
#obj-y += cpu_from_spl.o
|
||||
endif
|
||||
|
||||
obj-y += iobp.o
|
||||
obj-y += lpc.o
|
||||
obj-y += me.o
|
||||
@ -11,6 +28,6 @@ obj-y += northbridge.o
|
||||
obj-y += pch.o
|
||||
obj-y += pinctrl_broadwell.o
|
||||
obj-y += power_state.o
|
||||
obj-y += refcode.o
|
||||
obj-$(CONFIG_$(SPL_TPL_)X86_32BIT_INIT) += refcode.o
|
||||
obj-y += sata.o
|
||||
obj-y += sdram.o
|
||||
obj-$(CONFIG_$(SPL_TPL_)X86_32BIT_INIT) += sdram.o
|
||||
|
@ -12,75 +12,15 @@
|
||||
#include <asm/cpu_x86.h>
|
||||
#include <asm/cpu_common.h>
|
||||
#include <asm/intel_regs.h>
|
||||
#include <asm/lpc_common.h>
|
||||
#include <asm/msr.h>
|
||||
#include <asm/pci.h>
|
||||
#include <asm/post.h>
|
||||
#include <asm/turbo.h>
|
||||
#include <asm/arch/cpu.h>
|
||||
#include <asm/arch/pch.h>
|
||||
#include <asm/arch/rcb.h>
|
||||
|
||||
struct cpu_broadwell_priv {
|
||||
bool ht_disabled;
|
||||
};
|
||||
|
||||
/* Convert time in seconds to POWER_LIMIT_1_TIME MSR value */
|
||||
static const u8 power_limit_time_sec_to_msr[] = {
|
||||
[0] = 0x00,
|
||||
[1] = 0x0a,
|
||||
[2] = 0x0b,
|
||||
[3] = 0x4b,
|
||||
[4] = 0x0c,
|
||||
[5] = 0x2c,
|
||||
[6] = 0x4c,
|
||||
[7] = 0x6c,
|
||||
[8] = 0x0d,
|
||||
[10] = 0x2d,
|
||||
[12] = 0x4d,
|
||||
[14] = 0x6d,
|
||||
[16] = 0x0e,
|
||||
[20] = 0x2e,
|
||||
[24] = 0x4e,
|
||||
[28] = 0x6e,
|
||||
[32] = 0x0f,
|
||||
[40] = 0x2f,
|
||||
[48] = 0x4f,
|
||||
[56] = 0x6f,
|
||||
[64] = 0x10,
|
||||
[80] = 0x30,
|
||||
[96] = 0x50,
|
||||
[112] = 0x70,
|
||||
[128] = 0x11,
|
||||
};
|
||||
|
||||
/* Convert POWER_LIMIT_1_TIME MSR value to seconds */
|
||||
static const u8 power_limit_time_msr_to_sec[] = {
|
||||
[0x00] = 0,
|
||||
[0x0a] = 1,
|
||||
[0x0b] = 2,
|
||||
[0x4b] = 3,
|
||||
[0x0c] = 4,
|
||||
[0x2c] = 5,
|
||||
[0x4c] = 6,
|
||||
[0x6c] = 7,
|
||||
[0x0d] = 8,
|
||||
[0x2d] = 10,
|
||||
[0x4d] = 12,
|
||||
[0x6d] = 14,
|
||||
[0x0e] = 16,
|
||||
[0x2e] = 20,
|
||||
[0x4e] = 24,
|
||||
[0x6e] = 28,
|
||||
[0x0f] = 32,
|
||||
[0x2f] = 40,
|
||||
[0x4f] = 48,
|
||||
[0x6f] = 56,
|
||||
[0x10] = 64,
|
||||
[0x30] = 80,
|
||||
[0x50] = 96,
|
||||
[0x70] = 112,
|
||||
[0x11] = 128,
|
||||
};
|
||||
|
||||
int arch_cpu_init_dm(void)
|
||||
{
|
||||
struct udevice *dev;
|
||||
@ -156,613 +96,13 @@ int print_cpuinfo(void)
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* The core 100MHz BLCK is disabled in deeper c-states. One needs to calibrate
|
||||
* the 100MHz BCLCK against the 24MHz BLCK to restore the clocks properly
|
||||
* when a core is woken up
|
||||
*/
|
||||
static int pcode_ready(void)
|
||||
void board_debug_uart_init(void)
|
||||
{
|
||||
int wait_count;
|
||||
const int delay_step = 10;
|
||||
struct udevice *bus = NULL;
|
||||
|
||||
wait_count = 0;
|
||||
do {
|
||||
if (!(readl(MCHBAR_REG(BIOS_MAILBOX_INTERFACE)) &
|
||||
MAILBOX_RUN_BUSY))
|
||||
return 0;
|
||||
wait_count += delay_step;
|
||||
udelay(delay_step);
|
||||
} while (wait_count < 1000);
|
||||
/* com1 / com2 decode range */
|
||||
pci_x86_write_config(bus, PCH_DEV_LPC, LPC_IO_DEC, 1 << 4, PCI_SIZE_16);
|
||||
|
||||
return -ETIMEDOUT;
|
||||
pci_x86_write_config(bus, PCH_DEV_LPC, LPC_EN, COMA_LPC_EN,
|
||||
PCI_SIZE_16);
|
||||
}
|
||||
|
||||
static u32 pcode_mailbox_read(u32 command)
|
||||
{
|
||||
int ret;
|
||||
|
||||
ret = pcode_ready();
|
||||
if (ret) {
|
||||
debug("PCODE: mailbox timeout on wait ready\n");
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Send command and start transaction */
|
||||
writel(command | MAILBOX_RUN_BUSY, MCHBAR_REG(BIOS_MAILBOX_INTERFACE));
|
||||
|
||||
ret = pcode_ready();
|
||||
if (ret) {
|
||||
debug("PCODE: mailbox timeout on completion\n");
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Read mailbox */
|
||||
return readl(MCHBAR_REG(BIOS_MAILBOX_DATA));
|
||||
}
|
||||
|
||||
static int pcode_mailbox_write(u32 command, u32 data)
|
||||
{
|
||||
int ret;
|
||||
|
||||
ret = pcode_ready();
|
||||
if (ret) {
|
||||
debug("PCODE: mailbox timeout on wait ready\n");
|
||||
return ret;
|
||||
}
|
||||
|
||||
writel(data, MCHBAR_REG(BIOS_MAILBOX_DATA));
|
||||
|
||||
/* Send command and start transaction */
|
||||
writel(command | MAILBOX_RUN_BUSY, MCHBAR_REG(BIOS_MAILBOX_INTERFACE));
|
||||
|
||||
ret = pcode_ready();
|
||||
if (ret) {
|
||||
debug("PCODE: mailbox timeout on completion\n");
|
||||
return ret;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* @dev is the CPU device */
|
||||
static void initialize_vr_config(struct udevice *dev)
|
||||
{
|
||||
int ramp, min_vid;
|
||||
msr_t msr;
|
||||
|
||||
debug("Initializing VR config\n");
|
||||
|
||||
/* Configure VR_CURRENT_CONFIG */
|
||||
msr = msr_read(MSR_VR_CURRENT_CONFIG);
|
||||
/*
|
||||
* Preserve bits 63 and 62. Bit 62 is PSI4 enable, but it is only valid
|
||||
* on ULT systems
|
||||
*/
|
||||
msr.hi &= 0xc0000000;
|
||||
msr.hi |= (0x01 << (52 - 32)); /* PSI3 threshold - 1A */
|
||||
msr.hi |= (0x05 << (42 - 32)); /* PSI2 threshold - 5A */
|
||||
msr.hi |= (0x14 << (32 - 32)); /* PSI1 threshold - 20A */
|
||||
msr.hi |= (1 << (62 - 32)); /* Enable PSI4 */
|
||||
/* Leave the max instantaneous current limit (12:0) to default */
|
||||
msr_write(MSR_VR_CURRENT_CONFIG, msr);
|
||||
|
||||
/* Configure VR_MISC_CONFIG MSR */
|
||||
msr = msr_read(MSR_VR_MISC_CONFIG);
|
||||
/* Set the IOUT_SLOPE scalar applied to dIout in U10.1.9 format */
|
||||
msr.hi &= ~(0x3ff << (40 - 32));
|
||||
msr.hi |= (0x200 << (40 - 32)); /* 1.0 */
|
||||
/* Set IOUT_OFFSET to 0 */
|
||||
msr.hi &= ~0xff;
|
||||
/* Set entry ramp rate to slow */
|
||||
msr.hi &= ~(1 << (51 - 32));
|
||||
/* Enable decay mode on C-state entry */
|
||||
msr.hi |= (1 << (52 - 32));
|
||||
/* Set the slow ramp rate */
|
||||
msr.hi &= ~(0x3 << (53 - 32));
|
||||
/* Configure the C-state exit ramp rate */
|
||||
ramp = fdtdec_get_int(gd->fdt_blob, dev_of_offset(dev),
|
||||
"intel,slow-ramp", -1);
|
||||
if (ramp != -1) {
|
||||
/* Configured slow ramp rate */
|
||||
msr.hi |= ((ramp & 0x3) << (53 - 32));
|
||||
/* Set exit ramp rate to slow */
|
||||
msr.hi &= ~(1 << (50 - 32));
|
||||
} else {
|
||||
/* Fast ramp rate / 4 */
|
||||
msr.hi |= (0x01 << (53 - 32));
|
||||
/* Set exit ramp rate to fast */
|
||||
msr.hi |= (1 << (50 - 32));
|
||||
}
|
||||
/* Set MIN_VID (31:24) to allow CPU to have full control */
|
||||
msr.lo &= ~0xff000000;
|
||||
min_vid = fdtdec_get_int(gd->fdt_blob, dev_of_offset(dev),
|
||||
"intel,min-vid", 0);
|
||||
msr.lo |= (min_vid & 0xff) << 24;
|
||||
msr_write(MSR_VR_MISC_CONFIG, msr);
|
||||
|
||||
/* Configure VR_MISC_CONFIG2 MSR */
|
||||
msr = msr_read(MSR_VR_MISC_CONFIG2);
|
||||
msr.lo &= ~0xffff;
|
||||
/*
|
||||
* Allow CPU to control minimum voltage completely (15:8) and
|
||||
* set the fast ramp voltage in 10mV steps
|
||||
*/
|
||||
if (cpu_get_family_model() == BROADWELL_FAMILY_ULT)
|
||||
msr.lo |= 0x006a; /* 1.56V */
|
||||
else
|
||||
msr.lo |= 0x006f; /* 1.60V */
|
||||
msr_write(MSR_VR_MISC_CONFIG2, msr);
|
||||
|
||||
/* Set C9/C10 VCC Min */
|
||||
pcode_mailbox_write(MAILBOX_BIOS_CMD_WRITE_C9C10_VOLTAGE, 0x1f1f);
|
||||
}
|
||||
|
||||
static int calibrate_24mhz_bclk(void)
|
||||
{
|
||||
int err_code;
|
||||
int ret;
|
||||
|
||||
ret = pcode_ready();
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
/* A non-zero value initiates the PCODE calibration */
|
||||
writel(~0, MCHBAR_REG(BIOS_MAILBOX_DATA));
|
||||
writel(MAILBOX_RUN_BUSY | MAILBOX_BIOS_CMD_FSM_MEASURE_INTVL,
|
||||
MCHBAR_REG(BIOS_MAILBOX_INTERFACE));
|
||||
|
||||
ret = pcode_ready();
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
err_code = readl(MCHBAR_REG(BIOS_MAILBOX_INTERFACE)) & 0xff;
|
||||
|
||||
debug("PCODE: 24MHz BLCK calibration response: %d\n", err_code);
|
||||
|
||||
/* Read the calibrated value */
|
||||
writel(MAILBOX_RUN_BUSY | MAILBOX_BIOS_CMD_READ_CALIBRATION,
|
||||
MCHBAR_REG(BIOS_MAILBOX_INTERFACE));
|
||||
|
||||
ret = pcode_ready();
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
debug("PCODE: 24MHz BLCK calibration value: 0x%08x\n",
|
||||
readl(MCHBAR_REG(BIOS_MAILBOX_DATA)));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void configure_pch_power_sharing(void)
|
||||
{
|
||||
u32 pch_power, pch_power_ext, pmsync, pmsync2;
|
||||
int i;
|
||||
|
||||
/* Read PCH Power levels from PCODE */
|
||||
pch_power = pcode_mailbox_read(MAILBOX_BIOS_CMD_READ_PCH_POWER);
|
||||
pch_power_ext = pcode_mailbox_read(MAILBOX_BIOS_CMD_READ_PCH_POWER_EXT);
|
||||
|
||||
debug("PCH Power: PCODE Levels 0x%08x 0x%08x\n", pch_power,
|
||||
pch_power_ext);
|
||||
|
||||
pmsync = readl(RCB_REG(PMSYNC_CONFIG));
|
||||
pmsync2 = readl(RCB_REG(PMSYNC_CONFIG2));
|
||||
|
||||
/*
|
||||
* Program PMSYNC_TPR_CONFIG PCH power limit values
|
||||
* pmsync[0:4] = mailbox[0:5]
|
||||
* pmsync[8:12] = mailbox[6:11]
|
||||
* pmsync[16:20] = mailbox[12:17]
|
||||
*/
|
||||
for (i = 0; i < 3; i++) {
|
||||
u32 level = pch_power & 0x3f;
|
||||
pch_power >>= 6;
|
||||
pmsync &= ~(0x1f << (i * 8));
|
||||
pmsync |= (level & 0x1f) << (i * 8);
|
||||
}
|
||||
writel(pmsync, RCB_REG(PMSYNC_CONFIG));
|
||||
|
||||
/*
|
||||
* Program PMSYNC_TPR_CONFIG2 Extended PCH power limit values
|
||||
* pmsync2[0:4] = mailbox[23:18]
|
||||
* pmsync2[8:12] = mailbox_ext[6:11]
|
||||
* pmsync2[16:20] = mailbox_ext[12:17]
|
||||
* pmsync2[24:28] = mailbox_ext[18:22]
|
||||
*/
|
||||
pmsync2 &= ~0x1f;
|
||||
pmsync2 |= pch_power & 0x1f;
|
||||
|
||||
for (i = 1; i < 4; i++) {
|
||||
u32 level = pch_power_ext & 0x3f;
|
||||
pch_power_ext >>= 6;
|
||||
pmsync2 &= ~(0x1f << (i * 8));
|
||||
pmsync2 |= (level & 0x1f) << (i * 8);
|
||||
}
|
||||
writel(pmsync2, RCB_REG(PMSYNC_CONFIG2));
|
||||
}
|
||||
|
||||
static int bsp_init_before_ap_bringup(struct udevice *dev)
|
||||
{
|
||||
int ret;
|
||||
|
||||
initialize_vr_config(dev);
|
||||
ret = calibrate_24mhz_bclk();
|
||||
if (ret)
|
||||
return ret;
|
||||
configure_pch_power_sharing();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int cpu_config_tdp_levels(void)
|
||||
{
|
||||
msr_t platform_info;
|
||||
|
||||
/* Bits 34:33 indicate how many levels supported */
|
||||
platform_info = msr_read(MSR_PLATFORM_INFO);
|
||||
return (platform_info.hi >> 1) & 3;
|
||||
}
|
||||
|
||||
static void set_max_ratio(void)
|
||||
{
|
||||
msr_t msr, perf_ctl;
|
||||
|
||||
perf_ctl.hi = 0;
|
||||
|
||||
/* Check for configurable TDP option */
|
||||
if (turbo_get_state() == TURBO_ENABLED) {
|
||||
msr = msr_read(MSR_NHM_TURBO_RATIO_LIMIT);
|
||||
perf_ctl.lo = (msr.lo & 0xff) << 8;
|
||||
} else if (cpu_config_tdp_levels()) {
|
||||
/* Set to nominal TDP ratio */
|
||||
msr = msr_read(MSR_CONFIG_TDP_NOMINAL);
|
||||
perf_ctl.lo = (msr.lo & 0xff) << 8;
|
||||
} else {
|
||||
/* Platform Info bits 15:8 give max ratio */
|
||||
msr = msr_read(MSR_PLATFORM_INFO);
|
||||
perf_ctl.lo = msr.lo & 0xff00;
|
||||
}
|
||||
msr_write(IA32_PERF_CTL, perf_ctl);
|
||||
|
||||
debug("cpu: frequency set to %d\n",
|
||||
((perf_ctl.lo >> 8) & 0xff) * CPU_BCLK);
|
||||
}
|
||||
|
||||
int broadwell_init(struct udevice *dev)
|
||||
{
|
||||
struct cpu_broadwell_priv *priv = dev_get_priv(dev);
|
||||
int num_threads;
|
||||
int num_cores;
|
||||
msr_t msr;
|
||||
int ret;
|
||||
|
||||
msr = msr_read(CORE_THREAD_COUNT_MSR);
|
||||
num_threads = (msr.lo >> 0) & 0xffff;
|
||||
num_cores = (msr.lo >> 16) & 0xffff;
|
||||
debug("CPU has %u cores, %u threads enabled\n", num_cores,
|
||||
num_threads);
|
||||
|
||||
priv->ht_disabled = num_threads == num_cores;
|
||||
|
||||
ret = bsp_init_before_ap_bringup(dev);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
set_max_ratio();
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void configure_mca(void)
|
||||
{
|
||||
msr_t msr;
|
||||
const unsigned int mcg_cap_msr = 0x179;
|
||||
int i;
|
||||
int num_banks;
|
||||
|
||||
msr = msr_read(mcg_cap_msr);
|
||||
num_banks = msr.lo & 0xff;
|
||||
msr.lo = 0;
|
||||
msr.hi = 0;
|
||||
/*
|
||||
* TODO(adurbin): This should only be done on a cold boot. Also, some
|
||||
* of these banks are core vs package scope. For now every CPU clears
|
||||
* every bank
|
||||
*/
|
||||
for (i = 0; i < num_banks; i++)
|
||||
msr_write(MSR_IA32_MC0_STATUS + (i * 4), msr);
|
||||
}
|
||||
|
||||
static void enable_lapic_tpr(void)
|
||||
{
|
||||
msr_t msr;
|
||||
|
||||
msr = msr_read(MSR_PIC_MSG_CONTROL);
|
||||
msr.lo &= ~(1 << 10); /* Enable APIC TPR updates */
|
||||
msr_write(MSR_PIC_MSG_CONTROL, msr);
|
||||
}
|
||||
|
||||
|
||||
static void configure_c_states(void)
|
||||
{
|
||||
msr_t msr;
|
||||
|
||||
msr = msr_read(MSR_PMG_CST_CONFIG_CONTROL);
|
||||
msr.lo |= (1 << 31); /* Timed MWAIT Enable */
|
||||
msr.lo |= (1 << 30); /* Package c-state Undemotion Enable */
|
||||
msr.lo |= (1 << 29); /* Package c-state Demotion Enable */
|
||||
msr.lo |= (1 << 28); /* C1 Auto Undemotion Enable */
|
||||
msr.lo |= (1 << 27); /* C3 Auto Undemotion Enable */
|
||||
msr.lo |= (1 << 26); /* C1 Auto Demotion Enable */
|
||||
msr.lo |= (1 << 25); /* C3 Auto Demotion Enable */
|
||||
msr.lo &= ~(1 << 10); /* Disable IO MWAIT redirection */
|
||||
/* The deepest package c-state defaults to factory-configured value */
|
||||
msr_write(MSR_PMG_CST_CONFIG_CONTROL, msr);
|
||||
|
||||
msr = msr_read(MSR_MISC_PWR_MGMT);
|
||||
msr.lo &= ~(1 << 0); /* Enable P-state HW_ALL coordination */
|
||||
msr_write(MSR_MISC_PWR_MGMT, msr);
|
||||
|
||||
msr = msr_read(MSR_POWER_CTL);
|
||||
msr.lo |= (1 << 18); /* Enable Energy Perf Bias MSR 0x1b0 */
|
||||
msr.lo |= (1 << 1); /* C1E Enable */
|
||||
msr.lo |= (1 << 0); /* Bi-directional PROCHOT# */
|
||||
msr_write(MSR_POWER_CTL, msr);
|
||||
|
||||
/* C-state Interrupt Response Latency Control 0 - package C3 latency */
|
||||
msr.hi = 0;
|
||||
msr.lo = IRTL_VALID | IRTL_1024_NS | C_STATE_LATENCY_CONTROL_0_LIMIT;
|
||||
msr_write(MSR_C_STATE_LATENCY_CONTROL_0, msr);
|
||||
|
||||
/* C-state Interrupt Response Latency Control 1 */
|
||||
msr.hi = 0;
|
||||
msr.lo = IRTL_VALID | IRTL_1024_NS | C_STATE_LATENCY_CONTROL_1_LIMIT;
|
||||
msr_write(MSR_C_STATE_LATENCY_CONTROL_1, msr);
|
||||
|
||||
/* C-state Interrupt Response Latency Control 2 - package C6/C7 short */
|
||||
msr.hi = 0;
|
||||
msr.lo = IRTL_VALID | IRTL_1024_NS | C_STATE_LATENCY_CONTROL_2_LIMIT;
|
||||
msr_write(MSR_C_STATE_LATENCY_CONTROL_2, msr);
|
||||
|
||||
/* C-state Interrupt Response Latency Control 3 - package C8 */
|
||||
msr.hi = 0;
|
||||
msr.lo = IRTL_VALID | IRTL_1024_NS | C_STATE_LATENCY_CONTROL_3_LIMIT;
|
||||
msr_write(MSR_C_STATE_LATENCY_CONTROL_3, msr);
|
||||
|
||||
/* C-state Interrupt Response Latency Control 4 - package C9 */
|
||||
msr.hi = 0;
|
||||
msr.lo = IRTL_VALID | IRTL_1024_NS | C_STATE_LATENCY_CONTROL_4_LIMIT;
|
||||
msr_write(MSR_C_STATE_LATENCY_CONTROL_4, msr);
|
||||
|
||||
/* C-state Interrupt Response Latency Control 5 - package C10 */
|
||||
msr.hi = 0;
|
||||
msr.lo = IRTL_VALID | IRTL_1024_NS | C_STATE_LATENCY_CONTROL_5_LIMIT;
|
||||
msr_write(MSR_C_STATE_LATENCY_CONTROL_5, msr);
|
||||
}
|
||||
|
||||
static void configure_misc(void)
|
||||
{
|
||||
msr_t msr;
|
||||
|
||||
msr = msr_read(MSR_IA32_MISC_ENABLE);
|
||||
msr.lo |= (1 << 0); /* Fast String enable */
|
||||
msr.lo |= (1 << 3); /* TM1/TM2/EMTTM enable */
|
||||
msr.lo |= (1 << 16); /* Enhanced SpeedStep Enable */
|
||||
msr_write(MSR_IA32_MISC_ENABLE, msr);
|
||||
|
||||
/* Disable thermal interrupts */
|
||||
msr.lo = 0;
|
||||
msr.hi = 0;
|
||||
msr_write(MSR_IA32_THERM_INTERRUPT, msr);
|
||||
|
||||
/* Enable package critical interrupt only */
|
||||
msr.lo = 1 << 4;
|
||||
msr.hi = 0;
|
||||
msr_write(MSR_IA32_PACKAGE_THERM_INTERRUPT, msr);
|
||||
}
|
||||
|
||||
static void configure_thermal_target(struct udevice *dev)
|
||||
{
|
||||
int tcc_offset;
|
||||
msr_t msr;
|
||||
|
||||
tcc_offset = fdtdec_get_int(gd->fdt_blob, dev_of_offset(dev),
|
||||
"intel,tcc-offset", 0);
|
||||
|
||||
/* Set TCC activaiton offset if supported */
|
||||
msr = msr_read(MSR_PLATFORM_INFO);
|
||||
if ((msr.lo & (1 << 30)) && tcc_offset) {
|
||||
msr = msr_read(MSR_TEMPERATURE_TARGET);
|
||||
msr.lo &= ~(0xf << 24); /* Bits 27:24 */
|
||||
msr.lo |= (tcc_offset & 0xf) << 24;
|
||||
msr_write(MSR_TEMPERATURE_TARGET, msr);
|
||||
}
|
||||
}
|
||||
|
||||
static void configure_dca_cap(void)
|
||||
{
|
||||
struct cpuid_result cpuid_regs;
|
||||
msr_t msr;
|
||||
|
||||
/* Check feature flag in CPUID.(EAX=1):ECX[18]==1 */
|
||||
cpuid_regs = cpuid(1);
|
||||
if (cpuid_regs.ecx & (1 << 18)) {
|
||||
msr = msr_read(MSR_IA32_PLATFORM_DCA_CAP);
|
||||
msr.lo |= 1;
|
||||
msr_write(MSR_IA32_PLATFORM_DCA_CAP, msr);
|
||||
}
|
||||
}
|
||||
|
||||
static void set_energy_perf_bias(u8 policy)
|
||||
{
|
||||
msr_t msr;
|
||||
int ecx;
|
||||
|
||||
/* Determine if energy efficient policy is supported */
|
||||
ecx = cpuid_ecx(0x6);
|
||||
if (!(ecx & (1 << 3)))
|
||||
return;
|
||||
|
||||
/* Energy Policy is bits 3:0 */
|
||||
msr = msr_read(MSR_IA32_ENERGY_PERFORMANCE_BIAS);
|
||||
msr.lo &= ~0xf;
|
||||
msr.lo |= policy & 0xf;
|
||||
msr_write(MSR_IA32_ENERGY_PERFORMANCE_BIAS, msr);
|
||||
|
||||
debug("cpu: energy policy set to %u\n", policy);
|
||||
}
|
||||
|
||||
/* All CPUs including BSP will run the following function */
|
||||
static void cpu_core_init(struct udevice *dev)
|
||||
{
|
||||
/* Clear out pending MCEs */
|
||||
configure_mca();
|
||||
|
||||
/* Enable the local cpu apics */
|
||||
enable_lapic_tpr();
|
||||
|
||||
/* Configure C States */
|
||||
configure_c_states();
|
||||
|
||||
/* Configure Enhanced SpeedStep and Thermal Sensors */
|
||||
configure_misc();
|
||||
|
||||
/* Thermal throttle activation offset */
|
||||
configure_thermal_target(dev);
|
||||
|
||||
/* Enable Direct Cache Access */
|
||||
configure_dca_cap();
|
||||
|
||||
/* Set energy policy */
|
||||
set_energy_perf_bias(ENERGY_POLICY_NORMAL);
|
||||
|
||||
/* Enable Turbo */
|
||||
turbo_enable();
|
||||
}
|
||||
|
||||
/*
|
||||
* Configure processor power limits if possible
|
||||
* This must be done AFTER set of BIOS_RESET_CPL
|
||||
*/
|
||||
void cpu_set_power_limits(int power_limit_1_time)
|
||||
{
|
||||
msr_t msr;
|
||||
msr_t limit;
|
||||
unsigned power_unit;
|
||||
unsigned tdp, min_power, max_power, max_time;
|
||||
u8 power_limit_1_val;
|
||||
|
||||
msr = msr_read(MSR_PLATFORM_INFO);
|
||||
if (power_limit_1_time > ARRAY_SIZE(power_limit_time_sec_to_msr))
|
||||
power_limit_1_time = 28;
|
||||
|
||||
if (!(msr.lo & PLATFORM_INFO_SET_TDP))
|
||||
return;
|
||||
|
||||
/* Get units */
|
||||
msr = msr_read(MSR_PKG_POWER_SKU_UNIT);
|
||||
power_unit = 2 << ((msr.lo & 0xf) - 1);
|
||||
|
||||
/* Get power defaults for this SKU */
|
||||
msr = msr_read(MSR_PKG_POWER_SKU);
|
||||
tdp = msr.lo & 0x7fff;
|
||||
min_power = (msr.lo >> 16) & 0x7fff;
|
||||
max_power = msr.hi & 0x7fff;
|
||||
max_time = (msr.hi >> 16) & 0x7f;
|
||||
|
||||
debug("CPU TDP: %u Watts\n", tdp / power_unit);
|
||||
|
||||
if (power_limit_time_msr_to_sec[max_time] > power_limit_1_time)
|
||||
power_limit_1_time = power_limit_time_msr_to_sec[max_time];
|
||||
|
||||
if (min_power > 0 && tdp < min_power)
|
||||
tdp = min_power;
|
||||
|
||||
if (max_power > 0 && tdp > max_power)
|
||||
tdp = max_power;
|
||||
|
||||
power_limit_1_val = power_limit_time_sec_to_msr[power_limit_1_time];
|
||||
|
||||
/* Set long term power limit to TDP */
|
||||
limit.lo = 0;
|
||||
limit.lo |= tdp & PKG_POWER_LIMIT_MASK;
|
||||
limit.lo |= PKG_POWER_LIMIT_EN;
|
||||
limit.lo |= (power_limit_1_val & PKG_POWER_LIMIT_TIME_MASK) <<
|
||||
PKG_POWER_LIMIT_TIME_SHIFT;
|
||||
|
||||
/* Set short term power limit to 1.25 * TDP */
|
||||
limit.hi = 0;
|
||||
limit.hi |= ((tdp * 125) / 100) & PKG_POWER_LIMIT_MASK;
|
||||
limit.hi |= PKG_POWER_LIMIT_EN;
|
||||
/* Power limit 2 time is only programmable on server SKU */
|
||||
|
||||
msr_write(MSR_PKG_POWER_LIMIT, limit);
|
||||
|
||||
/* Set power limit values in MCHBAR as well */
|
||||
writel(limit.lo, MCHBAR_REG(MCH_PKG_POWER_LIMIT_LO));
|
||||
writel(limit.hi, MCHBAR_REG(MCH_PKG_POWER_LIMIT_HI));
|
||||
|
||||
/* Set DDR RAPL power limit by copying from MMIO to MSR */
|
||||
msr.lo = readl(MCHBAR_REG(MCH_DDR_POWER_LIMIT_LO));
|
||||
msr.hi = readl(MCHBAR_REG(MCH_DDR_POWER_LIMIT_HI));
|
||||
msr_write(MSR_DDR_RAPL_LIMIT, msr);
|
||||
|
||||
/* Use nominal TDP values for CPUs with configurable TDP */
|
||||
if (cpu_config_tdp_levels()) {
|
||||
msr = msr_read(MSR_CONFIG_TDP_NOMINAL);
|
||||
limit.hi = 0;
|
||||
limit.lo = msr.lo & 0xff;
|
||||
msr_write(MSR_TURBO_ACTIVATION_RATIO, limit);
|
||||
}
|
||||
}
|
||||
|
||||
static int broadwell_get_info(struct udevice *dev, struct cpu_info *info)
|
||||
{
|
||||
msr_t msr;
|
||||
|
||||
msr = msr_read(IA32_PERF_CTL);
|
||||
info->cpu_freq = ((msr.lo >> 8) & 0xff) * BROADWELL_BCLK * 1000000;
|
||||
info->features = 1 << CPU_FEAT_L1_CACHE | 1 << CPU_FEAT_MMU |
|
||||
1 << CPU_FEAT_UCODE | 1 << CPU_FEAT_DEVICE_ID;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int broadwell_get_count(struct udevice *dev)
|
||||
{
|
||||
return 4;
|
||||
}
|
||||
|
||||
static int cpu_x86_broadwell_probe(struct udevice *dev)
|
||||
{
|
||||
if (dev->seq == 0) {
|
||||
cpu_core_init(dev);
|
||||
return broadwell_init(dev);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct cpu_ops cpu_x86_broadwell_ops = {
|
||||
.get_desc = cpu_x86_get_desc,
|
||||
.get_info = broadwell_get_info,
|
||||
.get_count = broadwell_get_count,
|
||||
.get_vendor = cpu_x86_get_vendor,
|
||||
};
|
||||
|
||||
static const struct udevice_id cpu_x86_broadwell_ids[] = {
|
||||
{ .compatible = "intel,core-i3-gen5" },
|
||||
{ }
|
||||
};
|
||||
|
||||
U_BOOT_DRIVER(cpu_x86_broadwell_drv) = {
|
||||
.name = "cpu_x86_broadwell",
|
||||
.id = UCLASS_CPU,
|
||||
.of_match = cpu_x86_broadwell_ids,
|
||||
.bind = cpu_x86_bind,
|
||||
.probe = cpu_x86_broadwell_probe,
|
||||
.ops = &cpu_x86_broadwell_ops,
|
||||
.priv_auto_alloc_size = sizeof(struct cpu_broadwell_priv),
|
||||
.flags = DM_FLAG_PRE_RELOC,
|
||||
};
|
||||
|
63
arch/x86/cpu/broadwell/cpu_from_spl.c
Normal file
63
arch/x86/cpu/broadwell/cpu_from_spl.c
Normal file
@ -0,0 +1,63 @@
|
||||
// SPDX-License-Identifier: GPL-2.0+
|
||||
/*
|
||||
* (C) Copyright 2016 Google, Inc
|
||||
* Written by Simon Glass <sjg@chromium.org>
|
||||
*/
|
||||
|
||||
#include <common.h>
|
||||
#include <bloblist.h>
|
||||
#include <debug_uart.h>
|
||||
#include <handoff.h>
|
||||
#include <asm/mtrr.h>
|
||||
|
||||
int misc_init_r(void)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
int dram_init(void)
|
||||
{
|
||||
struct spl_handoff *ho;
|
||||
|
||||
ho = bloblist_find(BLOBLISTT_SPL_HANDOFF, sizeof(*ho));
|
||||
if (!ho)
|
||||
return log_msg_ret("Missing SPL hand-off info", -ENOENT);
|
||||
handoff_load_dram_size(ho);
|
||||
#ifdef CONFIG_TPL
|
||||
/* TODO(sjg@chromium.org): MTRR cannot be adjusted without a hang */
|
||||
mtrr_add_request(MTRR_TYPE_WRBACK, 0, 2ULL << 30);
|
||||
#else
|
||||
mtrr_add_request(MTRR_TYPE_WRBACK, 0, gd->ram_size);
|
||||
mtrr_commit(true);
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int checkcpu(void)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
int print_cpuinfo(void)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
void board_debug_uart_init(void)
|
||||
{
|
||||
}
|
||||
|
||||
int dram_init_banksize(void)
|
||||
{
|
||||
#ifdef CONFIG_NR_DRAM_BANKS
|
||||
struct spl_handoff *ho;
|
||||
|
||||
ho = bloblist_find(BLOBLISTT_SPL_HANDOFF, sizeof(*ho));
|
||||
if (!ho)
|
||||
return log_msg_ret("Missing SPL hand-off info", -ENOENT);
|
||||
handoff_load_dram_banks(ho);
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
}
|
694
arch/x86/cpu/broadwell/cpu_full.c
Normal file
694
arch/x86/cpu/broadwell/cpu_full.c
Normal file
@ -0,0 +1,694 @@
|
||||
// SPDX-License-Identifier: GPL-2.0
|
||||
/*
|
||||
* Copyright (c) 2016 Google, Inc
|
||||
*
|
||||
* Based on code from coreboot src/soc/intel/broadwell/cpu.c
|
||||
*/
|
||||
|
||||
#include <common.h>
|
||||
#include <dm.h>
|
||||
#include <cpu.h>
|
||||
#include <asm/cpu.h>
|
||||
#include <asm/cpu_x86.h>
|
||||
#include <asm/cpu_common.h>
|
||||
#include <asm/intel_regs.h>
|
||||
#include <asm/msr.h>
|
||||
#include <asm/post.h>
|
||||
#include <asm/turbo.h>
|
||||
#include <asm/arch/cpu.h>
|
||||
#include <asm/arch/pch.h>
|
||||
#include <asm/arch/rcb.h>
|
||||
|
||||
struct cpu_broadwell_priv {
|
||||
bool ht_disabled;
|
||||
};
|
||||
|
||||
/* Convert time in seconds to POWER_LIMIT_1_TIME MSR value */
|
||||
static const u8 power_limit_time_sec_to_msr[] = {
|
||||
[0] = 0x00,
|
||||
[1] = 0x0a,
|
||||
[2] = 0x0b,
|
||||
[3] = 0x4b,
|
||||
[4] = 0x0c,
|
||||
[5] = 0x2c,
|
||||
[6] = 0x4c,
|
||||
[7] = 0x6c,
|
||||
[8] = 0x0d,
|
||||
[10] = 0x2d,
|
||||
[12] = 0x4d,
|
||||
[14] = 0x6d,
|
||||
[16] = 0x0e,
|
||||
[20] = 0x2e,
|
||||
[24] = 0x4e,
|
||||
[28] = 0x6e,
|
||||
[32] = 0x0f,
|
||||
[40] = 0x2f,
|
||||
[48] = 0x4f,
|
||||
[56] = 0x6f,
|
||||
[64] = 0x10,
|
||||
[80] = 0x30,
|
||||
[96] = 0x50,
|
||||
[112] = 0x70,
|
||||
[128] = 0x11,
|
||||
};
|
||||
|
||||
/* Convert POWER_LIMIT_1_TIME MSR value to seconds */
|
||||
static const u8 power_limit_time_msr_to_sec[] = {
|
||||
[0x00] = 0,
|
||||
[0x0a] = 1,
|
||||
[0x0b] = 2,
|
||||
[0x4b] = 3,
|
||||
[0x0c] = 4,
|
||||
[0x2c] = 5,
|
||||
[0x4c] = 6,
|
||||
[0x6c] = 7,
|
||||
[0x0d] = 8,
|
||||
[0x2d] = 10,
|
||||
[0x4d] = 12,
|
||||
[0x6d] = 14,
|
||||
[0x0e] = 16,
|
||||
[0x2e] = 20,
|
||||
[0x4e] = 24,
|
||||
[0x6e] = 28,
|
||||
[0x0f] = 32,
|
||||
[0x2f] = 40,
|
||||
[0x4f] = 48,
|
||||
[0x6f] = 56,
|
||||
[0x10] = 64,
|
||||
[0x30] = 80,
|
||||
[0x50] = 96,
|
||||
[0x70] = 112,
|
||||
[0x11] = 128,
|
||||
};
|
||||
|
||||
/*
|
||||
* The core 100MHz BLCK is disabled in deeper c-states. One needs to calibrate
|
||||
* the 100MHz BCLCK against the 24MHz BLCK to restore the clocks properly
|
||||
* when a core is woken up
|
||||
*/
|
||||
static int pcode_ready(void)
|
||||
{
|
||||
int wait_count;
|
||||
const int delay_step = 10;
|
||||
|
||||
wait_count = 0;
|
||||
do {
|
||||
if (!(readl(MCHBAR_REG(BIOS_MAILBOX_INTERFACE)) &
|
||||
MAILBOX_RUN_BUSY))
|
||||
return 0;
|
||||
wait_count += delay_step;
|
||||
udelay(delay_step);
|
||||
} while (wait_count < 1000);
|
||||
|
||||
return -ETIMEDOUT;
|
||||
}
|
||||
|
||||
static u32 pcode_mailbox_read(u32 command)
|
||||
{
|
||||
int ret;
|
||||
|
||||
ret = pcode_ready();
|
||||
if (ret) {
|
||||
debug("PCODE: mailbox timeout on wait ready\n");
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Send command and start transaction */
|
||||
writel(command | MAILBOX_RUN_BUSY, MCHBAR_REG(BIOS_MAILBOX_INTERFACE));
|
||||
|
||||
ret = pcode_ready();
|
||||
if (ret) {
|
||||
debug("PCODE: mailbox timeout on completion\n");
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Read mailbox */
|
||||
return readl(MCHBAR_REG(BIOS_MAILBOX_DATA));
|
||||
}
|
||||
|
||||
static int pcode_mailbox_write(u32 command, u32 data)
|
||||
{
|
||||
int ret;
|
||||
|
||||
ret = pcode_ready();
|
||||
if (ret) {
|
||||
debug("PCODE: mailbox timeout on wait ready\n");
|
||||
return ret;
|
||||
}
|
||||
|
||||
writel(data, MCHBAR_REG(BIOS_MAILBOX_DATA));
|
||||
|
||||
/* Send command and start transaction */
|
||||
writel(command | MAILBOX_RUN_BUSY, MCHBAR_REG(BIOS_MAILBOX_INTERFACE));
|
||||
|
||||
ret = pcode_ready();
|
||||
if (ret) {
|
||||
debug("PCODE: mailbox timeout on completion\n");
|
||||
return ret;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* @dev is the CPU device */
|
||||
static void initialize_vr_config(struct udevice *dev)
|
||||
{
|
||||
int ramp, min_vid;
|
||||
msr_t msr;
|
||||
|
||||
debug("Initializing VR config\n");
|
||||
|
||||
/* Configure VR_CURRENT_CONFIG */
|
||||
msr = msr_read(MSR_VR_CURRENT_CONFIG);
|
||||
/*
|
||||
* Preserve bits 63 and 62. Bit 62 is PSI4 enable, but it is only valid
|
||||
* on ULT systems
|
||||
*/
|
||||
msr.hi &= 0xc0000000;
|
||||
msr.hi |= (0x01 << (52 - 32)); /* PSI3 threshold - 1A */
|
||||
msr.hi |= (0x05 << (42 - 32)); /* PSI2 threshold - 5A */
|
||||
msr.hi |= (0x14 << (32 - 32)); /* PSI1 threshold - 20A */
|
||||
msr.hi |= (1 << (62 - 32)); /* Enable PSI4 */
|
||||
/* Leave the max instantaneous current limit (12:0) to default */
|
||||
msr_write(MSR_VR_CURRENT_CONFIG, msr);
|
||||
|
||||
/* Configure VR_MISC_CONFIG MSR */
|
||||
msr = msr_read(MSR_VR_MISC_CONFIG);
|
||||
/* Set the IOUT_SLOPE scalar applied to dIout in U10.1.9 format */
|
||||
msr.hi &= ~(0x3ff << (40 - 32));
|
||||
msr.hi |= (0x200 << (40 - 32)); /* 1.0 */
|
||||
/* Set IOUT_OFFSET to 0 */
|
||||
msr.hi &= ~0xff;
|
||||
/* Set entry ramp rate to slow */
|
||||
msr.hi &= ~(1 << (51 - 32));
|
||||
/* Enable decay mode on C-state entry */
|
||||
msr.hi |= (1 << (52 - 32));
|
||||
/* Set the slow ramp rate */
|
||||
msr.hi &= ~(0x3 << (53 - 32));
|
||||
/* Configure the C-state exit ramp rate */
|
||||
ramp = fdtdec_get_int(gd->fdt_blob, dev_of_offset(dev),
|
||||
"intel,slow-ramp", -1);
|
||||
if (ramp != -1) {
|
||||
/* Configured slow ramp rate */
|
||||
msr.hi |= ((ramp & 0x3) << (53 - 32));
|
||||
/* Set exit ramp rate to slow */
|
||||
msr.hi &= ~(1 << (50 - 32));
|
||||
} else {
|
||||
/* Fast ramp rate / 4 */
|
||||
msr.hi |= (0x01 << (53 - 32));
|
||||
/* Set exit ramp rate to fast */
|
||||
msr.hi |= (1 << (50 - 32));
|
||||
}
|
||||
/* Set MIN_VID (31:24) to allow CPU to have full control */
|
||||
msr.lo &= ~0xff000000;
|
||||
min_vid = fdtdec_get_int(gd->fdt_blob, dev_of_offset(dev),
|
||||
"intel,min-vid", 0);
|
||||
msr.lo |= (min_vid & 0xff) << 24;
|
||||
msr_write(MSR_VR_MISC_CONFIG, msr);
|
||||
|
||||
/* Configure VR_MISC_CONFIG2 MSR */
|
||||
msr = msr_read(MSR_VR_MISC_CONFIG2);
|
||||
msr.lo &= ~0xffff;
|
||||
/*
|
||||
* Allow CPU to control minimum voltage completely (15:8) and
|
||||
* set the fast ramp voltage in 10mV steps
|
||||
*/
|
||||
if (cpu_get_family_model() == BROADWELL_FAMILY_ULT)
|
||||
msr.lo |= 0x006a; /* 1.56V */
|
||||
else
|
||||
msr.lo |= 0x006f; /* 1.60V */
|
||||
msr_write(MSR_VR_MISC_CONFIG2, msr);
|
||||
|
||||
/* Set C9/C10 VCC Min */
|
||||
pcode_mailbox_write(MAILBOX_BIOS_CMD_WRITE_C9C10_VOLTAGE, 0x1f1f);
|
||||
}
|
||||
|
||||
static int calibrate_24mhz_bclk(void)
|
||||
{
|
||||
int err_code;
|
||||
int ret;
|
||||
|
||||
ret = pcode_ready();
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
/* A non-zero value initiates the PCODE calibration */
|
||||
writel(~0, MCHBAR_REG(BIOS_MAILBOX_DATA));
|
||||
writel(MAILBOX_RUN_BUSY | MAILBOX_BIOS_CMD_FSM_MEASURE_INTVL,
|
||||
MCHBAR_REG(BIOS_MAILBOX_INTERFACE));
|
||||
|
||||
ret = pcode_ready();
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
err_code = readl(MCHBAR_REG(BIOS_MAILBOX_INTERFACE)) & 0xff;
|
||||
|
||||
debug("PCODE: 24MHz BLCK calibration response: %d\n", err_code);
|
||||
|
||||
/* Read the calibrated value */
|
||||
writel(MAILBOX_RUN_BUSY | MAILBOX_BIOS_CMD_READ_CALIBRATION,
|
||||
MCHBAR_REG(BIOS_MAILBOX_INTERFACE));
|
||||
|
||||
ret = pcode_ready();
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
debug("PCODE: 24MHz BLCK calibration value: 0x%08x\n",
|
||||
readl(MCHBAR_REG(BIOS_MAILBOX_DATA)));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void configure_pch_power_sharing(void)
|
||||
{
|
||||
u32 pch_power, pch_power_ext, pmsync, pmsync2;
|
||||
int i;
|
||||
|
||||
/* Read PCH Power levels from PCODE */
|
||||
pch_power = pcode_mailbox_read(MAILBOX_BIOS_CMD_READ_PCH_POWER);
|
||||
pch_power_ext = pcode_mailbox_read(MAILBOX_BIOS_CMD_READ_PCH_POWER_EXT);
|
||||
|
||||
debug("PCH Power: PCODE Levels 0x%08x 0x%08x\n", pch_power,
|
||||
pch_power_ext);
|
||||
|
||||
pmsync = readl(RCB_REG(PMSYNC_CONFIG));
|
||||
pmsync2 = readl(RCB_REG(PMSYNC_CONFIG2));
|
||||
|
||||
/*
|
||||
* Program PMSYNC_TPR_CONFIG PCH power limit values
|
||||
* pmsync[0:4] = mailbox[0:5]
|
||||
* pmsync[8:12] = mailbox[6:11]
|
||||
* pmsync[16:20] = mailbox[12:17]
|
||||
*/
|
||||
for (i = 0; i < 3; i++) {
|
||||
u32 level = pch_power & 0x3f;
|
||||
|
||||
pch_power >>= 6;
|
||||
pmsync &= ~(0x1f << (i * 8));
|
||||
pmsync |= (level & 0x1f) << (i * 8);
|
||||
}
|
||||
writel(pmsync, RCB_REG(PMSYNC_CONFIG));
|
||||
|
||||
/*
|
||||
* Program PMSYNC_TPR_CONFIG2 Extended PCH power limit values
|
||||
* pmsync2[0:4] = mailbox[23:18]
|
||||
* pmsync2[8:12] = mailbox_ext[6:11]
|
||||
* pmsync2[16:20] = mailbox_ext[12:17]
|
||||
* pmsync2[24:28] = mailbox_ext[18:22]
|
||||
*/
|
||||
pmsync2 &= ~0x1f;
|
||||
pmsync2 |= pch_power & 0x1f;
|
||||
|
||||
for (i = 1; i < 4; i++) {
|
||||
u32 level = pch_power_ext & 0x3f;
|
||||
|
||||
pch_power_ext >>= 6;
|
||||
pmsync2 &= ~(0x1f << (i * 8));
|
||||
pmsync2 |= (level & 0x1f) << (i * 8);
|
||||
}
|
||||
writel(pmsync2, RCB_REG(PMSYNC_CONFIG2));
|
||||
}
|
||||
|
||||
static int bsp_init_before_ap_bringup(struct udevice *dev)
|
||||
{
|
||||
int ret;
|
||||
|
||||
initialize_vr_config(dev);
|
||||
ret = calibrate_24mhz_bclk();
|
||||
if (ret)
|
||||
return ret;
|
||||
configure_pch_power_sharing();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int cpu_config_tdp_levels(void)
|
||||
{
|
||||
msr_t platform_info;
|
||||
|
||||
/* Bits 34:33 indicate how many levels supported */
|
||||
platform_info = msr_read(MSR_PLATFORM_INFO);
|
||||
return (platform_info.hi >> 1) & 3;
|
||||
}
|
||||
|
||||
static void set_max_ratio(void)
|
||||
{
|
||||
msr_t msr, perf_ctl;
|
||||
|
||||
perf_ctl.hi = 0;
|
||||
|
||||
/* Check for configurable TDP option */
|
||||
if (turbo_get_state() == TURBO_ENABLED) {
|
||||
msr = msr_read(MSR_NHM_TURBO_RATIO_LIMIT);
|
||||
perf_ctl.lo = (msr.lo & 0xff) << 8;
|
||||
} else if (cpu_config_tdp_levels()) {
|
||||
/* Set to nominal TDP ratio */
|
||||
msr = msr_read(MSR_CONFIG_TDP_NOMINAL);
|
||||
perf_ctl.lo = (msr.lo & 0xff) << 8;
|
||||
} else {
|
||||
/* Platform Info bits 15:8 give max ratio */
|
||||
msr = msr_read(MSR_PLATFORM_INFO);
|
||||
perf_ctl.lo = msr.lo & 0xff00;
|
||||
}
|
||||
msr_write(IA32_PERF_CTL, perf_ctl);
|
||||
|
||||
debug("cpu: frequency set to %d\n",
|
||||
((perf_ctl.lo >> 8) & 0xff) * CPU_BCLK);
|
||||
}
|
||||
|
||||
int broadwell_init(struct udevice *dev)
|
||||
{
|
||||
struct cpu_broadwell_priv *priv = dev_get_priv(dev);
|
||||
int num_threads;
|
||||
int num_cores;
|
||||
msr_t msr;
|
||||
int ret;
|
||||
|
||||
msr = msr_read(CORE_THREAD_COUNT_MSR);
|
||||
num_threads = (msr.lo >> 0) & 0xffff;
|
||||
num_cores = (msr.lo >> 16) & 0xffff;
|
||||
debug("CPU has %u cores, %u threads enabled\n", num_cores,
|
||||
num_threads);
|
||||
|
||||
priv->ht_disabled = num_threads == num_cores;
|
||||
|
||||
ret = bsp_init_before_ap_bringup(dev);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
set_max_ratio();
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void configure_mca(void)
|
||||
{
|
||||
msr_t msr;
|
||||
const unsigned int mcg_cap_msr = 0x179;
|
||||
int i;
|
||||
int num_banks;
|
||||
|
||||
msr = msr_read(mcg_cap_msr);
|
||||
num_banks = msr.lo & 0xff;
|
||||
msr.lo = 0;
|
||||
msr.hi = 0;
|
||||
/*
|
||||
* TODO(adurbin): This should only be done on a cold boot. Also, some
|
||||
* of these banks are core vs package scope. For now every CPU clears
|
||||
* every bank
|
||||
*/
|
||||
for (i = 0; i < num_banks; i++)
|
||||
msr_write(MSR_IA32_MC0_STATUS + (i * 4), msr);
|
||||
}
|
||||
|
||||
static void enable_lapic_tpr(void)
|
||||
{
|
||||
msr_t msr;
|
||||
|
||||
msr = msr_read(MSR_PIC_MSG_CONTROL);
|
||||
msr.lo &= ~(1 << 10); /* Enable APIC TPR updates */
|
||||
msr_write(MSR_PIC_MSG_CONTROL, msr);
|
||||
}
|
||||
|
||||
static void configure_c_states(void)
|
||||
{
|
||||
msr_t msr;
|
||||
|
||||
msr = msr_read(MSR_PMG_CST_CONFIG_CONTROL);
|
||||
msr.lo |= (1 << 31); /* Timed MWAIT Enable */
|
||||
msr.lo |= (1 << 30); /* Package c-state Undemotion Enable */
|
||||
msr.lo |= (1 << 29); /* Package c-state Demotion Enable */
|
||||
msr.lo |= (1 << 28); /* C1 Auto Undemotion Enable */
|
||||
msr.lo |= (1 << 27); /* C3 Auto Undemotion Enable */
|
||||
msr.lo |= (1 << 26); /* C1 Auto Demotion Enable */
|
||||
msr.lo |= (1 << 25); /* C3 Auto Demotion Enable */
|
||||
msr.lo &= ~(1 << 10); /* Disable IO MWAIT redirection */
|
||||
/* The deepest package c-state defaults to factory-configured value */
|
||||
msr_write(MSR_PMG_CST_CONFIG_CONTROL, msr);
|
||||
|
||||
msr = msr_read(MSR_MISC_PWR_MGMT);
|
||||
msr.lo &= ~(1 << 0); /* Enable P-state HW_ALL coordination */
|
||||
msr_write(MSR_MISC_PWR_MGMT, msr);
|
||||
|
||||
msr = msr_read(MSR_POWER_CTL);
|
||||
msr.lo |= (1 << 18); /* Enable Energy Perf Bias MSR 0x1b0 */
|
||||
msr.lo |= (1 << 1); /* C1E Enable */
|
||||
msr.lo |= (1 << 0); /* Bi-directional PROCHOT# */
|
||||
msr_write(MSR_POWER_CTL, msr);
|
||||
|
||||
/* C-state Interrupt Response Latency Control 0 - package C3 latency */
|
||||
msr.hi = 0;
|
||||
msr.lo = IRTL_VALID | IRTL_1024_NS | C_STATE_LATENCY_CONTROL_0_LIMIT;
|
||||
msr_write(MSR_C_STATE_LATENCY_CONTROL_0, msr);
|
||||
|
||||
/* C-state Interrupt Response Latency Control 1 */
|
||||
msr.hi = 0;
|
||||
msr.lo = IRTL_VALID | IRTL_1024_NS | C_STATE_LATENCY_CONTROL_1_LIMIT;
|
||||
msr_write(MSR_C_STATE_LATENCY_CONTROL_1, msr);
|
||||
|
||||
/* C-state Interrupt Response Latency Control 2 - package C6/C7 short */
|
||||
msr.hi = 0;
|
||||
msr.lo = IRTL_VALID | IRTL_1024_NS | C_STATE_LATENCY_CONTROL_2_LIMIT;
|
||||
msr_write(MSR_C_STATE_LATENCY_CONTROL_2, msr);
|
||||
|
||||
/* C-state Interrupt Response Latency Control 3 - package C8 */
|
||||
msr.hi = 0;
|
||||
msr.lo = IRTL_VALID | IRTL_1024_NS | C_STATE_LATENCY_CONTROL_3_LIMIT;
|
||||
msr_write(MSR_C_STATE_LATENCY_CONTROL_3, msr);
|
||||
|
||||
/* C-state Interrupt Response Latency Control 4 - package C9 */
|
||||
msr.hi = 0;
|
||||
msr.lo = IRTL_VALID | IRTL_1024_NS | C_STATE_LATENCY_CONTROL_4_LIMIT;
|
||||
msr_write(MSR_C_STATE_LATENCY_CONTROL_4, msr);
|
||||
|
||||
/* C-state Interrupt Response Latency Control 5 - package C10 */
|
||||
msr.hi = 0;
|
||||
msr.lo = IRTL_VALID | IRTL_1024_NS | C_STATE_LATENCY_CONTROL_5_LIMIT;
|
||||
msr_write(MSR_C_STATE_LATENCY_CONTROL_5, msr);
|
||||
}
|
||||
|
||||
static void configure_misc(void)
|
||||
{
|
||||
msr_t msr;
|
||||
|
||||
msr = msr_read(MSR_IA32_MISC_ENABLE);
|
||||
msr.lo |= (1 << 0); /* Fast String enable */
|
||||
msr.lo |= (1 << 3); /* TM1/TM2/EMTTM enable */
|
||||
msr.lo |= (1 << 16); /* Enhanced SpeedStep Enable */
|
||||
msr_write(MSR_IA32_MISC_ENABLE, msr);
|
||||
|
||||
/* Disable thermal interrupts */
|
||||
msr.lo = 0;
|
||||
msr.hi = 0;
|
||||
msr_write(MSR_IA32_THERM_INTERRUPT, msr);
|
||||
|
||||
/* Enable package critical interrupt only */
|
||||
msr.lo = 1 << 4;
|
||||
msr.hi = 0;
|
||||
msr_write(MSR_IA32_PACKAGE_THERM_INTERRUPT, msr);
|
||||
}
|
||||
|
||||
static void configure_thermal_target(struct udevice *dev)
|
||||
{
|
||||
int tcc_offset;
|
||||
msr_t msr;
|
||||
|
||||
tcc_offset = fdtdec_get_int(gd->fdt_blob, dev_of_offset(dev),
|
||||
"intel,tcc-offset", 0);
|
||||
|
||||
/* Set TCC activaiton offset if supported */
|
||||
msr = msr_read(MSR_PLATFORM_INFO);
|
||||
if ((msr.lo & (1 << 30)) && tcc_offset) {
|
||||
msr = msr_read(MSR_TEMPERATURE_TARGET);
|
||||
msr.lo &= ~(0xf << 24); /* Bits 27:24 */
|
||||
msr.lo |= (tcc_offset & 0xf) << 24;
|
||||
msr_write(MSR_TEMPERATURE_TARGET, msr);
|
||||
}
|
||||
}
|
||||
|
||||
static void configure_dca_cap(void)
|
||||
{
|
||||
struct cpuid_result cpuid_regs;
|
||||
msr_t msr;
|
||||
|
||||
/* Check feature flag in CPUID.(EAX=1):ECX[18]==1 */
|
||||
cpuid_regs = cpuid(1);
|
||||
if (cpuid_regs.ecx & (1 << 18)) {
|
||||
msr = msr_read(MSR_IA32_PLATFORM_DCA_CAP);
|
||||
msr.lo |= 1;
|
||||
msr_write(MSR_IA32_PLATFORM_DCA_CAP, msr);
|
||||
}
|
||||
}
|
||||
|
||||
static void set_energy_perf_bias(u8 policy)
|
||||
{
|
||||
msr_t msr;
|
||||
int ecx;
|
||||
|
||||
/* Determine if energy efficient policy is supported */
|
||||
ecx = cpuid_ecx(0x6);
|
||||
if (!(ecx & (1 << 3)))
|
||||
return;
|
||||
|
||||
/* Energy Policy is bits 3:0 */
|
||||
msr = msr_read(MSR_IA32_ENERGY_PERFORMANCE_BIAS);
|
||||
msr.lo &= ~0xf;
|
||||
msr.lo |= policy & 0xf;
|
||||
msr_write(MSR_IA32_ENERGY_PERFORMANCE_BIAS, msr);
|
||||
|
||||
debug("cpu: energy policy set to %u\n", policy);
|
||||
}
|
||||
|
||||
/* All CPUs including BSP will run the following function */
|
||||
static void cpu_core_init(struct udevice *dev)
|
||||
{
|
||||
/* Clear out pending MCEs */
|
||||
configure_mca();
|
||||
|
||||
/* Enable the local cpu apics */
|
||||
enable_lapic_tpr();
|
||||
|
||||
/* Configure C States */
|
||||
configure_c_states();
|
||||
|
||||
/* Configure Enhanced SpeedStep and Thermal Sensors */
|
||||
configure_misc();
|
||||
|
||||
/* Thermal throttle activation offset */
|
||||
configure_thermal_target(dev);
|
||||
|
||||
/* Enable Direct Cache Access */
|
||||
configure_dca_cap();
|
||||
|
||||
/* Set energy policy */
|
||||
set_energy_perf_bias(ENERGY_POLICY_NORMAL);
|
||||
|
||||
/* Enable Turbo */
|
||||
turbo_enable();
|
||||
}
|
||||
|
||||
/*
|
||||
* Configure processor power limits if possible
|
||||
* This must be done AFTER set of BIOS_RESET_CPL
|
||||
*/
|
||||
void cpu_set_power_limits(int power_limit_1_time)
|
||||
{
|
||||
msr_t msr;
|
||||
msr_t limit;
|
||||
uint power_unit;
|
||||
uint tdp, min_power, max_power, max_time;
|
||||
u8 power_limit_1_val;
|
||||
|
||||
msr = msr_read(MSR_PLATFORM_INFO);
|
||||
if (power_limit_1_time > ARRAY_SIZE(power_limit_time_sec_to_msr))
|
||||
power_limit_1_time = 28;
|
||||
|
||||
if (!(msr.lo & PLATFORM_INFO_SET_TDP))
|
||||
return;
|
||||
|
||||
/* Get units */
|
||||
msr = msr_read(MSR_PKG_POWER_SKU_UNIT);
|
||||
power_unit = 2 << ((msr.lo & 0xf) - 1);
|
||||
|
||||
/* Get power defaults for this SKU */
|
||||
msr = msr_read(MSR_PKG_POWER_SKU);
|
||||
tdp = msr.lo & 0x7fff;
|
||||
min_power = (msr.lo >> 16) & 0x7fff;
|
||||
max_power = msr.hi & 0x7fff;
|
||||
max_time = (msr.hi >> 16) & 0x7f;
|
||||
|
||||
debug("CPU TDP: %u Watts\n", tdp / power_unit);
|
||||
|
||||
if (power_limit_time_msr_to_sec[max_time] > power_limit_1_time)
|
||||
power_limit_1_time = power_limit_time_msr_to_sec[max_time];
|
||||
|
||||
if (min_power > 0 && tdp < min_power)
|
||||
tdp = min_power;
|
||||
|
||||
if (max_power > 0 && tdp > max_power)
|
||||
tdp = max_power;
|
||||
|
||||
power_limit_1_val = power_limit_time_sec_to_msr[power_limit_1_time];
|
||||
|
||||
/* Set long term power limit to TDP */
|
||||
limit.lo = 0;
|
||||
limit.lo |= tdp & PKG_POWER_LIMIT_MASK;
|
||||
limit.lo |= PKG_POWER_LIMIT_EN;
|
||||
limit.lo |= (power_limit_1_val & PKG_POWER_LIMIT_TIME_MASK) <<
|
||||
PKG_POWER_LIMIT_TIME_SHIFT;
|
||||
|
||||
/* Set short term power limit to 1.25 * TDP */
|
||||
limit.hi = 0;
|
||||
limit.hi |= ((tdp * 125) / 100) & PKG_POWER_LIMIT_MASK;
|
||||
limit.hi |= PKG_POWER_LIMIT_EN;
|
||||
/* Power limit 2 time is only programmable on server SKU */
|
||||
|
||||
msr_write(MSR_PKG_POWER_LIMIT, limit);
|
||||
|
||||
/* Set power limit values in MCHBAR as well */
|
||||
writel(limit.lo, MCHBAR_REG(MCH_PKG_POWER_LIMIT_LO));
|
||||
writel(limit.hi, MCHBAR_REG(MCH_PKG_POWER_LIMIT_HI));
|
||||
|
||||
/* Set DDR RAPL power limit by copying from MMIO to MSR */
|
||||
msr.lo = readl(MCHBAR_REG(MCH_DDR_POWER_LIMIT_LO));
|
||||
msr.hi = readl(MCHBAR_REG(MCH_DDR_POWER_LIMIT_HI));
|
||||
msr_write(MSR_DDR_RAPL_LIMIT, msr);
|
||||
|
||||
/* Use nominal TDP values for CPUs with configurable TDP */
|
||||
if (cpu_config_tdp_levels()) {
|
||||
msr = msr_read(MSR_CONFIG_TDP_NOMINAL);
|
||||
limit.hi = 0;
|
||||
limit.lo = msr.lo & 0xff;
|
||||
msr_write(MSR_TURBO_ACTIVATION_RATIO, limit);
|
||||
}
|
||||
}
|
||||
|
||||
static int broadwell_get_info(struct udevice *dev, struct cpu_info *info)
|
||||
{
|
||||
msr_t msr;
|
||||
|
||||
msr = msr_read(IA32_PERF_CTL);
|
||||
info->cpu_freq = ((msr.lo >> 8) & 0xff) * BROADWELL_BCLK * 1000000;
|
||||
info->features = 1 << CPU_FEAT_L1_CACHE | 1 << CPU_FEAT_MMU |
|
||||
1 << CPU_FEAT_UCODE | 1 << CPU_FEAT_DEVICE_ID;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int broadwell_get_count(struct udevice *dev)
|
||||
{
|
||||
return 4;
|
||||
}
|
||||
|
||||
static int cpu_x86_broadwell_probe(struct udevice *dev)
|
||||
{
|
||||
if (dev->seq == 0) {
|
||||
cpu_core_init(dev);
|
||||
return broadwell_init(dev);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct cpu_ops cpu_x86_broadwell_ops = {
|
||||
.get_desc = cpu_x86_get_desc,
|
||||
.get_info = broadwell_get_info,
|
||||
.get_count = broadwell_get_count,
|
||||
.get_vendor = cpu_x86_get_vendor,
|
||||
};
|
||||
|
||||
static const struct udevice_id cpu_x86_broadwell_ids[] = {
|
||||
{ .compatible = "intel,core-i3-gen5" },
|
||||
{ }
|
||||
};
|
||||
|
||||
U_BOOT_DRIVER(cpu_x86_broadwell_drv) = {
|
||||
.name = "cpu_x86_broadwell",
|
||||
.id = UCLASS_CPU,
|
||||
.of_match = cpu_x86_broadwell_ids,
|
||||
.bind = cpu_x86_bind,
|
||||
.probe = cpu_x86_broadwell_probe,
|
||||
.ops = &cpu_x86_broadwell_ops,
|
||||
.priv_auto_alloc_size = sizeof(struct cpu_broadwell_priv),
|
||||
.flags = DM_FLAG_PRE_RELOC,
|
||||
};
|
@ -6,8 +6,108 @@
|
||||
#include <common.h>
|
||||
#include <dm.h>
|
||||
#include <asm/io.h>
|
||||
#include <asm/mrc_common.h>
|
||||
#include <asm/arch/iomap.h>
|
||||
#include <asm/arch/pch.h>
|
||||
#include <asm/arch/pei_data.h>
|
||||
|
||||
__weak asmlinkage void sdram_console_tx_byte(unsigned char byte)
|
||||
{
|
||||
#ifdef DEBUG
|
||||
putc(byte);
|
||||
#endif
|
||||
}
|
||||
|
||||
void broadwell_fill_pei_data(struct pei_data *pei_data)
|
||||
{
|
||||
pei_data->pei_version = PEI_VERSION;
|
||||
pei_data->board_type = BOARD_TYPE_ULT;
|
||||
pei_data->pciexbar = MCFG_BASE_ADDRESS;
|
||||
pei_data->smbusbar = SMBUS_BASE_ADDRESS;
|
||||
pei_data->ehcibar = EARLY_EHCI_BAR;
|
||||
pei_data->xhcibar = EARLY_XHCI_BAR;
|
||||
pei_data->gttbar = EARLY_GTT_BAR;
|
||||
pei_data->pmbase = ACPI_BASE_ADDRESS;
|
||||
pei_data->gpiobase = GPIO_BASE_ADDRESS;
|
||||
pei_data->tseg_size = CONFIG_SMM_TSEG_SIZE;
|
||||
pei_data->temp_mmio_base = EARLY_TEMP_MMIO;
|
||||
pei_data->tx_byte = sdram_console_tx_byte;
|
||||
pei_data->ddr_refresh_2x = 1;
|
||||
}
|
||||
|
||||
static void pei_data_usb2_port(struct pei_data *pei_data, int port, uint length,
|
||||
uint enable, uint oc_pin, uint location)
|
||||
{
|
||||
pei_data->usb2_ports[port].length = length;
|
||||
pei_data->usb2_ports[port].enable = enable;
|
||||
pei_data->usb2_ports[port].oc_pin = oc_pin;
|
||||
pei_data->usb2_ports[port].location = location;
|
||||
}
|
||||
|
||||
static void pei_data_usb3_port(struct pei_data *pei_data, int port, uint enable,
|
||||
uint oc_pin, uint fixed_eq)
|
||||
{
|
||||
pei_data->usb3_ports[port].enable = enable;
|
||||
pei_data->usb3_ports[port].oc_pin = oc_pin;
|
||||
pei_data->usb3_ports[port].fixed_eq = fixed_eq;
|
||||
}
|
||||
|
||||
void mainboard_fill_pei_data(struct pei_data *pei_data)
|
||||
{
|
||||
/* DQ byte map for Samus board */
|
||||
const u8 dq_map[2][6][2] = {
|
||||
{ { 0x0F, 0xF0 }, { 0x00, 0xF0 }, { 0x0F, 0xF0 },
|
||||
{ 0x0F, 0x00 }, { 0xFF, 0x00 }, { 0xFF, 0x00 } },
|
||||
{ { 0x0F, 0xF0 }, { 0x00, 0xF0 }, { 0x0F, 0xF0 },
|
||||
{ 0x0F, 0x00 }, { 0xFF, 0x00 }, { 0xFF, 0x00 } } };
|
||||
/* DQS CPU<>DRAM map for Samus board */
|
||||
const u8 dqs_map[2][8] = {
|
||||
{ 2, 0, 1, 3, 6, 4, 7, 5 },
|
||||
{ 2, 1, 0, 3, 6, 5, 4, 7 } };
|
||||
|
||||
pei_data->ec_present = 1;
|
||||
|
||||
/* One installed DIMM per channel */
|
||||
pei_data->dimm_channel0_disabled = 2;
|
||||
pei_data->dimm_channel1_disabled = 2;
|
||||
|
||||
memcpy(pei_data->dq_map, dq_map, sizeof(dq_map));
|
||||
memcpy(pei_data->dqs_map, dqs_map, sizeof(dqs_map));
|
||||
|
||||
/* P0: HOST PORT */
|
||||
pei_data_usb2_port(pei_data, 0, 0x0080, 1, 0,
|
||||
USB_PORT_BACK_PANEL);
|
||||
/* P1: HOST PORT */
|
||||
pei_data_usb2_port(pei_data, 1, 0x0080, 1, 1,
|
||||
USB_PORT_BACK_PANEL);
|
||||
/* P2: RAIDEN */
|
||||
pei_data_usb2_port(pei_data, 2, 0x0080, 1, USB_OC_PIN_SKIP,
|
||||
USB_PORT_BACK_PANEL);
|
||||
/* P3: SD CARD */
|
||||
pei_data_usb2_port(pei_data, 3, 0x0040, 1, USB_OC_PIN_SKIP,
|
||||
USB_PORT_INTERNAL);
|
||||
/* P4: RAIDEN */
|
||||
pei_data_usb2_port(pei_data, 4, 0x0080, 1, USB_OC_PIN_SKIP,
|
||||
USB_PORT_BACK_PANEL);
|
||||
/* P5: WWAN (Disabled) */
|
||||
pei_data_usb2_port(pei_data, 5, 0x0000, 0, USB_OC_PIN_SKIP,
|
||||
USB_PORT_SKIP);
|
||||
/* P6: CAMERA */
|
||||
pei_data_usb2_port(pei_data, 6, 0x0040, 1, USB_OC_PIN_SKIP,
|
||||
USB_PORT_INTERNAL);
|
||||
/* P7: BT */
|
||||
pei_data_usb2_port(pei_data, 7, 0x0040, 1, USB_OC_PIN_SKIP,
|
||||
USB_PORT_INTERNAL);
|
||||
|
||||
/* P1: HOST PORT */
|
||||
pei_data_usb3_port(pei_data, 0, 1, 0, 0);
|
||||
/* P2: HOST PORT */
|
||||
pei_data_usb3_port(pei_data, 1, 1, 1, 0);
|
||||
/* P3: RAIDEN */
|
||||
pei_data_usb3_port(pei_data, 2, 1, USB_OC_PIN_SKIP, 0);
|
||||
/* P4: RAIDEN */
|
||||
pei_data_usb3_port(pei_data, 3, 1, USB_OC_PIN_SKIP, 0);
|
||||
}
|
||||
|
||||
static int broadwell_northbridge_early_init(struct udevice *dev)
|
||||
{
|
||||
|
@ -599,10 +599,16 @@ static int broadwell_pch_init(struct udevice *dev)
|
||||
|
||||
static int broadwell_pch_probe(struct udevice *dev)
|
||||
{
|
||||
if (!(gd->flags & GD_FLG_RELOC))
|
||||
return broadwell_pch_early_init(dev);
|
||||
else
|
||||
if (CONFIG_IS_ENABLED(X86_32BIT_INIT)) {
|
||||
if (!(gd->flags & GD_FLG_RELOC))
|
||||
return broadwell_pch_early_init(dev);
|
||||
else
|
||||
return broadwell_pch_init(dev);
|
||||
} else if (IS_ENABLED(CONFIG_SPL) && !IS_ENABLED(CONFIG_SPL_BUILD)) {
|
||||
return broadwell_pch_init(dev);
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
static int broadwell_pch_get_spi_base(struct udevice *dev, ulong *sbasep)
|
||||
@ -630,10 +636,35 @@ static int broadwell_get_gpio_base(struct udevice *dev, u32 *gbasep)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int broadwell_ioctl(struct udevice *dev, enum pch_req_t req, void *data,
|
||||
int size)
|
||||
{
|
||||
switch (req) {
|
||||
case PCH_REQ_PMBASE_INFO: {
|
||||
struct pch_pmbase_info *pm = data;
|
||||
int ret;
|
||||
|
||||
/* Find the base address of the powermanagement registers */
|
||||
ret = dm_pci_read_config16(dev, 0x40, &pm->base);
|
||||
if (ret)
|
||||
return ret;
|
||||
pm->base &= 0xfffe;
|
||||
pm->gpio0_en_ofs = GPE0_EN(0);
|
||||
pm->pm1_sts_ofs = PM1_STS;
|
||||
pm->pm1_cnt_ofs = PM1_CNT;
|
||||
|
||||
return 0;
|
||||
}
|
||||
default:
|
||||
return -ENOSYS;
|
||||
}
|
||||
}
|
||||
|
||||
static const struct pch_ops broadwell_pch_ops = {
|
||||
.get_spi_base = broadwell_pch_get_spi_base,
|
||||
.set_spi_protect = broadwell_set_spi_protect,
|
||||
.get_gpio_base = broadwell_get_gpio_base,
|
||||
.ioctl = broadwell_ioctl,
|
||||
};
|
||||
|
||||
static const struct udevice_id broadwell_pch_ids[] = {
|
||||
|
@ -34,99 +34,6 @@ int dram_init_banksize(void)
|
||||
return 0;
|
||||
}
|
||||
|
||||
void broadwell_fill_pei_data(struct pei_data *pei_data)
|
||||
{
|
||||
pei_data->pei_version = PEI_VERSION;
|
||||
pei_data->board_type = BOARD_TYPE_ULT;
|
||||
pei_data->pciexbar = MCFG_BASE_ADDRESS;
|
||||
pei_data->smbusbar = SMBUS_BASE_ADDRESS;
|
||||
pei_data->ehcibar = EARLY_EHCI_BAR;
|
||||
pei_data->xhcibar = EARLY_XHCI_BAR;
|
||||
pei_data->gttbar = EARLY_GTT_BAR;
|
||||
pei_data->pmbase = ACPI_BASE_ADDRESS;
|
||||
pei_data->gpiobase = GPIO_BASE_ADDRESS;
|
||||
pei_data->tseg_size = CONFIG_SMM_TSEG_SIZE;
|
||||
pei_data->temp_mmio_base = EARLY_TEMP_MMIO;
|
||||
pei_data->tx_byte = sdram_console_tx_byte;
|
||||
pei_data->ddr_refresh_2x = 1;
|
||||
}
|
||||
|
||||
static inline void pei_data_usb2_port(struct pei_data *pei_data, int port,
|
||||
uint16_t length, uint8_t enable,
|
||||
uint8_t oc_pin, uint8_t location)
|
||||
{
|
||||
pei_data->usb2_ports[port].length = length;
|
||||
pei_data->usb2_ports[port].enable = enable;
|
||||
pei_data->usb2_ports[port].oc_pin = oc_pin;
|
||||
pei_data->usb2_ports[port].location = location;
|
||||
}
|
||||
|
||||
static inline void pei_data_usb3_port(struct pei_data *pei_data, int port,
|
||||
uint8_t enable, uint8_t oc_pin,
|
||||
uint8_t fixed_eq)
|
||||
{
|
||||
pei_data->usb3_ports[port].enable = enable;
|
||||
pei_data->usb3_ports[port].oc_pin = oc_pin;
|
||||
pei_data->usb3_ports[port].fixed_eq = fixed_eq;
|
||||
}
|
||||
|
||||
void mainboard_fill_pei_data(struct pei_data *pei_data)
|
||||
{
|
||||
/* DQ byte map for Samus board */
|
||||
const u8 dq_map[2][6][2] = {
|
||||
{ { 0x0F, 0xF0 }, { 0x00, 0xF0 }, { 0x0F, 0xF0 },
|
||||
{ 0x0F, 0x00 }, { 0xFF, 0x00 }, { 0xFF, 0x00 } },
|
||||
{ { 0x0F, 0xF0 }, { 0x00, 0xF0 }, { 0x0F, 0xF0 },
|
||||
{ 0x0F, 0x00 }, { 0xFF, 0x00 }, { 0xFF, 0x00 } } };
|
||||
/* DQS CPU<>DRAM map for Samus board */
|
||||
const u8 dqs_map[2][8] = {
|
||||
{ 2, 0, 1, 3, 6, 4, 7, 5 },
|
||||
{ 2, 1, 0, 3, 6, 5, 4, 7 } };
|
||||
|
||||
pei_data->ec_present = 1;
|
||||
|
||||
/* One installed DIMM per channel */
|
||||
pei_data->dimm_channel0_disabled = 2;
|
||||
pei_data->dimm_channel1_disabled = 2;
|
||||
|
||||
memcpy(pei_data->dq_map, dq_map, sizeof(dq_map));
|
||||
memcpy(pei_data->dqs_map, dqs_map, sizeof(dqs_map));
|
||||
|
||||
/* P0: HOST PORT */
|
||||
pei_data_usb2_port(pei_data, 0, 0x0080, 1, 0,
|
||||
USB_PORT_BACK_PANEL);
|
||||
/* P1: HOST PORT */
|
||||
pei_data_usb2_port(pei_data, 1, 0x0080, 1, 1,
|
||||
USB_PORT_BACK_PANEL);
|
||||
/* P2: RAIDEN */
|
||||
pei_data_usb2_port(pei_data, 2, 0x0080, 1, USB_OC_PIN_SKIP,
|
||||
USB_PORT_BACK_PANEL);
|
||||
/* P3: SD CARD */
|
||||
pei_data_usb2_port(pei_data, 3, 0x0040, 1, USB_OC_PIN_SKIP,
|
||||
USB_PORT_INTERNAL);
|
||||
/* P4: RAIDEN */
|
||||
pei_data_usb2_port(pei_data, 4, 0x0080, 1, USB_OC_PIN_SKIP,
|
||||
USB_PORT_BACK_PANEL);
|
||||
/* P5: WWAN (Disabled) */
|
||||
pei_data_usb2_port(pei_data, 5, 0x0000, 0, USB_OC_PIN_SKIP,
|
||||
USB_PORT_SKIP);
|
||||
/* P6: CAMERA */
|
||||
pei_data_usb2_port(pei_data, 6, 0x0040, 1, USB_OC_PIN_SKIP,
|
||||
USB_PORT_INTERNAL);
|
||||
/* P7: BT */
|
||||
pei_data_usb2_port(pei_data, 7, 0x0040, 1, USB_OC_PIN_SKIP,
|
||||
USB_PORT_INTERNAL);
|
||||
|
||||
/* P1: HOST PORT */
|
||||
pei_data_usb3_port(pei_data, 0, 1, 0, 0);
|
||||
/* P2: HOST PORT */
|
||||
pei_data_usb3_port(pei_data, 1, 1, 1, 0);
|
||||
/* P3: RAIDEN */
|
||||
pei_data_usb3_port(pei_data, 2, 1, USB_OC_PIN_SKIP, 0);
|
||||
/* P4: RAIDEN */
|
||||
pei_data_usb3_port(pei_data, 3, 1, USB_OC_PIN_SKIP, 0);
|
||||
}
|
||||
|
||||
static unsigned long get_top_of_ram(struct udevice *dev)
|
||||
{
|
||||
/*
|
||||
@ -204,16 +111,18 @@ int dram_init(void)
|
||||
|
||||
/* Print ME state before MRC */
|
||||
ret = syscon_get_by_driver_data(X86_SYSCON_ME, &me_dev);
|
||||
if (ret)
|
||||
if (ret) {
|
||||
debug("Cannot get ME (err=%d)\n", ret);
|
||||
return ret;
|
||||
}
|
||||
intel_me_status(me_dev);
|
||||
|
||||
/* Save ME HSIO version */
|
||||
ret = uclass_first_device(UCLASS_PCH, &pch_dev);
|
||||
if (ret)
|
||||
ret = uclass_first_device_err(UCLASS_PCH, &pch_dev);
|
||||
if (ret) {
|
||||
debug("Cannot get PCH (err=%d)\n", ret);
|
||||
return ret;
|
||||
if (!pch_dev)
|
||||
return -ENODEV;
|
||||
}
|
||||
power_state_get(pch_dev, &ps);
|
||||
|
||||
intel_me_hsio_version(me_dev, &ps.hsio_version, &ps.hsio_checksum);
|
||||
@ -221,15 +130,17 @@ int dram_init(void)
|
||||
broadwell_fill_pei_data(pei_data);
|
||||
mainboard_fill_pei_data(pei_data);
|
||||
|
||||
ret = uclass_first_device(UCLASS_NORTHBRIDGE, &dev);
|
||||
if (ret)
|
||||
ret = uclass_first_device_err(UCLASS_NORTHBRIDGE, &dev);
|
||||
if (ret) {
|
||||
debug("Cannot get Northbridge (err=%d)\n", ret);
|
||||
return ret;
|
||||
if (!dev)
|
||||
return -ENODEV;
|
||||
}
|
||||
size = 256;
|
||||
ret = mrc_locate_spd(dev, size, &spd_data);
|
||||
if (ret)
|
||||
if (ret) {
|
||||
debug("Cannot locate SPD (err=%d)\n", ret);
|
||||
return ret;
|
||||
}
|
||||
memcpy(pei_data->spd_data[0][0], spd_data, size);
|
||||
memcpy(pei_data->spd_data[1][0], spd_data, size);
|
||||
|
||||
@ -239,13 +150,17 @@ int dram_init(void)
|
||||
|
||||
debug("PEI version %#x\n", pei_data->pei_version);
|
||||
ret = mrc_common_init(dev, pei_data, true);
|
||||
if (ret)
|
||||
if (ret) {
|
||||
debug("mrc_common_init() failed(err=%d)\n", ret);
|
||||
return ret;
|
||||
}
|
||||
debug("Memory init done\n");
|
||||
|
||||
ret = sdram_find(dev);
|
||||
if (ret)
|
||||
if (ret) {
|
||||
debug("sdram_find() failed (err=%d)\n", ret);
|
||||
return ret;
|
||||
}
|
||||
gd->ram_size = gd->arch.meminfo.total_32bit_memory;
|
||||
debug("RAM size %llx\n", (unsigned long long)gd->ram_size);
|
||||
|
||||
@ -279,17 +194,6 @@ int misc_init_r(void)
|
||||
return 0;
|
||||
}
|
||||
|
||||
void board_debug_uart_init(void)
|
||||
{
|
||||
struct udevice *bus = NULL;
|
||||
|
||||
/* com1 / com2 decode range */
|
||||
pci_x86_write_config(bus, PCH_DEV_LPC, LPC_IO_DEC, 1 << 4, PCI_SIZE_16);
|
||||
|
||||
pci_x86_write_config(bus, PCH_DEV_LPC, LPC_EN, COMA_LPC_EN,
|
||||
PCI_SIZE_16);
|
||||
}
|
||||
|
||||
static const struct udevice_id broadwell_syscon_ids[] = {
|
||||
{ .compatible = "intel,me", .data = X86_SYSCON_ME },
|
||||
{ }
|
||||
|
@ -309,21 +309,22 @@ u32 cpu_get_stepping(void)
|
||||
return gd->arch.x86_mask;
|
||||
}
|
||||
|
||||
int x86_cpu_init_f(void)
|
||||
/* initialise FPU, reset EM, set MP and NE */
|
||||
static void setup_cpu_features(void)
|
||||
{
|
||||
const u32 em_rst = ~X86_CR0_EM;
|
||||
const u32 mp_ne_set = X86_CR0_MP | X86_CR0_NE;
|
||||
|
||||
if (ll_boot_init()) {
|
||||
/* initialize FPU, reset EM, set MP and NE */
|
||||
asm ("fninit\n" \
|
||||
"movl %%cr0, %%eax\n" \
|
||||
"andl %0, %%eax\n" \
|
||||
"orl %1, %%eax\n" \
|
||||
"movl %%eax, %%cr0\n" \
|
||||
: : "i" (em_rst), "i" (mp_ne_set) : "eax");
|
||||
}
|
||||
asm ("fninit\n" \
|
||||
"movl %%cr0, %%eax\n" \
|
||||
"andl %0, %%eax\n" \
|
||||
"orl %1, %%eax\n" \
|
||||
"movl %%eax, %%cr0\n" \
|
||||
: : "i" (em_rst), "i" (mp_ne_set) : "eax");
|
||||
}
|
||||
|
||||
static void setup_identity(void)
|
||||
{
|
||||
/* identify CPU via cpuid and store the decoded info into gd->arch */
|
||||
if (has_cpuid()) {
|
||||
struct cpu_device_id cpu;
|
||||
@ -339,46 +340,70 @@ int x86_cpu_init_f(void)
|
||||
|
||||
gd->arch.has_mtrr = has_mtrr();
|
||||
}
|
||||
/* Don't allow PCI region 3 to use memory in the 2-4GB memory hole */
|
||||
}
|
||||
|
||||
/* Don't allow PCI region 3 to use memory in the 2-4GB memory hole */
|
||||
static void setup_pci_ram_top(void)
|
||||
{
|
||||
gd->pci_ram_top = 0x80000000U;
|
||||
}
|
||||
|
||||
static void setup_mtrr(void)
|
||||
{
|
||||
u64 mtrr_cap;
|
||||
|
||||
/* Configure fixed range MTRRs for some legacy regions */
|
||||
if (gd->arch.has_mtrr) {
|
||||
u64 mtrr_cap;
|
||||
if (!gd->arch.has_mtrr)
|
||||
return;
|
||||
|
||||
mtrr_cap = native_read_msr(MTRR_CAP_MSR);
|
||||
if (mtrr_cap & MTRR_CAP_FIX) {
|
||||
/* Mark the VGA RAM area as uncacheable */
|
||||
native_write_msr(MTRR_FIX_16K_A0000_MSR,
|
||||
MTRR_FIX_TYPE(MTRR_TYPE_UNCACHEABLE),
|
||||
MTRR_FIX_TYPE(MTRR_TYPE_UNCACHEABLE));
|
||||
mtrr_cap = native_read_msr(MTRR_CAP_MSR);
|
||||
if (mtrr_cap & MTRR_CAP_FIX) {
|
||||
/* Mark the VGA RAM area as uncacheable */
|
||||
native_write_msr(MTRR_FIX_16K_A0000_MSR,
|
||||
MTRR_FIX_TYPE(MTRR_TYPE_UNCACHEABLE),
|
||||
MTRR_FIX_TYPE(MTRR_TYPE_UNCACHEABLE));
|
||||
|
||||
/*
|
||||
* Mark the PCI ROM area as cacheable to improve ROM
|
||||
* execution performance.
|
||||
*/
|
||||
native_write_msr(MTRR_FIX_4K_C0000_MSR,
|
||||
MTRR_FIX_TYPE(MTRR_TYPE_WRBACK),
|
||||
MTRR_FIX_TYPE(MTRR_TYPE_WRBACK));
|
||||
native_write_msr(MTRR_FIX_4K_C8000_MSR,
|
||||
MTRR_FIX_TYPE(MTRR_TYPE_WRBACK),
|
||||
MTRR_FIX_TYPE(MTRR_TYPE_WRBACK));
|
||||
native_write_msr(MTRR_FIX_4K_D0000_MSR,
|
||||
MTRR_FIX_TYPE(MTRR_TYPE_WRBACK),
|
||||
MTRR_FIX_TYPE(MTRR_TYPE_WRBACK));
|
||||
native_write_msr(MTRR_FIX_4K_D8000_MSR,
|
||||
MTRR_FIX_TYPE(MTRR_TYPE_WRBACK),
|
||||
MTRR_FIX_TYPE(MTRR_TYPE_WRBACK));
|
||||
/*
|
||||
* Mark the PCI ROM area as cacheable to improve ROM
|
||||
* execution performance.
|
||||
*/
|
||||
native_write_msr(MTRR_FIX_4K_C0000_MSR,
|
||||
MTRR_FIX_TYPE(MTRR_TYPE_WRBACK),
|
||||
MTRR_FIX_TYPE(MTRR_TYPE_WRBACK));
|
||||
native_write_msr(MTRR_FIX_4K_C8000_MSR,
|
||||
MTRR_FIX_TYPE(MTRR_TYPE_WRBACK),
|
||||
MTRR_FIX_TYPE(MTRR_TYPE_WRBACK));
|
||||
native_write_msr(MTRR_FIX_4K_D0000_MSR,
|
||||
MTRR_FIX_TYPE(MTRR_TYPE_WRBACK),
|
||||
MTRR_FIX_TYPE(MTRR_TYPE_WRBACK));
|
||||
native_write_msr(MTRR_FIX_4K_D8000_MSR,
|
||||
MTRR_FIX_TYPE(MTRR_TYPE_WRBACK),
|
||||
MTRR_FIX_TYPE(MTRR_TYPE_WRBACK));
|
||||
|
||||
/* Enable the fixed range MTRRs */
|
||||
msr_setbits_64(MTRR_DEF_TYPE_MSR, MTRR_DEF_TYPE_FIX_EN);
|
||||
}
|
||||
/* Enable the fixed range MTRRs */
|
||||
msr_setbits_64(MTRR_DEF_TYPE_MSR, MTRR_DEF_TYPE_FIX_EN);
|
||||
}
|
||||
}
|
||||
|
||||
int x86_cpu_init_f(void)
|
||||
{
|
||||
if (ll_boot_init())
|
||||
setup_cpu_features();
|
||||
setup_identity();
|
||||
setup_mtrr();
|
||||
setup_pci_ram_top();
|
||||
|
||||
#ifdef CONFIG_I8254_TIMER
|
||||
/* Set up the i8254 timer if required */
|
||||
i8254_init();
|
||||
#endif
|
||||
if (IS_ENABLED(CONFIG_I8254_TIMER))
|
||||
i8254_init();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int x86_cpu_reinit_f(void)
|
||||
{
|
||||
setup_identity();
|
||||
setup_pci_ram_top();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -3,14 +3,23 @@
|
||||
# Copyright (c) 2016 Google, Inc
|
||||
|
||||
ifdef CONFIG_HAVE_MRC
|
||||
obj-$(CONFIG_$(SPL_)X86_32BIT_INIT) += car.o
|
||||
obj-$(CONFIG_$(SPL_)X86_32BIT_INIT) += me_status.o
|
||||
obj-$(CONFIG_$(SPL_)X86_32BIT_INIT) += report_platform.o
|
||||
obj-$(CONFIG_$(SPL_)X86_32BIT_INIT) += mrc.o
|
||||
obj-$(CONFIG_$(SPL_TPL_)X86_16BIT_INIT) += car.o
|
||||
obj-$(CONFIG_$(SPL_TPL_)X86_32BIT_INIT) += me_status.o
|
||||
obj-$(CONFIG_$(SPL_TPL_)X86_32BIT_INIT) += report_platform.o
|
||||
obj-$(CONFIG_$(SPL_TPL_)X86_32BIT_INIT) += mrc.o
|
||||
endif
|
||||
obj-y += cpu.o
|
||||
obj-y += lpc.o
|
||||
ifndef CONFIG_TARGET_EFI_APP
|
||||
obj-$(CONFIG_$(SPL_TPL_)X86_32BIT_INIT) += microcode.o
|
||||
ifndef CONFIG_$(SPL_)X86_64
|
||||
obj-y += microcode.o
|
||||
endif
|
||||
endif
|
||||
obj-y += pch.o
|
||||
|
||||
ifdef CONFIG_SPL
|
||||
ifndef CONFIG_SPL_BUILD
|
||||
obj-y += cpu_from_spl.o
|
||||
endif
|
||||
endif
|
||||
|
@ -235,7 +235,7 @@ mtrr_table_end:
|
||||
|
||||
.align 4
|
||||
_dt_ucode_base_size:
|
||||
/* These next two fields are filled in by ifdtool */
|
||||
/* These next two fields are filled in by binman */
|
||||
.globl ucode_base
|
||||
ucode_base: /* Declared in microcode.h */
|
||||
.long 0 /* microcode base */
|
||||
|
27
arch/x86/cpu/intel_common/cpu_from_spl.c
Normal file
27
arch/x86/cpu/intel_common/cpu_from_spl.c
Normal file
@ -0,0 +1,27 @@
|
||||
// SPDX-License-Identifier: GPL-2.0
|
||||
/*
|
||||
* Copyright (c) 2016 Google, Inc
|
||||
*/
|
||||
|
||||
#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;
|
||||
|
||||
int arch_cpu_init(void)
|
||||
{
|
||||
int ret;
|
||||
|
||||
ret = x86_cpu_reinit_f();
|
||||
|
||||
return ret;
|
||||
}
|
@ -229,6 +229,21 @@ static int bd82x6x_ioctl(struct udevice *dev, enum pch_req_t req, void *data,
|
||||
return -ENOENT;
|
||||
|
||||
return val & RCBA_AUDIO_CONFIG_MASK;
|
||||
case PCH_REQ_PMBASE_INFO: {
|
||||
struct pch_pmbase_info *pm = data;
|
||||
int ret;
|
||||
|
||||
/* Find the base address of the powermanagement registers */
|
||||
ret = dm_pci_read_config16(dev, 0x40, &pm->base);
|
||||
if (ret)
|
||||
return ret;
|
||||
pm->base &= 0xfffe;
|
||||
pm->gpio0_en_ofs = GPE0_EN;
|
||||
pm->pm1_sts_ofs = PM1_STS;
|
||||
pm->pm1_cnt_ofs = PM1_CNT;
|
||||
|
||||
return 0;
|
||||
}
|
||||
default:
|
||||
return -ENOSYS;
|
||||
}
|
||||
|
@ -322,7 +322,7 @@ static int start_aps(int ap_count, atomic_t *num_aps)
|
||||
if (sipi_vector > max_vector_loc) {
|
||||
printf("SIPI vector too large! 0x%08x\n",
|
||||
sipi_vector);
|
||||
return -1;
|
||||
return -ENOSPC;
|
||||
}
|
||||
|
||||
debug("Attempting to start %d APs\n", ap_count);
|
||||
@ -364,7 +364,7 @@ static int start_aps(int ap_count, atomic_t *num_aps)
|
||||
if (wait_for_aps(num_aps, ap_count, 10000, 50)) {
|
||||
debug("Not all APs checked in: %d/%d\n",
|
||||
atomic_read(num_aps), ap_count);
|
||||
return -1;
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
return 0;
|
||||
@ -387,7 +387,7 @@ static int bsp_do_flight_plan(struct udevice *cpu, struct mp_params *mp_params)
|
||||
if (wait_for_aps(&rec->cpus_entered, num_aps,
|
||||
timeout_us, step_us)) {
|
||||
debug("MP record %d timeout\n", i);
|
||||
ret = -1;
|
||||
ret = -ETIMEDOUT;
|
||||
}
|
||||
}
|
||||
|
||||
@ -508,7 +508,7 @@ int mp_init(struct mp_params *p)
|
||||
|
||||
if (p == NULL || p->flight_plan == NULL || p->num_records < 1) {
|
||||
printf("Invalid MP parameters\n");
|
||||
return -1;
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
num_cpus = cpu_get_count(cpu);
|
||||
@ -531,7 +531,7 @@ int mp_init(struct mp_params *p)
|
||||
/* Load the SIPI vector */
|
||||
ret = load_sipi_vector(&ap_count, num_cpus);
|
||||
if (ap_count == NULL)
|
||||
return -1;
|
||||
return -ENOENT;
|
||||
|
||||
/*
|
||||
* Make sure SIPI data hits RAM so the APs that come up will see
|
||||
|
@ -190,6 +190,19 @@ board_init_f_r_trampoline:
|
||||
/* Re-enter U-Boot by calling board_init_f_r() */
|
||||
call board_init_f_r
|
||||
|
||||
#ifdef CONFIG_TPL
|
||||
.globl jump_to_spl
|
||||
.type jump_to_spl, @function
|
||||
jump_to_spl:
|
||||
/* Reset stack to the top of CAR space */
|
||||
movl $(CONFIG_SYS_CAR_ADDR + CONFIG_SYS_CAR_SIZE - 4), %esp
|
||||
#ifdef CONFIG_DCACHE_RAM_MRC_VAR_SIZE
|
||||
subl $CONFIG_DCACHE_RAM_MRC_VAR_SIZE, %esp
|
||||
#endif
|
||||
|
||||
jmp *%eax
|
||||
#endif
|
||||
|
||||
die:
|
||||
hlt
|
||||
jmp die
|
||||
|
@ -2,7 +2,7 @@
|
||||
/*
|
||||
* 64-bit x86 Startup Code
|
||||
*
|
||||
* (C) Copyright 216 Google, Inc
|
||||
* Copyright 2019 Google, Inc
|
||||
* Written by Simon Glass <sjg@chromium.org>
|
||||
*/
|
||||
|
||||
|
71
arch/x86/cpu/start_from_spl.S
Normal file
71
arch/x86/cpu/start_from_spl.S
Normal file
@ -0,0 +1,71 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0+ */
|
||||
/*
|
||||
* 32-bit x86 Startup Code when running from SPL
|
||||
*
|
||||
* Copyright 2018 Google, Inc
|
||||
* Written by Simon Glass <sjg@chromium.org>
|
||||
*/
|
||||
|
||||
#include <config.h>
|
||||
|
||||
.section .text.start
|
||||
.code32
|
||||
.globl _start
|
||||
.type _start, @function
|
||||
_start:
|
||||
/* Set up memory using the existing stack */
|
||||
movl $(CONFIG_SYS_CAR_ADDR + CONFIG_SYS_CAR_SIZE - 4), %eax
|
||||
#ifdef CONFIG_DCACHE_RAM_MRC_VAR_SIZE
|
||||
subl $CONFIG_DCACHE_RAM_MRC_VAR_SIZE, %eax
|
||||
#endif
|
||||
/*
|
||||
* We don't subject CONFIG_DCACHE_RAM_MRC_VAR_SIZE since memory is
|
||||
* already set up. This has the happy side-effect of putting gd in a
|
||||
* new place separate from SPL, so the memset() in
|
||||
* board_init_f_init_reserve() does not cause any problems (otherwise
|
||||
* it would zero out the gd and crash)
|
||||
*/
|
||||
call board_init_f_alloc_reserve
|
||||
mov %eax, %esp
|
||||
|
||||
call board_init_f_init_reserve
|
||||
|
||||
xorl %eax, %eax
|
||||
call board_init_f
|
||||
call board_init_f_r
|
||||
|
||||
/* Should not return here */
|
||||
jmp .
|
||||
|
||||
.globl board_init_f_r_trampoline
|
||||
.type board_init_f_r_trampoline, @function
|
||||
board_init_f_r_trampoline:
|
||||
/*
|
||||
* SPL has been executed and SDRAM has been initialised, U-Boot code
|
||||
* has been copied into RAM, BSS has been cleared and relocation
|
||||
* adjustments have been made. It is now time to jump into the in-RAM
|
||||
* copy of U-Boot
|
||||
*
|
||||
* %eax = Address of top of new stack
|
||||
*/
|
||||
|
||||
/* Stack grows down from top of SDRAM */
|
||||
movl %eax, %esp
|
||||
|
||||
/* Re-enter U-Boot by calling board_init_f_r() */
|
||||
call board_init_f_r
|
||||
|
||||
die:
|
||||
hlt
|
||||
jmp die
|
||||
hlt
|
||||
|
||||
.align 4
|
||||
_dt_ucode_base_size:
|
||||
/* These next two fields are filled in by binman */
|
||||
.globl ucode_base
|
||||
ucode_base: /* Declared in microcode.h */
|
||||
.long 0 /* microcode base */
|
||||
.globl ucode_size
|
||||
ucode_size: /* Declared in microcode.h */
|
||||
.long 0 /* microcode size */
|
49
arch/x86/cpu/start_from_tpl.S
Normal file
49
arch/x86/cpu/start_from_tpl.S
Normal file
@ -0,0 +1,49 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0+ */
|
||||
/*
|
||||
* 32-bit x86 Startup Code when running from TPL
|
||||
*
|
||||
* Copyright 2018 Google, Inc
|
||||
* Written by Simon Glass <sjg@chromium.org>
|
||||
*/
|
||||
|
||||
#include <config.h>
|
||||
|
||||
.section .text.start
|
||||
.code32
|
||||
.globl _start
|
||||
.type _start, @function
|
||||
_start:
|
||||
/* Set up memory using the existing stack */
|
||||
mov %esp, %eax
|
||||
call board_init_f_alloc_reserve
|
||||
mov %eax, %esp
|
||||
|
||||
call board_init_f_init_reserve
|
||||
|
||||
xorl %eax, %eax
|
||||
call board_init_f
|
||||
call board_init_f_r
|
||||
|
||||
/* Should not return here */
|
||||
jmp .
|
||||
|
||||
.globl board_init_f_r_trampoline
|
||||
.type board_init_f_r_trampoline, @function
|
||||
board_init_f_r_trampoline:
|
||||
/*
|
||||
* TPL has been executed: SDRAM has been initialised, BSS has been
|
||||
* cleared.
|
||||
*
|
||||
* %eax = Address of top of new stack
|
||||
*/
|
||||
|
||||
/* Stack grows down from top of SDRAM */
|
||||
movl %eax, %esp
|
||||
|
||||
/* Re-enter SPL by calling board_init_f_r() */
|
||||
call board_init_f_r
|
||||
|
||||
die:
|
||||
hlt
|
||||
jmp die
|
||||
hlt
|
@ -54,7 +54,7 @@ SECTIONS
|
||||
/DISCARD/ : { *(.interp*) }
|
||||
/DISCARD/ : { *(.gnu*) }
|
||||
|
||||
#ifdef CONFIG_SPL_X86_16BIT_INIT
|
||||
#if defined(CONFIG_SPL_X86_16BIT_INIT) || defined(CONFIG_TPL_X86_16BIT_INIT)
|
||||
/*
|
||||
* The following expressions place the 16-bit Real-Mode code and
|
||||
* Reset Vector at the end of the Flash ROM
|
||||
|
@ -61,3 +61,8 @@ int print_cpuinfo(void)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
int x86_cpu_reinit_f(void)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
@ -9,6 +9,12 @@
|
||||
/include/ "rtc.dtsi"
|
||||
/include/ "tsc_timer.dtsi"
|
||||
|
||||
#ifdef CONFIG_CHROMEOS
|
||||
#include "chromeos-x86.dtsi"
|
||||
#include "flashmap-x86-ro.dtsi"
|
||||
#include "flashmap-8mb-rw.dtsi"
|
||||
#endif
|
||||
|
||||
/ {
|
||||
model = "Google Samus";
|
||||
compatible = "google,samus", "intel,broadwell";
|
||||
@ -17,6 +23,7 @@
|
||||
spi0 = &spi;
|
||||
usb0 = &usb_0;
|
||||
usb1 = &usb_1;
|
||||
cros-ec0 = &cros_ec;
|
||||
};
|
||||
|
||||
config {
|
||||
@ -73,6 +80,7 @@
|
||||
|
||||
/* Put this first: it is the default */
|
||||
gpio_unused: gpio-unused {
|
||||
u-boot,dm-pre-reloc;
|
||||
mode-gpio;
|
||||
direction = <PIN_INPUT>;
|
||||
owner = <OWNER_GPIO>;
|
||||
@ -80,6 +88,7 @@
|
||||
};
|
||||
|
||||
gpio_acpi_sci: acpi-sci {
|
||||
u-boot,dm-pre-reloc;
|
||||
mode-gpio;
|
||||
direction = <PIN_INPUT>;
|
||||
invert;
|
||||
@ -87,6 +96,7 @@
|
||||
};
|
||||
|
||||
gpio_acpi_smi: acpi-smi {
|
||||
u-boot,dm-pre-reloc;
|
||||
mode-gpio;
|
||||
direction = <PIN_INPUT>;
|
||||
invert;
|
||||
@ -94,12 +104,14 @@
|
||||
};
|
||||
|
||||
gpio_input: gpio-input {
|
||||
u-boot,dm-pre-reloc;
|
||||
mode-gpio;
|
||||
direction = <PIN_INPUT>;
|
||||
owner = <OWNER_GPIO>;
|
||||
};
|
||||
|
||||
gpio_input_invert: gpio-input-invert {
|
||||
u-boot,dm-pre-reloc;
|
||||
mode-gpio;
|
||||
direction = <PIN_INPUT>;
|
||||
owner = <OWNER_GPIO>;
|
||||
@ -107,9 +119,11 @@
|
||||
};
|
||||
|
||||
gpio_native: gpio-native {
|
||||
u-boot,dm-pre-reloc;
|
||||
};
|
||||
|
||||
gpio_out_high: gpio-out-high {
|
||||
u-boot,dm-pre-reloc;
|
||||
mode-gpio;
|
||||
direction = <PIN_OUTPUT>;
|
||||
output-value = <1>;
|
||||
@ -118,6 +132,7 @@
|
||||
};
|
||||
|
||||
gpio_out_low: gpio-out-low {
|
||||
u-boot,dm-pre-reloc;
|
||||
mode-gpio;
|
||||
direction = <PIN_OUTPUT>;
|
||||
output-value = <0>;
|
||||
@ -126,6 +141,7 @@
|
||||
};
|
||||
|
||||
gpio_pirq: gpio-pirq {
|
||||
u-boot,dm-pre-reloc;
|
||||
mode-gpio;
|
||||
direction = <PIN_INPUT>;
|
||||
owner = <OWNER_GPIO>;
|
||||
@ -133,6 +149,7 @@
|
||||
};
|
||||
|
||||
soc_gpio@0 {
|
||||
u-boot,dm-pre-reloc;
|
||||
config =
|
||||
<0 &gpio_unused 0>, /* unused */
|
||||
<1 &gpio_unused 0>, /* unused */
|
||||
@ -250,8 +267,10 @@
|
||||
spd {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
u-boot,dm-pre-reloc;
|
||||
samsung_4 {
|
||||
reg = <6>;
|
||||
u-boot,dm-pre-reloc;
|
||||
data = [91 20 f1 03 04 11 05 0b
|
||||
03 11 01 08 0a 00 50 01
|
||||
78 78 90 50 90 11 50 e0
|
||||
@ -291,6 +310,7 @@
|
||||
* columns 10, density 4096 mb, x32
|
||||
*/
|
||||
reg = <8>;
|
||||
u-boot,dm-pre-reloc;
|
||||
data = [91 20 f1 03 04 11 05 0b
|
||||
03 11 01 08 0a 00 50 01
|
||||
78 78 90 50 90 11 50 e0
|
||||
@ -326,6 +346,7 @@
|
||||
};
|
||||
samsung_8 {
|
||||
reg = <10>;
|
||||
u-boot,dm-pre-reloc;
|
||||
data = [91 20 f1 03 04 12 05 0a
|
||||
03 11 01 08 0a 00 50 01
|
||||
78 78 90 50 90 11 50 e0
|
||||
@ -365,6 +386,7 @@
|
||||
* columns 11, density 4096 mb, x16
|
||||
*/
|
||||
reg = <12>;
|
||||
u-boot,dm-pre-reloc;
|
||||
data = [91 20 f1 03 04 12 05 0a
|
||||
03 11 01 08 0a 00 50 01
|
||||
78 78 90 50 90 11 50 e0
|
||||
@ -404,6 +426,7 @@
|
||||
* columns 11, density 8192 mb, x16
|
||||
*/
|
||||
reg = <13>;
|
||||
u-boot,dm-pre-reloc;
|
||||
data = [91 20 f1 03 05 1a 05 0a
|
||||
03 11 01 08 0a 00 50 01
|
||||
78 78 90 50 90 11 50 e0
|
||||
@ -443,6 +466,7 @@
|
||||
* columns 11, density 8192 mb, x16
|
||||
*/
|
||||
reg = <15>;
|
||||
u-boot,dm-pre-reloc;
|
||||
data = [91 20 f1 03 05 1a 05 0a
|
||||
03 11 01 08 0a 00 50 01
|
||||
78 78 90 50 90 11 50 e0
|
||||
@ -540,7 +564,7 @@
|
||||
compatible = "ehci-pci";
|
||||
};
|
||||
|
||||
pch@1f,0 {
|
||||
pch: pch@1f,0 {
|
||||
reg = <0x0000f800 0 0 0 0>;
|
||||
compatible = "intel,broadwell-pch";
|
||||
u-boot,dm-pre-reloc;
|
||||
@ -559,10 +583,12 @@
|
||||
power-enable-gpio = <&gpio_a 23 0>;
|
||||
|
||||
spi: spi {
|
||||
u-boot,dm-pre-reloc;
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
compatible = "intel,ich9-spi";
|
||||
spi-flash@0 {
|
||||
fwstore_spi: spi-flash@0 {
|
||||
u-boot,dm-pre-reloc;
|
||||
#size-cells = <1>;
|
||||
#address-cells = <1>;
|
||||
reg = <0>;
|
||||
@ -570,6 +596,7 @@
|
||||
"jedec,spi-nor";
|
||||
memory-map = <0xff800000 0x00800000>;
|
||||
rw-mrc-cache {
|
||||
u-boot,dm-pre-reloc;
|
||||
label = "rw-mrc-cache";
|
||||
reg = <0x003e0000 0x00010000>;
|
||||
};
|
||||
@ -609,7 +636,8 @@
|
||||
#size-cells = <0>;
|
||||
u-boot,dm-pre-reloc;
|
||||
intel,gen-dec = <0x800 0xfc 0x900 0xfc>;
|
||||
cros-ec@200 {
|
||||
cros_ec: cros-ec {
|
||||
u-boot,dm-pre-reloc;
|
||||
compatible = "google,cros-ec-lpc";
|
||||
reg = <0x204 1 0x200 1 0x880 0x80>;
|
||||
|
||||
@ -630,7 +658,7 @@
|
||||
sata@1f,2 {
|
||||
compatible = "intel,wildcatpoint-ahci";
|
||||
reg = <0x0000fa00 0 0 0 0>;
|
||||
u-boot,dm-pre-reloc;
|
||||
u-boot,dm-pre-proper;
|
||||
intel,sata-mode = "ahci";
|
||||
intel,sata-port-map = <1>;
|
||||
intel,sata-port0-gen3-tx = <0x72>;
|
||||
@ -645,12 +673,19 @@
|
||||
};
|
||||
|
||||
tpm {
|
||||
u-boot,dm-pre-reloc;
|
||||
reg = <0xfed40000 0x5000>;
|
||||
compatible = "infineon,slb9635lpc";
|
||||
secdata {
|
||||
u-boot,dm-pre-reloc;
|
||||
compatible = "google,tpm-secdata";
|
||||
};
|
||||
};
|
||||
|
||||
microcode {
|
||||
u-boot,dm-pre-reloc;
|
||||
update@0 {
|
||||
u-boot,dm-pre-reloc;
|
||||
#include "microcode/mc0306d4_00000018.dtsi"
|
||||
};
|
||||
};
|
||||
@ -668,3 +703,13 @@
|
||||
};
|
||||
|
||||
};
|
||||
|
||||
&rtc {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
nvdata {
|
||||
u-boot,dm-pre-reloc;
|
||||
compatible = "google,cmos-nvdata";
|
||||
reg = <0x26>;
|
||||
};
|
||||
};
|
||||
|
@ -1,5 +1,5 @@
|
||||
/ {
|
||||
reset {
|
||||
reset: reset {
|
||||
compatible = "x86,reset";
|
||||
u-boot,dm-pre-reloc;
|
||||
};
|
||||
|
@ -1,5 +1,5 @@
|
||||
/ {
|
||||
rtc {
|
||||
rtc: rtc {
|
||||
compatible = "motorola,mc146818";
|
||||
u-boot,dm-pre-reloc;
|
||||
reg = <0x70 2>;
|
||||
|
@ -6,86 +6,128 @@
|
||||
|
||||
#include <config.h>
|
||||
|
||||
#ifdef CONFIG_ROM_SIZE
|
||||
#ifdef CONFIG_CHROMEOS
|
||||
/ {
|
||||
binman {
|
||||
filename = "u-boot.rom";
|
||||
end-at-4gb;
|
||||
sort-by-offset;
|
||||
pad-byte = <0xff>;
|
||||
size = <CONFIG_ROM_SIZE>;
|
||||
#ifdef CONFIG_HAVE_INTEL_ME
|
||||
intel-descriptor {
|
||||
filename = CONFIG_FLASH_DESCRIPTOR_FILE;
|
||||
};
|
||||
intel-me {
|
||||
filename = CONFIG_INTEL_ME_FILE;
|
||||
};
|
||||
#endif
|
||||
#ifdef CONFIG_SPL
|
||||
u-boot-spl-with-ucode-ptr {
|
||||
offset = <CONFIG_SPL_TEXT_BASE>;
|
||||
};
|
||||
|
||||
u-boot-dtb-with-ucode2 {
|
||||
type = "u-boot-dtb-with-ucode";
|
||||
};
|
||||
u-boot {
|
||||
offset = <0xfff00000>;
|
||||
multiple-images;
|
||||
rom: rom {
|
||||
};
|
||||
};
|
||||
};
|
||||
#else
|
||||
u-boot-with-ucode-ptr {
|
||||
offset = <CONFIG_SYS_TEXT_BASE>;
|
||||
};
|
||||
#endif
|
||||
u-boot-dtb-with-ucode {
|
||||
};
|
||||
u-boot-ucode {
|
||||
align = <16>;
|
||||
};
|
||||
#ifdef CONFIG_HAVE_MRC
|
||||
intel-mrc {
|
||||
offset = <CONFIG_X86_MRC_ADDR>;
|
||||
};
|
||||
#endif
|
||||
#ifdef CONFIG_HAVE_FSP
|
||||
intel-fsp {
|
||||
filename = CONFIG_FSP_FILE;
|
||||
offset = <CONFIG_FSP_ADDR>;
|
||||
};
|
||||
#endif
|
||||
#ifdef CONFIG_HAVE_CMC
|
||||
intel-cmc {
|
||||
filename = CONFIG_CMC_FILE;
|
||||
offset = <CONFIG_CMC_ADDR>;
|
||||
};
|
||||
#endif
|
||||
#ifdef CONFIG_HAVE_VGA_BIOS
|
||||
intel-vga {
|
||||
filename = CONFIG_VGA_BIOS_FILE;
|
||||
offset = <CONFIG_VGA_BIOS_ADDR>;
|
||||
};
|
||||
#endif
|
||||
#ifdef CONFIG_HAVE_VBT
|
||||
intel-vbt {
|
||||
filename = CONFIG_VBT_FILE;
|
||||
offset = <CONFIG_VBT_ADDR>;
|
||||
};
|
||||
#endif
|
||||
#ifdef CONFIG_HAVE_REFCODE
|
||||
intel-refcode {
|
||||
offset = <CONFIG_X86_REFCODE_ADDR>;
|
||||
};
|
||||
#endif
|
||||
#ifdef CONFIG_SPL
|
||||
x86-start16-spl {
|
||||
offset = <CONFIG_SYS_X86_START16>;
|
||||
};
|
||||
#else
|
||||
x86-start16 {
|
||||
offset = <CONFIG_SYS_X86_START16>;
|
||||
};
|
||||
#endif
|
||||
/ {
|
||||
rom: binman {
|
||||
};
|
||||
};
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_ROM_SIZE
|
||||
&rom {
|
||||
filename = "u-boot.rom";
|
||||
end-at-4gb;
|
||||
sort-by-offset;
|
||||
pad-byte = <0xff>;
|
||||
size = <CONFIG_ROM_SIZE>;
|
||||
#ifdef CONFIG_HAVE_INTEL_ME
|
||||
intel-descriptor {
|
||||
filename = CONFIG_FLASH_DESCRIPTOR_FILE;
|
||||
};
|
||||
intel-me {
|
||||
filename = CONFIG_INTEL_ME_FILE;
|
||||
};
|
||||
#endif
|
||||
#ifdef CONFIG_TPL
|
||||
u-boot-tpl-with-ucode-ptr {
|
||||
offset = <CONFIG_TPL_TEXT_BASE>;
|
||||
};
|
||||
u-boot-tpl-dtb {
|
||||
};
|
||||
u-boot-spl {
|
||||
offset = <CONFIG_SPL_TEXT_BASE>;
|
||||
};
|
||||
u-boot-spl-dtb {
|
||||
};
|
||||
u-boot {
|
||||
offset = <CONFIG_SYS_TEXT_BASE>;
|
||||
};
|
||||
#elif defined(CONFIG_SPL)
|
||||
u-boot-spl-with-ucode-ptr {
|
||||
offset = <CONFIG_SPL_TEXT_BASE>;
|
||||
};
|
||||
u-boot-dtb-with-ucode2 {
|
||||
type = "u-boot-dtb-with-ucode";
|
||||
};
|
||||
u-boot {
|
||||
/*
|
||||
* TODO(sjg@chromium.org):
|
||||
* Normally we use CONFIG_SYS_TEXT_BASE as the flash offset. But
|
||||
* for boards with textbase in SDRAM we cannot do this. Just use
|
||||
* an assumed-valid value (1MB before the end of flash) here so
|
||||
* that we can actually build an image for coreboot, etc.
|
||||
* We need a better solution, perhaps a separate Kconfig.
|
||||
*/
|
||||
#if CONFIG_SYS_TEXT_BASE == 0x1110000
|
||||
offset = <0xfff00000>;
|
||||
#else
|
||||
offset = <CONFIG_SYS_TEXT_BASE>;
|
||||
#endif
|
||||
};
|
||||
#else
|
||||
u-boot-with-ucode-ptr {
|
||||
offset = <CONFIG_SYS_TEXT_BASE>;
|
||||
};
|
||||
#endif
|
||||
u-boot-dtb-with-ucode {
|
||||
};
|
||||
u-boot-ucode {
|
||||
align = <16>;
|
||||
};
|
||||
#ifdef CONFIG_HAVE_MRC
|
||||
intel-mrc {
|
||||
offset = <CONFIG_X86_MRC_ADDR>;
|
||||
};
|
||||
#endif
|
||||
#ifdef CONFIG_HAVE_FSP
|
||||
intel-fsp {
|
||||
filename = CONFIG_FSP_FILE;
|
||||
offset = <CONFIG_FSP_ADDR>;
|
||||
};
|
||||
#endif
|
||||
#ifdef CONFIG_HAVE_CMC
|
||||
intel-cmc {
|
||||
filename = CONFIG_CMC_FILE;
|
||||
offset = <CONFIG_CMC_ADDR>;
|
||||
};
|
||||
#endif
|
||||
#ifdef CONFIG_HAVE_VGA_BIOS
|
||||
intel-vga {
|
||||
filename = CONFIG_VGA_BIOS_FILE;
|
||||
offset = <CONFIG_VGA_BIOS_ADDR>;
|
||||
};
|
||||
#endif
|
||||
#ifdef CONFIG_HAVE_VBT
|
||||
intel-vbt {
|
||||
filename = CONFIG_VBT_FILE;
|
||||
offset = <CONFIG_VBT_ADDR>;
|
||||
};
|
||||
#endif
|
||||
#ifdef CONFIG_HAVE_REFCODE
|
||||
intel-refcode {
|
||||
offset = <CONFIG_X86_REFCODE_ADDR>;
|
||||
};
|
||||
#endif
|
||||
#ifdef CONFIG_TPL
|
||||
x86-start16-tpl {
|
||||
offset = <CONFIG_SYS_X86_START16>;
|
||||
};
|
||||
#elif defined(CONFIG_SPL)
|
||||
x86-start16-spl {
|
||||
offset = <CONFIG_SYS_X86_START16>;
|
||||
};
|
||||
#else
|
||||
x86-start16 {
|
||||
offset = <CONFIG_SYS_X86_START16>;
|
||||
};
|
||||
#endif
|
||||
};
|
||||
#endif
|
||||
|
15
arch/x86/include/asm/handoff.h
Normal file
15
arch/x86/include/asm/handoff.h
Normal file
@ -0,0 +1,15 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0+ */
|
||||
/*
|
||||
* Architecture-specific SPL handoff information for x86
|
||||
*
|
||||
* Copyright 2018 Google, Inc
|
||||
* Written by Simon Glass <sjg@chromium.org>
|
||||
*/
|
||||
|
||||
#ifndef __x86_asm_handoff_h
|
||||
#define __x86_asm_handoff_h
|
||||
|
||||
struct arch_spl_handoff {
|
||||
};
|
||||
|
||||
#endif
|
@ -103,4 +103,15 @@ int mrccache_get_region(struct udevice **devp, struct mrc_region *entry);
|
||||
*/
|
||||
int mrccache_save(void);
|
||||
|
||||
/**
|
||||
* mrccache_spl_save() - Save to the MRC region from SPL
|
||||
*
|
||||
* When SPL is used to set up the memory controller we want to save the MRC
|
||||
* data in SPL to avoid needing to pass it up to U-Boot proper to save. This
|
||||
* function handles that.
|
||||
*
|
||||
* @return 0 if saved to SPI flash successfully, other error if failed
|
||||
*/
|
||||
int mrccache_spl_save(void);
|
||||
|
||||
#endif /* _ASM_MRCCACHE_H */
|
||||
|
@ -2,6 +2,19 @@
|
||||
/*
|
||||
* Copyright (C) 2017 Google, Inc
|
||||
* Written by Simon Glass <sjg@chromium.org>
|
||||
*
|
||||
* This file is required for SPL to build, but is empty.
|
||||
*/
|
||||
|
||||
#ifndef __asm_spl_h
|
||||
#define __asm_spl_h
|
||||
|
||||
#define CONFIG_SPL_BOARD_LOAD_IMAGE
|
||||
|
||||
enum {
|
||||
BOOT_DEVICE_SPI = 10,
|
||||
BOOT_DEVICE_BOARD,
|
||||
BOOT_DEVICE_CROS_VBOOT,
|
||||
};
|
||||
|
||||
void jump_to_spl(ulong entry);
|
||||
|
||||
#endif
|
||||
|
@ -13,7 +13,27 @@ extern char gdt_rom[];
|
||||
|
||||
/* cpu/.../cpu.c */
|
||||
int arch_cpu_init(void);
|
||||
|
||||
/**
|
||||
* x86_cpu_init_f() - Set up basic features of the x86 CPU
|
||||
*
|
||||
* 0 on success, -ve on error
|
||||
*/
|
||||
int x86_cpu_init_f(void);
|
||||
|
||||
/**
|
||||
* x86_cpu_reinit_f() - Set up the CPU a second time
|
||||
*
|
||||
* Once cpu_init_f() has been called (e.g. in SPL) we should not call it
|
||||
* again (e.g. in U-Boot proper) since it sets up the state from scratch.
|
||||
* Call this function in later phases of U-Boot instead. It reads the CPU
|
||||
* identify so that CPU functions can be used correctly, but does not change
|
||||
* anything.
|
||||
*
|
||||
* @return 0 (indicating success, to mimic cpu_init_f())
|
||||
*/
|
||||
int x86_cpu_reinit_f(void);
|
||||
|
||||
int cpu_init_f(void);
|
||||
void setup_gdt(struct global_data *id, u64 *gdt_addr);
|
||||
/*
|
||||
|
@ -43,7 +43,14 @@ ifndef CONFIG_SPL_BUILD
|
||||
obj-$(CONFIG_CMD_ZBOOT) += zimage.o
|
||||
endif
|
||||
obj-$(CONFIG_HAVE_FSP) += fsp/
|
||||
obj-$(CONFIG_SPL_BUILD) += spl.o
|
||||
|
||||
ifdef CONFIG_SPL_BUILD
|
||||
ifdef CONFIG_TPL_BUILD
|
||||
obj-y += tpl.o
|
||||
else
|
||||
obj-y += spl.o
|
||||
endif
|
||||
endif
|
||||
|
||||
lib-$(CONFIG_USE_PRIVATE_LIBGCC) += div64.o
|
||||
|
||||
|
@ -35,7 +35,7 @@ void bootm_announce_and_cleanup(void)
|
||||
timestamp_add_now(TS_U_BOOT_START_KERNEL);
|
||||
#endif
|
||||
bootstage_mark_name(BOOTSTAGE_ID_BOOTM_HANDOFF, "start_kernel");
|
||||
#ifdef CONFIG_BOOTSTAGE_REPORT
|
||||
#if CONFIG_IS_ENABLED(BOOTSTAGE_REPORT)
|
||||
bootstage_report();
|
||||
#endif
|
||||
|
||||
|
@ -100,7 +100,7 @@ temp_ram_init_romstack:
|
||||
.long temp_ram_init_params
|
||||
temp_ram_init_params:
|
||||
_dt_ucode_base_size:
|
||||
/* These next two fields are filled in by ifdtool */
|
||||
/* These next two fields are filled in by binman */
|
||||
.globl ucode_base
|
||||
ucode_base: /* Declared in microcode.h */
|
||||
.long 0 /* microcode base */
|
||||
|
@ -18,7 +18,10 @@ __weak ulong board_get_usable_ram_top(ulong total_size)
|
||||
|
||||
int init_cache_f_r(void)
|
||||
{
|
||||
#if CONFIG_IS_ENABLED(X86_32BIT_INIT) && !defined(CONFIG_HAVE_FSP)
|
||||
#if (CONFIG_IS_ENABLED(X86_32BIT_INIT) || \
|
||||
(!defined(CONFIG_SPL_BUILD) && \
|
||||
!CONFIG_IS_ENABLED(CONFIG_X86_RUN_64BIT))) && \
|
||||
!defined(CONFIG_HAVE_FSP)
|
||||
int ret;
|
||||
|
||||
ret = mtrr_commit(false);
|
||||
|
@ -113,8 +113,10 @@ int mrccache_update(struct udevice *sf, struct mrc_region *entry,
|
||||
ulong base_addr;
|
||||
int ret;
|
||||
|
||||
if (!is_mrc_cache(cur))
|
||||
if (!is_mrc_cache(cur)) {
|
||||
debug("%s: Cache data not valid\n", __func__);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/* Find the last used block */
|
||||
base_addr = entry->base + entry->offset;
|
||||
@ -159,18 +161,11 @@ int mrccache_update(struct udevice *sf, struct mrc_region *entry,
|
||||
return 0;
|
||||
}
|
||||
|
||||
int mrccache_reserve(void)
|
||||
static void mrccache_setup(void *data)
|
||||
{
|
||||
struct mrc_data_container *cache;
|
||||
struct mrc_data_container *cache = data;
|
||||
u16 checksum;
|
||||
|
||||
if (!gd->arch.mrc_output_len)
|
||||
return 0;
|
||||
|
||||
/* adjust stack pointer to store pure cache data plus the header */
|
||||
gd->start_addr_sp -= (gd->arch.mrc_output_len + MRC_DATA_HEADER_SIZE);
|
||||
cache = (struct mrc_data_container *)gd->start_addr_sp;
|
||||
|
||||
cache->signature = MRC_DATA_SIGNATURE;
|
||||
cache->data_size = gd->arch.mrc_output_len;
|
||||
checksum = compute_ip_checksum(gd->arch.mrc_output, cache->data_size);
|
||||
@ -182,6 +177,16 @@ int mrccache_reserve(void)
|
||||
|
||||
/* gd->arch.mrc_output now points to the container */
|
||||
gd->arch.mrc_output = (char *)cache;
|
||||
}
|
||||
|
||||
int mrccache_reserve(void)
|
||||
{
|
||||
if (!gd->arch.mrc_output_len)
|
||||
return 0;
|
||||
|
||||
/* adjust stack pointer to store pure cache data plus the header */
|
||||
gd->start_addr_sp -= (gd->arch.mrc_output_len + MRC_DATA_HEADER_SIZE);
|
||||
mrccache_setup((void *)gd->start_addr_sp);
|
||||
|
||||
gd->start_addr_sp &= ~0xf;
|
||||
|
||||
@ -202,17 +207,23 @@ int mrccache_get_region(struct udevice **devp, struct mrc_region *entry)
|
||||
return -ENOENT;
|
||||
}
|
||||
|
||||
if (fdtdec_get_int_array(blob, node, "memory-map", reg, 2))
|
||||
if (fdtdec_get_int_array(blob, node, "memory-map", reg, 2)) {
|
||||
debug("%s: Cannot find memory map\n", __func__);
|
||||
return -EINVAL;
|
||||
}
|
||||
entry->base = reg[0];
|
||||
|
||||
/* Find the place where we put the MRC cache */
|
||||
mrc_node = fdt_subnode_offset(blob, node, "rw-mrc-cache");
|
||||
if (mrc_node < 0)
|
||||
if (mrc_node < 0) {
|
||||
debug("%s: Cannot find node\n", __func__);
|
||||
return -EPERM;
|
||||
}
|
||||
|
||||
if (fdtdec_get_int_array(blob, mrc_node, "reg", reg, 2))
|
||||
if (fdtdec_get_int_array(blob, mrc_node, "reg", reg, 2)) {
|
||||
debug("%s: Cannot find address\n", __func__);
|
||||
return -EINVAL;
|
||||
}
|
||||
entry->offset = reg[0];
|
||||
entry->length = reg[1];
|
||||
|
||||
@ -256,3 +267,18 @@ err_entry:
|
||||
debug("%s: Failed: %d\n", __func__, ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
int mrccache_spl_save(void)
|
||||
{
|
||||
void *data;
|
||||
int size;
|
||||
|
||||
size = gd->arch.mrc_output_len + MRC_DATA_HEADER_SIZE;
|
||||
data = malloc(size);
|
||||
if (!data)
|
||||
return log_msg_ret("Allocate MRC cache block", -ENOMEM);
|
||||
mrccache_setup(data);
|
||||
gd->arch.mrc_output = data;
|
||||
|
||||
return mrccache_save();
|
||||
}
|
||||
|
@ -5,8 +5,10 @@
|
||||
|
||||
#include <common.h>
|
||||
#include <debug_uart.h>
|
||||
#include <malloc.h>
|
||||
#include <spl.h>
|
||||
#include <asm/cpu.h>
|
||||
#include <asm/mrccache.h>
|
||||
#include <asm/mtrr.h>
|
||||
#include <asm/processor.h>
|
||||
#include <asm-generic/sections.h>
|
||||
@ -20,6 +22,7 @@ __weak int arch_cpu_init_dm(void)
|
||||
|
||||
static int x86_spl_init(void)
|
||||
{
|
||||
#ifndef CONFIG_TPL
|
||||
/*
|
||||
* TODO(sjg@chromium.org): We use this area of RAM for the stack
|
||||
* and global_data in SPL. Once U-Boot starts up and releocates it
|
||||
@ -27,6 +30,7 @@ static int x86_spl_init(void)
|
||||
* place it immediately below CONFIG_SYS_TEXT_BASE.
|
||||
*/
|
||||
char *ptr = (char *)0x110000;
|
||||
#endif
|
||||
int ret;
|
||||
|
||||
debug("%s starting\n", __func__);
|
||||
@ -35,27 +39,44 @@ static int x86_spl_init(void)
|
||||
debug("%s: spl_init() failed\n", __func__);
|
||||
return ret;
|
||||
}
|
||||
#ifdef CONFIG_TPL
|
||||
/* Do a mini-init if TPL has already done the full init */
|
||||
ret = x86_cpu_reinit_f();
|
||||
#else
|
||||
ret = arch_cpu_init();
|
||||
#endif
|
||||
if (ret) {
|
||||
debug("%s: arch_cpu_init() failed\n", __func__);
|
||||
return ret;
|
||||
}
|
||||
#ifndef CONFIG_TPL
|
||||
ret = arch_cpu_init_dm();
|
||||
if (ret) {
|
||||
debug("%s: arch_cpu_init_dm() failed\n", __func__);
|
||||
return ret;
|
||||
}
|
||||
#endif
|
||||
preloader_console_init();
|
||||
#ifndef CONFIG_TPL
|
||||
ret = print_cpuinfo();
|
||||
if (ret) {
|
||||
debug("%s: print_cpuinfo() failed\n", __func__);
|
||||
return ret;
|
||||
}
|
||||
#endif
|
||||
ret = dram_init();
|
||||
if (ret) {
|
||||
debug("%s: dram_init() failed\n", __func__);
|
||||
return ret;
|
||||
}
|
||||
if (IS_ENABLED(CONFIG_ENABLE_MRC_CACHE)) {
|
||||
ret = mrccache_spl_save();
|
||||
if (ret)
|
||||
debug("%s: Failed to write to mrccache (err=%d)\n",
|
||||
__func__, ret);
|
||||
}
|
||||
|
||||
#ifndef CONFIG_TPL
|
||||
memset(&__bss_start, 0, (ulong)&__bss_end - (ulong)&__bss_start);
|
||||
|
||||
/* TODO(sjg@chromium.org): Consider calling cpu_init_r() here */
|
||||
@ -80,9 +101,11 @@ static int x86_spl_init(void)
|
||||
(1ULL << 32) - CONFIG_XIP_ROM_SIZE,
|
||||
CONFIG_XIP_ROM_SIZE);
|
||||
if (ret) {
|
||||
debug("%s: SPI cache setup failed\n", __func__);
|
||||
debug("%s: SPI cache setup failed (err=%d)\n", __func__, ret);
|
||||
return ret;
|
||||
}
|
||||
mtrr_commit(true);
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -96,9 +119,17 @@ void board_init_f(ulong flags)
|
||||
debug("Error %d\n", ret);
|
||||
hang();
|
||||
}
|
||||
|
||||
#ifdef CONFIG_TPL
|
||||
gd->bd = malloc(sizeof(*gd->bd));
|
||||
if (!gd->bd) {
|
||||
printf("Out of memory for bd_info size %x\n", sizeof(*gd->bd));
|
||||
hang();
|
||||
}
|
||||
board_init_r(gd, 0);
|
||||
#else
|
||||
/* Uninit CAR and jump to board_init_f_r() */
|
||||
board_init_f_r_trampoline(gd->start_addr_sp);
|
||||
#endif
|
||||
}
|
||||
|
||||
void board_init_f_r(void)
|
||||
@ -144,6 +175,7 @@ int spl_spi_load_image(void)
|
||||
return -EPERM;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_X86_RUN_64BIT
|
||||
void __noreturn jump_to_image_no_args(struct spl_image_info *spl_image)
|
||||
{
|
||||
int ret;
|
||||
@ -154,3 +186,11 @@ void __noreturn jump_to_image_no_args(struct spl_image_info *spl_image)
|
||||
while (1)
|
||||
;
|
||||
}
|
||||
#endif
|
||||
|
||||
void spl_board_init(void)
|
||||
{
|
||||
#ifndef CONFIG_TPL
|
||||
preloader_console_init();
|
||||
#endif
|
||||
}
|
||||
|
118
arch/x86/lib/tpl.c
Normal file
118
arch/x86/lib/tpl.c
Normal file
@ -0,0 +1,118 @@
|
||||
// SPDX-License-Identifier: GPL-2.0
|
||||
/*
|
||||
* Copyright (c) 2018 Google, Inc
|
||||
*/
|
||||
|
||||
#include <common.h>
|
||||
#include <debug_uart.h>
|
||||
#include <spl.h>
|
||||
#include <asm/cpu.h>
|
||||
#include <asm/mtrr.h>
|
||||
#include <asm/processor.h>
|
||||
#include <asm-generic/sections.h>
|
||||
|
||||
DECLARE_GLOBAL_DATA_PTR;
|
||||
|
||||
__weak int arch_cpu_init_dm(void)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int x86_tpl_init(void)
|
||||
{
|
||||
int ret;
|
||||
|
||||
debug("%s starting\n", __func__);
|
||||
ret = spl_init();
|
||||
if (ret) {
|
||||
debug("%s: spl_init() failed\n", __func__);
|
||||
return ret;
|
||||
}
|
||||
ret = arch_cpu_init();
|
||||
if (ret) {
|
||||
debug("%s: arch_cpu_init() failed\n", __func__);
|
||||
return ret;
|
||||
}
|
||||
ret = arch_cpu_init_dm();
|
||||
if (ret) {
|
||||
debug("%s: arch_cpu_init_dm() failed\n", __func__);
|
||||
return ret;
|
||||
}
|
||||
preloader_console_init();
|
||||
ret = print_cpuinfo();
|
||||
if (ret) {
|
||||
debug("%s: print_cpuinfo() failed\n", __func__);
|
||||
return ret;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void board_init_f(ulong flags)
|
||||
{
|
||||
int ret;
|
||||
|
||||
ret = x86_tpl_init();
|
||||
if (ret) {
|
||||
debug("Error %d\n", ret);
|
||||
hang();
|
||||
}
|
||||
|
||||
/* Uninit CAR and jump to board_init_f_r() */
|
||||
board_init_r(gd, 0);
|
||||
}
|
||||
|
||||
void board_init_f_r(void)
|
||||
{
|
||||
/* Not used since we never call board_init_f_r_trampoline() */
|
||||
while (1);
|
||||
}
|
||||
|
||||
u32 spl_boot_device(void)
|
||||
{
|
||||
return IS_ENABLED(CONFIG_CHROMEOS) ? BOOT_DEVICE_CROS_VBOOT :
|
||||
BOOT_DEVICE_BOARD;
|
||||
}
|
||||
|
||||
int spl_start_uboot(void)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
void spl_board_announce_boot_device(void)
|
||||
{
|
||||
printf("SPI flash");
|
||||
}
|
||||
|
||||
static int spl_board_load_image(struct spl_image_info *spl_image,
|
||||
struct spl_boot_device *bootdev)
|
||||
{
|
||||
spl_image->size = CONFIG_SYS_MONITOR_LEN; /* We don't know SPL size */
|
||||
spl_image->entry_point = CONFIG_SPL_TEXT_BASE;
|
||||
spl_image->load_addr = CONFIG_SPL_TEXT_BASE;
|
||||
spl_image->os = IH_OS_U_BOOT;
|
||||
spl_image->name = "U-Boot";
|
||||
|
||||
debug("Loading to %lx\n", spl_image->load_addr);
|
||||
|
||||
return 0;
|
||||
}
|
||||
SPL_LOAD_IMAGE_METHOD("SPI", 0, BOOT_DEVICE_BOARD, spl_board_load_image);
|
||||
|
||||
int spl_spi_load_image(void)
|
||||
{
|
||||
return -EPERM;
|
||||
}
|
||||
|
||||
void __noreturn jump_to_image_no_args(struct spl_image_info *spl_image)
|
||||
{
|
||||
printf("Jumping to U-Boot SPL at %lx\n", (ulong)spl_image->entry_point);
|
||||
jump_to_spl(spl_image->entry_point);
|
||||
while (1)
|
||||
;
|
||||
}
|
||||
|
||||
void spl_board_init(void)
|
||||
{
|
||||
preloader_console_init();
|
||||
}
|
@ -52,6 +52,14 @@ config TARGET_CHROMEBOOK_SAMUS
|
||||
Chrome OS EC connected on LPC, and it provides a 2560x1700 high
|
||||
resolution touch-enabled LCD display.
|
||||
|
||||
config TARGET_CHROMEBOOK_SAMUS_TPL
|
||||
bool "Chromebook samus booting from TPL"
|
||||
help
|
||||
This is a version of Samus which boots into TPL, then to SPL and
|
||||
U-Boot proper. This is useful where verified boot must select
|
||||
between different A/B versions of SPL/U-Boot, to allow upgrading of
|
||||
almost all U-Boot code in the field.
|
||||
|
||||
endchoice
|
||||
|
||||
source "board/google/chromebook_link/Kconfig"
|
||||
|
@ -1,4 +1,4 @@
|
||||
if TARGET_CHROMEBOOK_SAMUS
|
||||
if TARGET_CHROMEBOOK_SAMUS || TARGET_CHROMEBOOK_SAMUS_TPL
|
||||
|
||||
config SYS_BOARD
|
||||
default "chromebook_samus"
|
||||
@ -10,7 +10,8 @@ config SYS_SOC
|
||||
default "broadwell"
|
||||
|
||||
config SYS_CONFIG_NAME
|
||||
default "chromebook_samus"
|
||||
default "chromebook_samus" if TARGET_CHROMEBOOK_SAMUS
|
||||
default "chromebook_samus" if TARGET_CHROMEBOOK_SAMUS_TPL
|
||||
|
||||
config SYS_TEXT_BASE
|
||||
default 0xffe00000
|
||||
@ -39,3 +40,12 @@ config SYS_CAR_SIZE
|
||||
default 0x40000
|
||||
|
||||
endif
|
||||
|
||||
if TARGET_CHROMEBOOK_SAMUS_TPL
|
||||
|
||||
config BOARD_SPECIFIC_OPTIONS_TPL # dummy
|
||||
def_bool y
|
||||
select SPL
|
||||
select TPL
|
||||
|
||||
endif
|
||||
|
@ -4,3 +4,10 @@ S: Maintained
|
||||
F: board/google/chromebook_samus/
|
||||
F: include/configs/chromebook_samus.h
|
||||
F: configs/chromebook_samus_defconfig
|
||||
|
||||
CHROMEBOOK SAMUS TPL BOARD
|
||||
M: Simon Glass <sjg@chromium.org>
|
||||
S: Maintained
|
||||
F: board/google/chromebook_samus/
|
||||
F: include/configs/chromebook_samus.h
|
||||
F: configs/chromebook_samus_tpl_defconfig
|
||||
|
@ -1,6 +1,6 @@
|
||||
CONFIG_X86=y
|
||||
CONFIG_SYS_TEXT_BASE=0xFFE00000
|
||||
CONFIG_SYS_MALLOC_F_LEN=0x1c00
|
||||
CONFIG_SYS_MALLOC_F_LEN=0x1d00
|
||||
CONFIG_NR_DRAM_BANKS=8
|
||||
CONFIG_DEBUG_UART_BOARD_INIT=y
|
||||
CONFIG_DEBUG_UART_BASE=0x3f8
|
||||
|
82
configs/chromebook_samus_tpl_defconfig
Normal file
82
configs/chromebook_samus_tpl_defconfig
Normal file
@ -0,0 +1,82 @@
|
||||
CONFIG_X86=y
|
||||
CONFIG_SYS_TEXT_BASE=0xffed0000
|
||||
CONFIG_SYS_MALLOC_F_LEN=0x1a00
|
||||
CONFIG_NR_DRAM_BANKS=8
|
||||
CONFIG_DEBUG_UART_BOARD_INIT=y
|
||||
CONFIG_DEBUG_UART_BASE=0x3f8
|
||||
CONFIG_DEBUG_UART_CLOCK=1843200
|
||||
CONFIG_VENDOR_GOOGLE=y
|
||||
CONFIG_TARGET_CHROMEBOOK_SAMUS_TPL=y
|
||||
CONFIG_DEBUG_UART=y
|
||||
CONFIG_HAVE_MRC=y
|
||||
CONFIG_HAVE_REFCODE=y
|
||||
CONFIG_SMP=y
|
||||
CONFIG_HAVE_VGA_BIOS=y
|
||||
CONFIG_BOOTSTAGE=y
|
||||
CONFIG_BOOTSTAGE_REPORT=y
|
||||
CONFIG_USE_BOOTARGS=y
|
||||
CONFIG_BOOTARGS="root=/dev/sdb3 init=/sbin/init rootwait ro"
|
||||
CONFIG_SYS_CONSOLE_INFO_QUIET=y
|
||||
CONFIG_MISC_INIT_R=y
|
||||
CONFIG_DISPLAY_BOARDINFO_LATE=y
|
||||
CONFIG_LAST_STAGE_INIT=y
|
||||
CONFIG_BLOBLIST=y
|
||||
CONFIG_BLOBLIST_SIZE=0x1000
|
||||
CONFIG_BLOBLIST_ADDR=0xff7c0000
|
||||
CONFIG_HANDOFF=y
|
||||
CONFIG_SPL_TEXT_BASE=0xffe70000
|
||||
CONFIG_SPL_SEPARATE_BSS=y
|
||||
CONFIG_SPL_NET_SUPPORT=y
|
||||
CONFIG_SPL_PCI=y
|
||||
CONFIG_SPL_PCH_SUPPORT=y
|
||||
CONFIG_TPL_PCI=y
|
||||
CONFIG_TPL_PCH_SUPPORT=y
|
||||
CONFIG_HUSH_PARSER=y
|
||||
CONFIG_CMD_CPU=y
|
||||
# CONFIG_CMD_FLASH is not set
|
||||
CONFIG_CMD_GPIO=y
|
||||
CONFIG_CMD_I2C=y
|
||||
CONFIG_CMD_PART=y
|
||||
CONFIG_CMD_SATA=y
|
||||
CONFIG_CMD_SF=y
|
||||
CONFIG_CMD_SPI=y
|
||||
CONFIG_CMD_USB=y
|
||||
# CONFIG_CMD_SETEXPR is not set
|
||||
CONFIG_CMD_TIME=y
|
||||
CONFIG_CMD_SOUND=y
|
||||
CONFIG_CMD_BOOTSTAGE=y
|
||||
CONFIG_CMD_TPM=y
|
||||
CONFIG_CMD_TPM_TEST=y
|
||||
CONFIG_CMD_EXT2=y
|
||||
CONFIG_CMD_EXT4=y
|
||||
CONFIG_CMD_EXT4_WRITE=y
|
||||
CONFIG_CMD_FAT=y
|
||||
CONFIG_CMD_FS_GENERIC=y
|
||||
CONFIG_MAC_PARTITION=y
|
||||
# CONFIG_SPL_MAC_PARTITION is not set
|
||||
# CONFIG_SPL_DOS_PARTITION is not set
|
||||
CONFIG_ISO_PARTITION=y
|
||||
CONFIG_EFI_PARTITION=y
|
||||
# CONFIG_SPL_EFI_PARTITION is not set
|
||||
CONFIG_DEFAULT_DEVICE_TREE="chromebook_samus"
|
||||
# CONFIG_NET is not set
|
||||
CONFIG_REGMAP=y
|
||||
CONFIG_SYSCON=y
|
||||
CONFIG_CPU=y
|
||||
CONFIG_DM_I2C=y
|
||||
CONFIG_SYS_I2C_DW=y
|
||||
CONFIG_TPL_MISC=y
|
||||
CONFIG_CROS_EC=y
|
||||
CONFIG_CROS_EC_LPC=y
|
||||
CONFIG_SYS_NS16550=y
|
||||
CONFIG_SOUND=y
|
||||
CONFIG_SOUND_I8254=y
|
||||
CONFIG_SOUND_RT5677=y
|
||||
CONFIG_SPI=y
|
||||
CONFIG_TPM_TIS_LPC=y
|
||||
CONFIG_USB_STORAGE=y
|
||||
CONFIG_USB_KEYBOARD=y
|
||||
CONFIG_FRAMEBUFFER_SET_VESA_MODE=y
|
||||
CONFIG_FRAMEBUFFER_VESA_MODE_11A=y
|
||||
CONFIG_CONSOLE_SCROLL_LINES=5
|
||||
CONFIG_TPM=y
|
@ -185,6 +185,22 @@ If you are using em100, then this command will flash write -Boot:
|
||||
|
||||
em100 -s -d filename.rom -c W25Q64CV -r
|
||||
|
||||
Flash map for samus / broadwell:
|
||||
|
||||
fffff800 SYS_X86_START16
|
||||
ffff0000 RESET_SEG_START
|
||||
fffd8000 TPL_TEXT_BASE
|
||||
fffa0000 X86_MRC_ADDR
|
||||
fff90000 VGA_BIOS_ADDR
|
||||
ffed0000 SYS_TEXT_BASE
|
||||
ffea0000 X86_REFCODE_ADDR
|
||||
ffe70000 SPL_TEXT_BASE
|
||||
ffbf8000 CONFIG_ENV_OFFSET (environemnt offset)
|
||||
ffbe0000 rw-mrc-cache (Memory-reference-code cache)
|
||||
ffa00000 <spare>
|
||||
ff801000 intel-me (address set by descriptor.bin)
|
||||
ff800000 intel-descriptor
|
||||
|
||||
---
|
||||
|
||||
Intel Crown Bay specific instructions for bare mode:
|
||||
|
@ -546,7 +546,7 @@ fdt_addr_t ofnode_get_addr_size(ofnode node, const char *property,
|
||||
ns = of_n_size_cells(np);
|
||||
*sizep = of_read_number(prop + na, ns);
|
||||
|
||||
if (IS_ENABLED(CONFIG_OF_TRANSLATE) && ns > 0)
|
||||
if (CONFIG_IS_ENABLED(OF_TRANSLATE) && ns > 0)
|
||||
return of_translate_address(np, prop);
|
||||
else
|
||||
return of_read_number(prop, na);
|
||||
|
@ -1482,7 +1482,7 @@ int cros_ec_set_lid_shutdown_mask(struct udevice *dev, int enable)
|
||||
|
||||
UCLASS_DRIVER(cros_ec) = {
|
||||
.id = UCLASS_CROS_EC,
|
||||
.name = "cros_ec",
|
||||
.name = "cros-ec",
|
||||
.per_device_auto_alloc_size = sizeof(struct cros_ec_dev),
|
||||
.post_bind = dm_scan_fdt_dev,
|
||||
.flags = DM_UC_FLAG_ALLOC_PRIV_DMA,
|
||||
|
@ -306,7 +306,7 @@ int dm_pci_run_vga_bios(struct udevice *dev, int (*int15_handler)(void),
|
||||
goto err;
|
||||
#endif
|
||||
} else {
|
||||
#if defined(CONFIG_X86) && CONFIG_IS_ENABLED(X86_32BIT_INIT)
|
||||
#if defined(CONFIG_X86) && (CONFIG_IS_ENABLED(X86_32BIT_INIT) || CONFIG_TPL)
|
||||
bios_set_interrupt_handler(0x15, int15_handler);
|
||||
|
||||
bios_run_on_x86(dev, (unsigned long)ram, vesa_mode,
|
||||
|
@ -7,15 +7,75 @@
|
||||
|
||||
#include <common.h>
|
||||
#include <dm.h>
|
||||
#include <efi_loader.h>
|
||||
#include <pch.h>
|
||||
#include <sysreset.h>
|
||||
#include <asm/acpi_s3.h>
|
||||
#include <asm/io.h>
|
||||
#include <asm/processor.h>
|
||||
#include <efi_loader.h>
|
||||
|
||||
static __efi_runtime int x86_sysreset_request(struct udevice *dev,
|
||||
enum sysreset_t type)
|
||||
struct x86_sysreset_platdata {
|
||||
struct udevice *pch;
|
||||
};
|
||||
|
||||
/*
|
||||
* Power down the machine by using the power management sleep control
|
||||
* of the chipset. This will currently only work on Intel chipsets.
|
||||
* However, adapting it to new chipsets is fairly simple. You will
|
||||
* have to find the IO address of the power management register block
|
||||
* in your southbridge, and look up the appropriate SLP_TYP_S5 value
|
||||
* from your southbridge's data sheet.
|
||||
*
|
||||
* This function never returns.
|
||||
*/
|
||||
int pch_sysreset_power_off(struct udevice *dev)
|
||||
{
|
||||
struct x86_sysreset_platdata *plat = dev_get_platdata(dev);
|
||||
struct pch_pmbase_info pm;
|
||||
u32 reg32;
|
||||
int ret;
|
||||
|
||||
if (!plat->pch)
|
||||
return -ENOENT;
|
||||
ret = pch_ioctl(plat->pch, PCH_REQ_PMBASE_INFO, &pm, sizeof(pm));
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
/*
|
||||
* Mask interrupts or system might stay in a coma, not executing code
|
||||
* anymore, but not powered off either.
|
||||
*/
|
||||
asm("cli");
|
||||
|
||||
/*
|
||||
* Avoid any GPI waking the system from S5* or the system might stay in
|
||||
* a coma
|
||||
*/
|
||||
outl(0x00000000, pm.base + pm.gpio0_en_ofs);
|
||||
|
||||
/* Clear Power Button Status */
|
||||
outw(PWRBTN_STS, pm.base + pm.pm1_sts_ofs);
|
||||
|
||||
/* PMBASE + 4, Bit 10-12, Sleeping Type, * set to 111 -> S5, soft_off */
|
||||
reg32 = inl(pm.base + pm.pm1_cnt_ofs);
|
||||
|
||||
/* Set Sleeping Type to S5 (poweroff) */
|
||||
reg32 &= ~(SLP_EN | SLP_TYP);
|
||||
reg32 |= SLP_TYP_S5;
|
||||
outl(reg32, pm.base + pm.pm1_cnt_ofs);
|
||||
|
||||
/* Now set the Sleep Enable bit */
|
||||
reg32 |= SLP_EN;
|
||||
outl(reg32, pm.base + pm.pm1_cnt_ofs);
|
||||
|
||||
for (;;)
|
||||
asm("hlt");
|
||||
}
|
||||
|
||||
static int x86_sysreset_request(struct udevice *dev, enum sysreset_t type)
|
||||
{
|
||||
int value;
|
||||
int ret;
|
||||
|
||||
switch (type) {
|
||||
case SYSRESET_WARM:
|
||||
@ -24,6 +84,11 @@ static __efi_runtime int x86_sysreset_request(struct udevice *dev,
|
||||
case SYSRESET_COLD:
|
||||
value = SYS_RST | RST_CPU | FULL_RST;
|
||||
break;
|
||||
case SYSRESET_POWER_OFF:
|
||||
ret = pch_sysreset_power_off(dev);
|
||||
if (ret)
|
||||
return ret;
|
||||
return -EINPROGRESS;
|
||||
default:
|
||||
return -ENOSYS;
|
||||
}
|
||||
@ -33,17 +98,29 @@ static __efi_runtime int x86_sysreset_request(struct udevice *dev,
|
||||
return -EINPROGRESS;
|
||||
}
|
||||
|
||||
static int x86_sysreset_get_last(struct udevice *dev)
|
||||
{
|
||||
return SYSRESET_POWER;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_EFI_LOADER
|
||||
void __efi_runtime EFIAPI efi_reset_system(
|
||||
enum efi_reset_type reset_type,
|
||||
efi_status_t reset_status,
|
||||
unsigned long data_size, void *reset_data)
|
||||
{
|
||||
int value;
|
||||
|
||||
/*
|
||||
* inline this code since we are not caused in the context of a
|
||||
* udevice and passing NULL to x86_sysreset_request() is too horrible.
|
||||
*/
|
||||
if (reset_type == EFI_RESET_COLD ||
|
||||
reset_type == EFI_RESET_PLATFORM_SPECIFIC)
|
||||
x86_sysreset_request(NULL, SYSRESET_COLD);
|
||||
else if (reset_type == EFI_RESET_WARM)
|
||||
x86_sysreset_request(NULL, SYSRESET_WARM);
|
||||
value = SYS_RST | RST_CPU | FULL_RST;
|
||||
else /* assume EFI_RESET_WARM since we cannot return an error */
|
||||
value = SYS_RST | RST_CPU;
|
||||
outb(value, IO_PORT_RESET);
|
||||
|
||||
/* TODO EFI_RESET_SHUTDOWN */
|
||||
|
||||
@ -51,6 +128,15 @@ void __efi_runtime EFIAPI efi_reset_system(
|
||||
}
|
||||
#endif
|
||||
|
||||
static int x86_sysreset_probe(struct udevice *dev)
|
||||
{
|
||||
struct x86_sysreset_platdata *plat = dev_get_platdata(dev);
|
||||
|
||||
/* Locate the PCH if there is one. It isn't essential */
|
||||
uclass_first_device(UCLASS_PCH, &plat->pch);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct udevice_id x86_sysreset_ids[] = {
|
||||
{ .compatible = "x86,reset" },
|
||||
@ -59,6 +145,7 @@ static const struct udevice_id x86_sysreset_ids[] = {
|
||||
|
||||
static struct sysreset_ops x86_sysreset_ops = {
|
||||
.request = x86_sysreset_request,
|
||||
.get_last = x86_sysreset_get_last,
|
||||
};
|
||||
|
||||
U_BOOT_DRIVER(x86_sysreset) = {
|
||||
@ -66,4 +153,6 @@ U_BOOT_DRIVER(x86_sysreset) = {
|
||||
.id = UCLASS_SYSRESET,
|
||||
.of_match = x86_sysreset_ids,
|
||||
.ops = &x86_sysreset_ops,
|
||||
.probe = x86_sysreset_probe,
|
||||
.platdata_auto_alloc_size = sizeof(struct x86_sysreset_platdata),
|
||||
};
|
||||
|
@ -18,9 +18,6 @@
|
||||
#define CONFIG_ENV_SECT_SIZE 0x1000
|
||||
#define CONFIG_ENV_OFFSET 0x003f8000
|
||||
|
||||
#define BOOT_DEVICE_SPI 10
|
||||
|
||||
#define CONFIG_SPL_BOARD_LOAD_IMAGE
|
||||
#define BOOT_DEVICE_BOARD 11
|
||||
|
||||
#endif /* __CONFIG_H */
|
||||
|
@ -23,4 +23,6 @@
|
||||
#define CONFIG_ENV_SECT_SIZE 0x1000
|
||||
#define CONFIG_ENV_OFFSET 0x003f8000
|
||||
|
||||
#define CONFIG_TPL_TEXT_BASE 0xfffd8000
|
||||
|
||||
#endif /* __CONFIG_H */
|
||||
|
@ -33,11 +33,6 @@
|
||||
#define CONFIG_SYS_ATA_IDE1_OFFSET 0x170
|
||||
#define CONFIG_ATAPI
|
||||
|
||||
/* SPI is not supported */
|
||||
|
||||
#define BOOT_DEVICE_SPI 10
|
||||
|
||||
#define CONFIG_SPL_BOARD_LOAD_IMAGE
|
||||
#define BOOT_DEVICE_BOARD 11
|
||||
|
||||
#endif /* __CONFIG_H */
|
||||
|
@ -36,7 +36,6 @@
|
||||
/*-----------------------------------------------------------------------
|
||||
* Real Time Clock Configuration
|
||||
*/
|
||||
#define CONFIG_RTC_MC146818
|
||||
#define CONFIG_SYS_ISA_IO_BASE_ADDRESS 0
|
||||
#define CONFIG_SYS_ISA_IO CONFIG_SYS_ISA_IO_BASE_ADDRESS
|
||||
|
||||
|
@ -16,6 +16,9 @@ enum pch_req_t {
|
||||
/* Returns HDA config info if Azalia V1CTL enabled, -ENOENT if not */
|
||||
PCH_REQ_HDA_CONFIG,
|
||||
|
||||
/* Fills out a struct pch_pmbase_info if available */
|
||||
PCH_REQ_PMBASE_INFO,
|
||||
|
||||
PCH_REQ_TEST1, /* Test requests for sandbox driver */
|
||||
PCH_REQ_TEST2,
|
||||
PCH_REQ_TEST3,
|
||||
@ -23,6 +26,21 @@ enum pch_req_t {
|
||||
PCH_REQ_COUNT, /* Number of ioctrls supported */
|
||||
};
|
||||
|
||||
/**
|
||||
* struct pch_pmbase_info - Information filled in by PCH_REQ_PMBASE_INFO
|
||||
*
|
||||
* @pmbase: IO address of power-management controller
|
||||
* @gpio0_en_ofs: Offset of GPIO0 enable register
|
||||
* @pm1_sts_ofs: Offset of status register
|
||||
* @pm1_cnt_ofs: Offset of control register
|
||||
*/
|
||||
struct pch_pmbase_info {
|
||||
u16 base;
|
||||
u8 gpio0_en_ofs;
|
||||
u8 pm1_sts_ofs;
|
||||
u8 pm1_cnt_ofs;
|
||||
};
|
||||
|
||||
/**
|
||||
* struct pch_ops - Operations for the Platform Controller Hub
|
||||
*
|
||||
|
@ -546,11 +546,7 @@ extern void pci_cfgfunc_do_nothing(struct pci_controller* hose, pci_dev_t dev,
|
||||
extern void pci_cfgfunc_config_device(struct pci_controller* hose, pci_dev_t dev,
|
||||
struct pci_config_table *);
|
||||
|
||||
#ifdef CONFIG_NR_DRAM_BANKS
|
||||
#define MAX_PCI_REGIONS (CONFIG_NR_DRAM_BANKS + 7)
|
||||
#else
|
||||
#define MAX_PCI_REGIONS 7
|
||||
#endif
|
||||
#define MAX_PCI_REGIONS 7
|
||||
|
||||
#define INDIRECT_TYPE_NO_PCIE_LINK 1
|
||||
|
||||
|
@ -228,7 +228,11 @@ ifeq ($(CONFIG_SYS_SOC),"at91")
|
||||
ALL-y += $(obj)/boot.bin
|
||||
endif
|
||||
|
||||
ifdef CONFIG_TPL_BUILD
|
||||
ALL-$(CONFIG_TPL_X86_16BIT_INIT) += $(obj)/u-boot-x86-16bit-tpl.bin
|
||||
else
|
||||
ALL-$(CONFIG_SPL_X86_16BIT_INIT) += $(obj)/u-boot-x86-16bit-spl.bin
|
||||
endif
|
||||
|
||||
ALL-$(CONFIG_ARCH_ZYNQ) += $(obj)/boot.bin
|
||||
ALL-$(CONFIG_ARCH_ZYNQMP) += $(obj)/boot.bin
|
||||
@ -253,8 +257,20 @@ else
|
||||
FINAL_DTB_CONTAINER = $(obj)/$(SPL_BIN).multidtb.fit
|
||||
endif
|
||||
|
||||
# Build the .dtb file if:
|
||||
# - we are not using OF_PLATDATA
|
||||
# - we are using OF_CONTROL
|
||||
# - we have either OF_SEPARATE or OF_HOSTFILE
|
||||
build_dtb :=
|
||||
ifeq ($(CONFIG_$(SPL_TPL_)OF_PLATDATA),)
|
||||
ifneq ($(CONFIG_$(SPL_TPL_)OF_CONTROL),)
|
||||
ifeq ($(CONFIG_OF_SEPARATE)$(CONFIG_OF_HOSTFILE),y)
|
||||
build_dtb := y
|
||||
endif
|
||||
endif
|
||||
endif
|
||||
|
||||
ifeq ($(CONFIG_$(SPL_TPL_)OF_CONTROL)$(CONFIG_OF_SEPARATE)$(CONFIG_$(SPL_TPL_)OF_PLATDATA),yy)
|
||||
ifneq ($(build_dtb),)
|
||||
$(obj)/$(SPL_BIN)-dtb.bin: $(obj)/$(SPL_BIN)-nodtb.bin \
|
||||
$(if $(CONFIG_SPL_SEPARATE_BSS),,$(obj)/$(SPL_BIN)-pad.bin) \
|
||||
$(FINAL_DTB_CONTAINER) FORCE
|
||||
@ -316,7 +332,7 @@ quiet_cmd_objcopy = OBJCOPY $@
|
||||
cmd_objcopy = $(OBJCOPY) $(OBJCOPYFLAGS) $(OBJCOPYFLAGS_$(@F)) $< $@
|
||||
|
||||
OBJCOPYFLAGS_$(SPL_BIN)-nodtb.bin = $(SPL_OBJCFLAGS) -O binary \
|
||||
$(if $(CONFIG_SPL_X86_16BIT_INIT),-R .start16 -R .resetvec)
|
||||
$(if $(CONFIG_$(SPL_TPL_)X86_16BIT_INIT),-R .start16 -R .resetvec)
|
||||
|
||||
$(obj)/$(SPL_BIN)-nodtb.bin: $(obj)/$(SPL_BIN) FORCE
|
||||
$(call if_changed,objcopy)
|
||||
@ -325,6 +341,10 @@ OBJCOPYFLAGS_u-boot-x86-16bit-spl.bin := -O binary -j .start16 -j .resetvec
|
||||
$(obj)/u-boot-x86-16bit-spl.bin: $(obj)/u-boot-spl FORCE
|
||||
$(call if_changed,objcopy)
|
||||
|
||||
OBJCOPYFLAGS_u-boot-x86-16bit-tpl.bin := -O binary -j .start16 -j .resetvec
|
||||
$(obj)/u-boot-x86-16bit-tpl.bin: $(obj)/u-boot-tpl FORCE
|
||||
$(call if_changed,objcopy)
|
||||
|
||||
LDFLAGS_$(SPL_BIN) += -T u-boot-spl.lds $(LDFLAGS_FINAL)
|
||||
|
||||
# Avoid 'Not enough room for program headers' error on binutils 2.28 onwards.
|
||||
|
@ -342,6 +342,13 @@ size:
|
||||
Sets the image size in bytes, for example 'size = <0x100000>' for a
|
||||
1MB image.
|
||||
|
||||
offset:
|
||||
This is similar to 'offset' in entries, setting the offset of a section
|
||||
within the image or section containing it. The first byte of the section
|
||||
is normally at offset 0. If 'offset' is not provided, binman sets it to
|
||||
the end of the previous region, or the start of the image's entry area
|
||||
(normally 0) if there is no previous region.
|
||||
|
||||
align-size:
|
||||
This sets the alignment of the image size. For example, to ensure
|
||||
that the image ends on a 512-byte boundary, use 'align-size = <512>'.
|
||||
|
@ -57,7 +57,7 @@ class Section(object):
|
||||
self._name = name
|
||||
self._node = node
|
||||
self._image = image
|
||||
self._offset = 0
|
||||
self._offset = None
|
||||
self._size = None
|
||||
self._align_size = None
|
||||
self._pad_before = 0
|
||||
@ -75,6 +75,7 @@ class Section(object):
|
||||
|
||||
def _ReadNode(self):
|
||||
"""Read properties from the section node"""
|
||||
self._offset = fdt_util.GetInt(self._node, 'offset')
|
||||
self._size = fdt_util.GetInt(self._node, 'size')
|
||||
self._align_size = fdt_util.GetInt(self._node, 'align-size')
|
||||
if tools.NotPowerOfTwo(self._align_size):
|
||||
@ -130,7 +131,7 @@ class Section(object):
|
||||
entry.AddMissingProperties()
|
||||
|
||||
def SetCalculatedProperties(self):
|
||||
state.SetInt(self._node, 'offset', self._offset)
|
||||
state.SetInt(self._node, 'offset', self._offset or 0)
|
||||
state.SetInt(self._node, 'size', self._size)
|
||||
image_pos = self._image_pos
|
||||
if self._parent_section:
|
||||
@ -424,8 +425,8 @@ class Section(object):
|
||||
Args:
|
||||
fd: File to write the map to
|
||||
"""
|
||||
Entry.WriteMapLine(fd, indent, self._name, self._offset, self._size,
|
||||
self._image_pos)
|
||||
Entry.WriteMapLine(fd, indent, self._name, self._offset or 0,
|
||||
self._size, self._image_pos)
|
||||
for entry in self._entries.values():
|
||||
entry.WriteMap(fd, indent + 1)
|
||||
|
||||
|
@ -133,8 +133,8 @@ def Binman(options, args):
|
||||
if name not in options.image:
|
||||
del images[name]
|
||||
skip.append(name)
|
||||
if skip:
|
||||
print 'Skipping images: %s\n' % ', '.join(skip)
|
||||
if skip and options.verbosity >= 2:
|
||||
print 'Skipping images: %s' % ', '.join(skip)
|
||||
|
||||
state.Prepare(images, dtb)
|
||||
|
||||
|
@ -67,7 +67,8 @@ class Entry_section(Entry):
|
||||
def Pack(self, offset):
|
||||
"""Pack all entries into the section"""
|
||||
self._section.PackEntries()
|
||||
self._section.SetOffset(offset)
|
||||
if self._section._offset is None:
|
||||
self._section.SetOffset(offset)
|
||||
self.size = self._section.GetSize()
|
||||
return super(Entry_section, self).Pack(offset)
|
||||
|
||||
|
@ -51,10 +51,10 @@ class Entry_text(Entry):
|
||||
self.text_label, = self.GetEntryArgsOrProps(
|
||||
[EntryArg('text-label', str)])
|
||||
self.value, = self.GetEntryArgsOrProps([EntryArg(self.text_label, str)])
|
||||
|
||||
def ObtainContents(self):
|
||||
if not self.value:
|
||||
self.Raise("No value provided for text label '%s'" %
|
||||
self.text_label)
|
||||
|
||||
def ObtainContents(self):
|
||||
self.SetContents(self.value)
|
||||
return True
|
||||
|
@ -18,6 +18,7 @@ class Entry_vblock(Entry):
|
||||
"""An entry which contains a Chromium OS verified boot block
|
||||
|
||||
Properties / Entry arguments:
|
||||
- content: List of phandles to entries to sign
|
||||
- keydir: Directory containing the public keys to use
|
||||
- keyblock: Name of the key file to use (inside keydir)
|
||||
- signprivate: Name of provide key file to use (inside keydir)
|
||||
|
@ -187,7 +187,8 @@ class TestFunctional(unittest.TestCase):
|
||||
return control.Binman(options, args)
|
||||
|
||||
def _DoTestFile(self, fname, debug=False, map=False, update_dtb=False,
|
||||
entry_args=None, images=None, use_real_dtb=False):
|
||||
entry_args=None, images=None, use_real_dtb=False,
|
||||
verbosity=None):
|
||||
"""Run binman with a given test file
|
||||
|
||||
Args:
|
||||
@ -210,6 +211,8 @@ class TestFunctional(unittest.TestCase):
|
||||
args.append('-up')
|
||||
if not use_real_dtb:
|
||||
args.append('--fake-dtb')
|
||||
if verbosity is not None:
|
||||
args.append('-v%d' % verbosity)
|
||||
if entry_args:
|
||||
for arg, value in entry_args.iteritems():
|
||||
args.append('-a%s=%s' % (arg, value))
|
||||
@ -1459,13 +1462,22 @@ class TestFunctional(unittest.TestCase):
|
||||
|
||||
def testSelectImage(self):
|
||||
"""Test that we can select which images to build"""
|
||||
with test_util.capture_sys_output() as (stdout, stderr):
|
||||
retcode = self._DoTestFile('006_dual_image.dts', images=['image2'])
|
||||
self.assertEqual(0, retcode)
|
||||
self.assertIn('Skipping images: image1', stdout.getvalue())
|
||||
expected = 'Skipping images: image1'
|
||||
|
||||
self.assertFalse(os.path.exists(tools.GetOutputFilename('image1.bin')))
|
||||
self.assertTrue(os.path.exists(tools.GetOutputFilename('image2.bin')))
|
||||
# We should only get the expected message in verbose mode
|
||||
for verbosity in (None, 2):
|
||||
with test_util.capture_sys_output() as (stdout, stderr):
|
||||
retcode = self._DoTestFile('006_dual_image.dts',
|
||||
verbosity=verbosity,
|
||||
images=['image2'])
|
||||
self.assertEqual(0, retcode)
|
||||
if verbosity:
|
||||
self.assertIn(expected, stdout.getvalue())
|
||||
else:
|
||||
self.assertNotIn(expected, stdout.getvalue())
|
||||
|
||||
self.assertFalse(os.path.exists(tools.GetOutputFilename('image1.bin')))
|
||||
self.assertTrue(os.path.exists(tools.GetOutputFilename('image2.bin')))
|
||||
|
||||
def testUpdateFdtAll(self):
|
||||
"""Test that all device trees are updated with offset/size info"""
|
||||
@ -1771,6 +1783,24 @@ class TestFunctional(unittest.TestCase):
|
||||
data = self._DoReadFile('100_intel_refcode.dts')
|
||||
self.assertEqual(REFCODE_DATA, data[:len(REFCODE_DATA)])
|
||||
|
||||
def testSectionOffset(self):
|
||||
"""Tests use of a section with an offset"""
|
||||
data, _, map_data, _ = self._DoReadFileDtb('101_sections_offset.dts',
|
||||
map=True)
|
||||
self.assertEqual('''ImagePos Offset Size Name
|
||||
00000000 00000000 00000038 main-section
|
||||
00000004 00000004 00000010 section@0
|
||||
00000004 00000000 00000004 u-boot
|
||||
00000018 00000018 00000010 section@1
|
||||
00000018 00000000 00000004 u-boot
|
||||
0000002c 0000002c 00000004 section@2
|
||||
0000002c 00000000 00000004 u-boot
|
||||
''', map_data)
|
||||
self.assertEqual(data,
|
||||
4 * chr(0x26) + U_BOOT_DATA + 12 * chr(0x21) +
|
||||
4 * chr(0x26) + U_BOOT_DATA + 12 * chr(0x61) +
|
||||
4 * chr(0x26) + U_BOOT_DATA + 8 * chr(0x26))
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
unittest.main()
|
||||
|
35
tools/binman/test/101_sections_offset.dts
Normal file
35
tools/binman/test/101_sections_offset.dts
Normal file
@ -0,0 +1,35 @@
|
||||
// SPDX-License-Identifier: GPL-2.0+
|
||||
|
||||
/dts-v1/;
|
||||
|
||||
/ {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <1>;
|
||||
|
||||
binman {
|
||||
pad-byte = <0x26>;
|
||||
size = <0x38>;
|
||||
section@0 {
|
||||
read-only;
|
||||
offset = <0x4>;
|
||||
size = <0x10>;
|
||||
pad-byte = <0x21>;
|
||||
|
||||
u-boot {
|
||||
};
|
||||
};
|
||||
section@1 {
|
||||
size = <0x10>;
|
||||
pad-byte = <0x61>;
|
||||
offset = <0x18>;
|
||||
|
||||
u-boot {
|
||||
};
|
||||
};
|
||||
section@2 {
|
||||
offset = <0x2c>;
|
||||
u-boot {
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
Loading…
Reference in New Issue
Block a user