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
64 changed files with 2076 additions and 995 deletions
1
Makefile
1
Makefile
|
@ -1380,6 +1380,7 @@ cmd_ldr = $(LD) $(LDFLAGS_$(@F)) \
|
||||||
|
|
||||||
u-boot.rom: u-boot-x86-16bit.bin u-boot.bin \
|
u-boot.rom: u-boot-x86-16bit.bin u-boot.bin \
|
||||||
$(if $(CONFIG_SPL_X86_16BIT_INIT),spl/u-boot-spl.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
|
$(if $(CONFIG_HAVE_REFCODE),refcode.bin) FORCE
|
||||||
$(call if_changed,binman)
|
$(call if_changed,binman)
|
||||||
|
|
||||||
|
|
32
arch/Kconfig
32
arch/Kconfig
|
@ -126,6 +126,8 @@ config SH
|
||||||
|
|
||||||
config X86
|
config X86
|
||||||
bool "x86 architecture"
|
bool "x86 architecture"
|
||||||
|
select SUPPORT_SPL
|
||||||
|
select SUPPORT_TPL
|
||||||
select CREATE_ARCH_SYMLINK
|
select CREATE_ARCH_SYMLINK
|
||||||
select DM
|
select DM
|
||||||
select DM_PCI
|
select DM_PCI
|
||||||
|
@ -163,6 +165,36 @@ config X86
|
||||||
imply USB_ETHER_SMSC95XX
|
imply USB_ETHER_SMSC95XX
|
||||||
imply USB_HOST_ETHER
|
imply USB_HOST_ETHER
|
||||||
imply PCH
|
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
|
config XTENSA
|
||||||
bool "Xtensa architecture"
|
bool "Xtensa architecture"
|
||||||
|
|
|
@ -32,7 +32,6 @@ config X86_RUN_32BIT
|
||||||
config X86_RUN_64BIT
|
config X86_RUN_64BIT
|
||||||
bool "64-bit"
|
bool "64-bit"
|
||||||
select X86_64
|
select X86_64
|
||||||
select SUPPORT_SPL
|
|
||||||
select SPL
|
select SPL
|
||||||
select SPL_SEPARATE_BSS
|
select SPL_SEPARATE_BSS
|
||||||
help
|
help
|
||||||
|
@ -177,10 +176,17 @@ config X86_16BIT_INIT
|
||||||
config SPL_X86_16BIT_INIT
|
config SPL_X86_16BIT_INIT
|
||||||
bool
|
bool
|
||||||
depends on X86_RESET_VECTOR
|
depends on X86_RESET_VECTOR
|
||||||
default y if X86_RESET_VECTOR && SPL
|
default y if X86_RESET_VECTOR && SPL && !TPL
|
||||||
help
|
help
|
||||||
This is enabled when 16-bit init is in SPL
|
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
|
config X86_32BIT_INIT
|
||||||
bool
|
bool
|
||||||
depends on X86_RESET_VECTOR
|
depends on X86_RESET_VECTOR
|
||||||
|
|
|
@ -4,12 +4,24 @@ ifeq ($(CONFIG_EFI_APP),)
|
||||||
ifdef CONFIG_$(SPL_)X86_64
|
ifdef CONFIG_$(SPL_)X86_64
|
||||||
head-y := arch/x86/cpu/start64.o
|
head-y := arch/x86/cpu/start64.o
|
||||||
else
|
else
|
||||||
|
ifeq ($(CONFIG_$(SPL_TPL_)X86_16BIT_INIT),y)
|
||||||
head-y := arch/x86/cpu/start.o
|
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
|
||||||
|
endif
|
||||||
|
endif # EFI
|
||||||
|
|
||||||
head-$(CONFIG_$(SPL_)X86_16BIT_INIT) += arch/x86/cpu/start16.o
|
head-$(CONFIG_$(SPL_TPL_)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/resetvec.o
|
||||||
|
|
||||||
libs-y += arch/x86/cpu/
|
libs-y += arch/x86/cpu/
|
||||||
libs-y += arch/x86/lib/
|
libs-y += arch/x86/lib/
|
||||||
|
|
|
@ -9,9 +9,22 @@
|
||||||
ifeq ($(CONFIG_$(SPL_)X86_64),y)
|
ifeq ($(CONFIG_$(SPL_)X86_64),y)
|
||||||
extra-y = start64.o
|
extra-y = start64.o
|
||||||
else
|
else
|
||||||
|
ifeq ($(CONFIG_$(SPL_TPL_)X86_16BIT_INIT),y)
|
||||||
extra-y = start.o
|
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
|
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
|
obj-y += cpu.o cpu_x86.o
|
||||||
|
|
||||||
|
|
|
@ -3,7 +3,24 @@
|
||||||
# Copyright (c) 2016 Google, Inc
|
# Copyright (c) 2016 Google, Inc
|
||||||
|
|
||||||
obj-y += adsp.o
|
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 += iobp.o
|
||||||
obj-y += lpc.o
|
obj-y += lpc.o
|
||||||
obj-y += me.o
|
obj-y += me.o
|
||||||
|
@ -11,6 +28,6 @@ obj-y += northbridge.o
|
||||||
obj-y += pch.o
|
obj-y += pch.o
|
||||||
obj-y += pinctrl_broadwell.o
|
obj-y += pinctrl_broadwell.o
|
||||||
obj-y += power_state.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 += 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_x86.h>
|
||||||
#include <asm/cpu_common.h>
|
#include <asm/cpu_common.h>
|
||||||
#include <asm/intel_regs.h>
|
#include <asm/intel_regs.h>
|
||||||
|
#include <asm/lpc_common.h>
|
||||||
#include <asm/msr.h>
|
#include <asm/msr.h>
|
||||||
|
#include <asm/pci.h>
|
||||||
#include <asm/post.h>
|
#include <asm/post.h>
|
||||||
#include <asm/turbo.h>
|
#include <asm/turbo.h>
|
||||||
#include <asm/arch/cpu.h>
|
#include <asm/arch/cpu.h>
|
||||||
#include <asm/arch/pch.h>
|
#include <asm/arch/pch.h>
|
||||||
#include <asm/arch/rcb.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)
|
int arch_cpu_init_dm(void)
|
||||||
{
|
{
|
||||||
struct udevice *dev;
|
struct udevice *dev;
|
||||||
|
@ -156,613 +96,13 @@ int print_cpuinfo(void)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
void board_debug_uart_init(void)
|
||||||
* 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;
|
struct udevice *bus = NULL;
|
||||||
const int delay_step = 10;
|
|
||||||
|
|
||||||
wait_count = 0;
|
/* com1 / com2 decode range */
|
||||||
do {
|
pci_x86_write_config(bus, PCH_DEV_LPC, LPC_IO_DEC, 1 << 4, PCI_SIZE_16);
|
||||||
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;
|
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 <common.h>
|
||||||
#include <dm.h>
|
#include <dm.h>
|
||||||
#include <asm/io.h>
|
#include <asm/io.h>
|
||||||
|
#include <asm/mrc_common.h>
|
||||||
#include <asm/arch/iomap.h>
|
#include <asm/arch/iomap.h>
|
||||||
#include <asm/arch/pch.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)
|
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)
|
static int broadwell_pch_probe(struct udevice *dev)
|
||||||
{
|
{
|
||||||
if (!(gd->flags & GD_FLG_RELOC))
|
if (CONFIG_IS_ENABLED(X86_32BIT_INIT)) {
|
||||||
return broadwell_pch_early_init(dev);
|
if (!(gd->flags & GD_FLG_RELOC))
|
||||||
else
|
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);
|
return broadwell_pch_init(dev);
|
||||||
|
} else {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static int broadwell_pch_get_spi_base(struct udevice *dev, ulong *sbasep)
|
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;
|
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 = {
|
static const struct pch_ops broadwell_pch_ops = {
|
||||||
.get_spi_base = broadwell_pch_get_spi_base,
|
.get_spi_base = broadwell_pch_get_spi_base,
|
||||||
.set_spi_protect = broadwell_set_spi_protect,
|
.set_spi_protect = broadwell_set_spi_protect,
|
||||||
.get_gpio_base = broadwell_get_gpio_base,
|
.get_gpio_base = broadwell_get_gpio_base,
|
||||||
|
.ioctl = broadwell_ioctl,
|
||||||
};
|
};
|
||||||
|
|
||||||
static const struct udevice_id broadwell_pch_ids[] = {
|
static const struct udevice_id broadwell_pch_ids[] = {
|
||||||
|
|
|
@ -34,99 +34,6 @@ int dram_init_banksize(void)
|
||||||
return 0;
|
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)
|
static unsigned long get_top_of_ram(struct udevice *dev)
|
||||||
{
|
{
|
||||||
/*
|
/*
|
||||||
|
@ -204,16 +111,18 @@ int dram_init(void)
|
||||||
|
|
||||||
/* Print ME state before MRC */
|
/* Print ME state before MRC */
|
||||||
ret = syscon_get_by_driver_data(X86_SYSCON_ME, &me_dev);
|
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;
|
return ret;
|
||||||
|
}
|
||||||
intel_me_status(me_dev);
|
intel_me_status(me_dev);
|
||||||
|
|
||||||
/* Save ME HSIO version */
|
/* Save ME HSIO version */
|
||||||
ret = uclass_first_device(UCLASS_PCH, &pch_dev);
|
ret = uclass_first_device_err(UCLASS_PCH, &pch_dev);
|
||||||
if (ret)
|
if (ret) {
|
||||||
|
debug("Cannot get PCH (err=%d)\n", ret);
|
||||||
return ret;
|
return ret;
|
||||||
if (!pch_dev)
|
}
|
||||||
return -ENODEV;
|
|
||||||
power_state_get(pch_dev, &ps);
|
power_state_get(pch_dev, &ps);
|
||||||
|
|
||||||
intel_me_hsio_version(me_dev, &ps.hsio_version, &ps.hsio_checksum);
|
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);
|
broadwell_fill_pei_data(pei_data);
|
||||||
mainboard_fill_pei_data(pei_data);
|
mainboard_fill_pei_data(pei_data);
|
||||||
|
|
||||||
ret = uclass_first_device(UCLASS_NORTHBRIDGE, &dev);
|
ret = uclass_first_device_err(UCLASS_NORTHBRIDGE, &dev);
|
||||||
if (ret)
|
if (ret) {
|
||||||
|
debug("Cannot get Northbridge (err=%d)\n", ret);
|
||||||
return ret;
|
return ret;
|
||||||
if (!dev)
|
}
|
||||||
return -ENODEV;
|
|
||||||
size = 256;
|
size = 256;
|
||||||
ret = mrc_locate_spd(dev, size, &spd_data);
|
ret = mrc_locate_spd(dev, size, &spd_data);
|
||||||
if (ret)
|
if (ret) {
|
||||||
|
debug("Cannot locate SPD (err=%d)\n", ret);
|
||||||
return ret;
|
return ret;
|
||||||
|
}
|
||||||
memcpy(pei_data->spd_data[0][0], spd_data, size);
|
memcpy(pei_data->spd_data[0][0], spd_data, size);
|
||||||
memcpy(pei_data->spd_data[1][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);
|
debug("PEI version %#x\n", pei_data->pei_version);
|
||||||
ret = mrc_common_init(dev, pei_data, true);
|
ret = mrc_common_init(dev, pei_data, true);
|
||||||
if (ret)
|
if (ret) {
|
||||||
|
debug("mrc_common_init() failed(err=%d)\n", ret);
|
||||||
return ret;
|
return ret;
|
||||||
|
}
|
||||||
debug("Memory init done\n");
|
debug("Memory init done\n");
|
||||||
|
|
||||||
ret = sdram_find(dev);
|
ret = sdram_find(dev);
|
||||||
if (ret)
|
if (ret) {
|
||||||
|
debug("sdram_find() failed (err=%d)\n", ret);
|
||||||
return ret;
|
return ret;
|
||||||
|
}
|
||||||
gd->ram_size = gd->arch.meminfo.total_32bit_memory;
|
gd->ram_size = gd->arch.meminfo.total_32bit_memory;
|
||||||
debug("RAM size %llx\n", (unsigned long long)gd->ram_size);
|
debug("RAM size %llx\n", (unsigned long long)gd->ram_size);
|
||||||
|
|
||||||
|
@ -279,17 +194,6 @@ int misc_init_r(void)
|
||||||
return 0;
|
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[] = {
|
static const struct udevice_id broadwell_syscon_ids[] = {
|
||||||
{ .compatible = "intel,me", .data = X86_SYSCON_ME },
|
{ .compatible = "intel,me", .data = X86_SYSCON_ME },
|
||||||
{ }
|
{ }
|
||||||
|
|
|
@ -309,21 +309,22 @@ u32 cpu_get_stepping(void)
|
||||||
return gd->arch.x86_mask;
|
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 em_rst = ~X86_CR0_EM;
|
||||||
const u32 mp_ne_set = X86_CR0_MP | X86_CR0_NE;
|
const u32 mp_ne_set = X86_CR0_MP | X86_CR0_NE;
|
||||||
|
|
||||||
if (ll_boot_init()) {
|
asm ("fninit\n" \
|
||||||
/* initialize FPU, reset EM, set MP and NE */
|
"movl %%cr0, %%eax\n" \
|
||||||
asm ("fninit\n" \
|
"andl %0, %%eax\n" \
|
||||||
"movl %%cr0, %%eax\n" \
|
"orl %1, %%eax\n" \
|
||||||
"andl %0, %%eax\n" \
|
"movl %%eax, %%cr0\n" \
|
||||||
"orl %1, %%eax\n" \
|
: : "i" (em_rst), "i" (mp_ne_set) : "eax");
|
||||||
"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 */
|
/* identify CPU via cpuid and store the decoded info into gd->arch */
|
||||||
if (has_cpuid()) {
|
if (has_cpuid()) {
|
||||||
struct cpu_device_id cpu;
|
struct cpu_device_id cpu;
|
||||||
|
@ -339,46 +340,70 @@ int x86_cpu_init_f(void)
|
||||||
|
|
||||||
gd->arch.has_mtrr = has_mtrr();
|
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;
|
gd->pci_ram_top = 0x80000000U;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void setup_mtrr(void)
|
||||||
|
{
|
||||||
|
u64 mtrr_cap;
|
||||||
|
|
||||||
/* Configure fixed range MTRRs for some legacy regions */
|
/* Configure fixed range MTRRs for some legacy regions */
|
||||||
if (gd->arch.has_mtrr) {
|
if (!gd->arch.has_mtrr)
|
||||||
u64 mtrr_cap;
|
return;
|
||||||
|
|
||||||
mtrr_cap = native_read_msr(MTRR_CAP_MSR);
|
mtrr_cap = native_read_msr(MTRR_CAP_MSR);
|
||||||
if (mtrr_cap & MTRR_CAP_FIX) {
|
if (mtrr_cap & MTRR_CAP_FIX) {
|
||||||
/* Mark the VGA RAM area as uncacheable */
|
/* Mark the VGA RAM area as uncacheable */
|
||||||
native_write_msr(MTRR_FIX_16K_A0000_MSR,
|
native_write_msr(MTRR_FIX_16K_A0000_MSR,
|
||||||
MTRR_FIX_TYPE(MTRR_TYPE_UNCACHEABLE),
|
MTRR_FIX_TYPE(MTRR_TYPE_UNCACHEABLE),
|
||||||
MTRR_FIX_TYPE(MTRR_TYPE_UNCACHEABLE));
|
MTRR_FIX_TYPE(MTRR_TYPE_UNCACHEABLE));
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Mark the PCI ROM area as cacheable to improve ROM
|
* Mark the PCI ROM area as cacheable to improve ROM
|
||||||
* execution performance.
|
* execution performance.
|
||||||
*/
|
*/
|
||||||
native_write_msr(MTRR_FIX_4K_C0000_MSR,
|
native_write_msr(MTRR_FIX_4K_C0000_MSR,
|
||||||
MTRR_FIX_TYPE(MTRR_TYPE_WRBACK),
|
MTRR_FIX_TYPE(MTRR_TYPE_WRBACK),
|
||||||
MTRR_FIX_TYPE(MTRR_TYPE_WRBACK));
|
MTRR_FIX_TYPE(MTRR_TYPE_WRBACK));
|
||||||
native_write_msr(MTRR_FIX_4K_C8000_MSR,
|
native_write_msr(MTRR_FIX_4K_C8000_MSR,
|
||||||
MTRR_FIX_TYPE(MTRR_TYPE_WRBACK),
|
MTRR_FIX_TYPE(MTRR_TYPE_WRBACK),
|
||||||
MTRR_FIX_TYPE(MTRR_TYPE_WRBACK));
|
MTRR_FIX_TYPE(MTRR_TYPE_WRBACK));
|
||||||
native_write_msr(MTRR_FIX_4K_D0000_MSR,
|
native_write_msr(MTRR_FIX_4K_D0000_MSR,
|
||||||
MTRR_FIX_TYPE(MTRR_TYPE_WRBACK),
|
MTRR_FIX_TYPE(MTRR_TYPE_WRBACK),
|
||||||
MTRR_FIX_TYPE(MTRR_TYPE_WRBACK));
|
MTRR_FIX_TYPE(MTRR_TYPE_WRBACK));
|
||||||
native_write_msr(MTRR_FIX_4K_D8000_MSR,
|
native_write_msr(MTRR_FIX_4K_D8000_MSR,
|
||||||
MTRR_FIX_TYPE(MTRR_TYPE_WRBACK),
|
MTRR_FIX_TYPE(MTRR_TYPE_WRBACK),
|
||||||
MTRR_FIX_TYPE(MTRR_TYPE_WRBACK));
|
MTRR_FIX_TYPE(MTRR_TYPE_WRBACK));
|
||||||
|
|
||||||
/* Enable the fixed range MTRRs */
|
/* Enable the fixed range MTRRs */
|
||||||
msr_setbits_64(MTRR_DEF_TYPE_MSR, MTRR_DEF_TYPE_FIX_EN);
|
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 */
|
/* Set up the i8254 timer if required */
|
||||||
i8254_init();
|
if (IS_ENABLED(CONFIG_I8254_TIMER))
|
||||||
#endif
|
i8254_init();
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int x86_cpu_reinit_f(void)
|
||||||
|
{
|
||||||
|
setup_identity();
|
||||||
|
setup_pci_ram_top();
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,14 +3,23 @@
|
||||||
# Copyright (c) 2016 Google, Inc
|
# Copyright (c) 2016 Google, Inc
|
||||||
|
|
||||||
ifdef CONFIG_HAVE_MRC
|
ifdef CONFIG_HAVE_MRC
|
||||||
obj-$(CONFIG_$(SPL_)X86_32BIT_INIT) += car.o
|
obj-$(CONFIG_$(SPL_TPL_)X86_16BIT_INIT) += car.o
|
||||||
obj-$(CONFIG_$(SPL_)X86_32BIT_INIT) += me_status.o
|
obj-$(CONFIG_$(SPL_TPL_)X86_32BIT_INIT) += me_status.o
|
||||||
obj-$(CONFIG_$(SPL_)X86_32BIT_INIT) += report_platform.o
|
obj-$(CONFIG_$(SPL_TPL_)X86_32BIT_INIT) += report_platform.o
|
||||||
obj-$(CONFIG_$(SPL_)X86_32BIT_INIT) += mrc.o
|
obj-$(CONFIG_$(SPL_TPL_)X86_32BIT_INIT) += mrc.o
|
||||||
endif
|
endif
|
||||||
obj-y += cpu.o
|
obj-y += cpu.o
|
||||||
obj-y += lpc.o
|
obj-y += lpc.o
|
||||||
ifndef CONFIG_TARGET_EFI_APP
|
ifndef CONFIG_TARGET_EFI_APP
|
||||||
|
obj-$(CONFIG_$(SPL_TPL_)X86_32BIT_INIT) += microcode.o
|
||||||
|
ifndef CONFIG_$(SPL_)X86_64
|
||||||
obj-y += microcode.o
|
obj-y += microcode.o
|
||||||
endif
|
endif
|
||||||
|
endif
|
||||||
obj-y += pch.o
|
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
|
.align 4
|
||||||
_dt_ucode_base_size:
|
_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
|
.globl ucode_base
|
||||||
ucode_base: /* Declared in microcode.h */
|
ucode_base: /* Declared in microcode.h */
|
||||||
.long 0 /* microcode base */
|
.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 -ENOENT;
|
||||||
|
|
||||||
return val & RCBA_AUDIO_CONFIG_MASK;
|
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:
|
default:
|
||||||
return -ENOSYS;
|
return -ENOSYS;
|
||||||
}
|
}
|
||||||
|
|
|
@ -322,7 +322,7 @@ static int start_aps(int ap_count, atomic_t *num_aps)
|
||||||
if (sipi_vector > max_vector_loc) {
|
if (sipi_vector > max_vector_loc) {
|
||||||
printf("SIPI vector too large! 0x%08x\n",
|
printf("SIPI vector too large! 0x%08x\n",
|
||||||
sipi_vector);
|
sipi_vector);
|
||||||
return -1;
|
return -ENOSPC;
|
||||||
}
|
}
|
||||||
|
|
||||||
debug("Attempting to start %d APs\n", ap_count);
|
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)) {
|
if (wait_for_aps(num_aps, ap_count, 10000, 50)) {
|
||||||
debug("Not all APs checked in: %d/%d\n",
|
debug("Not all APs checked in: %d/%d\n",
|
||||||
atomic_read(num_aps), ap_count);
|
atomic_read(num_aps), ap_count);
|
||||||
return -1;
|
return -EIO;
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
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,
|
if (wait_for_aps(&rec->cpus_entered, num_aps,
|
||||||
timeout_us, step_us)) {
|
timeout_us, step_us)) {
|
||||||
debug("MP record %d timeout\n", i);
|
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) {
|
if (p == NULL || p->flight_plan == NULL || p->num_records < 1) {
|
||||||
printf("Invalid MP parameters\n");
|
printf("Invalid MP parameters\n");
|
||||||
return -1;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
num_cpus = cpu_get_count(cpu);
|
num_cpus = cpu_get_count(cpu);
|
||||||
|
@ -531,7 +531,7 @@ int mp_init(struct mp_params *p)
|
||||||
/* Load the SIPI vector */
|
/* Load the SIPI vector */
|
||||||
ret = load_sipi_vector(&ap_count, num_cpus);
|
ret = load_sipi_vector(&ap_count, num_cpus);
|
||||||
if (ap_count == NULL)
|
if (ap_count == NULL)
|
||||||
return -1;
|
return -ENOENT;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Make sure SIPI data hits RAM so the APs that come up will see
|
* 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() */
|
/* Re-enter U-Boot by calling board_init_f_r() */
|
||||||
call 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:
|
die:
|
||||||
hlt
|
hlt
|
||||||
jmp die
|
jmp die
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
/*
|
/*
|
||||||
* 64-bit x86 Startup Code
|
* 64-bit x86 Startup Code
|
||||||
*
|
*
|
||||||
* (C) Copyright 216 Google, Inc
|
* Copyright 2019 Google, Inc
|
||||||
* Written by Simon Glass <sjg@chromium.org>
|
* 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/ : { *(.interp*) }
|
||||||
/DISCARD/ : { *(.gnu*) }
|
/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
|
* The following expressions place the 16-bit Real-Mode code and
|
||||||
* Reset Vector at the end of the Flash ROM
|
* Reset Vector at the end of the Flash ROM
|
||||||
|
|
|
@ -61,3 +61,8 @@ int print_cpuinfo(void)
|
||||||
{
|
{
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int x86_cpu_reinit_f(void)
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
|
@ -9,6 +9,12 @@
|
||||||
/include/ "rtc.dtsi"
|
/include/ "rtc.dtsi"
|
||||||
/include/ "tsc_timer.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";
|
model = "Google Samus";
|
||||||
compatible = "google,samus", "intel,broadwell";
|
compatible = "google,samus", "intel,broadwell";
|
||||||
|
@ -17,6 +23,7 @@
|
||||||
spi0 = &spi;
|
spi0 = &spi;
|
||||||
usb0 = &usb_0;
|
usb0 = &usb_0;
|
||||||
usb1 = &usb_1;
|
usb1 = &usb_1;
|
||||||
|
cros-ec0 = &cros_ec;
|
||||||
};
|
};
|
||||||
|
|
||||||
config {
|
config {
|
||||||
|
@ -73,6 +80,7 @@
|
||||||
|
|
||||||
/* Put this first: it is the default */
|
/* Put this first: it is the default */
|
||||||
gpio_unused: gpio-unused {
|
gpio_unused: gpio-unused {
|
||||||
|
u-boot,dm-pre-reloc;
|
||||||
mode-gpio;
|
mode-gpio;
|
||||||
direction = <PIN_INPUT>;
|
direction = <PIN_INPUT>;
|
||||||
owner = <OWNER_GPIO>;
|
owner = <OWNER_GPIO>;
|
||||||
|
@ -80,6 +88,7 @@
|
||||||
};
|
};
|
||||||
|
|
||||||
gpio_acpi_sci: acpi-sci {
|
gpio_acpi_sci: acpi-sci {
|
||||||
|
u-boot,dm-pre-reloc;
|
||||||
mode-gpio;
|
mode-gpio;
|
||||||
direction = <PIN_INPUT>;
|
direction = <PIN_INPUT>;
|
||||||
invert;
|
invert;
|
||||||
|
@ -87,6 +96,7 @@
|
||||||
};
|
};
|
||||||
|
|
||||||
gpio_acpi_smi: acpi-smi {
|
gpio_acpi_smi: acpi-smi {
|
||||||
|
u-boot,dm-pre-reloc;
|
||||||
mode-gpio;
|
mode-gpio;
|
||||||
direction = <PIN_INPUT>;
|
direction = <PIN_INPUT>;
|
||||||
invert;
|
invert;
|
||||||
|
@ -94,12 +104,14 @@
|
||||||
};
|
};
|
||||||
|
|
||||||
gpio_input: gpio-input {
|
gpio_input: gpio-input {
|
||||||
|
u-boot,dm-pre-reloc;
|
||||||
mode-gpio;
|
mode-gpio;
|
||||||
direction = <PIN_INPUT>;
|
direction = <PIN_INPUT>;
|
||||||
owner = <OWNER_GPIO>;
|
owner = <OWNER_GPIO>;
|
||||||
};
|
};
|
||||||
|
|
||||||
gpio_input_invert: gpio-input-invert {
|
gpio_input_invert: gpio-input-invert {
|
||||||
|
u-boot,dm-pre-reloc;
|
||||||
mode-gpio;
|
mode-gpio;
|
||||||
direction = <PIN_INPUT>;
|
direction = <PIN_INPUT>;
|
||||||
owner = <OWNER_GPIO>;
|
owner = <OWNER_GPIO>;
|
||||||
|
@ -107,9 +119,11 @@
|
||||||
};
|
};
|
||||||
|
|
||||||
gpio_native: gpio-native {
|
gpio_native: gpio-native {
|
||||||
|
u-boot,dm-pre-reloc;
|
||||||
};
|
};
|
||||||
|
|
||||||
gpio_out_high: gpio-out-high {
|
gpio_out_high: gpio-out-high {
|
||||||
|
u-boot,dm-pre-reloc;
|
||||||
mode-gpio;
|
mode-gpio;
|
||||||
direction = <PIN_OUTPUT>;
|
direction = <PIN_OUTPUT>;
|
||||||
output-value = <1>;
|
output-value = <1>;
|
||||||
|
@ -118,6 +132,7 @@
|
||||||
};
|
};
|
||||||
|
|
||||||
gpio_out_low: gpio-out-low {
|
gpio_out_low: gpio-out-low {
|
||||||
|
u-boot,dm-pre-reloc;
|
||||||
mode-gpio;
|
mode-gpio;
|
||||||
direction = <PIN_OUTPUT>;
|
direction = <PIN_OUTPUT>;
|
||||||
output-value = <0>;
|
output-value = <0>;
|
||||||
|
@ -126,6 +141,7 @@
|
||||||
};
|
};
|
||||||
|
|
||||||
gpio_pirq: gpio-pirq {
|
gpio_pirq: gpio-pirq {
|
||||||
|
u-boot,dm-pre-reloc;
|
||||||
mode-gpio;
|
mode-gpio;
|
||||||
direction = <PIN_INPUT>;
|
direction = <PIN_INPUT>;
|
||||||
owner = <OWNER_GPIO>;
|
owner = <OWNER_GPIO>;
|
||||||
|
@ -133,6 +149,7 @@
|
||||||
};
|
};
|
||||||
|
|
||||||
soc_gpio@0 {
|
soc_gpio@0 {
|
||||||
|
u-boot,dm-pre-reloc;
|
||||||
config =
|
config =
|
||||||
<0 &gpio_unused 0>, /* unused */
|
<0 &gpio_unused 0>, /* unused */
|
||||||
<1 &gpio_unused 0>, /* unused */
|
<1 &gpio_unused 0>, /* unused */
|
||||||
|
@ -250,8 +267,10 @@
|
||||||
spd {
|
spd {
|
||||||
#address-cells = <1>;
|
#address-cells = <1>;
|
||||||
#size-cells = <0>;
|
#size-cells = <0>;
|
||||||
|
u-boot,dm-pre-reloc;
|
||||||
samsung_4 {
|
samsung_4 {
|
||||||
reg = <6>;
|
reg = <6>;
|
||||||
|
u-boot,dm-pre-reloc;
|
||||||
data = [91 20 f1 03 04 11 05 0b
|
data = [91 20 f1 03 04 11 05 0b
|
||||||
03 11 01 08 0a 00 50 01
|
03 11 01 08 0a 00 50 01
|
||||||
78 78 90 50 90 11 50 e0
|
78 78 90 50 90 11 50 e0
|
||||||
|
@ -291,6 +310,7 @@
|
||||||
* columns 10, density 4096 mb, x32
|
* columns 10, density 4096 mb, x32
|
||||||
*/
|
*/
|
||||||
reg = <8>;
|
reg = <8>;
|
||||||
|
u-boot,dm-pre-reloc;
|
||||||
data = [91 20 f1 03 04 11 05 0b
|
data = [91 20 f1 03 04 11 05 0b
|
||||||
03 11 01 08 0a 00 50 01
|
03 11 01 08 0a 00 50 01
|
||||||
78 78 90 50 90 11 50 e0
|
78 78 90 50 90 11 50 e0
|
||||||
|
@ -326,6 +346,7 @@
|
||||||
};
|
};
|
||||||
samsung_8 {
|
samsung_8 {
|
||||||
reg = <10>;
|
reg = <10>;
|
||||||
|
u-boot,dm-pre-reloc;
|
||||||
data = [91 20 f1 03 04 12 05 0a
|
data = [91 20 f1 03 04 12 05 0a
|
||||||
03 11 01 08 0a 00 50 01
|
03 11 01 08 0a 00 50 01
|
||||||
78 78 90 50 90 11 50 e0
|
78 78 90 50 90 11 50 e0
|
||||||
|
@ -365,6 +386,7 @@
|
||||||
* columns 11, density 4096 mb, x16
|
* columns 11, density 4096 mb, x16
|
||||||
*/
|
*/
|
||||||
reg = <12>;
|
reg = <12>;
|
||||||
|
u-boot,dm-pre-reloc;
|
||||||
data = [91 20 f1 03 04 12 05 0a
|
data = [91 20 f1 03 04 12 05 0a
|
||||||
03 11 01 08 0a 00 50 01
|
03 11 01 08 0a 00 50 01
|
||||||
78 78 90 50 90 11 50 e0
|
78 78 90 50 90 11 50 e0
|
||||||
|
@ -404,6 +426,7 @@
|
||||||
* columns 11, density 8192 mb, x16
|
* columns 11, density 8192 mb, x16
|
||||||
*/
|
*/
|
||||||
reg = <13>;
|
reg = <13>;
|
||||||
|
u-boot,dm-pre-reloc;
|
||||||
data = [91 20 f1 03 05 1a 05 0a
|
data = [91 20 f1 03 05 1a 05 0a
|
||||||
03 11 01 08 0a 00 50 01
|
03 11 01 08 0a 00 50 01
|
||||||
78 78 90 50 90 11 50 e0
|
78 78 90 50 90 11 50 e0
|
||||||
|
@ -443,6 +466,7 @@
|
||||||
* columns 11, density 8192 mb, x16
|
* columns 11, density 8192 mb, x16
|
||||||
*/
|
*/
|
||||||
reg = <15>;
|
reg = <15>;
|
||||||
|
u-boot,dm-pre-reloc;
|
||||||
data = [91 20 f1 03 05 1a 05 0a
|
data = [91 20 f1 03 05 1a 05 0a
|
||||||
03 11 01 08 0a 00 50 01
|
03 11 01 08 0a 00 50 01
|
||||||
78 78 90 50 90 11 50 e0
|
78 78 90 50 90 11 50 e0
|
||||||
|
@ -540,7 +564,7 @@
|
||||||
compatible = "ehci-pci";
|
compatible = "ehci-pci";
|
||||||
};
|
};
|
||||||
|
|
||||||
pch@1f,0 {
|
pch: pch@1f,0 {
|
||||||
reg = <0x0000f800 0 0 0 0>;
|
reg = <0x0000f800 0 0 0 0>;
|
||||||
compatible = "intel,broadwell-pch";
|
compatible = "intel,broadwell-pch";
|
||||||
u-boot,dm-pre-reloc;
|
u-boot,dm-pre-reloc;
|
||||||
|
@ -559,10 +583,12 @@
|
||||||
power-enable-gpio = <&gpio_a 23 0>;
|
power-enable-gpio = <&gpio_a 23 0>;
|
||||||
|
|
||||||
spi: spi {
|
spi: spi {
|
||||||
|
u-boot,dm-pre-reloc;
|
||||||
#address-cells = <1>;
|
#address-cells = <1>;
|
||||||
#size-cells = <0>;
|
#size-cells = <0>;
|
||||||
compatible = "intel,ich9-spi";
|
compatible = "intel,ich9-spi";
|
||||||
spi-flash@0 {
|
fwstore_spi: spi-flash@0 {
|
||||||
|
u-boot,dm-pre-reloc;
|
||||||
#size-cells = <1>;
|
#size-cells = <1>;
|
||||||
#address-cells = <1>;
|
#address-cells = <1>;
|
||||||
reg = <0>;
|
reg = <0>;
|
||||||
|
@ -570,6 +596,7 @@
|
||||||
"jedec,spi-nor";
|
"jedec,spi-nor";
|
||||||
memory-map = <0xff800000 0x00800000>;
|
memory-map = <0xff800000 0x00800000>;
|
||||||
rw-mrc-cache {
|
rw-mrc-cache {
|
||||||
|
u-boot,dm-pre-reloc;
|
||||||
label = "rw-mrc-cache";
|
label = "rw-mrc-cache";
|
||||||
reg = <0x003e0000 0x00010000>;
|
reg = <0x003e0000 0x00010000>;
|
||||||
};
|
};
|
||||||
|
@ -609,7 +636,8 @@
|
||||||
#size-cells = <0>;
|
#size-cells = <0>;
|
||||||
u-boot,dm-pre-reloc;
|
u-boot,dm-pre-reloc;
|
||||||
intel,gen-dec = <0x800 0xfc 0x900 0xfc>;
|
intel,gen-dec = <0x800 0xfc 0x900 0xfc>;
|
||||||
cros-ec@200 {
|
cros_ec: cros-ec {
|
||||||
|
u-boot,dm-pre-reloc;
|
||||||
compatible = "google,cros-ec-lpc";
|
compatible = "google,cros-ec-lpc";
|
||||||
reg = <0x204 1 0x200 1 0x880 0x80>;
|
reg = <0x204 1 0x200 1 0x880 0x80>;
|
||||||
|
|
||||||
|
@ -630,7 +658,7 @@
|
||||||
sata@1f,2 {
|
sata@1f,2 {
|
||||||
compatible = "intel,wildcatpoint-ahci";
|
compatible = "intel,wildcatpoint-ahci";
|
||||||
reg = <0x0000fa00 0 0 0 0>;
|
reg = <0x0000fa00 0 0 0 0>;
|
||||||
u-boot,dm-pre-reloc;
|
u-boot,dm-pre-proper;
|
||||||
intel,sata-mode = "ahci";
|
intel,sata-mode = "ahci";
|
||||||
intel,sata-port-map = <1>;
|
intel,sata-port-map = <1>;
|
||||||
intel,sata-port0-gen3-tx = <0x72>;
|
intel,sata-port0-gen3-tx = <0x72>;
|
||||||
|
@ -645,12 +673,19 @@
|
||||||
};
|
};
|
||||||
|
|
||||||
tpm {
|
tpm {
|
||||||
|
u-boot,dm-pre-reloc;
|
||||||
reg = <0xfed40000 0x5000>;
|
reg = <0xfed40000 0x5000>;
|
||||||
compatible = "infineon,slb9635lpc";
|
compatible = "infineon,slb9635lpc";
|
||||||
|
secdata {
|
||||||
|
u-boot,dm-pre-reloc;
|
||||||
|
compatible = "google,tpm-secdata";
|
||||||
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
microcode {
|
microcode {
|
||||||
|
u-boot,dm-pre-reloc;
|
||||||
update@0 {
|
update@0 {
|
||||||
|
u-boot,dm-pre-reloc;
|
||||||
#include "microcode/mc0306d4_00000018.dtsi"
|
#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";
|
compatible = "x86,reset";
|
||||||
u-boot,dm-pre-reloc;
|
u-boot,dm-pre-reloc;
|
||||||
};
|
};
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/ {
|
/ {
|
||||||
rtc {
|
rtc: rtc {
|
||||||
compatible = "motorola,mc146818";
|
compatible = "motorola,mc146818";
|
||||||
u-boot,dm-pre-reloc;
|
u-boot,dm-pre-reloc;
|
||||||
reg = <0x70 2>;
|
reg = <0x70 2>;
|
||||||
|
|
|
@ -6,86 +6,128 @@
|
||||||
|
|
||||||
#include <config.h>
|
#include <config.h>
|
||||||
|
|
||||||
#ifdef CONFIG_ROM_SIZE
|
#ifdef CONFIG_CHROMEOS
|
||||||
/ {
|
/ {
|
||||||
binman {
|
binman {
|
||||||
filename = "u-boot.rom";
|
multiple-images;
|
||||||
end-at-4gb;
|
rom: rom {
|
||||||
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>;
|
|
||||||
};
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
#else
|
#else
|
||||||
u-boot-with-ucode-ptr {
|
/ {
|
||||||
offset = <CONFIG_SYS_TEXT_BASE>;
|
rom: binman {
|
||||||
};
|
|
||||||
#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
|
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
#endif
|
#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);
|
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 */
|
#endif /* _ASM_MRCCACHE_H */
|
||||||
|
|
|
@ -2,6 +2,19 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (C) 2017 Google, Inc
|
* Copyright (C) 2017 Google, Inc
|
||||||
* Written by Simon Glass <sjg@chromium.org>
|
* 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 */
|
/* cpu/.../cpu.c */
|
||||||
int arch_cpu_init(void);
|
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);
|
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);
|
int cpu_init_f(void);
|
||||||
void setup_gdt(struct global_data *id, u64 *gdt_addr);
|
void setup_gdt(struct global_data *id, u64 *gdt_addr);
|
||||||
/*
|
/*
|
||||||
|
|
|
@ -43,7 +43,14 @@ ifndef CONFIG_SPL_BUILD
|
||||||
obj-$(CONFIG_CMD_ZBOOT) += zimage.o
|
obj-$(CONFIG_CMD_ZBOOT) += zimage.o
|
||||||
endif
|
endif
|
||||||
obj-$(CONFIG_HAVE_FSP) += fsp/
|
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
|
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);
|
timestamp_add_now(TS_U_BOOT_START_KERNEL);
|
||||||
#endif
|
#endif
|
||||||
bootstage_mark_name(BOOTSTAGE_ID_BOOTM_HANDOFF, "start_kernel");
|
bootstage_mark_name(BOOTSTAGE_ID_BOOTM_HANDOFF, "start_kernel");
|
||||||
#ifdef CONFIG_BOOTSTAGE_REPORT
|
#if CONFIG_IS_ENABLED(BOOTSTAGE_REPORT)
|
||||||
bootstage_report();
|
bootstage_report();
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
|
@ -100,7 +100,7 @@ temp_ram_init_romstack:
|
||||||
.long temp_ram_init_params
|
.long temp_ram_init_params
|
||||||
temp_ram_init_params:
|
temp_ram_init_params:
|
||||||
_dt_ucode_base_size:
|
_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
|
.globl ucode_base
|
||||||
ucode_base: /* Declared in microcode.h */
|
ucode_base: /* Declared in microcode.h */
|
||||||
.long 0 /* microcode base */
|
.long 0 /* microcode base */
|
||||||
|
|
|
@ -18,7 +18,10 @@ __weak ulong board_get_usable_ram_top(ulong total_size)
|
||||||
|
|
||||||
int init_cache_f_r(void)
|
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;
|
int ret;
|
||||||
|
|
||||||
ret = mtrr_commit(false);
|
ret = mtrr_commit(false);
|
||||||
|
|
|
@ -113,8 +113,10 @@ int mrccache_update(struct udevice *sf, struct mrc_region *entry,
|
||||||
ulong base_addr;
|
ulong base_addr;
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
if (!is_mrc_cache(cur))
|
if (!is_mrc_cache(cur)) {
|
||||||
|
debug("%s: Cache data not valid\n", __func__);
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
/* Find the last used block */
|
/* Find the last used block */
|
||||||
base_addr = entry->base + entry->offset;
|
base_addr = entry->base + entry->offset;
|
||||||
|
@ -159,18 +161,11 @@ int mrccache_update(struct udevice *sf, struct mrc_region *entry,
|
||||||
return 0;
|
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;
|
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->signature = MRC_DATA_SIGNATURE;
|
||||||
cache->data_size = gd->arch.mrc_output_len;
|
cache->data_size = gd->arch.mrc_output_len;
|
||||||
checksum = compute_ip_checksum(gd->arch.mrc_output, cache->data_size);
|
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 now points to the container */
|
||||||
gd->arch.mrc_output = (char *)cache;
|
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;
|
gd->start_addr_sp &= ~0xf;
|
||||||
|
|
||||||
|
@ -202,17 +207,23 @@ int mrccache_get_region(struct udevice **devp, struct mrc_region *entry)
|
||||||
return -ENOENT;
|
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;
|
return -EINVAL;
|
||||||
|
}
|
||||||
entry->base = reg[0];
|
entry->base = reg[0];
|
||||||
|
|
||||||
/* Find the place where we put the MRC cache */
|
/* Find the place where we put the MRC cache */
|
||||||
mrc_node = fdt_subnode_offset(blob, node, "rw-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;
|
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;
|
return -EINVAL;
|
||||||
|
}
|
||||||
entry->offset = reg[0];
|
entry->offset = reg[0];
|
||||||
entry->length = reg[1];
|
entry->length = reg[1];
|
||||||
|
|
||||||
|
@ -256,3 +267,18 @@ err_entry:
|
||||||
debug("%s: Failed: %d\n", __func__, ret);
|
debug("%s: Failed: %d\n", __func__, ret);
|
||||||
return 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 <common.h>
|
||||||
#include <debug_uart.h>
|
#include <debug_uart.h>
|
||||||
|
#include <malloc.h>
|
||||||
#include <spl.h>
|
#include <spl.h>
|
||||||
#include <asm/cpu.h>
|
#include <asm/cpu.h>
|
||||||
|
#include <asm/mrccache.h>
|
||||||
#include <asm/mtrr.h>
|
#include <asm/mtrr.h>
|
||||||
#include <asm/processor.h>
|
#include <asm/processor.h>
|
||||||
#include <asm-generic/sections.h>
|
#include <asm-generic/sections.h>
|
||||||
|
@ -20,6 +22,7 @@ __weak int arch_cpu_init_dm(void)
|
||||||
|
|
||||||
static int x86_spl_init(void)
|
static int x86_spl_init(void)
|
||||||
{
|
{
|
||||||
|
#ifndef CONFIG_TPL
|
||||||
/*
|
/*
|
||||||
* TODO(sjg@chromium.org): We use this area of RAM for the stack
|
* 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
|
* 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.
|
* place it immediately below CONFIG_SYS_TEXT_BASE.
|
||||||
*/
|
*/
|
||||||
char *ptr = (char *)0x110000;
|
char *ptr = (char *)0x110000;
|
||||||
|
#endif
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
debug("%s starting\n", __func__);
|
debug("%s starting\n", __func__);
|
||||||
|
@ -35,27 +39,44 @@ static int x86_spl_init(void)
|
||||||
debug("%s: spl_init() failed\n", __func__);
|
debug("%s: spl_init() failed\n", __func__);
|
||||||
return ret;
|
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();
|
ret = arch_cpu_init();
|
||||||
|
#endif
|
||||||
if (ret) {
|
if (ret) {
|
||||||
debug("%s: arch_cpu_init() failed\n", __func__);
|
debug("%s: arch_cpu_init() failed\n", __func__);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
#ifndef CONFIG_TPL
|
||||||
ret = arch_cpu_init_dm();
|
ret = arch_cpu_init_dm();
|
||||||
if (ret) {
|
if (ret) {
|
||||||
debug("%s: arch_cpu_init_dm() failed\n", __func__);
|
debug("%s: arch_cpu_init_dm() failed\n", __func__);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
preloader_console_init();
|
preloader_console_init();
|
||||||
|
#ifndef CONFIG_TPL
|
||||||
ret = print_cpuinfo();
|
ret = print_cpuinfo();
|
||||||
if (ret) {
|
if (ret) {
|
||||||
debug("%s: print_cpuinfo() failed\n", __func__);
|
debug("%s: print_cpuinfo() failed\n", __func__);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
ret = dram_init();
|
ret = dram_init();
|
||||||
if (ret) {
|
if (ret) {
|
||||||
debug("%s: dram_init() failed\n", __func__);
|
debug("%s: dram_init() failed\n", __func__);
|
||||||
return ret;
|
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);
|
memset(&__bss_start, 0, (ulong)&__bss_end - (ulong)&__bss_start);
|
||||||
|
|
||||||
/* TODO(sjg@chromium.org): Consider calling cpu_init_r() here */
|
/* 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,
|
(1ULL << 32) - CONFIG_XIP_ROM_SIZE,
|
||||||
CONFIG_XIP_ROM_SIZE);
|
CONFIG_XIP_ROM_SIZE);
|
||||||
if (ret) {
|
if (ret) {
|
||||||
debug("%s: SPI cache setup failed\n", __func__);
|
debug("%s: SPI cache setup failed (err=%d)\n", __func__, ret);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
mtrr_commit(true);
|
||||||
|
#endif
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -96,9 +119,17 @@ void board_init_f(ulong flags)
|
||||||
debug("Error %d\n", ret);
|
debug("Error %d\n", ret);
|
||||||
hang();
|
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() */
|
/* Uninit CAR and jump to board_init_f_r() */
|
||||||
board_init_f_r_trampoline(gd->start_addr_sp);
|
board_init_f_r_trampoline(gd->start_addr_sp);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
void board_init_f_r(void)
|
void board_init_f_r(void)
|
||||||
|
@ -144,6 +175,7 @@ int spl_spi_load_image(void)
|
||||||
return -EPERM;
|
return -EPERM;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef CONFIG_X86_RUN_64BIT
|
||||||
void __noreturn jump_to_image_no_args(struct spl_image_info *spl_image)
|
void __noreturn jump_to_image_no_args(struct spl_image_info *spl_image)
|
||||||
{
|
{
|
||||||
int ret;
|
int ret;
|
||||||
|
@ -154,3 +186,11 @@ void __noreturn jump_to_image_no_args(struct spl_image_info *spl_image)
|
||||||
while (1)
|
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
|
Chrome OS EC connected on LPC, and it provides a 2560x1700 high
|
||||||
resolution touch-enabled LCD display.
|
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
|
endchoice
|
||||||
|
|
||||||
source "board/google/chromebook_link/Kconfig"
|
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
|
config SYS_BOARD
|
||||||
default "chromebook_samus"
|
default "chromebook_samus"
|
||||||
|
@ -10,7 +10,8 @@ config SYS_SOC
|
||||||
default "broadwell"
|
default "broadwell"
|
||||||
|
|
||||||
config SYS_CONFIG_NAME
|
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
|
config SYS_TEXT_BASE
|
||||||
default 0xffe00000
|
default 0xffe00000
|
||||||
|
@ -39,3 +40,12 @@ config SYS_CAR_SIZE
|
||||||
default 0x40000
|
default 0x40000
|
||||||
|
|
||||||
endif
|
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: board/google/chromebook_samus/
|
||||||
F: include/configs/chromebook_samus.h
|
F: include/configs/chromebook_samus.h
|
||||||
F: configs/chromebook_samus_defconfig
|
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_X86=y
|
||||||
CONFIG_SYS_TEXT_BASE=0xFFE00000
|
CONFIG_SYS_TEXT_BASE=0xFFE00000
|
||||||
CONFIG_SYS_MALLOC_F_LEN=0x1c00
|
CONFIG_SYS_MALLOC_F_LEN=0x1d00
|
||||||
CONFIG_NR_DRAM_BANKS=8
|
CONFIG_NR_DRAM_BANKS=8
|
||||||
CONFIG_DEBUG_UART_BOARD_INIT=y
|
CONFIG_DEBUG_UART_BOARD_INIT=y
|
||||||
CONFIG_DEBUG_UART_BASE=0x3f8
|
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
|
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:
|
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);
|
ns = of_n_size_cells(np);
|
||||||
*sizep = of_read_number(prop + na, ns);
|
*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);
|
return of_translate_address(np, prop);
|
||||||
else
|
else
|
||||||
return of_read_number(prop, na);
|
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) = {
|
UCLASS_DRIVER(cros_ec) = {
|
||||||
.id = UCLASS_CROS_EC,
|
.id = UCLASS_CROS_EC,
|
||||||
.name = "cros_ec",
|
.name = "cros-ec",
|
||||||
.per_device_auto_alloc_size = sizeof(struct cros_ec_dev),
|
.per_device_auto_alloc_size = sizeof(struct cros_ec_dev),
|
||||||
.post_bind = dm_scan_fdt_dev,
|
.post_bind = dm_scan_fdt_dev,
|
||||||
.flags = DM_UC_FLAG_ALLOC_PRIV_DMA,
|
.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;
|
goto err;
|
||||||
#endif
|
#endif
|
||||||
} else {
|
} 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_set_interrupt_handler(0x15, int15_handler);
|
||||||
|
|
||||||
bios_run_on_x86(dev, (unsigned long)ram, vesa_mode,
|
bios_run_on_x86(dev, (unsigned long)ram, vesa_mode,
|
||||||
|
|
|
@ -7,15 +7,75 @@
|
||||||
|
|
||||||
#include <common.h>
|
#include <common.h>
|
||||||
#include <dm.h>
|
#include <dm.h>
|
||||||
|
#include <efi_loader.h>
|
||||||
|
#include <pch.h>
|
||||||
#include <sysreset.h>
|
#include <sysreset.h>
|
||||||
|
#include <asm/acpi_s3.h>
|
||||||
#include <asm/io.h>
|
#include <asm/io.h>
|
||||||
#include <asm/processor.h>
|
#include <asm/processor.h>
|
||||||
#include <efi_loader.h>
|
|
||||||
|
|
||||||
static __efi_runtime int x86_sysreset_request(struct udevice *dev,
|
struct x86_sysreset_platdata {
|
||||||
enum sysreset_t type)
|
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 value;
|
||||||
|
int ret;
|
||||||
|
|
||||||
switch (type) {
|
switch (type) {
|
||||||
case SYSRESET_WARM:
|
case SYSRESET_WARM:
|
||||||
|
@ -24,6 +84,11 @@ static __efi_runtime int x86_sysreset_request(struct udevice *dev,
|
||||||
case SYSRESET_COLD:
|
case SYSRESET_COLD:
|
||||||
value = SYS_RST | RST_CPU | FULL_RST;
|
value = SYS_RST | RST_CPU | FULL_RST;
|
||||||
break;
|
break;
|
||||||
|
case SYSRESET_POWER_OFF:
|
||||||
|
ret = pch_sysreset_power_off(dev);
|
||||||
|
if (ret)
|
||||||
|
return ret;
|
||||||
|
return -EINPROGRESS;
|
||||||
default:
|
default:
|
||||||
return -ENOSYS;
|
return -ENOSYS;
|
||||||
}
|
}
|
||||||
|
@ -33,17 +98,29 @@ static __efi_runtime int x86_sysreset_request(struct udevice *dev,
|
||||||
return -EINPROGRESS;
|
return -EINPROGRESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int x86_sysreset_get_last(struct udevice *dev)
|
||||||
|
{
|
||||||
|
return SYSRESET_POWER;
|
||||||
|
}
|
||||||
|
|
||||||
#ifdef CONFIG_EFI_LOADER
|
#ifdef CONFIG_EFI_LOADER
|
||||||
void __efi_runtime EFIAPI efi_reset_system(
|
void __efi_runtime EFIAPI efi_reset_system(
|
||||||
enum efi_reset_type reset_type,
|
enum efi_reset_type reset_type,
|
||||||
efi_status_t reset_status,
|
efi_status_t reset_status,
|
||||||
unsigned long data_size, void *reset_data)
|
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 ||
|
if (reset_type == EFI_RESET_COLD ||
|
||||||
reset_type == EFI_RESET_PLATFORM_SPECIFIC)
|
reset_type == EFI_RESET_PLATFORM_SPECIFIC)
|
||||||
x86_sysreset_request(NULL, SYSRESET_COLD);
|
value = SYS_RST | RST_CPU | FULL_RST;
|
||||||
else if (reset_type == EFI_RESET_WARM)
|
else /* assume EFI_RESET_WARM since we cannot return an error */
|
||||||
x86_sysreset_request(NULL, SYSRESET_WARM);
|
value = SYS_RST | RST_CPU;
|
||||||
|
outb(value, IO_PORT_RESET);
|
||||||
|
|
||||||
/* TODO EFI_RESET_SHUTDOWN */
|
/* TODO EFI_RESET_SHUTDOWN */
|
||||||
|
|
||||||
|
@ -51,6 +128,15 @@ void __efi_runtime EFIAPI efi_reset_system(
|
||||||
}
|
}
|
||||||
#endif
|
#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[] = {
|
static const struct udevice_id x86_sysreset_ids[] = {
|
||||||
{ .compatible = "x86,reset" },
|
{ .compatible = "x86,reset" },
|
||||||
|
@ -59,6 +145,7 @@ static const struct udevice_id x86_sysreset_ids[] = {
|
||||||
|
|
||||||
static struct sysreset_ops x86_sysreset_ops = {
|
static struct sysreset_ops x86_sysreset_ops = {
|
||||||
.request = x86_sysreset_request,
|
.request = x86_sysreset_request,
|
||||||
|
.get_last = x86_sysreset_get_last,
|
||||||
};
|
};
|
||||||
|
|
||||||
U_BOOT_DRIVER(x86_sysreset) = {
|
U_BOOT_DRIVER(x86_sysreset) = {
|
||||||
|
@ -66,4 +153,6 @@ U_BOOT_DRIVER(x86_sysreset) = {
|
||||||
.id = UCLASS_SYSRESET,
|
.id = UCLASS_SYSRESET,
|
||||||
.of_match = x86_sysreset_ids,
|
.of_match = x86_sysreset_ids,
|
||||||
.ops = &x86_sysreset_ops,
|
.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_SECT_SIZE 0x1000
|
||||||
#define CONFIG_ENV_OFFSET 0x003f8000
|
#define CONFIG_ENV_OFFSET 0x003f8000
|
||||||
|
|
||||||
#define BOOT_DEVICE_SPI 10
|
|
||||||
|
|
||||||
#define CONFIG_SPL_BOARD_LOAD_IMAGE
|
#define CONFIG_SPL_BOARD_LOAD_IMAGE
|
||||||
#define BOOT_DEVICE_BOARD 11
|
|
||||||
|
|
||||||
#endif /* __CONFIG_H */
|
#endif /* __CONFIG_H */
|
||||||
|
|
|
@ -23,4 +23,6 @@
|
||||||
#define CONFIG_ENV_SECT_SIZE 0x1000
|
#define CONFIG_ENV_SECT_SIZE 0x1000
|
||||||
#define CONFIG_ENV_OFFSET 0x003f8000
|
#define CONFIG_ENV_OFFSET 0x003f8000
|
||||||
|
|
||||||
|
#define CONFIG_TPL_TEXT_BASE 0xfffd8000
|
||||||
|
|
||||||
#endif /* __CONFIG_H */
|
#endif /* __CONFIG_H */
|
||||||
|
|
|
@ -33,11 +33,6 @@
|
||||||
#define CONFIG_SYS_ATA_IDE1_OFFSET 0x170
|
#define CONFIG_SYS_ATA_IDE1_OFFSET 0x170
|
||||||
#define CONFIG_ATAPI
|
#define CONFIG_ATAPI
|
||||||
|
|
||||||
/* SPI is not supported */
|
|
||||||
|
|
||||||
#define BOOT_DEVICE_SPI 10
|
|
||||||
|
|
||||||
#define CONFIG_SPL_BOARD_LOAD_IMAGE
|
#define CONFIG_SPL_BOARD_LOAD_IMAGE
|
||||||
#define BOOT_DEVICE_BOARD 11
|
|
||||||
|
|
||||||
#endif /* __CONFIG_H */
|
#endif /* __CONFIG_H */
|
||||||
|
|
|
@ -36,7 +36,6 @@
|
||||||
/*-----------------------------------------------------------------------
|
/*-----------------------------------------------------------------------
|
||||||
* Real Time Clock Configuration
|
* Real Time Clock Configuration
|
||||||
*/
|
*/
|
||||||
#define CONFIG_RTC_MC146818
|
|
||||||
#define CONFIG_SYS_ISA_IO_BASE_ADDRESS 0
|
#define CONFIG_SYS_ISA_IO_BASE_ADDRESS 0
|
||||||
#define CONFIG_SYS_ISA_IO CONFIG_SYS_ISA_IO_BASE_ADDRESS
|
#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 */
|
/* Returns HDA config info if Azalia V1CTL enabled, -ENOENT if not */
|
||||||
PCH_REQ_HDA_CONFIG,
|
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_TEST1, /* Test requests for sandbox driver */
|
||||||
PCH_REQ_TEST2,
|
PCH_REQ_TEST2,
|
||||||
PCH_REQ_TEST3,
|
PCH_REQ_TEST3,
|
||||||
|
@ -23,6 +26,21 @@ enum pch_req_t {
|
||||||
PCH_REQ_COUNT, /* Number of ioctrls supported */
|
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
|
* 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,
|
extern void pci_cfgfunc_config_device(struct pci_controller* hose, pci_dev_t dev,
|
||||||
struct pci_config_table *);
|
struct pci_config_table *);
|
||||||
|
|
||||||
#ifdef CONFIG_NR_DRAM_BANKS
|
#define MAX_PCI_REGIONS 7
|
||||||
#define MAX_PCI_REGIONS (CONFIG_NR_DRAM_BANKS + 7)
|
|
||||||
#else
|
|
||||||
#define MAX_PCI_REGIONS 7
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#define INDIRECT_TYPE_NO_PCIE_LINK 1
|
#define INDIRECT_TYPE_NO_PCIE_LINK 1
|
||||||
|
|
||||||
|
|
|
@ -228,7 +228,11 @@ ifeq ($(CONFIG_SYS_SOC),"at91")
|
||||||
ALL-y += $(obj)/boot.bin
|
ALL-y += $(obj)/boot.bin
|
||||||
endif
|
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
|
ALL-$(CONFIG_SPL_X86_16BIT_INIT) += $(obj)/u-boot-x86-16bit-spl.bin
|
||||||
|
endif
|
||||||
|
|
||||||
ALL-$(CONFIG_ARCH_ZYNQ) += $(obj)/boot.bin
|
ALL-$(CONFIG_ARCH_ZYNQ) += $(obj)/boot.bin
|
||||||
ALL-$(CONFIG_ARCH_ZYNQMP) += $(obj)/boot.bin
|
ALL-$(CONFIG_ARCH_ZYNQMP) += $(obj)/boot.bin
|
||||||
|
@ -253,8 +257,20 @@ else
|
||||||
FINAL_DTB_CONTAINER = $(obj)/$(SPL_BIN).multidtb.fit
|
FINAL_DTB_CONTAINER = $(obj)/$(SPL_BIN).multidtb.fit
|
||||||
endif
|
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 \
|
$(obj)/$(SPL_BIN)-dtb.bin: $(obj)/$(SPL_BIN)-nodtb.bin \
|
||||||
$(if $(CONFIG_SPL_SEPARATE_BSS),,$(obj)/$(SPL_BIN)-pad.bin) \
|
$(if $(CONFIG_SPL_SEPARATE_BSS),,$(obj)/$(SPL_BIN)-pad.bin) \
|
||||||
$(FINAL_DTB_CONTAINER) FORCE
|
$(FINAL_DTB_CONTAINER) FORCE
|
||||||
|
@ -316,7 +332,7 @@ quiet_cmd_objcopy = OBJCOPY $@
|
||||||
cmd_objcopy = $(OBJCOPY) $(OBJCOPYFLAGS) $(OBJCOPYFLAGS_$(@F)) $< $@
|
cmd_objcopy = $(OBJCOPY) $(OBJCOPYFLAGS) $(OBJCOPYFLAGS_$(@F)) $< $@
|
||||||
|
|
||||||
OBJCOPYFLAGS_$(SPL_BIN)-nodtb.bin = $(SPL_OBJCFLAGS) -O binary \
|
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
|
$(obj)/$(SPL_BIN)-nodtb.bin: $(obj)/$(SPL_BIN) FORCE
|
||||||
$(call if_changed,objcopy)
|
$(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
|
$(obj)/u-boot-x86-16bit-spl.bin: $(obj)/u-boot-spl FORCE
|
||||||
$(call if_changed,objcopy)
|
$(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)
|
LDFLAGS_$(SPL_BIN) += -T u-boot-spl.lds $(LDFLAGS_FINAL)
|
||||||
|
|
||||||
# Avoid 'Not enough room for program headers' error on binutils 2.28 onwards.
|
# 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
|
Sets the image size in bytes, for example 'size = <0x100000>' for a
|
||||||
1MB image.
|
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:
|
align-size:
|
||||||
This sets the alignment of the image size. For example, to ensure
|
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>'.
|
that the image ends on a 512-byte boundary, use 'align-size = <512>'.
|
||||||
|
|
|
@ -57,7 +57,7 @@ class Section(object):
|
||||||
self._name = name
|
self._name = name
|
||||||
self._node = node
|
self._node = node
|
||||||
self._image = image
|
self._image = image
|
||||||
self._offset = 0
|
self._offset = None
|
||||||
self._size = None
|
self._size = None
|
||||||
self._align_size = None
|
self._align_size = None
|
||||||
self._pad_before = 0
|
self._pad_before = 0
|
||||||
|
@ -75,6 +75,7 @@ class Section(object):
|
||||||
|
|
||||||
def _ReadNode(self):
|
def _ReadNode(self):
|
||||||
"""Read properties from the section node"""
|
"""Read properties from the section node"""
|
||||||
|
self._offset = fdt_util.GetInt(self._node, 'offset')
|
||||||
self._size = fdt_util.GetInt(self._node, 'size')
|
self._size = fdt_util.GetInt(self._node, 'size')
|
||||||
self._align_size = fdt_util.GetInt(self._node, 'align-size')
|
self._align_size = fdt_util.GetInt(self._node, 'align-size')
|
||||||
if tools.NotPowerOfTwo(self._align_size):
|
if tools.NotPowerOfTwo(self._align_size):
|
||||||
|
@ -130,7 +131,7 @@ class Section(object):
|
||||||
entry.AddMissingProperties()
|
entry.AddMissingProperties()
|
||||||
|
|
||||||
def SetCalculatedProperties(self):
|
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)
|
state.SetInt(self._node, 'size', self._size)
|
||||||
image_pos = self._image_pos
|
image_pos = self._image_pos
|
||||||
if self._parent_section:
|
if self._parent_section:
|
||||||
|
@ -424,8 +425,8 @@ class Section(object):
|
||||||
Args:
|
Args:
|
||||||
fd: File to write the map to
|
fd: File to write the map to
|
||||||
"""
|
"""
|
||||||
Entry.WriteMapLine(fd, indent, self._name, self._offset, self._size,
|
Entry.WriteMapLine(fd, indent, self._name, self._offset or 0,
|
||||||
self._image_pos)
|
self._size, self._image_pos)
|
||||||
for entry in self._entries.values():
|
for entry in self._entries.values():
|
||||||
entry.WriteMap(fd, indent + 1)
|
entry.WriteMap(fd, indent + 1)
|
||||||
|
|
||||||
|
|
|
@ -133,8 +133,8 @@ def Binman(options, args):
|
||||||
if name not in options.image:
|
if name not in options.image:
|
||||||
del images[name]
|
del images[name]
|
||||||
skip.append(name)
|
skip.append(name)
|
||||||
if skip:
|
if skip and options.verbosity >= 2:
|
||||||
print 'Skipping images: %s\n' % ', '.join(skip)
|
print 'Skipping images: %s' % ', '.join(skip)
|
||||||
|
|
||||||
state.Prepare(images, dtb)
|
state.Prepare(images, dtb)
|
||||||
|
|
||||||
|
|
|
@ -67,7 +67,8 @@ class Entry_section(Entry):
|
||||||
def Pack(self, offset):
|
def Pack(self, offset):
|
||||||
"""Pack all entries into the section"""
|
"""Pack all entries into the section"""
|
||||||
self._section.PackEntries()
|
self._section.PackEntries()
|
||||||
self._section.SetOffset(offset)
|
if self._section._offset is None:
|
||||||
|
self._section.SetOffset(offset)
|
||||||
self.size = self._section.GetSize()
|
self.size = self._section.GetSize()
|
||||||
return super(Entry_section, self).Pack(offset)
|
return super(Entry_section, self).Pack(offset)
|
||||||
|
|
||||||
|
|
|
@ -51,10 +51,10 @@ class Entry_text(Entry):
|
||||||
self.text_label, = self.GetEntryArgsOrProps(
|
self.text_label, = self.GetEntryArgsOrProps(
|
||||||
[EntryArg('text-label', str)])
|
[EntryArg('text-label', str)])
|
||||||
self.value, = self.GetEntryArgsOrProps([EntryArg(self.text_label, str)])
|
self.value, = self.GetEntryArgsOrProps([EntryArg(self.text_label, str)])
|
||||||
|
|
||||||
|
def ObtainContents(self):
|
||||||
if not self.value:
|
if not self.value:
|
||||||
self.Raise("No value provided for text label '%s'" %
|
self.Raise("No value provided for text label '%s'" %
|
||||||
self.text_label)
|
self.text_label)
|
||||||
|
|
||||||
def ObtainContents(self):
|
|
||||||
self.SetContents(self.value)
|
self.SetContents(self.value)
|
||||||
return True
|
return True
|
||||||
|
|
|
@ -18,6 +18,7 @@ class Entry_vblock(Entry):
|
||||||
"""An entry which contains a Chromium OS verified boot block
|
"""An entry which contains a Chromium OS verified boot block
|
||||||
|
|
||||||
Properties / Entry arguments:
|
Properties / Entry arguments:
|
||||||
|
- content: List of phandles to entries to sign
|
||||||
- keydir: Directory containing the public keys to use
|
- keydir: Directory containing the public keys to use
|
||||||
- keyblock: Name of the key file to use (inside keydir)
|
- keyblock: Name of the key file to use (inside keydir)
|
||||||
- signprivate: Name of provide 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)
|
return control.Binman(options, args)
|
||||||
|
|
||||||
def _DoTestFile(self, fname, debug=False, map=False, update_dtb=False,
|
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
|
"""Run binman with a given test file
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
|
@ -210,6 +211,8 @@ class TestFunctional(unittest.TestCase):
|
||||||
args.append('-up')
|
args.append('-up')
|
||||||
if not use_real_dtb:
|
if not use_real_dtb:
|
||||||
args.append('--fake-dtb')
|
args.append('--fake-dtb')
|
||||||
|
if verbosity is not None:
|
||||||
|
args.append('-v%d' % verbosity)
|
||||||
if entry_args:
|
if entry_args:
|
||||||
for arg, value in entry_args.iteritems():
|
for arg, value in entry_args.iteritems():
|
||||||
args.append('-a%s=%s' % (arg, value))
|
args.append('-a%s=%s' % (arg, value))
|
||||||
|
@ -1459,13 +1462,22 @@ class TestFunctional(unittest.TestCase):
|
||||||
|
|
||||||
def testSelectImage(self):
|
def testSelectImage(self):
|
||||||
"""Test that we can select which images to build"""
|
"""Test that we can select which images to build"""
|
||||||
with test_util.capture_sys_output() as (stdout, stderr):
|
expected = 'Skipping images: image1'
|
||||||
retcode = self._DoTestFile('006_dual_image.dts', images=['image2'])
|
|
||||||
self.assertEqual(0, retcode)
|
|
||||||
self.assertIn('Skipping images: image1', stdout.getvalue())
|
|
||||||
|
|
||||||
self.assertFalse(os.path.exists(tools.GetOutputFilename('image1.bin')))
|
# We should only get the expected message in verbose mode
|
||||||
self.assertTrue(os.path.exists(tools.GetOutputFilename('image2.bin')))
|
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):
|
def testUpdateFdtAll(self):
|
||||||
"""Test that all device trees are updated with offset/size info"""
|
"""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')
|
data = self._DoReadFile('100_intel_refcode.dts')
|
||||||
self.assertEqual(REFCODE_DATA, data[:len(REFCODE_DATA)])
|
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__":
|
if __name__ == "__main__":
|
||||||
unittest.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 a new issue