[U-Boot] [PATCH 00/40] x86: Add support for booting from TPL

At present SPL is used on 64-bit platforms, to allow SPL to be built as a 32-bit program and U-Boot proper to be built as 64-bit.
However it is useful to be able to use SPL on any x86 platform, where U-Boot needs to be updated in the field. Then SPL can select which U-Boot to run (A or B) and most of the code can be updated. Similarly, using TPL allows both SPL and U-Boot to be updated. This is the best approach, since it means that all of U-Boot proper as well as SPL (in particular SDRAM init) can be updated in the field. This provides for the smallest possible amount of read-only (non-updateable) code: just the TPL code.
This series contains a number of changes to allow x86 boards to use TPL, SPL and U-Boot proper. As a test, it is enabled for samus with a new chromebook_samus_tpl board.
Simon Glass (40): binman: Don't generate an error in 'text' entry constructor binman: Don't show image-skip message by default binman: Add a missing comment in Entry_vblock dm: core: Fix translate condition in ofnode_get_addr_size() cros_ec: Use a hyphen in the uclass name spl: Allow sandbox to build a device-tree file RFC: binman: Allow sections to have an offset x86: start64: Fix copyright message x86: mp_init: Use proper error numbers x86: Add a way to reinit the cpu x86: dts: Add device-tree labels for rtc and reset x86: Update a stale comment about ifdtool x86: Support SPL and TPL x86: Support booting with TPL x86: Add a handoff header file x86: broadwell: Improve SDRAM debugging output x86: broadwell: Allow SDRAM init from SPL x86: Move init of debug UART to cpu.c x86: broadwell: Split CPU init x86: Add support for starting from SPL/TPL x86: Allow 16-bit init to be in TPL x86: broadwell: Allow booting from SPL x86: broadwell: Select refcode and CPU code for SPL x86: Add common Intel code for SPL x86: Support saving MRC data from SPL x86: Add a simple TPL implementations x86: mrccache: Add more debugging x86: Add a sysreset driver for the Intel PCH x86: Support TPL in Intel common code x86: Don't set up MTRRs in SPL x86: Don't generate a bootstage report in SPL x86: Support PCI VGA ROM when TPL is used x86: sysreset: Implement the get_last() method x86: Add documention on the samus flashmap x86: samus: Update device tree for SPL x86: samus: Update device tree for verified boot x86: Update device tree for TPL x86: Update device tree for Chromium OS verified boot x86: Fix device-tree indentation x86: samus: Add a target to boot through TPL
Makefile | 1 + arch/Kconfig | 30 + arch/x86/Kconfig | 10 +- arch/x86/Makefile | 16 +- arch/x86/cpu/Makefile | 15 +- arch/x86/cpu/broadwell/Kconfig | 1 + arch/x86/cpu/broadwell/Makefile | 23 +- arch/x86/cpu/broadwell/cpu.c | 676 +-------------------- arch/x86/cpu/broadwell/cpu_from_spl.c | 63 ++ arch/x86/cpu/broadwell/cpu_full.c | 694 ++++++++++++++++++++++ arch/x86/cpu/broadwell/northbridge.c | 93 +++ arch/x86/cpu/broadwell/sdram.c | 136 +---- arch/x86/cpu/i386/cpu.c | 113 ++-- arch/x86/cpu/intel_common/Makefile | 17 +- arch/x86/cpu/intel_common/car.S | 2 +- arch/x86/cpu/intel_common/cpu_from_spl.c | 27 + arch/x86/cpu/mp_init.c | 10 +- arch/x86/cpu/start64.S | 2 +- arch/x86/cpu/start_from_spl.S | 71 +++ arch/x86/cpu/start_from_tpl.S | 50 ++ arch/x86/cpu/u-boot-spl.lds | 2 +- arch/x86/cpu/x86_64/cpu.c | 5 + arch/x86/dts/chromebook_samus.dts | 60 +- arch/x86/dts/reset.dtsi | 2 +- arch/x86/dts/rtc.dtsi | 2 +- arch/x86/dts/u-boot.dtsi | 154 +++-- arch/x86/include/asm/handoff.h | 15 + arch/x86/include/asm/mrccache.h | 11 + arch/x86/include/asm/spl.h | 17 +- arch/x86/include/asm/u-boot-x86.h | 20 + arch/x86/lib/Makefile | 9 +- arch/x86/lib/bootm.c | 2 +- arch/x86/lib/init_helpers.c | 5 +- arch/x86/lib/mrccache.c | 52 +- arch/x86/lib/spl.c | 44 +- arch/x86/lib/tpl.c | 118 ++++ board/google/Kconfig | 8 + board/google/chromebook_samus/Kconfig | 14 +- board/google/chromebook_samus/MAINTAINERS | 7 + configs/chromebook_samus_tpl_defconfig | 80 +++ doc/README.x86 | 14 + drivers/core/ofnode.c | 2 +- drivers/misc/cros_ec.c | 2 +- drivers/pci/pci_rom.c | 2 +- drivers/sysreset/Kconfig | 9 + drivers/sysreset/Makefile | 1 + drivers/sysreset/sysreset_intel_pch.c | 125 ++++ drivers/sysreset/sysreset_x86.c | 6 + include/configs/chromebook_link.h | 3 - include/configs/chromebook_samus.h | 3 + include/configs/qemu-x86.h | 3 - scripts/Makefile.spl | 24 +- tools/binman/bsection.py | 5 +- tools/binman/control.py | 4 +- tools/binman/etype/section.py | 3 +- tools/binman/etype/text.py | 4 +- tools/binman/etype/vblock.py | 1 + 57 files changed, 1933 insertions(+), 955 deletions(-) create mode 100644 arch/x86/cpu/broadwell/cpu_from_spl.c create mode 100644 arch/x86/cpu/broadwell/cpu_full.c create mode 100644 arch/x86/cpu/intel_common/cpu_from_spl.c create mode 100644 arch/x86/cpu/start_from_spl.S create mode 100644 arch/x86/cpu/start_from_tpl.S create mode 100644 arch/x86/include/asm/handoff.h create mode 100644 arch/x86/lib/tpl.c create mode 100644 configs/chromebook_samus_tpl_defconfig create mode 100644 drivers/sysreset/sysreset_intel_pch.c

It is not good practice to raise an exception in a constructor. In this case the 'text' entry may not actually be used, if -i is used to filter out the images that get built.
Move the exception to where the data is actually used.
Signed-off-by: Simon Glass sjg@chromium.org ---
tools/binman/etype/text.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/tools/binman/etype/text.py b/tools/binman/etype/text.py index 6e99819487..c4aa510a87 100644 --- a/tools/binman/etype/text.py +++ b/tools/binman/etype/text.py @@ -51,10 +51,10 @@ class Entry_text(Entry): self.text_label, = self.GetEntryArgsOrProps( [EntryArg('text-label', str)]) self.value, = self.GetEntryArgsOrProps([EntryArg(self.text_label, str)]) + + def ObtainContents(self): if not self.value: self.Raise("No value provided for text label '%s'" % self.text_label) - - def ObtainContents(self): self.SetContents(self.value) return True

On Wed, Jan 30, 2019 at 12:00 PM Simon Glass sjg@chromium.org wrote:
It is not good practice to raise an exception in a constructor. In this case the 'text' entry may not actually be used, if -i is used to filter out the images that get built.
Move the exception to where the data is actually used.
Signed-off-by: Simon Glass sjg@chromium.org
tools/binman/etype/text.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
Reviewed-by: Bin Meng bmeng.cn@gmail.com

This message is not very important since it is simply indicating that the user's instructions are being followed. Only show it when the verbosity level is above the default.
Signed-off-by: Simon Glass sjg@chromium.org ---
tools/binman/control.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/tools/binman/control.py b/tools/binman/control.py index 3446e2e79c..b32e4e1996 100644 --- a/tools/binman/control.py +++ b/tools/binman/control.py @@ -133,8 +133,8 @@ def Binman(options, args): if name not in options.image: del images[name] skip.append(name) - if skip: - print 'Skipping images: %s\n' % ', '.join(skip) + if skip and options.verbosity >= 2: + print 'Skipping images: %s' % ', '.join(skip)
state.Prepare(images, dtb)

Hi Simon,
On Wed, Jan 30, 2019 at 12:00 PM Simon Glass sjg@chromium.org wrote:
This message is not very important since it is simply indicating that the user's instructions are being followed. Only show it when the verbosity level is above the default.
Signed-off-by: Simon Glass sjg@chromium.org
tools/binman/control.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/tools/binman/control.py b/tools/binman/control.py index 3446e2e79c..b32e4e1996 100644 --- a/tools/binman/control.py +++ b/tools/binman/control.py @@ -133,8 +133,8 @@ def Binman(options, args): if name not in options.image: del images[name] skip.append(name)
if skip:
print 'Skipping images: %s\n' % ', '.join(skip)
if skip and options.verbosity >= 2:
print 'Skipping images: %s' % ', '.join(skip)
Is dropping '\n' intentional?
state.Prepare(images, dtb)
--
Regards, Bin

An important property is missing. Update the entry comment to include this.
Signed-off-by: Simon Glass sjg@chromium.org ---
tools/binman/etype/vblock.py | 1 + 1 file changed, 1 insertion(+)
diff --git a/tools/binman/etype/vblock.py b/tools/binman/etype/vblock.py index c4d970ed16..334ff9f966 100644 --- a/tools/binman/etype/vblock.py +++ b/tools/binman/etype/vblock.py @@ -18,6 +18,7 @@ class Entry_vblock(Entry): """An entry which contains a Chromium OS verified boot block
Properties / Entry arguments: + - content: List of phandles to entries to sign - keydir: Directory containing the public keys to use - keyblock: Name of the key file to use (inside keydir) - signprivate: Name of provide key file to use (inside keydir)

On Wed, Jan 30, 2019 at 12:00 PM Simon Glass sjg@chromium.org wrote:
An important property is missing. Update the entry comment to include this.
Signed-off-by: Simon Glass sjg@chromium.org
tools/binman/etype/vblock.py | 1 + 1 file changed, 1 insertion(+)
Reviewed-by: Bin Meng bmeng.cn@gmail.com

Update the condition to translate only if this is enabled for SPL.
Signed-off-by: Simon Glass sjg@chromium.org ---
drivers/core/ofnode.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/core/ofnode.c b/drivers/core/ofnode.c index 0e584c12dc..34f3c88b92 100644 --- a/drivers/core/ofnode.c +++ b/drivers/core/ofnode.c @@ -547,7 +547,7 @@ fdt_addr_t ofnode_get_addr_size(ofnode node, const char *property, ns = of_n_size_cells(np); *sizep = of_read_number(prop + na, ns);
- if (IS_ENABLED(CONFIG_OF_TRANSLATE) && ns > 0) + if (CONFIG_IS_ENABLED(OF_TRANSLATE) && ns > 0) return of_translate_address(np, prop); else return of_read_number(prop, na);

On Wed, Jan 30, 2019 at 12:00 PM Simon Glass sjg@chromium.org wrote:
Update the condition to translate only if this is enabled for SPL.
Signed-off-by: Simon Glass sjg@chromium.org
drivers/core/ofnode.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
Reviewed-by: Bin Meng bmeng.cn@gmail.com

Device-tree rules require that aliases use a hyphen rather than a underscore. Update the uclass name to fit with this.
Signed-off-by: Simon Glass sjg@chromium.org ---
drivers/misc/cros_ec.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/misc/cros_ec.c b/drivers/misc/cros_ec.c index 565de040fe..382f826286 100644 --- a/drivers/misc/cros_ec.c +++ b/drivers/misc/cros_ec.c @@ -1482,7 +1482,7 @@ int cros_ec_set_lid_shutdown_mask(struct udevice *dev, int enable)
UCLASS_DRIVER(cros_ec) = { .id = UCLASS_CROS_EC, - .name = "cros_ec", + .name = "cros-ec", .per_device_auto_alloc_size = sizeof(struct cros_ec_dev), .post_bind = dm_scan_fdt_dev, .flags = DM_UC_FLAG_ALLOC_PRIV_DMA,

Hi Simon,
On Wed, Jan 30, 2019 at 12:00 PM Simon Glass sjg@chromium.org wrote:
Device-tree rules require that aliases use a hyphen rather than a underscore. Update the uclass name to fit with this.
I don't understand the connection between the uclass name and the DT aliases. Could you please provide more details?
Signed-off-by: Simon Glass sjg@chromium.org
Regards, Bin

At present only OF_SEPARATE is considered valid for building a device-tree file in SPL. However sandbox uses OF_HOSTFILE instead. Update the logic to handle this and make it easier to understand.
Signed-off-by: Simon Glass sjg@chromium.org ---
scripts/Makefile.spl | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-)
diff --git a/scripts/Makefile.spl b/scripts/Makefile.spl index 1430d7d851..c9eea629dd 100644 --- a/scripts/Makefile.spl +++ b/scripts/Makefile.spl @@ -255,8 +255,20 @@ else FINAL_DTB_CONTAINER = $(obj)/$(SPL_BIN).multidtb.fit endif
+# Build the .dtb file if: +# - we are not using OF_PLATDATA +# - we are using OF_CONTROL +# - we have either OF_SEPARATE or OF_HOSTFILE +build_dtb := +ifeq ($(CONFIG_$(SPL_TPL_)OF_PLATDATA),) +ifneq ($(CONFIG_$(SPL_TPL_)OF_CONTROL),) +ifeq ($(CONFIG_OF_SEPARATE)$(CONFIG_OF_HOSTFILE),y) +build_dtb := y +endif +endif +endif
-ifeq ($(CONFIG_$(SPL_TPL_)OF_CONTROL)$(CONFIG_OF_SEPARATE)$(CONFIG_$(SPL_TPL_)OF_PLATDATA),yy) +ifneq ($(build_dtb),) $(obj)/$(SPL_BIN)-dtb.bin: $(obj)/$(SPL_BIN)-nodtb.bin \ $(if $(CONFIG_SPL_SEPARATE_BSS),,$(obj)/$(SPL_BIN)-pad.bin) \ $(FINAL_DTB_CONTAINER) FORCE

Hi Simon,
On Wed, Jan 30, 2019 at 12:00 PM Simon Glass sjg@chromium.org wrote:
At present only OF_SEPARATE is considered valid for building a device-tree file in SPL. However sandbox uses OF_HOSTFILE instead. Update the logic to handle this and make it easier to understand.
Signed-off-by: Simon Glass sjg@chromium.org
scripts/Makefile.spl | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-)
diff --git a/scripts/Makefile.spl b/scripts/Makefile.spl index 1430d7d851..c9eea629dd 100644 --- a/scripts/Makefile.spl +++ b/scripts/Makefile.spl @@ -255,8 +255,20 @@ else FINAL_DTB_CONTAINER = $(obj)/$(SPL_BIN).multidtb.fit endif
+# Build the .dtb file if: +# - we are not using OF_PLATDATA +# - we are using OF_CONTROL +# - we have either OF_SEPARATE or OF_HOSTFILE
This is not 1:1 translation of the original logic.
The original logic was any two of the 3 macros: $CONFIG_$(SPL_TPL_)OF_CONTROL, $CONFIG_OF_SEPARATE, $CONFIG_$(SPL_TPL_)OF_PLATDATA, are defined. But here the new logic is excluding $CONFIG_$(SPL_TPL_)OF_PLATDATA.
+build_dtb := +ifeq ($(CONFIG_$(SPL_TPL_)OF_PLATDATA),) +ifneq ($(CONFIG_$(SPL_TPL_)OF_CONTROL),) +ifeq ($(CONFIG_OF_SEPARATE)$(CONFIG_OF_HOSTFILE),y) +build_dtb := y +endif +endif +endif
-ifeq ($(CONFIG_$(SPL_TPL_)OF_CONTROL)$(CONFIG_OF_SEPARATE)$(CONFIG_$(SPL_TPL_)OF_PLATDATA),yy) +ifneq ($(build_dtb),) $(obj)/$(SPL_BIN)-dtb.bin: $(obj)/$(SPL_BIN)-nodtb.bin \ $(if $(CONFIG_SPL_SEPARATE_BSS),,$(obj)/$(SPL_BIN)-pad.bin) \ $(FINAL_DTB_CONTAINER) FORCE --
Regards, Bin

At present sections are always placed automatically. Even if an 'offset' property is provided it is ignored. Update the logic to support an offset for sections.
Note: Needs a test updates
Signed-off-by: Simon Glass sjg@chromium.org ---
tools/binman/bsection.py | 5 +++-- tools/binman/etype/section.py | 3 ++- 2 files changed, 5 insertions(+), 3 deletions(-)
diff --git a/tools/binman/bsection.py b/tools/binman/bsection.py index ccf2920c5b..4a5ced201e 100644 --- a/tools/binman/bsection.py +++ b/tools/binman/bsection.py @@ -57,7 +57,7 @@ class Section(object): self._name = name self._node = node self._image = image - self._offset = 0 + self._offset = None self._size = None self._align_size = None self._pad_before = 0 @@ -75,6 +75,7 @@ class Section(object):
def _ReadNode(self): """Read properties from the section node""" + self._offset = fdt_util.GetInt(self._node, 'offset') self._size = fdt_util.GetInt(self._node, 'size') self._align_size = fdt_util.GetInt(self._node, 'align-size') if tools.NotPowerOfTwo(self._align_size): @@ -130,7 +131,7 @@ class Section(object): entry.AddMissingProperties()
def SetCalculatedProperties(self): - state.SetInt(self._node, 'offset', self._offset) + state.SetInt(self._node, 'offset', self._offset or 0) state.SetInt(self._node, 'size', self._size) image_pos = self._image_pos if self._parent_section: diff --git a/tools/binman/etype/section.py b/tools/binman/etype/section.py index 7f1b413604..3681a48468 100644 --- a/tools/binman/etype/section.py +++ b/tools/binman/etype/section.py @@ -67,7 +67,8 @@ class Entry_section(Entry): def Pack(self, offset): """Pack all entries into the section""" self._section.PackEntries() - self._section.SetOffset(offset) + if self._section._offset is None: + self._section.SetOffset(offset) self.size = self._section.GetSize() return super(Entry_section, self).Pack(offset)

Hi Simon,
On Wed, Jan 30, 2019 at 12:00 PM Simon Glass sjg@chromium.org wrote:
At present sections are always placed automatically. Even if an 'offset' property is provided it is ignored. Update the logic to support an offset for sections.
Note: Needs a test updates
Signed-off-by: Simon Glass sjg@chromium.org
tools/binman/bsection.py | 5 +++-- tools/binman/etype/section.py | 3 ++- 2 files changed, 5 insertions(+), 3 deletions(-)
Reviewed-by: Bin Meng bmeng.cn@gmail.com
x86 is not using 'offset' in section so it should be fine. I think we will need update tools/binman/README to document 'offset' too.
Regards, Bin

There is a typo in this header. Fix it.
Signed-off-by: Simon Glass sjg@chromium.org ---
arch/x86/cpu/start64.S | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/arch/x86/cpu/start64.S b/arch/x86/cpu/start64.S index a78a3316b6..7be834788b 100644 --- a/arch/x86/cpu/start64.S +++ b/arch/x86/cpu/start64.S @@ -2,7 +2,7 @@ /* * 64-bit x86 Startup Code * - * (C) Copyright 216 Google, Inc + * Copyright 2019 Google, Inc * Written by Simon Glass sjg@chromium.org */

On Wed, Jan 30, 2019 at 12:00 PM Simon Glass sjg@chromium.org wrote:
There is a typo in this header. Fix it.
Signed-off-by: Simon Glass sjg@chromium.org
arch/x86/cpu/start64.S | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
Reviewed-by: Bin Meng bmeng.cn@gmail.com

At present many of the functions in this file return -1 as an error number. which is -EPERM. Update the code to use real error numbers.
Signed-off-by: Simon Glass sjg@chromium.org ---
arch/x86/cpu/mp_init.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-)
diff --git a/arch/x86/cpu/mp_init.c b/arch/x86/cpu/mp_init.c index ea64c2ee57..fefbf8f728 100644 --- a/arch/x86/cpu/mp_init.c +++ b/arch/x86/cpu/mp_init.c @@ -322,7 +322,7 @@ static int start_aps(int ap_count, atomic_t *num_aps) if (sipi_vector > max_vector_loc) { printf("SIPI vector too large! 0x%08x\n", sipi_vector); - return -1; + return -ENOSPC; }
debug("Attempting to start %d APs\n", ap_count); @@ -364,7 +364,7 @@ static int start_aps(int ap_count, atomic_t *num_aps) if (wait_for_aps(num_aps, ap_count, 10000, 50)) { debug("Not all APs checked in: %d/%d\n", atomic_read(num_aps), ap_count); - return -1; + return -EIO; }
return 0; @@ -387,7 +387,7 @@ static int bsp_do_flight_plan(struct udevice *cpu, struct mp_params *mp_params) if (wait_for_aps(&rec->cpus_entered, num_aps, timeout_us, step_us)) { debug("MP record %d timeout\n", i); - ret = -1; + ret = -ETIMEDOUT; } }
@@ -508,7 +508,7 @@ int mp_init(struct mp_params *p)
if (p == NULL || p->flight_plan == NULL || p->num_records < 1) { printf("Invalid MP parameters\n"); - return -1; + return -EINVAL; }
num_cpus = cpu_get_count(cpu); @@ -531,7 +531,7 @@ int mp_init(struct mp_params *p) /* Load the SIPI vector */ ret = load_sipi_vector(&ap_count, num_cpus); if (ap_count == NULL) - return -1; + return -ENOENT;
/* * Make sure SIPI data hits RAM so the APs that come up will see

On Wed, Jan 30, 2019 at 12:00 PM Simon Glass sjg@chromium.org wrote:
At present many of the functions in this file return -1 as an error number. which is -EPERM. Update the code to use real error numbers.
Signed-off-by: Simon Glass sjg@chromium.org
arch/x86/cpu/mp_init.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-)
Reviewed-by: Bin Meng bmeng.cn@gmail.com

We cannot init the CPU fully both than once during a boot. Add a new function which can be called to figure out the CPU identity, but which does not change anything. For x86_64, this is empty for now.
Signed-off-by: Simon Glass sjg@chromium.org ---
arch/x86/cpu/i386/cpu.c | 113 ++++++++++++++++++------------ arch/x86/cpu/x86_64/cpu.c | 5 ++ arch/x86/include/asm/u-boot-x86.h | 20 ++++++ 3 files changed, 94 insertions(+), 44 deletions(-)
diff --git a/arch/x86/cpu/i386/cpu.c b/arch/x86/cpu/i386/cpu.c index 208ef08562..4c362f4adc 100644 --- a/arch/x86/cpu/i386/cpu.c +++ b/arch/x86/cpu/i386/cpu.c @@ -309,21 +309,22 @@ u32 cpu_get_stepping(void) return gd->arch.x86_mask; }
-int x86_cpu_init_f(void) +/* initialise FPU, reset EM, set MP and NE */ +static void setup_cpu_features(void) { const u32 em_rst = ~X86_CR0_EM; const u32 mp_ne_set = X86_CR0_MP | X86_CR0_NE;
- if (ll_boot_init()) { - /* initialize FPU, reset EM, set MP and NE */ - asm ("fninit\n" \ - "movl %%cr0, %%eax\n" \ - "andl %0, %%eax\n" \ - "orl %1, %%eax\n" \ - "movl %%eax, %%cr0\n" \ - : : "i" (em_rst), "i" (mp_ne_set) : "eax"); - } + asm ("fninit\n" \ + "movl %%cr0, %%eax\n" \ + "andl %0, %%eax\n" \ + "orl %1, %%eax\n" \ + "movl %%eax, %%cr0\n" \ + : : "i" (em_rst), "i" (mp_ne_set) : "eax"); +}
+static void setup_identity(void) +{ /* identify CPU via cpuid and store the decoded info into gd->arch */ if (has_cpuid()) { struct cpu_device_id cpu; @@ -339,46 +340,70 @@ int x86_cpu_init_f(void)
gd->arch.has_mtrr = has_mtrr(); } - /* Don't allow PCI region 3 to use memory in the 2-4GB memory hole */ +} + +/* Don't allow PCI region 3 to use memory in the 2-4GB memory hole */ +static void setup_pci_ram_top(void) +{ gd->pci_ram_top = 0x80000000U; +} + +static void setup_mtrr(void) +{ + u64 mtrr_cap;
/* Configure fixed range MTRRs for some legacy regions */ - if (gd->arch.has_mtrr) { - u64 mtrr_cap; - - mtrr_cap = native_read_msr(MTRR_CAP_MSR); - if (mtrr_cap & MTRR_CAP_FIX) { - /* Mark the VGA RAM area as uncacheable */ - native_write_msr(MTRR_FIX_16K_A0000_MSR, - MTRR_FIX_TYPE(MTRR_TYPE_UNCACHEABLE), - MTRR_FIX_TYPE(MTRR_TYPE_UNCACHEABLE)); - - /* - * Mark the PCI ROM area as cacheable to improve ROM - * execution performance. - */ - native_write_msr(MTRR_FIX_4K_C0000_MSR, - MTRR_FIX_TYPE(MTRR_TYPE_WRBACK), - MTRR_FIX_TYPE(MTRR_TYPE_WRBACK)); - native_write_msr(MTRR_FIX_4K_C8000_MSR, - MTRR_FIX_TYPE(MTRR_TYPE_WRBACK), - MTRR_FIX_TYPE(MTRR_TYPE_WRBACK)); - native_write_msr(MTRR_FIX_4K_D0000_MSR, - MTRR_FIX_TYPE(MTRR_TYPE_WRBACK), - MTRR_FIX_TYPE(MTRR_TYPE_WRBACK)); - native_write_msr(MTRR_FIX_4K_D8000_MSR, - MTRR_FIX_TYPE(MTRR_TYPE_WRBACK), - MTRR_FIX_TYPE(MTRR_TYPE_WRBACK)); - - /* Enable the fixed range MTRRs */ - msr_setbits_64(MTRR_DEF_TYPE_MSR, MTRR_DEF_TYPE_FIX_EN); - } + if (!gd->arch.has_mtrr) + return; + + mtrr_cap = native_read_msr(MTRR_CAP_MSR); + if (mtrr_cap & MTRR_CAP_FIX) { + /* Mark the VGA RAM area as uncacheable */ + native_write_msr(MTRR_FIX_16K_A0000_MSR, + MTRR_FIX_TYPE(MTRR_TYPE_UNCACHEABLE), + MTRR_FIX_TYPE(MTRR_TYPE_UNCACHEABLE)); + + /* + * Mark the PCI ROM area as cacheable to improve ROM + * execution performance. + */ + native_write_msr(MTRR_FIX_4K_C0000_MSR, + MTRR_FIX_TYPE(MTRR_TYPE_WRBACK), + MTRR_FIX_TYPE(MTRR_TYPE_WRBACK)); + native_write_msr(MTRR_FIX_4K_C8000_MSR, + MTRR_FIX_TYPE(MTRR_TYPE_WRBACK), + MTRR_FIX_TYPE(MTRR_TYPE_WRBACK)); + native_write_msr(MTRR_FIX_4K_D0000_MSR, + MTRR_FIX_TYPE(MTRR_TYPE_WRBACK), + MTRR_FIX_TYPE(MTRR_TYPE_WRBACK)); + native_write_msr(MTRR_FIX_4K_D8000_MSR, + MTRR_FIX_TYPE(MTRR_TYPE_WRBACK), + MTRR_FIX_TYPE(MTRR_TYPE_WRBACK)); + + /* Enable the fixed range MTRRs */ + msr_setbits_64(MTRR_DEF_TYPE_MSR, MTRR_DEF_TYPE_FIX_EN); } +} + +int x86_cpu_init_f(void) +{ + if (ll_boot_init()) + setup_cpu_features(); + setup_identity(); + setup_mtrr(); + setup_pci_ram_top();
-#ifdef CONFIG_I8254_TIMER /* Set up the i8254 timer if required */ - i8254_init(); -#endif + if (IS_ENABLED(CONFIG_I8254_TIMER)) + i8254_init(); + + return 0; +} + +int x86_cpu_reinit_f(void) +{ + setup_identity(); + setup_pci_ram_top();
return 0; } diff --git a/arch/x86/cpu/x86_64/cpu.c b/arch/x86/cpu/x86_64/cpu.c index 6c063e8200..42abb23a9e 100644 --- a/arch/x86/cpu/x86_64/cpu.c +++ b/arch/x86/cpu/x86_64/cpu.c @@ -61,3 +61,8 @@ int print_cpuinfo(void) { return 0; } + +int x86_cpu_reinit_f(void) +{ + return 0; +} diff --git a/arch/x86/include/asm/u-boot-x86.h b/arch/x86/include/asm/u-boot-x86.h index 670fcdc009..c252192bf4 100644 --- a/arch/x86/include/asm/u-boot-x86.h +++ b/arch/x86/include/asm/u-boot-x86.h @@ -13,7 +13,27 @@ extern char gdt_rom[];
/* cpu/.../cpu.c */ int arch_cpu_init(void); + +/** + * x86_cpu_init_f() - Set up basic features of the x86 CPU + * + * 0 on success, -ve on error + */ int x86_cpu_init_f(void); + +/** + * x86_cpu_reinit_f() - Set up the CPU a second time + * + * Once cpu_init_f() has been called (e.g. in SPL) we should not call it + * again (e.g. in U-Boot proper) since it sets up the state from scratch. + * Call this function in later phases of U-Boot instead. It reads the CPU + * identify so that CPU functions can be used correctly, but does not change + * anything. + * + * @return 0 (indicating success, to mimic cpu_init_f()) + */ +int x86_cpu_reinit_f(void); + int cpu_init_f(void); void setup_gdt(struct global_data *id, u64 *gdt_addr); /*

On Wed, Jan 30, 2019 at 12:00 PM Simon Glass sjg@chromium.org wrote:
We cannot init the CPU fully both than once during a boot. Add a new function which can be called to figure out the CPU identity, but which does not change anything. For x86_64, this is empty for now.
Signed-off-by: Simon Glass sjg@chromium.org
arch/x86/cpu/i386/cpu.c | 113 ++++++++++++++++++------------ arch/x86/cpu/x86_64/cpu.c | 5 ++ arch/x86/include/asm/u-boot-x86.h | 20 ++++++ 3 files changed, 94 insertions(+), 44 deletions(-)
Reviewed-by: Bin Meng bmeng.cn@gmail.com

Add labels for these nodes so that board DT files can reference them.
Signed-off-by: Simon Glass sjg@chromium.org ---
arch/x86/dts/reset.dtsi | 2 +- arch/x86/dts/rtc.dtsi | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/arch/x86/dts/reset.dtsi b/arch/x86/dts/reset.dtsi index f979d83757..555d0dd960 100644 --- a/arch/x86/dts/reset.dtsi +++ b/arch/x86/dts/reset.dtsi @@ -1,5 +1,5 @@ / { - reset { + reset: reset { compatible = "x86,reset"; u-boot,dm-pre-reloc; }; diff --git a/arch/x86/dts/rtc.dtsi b/arch/x86/dts/rtc.dtsi index 1797e042da..d0bbd84e50 100644 --- a/arch/x86/dts/rtc.dtsi +++ b/arch/x86/dts/rtc.dtsi @@ -1,5 +1,5 @@ / { - rtc { + rtc: rtc { compatible = "motorola,mc146818"; u-boot,dm-pre-reloc; reg = <0x70 2>;

On Wed, Jan 30, 2019 at 12:00 PM Simon Glass sjg@chromium.org wrote:
Add labels for these nodes so that board DT files can reference them.
Signed-off-by: Simon Glass sjg@chromium.org
arch/x86/dts/reset.dtsi | 2 +- arch/x86/dts/rtc.dtsi | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-)
Reviewed-by: Bin Meng bmeng.cn@gmail.com

We use binman to build the x86 image now. Update a comment which still refers to ifdtool.
Signed-off-by: Simon Glass sjg@chromium.org ---
arch/x86/cpu/intel_common/car.S | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/arch/x86/cpu/intel_common/car.S b/arch/x86/cpu/intel_common/car.S index 52a77bb2d1..00308dbdef 100644 --- a/arch/x86/cpu/intel_common/car.S +++ b/arch/x86/cpu/intel_common/car.S @@ -235,7 +235,7 @@ mtrr_table_end:
.align 4 _dt_ucode_base_size: - /* These next two fields are filled in by ifdtool */ + /* These next two fields are filled in by binman */ .globl ucode_base ucode_base: /* Declared in microcode.h */ .long 0 /* microcode base */

Hi Simon,
On Wed, Jan 30, 2019 at 12:00 PM Simon Glass sjg@chromium.org wrote:
We use binman to build the x86 image now. Update a comment which still refers to ifdtool.
Signed-off-by: Simon Glass sjg@chromium.org
arch/x86/cpu/intel_common/car.S | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
Reviewed-by: Bin Meng bmeng.cn@gmail.com
But we should apply the same change in arch/x86/lib/fsp/fsp_car.S too.
Regards, Bin

At present only chromebook_link64 supports SPL. It is useful to eb able to support both TPL and SPL to implement verified boot on x86.
Enable the options for both along with some suitable default options needed to boot through these phases.
Signed-off-by: Simon Glass sjg@chromium.org ---
arch/Kconfig | 30 ++++++++++++++++++++++++++++++ arch/x86/Kconfig | 1 - 2 files changed, 30 insertions(+), 1 deletion(-)
diff --git a/arch/Kconfig b/arch/Kconfig index 35e2712fce..7cb207fe35 100644 --- a/arch/Kconfig +++ b/arch/Kconfig @@ -124,6 +124,8 @@ config SH
config X86 bool "x86 architecture" + select SUPPORT_SPL + select SUPPORT_TPL select CREATE_ARCH_SYMLINK select DM select DM_PCI @@ -160,6 +162,34 @@ config X86 imply USB_ETHER_ASIX imply USB_ETHER_SMSC95XX imply USB_HOST_ETHER + # Thing to enable for when SPL/TPL are enabled: SPL + imply SPL_DM + imply SPL_OF_LIBFDT + imply SPL_DRIVERS_MISC_SUPPORT + imply SPL_GPIO_SUPPORT + imply SPL_LIBCOMMON_SUPPORT + imply SPL_LIBGENERIC_SUPPORT + imply SPL_SERIAL_SUPPORT + imply SPL_SPI_FLASH_SUPPORT + imply SPL_SPI_SUPPORT + imply SPL_OF_CONTROL + imply SPL_TIMER + imply SPL_REGMAP + imply SPL_SYSCON + # TPL + imply TPL_DM + imply TPL_OF_LIBFDT + imply TPL_DRIVERS_MISC_SUPPORT + imply TPL_GPIO_SUPPORT + imply TPL_LIBCOMMON_SUPPORT + imply TPL_LIBGENERIC_SUPPORT + imply TPL_SERIAL_SUPPORT + imply TPL_SPI_FLASH_SUPPORT + imply TPL_SPI_SUPPORT + imply TPL_OF_CONTROL + imply TPL_TIMER + imply TPL_REGMAP + imply TPL_SYSCON
config XTENSA bool "Xtensa architecture" diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig index e052093775..185f0ef8c4 100644 --- a/arch/x86/Kconfig +++ b/arch/x86/Kconfig @@ -32,7 +32,6 @@ config X86_RUN_32BIT config X86_RUN_64BIT bool "64-bit" select X86_64 - select SUPPORT_SPL select SPL select SPL_SEPARATE_BSS help

On Wed, Jan 30, 2019 at 12:00 PM Simon Glass sjg@chromium.org wrote:
At present only chromebook_link64 supports SPL. It is useful to eb able to support both TPL and SPL to implement verified boot on x86.
Enable the options for both along with some suitable default options needed to boot through these phases.
Signed-off-by: Simon Glass sjg@chromium.org
arch/Kconfig | 30 ++++++++++++++++++++++++++++++ arch/x86/Kconfig | 1 - 2 files changed, 30 insertions(+), 1 deletion(-)
Reviewed-by: Bin Meng bmeng.cn@gmail.com

Some boards want to use TPL as the first phase of U-Boot. This allows selection of A or B SPL phases, thus allowing the memory init to be upgraded in the field.
Add a new Kconfig option for this.
Signed-off-by: Simon Glass sjg@chromium.org ---
arch/x86/Kconfig | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-)
diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig index 185f0ef8c4..45a533625a 100644 --- a/arch/x86/Kconfig +++ b/arch/x86/Kconfig @@ -176,10 +176,17 @@ config X86_16BIT_INIT config SPL_X86_16BIT_INIT bool depends on X86_RESET_VECTOR - default y if X86_RESET_VECTOR && SPL + default y if X86_RESET_VECTOR && SPL && !TPL help This is enabled when 16-bit init is in SPL
+config TPL_X86_16BIT_INIT + bool + depends on X86_RESET_VECTOR + default y if X86_RESET_VECTOR && TPL + help + This is enabled when 16-bit init is in TPL + config X86_32BIT_INIT bool depends on X86_RESET_VECTOR

On Wed, Jan 30, 2019 at 12:00 PM Simon Glass sjg@chromium.org wrote:
Some boards want to use TPL as the first phase of U-Boot. This allows selection of A or B SPL phases, thus allowing the memory init to be upgraded in the field.
Add a new Kconfig option for this.
Signed-off-by: Simon Glass sjg@chromium.org
arch/x86/Kconfig | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-)
Reviewed-by: Bin Meng bmeng.cn@gmail.com

Add an arch-specific handoff header so that we can use the HANDOFF feature on x86 devices.
Signed-off-by: Simon Glass sjg@chromium.org ---
arch/x86/include/asm/handoff.h | 15 +++++++++++++++ 1 file changed, 15 insertions(+) create mode 100644 arch/x86/include/asm/handoff.h
diff --git a/arch/x86/include/asm/handoff.h b/arch/x86/include/asm/handoff.h new file mode 100644 index 0000000000..4d18d59efe --- /dev/null +++ b/arch/x86/include/asm/handoff.h @@ -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

On Wed, Jan 30, 2019 at 12:00 PM Simon Glass sjg@chromium.org wrote:
Add an arch-specific handoff header so that we can use the HANDOFF feature on x86 devices.
Signed-off-by: Simon Glass sjg@chromium.org
arch/x86/include/asm/handoff.h | 15 +++++++++++++++ 1 file changed, 15 insertions(+) create mode 100644 arch/x86/include/asm/handoff.h
Reviewed-by: Bin Meng bmeng.cn@gmail.com

Add debugging during SDRAM init so that problems are easier to diagnose.
Signed-off-by: Simon Glass sjg@chromium.org ---
arch/x86/cpu/broadwell/sdram.c | 32 ++++++++++++++++++++------------ 1 file changed, 20 insertions(+), 12 deletions(-)
diff --git a/arch/x86/cpu/broadwell/sdram.c b/arch/x86/cpu/broadwell/sdram.c index 03a35bcf73..1b9f9840c6 100644 --- a/arch/x86/cpu/broadwell/sdram.c +++ b/arch/x86/cpu/broadwell/sdram.c @@ -204,16 +204,18 @@ int dram_init(void)
/* Print ME state before MRC */ ret = syscon_get_by_driver_data(X86_SYSCON_ME, &me_dev); - if (ret) + if (ret) { + debug("Cannot get ME (err=%d)\n", ret); return ret; + } intel_me_status(me_dev);
/* Save ME HSIO version */ - ret = uclass_first_device(UCLASS_PCH, &pch_dev); - if (ret) + ret = uclass_first_device_err(UCLASS_PCH, &pch_dev); + if (ret) { + debug("Cannot get PCH (err=%d)\n", ret); return ret; - if (!pch_dev) - return -ENODEV; + } power_state_get(pch_dev, &ps);
intel_me_hsio_version(me_dev, &ps.hsio_version, &ps.hsio_checksum); @@ -221,15 +223,17 @@ int dram_init(void) broadwell_fill_pei_data(pei_data); mainboard_fill_pei_data(pei_data);
- ret = uclass_first_device(UCLASS_NORTHBRIDGE, &dev); - if (ret) + ret = uclass_first_device_err(UCLASS_NORTHBRIDGE, &dev); + if (ret) { + debug("Cannot get Northbridge (err=%d)\n", ret); return ret; - if (!dev) - return -ENODEV; + } size = 256; ret = mrc_locate_spd(dev, size, &spd_data); - if (ret) + if (ret) { + debug("Cannot locate SPD (err=%d)\n", ret); return ret; + } memcpy(pei_data->spd_data[0][0], spd_data, size); memcpy(pei_data->spd_data[1][0], spd_data, size);
@@ -239,13 +243,17 @@ int dram_init(void)
debug("PEI version %#x\n", pei_data->pei_version); ret = mrc_common_init(dev, pei_data, true); - if (ret) + if (ret) { + debug("mrc_common_init() failed(err=%d)\n", ret); return ret; + } debug("Memory init done\n");
ret = sdram_find(dev); - if (ret) + if (ret) { + debug("sdram_find() failed (err=%d)\n", ret); return ret; + } gd->ram_size = gd->arch.meminfo.total_32bit_memory; debug("RAM size %llx\n", (unsigned long long)gd->ram_size);

On Wed, Jan 30, 2019 at 12:00 PM Simon Glass sjg@chromium.org wrote:
Add debugging during SDRAM init so that problems are easier to diagnose.
Signed-off-by: Simon Glass sjg@chromium.org
arch/x86/cpu/broadwell/sdram.c | 32 ++++++++++++++++++++------------ 1 file changed, 20 insertions(+), 12 deletions(-)
Reviewed-by: Bin Meng bmeng.cn@gmail.com

At present SDRAM is always set up in U-Boot proper. Allow this to be done in SPL instead so that U-Boot proper can be loaded into SDRAM and run from there. This allows U-Boot to be compressed to reduce space, since it is not necessary to run it directly from flash.
Signed-off-by: Simon Glass sjg@chromium.org ---
arch/x86/cpu/broadwell/Makefile | 2 +- arch/x86/cpu/broadwell/northbridge.c | 93 ++++++++++++++++++++++++++++ arch/x86/cpu/broadwell/sdram.c | 93 ---------------------------- 3 files changed, 94 insertions(+), 94 deletions(-)
diff --git a/arch/x86/cpu/broadwell/Makefile b/arch/x86/cpu/broadwell/Makefile index a032861e57..55f2c93719 100644 --- a/arch/x86/cpu/broadwell/Makefile +++ b/arch/x86/cpu/broadwell/Makefile @@ -12,4 +12,4 @@ obj-y += pinctrl_broadwell.o obj-y += power_state.o obj-y += refcode.o obj-y += sata.o -obj-y += sdram.o +obj-$(CONFIG_$(SPL_TPL_)X86_32BIT_INIT) += sdram.o diff --git a/arch/x86/cpu/broadwell/northbridge.c b/arch/x86/cpu/broadwell/northbridge.c index 3055880bb7..93f2dc25b5 100644 --- a/arch/x86/cpu/broadwell/northbridge.c +++ b/arch/x86/cpu/broadwell/northbridge.c @@ -6,8 +6,101 @@ #include <common.h> #include <dm.h> #include <asm/io.h> +#include <asm/mrc_common.h> #include <asm/arch/iomap.h> #include <asm/arch/pch.h> +#include <asm/arch/pei_data.h> + +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) { diff --git a/arch/x86/cpu/broadwell/sdram.c b/arch/x86/cpu/broadwell/sdram.c index 1b9f9840c6..b8450cc9d2 100644 --- a/arch/x86/cpu/broadwell/sdram.c +++ b/arch/x86/cpu/broadwell/sdram.c @@ -34,99 +34,6 @@ int dram_init_banksize(void) return 0; }
-void broadwell_fill_pei_data(struct pei_data *pei_data) -{ - pei_data->pei_version = PEI_VERSION; - pei_data->board_type = BOARD_TYPE_ULT; - pei_data->pciexbar = MCFG_BASE_ADDRESS; - pei_data->smbusbar = SMBUS_BASE_ADDRESS; - pei_data->ehcibar = EARLY_EHCI_BAR; - pei_data->xhcibar = EARLY_XHCI_BAR; - pei_data->gttbar = EARLY_GTT_BAR; - pei_data->pmbase = ACPI_BASE_ADDRESS; - pei_data->gpiobase = GPIO_BASE_ADDRESS; - pei_data->tseg_size = CONFIG_SMM_TSEG_SIZE; - pei_data->temp_mmio_base = EARLY_TEMP_MMIO; - pei_data->tx_byte = sdram_console_tx_byte; - pei_data->ddr_refresh_2x = 1; -} - -static inline void pei_data_usb2_port(struct pei_data *pei_data, int port, - uint16_t length, uint8_t enable, - uint8_t oc_pin, uint8_t location) -{ - pei_data->usb2_ports[port].length = length; - pei_data->usb2_ports[port].enable = enable; - pei_data->usb2_ports[port].oc_pin = oc_pin; - pei_data->usb2_ports[port].location = location; -} - -static inline void pei_data_usb3_port(struct pei_data *pei_data, int port, - uint8_t enable, uint8_t oc_pin, - uint8_t fixed_eq) -{ - pei_data->usb3_ports[port].enable = enable; - pei_data->usb3_ports[port].oc_pin = oc_pin; - pei_data->usb3_ports[port].fixed_eq = fixed_eq; -} - -void mainboard_fill_pei_data(struct pei_data *pei_data) -{ - /* DQ byte map for Samus board */ - const u8 dq_map[2][6][2] = { - { { 0x0F, 0xF0 }, { 0x00, 0xF0 }, { 0x0F, 0xF0 }, - { 0x0F, 0x00 }, { 0xFF, 0x00 }, { 0xFF, 0x00 } }, - { { 0x0F, 0xF0 }, { 0x00, 0xF0 }, { 0x0F, 0xF0 }, - { 0x0F, 0x00 }, { 0xFF, 0x00 }, { 0xFF, 0x00 } } }; - /* DQS CPU<>DRAM map for Samus board */ - const u8 dqs_map[2][8] = { - { 2, 0, 1, 3, 6, 4, 7, 5 }, - { 2, 1, 0, 3, 6, 5, 4, 7 } }; - - pei_data->ec_present = 1; - - /* One installed DIMM per channel */ - pei_data->dimm_channel0_disabled = 2; - pei_data->dimm_channel1_disabled = 2; - - memcpy(pei_data->dq_map, dq_map, sizeof(dq_map)); - memcpy(pei_data->dqs_map, dqs_map, sizeof(dqs_map)); - - /* P0: HOST PORT */ - pei_data_usb2_port(pei_data, 0, 0x0080, 1, 0, - USB_PORT_BACK_PANEL); - /* P1: HOST PORT */ - pei_data_usb2_port(pei_data, 1, 0x0080, 1, 1, - USB_PORT_BACK_PANEL); - /* P2: RAIDEN */ - pei_data_usb2_port(pei_data, 2, 0x0080, 1, USB_OC_PIN_SKIP, - USB_PORT_BACK_PANEL); - /* P3: SD CARD */ - pei_data_usb2_port(pei_data, 3, 0x0040, 1, USB_OC_PIN_SKIP, - USB_PORT_INTERNAL); - /* P4: RAIDEN */ - pei_data_usb2_port(pei_data, 4, 0x0080, 1, USB_OC_PIN_SKIP, - USB_PORT_BACK_PANEL); - /* P5: WWAN (Disabled) */ - pei_data_usb2_port(pei_data, 5, 0x0000, 0, USB_OC_PIN_SKIP, - USB_PORT_SKIP); - /* P6: CAMERA */ - pei_data_usb2_port(pei_data, 6, 0x0040, 1, USB_OC_PIN_SKIP, - USB_PORT_INTERNAL); - /* P7: BT */ - pei_data_usb2_port(pei_data, 7, 0x0040, 1, USB_OC_PIN_SKIP, - USB_PORT_INTERNAL); - - /* P1: HOST PORT */ - pei_data_usb3_port(pei_data, 0, 1, 0, 0); - /* P2: HOST PORT */ - pei_data_usb3_port(pei_data, 1, 1, 1, 0); - /* P3: RAIDEN */ - pei_data_usb3_port(pei_data, 2, 1, USB_OC_PIN_SKIP, 0); - /* P4: RAIDEN */ - pei_data_usb3_port(pei_data, 3, 1, USB_OC_PIN_SKIP, 0); -} - static unsigned long get_top_of_ram(struct udevice *dev) { /*

Hi Simon,
On Wed, Jan 30, 2019 at 12:00 PM Simon Glass sjg@chromium.org wrote:
At present SDRAM is always set up in U-Boot proper. Allow this to be done
I don't understand. I thought SDRAM was already set up in the U-Boot SPL in the 64-bit build. The U-Boot proper needs a MMU table which resides in RAM, so without RAM being initialized first there is no way for U-Boot proper to run. Am I missing anything?
in SPL instead so that U-Boot proper can be loaded into SDRAM and run from there. This allows U-Boot to be compressed to reduce space, since it is not necessary to run it directly from flash.
Signed-off-by: Simon Glass sjg@chromium.org
arch/x86/cpu/broadwell/Makefile | 2 +- arch/x86/cpu/broadwell/northbridge.c | 93 ++++++++++++++++++++++++++++ arch/x86/cpu/broadwell/sdram.c | 93 ---------------------------- 3 files changed, 94 insertions(+), 94 deletions(-)
Regards, Bin

Hi Bin,
On Fri, 22 Feb 2019 at 00:19, Bin Meng bmeng.cn@gmail.com wrote:
Hi Simon,
On Wed, Jan 30, 2019 at 12:00 PM Simon Glass sjg@chromium.org wrote:
At present SDRAM is always set up in U-Boot proper. Allow this to be done
I don't understand. I thought SDRAM was already set up in the U-Boot SPL in the 64-bit build. The U-Boot proper needs a MMU table which resides in RAM, so without RAM being initialized first there is no way for U-Boot proper to run. Am I missing anything?
I'll update this to make it clear it is just for broadwell, which doesn't support 64-bit.
Regards, Simon
in SPL instead so that U-Boot proper can be loaded into SDRAM and run from there. This allows U-Boot to be compressed to reduce space, since it is not necessary to run it directly from flash.
Signed-off-by: Simon Glass sjg@chromium.org
arch/x86/cpu/broadwell/Makefile | 2 +- arch/x86/cpu/broadwell/northbridge.c | 93 ++++++++++++++++++++++++++++ arch/x86/cpu/broadwell/sdram.c | 93 ---------------------------- 3 files changed, 94 insertions(+), 94 deletions(-)
Regards, Bin

At present the debug UART is set up in sdram.c which is not the best place since it has nothing in particular to do with SDRAM. Since we want to support initing this in SPL too, move it to a common file.
Signed-off-by: Simon Glass sjg@chromium.org ---
arch/x86/cpu/broadwell/cpu.c | 13 +++++++++++++ arch/x86/cpu/broadwell/sdram.c | 11 ----------- 2 files changed, 13 insertions(+), 11 deletions(-)
diff --git a/arch/x86/cpu/broadwell/cpu.c b/arch/x86/cpu/broadwell/cpu.c index 232fa40eb5..d53c7b863f 100644 --- a/arch/x86/cpu/broadwell/cpu.c +++ b/arch/x86/cpu/broadwell/cpu.c @@ -12,7 +12,9 @@ #include <asm/cpu_x86.h> #include <asm/cpu_common.h> #include <asm/intel_regs.h> +#include <asm/lpc_common.h> #include <asm/msr.h> +#include <asm/pci.h> #include <asm/post.h> #include <asm/turbo.h> #include <asm/arch/cpu.h> @@ -156,6 +158,17 @@ int print_cpuinfo(void) return 0; }
+void board_debug_uart_init(void) +{ + struct udevice *bus = NULL; + + /* com1 / com2 decode range */ + pci_x86_write_config(bus, PCH_DEV_LPC, LPC_IO_DEC, 1 << 4, PCI_SIZE_16); + + pci_x86_write_config(bus, PCH_DEV_LPC, LPC_EN, COMA_LPC_EN, + PCI_SIZE_16); +} + /* * 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 diff --git a/arch/x86/cpu/broadwell/sdram.c b/arch/x86/cpu/broadwell/sdram.c index b8450cc9d2..b31d78c092 100644 --- a/arch/x86/cpu/broadwell/sdram.c +++ b/arch/x86/cpu/broadwell/sdram.c @@ -194,17 +194,6 @@ int misc_init_r(void) return 0; }
-void board_debug_uart_init(void) -{ - struct udevice *bus = NULL; - - /* com1 / com2 decode range */ - pci_x86_write_config(bus, PCH_DEV_LPC, LPC_IO_DEC, 1 << 4, PCI_SIZE_16); - - pci_x86_write_config(bus, PCH_DEV_LPC, LPC_EN, COMA_LPC_EN, - PCI_SIZE_16); -} - static const struct udevice_id broadwell_syscon_ids[] = { { .compatible = "intel,me", .data = X86_SYSCON_ME }, { }

On Wed, Jan 30, 2019 at 12:00 PM Simon Glass sjg@chromium.org wrote:
At present the debug UART is set up in sdram.c which is not the best place since it has nothing in particular to do with SDRAM. Since we want to support initing this in SPL too, move it to a common file.
Signed-off-by: Simon Glass sjg@chromium.org
arch/x86/cpu/broadwell/cpu.c | 13 +++++++++++++ arch/x86/cpu/broadwell/sdram.c | 11 ----------- 2 files changed, 13 insertions(+), 11 deletions(-)
Reviewed-by: Bin Meng bmeng.cn@gmail.com

Split the CPU init into two parts - the 'full' init which happens in the first U-Boot phase, and the rest of the init that happens on subsequent stages.
Signed-off-by: Simon Glass sjg@chromium.org ---
arch/x86/cpu/broadwell/Makefile | 1 + arch/x86/cpu/broadwell/cpu.c | 673 ----------------------------- arch/x86/cpu/broadwell/cpu_full.c | 694 ++++++++++++++++++++++++++++++ 3 files changed, 695 insertions(+), 673 deletions(-) create mode 100644 arch/x86/cpu/broadwell/cpu_full.c
diff --git a/arch/x86/cpu/broadwell/Makefile b/arch/x86/cpu/broadwell/Makefile index 55f2c93719..303d2b274b 100644 --- a/arch/x86/cpu/broadwell/Makefile +++ b/arch/x86/cpu/broadwell/Makefile @@ -3,6 +3,7 @@ # Copyright (c) 2016 Google, Inc
obj-y += cpu.o +obj-y += cpu_full.o obj-y += iobp.o obj-y += lpc.o obj-y += me.o diff --git a/arch/x86/cpu/broadwell/cpu.c b/arch/x86/cpu/broadwell/cpu.c index d53c7b863f..bb7c361408 100644 --- a/arch/x86/cpu/broadwell/cpu.c +++ b/arch/x86/cpu/broadwell/cpu.c @@ -21,68 +21,6 @@ #include <asm/arch/pch.h> #include <asm/arch/rcb.h>
-struct cpu_broadwell_priv { - bool ht_disabled; -}; - -/* Convert time in seconds to POWER_LIMIT_1_TIME MSR value */ -static const u8 power_limit_time_sec_to_msr[] = { - [0] = 0x00, - [1] = 0x0a, - [2] = 0x0b, - [3] = 0x4b, - [4] = 0x0c, - [5] = 0x2c, - [6] = 0x4c, - [7] = 0x6c, - [8] = 0x0d, - [10] = 0x2d, - [12] = 0x4d, - [14] = 0x6d, - [16] = 0x0e, - [20] = 0x2e, - [24] = 0x4e, - [28] = 0x6e, - [32] = 0x0f, - [40] = 0x2f, - [48] = 0x4f, - [56] = 0x6f, - [64] = 0x10, - [80] = 0x30, - [96] = 0x50, - [112] = 0x70, - [128] = 0x11, -}; - -/* Convert POWER_LIMIT_1_TIME MSR value to seconds */ -static const u8 power_limit_time_msr_to_sec[] = { - [0x00] = 0, - [0x0a] = 1, - [0x0b] = 2, - [0x4b] = 3, - [0x0c] = 4, - [0x2c] = 5, - [0x4c] = 6, - [0x6c] = 7, - [0x0d] = 8, - [0x2d] = 10, - [0x4d] = 12, - [0x6d] = 14, - [0x0e] = 16, - [0x2e] = 20, - [0x4e] = 24, - [0x6e] = 28, - [0x0f] = 32, - [0x2f] = 40, - [0x4f] = 48, - [0x6f] = 56, - [0x10] = 64, - [0x30] = 80, - [0x50] = 96, - [0x70] = 112, - [0x11] = 128, -}; - int arch_cpu_init_dm(void) { struct udevice *dev; @@ -168,614 +106,3 @@ void board_debug_uart_init(void) pci_x86_write_config(bus, PCH_DEV_LPC, LPC_EN, COMA_LPC_EN, PCI_SIZE_16); } - -/* - * 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; -} - -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, -}; diff --git a/arch/x86/cpu/broadwell/cpu_full.c b/arch/x86/cpu/broadwell/cpu_full.c new file mode 100644 index 0000000000..c1db184549 --- /dev/null +++ b/arch/x86/cpu/broadwell/cpu_full.c @@ -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, +};

On Wed, Jan 30, 2019 at 12:00 PM Simon Glass sjg@chromium.org wrote:
Split the CPU init into two parts - the 'full' init which happens in the first U-Boot phase, and the rest of the init that happens on subsequent stages.
Signed-off-by: Simon Glass sjg@chromium.org
arch/x86/cpu/broadwell/Makefile | 1 + arch/x86/cpu/broadwell/cpu.c | 673 ----------------------------- arch/x86/cpu/broadwell/cpu_full.c | 694 ++++++++++++++++++++++++++++++ 3 files changed, 695 insertions(+), 673 deletions(-) create mode 100644 arch/x86/cpu/broadwell/cpu_full.c
Reviewed-by: Bin Meng bmeng.cn@gmail.com

When a previous phase of U-Boot has run we need to adjust the init of subsequent states to avoid messing up the CPU state.
Add a new version of the start logic for SPL, when it boots from TPL (start_from tpl.c) and a new version for U-Boot when it boots from SPL.
Signed-off-by: Simon Glass sjg@chromium.org ---
arch/x86/Makefile | 12 ++++++ arch/x86/cpu/Makefile | 15 +++++++- arch/x86/cpu/start_from_spl.S | 71 +++++++++++++++++++++++++++++++++++ arch/x86/cpu/start_from_tpl.S | 50 ++++++++++++++++++++++++ 4 files changed, 147 insertions(+), 1 deletion(-) create mode 100644 arch/x86/cpu/start_from_spl.S create mode 100644 arch/x86/cpu/start_from_tpl.S
diff --git a/arch/x86/Makefile b/arch/x86/Makefile index fec14847cc..9fd6cf2d3b 100644 --- a/arch/x86/Makefile +++ b/arch/x86/Makefile @@ -4,9 +4,21 @@ ifeq ($(CONFIG_EFI_APP),) ifdef CONFIG_$(SPL_)X86_64 head-y := arch/x86/cpu/start64.o else +ifeq ($(CONFIG_$(SPL_TPL_)X86_16BIT_INIT),y) head-y := arch/x86/cpu/start.o +else +ifndef CONFIG_SPL +head-y := arch/x86/cpu/start.o +else +ifdef CONFIG_SPL_BUILD +head-y = arch/x86/cpu/start_from_tpl.o +else +head-y = arch/x86/cpu/start_from_spl.o +endif +endif endif endif +endif # EFI
head-$(CONFIG_$(SPL_)X86_16BIT_INIT) += arch/x86/cpu/start16.o head-$(CONFIG_$(SPL_)X86_16BIT_INIT) += arch/x86/cpu/resetvec.o diff --git a/arch/x86/cpu/Makefile b/arch/x86/cpu/Makefile index 54668aab24..85fd5e616e 100644 --- a/arch/x86/cpu/Makefile +++ b/arch/x86/cpu/Makefile @@ -9,9 +9,22 @@ ifeq ($(CONFIG_$(SPL_)X86_64),y) extra-y = start64.o else +ifeq ($(CONFIG_$(SPL_TPL_)X86_16BIT_INIT),y) extra-y = start.o +else +ifndef CONFIG_SPL +extra-y = start.o +else +ifdef CONFIG_SPL_BUILD +extra-y = start_from_tpl.o +else +extra-y = start_from_spl.o endif -extra-$(CONFIG_$(SPL_)X86_16BIT_INIT) += resetvec.o start16.o +endif +endif +endif + +extra-$(CONFIG_$(SPL_TPL_)X86_16BIT_INIT) += resetvec.o start16.o
obj-y += cpu.o cpu_x86.o
diff --git a/arch/x86/cpu/start_from_spl.S b/arch/x86/cpu/start_from_spl.S new file mode 100644 index 0000000000..4d4e5d0758 --- /dev/null +++ b/arch/x86/cpu/start_from_spl.S @@ -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 */ diff --git a/arch/x86/cpu/start_from_tpl.S b/arch/x86/cpu/start_from_tpl.S new file mode 100644 index 0000000000..e27f39eddf --- /dev/null +++ b/arch/x86/cpu/start_from_tpl.S @@ -0,0 +1,50 @@ +/* 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 */ + mov %esp, %eax + call board_init_f_alloc_reserve + mov %eax, %esp + + call board_init_f_init_reserve + + 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

Hi Simon,
On Wed, Jan 30, 2019 at 12:00 PM Simon Glass sjg@chromium.org wrote:
When a previous phase of U-Boot has run we need to adjust the init of subsequent states to avoid messing up the CPU state.
Add a new version of the start logic for SPL, when it boots from TPL (start_from tpl.c) and a new version for U-Boot when it boots from SPL.
Signed-off-by: Simon Glass sjg@chromium.org
arch/x86/Makefile | 12 ++++++ arch/x86/cpu/Makefile | 15 +++++++- arch/x86/cpu/start_from_spl.S | 71 +++++++++++++++++++++++++++++++++++ arch/x86/cpu/start_from_tpl.S | 50 ++++++++++++++++++++++++ 4 files changed, 147 insertions(+), 1 deletion(-) create mode 100644 arch/x86/cpu/start_from_spl.S create mode 100644 arch/x86/cpu/start_from_tpl.S
diff --git a/arch/x86/Makefile b/arch/x86/Makefile index fec14847cc..9fd6cf2d3b 100644 --- a/arch/x86/Makefile +++ b/arch/x86/Makefile @@ -4,9 +4,21 @@ ifeq ($(CONFIG_EFI_APP),) ifdef CONFIG_$(SPL_)X86_64 head-y := arch/x86/cpu/start64.o else +ifeq ($(CONFIG_$(SPL_TPL_)X86_16BIT_INIT),y) head-y := arch/x86/cpu/start.o +else +ifndef CONFIG_SPL +head-y := arch/x86/cpu/start.o +else +ifdef CONFIG_SPL_BUILD +head-y = arch/x86/cpu/start_from_tpl.o +else +head-y = arch/x86/cpu/start_from_spl.o +endif +endif endif endif +endif # EFI
head-$(CONFIG_$(SPL_)X86_16BIT_INIT) += arch/x86/cpu/start16.o head-$(CONFIG_$(SPL_)X86_16BIT_INIT) += arch/x86/cpu/resetvec.o diff --git a/arch/x86/cpu/Makefile b/arch/x86/cpu/Makefile index 54668aab24..85fd5e616e 100644 --- a/arch/x86/cpu/Makefile +++ b/arch/x86/cpu/Makefile @@ -9,9 +9,22 @@ ifeq ($(CONFIG_$(SPL_)X86_64),y) extra-y = start64.o else +ifeq ($(CONFIG_$(SPL_TPL_)X86_16BIT_INIT),y) extra-y = start.o +else +ifndef CONFIG_SPL +extra-y = start.o +else +ifdef CONFIG_SPL_BUILD +extra-y = start_from_tpl.o +else +extra-y = start_from_spl.o endif -extra-$(CONFIG_$(SPL_)X86_16BIT_INIT) += resetvec.o start16.o +endif +endif +endif
+extra-$(CONFIG_$(SPL_TPL_)X86_16BIT_INIT) += resetvec.o start16.o
obj-y += cpu.o cpu_x86.o
diff --git a/arch/x86/cpu/start_from_spl.S b/arch/x86/cpu/start_from_spl.S
Is it possible to consolidate start_from_spl.S and start_from_tpl.S into one file, to save some duplicates?
new file mode 100644 index 0000000000..4d4e5d0758 --- /dev/null +++ b/arch/x86/cpu/start_from_spl.S @@ -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 */
diff --git a/arch/x86/cpu/start_from_tpl.S b/arch/x86/cpu/start_from_tpl.S new file mode 100644 index 0000000000..e27f39eddf --- /dev/null +++ b/arch/x86/cpu/start_from_tpl.S @@ -0,0 +1,50 @@ +/* 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 */
mov %esp, %eax
call board_init_f_alloc_reserve
mov %eax, %esp
call board_init_f_init_reserve
missing "xorl %eax, %eax" here
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
TPL?
* 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
--
Regards, Bin

At present we support having 16-bit init be in SPL or U-Boot proper, but not TPL. Add support for this so that TPL can boot.
Signed-off-by: Simon Glass sjg@chromium.org ---
Makefile | 1 + arch/x86/Makefile | 4 ++-- arch/x86/cpu/intel_common/Makefile | 2 +- arch/x86/cpu/u-boot-spl.lds | 2 +- scripts/Makefile.spl | 10 +++++++++- 5 files changed, 14 insertions(+), 5 deletions(-)
diff --git a/Makefile b/Makefile index c73b116480..86b21a1a78 100644 --- a/Makefile +++ b/Makefile @@ -1399,6 +1399,7 @@ cmd_ldr = $(LD) $(LDFLAGS_$(@F)) \
u-boot.rom: u-boot-x86-16bit.bin u-boot.bin \ $(if $(CONFIG_SPL_X86_16BIT_INIT),spl/u-boot-spl.bin) \ + $(if $(CONFIG_TPL_X86_16BIT_INIT),tpl/u-boot-tpl.bin) \ $(if $(CONFIG_HAVE_REFCODE),refcode.bin) FORCE $(call if_changed,binman)
diff --git a/arch/x86/Makefile b/arch/x86/Makefile index 9fd6cf2d3b..f1afc74fff 100644 --- a/arch/x86/Makefile +++ b/arch/x86/Makefile @@ -20,8 +20,8 @@ endif endif endif # EFI
-head-$(CONFIG_$(SPL_)X86_16BIT_INIT) += arch/x86/cpu/start16.o -head-$(CONFIG_$(SPL_)X86_16BIT_INIT) += arch/x86/cpu/resetvec.o +head-$(CONFIG_$(SPL_TPL_)X86_16BIT_INIT) += arch/x86/cpu/start16.o +head-$(CONFIG_$(SPL_TPL_)X86_16BIT_INIT) += arch/x86/cpu/resetvec.o
libs-y += arch/x86/cpu/ libs-y += arch/x86/lib/ diff --git a/arch/x86/cpu/intel_common/Makefile b/arch/x86/cpu/intel_common/Makefile index bf798c287f..80fbc7ab66 100644 --- a/arch/x86/cpu/intel_common/Makefile +++ b/arch/x86/cpu/intel_common/Makefile @@ -3,7 +3,7 @@ # Copyright (c) 2016 Google, Inc
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_)X86_32BIT_INIT) += report_platform.o obj-$(CONFIG_$(SPL_)X86_32BIT_INIT) += mrc.o diff --git a/arch/x86/cpu/u-boot-spl.lds b/arch/x86/cpu/u-boot-spl.lds index 4e656dc4e5..f20c0b810d 100644 --- a/arch/x86/cpu/u-boot-spl.lds +++ b/arch/x86/cpu/u-boot-spl.lds @@ -54,7 +54,7 @@ SECTIONS /DISCARD/ : { *(.interp*) } /DISCARD/ : { *(.gnu*) }
-#ifdef CONFIG_SPL_X86_16BIT_INIT +#if defined(CONFIG_SPL_X86_16BIT_INIT) || defined(CONFIG_TPL_X86_16BIT_INIT) /* * The following expressions place the 16-bit Real-Mode code and * Reset Vector at the end of the Flash ROM diff --git a/scripts/Makefile.spl b/scripts/Makefile.spl index c9eea629dd..107f1e257a 100644 --- a/scripts/Makefile.spl +++ b/scripts/Makefile.spl @@ -230,7 +230,11 @@ ifeq ($(CONFIG_SYS_SOC),"at91") ALL-y += boot.bin endif
+ifdef CONFIG_TPL_BUILD +ALL-$(CONFIG_TPL_X86_16BIT_INIT) += $(obj)/u-boot-x86-16bit-tpl.bin +else ALL-$(CONFIG_SPL_X86_16BIT_INIT) += $(obj)/u-boot-x86-16bit-spl.bin +endif
ALL-$(CONFIG_ARCH_ZYNQ) += $(obj)/boot.bin ALL-$(CONFIG_ARCH_ZYNQMP) += $(obj)/boot.bin @@ -330,7 +334,7 @@ quiet_cmd_objcopy = OBJCOPY $@ cmd_objcopy = $(OBJCOPY) $(OBJCOPYFLAGS) $(OBJCOPYFLAGS_$(@F)) $< $@
OBJCOPYFLAGS_$(SPL_BIN)-nodtb.bin = $(SPL_OBJCFLAGS) -O binary \ - $(if $(CONFIG_SPL_X86_16BIT_INIT),-R .start16 -R .resetvec) + $(if $(CONFIG_$(SPL_TPL_)X86_16BIT_INIT),-R .start16 -R .resetvec)
$(obj)/$(SPL_BIN)-nodtb.bin: $(obj)/$(SPL_BIN) FORCE $(call if_changed,objcopy) @@ -339,6 +343,10 @@ OBJCOPYFLAGS_u-boot-x86-16bit-spl.bin := -O binary -j .start16 -j .resetvec $(obj)/u-boot-x86-16bit-spl.bin: $(obj)/u-boot-spl FORCE $(call if_changed,objcopy)
+OBJCOPYFLAGS_u-boot-x86-16bit-tpl.bin := -O binary -j .start16 -j .resetvec +$(obj)/u-boot-x86-16bit-tpl.bin: $(obj)/u-boot-tpl FORCE + $(call if_changed,objcopy) + LDFLAGS_$(SPL_BIN) += -T u-boot-spl.lds $(LDFLAGS_FINAL)
# Avoid 'Not enough room for program headers' error on binutils 2.28 onwards.

On Wed, Jan 30, 2019 at 12:00 PM Simon Glass sjg@chromium.org wrote:
At present we support having 16-bit init be in SPL or U-Boot proper, but not TPL. Add support for this so that TPL can boot.
Signed-off-by: Simon Glass sjg@chromium.org
Makefile | 1 + arch/x86/Makefile | 4 ++-- arch/x86/cpu/intel_common/Makefile | 2 +- arch/x86/cpu/u-boot-spl.lds | 2 +- scripts/Makefile.spl | 10 +++++++++- 5 files changed, 14 insertions(+), 5 deletions(-)
Reviewed-by: Bin Meng bmeng.cn@gmail.com

At present broadwell only supports booting straight into U-Boot proper. Add a separate init file to boot from SPL into U-Boot proper, and select it when SPL is in use.
Signed-off-by: Simon Glass sjg@chromium.org ---
arch/x86/cpu/broadwell/Makefile | 15 +++++++ arch/x86/cpu/broadwell/cpu_from_spl.c | 63 +++++++++++++++++++++++++++ 2 files changed, 78 insertions(+) create mode 100644 arch/x86/cpu/broadwell/cpu_from_spl.c
diff --git a/arch/x86/cpu/broadwell/Makefile b/arch/x86/cpu/broadwell/Makefile index 303d2b274b..11d30b03e5 100644 --- a/arch/x86/cpu/broadwell/Makefile +++ b/arch/x86/cpu/broadwell/Makefile @@ -4,6 +4,21 @@
obj-y += cpu.o obj-y += cpu_full.o + +ifdef CONFIG_SPL +ifndef CONFIG_SPL_BUILD +obj-y += cpu_from_spl.o +obj-y += cpu_full.o +endif +ifndef CONFIG_SPL_BUILD +# obj-y += cpu_from_spl.o +endif +endif + +ifeq ($(CONFIG_$(SPL_TPL_)X86_32BIT_INIT),) +#obj-y += cpu_from_spl.o +endif + obj-y += iobp.o obj-y += lpc.o obj-y += me.o diff --git a/arch/x86/cpu/broadwell/cpu_from_spl.c b/arch/x86/cpu/broadwell/cpu_from_spl.c new file mode 100644 index 0000000000..c3d4a8d547 --- /dev/null +++ b/arch/x86/cpu/broadwell/cpu_from_spl.c @@ -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; +}

On Wed, Jan 30, 2019 at 12:00 PM Simon Glass sjg@chromium.org wrote:
At present broadwell only supports booting straight into U-Boot proper. Add a separate init file to boot from SPL into U-Boot proper, and select it when SPL is in use.
Signed-off-by: Simon Glass sjg@chromium.org
arch/x86/cpu/broadwell/Makefile | 15 +++++++ arch/x86/cpu/broadwell/cpu_from_spl.c | 63 +++++++++++++++++++++++++++ 2 files changed, 78 insertions(+) create mode 100644 arch/x86/cpu/broadwell/cpu_from_spl.c
Reviewed-by: Bin Meng bmeng.cn@gmail.com

Allow broadwell to build for SPL and include the reference code.
Signed-off-by: Simon Glass sjg@chromium.org ---
arch/x86/cpu/broadwell/Makefile | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-)
diff --git a/arch/x86/cpu/broadwell/Makefile b/arch/x86/cpu/broadwell/Makefile index 11d30b03e5..394a794f91 100644 --- a/arch/x86/cpu/broadwell/Makefile +++ b/arch/x86/cpu/broadwell/Makefile @@ -2,13 +2,14 @@ # # Copyright (c) 2016 Google, Inc
-obj-y += cpu.o -obj-y += cpu_full.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 @@ -26,6 +27,6 @@ obj-y += northbridge.o obj-y += pch.o obj-y += pinctrl_broadwell.o obj-y += power_state.o -obj-y += refcode.o +obj-$(CONFIG_$(SPL_TPL_)X86_32BIT_INIT) += refcode.o obj-y += sata.o obj-$(CONFIG_$(SPL_TPL_)X86_32BIT_INIT) += sdram.o

On Wed, Jan 30, 2019 at 12:00 PM Simon Glass sjg@chromium.org wrote:
Allow broadwell to build for SPL and include the reference code.
Signed-off-by: Simon Glass sjg@chromium.org
arch/x86/cpu/broadwell/Makefile | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-)
Reviewed-by: Bin Meng bmeng.cn@gmail.com

Add an implementation of arch_cpu_init_f() so that the x86 SPL code builds and identifies the CPU.
Signed-off-by: Simon Glass sjg@chromium.org ---
arch/x86/cpu/intel_common/Makefile | 6 ++++++ arch/x86/cpu/intel_common/cpu_from_spl.c | 27 ++++++++++++++++++++++++ 2 files changed, 33 insertions(+) create mode 100644 arch/x86/cpu/intel_common/cpu_from_spl.c
diff --git a/arch/x86/cpu/intel_common/Makefile b/arch/x86/cpu/intel_common/Makefile index 80fbc7ab66..57cca0b930 100644 --- a/arch/x86/cpu/intel_common/Makefile +++ b/arch/x86/cpu/intel_common/Makefile @@ -14,3 +14,9 @@ ifndef CONFIG_TARGET_EFI_APP obj-y += microcode.o endif obj-y += pch.o + +ifdef CONFIG_SPL +ifndef CONFIG_SPL_BUILD +obj-y += cpu_from_spl.o +endif +endif diff --git a/arch/x86/cpu/intel_common/cpu_from_spl.c b/arch/x86/cpu/intel_common/cpu_from_spl.c new file mode 100644 index 0000000000..a6233c75ce --- /dev/null +++ b/arch/x86/cpu/intel_common/cpu_from_spl.c @@ -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; +}

On Wed, Jan 30, 2019 at 12:00 PM Simon Glass sjg@chromium.org wrote:
Add an implementation of arch_cpu_init_f() so that the x86 SPL code builds and identifies the CPU.
Signed-off-by: Simon Glass sjg@chromium.org
arch/x86/cpu/intel_common/Makefile | 6 ++++++ arch/x86/cpu/intel_common/cpu_from_spl.c | 27 ++++++++++++++++++++++++ 2 files changed, 33 insertions(+) create mode 100644 arch/x86/cpu/intel_common/cpu_from_spl.c
Reviewed-by: Bin Meng bmeng.cn@gmail.com

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. Add a function to handle that.
Signed-off-by: Simon Glass sjg@chromium.org ---
arch/x86/include/asm/mrccache.h | 11 ++++++++++ arch/x86/lib/mrccache.c | 36 ++++++++++++++++++++++++--------- 2 files changed, 38 insertions(+), 9 deletions(-)
diff --git a/arch/x86/include/asm/mrccache.h b/arch/x86/include/asm/mrccache.h index 04783cd329..40fda856ff 100644 --- a/arch/x86/include/asm/mrccache.h +++ b/arch/x86/include/asm/mrccache.h @@ -103,4 +103,15 @@ int mrccache_get_region(struct udevice **devp, struct mrc_region *entry); */ int mrccache_save(void);
+/** + * mrccache_spl_save() - Save to the MRC region from SPL + * + * When SPL is used to set up the memory controller we want to save the MRC + * data in SPL to avoid needing to pass it up to U-Boot proper to save. This + * function handles that. + * + * @return 0 if saved to SPI flash successfully, other error if failed + */ +int mrccache_spl_save(void); + #endif /* _ASM_MRCCACHE_H */ diff --git a/arch/x86/lib/mrccache.c b/arch/x86/lib/mrccache.c index 2a8919885b..f37a732a45 100644 --- a/arch/x86/lib/mrccache.c +++ b/arch/x86/lib/mrccache.c @@ -159,18 +159,11 @@ int mrccache_update(struct udevice *sf, struct mrc_region *entry, return 0; }
-int mrccache_reserve(void) +static void mrccache_setup(void *data) { - struct mrc_data_container *cache; + struct mrc_data_container *cache = data; u16 checksum;
- if (!gd->arch.mrc_output_len) - return 0; - - /* adjust stack pointer to store pure cache data plus the header */ - gd->start_addr_sp -= (gd->arch.mrc_output_len + MRC_DATA_HEADER_SIZE); - cache = (struct mrc_data_container *)gd->start_addr_sp; - cache->signature = MRC_DATA_SIGNATURE; cache->data_size = gd->arch.mrc_output_len; checksum = compute_ip_checksum(gd->arch.mrc_output, cache->data_size); @@ -182,6 +175,16 @@ int mrccache_reserve(void)
/* gd->arch.mrc_output now points to the container */ gd->arch.mrc_output = (char *)cache; +} + +int mrccache_reserve(void) +{ + if (!gd->arch.mrc_output_len) + return 0; + + /* adjust stack pointer to store pure cache data plus the header */ + gd->start_addr_sp -= (gd->arch.mrc_output_len + MRC_DATA_HEADER_SIZE); + mrccache_setup((void *)gd->start_addr_sp);
gd->start_addr_sp &= ~0xf;
@@ -256,3 +259,18 @@ err_entry: debug("%s: Failed: %d\n", __func__, ret); return ret; } + +int mrccache_spl_save(void) +{ + void *data; + int size; + + size = gd->arch.mrc_output_len + MRC_DATA_HEADER_SIZE; + data = malloc(size); + if (!data) + return log_msg_ret("Allocate MRC cache block", -ENOMEM); + mrccache_setup(data); + gd->arch.mrc_output = data; + + return mrccache_save(); +}

On Wed, Jan 30, 2019 at 12:00 PM Simon Glass sjg@chromium.org wrote:
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. Add a function to handle that.
Signed-off-by: Simon Glass sjg@chromium.org
arch/x86/include/asm/mrccache.h | 11 ++++++++++ arch/x86/lib/mrccache.c | 36 ++++++++++++++++++++++++--------- 2 files changed, 38 insertions(+), 9 deletions(-)
Reviewed-by: Bin Meng bmeng.cn@gmail.com

Add the required CPU code so that TPL builds correctly. Also update the SPL code to deal with being booted from TPL.
Signed-off-by: Simon Glass sjg@chromium.org ---
arch/x86/include/asm/spl.h | 17 ++++- arch/x86/lib/Makefile | 9 ++- arch/x86/lib/spl.c | 44 ++++++++++- arch/x86/lib/tpl.c | 118 ++++++++++++++++++++++++++++++ include/configs/chromebook_link.h | 3 - include/configs/qemu-x86.h | 3 - 6 files changed, 183 insertions(+), 11 deletions(-) create mode 100644 arch/x86/lib/tpl.c
diff --git a/arch/x86/include/asm/spl.h b/arch/x86/include/asm/spl.h index 8cf59d14e7..27432b2897 100644 --- a/arch/x86/include/asm/spl.h +++ b/arch/x86/include/asm/spl.h @@ -2,6 +2,19 @@ /* * Copyright (C) 2017 Google, Inc * Written by Simon Glass sjg@chromium.org - * - * This file is required for SPL to build, but is empty. */ + +#ifndef __asm_spl_h +#define __asm_spl_h + +#define CONFIG_SPL_BOARD_LOAD_IMAGE + +enum { + BOOT_DEVICE_SPI = 10, + BOOT_DEVICE_BOARD, + BOOT_DEVICE_CROS_VBOOT, +}; + +void jump_to_spl(ulong entry); + +#endif diff --git a/arch/x86/lib/Makefile b/arch/x86/lib/Makefile index 1e8efcc44f..a72378c0aa 100644 --- a/arch/x86/lib/Makefile +++ b/arch/x86/lib/Makefile @@ -43,7 +43,14 @@ ifndef CONFIG_SPL_BUILD obj-$(CONFIG_CMD_ZBOOT) += zimage.o endif obj-$(CONFIG_HAVE_FSP) += fsp/ -obj-$(CONFIG_SPL_BUILD) += spl.o + +ifdef CONFIG_SPL_BUILD +ifdef CONFIG_TPL_BUILD +obj-y += tpl.o +else +obj-y += spl.o +endif +endif
lib-$(CONFIG_USE_PRIVATE_LIBGCC) += div64.o
diff --git a/arch/x86/lib/spl.c b/arch/x86/lib/spl.c index 7d290740bf..5d5d1a9ca7 100644 --- a/arch/x86/lib/spl.c +++ b/arch/x86/lib/spl.c @@ -5,8 +5,10 @@
#include <common.h> #include <debug_uart.h> +#include <malloc.h> #include <spl.h> #include <asm/cpu.h> +#include <asm/mrccache.h> #include <asm/mtrr.h> #include <asm/processor.h> #include <asm-generic/sections.h> @@ -20,6 +22,7 @@ __weak int arch_cpu_init_dm(void)
static int x86_spl_init(void) { +#ifndef CONFIG_TPL /* * TODO(sjg@chromium.org): We use this area of RAM for the stack * and global_data in SPL. Once U-Boot starts up and releocates it @@ -27,6 +30,7 @@ static int x86_spl_init(void) * place it immediately below CONFIG_SYS_TEXT_BASE. */ char *ptr = (char *)0x110000; +#endif int ret;
debug("%s starting\n", __func__); @@ -35,27 +39,44 @@ static int x86_spl_init(void) debug("%s: spl_init() failed\n", __func__); return ret; } +#ifdef CONFIG_TPL + /* Do a mini-init if TPL has already done the full init */ + ret = x86_cpu_reinit_f(); +#else ret = arch_cpu_init(); +#endif if (ret) { debug("%s: arch_cpu_init() failed\n", __func__); return ret; } +#ifndef CONFIG_TPL ret = arch_cpu_init_dm(); if (ret) { debug("%s: arch_cpu_init_dm() failed\n", __func__); return ret; } +#endif preloader_console_init(); +#ifndef CONFIG_TPL ret = print_cpuinfo(); if (ret) { debug("%s: print_cpuinfo() failed\n", __func__); return ret; } +#endif ret = dram_init(); if (ret) { debug("%s: dram_init() failed\n", __func__); return ret; } + if (IS_ENABLED(CONFIG_ENABLE_MRC_CACHE)) { + ret = mrccache_spl_save(); + if (ret) + debug("%s: Failed to write to mrccache (err=%d)\n", + __func__, ret); + } + +#ifndef CONFIG_TPL memset(&__bss_start, 0, (ulong)&__bss_end - (ulong)&__bss_start);
/* TODO(sjg@chromium.org): Consider calling cpu_init_r() here */ @@ -80,9 +101,11 @@ static int x86_spl_init(void) (1ULL << 32) - CONFIG_XIP_ROM_SIZE, CONFIG_XIP_ROM_SIZE); if (ret) { - debug("%s: SPI cache setup failed\n", __func__); + debug("%s: SPI cache setup failed (err=%d)\n", __func__, ret); return ret; } + mtrr_commit(true); +#endif
return 0; } @@ -96,9 +119,17 @@ void board_init_f(ulong flags) debug("Error %d\n", ret); hang(); } - +#ifdef CONFIG_TPL + gd->bd = malloc(sizeof(*gd->bd)); + if (!gd->bd) { + printf("Out of memory for bd_info size %x\n", sizeof(*gd->bd)); + hang(); + } + board_init_r(gd, 0); +#else /* Uninit CAR and jump to board_init_f_r() */ board_init_f_r_trampoline(gd->start_addr_sp); +#endif }
void board_init_f_r(void) @@ -144,6 +175,7 @@ int spl_spi_load_image(void) return -EPERM; }
+#ifdef CONFIG_X86_RUN_64BIT void __noreturn jump_to_image_no_args(struct spl_image_info *spl_image) { int ret; @@ -154,3 +186,11 @@ void __noreturn jump_to_image_no_args(struct spl_image_info *spl_image) while (1) ; } +#endif + +void spl_board_init(void) +{ +#ifndef CONFIG_TPL + preloader_console_init(); +#endif +} diff --git a/arch/x86/lib/tpl.c b/arch/x86/lib/tpl.c new file mode 100644 index 0000000000..492a2d6521 --- /dev/null +++ b/arch/x86/lib/tpl.c @@ -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(); +} diff --git a/include/configs/chromebook_link.h b/include/configs/chromebook_link.h index ee546d8f89..f59ed8e28b 100644 --- a/include/configs/chromebook_link.h +++ b/include/configs/chromebook_link.h @@ -20,9 +20,6 @@
#define CONFIG_SPL_TEXT_BASE 0xfffd0000
-#define BOOT_DEVICE_SPI 10 - #define CONFIG_SPL_BOARD_LOAD_IMAGE -#define BOOT_DEVICE_BOARD 11
#endif /* __CONFIG_H */ diff --git a/include/configs/qemu-x86.h b/include/configs/qemu-x86.h index 4b9ddd6f25..59206fb24b 100644 --- a/include/configs/qemu-x86.h +++ b/include/configs/qemu-x86.h @@ -37,9 +37,6 @@
#define CONFIG_SPL_TEXT_BASE 0xfffd0000
-#define BOOT_DEVICE_SPI 10 - #define CONFIG_SPL_BOARD_LOAD_IMAGE -#define BOOT_DEVICE_BOARD 11
#endif /* __CONFIG_H */

On Wed, Jan 30, 2019 at 12:00 PM Simon Glass sjg@chromium.org wrote:
Add the required CPU code so that TPL builds correctly. Also update the SPL code to deal with being booted from TPL.
Signed-off-by: Simon Glass sjg@chromium.org
arch/x86/include/asm/spl.h | 17 ++++- arch/x86/lib/Makefile | 9 ++- arch/x86/lib/spl.c | 44 ++++++++++- arch/x86/lib/tpl.c | 118 ++++++++++++++++++++++++++++++ include/configs/chromebook_link.h | 3 - include/configs/qemu-x86.h | 3 - 6 files changed, 183 insertions(+), 11 deletions(-) create mode 100644 arch/x86/lib/tpl.c
Reviewed-by: Bin Meng bmeng.cn@gmail.com

When the MRC cache fails to save it is useful to have some debugging info to indicate what when wrong. Add some more debug() calls.
Signed-off-by: Simon Glass sjg@chromium.org ---
arch/x86/lib/mrccache.c | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-)
diff --git a/arch/x86/lib/mrccache.c b/arch/x86/lib/mrccache.c index f37a732a45..be107627b8 100644 --- a/arch/x86/lib/mrccache.c +++ b/arch/x86/lib/mrccache.c @@ -113,8 +113,10 @@ int mrccache_update(struct udevice *sf, struct mrc_region *entry, ulong base_addr; int ret;
- if (!is_mrc_cache(cur)) + if (!is_mrc_cache(cur)) { + debug("%s: Cache data not valid\n", __func__); return -EINVAL; + }
/* Find the last used block */ base_addr = entry->base + entry->offset; @@ -205,17 +207,23 @@ int mrccache_get_region(struct udevice **devp, struct mrc_region *entry) return -ENOENT; }
- if (fdtdec_get_int_array(blob, node, "memory-map", reg, 2)) + if (fdtdec_get_int_array(blob, node, "memory-map", reg, 2)) { + debug("%s: Cannot find memory map\n", __func__); return -EINVAL; + } entry->base = reg[0];
/* Find the place where we put the MRC cache */ mrc_node = fdt_subnode_offset(blob, node, "rw-mrc-cache"); - if (mrc_node < 0) + if (mrc_node < 0) { + debug("%s: Cannot find node\n", __func__); return -EPERM; + }
- if (fdtdec_get_int_array(blob, mrc_node, "reg", reg, 2)) + if (fdtdec_get_int_array(blob, mrc_node, "reg", reg, 2)) { + debug("%s: Cannot find address\n", __func__); return -EINVAL; + } entry->offset = reg[0]; entry->length = reg[1];

On Wed, Jan 30, 2019 at 12:00 PM Simon Glass sjg@chromium.org wrote:
When the MRC cache fails to save it is useful to have some debugging info to indicate what when wrong. Add some more debug() calls.
what went wrong.
Signed-off-by: Simon Glass sjg@chromium.org
arch/x86/lib/mrccache.c | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-)
Reviewed-by: Bin Meng bmeng.cn@gmail.com

Intel SoCs support a fairly stardard reset mechanism which can support powering off the device. Add support for this and enable it by default on broadwell, which already has the necessary pm.h header file.
This driver augments the standard x86 sysreset driver.
Signed-off-by: Simon Glass sjg@chromium.org ---
arch/x86/cpu/broadwell/Kconfig | 1 + drivers/sysreset/Kconfig | 9 ++ drivers/sysreset/Makefile | 1 + drivers/sysreset/sysreset_intel_pch.c | 125 ++++++++++++++++++++++++++ 4 files changed, 136 insertions(+) create mode 100644 drivers/sysreset/sysreset_intel_pch.c
diff --git a/arch/x86/cpu/broadwell/Kconfig b/arch/x86/cpu/broadwell/Kconfig index 5b015c89d9..2955ffc55b 100644 --- a/arch/x86/cpu/broadwell/Kconfig +++ b/arch/x86/cpu/broadwell/Kconfig @@ -18,6 +18,7 @@ config INTEL_BROADWELL imply USB imply USB_EHCI_HCD imply VIDEO_BROADWELL_IGD + imply SYSRESET_INTEL_PCH
if INTEL_BROADWELL
diff --git a/drivers/sysreset/Kconfig b/drivers/sysreset/Kconfig index 8ce3e2e207..f88412adcc 100644 --- a/drivers/sysreset/Kconfig +++ b/drivers/sysreset/Kconfig @@ -23,6 +23,15 @@ config SYSRESET_GPIO example on Microblaze where reset logic can be controlled via GPIO pin which triggers cpu reset.
+config SYSRESET_INTEL_PCH + bool "Enable support for Intel PCH reset driver" + depends on X86 + help + Enable this option to get reset support on Intel SoCs which have + a common Platform-Controller Hub (PCH). This driver supports powering + off the device. It augments the standard x86 sysreset driver which + provides normal reset options. + config SYSRESET_MICROBLAZE bool "Enable support for Microblaze soft reset" depends on MICROBLAZE diff --git a/drivers/sysreset/Makefile b/drivers/sysreset/Makefile index b3728ac17f..2add6cb37a 100644 --- a/drivers/sysreset/Makefile +++ b/drivers/sysreset/Makefile @@ -8,6 +8,7 @@ obj-$(CONFIG_ARCH_ROCKCHIP) += sysreset_rockchip.o obj-$(CONFIG_ARCH_STI) += sysreset_sti.o obj-$(CONFIG_SANDBOX) += sysreset_sandbox.o obj-$(CONFIG_SYSRESET_GPIO) += sysreset_gpio.o +obj-$(CONFIG_SYSRESET_INTEL_PCH) += sysreset_intel_pch.o obj-$(CONFIG_SYSRESET_MCP83XX) += sysreset_mpc83xx.o obj-$(CONFIG_SYSRESET_MICROBLAZE) += sysreset_microblaze.o obj-$(CONFIG_SYSRESET_PSCI) += sysreset_psci.o diff --git a/drivers/sysreset/sysreset_intel_pch.c b/drivers/sysreset/sysreset_intel_pch.c new file mode 100644 index 0000000000..b60fa40dda --- /dev/null +++ b/drivers/sysreset/sysreset_intel_pch.c @@ -0,0 +1,125 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright (C) 2018 Google Inc, + * Written by Simon Glass sjg@chromium.org + * + * Reset driver for intel x86 processors with a PCH. Supports powering the + * device off. + */ + +#include <common.h> +#include <dm.h> +#include <sysreset.h> +#include <asm/io.h> +#include <asm/processor.h> +#include <asm/arch/pch.h> +#include <asm/arch/pm.h> + +struct x86_reset_platdata { + struct udevice *pch; +}; + +/* + * Power down the machine by using the power management sleep control + * of the chipset. This will currently only work on Intel chipsets. + * However, adapting it to new chipsets is fairly simple. You will + * have to find the IO address of the power management register block + * in your southbridge, and look up the appropriate SLP_TYP_S5 value + * from your southbridge's data sheet. + * + * This function never returns. + */ +int pch_sysreset_power_off(struct udevice *dev) +{ + struct x86_reset_platdata *plat = dev_get_platdata(dev); + u16 pmbase; + u32 reg32; + int ret; + + if (!plat->pch) + return -ENOENT; + + /* Find the base address of the powermanagement registers */ + ret = dm_pci_read_config16(plat->pch, 0x40, &pmbase); + if (ret) + return ret; + + pmbase &= 0xfffe; + + /* 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, pmbase + GPE0_EN(0)); + + /* Clear Power Button Status */ + outw(PWRBTN_STS, pmbase + PM1_STS); + + /* PMBASE + 4, Bit 10-12, Sleeping Type, * set to 111 -> S5, soft_off */ + reg32 = inl(pmbase + PM1_CNT); + + /* Set Sleeping Type to S5 (poweroff) */ + reg32 &= ~(SLP_EN | SLP_TYP); + reg32 |= SLP_TYP_S5; + outl(reg32, pmbase + PM1_CNT); + + /* Now set the Sleep Enable bit */ + reg32 |= SLP_EN; + outl(reg32, pmbase + PM1_CNT); + + for (;;) + asm("hlt"); +} + +static int pch_sysreset_request(struct udevice *dev, enum sysreset_t type) +{ + int ret; + + switch (type) { + case SYSRESET_POWER_OFF: + ret = pch_sysreset_power_off(dev); + if (ret) + return ret; + break; + default: + return -ENOSYS; + } + + return -EINPROGRESS; +} + +static int pch_sysreset_ofdata_to_platdata(struct udevice *dev) +{ + struct x86_reset_platdata *plat = dev_get_platdata(dev); + int ret; + + ret = uclass_get_device_by_phandle(UCLASS_PCH, dev, "intel,pch", + &plat->pch); + if (ret && ret != -ENOENT) + return log_ret(ret); + + return 0; +} + +static const struct udevice_id pch_sysreset_ids[] = { + { .compatible = "intel,pch-reset" }, + { } +}; + +static struct sysreset_ops pch_sysreset_ops = { + .request = pch_sysreset_request, +}; + +U_BOOT_DRIVER(pch_sysreset) = { + .name = "pch-sysreset", + .id = UCLASS_SYSRESET, + .of_match = pch_sysreset_ids, + .ops = &pch_sysreset_ops, + .flags = DM_FLAG_PRE_RELOC, + .ofdata_to_platdata = pch_sysreset_ofdata_to_platdata, +};

Hi Simon,
On Wed, Jan 30, 2019 at 12:00 PM Simon Glass sjg@chromium.org wrote:
Intel SoCs support a fairly stardard reset mechanism which can support powering off the device. Add support for this and enable it by default on broadwell, which already has the necessary pm.h header file.
This driver augments the standard x86 sysreset driver.
I think we need update the existing sysreset_x86 driver to support SYSRESET_POWER_OFF, instead of creating a new driver to do such.
We can add a new PCH ioctl code to get the pmbase, and do the ACPI power off in the sysreset_x86 driver.
Signed-off-by: Simon Glass sjg@chromium.org
arch/x86/cpu/broadwell/Kconfig | 1 + drivers/sysreset/Kconfig | 9 ++ drivers/sysreset/Makefile | 1 + drivers/sysreset/sysreset_intel_pch.c | 125 ++++++++++++++++++++++++++ 4 files changed, 136 insertions(+) create mode 100644 drivers/sysreset/sysreset_intel_pch.c
Regards, Bin

Hi Bin,
On Fri, 22 Feb 2019 at 00:20, Bin Meng bmeng.cn@gmail.com wrote:
Hi Simon,
On Wed, Jan 30, 2019 at 12:00 PM Simon Glass sjg@chromium.org wrote:
Intel SoCs support a fairly stardard reset mechanism which can support powering off the device. Add support for this and enable it by default on broadwell, which already has the necessary pm.h header file.
This driver augments the standard x86 sysreset driver.
I think we need update the existing sysreset_x86 driver to support SYSRESET_POWER_OFF, instead of creating a new driver to do such.
We can add a new PCH ioctl code to get the pmbase, and do the ACPI power off in the sysreset_x86 driver.
So are you saying that the registers are the same for all x86 chips?
From what I can tell, the offsets vary.
Regards, Simon
Signed-off-by: Simon Glass sjg@chromium.org
arch/x86/cpu/broadwell/Kconfig | 1 + drivers/sysreset/Kconfig | 9 ++ drivers/sysreset/Makefile | 1 + drivers/sysreset/sysreset_intel_pch.c | 125 ++++++++++++++++++++++++++ 4 files changed, 136 insertions(+) create mode 100644 drivers/sysreset/sysreset_intel_pch.c
Regards, Bin

Hi Simon,
On Wed, Apr 3, 2019 at 10:22 AM Simon Glass sjg@chromium.org wrote:
Hi Bin,
On Fri, 22 Feb 2019 at 00:20, Bin Meng bmeng.cn@gmail.com wrote:
Hi Simon,
On Wed, Jan 30, 2019 at 12:00 PM Simon Glass sjg@chromium.org wrote:
Intel SoCs support a fairly stardard reset mechanism which can support powering off the device. Add support for this and enable it by default on broadwell, which already has the necessary pm.h header file.
This driver augments the standard x86 sysreset driver.
I think we need update the existing sysreset_x86 driver to support SYSRESET_POWER_OFF, instead of creating a new driver to do such.
We can add a new PCH ioctl code to get the pmbase, and do the ACPI power off in the sysreset_x86 driver.
So are you saying that the registers are the same for all x86 chips? From what I can tell, the offsets vary.
Yes, the offsets might be different, so instead of getting only the pmbase, we need do something like getting ACPI PM register block information from the PCH driver. That's how acpi_create_fadt() passes ACPI register block information to the OS.
Regards, Bin

Hi Bin,
On Wed, 3 Apr 2019 at 02:42, Bin Meng bmeng.cn@gmail.com wrote:
Hi Simon,
On Wed, Apr 3, 2019 at 10:22 AM Simon Glass sjg@chromium.org wrote:
Hi Bin,
On Fri, 22 Feb 2019 at 00:20, Bin Meng bmeng.cn@gmail.com wrote:
Hi Simon,
On Wed, Jan 30, 2019 at 12:00 PM Simon Glass sjg@chromium.org wrote:
Intel SoCs support a fairly stardard reset mechanism which can support powering off the device. Add support for this and enable it by default on broadwell, which already has the necessary pm.h header file.
This driver augments the standard x86 sysreset driver.
I think we need update the existing sysreset_x86 driver to support SYSRESET_POWER_OFF, instead of creating a new driver to do such.
We can add a new PCH ioctl code to get the pmbase, and do the ACPI power off in the sysreset_x86 driver.
So are you saying that the registers are the same for all x86 chips? From what I can tell, the offsets vary.
Yes, the offsets might be different, so instead of getting only the pmbase, we need do something like getting ACPI PM register block information from the PCH driver. That's how acpi_create_fadt() passes ACPI register block information to the OS.
That doesn't make a lot of sense to me. If the register layout is different, why not just use different drivers?
I suppose we could put the common code (with parameters) in a separate file and call it from the driver. The parameters would presumably be:
PMBASE GPE0_EN(0) PM1_STS PM1_CNT
Regards, Simon

Hi Simon,
On Sat, Apr 6, 2019 at 10:02 AM Simon Glass sjg@chromium.org wrote:
Hi Bin,
On Wed, 3 Apr 2019 at 02:42, Bin Meng bmeng.cn@gmail.com wrote:
Hi Simon,
On Wed, Apr 3, 2019 at 10:22 AM Simon Glass sjg@chromium.org wrote:
Hi Bin,
On Fri, 22 Feb 2019 at 00:20, Bin Meng bmeng.cn@gmail.com wrote:
Hi Simon,
On Wed, Jan 30, 2019 at 12:00 PM Simon Glass sjg@chromium.org wrote:
Intel SoCs support a fairly stardard reset mechanism which can support powering off the device. Add support for this and enable it by default on broadwell, which already has the necessary pm.h header file.
This driver augments the standard x86 sysreset driver.
I think we need update the existing sysreset_x86 driver to support SYSRESET_POWER_OFF, instead of creating a new driver to do such.
We can add a new PCH ioctl code to get the pmbase, and do the ACPI power off in the sysreset_x86 driver.
So are you saying that the registers are the same for all x86 chips? From what I can tell, the offsets vary.
Yes, the offsets might be different, so instead of getting only the pmbase, we need do something like getting ACPI PM register block information from the PCH driver. That's how acpi_create_fadt() passes ACPI register block information to the OS.
That doesn't make a lot of sense to me. If the register layout is different, why not just use different drivers?
Yes, the register layout might be different but the programming model is the same and well defined in the ACPI spec.
I suppose we could put the common code (with parameters) in a separate file and call it from the driver. The parameters would presumably be:
PMBASE GPE0_EN(0) PM1_STS PM1_CNT
That's why I suggest to ask PCH driver to provide these offsets in a struct via an ioctl call to the sysreset driver.
Regards, Bin

Update the Makefie rules to ensure that the correct files are built when TPL is being used.
Signed-off-by: Simon Glass sjg@chromium.org ---
arch/x86/cpu/intel_common/Makefile | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-)
diff --git a/arch/x86/cpu/intel_common/Makefile b/arch/x86/cpu/intel_common/Makefile index 57cca0b930..07f27c29ec 100644 --- a/arch/x86/cpu/intel_common/Makefile +++ b/arch/x86/cpu/intel_common/Makefile @@ -4,15 +4,18 @@
ifdef CONFIG_HAVE_MRC obj-$(CONFIG_$(SPL_TPL_)X86_16BIT_INIT) += car.o -obj-$(CONFIG_$(SPL_)X86_32BIT_INIT) += me_status.o -obj-$(CONFIG_$(SPL_)X86_32BIT_INIT) += report_platform.o -obj-$(CONFIG_$(SPL_)X86_32BIT_INIT) += mrc.o +obj-$(CONFIG_$(SPL_TPL_)X86_32BIT_INIT) += me_status.o +obj-$(CONFIG_$(SPL_TPL_)X86_32BIT_INIT) += report_platform.o +obj-$(CONFIG_$(SPL_TPL_)X86_32BIT_INIT) += mrc.o endif obj-y += cpu.o obj-y += lpc.o ifndef CONFIG_TARGET_EFI_APP +obj-$(CONFIG_$(SPL_TPL_)X86_32BIT_INIT) += microcode.o +ifndef CONFIG_$(SPL_)X86_64 obj-y += microcode.o endif +endif obj-y += pch.o
ifdef CONFIG_SPL

On Wed, Jan 30, 2019 at 12:00 PM Simon Glass sjg@chromium.org wrote:
Update the Makefie rules to ensure that the correct files are built when TPL is being used.
Signed-off-by: Simon Glass sjg@chromium.org
arch/x86/cpu/intel_common/Makefile | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-)
Reviewed-by: Bin Meng bmeng.cn@gmail.com

The MTRRs are normally set up in U-Boot proper, so avoid setting them up in SPL as well.
Signed-off-by: Simon Glass sjg@chromium.org ---
arch/x86/lib/init_helpers.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-)
diff --git a/arch/x86/lib/init_helpers.c b/arch/x86/lib/init_helpers.c index 0481f453ca..ac85278cdf 100644 --- a/arch/x86/lib/init_helpers.c +++ b/arch/x86/lib/init_helpers.c @@ -18,7 +18,10 @@ __weak ulong board_get_usable_ram_top(ulong total_size)
int init_cache_f_r(void) { -#if CONFIG_IS_ENABLED(X86_32BIT_INIT) && !defined(CONFIG_HAVE_FSP) +#if (CONFIG_IS_ENABLED(X86_32BIT_INIT) || \ + (!defined(CONFIG_SPL_BUILD) && \ + !CONFIG_IS_ENABLED(CONFIG_X86_RUN_64BIT))) && \ + !defined(CONFIG_HAVE_FSP) int ret;
ret = mtrr_commit(false);

On Wed, Jan 30, 2019 at 12:00 PM Simon Glass sjg@chromium.org wrote:
The MTRRs are normally set up in U-Boot proper, so avoid setting them up in SPL as well.
Signed-off-by: Simon Glass sjg@chromium.org
arch/x86/lib/init_helpers.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-)
Reviewed-by: Bin Meng bmeng.cn@gmail.com

This report is normally generated by U-Boot proper. Correct the condition here so that it respects the Kconfig options for bootstage.
Signed-off-by: Simon Glass sjg@chromium.org ---
arch/x86/lib/bootm.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/arch/x86/lib/bootm.c b/arch/x86/lib/bootm.c index 832b1f901c..5443a862ab 100644 --- a/arch/x86/lib/bootm.c +++ b/arch/x86/lib/bootm.c @@ -35,7 +35,7 @@ void bootm_announce_and_cleanup(void) timestamp_add_now(TS_U_BOOT_START_KERNEL); #endif bootstage_mark_name(BOOTSTAGE_ID_BOOTM_HANDOFF, "start_kernel"); -#ifdef CONFIG_BOOTSTAGE_REPORT +#if CONFIG_IS_ENABLED(BOOTSTAGE_REPORT) bootstage_report(); #endif

On Wed, Jan 30, 2019 at 12:00 PM Simon Glass sjg@chromium.org wrote:
This report is normally generated by U-Boot proper. Correct the condition here so that it respects the Kconfig options for bootstage.
Signed-off-by: Simon Glass sjg@chromium.org
arch/x86/lib/bootm.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
Reviewed-by: Bin Meng bmeng.cn@gmail.com

When TPL is in use, U-Boot proper should support initing the VGA ROM even though the 32-bit init portion is in SPL. Update the condition to handle this.
Signed-off-by: Simon Glass sjg@chromium.org ---
drivers/pci/pci_rom.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/pci/pci_rom.c b/drivers/pci/pci_rom.c index 7d9b75c2c4..2cede1211b 100644 --- a/drivers/pci/pci_rom.c +++ b/drivers/pci/pci_rom.c @@ -306,7 +306,7 @@ int dm_pci_run_vga_bios(struct udevice *dev, int (*int15_handler)(void), goto err; #endif } else { -#if defined(CONFIG_X86) && CONFIG_IS_ENABLED(X86_32BIT_INIT) +#if defined(CONFIG_X86) && (CONFIG_IS_ENABLED(X86_32BIT_INIT) || CONFIG_TPL) bios_set_interrupt_handler(0x15, int15_handler);
bios_run_on_x86(dev, (unsigned long)ram, vesa_mode,

On Wed, Jan 30, 2019 at 12:01 PM Simon Glass sjg@chromium.org wrote:
When TPL is in use, U-Boot proper should support initing the VGA ROM even though the 32-bit init portion is in SPL. Update the condition to handle this.
Signed-off-by: Simon Glass sjg@chromium.org
drivers/pci/pci_rom.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
Reviewed-by: Bin Meng bmeng.cn@gmail.com

Add a default implementation of this method which always indicates that the last reset was a power-on reset. This is the most likely type of reset and without a PCH-specific driver we cannot determine any other type.
Signed-off-by: Simon Glass sjg@chromium.org ---
drivers/sysreset/sysreset_x86.c | 6 ++++++ 1 file changed, 6 insertions(+)
diff --git a/drivers/sysreset/sysreset_x86.c b/drivers/sysreset/sysreset_x86.c index 20b958cfd4..2a8ec6b0d2 100644 --- a/drivers/sysreset/sysreset_x86.c +++ b/drivers/sysreset/sysreset_x86.c @@ -31,6 +31,11 @@ static int x86_sysreset_request(struct udevice *dev, enum sysreset_t type) return -EINPROGRESS; }
+static int x86_sysreset_get_last(struct udevice *dev) +{ + return SYSRESET_POWER; +} + static const struct udevice_id x86_sysreset_ids[] = { { .compatible = "x86,reset" }, { } @@ -38,6 +43,7 @@ static const struct udevice_id x86_sysreset_ids[] = {
static struct sysreset_ops x86_sysreset_ops = { .request = x86_sysreset_request, + .get_last = x86_sysreset_get_last, };
U_BOOT_DRIVER(x86_sysreset) = {

Hi Simon,
On Wed, Jan 30, 2019 at 12:01 PM Simon Glass sjg@chromium.org wrote:
Add a default implementation of this method which always indicates that the last reset was a power-on reset. This is the most likely type of reset and without a PCH-specific driver we cannot determine any other type.
See my comments for patch [28/40]. We can return the correct reset type based on whether PCH provided ioctl for pmbase address.
Signed-off-by: Simon Glass sjg@chromium.org
drivers/sysreset/sysreset_x86.c | 6 ++++++ 1 file changed, 6 insertions(+)
Regards, Bin

Hi Bin,
On Fri, 22 Feb 2019 at 00:20, Bin Meng bmeng.cn@gmail.com wrote:
Hi Simon,
On Wed, Jan 30, 2019 at 12:01 PM Simon Glass sjg@chromium.org wrote:
Add a default implementation of this method which always indicates that the last reset was a power-on reset. This is the most likely type of reset and without a PCH-specific driver we cannot determine any other type.
See my comments for patch [28/40]. We can return the correct reset type based on whether PCH provided ioctl for pmbase address.
I've haven't implemented this for v2. I think I need a few pointers on where to get this info. I suppose I could add it in a follow-on patch. Also it would be good to add a command to show this info.
Regards, Simon

There are quite a few variables which control where things appear in the final ROM image. Add a flashmap in the documentation to make this easier to figure out.
Signed-off-by: Simon Glass sjg@chromium.org ---
doc/README.x86 | 14 ++++++++++++++ 1 file changed, 14 insertions(+)
diff --git a/doc/README.x86 b/doc/README.x86 index fa49cb8b8a..d5224b7536 100644 --- a/doc/README.x86 +++ b/doc/README.x86 @@ -185,6 +185,20 @@ If you are using em100, then this command will flash write -Boot:
em100 -s -d filename.rom -c W25Q64CV -r
+Flash map for samus / broadwell: + + fffff800 SYS_X86_START16 + ffff0000 RESET_SEG_START + fffd8000 TPL_TEXT_BASE + fffa0000 X86_MRC_ADDR + fff90000 VGA_BIOS_ADDR + ffed0000 SYS_TEXT_BASE + ffea0000 X86_REFCODE_ADDR + ffe70000 SPL_TEXT_BASE + ffa00000 <spare> + ff801000 intel-me (address set by descriptor.bin) + ff800000 intel-descriptor + ---
Intel Crown Bay specific instructions for bare mode:

On Wed, Jan 30, 2019 at 12:01 PM Simon Glass sjg@chromium.org wrote:
There are quite a few variables which control where things appear in the final ROM image. Add a flashmap in the documentation to make this easier to figure out.
Signed-off-by: Simon Glass sjg@chromium.org
doc/README.x86 | 14 ++++++++++++++ 1 file changed, 14 insertions(+)
Reviewed-by: Bin Meng bmeng.cn@gmail.com

Add tags to allow required nodes to be present in SPL / TPL. Also enable the sysreset driver.
Signed-off-by: Simon Glass sjg@chromium.org ---
arch/x86/dts/chromebook_samus.dts | 38 +++++++++++++++++++++++++++---- 1 file changed, 34 insertions(+), 4 deletions(-)
diff --git a/arch/x86/dts/chromebook_samus.dts b/arch/x86/dts/chromebook_samus.dts index b58936b4ac..348d012e23 100644 --- a/arch/x86/dts/chromebook_samus.dts +++ b/arch/x86/dts/chromebook_samus.dts @@ -17,6 +17,7 @@ spi0 = &spi; usb0 = &usb_0; usb1 = &usb_1; + cros-ec0 = &cros_ec; };
config { @@ -73,6 +74,7 @@
/* Put this first: it is the default */ gpio_unused: gpio-unused { + u-boot,dm-pre-reloc; mode-gpio; direction = <PIN_INPUT>; owner = <OWNER_GPIO>; @@ -80,6 +82,7 @@ };
gpio_acpi_sci: acpi-sci { + u-boot,dm-pre-reloc; mode-gpio; direction = <PIN_INPUT>; invert; @@ -87,6 +90,7 @@ };
gpio_acpi_smi: acpi-smi { + u-boot,dm-pre-reloc; mode-gpio; direction = <PIN_INPUT>; invert; @@ -94,12 +98,14 @@ };
gpio_input: gpio-input { + u-boot,dm-pre-reloc; mode-gpio; direction = <PIN_INPUT>; owner = <OWNER_GPIO>; };
gpio_input_invert: gpio-input-invert { + u-boot,dm-pre-reloc; mode-gpio; direction = <PIN_INPUT>; owner = <OWNER_GPIO>; @@ -107,9 +113,11 @@ };
gpio_native: gpio-native { + u-boot,dm-pre-reloc; };
gpio_out_high: gpio-out-high { + u-boot,dm-pre-reloc; mode-gpio; direction = <PIN_OUTPUT>; output-value = <1>; @@ -118,6 +126,7 @@ };
gpio_out_low: gpio-out-low { + u-boot,dm-pre-reloc; mode-gpio; direction = <PIN_OUTPUT>; output-value = <0>; @@ -126,6 +135,7 @@ };
gpio_pirq: gpio-pirq { + u-boot,dm-pre-reloc; mode-gpio; direction = <PIN_INPUT>; owner = <OWNER_GPIO>; @@ -133,6 +143,7 @@ };
soc_gpio@0 { + u-boot,dm-pre-reloc; config = <0 &gpio_unused 0>, /* unused */ <1 &gpio_unused 0>, /* unused */ @@ -250,8 +261,10 @@ spd { #address-cells = <1>; #size-cells = <0>; + u-boot,dm-pre-reloc; samsung_4 { reg = <6>; + u-boot,dm-pre-reloc; data = [91 20 f1 03 04 11 05 0b 03 11 01 08 0a 00 50 01 78 78 90 50 90 11 50 e0 @@ -291,6 +304,7 @@ * columns 10, density 4096 mb, x32 */ reg = <8>; + u-boot,dm-pre-reloc; data = [91 20 f1 03 04 11 05 0b 03 11 01 08 0a 00 50 01 78 78 90 50 90 11 50 e0 @@ -326,6 +340,7 @@ }; samsung_8 { reg = <10>; + u-boot,dm-pre-reloc; data = [91 20 f1 03 04 12 05 0a 03 11 01 08 0a 00 50 01 78 78 90 50 90 11 50 e0 @@ -365,6 +380,7 @@ * columns 11, density 4096 mb, x16 */ reg = <12>; + u-boot,dm-pre-reloc; data = [91 20 f1 03 04 12 05 0a 03 11 01 08 0a 00 50 01 78 78 90 50 90 11 50 e0 @@ -404,6 +420,7 @@ * columns 11, density 8192 mb, x16 */ reg = <13>; + u-boot,dm-pre-reloc; data = [91 20 f1 03 05 1a 05 0a 03 11 01 08 0a 00 50 01 78 78 90 50 90 11 50 e0 @@ -443,6 +460,7 @@ * columns 11, density 8192 mb, x16 */ reg = <15>; + u-boot,dm-pre-reloc; data = [91 20 f1 03 05 1a 05 0a 03 11 01 08 0a 00 50 01 78 78 90 50 90 11 50 e0 @@ -511,7 +529,7 @@ compatible = "ehci-pci"; };
- pch@1f,0 { + pch: pch@1f,0 { reg = <0x0000f800 0 0 0 0>; compatible = "intel,broadwell-pch"; u-boot,dm-pre-reloc; @@ -530,17 +548,20 @@ power-enable-gpio = <&gpio_a 23 0>;
spi: spi { + u-boot,dm-pre-reloc; #address-cells = <1>; #size-cells = <0>; compatible = "intel,ich9-spi"; spi-flash@0 { + u-boot,dm-pre-reloc; #size-cells = <1>; #address-cells = <1>; reg = <0>; compatible = "winbond,w25q64", "spi-flash"; - memory-map = <0xff800000 0x00800000>; + memory-map = <0 0xff800000 0 0x00800000>; rw-mrc-cache { + u-boot,dm-pre-reloc; label = "rw-mrc-cache"; reg = <0x003e0000 0x00010000>; }; @@ -580,7 +601,8 @@ #size-cells = <0>; u-boot,dm-pre-reloc; intel,gen-dec = <0x800 0xfc 0x900 0xfc>; - cros-ec@200 { + cros_ec: cros-ec { + u-boot,dm-pre-reloc; compatible = "google,cros-ec-lpc"; reg = <0x204 1 0x200 1 0x880 0x80>;
@@ -601,7 +623,7 @@ sata@1f,2 { compatible = "intel,wildcatpoint-ahci"; reg = <0x0000fa00 0 0 0 0>; - u-boot,dm-pre-reloc; + u-boot,dm-pre-proper; intel,sata-mode = "ahci"; intel,sata-port-map = <1>; intel,sata-port0-gen3-tx = <0x72>; @@ -615,13 +637,21 @@ }; };
+ pch-reset { + compatible = "intel,pch-reset"; + intel,pch = <&pch>; + }; + tpm { + u-boot,dm-pre-reloc; reg = <0xfed40000 0x5000>; compatible = "infineon,slb9635lpc"; };
microcode { + u-boot,dm-pre-reloc; update@0 { + u-boot,dm-pre-reloc; #include "microcode/mc0306d4_00000018.dtsi" }; };

On Wed, Jan 30, 2019 at 12:01 PM Simon Glass sjg@chromium.org wrote:
Add tags to allow required nodes to be present in SPL / TPL. Also enable the sysreset driver.
Signed-off-by: Simon Glass sjg@chromium.org
arch/x86/dts/chromebook_samus.dts | 38 +++++++++++++++++++++++++++---- 1 file changed, 34 insertions(+), 4 deletions(-)
Reviewed-by: Bin Meng bmeng.cn@gmail.com

Add nvdata drivers for the TPM and RTC as used on samus. These are needed for Chromium OS verified boot on samus.
Signed-off-by: Simon Glass sjg@chromium.org ---
arch/x86/dts/chromebook_samus.dts | 22 +++++++++++++++++++++- 1 file changed, 21 insertions(+), 1 deletion(-)
diff --git a/arch/x86/dts/chromebook_samus.dts b/arch/x86/dts/chromebook_samus.dts index 348d012e23..7c5b1e4010 100644 --- a/arch/x86/dts/chromebook_samus.dts +++ b/arch/x86/dts/chromebook_samus.dts @@ -9,6 +9,12 @@ /include/ "rtc.dtsi" /include/ "tsc_timer.dtsi"
+#ifdef CONFIG_CHROMEOS +#include "chromeos-x86.dtsi" +#include "flashmap-x86-ro.dtsi" +#include "flashmap-8mb-rw.dtsi" +#endif + / { model = "Google Samus"; compatible = "google,samus", "intel,broadwell"; @@ -552,7 +558,7 @@ #address-cells = <1>; #size-cells = <0>; compatible = "intel,ich9-spi"; - spi-flash@0 { + fwstore_spi: spi-flash@0 { u-boot,dm-pre-reloc; #size-cells = <1>; #address-cells = <1>; @@ -646,6 +652,10 @@ u-boot,dm-pre-reloc; reg = <0xfed40000 0x5000>; compatible = "infineon,slb9635lpc"; + secdata { + u-boot,dm-pre-reloc; + compatible = "google,tpm-secdata"; + }; };
microcode { @@ -657,3 +667,13 @@ };
}; + +&rtc { + #address-cells = <1>; + #size-cells = <0>; + nvdata { + u-boot,dm-pre-reloc; + compatible = "google,cmos-nvdata"; + reg = <0x26>; + }; +};

On Wed, Jan 30, 2019 at 12:01 PM Simon Glass sjg@chromium.org wrote:
Add nvdata drivers for the TPM and RTC as used on samus. These are needed for Chromium OS verified boot on samus.
Signed-off-by: Simon Glass sjg@chromium.org
arch/x86/dts/chromebook_samus.dts | 22 +++++++++++++++++++++- 1 file changed, 21 insertions(+), 1 deletion(-)
Reviewed-by: Bin Meng bmeng.cn@gmail.com

Add TPL binaries to the device x86 binman desciption. When enabled, TPL will start first, doing the 16-bit init, then jump to SPL and finally U-Boot proper.
Signed-off-by: Simon Glass sjg@chromium.org ---
arch/x86/dts/u-boot.dtsi | 26 ++++++++++++++++++++++++-- 1 file changed, 24 insertions(+), 2 deletions(-)
diff --git a/arch/x86/dts/u-boot.dtsi b/arch/x86/dts/u-boot.dtsi index 1050236330..70e9c8f7ac 100644 --- a/arch/x86/dts/u-boot.dtsi +++ b/arch/x86/dts/u-boot.dtsi @@ -22,7 +22,21 @@ filename = CONFIG_INTEL_ME_FILE; }; #endif -#ifdef CONFIG_SPL +#ifdef CONFIG_TPL + u-boot-spl { + offset = <CONFIG_SPL_TEXT_BASE>; + }; + u-boot-spl-dtb { + }; + u-boot-tpl-with-ucode-ptr { + offset = <CONFIG_TPL_TEXT_BASE>; + }; + u-boot-tpl-dtb { + }; + u-boot { + offset = <CONFIG_SYS_TEXT_BASE>; + }; +#elif defined(CONFIG_SPL) u-boot-spl-with-ucode-ptr { offset = <CONFIG_SPL_TEXT_BASE>; }; @@ -31,7 +45,11 @@ type = "u-boot-dtb-with-ucode"; }; u-boot { +#if CONFIG_SYS_TEXT_BASE == 0x1110000 offset = <0xfff00000>; +#else + offset = <CONFIG_SYS_TEXT_BASE>; +#endif }; #else u-boot-with-ucode-ptr { @@ -77,7 +95,11 @@ offset = <CONFIG_X86_REFCODE_ADDR>; }; #endif -#ifdef CONFIG_SPL +#ifdef CONFIG_TPL + x86-start16-tpl { + offset = <CONFIG_SYS_X86_START16>; + }; +#elif defined(CONFIG_SPL) x86-start16-spl { offset = <CONFIG_SYS_X86_START16>; };

Hi Simon,
On Wed, Jan 30, 2019 at 12:01 PM Simon Glass sjg@chromium.org wrote:
Add TPL binaries to the device x86 binman desciption. When enabled, TPL will start first, doing the 16-bit init, then jump to SPL and finally U-Boot proper.
I am confused by "TPL will start first". My understanding is that "SPL" starts before "TPL".
Signed-off-by: Simon Glass sjg@chromium.org
arch/x86/dts/u-boot.dtsi | 26 ++++++++++++++++++++++++-- 1 file changed, 24 insertions(+), 2 deletions(-)
Regards, Bin

Hi Bin,
On Fri, 22 Feb 2019 at 00:20, Bin Meng bmeng.cn@gmail.com wrote:
Hi Simon,
On Wed, Jan 30, 2019 at 12:01 PM Simon Glass sjg@chromium.org wrote:
Add TPL binaries to the device x86 binman desciption. When enabled, TPL will start first, doing the 16-bit init, then jump to SPL and finally U-Boot proper.
I am confused by "TPL will start first". My understanding is that "SPL" starts before "TPL".
No, it is TPL -> SPL - > U-Boot.
Regards, Simon

The standard image generated by U-Boot on x86 is u-boot.rom. Add a separate image called image.bin for verified boot. This supports verification in TPL of which SPL/U-Boot to start, then jumping to the correct one, with SPL setting up the SDRAM and U-Boot proper providing the user interface if needed.
Signed-off-by: Simon Glass sjg@chromium.org ---
arch/x86/dts/u-boot.dtsi | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-)
diff --git a/arch/x86/dts/u-boot.dtsi b/arch/x86/dts/u-boot.dtsi index 70e9c8f7ac..5943619b86 100644 --- a/arch/x86/dts/u-boot.dtsi +++ b/arch/x86/dts/u-boot.dtsi @@ -6,9 +6,23 @@
#include <config.h>
-#ifdef CONFIG_ROM_SIZE +#ifdef CONFIG_CHROMEOS / { binman { + multiple-images; + rom: rom { + }; + }; +}; +#else +/ { + rom: binman { + }; +}; +#endif + +#ifdef CONFIG_ROM_SIZE +&rom { filename = "u-boot.rom"; end-at-4gb; sort-by-offset; @@ -108,6 +122,5 @@ offset = <CONFIG_SYS_X86_START16>; }; #endif - }; }; #endif

On Wed, Jan 30, 2019 at 12:01 PM Simon Glass sjg@chromium.org wrote:
The standard image generated by U-Boot on x86 is u-boot.rom. Add a separate image called image.bin for verified boot. This supports verification in TPL of which SPL/U-Boot to start, then jumping to the correct one, with SPL setting up the SDRAM and U-Boot proper providing the user interface if needed.
Signed-off-by: Simon Glass sjg@chromium.org
arch/x86/dts/u-boot.dtsi | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-)
Reviewed-by: Bin Meng bmeng.cn@gmail.com

With the use of a phandle we can outdent the device tree nodes a little. Fix this.
Signed-off-by: Simon Glass sjg@chromium.org ---
arch/x86/dts/u-boot.dtsi | 147 +++++++++++++++++++-------------------- 1 file changed, 73 insertions(+), 74 deletions(-)
diff --git a/arch/x86/dts/u-boot.dtsi b/arch/x86/dts/u-boot.dtsi index 5943619b86..8bb1318a2c 100644 --- a/arch/x86/dts/u-boot.dtsi +++ b/arch/x86/dts/u-boot.dtsi @@ -23,104 +23,103 @@
#ifdef CONFIG_ROM_SIZE &rom { - filename = "u-boot.rom"; - end-at-4gb; - sort-by-offset; - pad-byte = <0xff>; - size = <CONFIG_ROM_SIZE>; + 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; - }; + intel-descriptor { + filename = CONFIG_FLASH_DESCRIPTOR_FILE; + }; + intel-me { + filename = CONFIG_INTEL_ME_FILE; + }; #endif #ifdef CONFIG_TPL - u-boot-spl { - offset = <CONFIG_SPL_TEXT_BASE>; - }; - u-boot-spl-dtb { - }; - u-boot-tpl-with-ucode-ptr { - offset = <CONFIG_TPL_TEXT_BASE>; - }; - u-boot-tpl-dtb { - }; - u-boot { - offset = <CONFIG_SYS_TEXT_BASE>; - }; + u-boot-spl { + offset = <CONFIG_SPL_TEXT_BASE>; + }; + u-boot-spl-dtb { + }; + u-boot-tpl-with-ucode-ptr { + offset = <CONFIG_TPL_TEXT_BASE>; + }; + u-boot-tpl-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 { + u-boot-spl-with-ucode-ptr { + offset = <CONFIG_SPL_TEXT_BASE>; + }; + u-boot-dtb-with-ucode2 { + type = "u-boot-dtb-with-ucode"; + }; + u-boot { #if CONFIG_SYS_TEXT_BASE == 0x1110000 - offset = <0xfff00000>; + offset = <0xfff00000>; #else - offset = <CONFIG_SYS_TEXT_BASE>; + offset = <CONFIG_SYS_TEXT_BASE>; #endif - }; + }; #else - u-boot-with-ucode-ptr { - offset = <CONFIG_SYS_TEXT_BASE>; - }; + u-boot-with-ucode-ptr { + offset = <CONFIG_SYS_TEXT_BASE>; + }; #endif - u-boot-dtb-with-ucode { - }; - u-boot-ucode { - align = <16>; - }; + u-boot-dtb-with-ucode { + }; + u-boot-ucode { + align = <16>; + }; #ifdef CONFIG_HAVE_MRC - intel-mrc { - offset = <CONFIG_X86_MRC_ADDR>; - }; + intel-mrc { + offset = <CONFIG_X86_MRC_ADDR>; + }; #endif #ifdef CONFIG_HAVE_FSP - intel-fsp { - filename = CONFIG_FSP_FILE; - offset = <CONFIG_FSP_ADDR>; - }; + 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>; - }; + 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>; - }; + 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>; - }; + intel-vbt { + filename = CONFIG_VBT_FILE; + offset = <CONFIG_VBT_ADDR>; + }; #endif #ifdef CONFIG_HAVE_REFCODE - intel-refcode { - offset = <CONFIG_X86_REFCODE_ADDR>; - }; + intel-refcode { + offset = <CONFIG_X86_REFCODE_ADDR>; + }; #endif #ifdef CONFIG_TPL - x86-start16-tpl { - offset = <CONFIG_SYS_X86_START16>; - }; + x86-start16-tpl { + offset = <CONFIG_SYS_X86_START16>; + }; #elif defined(CONFIG_SPL) - x86-start16-spl { - offset = <CONFIG_SYS_X86_START16>; - }; + x86-start16-spl { + offset = <CONFIG_SYS_X86_START16>; + }; #else - x86-start16 { - offset = <CONFIG_SYS_X86_START16>; - }; + x86-start16 { + offset = <CONFIG_SYS_X86_START16>; + }; #endif }; #endif

On Wed, Jan 30, 2019 at 12:01 PM Simon Glass sjg@chromium.org wrote:
With the use of a phandle we can outdent the device tree nodes a little. Fix this.
Signed-off-by: Simon Glass sjg@chromium.org
arch/x86/dts/u-boot.dtsi | 147 +++++++++++++++++++-------------------- 1 file changed, 73 insertions(+), 74 deletions(-)
Reviewed-by: Bin Meng bmeng.cn@gmail.com

Add a version of samus which supports booting from TPL to SPL and then to U-Boot. This allows TPL to select from an A or B SPL to support verified boot with field upgrade.
Signed-off-by: Simon Glass sjg@chromium.org ---
board/google/Kconfig | 8 +++ board/google/chromebook_samus/Kconfig | 14 +++- board/google/chromebook_samus/MAINTAINERS | 7 ++ configs/chromebook_samus_tpl_defconfig | 80 +++++++++++++++++++++++ include/configs/chromebook_samus.h | 3 + 5 files changed, 110 insertions(+), 2 deletions(-) create mode 100644 configs/chromebook_samus_tpl_defconfig
diff --git a/board/google/Kconfig b/board/google/Kconfig index d98a5e818f..679a0f1023 100644 --- a/board/google/Kconfig +++ b/board/google/Kconfig @@ -52,6 +52,14 @@ config TARGET_CHROMEBOOK_SAMUS Chrome OS EC connected on LPC, and it provides a 2560x1700 high resolution touch-enabled LCD display.
+config TARGET_CHROMEBOOK_SAMUS_TPL + bool "Chromebook samus booting from TPL" + help + This is a version of Samus which boots into TPL, then to SPL and + U-Boot proper. This is useful where verified boot must select + between different A/B versions of SPL/U-Boot, to allow upgrading of + almost all U-Boot code in the field. + endchoice
source "board/google/chromebook_link/Kconfig" diff --git a/board/google/chromebook_samus/Kconfig b/board/google/chromebook_samus/Kconfig index afbfe53deb..90c23cba1b 100644 --- a/board/google/chromebook_samus/Kconfig +++ b/board/google/chromebook_samus/Kconfig @@ -1,4 +1,4 @@ -if TARGET_CHROMEBOOK_SAMUS +if TARGET_CHROMEBOOK_SAMUS || TARGET_CHROMEBOOK_SAMUS_TPL
config SYS_BOARD default "chromebook_samus" @@ -10,7 +10,8 @@ config SYS_SOC default "broadwell"
config SYS_CONFIG_NAME - default "chromebook_samus" + default "chromebook_samus" if TARGET_CHROMEBOOK_SAMUS + default "chromebook_samus" if TARGET_CHROMEBOOK_SAMUS_TPL
config SYS_TEXT_BASE default 0xffe00000 @@ -39,3 +40,12 @@ config SYS_CAR_SIZE default 0x40000
endif + +if TARGET_CHROMEBOOK_SAMUS_TPL + +config BOARD_SPECIFIC_OPTIONS_TPL # dummy + def_bool y + select SPL + select TPL + +endif diff --git a/board/google/chromebook_samus/MAINTAINERS b/board/google/chromebook_samus/MAINTAINERS index 5500e46b40..ca4b16500a 100644 --- a/board/google/chromebook_samus/MAINTAINERS +++ b/board/google/chromebook_samus/MAINTAINERS @@ -4,3 +4,10 @@ S: Maintained F: board/google/chromebook_samus/ F: include/configs/chromebook_samus.h F: configs/chromebook_samus_defconfig + +CHROMEBOOK SAMUS TPL BOARD +M: Simon Glass sjg@chromium.org +S: Maintained +F: board/google/chromebook_samus/ +F: include/configs/chromebook_samus.h +F: configs/chromebook_samus_tpl_defconfig diff --git a/configs/chromebook_samus_tpl_defconfig b/configs/chromebook_samus_tpl_defconfig new file mode 100644 index 0000000000..0a379e5b1c --- /dev/null +++ b/configs/chromebook_samus_tpl_defconfig @@ -0,0 +1,80 @@ +CONFIG_X86=y +CONFIG_SYS_TEXT_BASE=0xffed0000 +CONFIG_SYS_MALLOC_F_LEN=0x1a00 +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_NR_DRAM_BANKS=8 +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_HUSH_PARSER=y +CONFIG_CMD_CPU=y +# CONFIG_CMD_FLASH is not set +CONFIG_CMD_GPIO=y +CONFIG_CMD_PART=y +CONFIG_CMD_SF=y +CONFIG_CMD_SPI=y +CONFIG_CMD_USB=y +# CONFIG_CMD_SETEXPR is not set +CONFIG_CMD_DHCP=y +# CONFIG_CMD_NFS is not set +CONFIG_CMD_PING=y +CONFIG_CMD_TIME=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_ISO_PARTITION=y +CONFIG_EFI_PARTITION=y +CONFIG_DEFAULT_DEVICE_TREE="chromebook_samus" +CONFIG_REGMAP=y +CONFIG_SYSCON=y +CONFIG_CPU=y +CONFIG_CROS_EC=y +CONFIG_CROS_EC_LPC=y +CONFIG_SYS_NS16550=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 +CONFIG_SPL=y +CONFIG_TPL=y +CONFIG_HANDOFF=y +CONFIG_BLOBLIST_ADDR=0xff7c0000 +CONFIG_BLOBLIST_SIZE=0x1000 +CONFIG_BLOBLIST=y +CONFIG_SPL_PCI=y +CONFIG_SPL_PCH_SUPPORT=y +CONFIG_SPL_NET_SUPPORT=y +CONFIG_TPL_PCI=y +CONFIG_TPL_PCH_SUPPORT=y +CONFIG_TPL_MISC=y +# CONFIG_NET is not set +# CONFIG_SPL_ENV_SUPPORT is not set +# CONFIG_TPL_ENV_SUPPORT is not set +# CONFIG_SPL_DOS_PARTITION is not set +# CONFIG_SPL_EFI_PARTITION is not set +# CONFIG_SPL_MAC_PARTITION is not set +CONFIG_SPL_SEPARATE_BSS=y diff --git a/include/configs/chromebook_samus.h b/include/configs/chromebook_samus.h index ccb2fe8caa..610be1e7b5 100644 --- a/include/configs/chromebook_samus.h +++ b/include/configs/chromebook_samus.h @@ -23,4 +23,7 @@ #define CONFIG_ENV_SECT_SIZE 0x1000 #define CONFIG_ENV_OFFSET 0x003f8000
+#define CONFIG_SPL_TEXT_BASE 0xffe70000 +#define CONFIG_TPL_TEXT_BASE 0xfffd8000 + #endif /* __CONFIG_H */

On Wed, Jan 30, 2019 at 12:01 PM Simon Glass sjg@chromium.org wrote:
Add a version of samus which supports booting from TPL to SPL and then to U-Boot. This allows TPL to select from an A or B SPL to support verified boot with field upgrade.
Signed-off-by: Simon Glass sjg@chromium.org
board/google/Kconfig | 8 +++ board/google/chromebook_samus/Kconfig | 14 +++- board/google/chromebook_samus/MAINTAINERS | 7 ++ configs/chromebook_samus_tpl_defconfig | 80 +++++++++++++++++++++++ include/configs/chromebook_samus.h | 3 + 5 files changed, 110 insertions(+), 2 deletions(-) create mode 100644 configs/chromebook_samus_tpl_defconfig
Generally it looks good
Reviewed-by: Bin Meng bmeng.cn@gmail.com
But I still need understand the boot sequence of SPL/TPL.

Hi Bin,
On Wed, 30 Jan 2019 at 04:59, Simon Glass sjg@chromium.org wrote:
At present SPL is used on 64-bit platforms, to allow SPL to be built as a 32-bit program and U-Boot proper to be built as 64-bit.
However it is useful to be able to use SPL on any x86 platform, where U-Boot needs to be updated in the field. Then SPL can select which U-Boot to run (A or B) and most of the code can be updated. Similarly, using TPL allows both SPL and U-Boot to be updated. This is the best approach, since it means that all of U-Boot proper as well as SPL (in particular SDRAM init) can be updated in the field. This provides for the smallest possible amount of read-only (non-updateable) code: just the TPL code.
This series contains a number of changes to allow x86 boards to use TPL, SPL and U-Boot proper. As a test, it is enabled for samus with a new chromebook_samus_tpl board.
Simon Glass (40): binman: Don't generate an error in 'text' entry constructor binman: Don't show image-skip message by default binman: Add a missing comment in Entry_vblock dm: core: Fix translate condition in ofnode_get_addr_size() cros_ec: Use a hyphen in the uclass name spl: Allow sandbox to build a device-tree file RFC: binman: Allow sections to have an offset x86: start64: Fix copyright message x86: mp_init: Use proper error numbers x86: Add a way to reinit the cpu x86: dts: Add device-tree labels for rtc and reset x86: Update a stale comment about ifdtool x86: Support SPL and TPL x86: Support booting with TPL x86: Add a handoff header file x86: broadwell: Improve SDRAM debugging output x86: broadwell: Allow SDRAM init from SPL x86: Move init of debug UART to cpu.c x86: broadwell: Split CPU init x86: Add support for starting from SPL/TPL x86: Allow 16-bit init to be in TPL x86: broadwell: Allow booting from SPL x86: broadwell: Select refcode and CPU code for SPL x86: Add common Intel code for SPL x86: Support saving MRC data from SPL x86: Add a simple TPL implementations x86: mrccache: Add more debugging x86: Add a sysreset driver for the Intel PCH x86: Support TPL in Intel common code x86: Don't set up MTRRs in SPL x86: Don't generate a bootstage report in SPL x86: Support PCI VGA ROM when TPL is used x86: sysreset: Implement the get_last() method x86: Add documention on the samus flashmap x86: samus: Update device tree for SPL x86: samus: Update device tree for verified boot x86: Update device tree for TPL x86: Update device tree for Chromium OS verified boot x86: Fix device-tree indentation x86: samus: Add a target to boot through TPL
Just checking if you have any comments on this series?
Regards, Simon

Hi Simon,
On Tue, Feb 12, 2019 at 11:31 PM Simon Glass sjg@chromium.org wrote:
Hi Bin,
On Wed, 30 Jan 2019 at 04:59, Simon Glass sjg@chromium.org wrote:
At present SPL is used on 64-bit platforms, to allow SPL to be built as a 32-bit program and U-Boot proper to be built as 64-bit.
However it is useful to be able to use SPL on any x86 platform, where U-Boot needs to be updated in the field. Then SPL can select which U-Boot to run (A or B) and most of the code can be updated. Similarly, using TPL allows both SPL and U-Boot to be updated. This is the best approach, since it means that all of U-Boot proper as well as SPL (in particular SDRAM init) can be updated in the field. This provides for the smallest possible amount of read-only (non-updateable) code: just the TPL code.
This series contains a number of changes to allow x86 boards to use TPL, SPL and U-Boot proper. As a test, it is enabled for samus with a new chromebook_samus_tpl board.
Simon Glass (40): binman: Don't generate an error in 'text' entry constructor binman: Don't show image-skip message by default binman: Add a missing comment in Entry_vblock dm: core: Fix translate condition in ofnode_get_addr_size() cros_ec: Use a hyphen in the uclass name spl: Allow sandbox to build a device-tree file RFC: binman: Allow sections to have an offset x86: start64: Fix copyright message x86: mp_init: Use proper error numbers x86: Add a way to reinit the cpu x86: dts: Add device-tree labels for rtc and reset x86: Update a stale comment about ifdtool x86: Support SPL and TPL x86: Support booting with TPL x86: Add a handoff header file x86: broadwell: Improve SDRAM debugging output x86: broadwell: Allow SDRAM init from SPL x86: Move init of debug UART to cpu.c x86: broadwell: Split CPU init x86: Add support for starting from SPL/TPL x86: Allow 16-bit init to be in TPL x86: broadwell: Allow booting from SPL x86: broadwell: Select refcode and CPU code for SPL x86: Add common Intel code for SPL x86: Support saving MRC data from SPL x86: Add a simple TPL implementations x86: mrccache: Add more debugging x86: Add a sysreset driver for the Intel PCH x86: Support TPL in Intel common code x86: Don't set up MTRRs in SPL x86: Don't generate a bootstage report in SPL x86: Support PCI VGA ROM when TPL is used x86: sysreset: Implement the get_last() method x86: Add documention on the samus flashmap x86: samus: Update device tree for SPL x86: samus: Update device tree for verified boot x86: Update device tree for TPL x86: Update device tree for Chromium OS verified boot x86: Fix device-tree indentation x86: samus: Add a target to boot through TPL
Just checking if you have any comments on this series?
Sorry for the long delay due to Chinese new year holiday vacation. I will look at this series soon (in fact I started reviewing the sound series yesterday)
Regards, Bin
participants (2)
-
Bin Meng
-
Simon Glass