[U-Boot] [PATCH v2 00/50] 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.
Changes in v2: - Update commit message to mention dropping the \n - Update testSelectImage() to test in normal and verbose modes - Update the commit message to explain the implications on aliases - Add a better explanation of the logic change, in the commit message - Fix map output when section offset is not set (make it 0) - Add a test for sections with offsets - Update the comment in fsp_cap.S too - Update commit message to make it clear this patch is just for broadwell - Bring in sdram_console_tx_byte() to allow debugging - Add xorl to TPL code also - Update comments in start_from_tpl to correctly explain SPL state - Add new patch to separate out the EFI code in sysreset - Add new patch to add an ioctl to read power-management info - Add new patch to implement PCH_REQ_PMBASE_INFO on ivybridge - Add new patch to implement PCH_REQ_PMBASE_INFO on broadwell - Add new patch to implement power-off if available - Add new patch to enable the RTC in Kconfig - Add a new patch to update PCH to work in TPL - Add a new patch allowing jumping from TPL to SPL - Sort defconfig and adjust it to build after rebase on maste
Simon Glass (50): 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 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 implementation x86: mrccache: Add more debugging x86: sysreset: Separate out the EFI code x86: pch: Add an ioctl to read power-management info x86: ivybridge: Implement PCH_REQ_PMBASE_INFO x86: broadwell: Implement PCH_REQ_PMBASE_INFO x86: sysreset: Implement power-off if available 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: Increase the pre-reloc memory again Revert "pci: Scale MAX_PCI_REGIONS based on CONFIG_NR_DRAM_BANKS" x86: Enable the RTC on all boards x86: Update the memory map a little x86: broadwell: Update PCH to work in TPL x86: Add a way to jump from TPL to SPL x86: samus: Add a target to boot through TPL
Makefile | 1 + arch/Kconfig | 32 + arch/x86/Kconfig | 10 +- arch/x86/Makefile | 16 +- arch/x86/cpu/Makefile | 15 +- 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 | 100 ++++ arch/x86/cpu/broadwell/pch.c | 37 +- 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/ivybridge/bd82x6x.c | 15 + arch/x86/cpu/mp_init.c | 10 +- arch/x86/cpu/start.S | 13 + arch/x86/cpu/start64.S | 2 +- arch/x86/cpu/start_from_spl.S | 71 +++ arch/x86/cpu/start_from_tpl.S | 49 ++ 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/fsp/fsp_car.S | 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_link_defconfig | 1 + configs/chromebook_samus_defconfig | 2 +- configs/chromebook_samus_tpl_defconfig | 81 +++ doc/README.x86 | 16 + drivers/core/ofnode.c | 2 +- drivers/misc/cros_ec.c | 2 +- drivers/pci/pci_rom.c | 2 +- drivers/sysreset/sysreset_x86.c | 104 +++- include/configs/chromebook_link.h | 3 - include/configs/chromebook_samus.h | 3 + include/configs/qemu-x86.h | 3 - include/configs/x86-common.h | 1 - include/pch.h | 18 + include/pci.h | 6 +- scripts/Makefile.spl | 24 +- tools/binman/README | 7 + tools/binman/bsection.py | 9 +- tools/binman/control.py | 4 +- tools/binman/etype/section.py | 3 +- tools/binman/etype/text.py | 4 +- tools/binman/etype/vblock.py | 1 + tools/binman/ftest.py | 44 +- tools/binman/test/101_sections_offset.dts | 35 ++ 65 files changed, 2066 insertions(+), 980 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 tools/binman/test/101_sections_offset.dts

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 Reviewed-by: Bin Meng bmeng.cn@gmail.com ---
Changes in v2: None
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 6e99819487f..c4aa510a87b 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 Fri, Apr 26, 2019 at 11:59 AM 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 Reviewed-by: Bin Meng bmeng.cn@gmail.com
Changes in v2: None
tools/binman/etype/text.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
applied to u-boot-x86, thanks!

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.
Also drop the unnecessary extra newline on this message, which causes two line breaks.
Signed-off-by: Simon Glass sjg@chromium.org ---
Changes in v2: - Update commit message to mention dropping the \n - Update testSelectImage() to test in normal and verbose modes
tools/binman/control.py | 4 ++-- tools/binman/ftest.py | 26 +++++++++++++++++++------- 2 files changed, 21 insertions(+), 9 deletions(-)
diff --git a/tools/binman/control.py b/tools/binman/control.py index 3446e2e79c5..b32e4e1996f 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)
diff --git a/tools/binman/ftest.py b/tools/binman/ftest.py index e77fce5a26f..75658c9a366 100644 --- a/tools/binman/ftest.py +++ b/tools/binman/ftest.py @@ -187,7 +187,8 @@ class TestFunctional(unittest.TestCase): return control.Binman(options, args)
def _DoTestFile(self, fname, debug=False, map=False, update_dtb=False, - entry_args=None, images=None, use_real_dtb=False): + entry_args=None, images=None, use_real_dtb=False, + verbosity=None): """Run binman with a given test file
Args: @@ -210,6 +211,8 @@ class TestFunctional(unittest.TestCase): args.append('-up') if not use_real_dtb: args.append('--fake-dtb') + if verbosity is not None: + args.append('-v%d' % verbosity) if entry_args: for arg, value in entry_args.iteritems(): args.append('-a%s=%s' % (arg, value)) @@ -1459,13 +1462,22 @@ class TestFunctional(unittest.TestCase):
def testSelectImage(self): """Test that we can select which images to build""" - with test_util.capture_sys_output() as (stdout, stderr): - retcode = self._DoTestFile('006_dual_image.dts', images=['image2']) - self.assertEqual(0, retcode) - self.assertIn('Skipping images: image1', stdout.getvalue()) + expected = 'Skipping images: image1' + + # We should only get the expected message in verbose mode + for verbosity in (None, 2): + with test_util.capture_sys_output() as (stdout, stderr): + retcode = self._DoTestFile('006_dual_image.dts', + verbosity=verbosity, + images=['image2']) + self.assertEqual(0, retcode) + if verbosity: + self.assertIn(expected, stdout.getvalue()) + else: + self.assertNotIn(expected, stdout.getvalue())
- self.assertFalse(os.path.exists(tools.GetOutputFilename('image1.bin'))) - self.assertTrue(os.path.exists(tools.GetOutputFilename('image2.bin'))) + self.assertFalse(os.path.exists(tools.GetOutputFilename('image1.bin'))) + self.assertTrue(os.path.exists(tools.GetOutputFilename('image2.bin')))
def testUpdateFdtAll(self): """Test that all device trees are updated with offset/size info"""

On Fri, Apr 26, 2019 at 11:59 AM 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.
Also drop the unnecessary extra newline on this message, which causes two line breaks.
Signed-off-by: Simon Glass sjg@chromium.org
Changes in v2:
- Update commit message to mention dropping the \n
- Update testSelectImage() to test in normal and verbose modes
tools/binman/control.py | 4 ++-- tools/binman/ftest.py | 26 +++++++++++++++++++------- 2 files changed, 21 insertions(+), 9 deletions(-)
Reviewed-by: Bin Meng bmeng.cn@gmail.com

On Wed, May 1, 2019 at 7:59 PM Bin Meng bmeng.cn@gmail.com wrote:
On Fri, Apr 26, 2019 at 11:59 AM 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.
Also drop the unnecessary extra newline on this message, which causes two line breaks.
Signed-off-by: Simon Glass sjg@chromium.org
Changes in v2:
- Update commit message to mention dropping the \n
- Update testSelectImage() to test in normal and verbose modes
tools/binman/control.py | 4 ++-- tools/binman/ftest.py | 26 +++++++++++++++++++------- 2 files changed, 21 insertions(+), 9 deletions(-)
Reviewed-by: Bin Meng bmeng.cn@gmail.com
applied to u-boot-x86, thanks!

An important property is missing. Update the entry comment to include this.
Signed-off-by: Simon Glass sjg@chromium.org Reviewed-by: Bin Meng bmeng.cn@gmail.com ---
Changes in v2: None
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 c4d970ed160..334ff9f966a 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 Fri, Apr 26, 2019 at 11:59 AM 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 Reviewed-by: Bin Meng bmeng.cn@gmail.com
Changes in v2: None
tools/binman/etype/vblock.py | 1 + 1 file changed, 1 insertion(+)
applied to u-boot-x86, thanks!

Update the condition to translate only if this is enabled for SPL.
Signed-off-by: Simon Glass sjg@chromium.org Reviewed-by: Bin Meng bmeng.cn@gmail.com ---
Changes in v2: None
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 785f5c3acf7..cc0c031e0d7 100644 --- a/drivers/core/ofnode.c +++ b/drivers/core/ofnode.c @@ -546,7 +546,7 @@ fdt_addr_t ofnode_get_addr_size(ofnode node, const char *property, ns = of_n_size_cells(np); *sizep = of_read_number(prop + na, ns);
- if (IS_ENABLED(CONFIG_OF_TRANSLATE) && ns > 0) + if (CONFIG_IS_ENABLED(OF_TRANSLATE) && ns > 0) return of_translate_address(np, prop); else return of_read_number(prop, na);

On Fri, Apr 26, 2019 at 11:59 AM 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 Reviewed-by: Bin Meng bmeng.cn@gmail.com
Changes in v2: None
drivers/core/ofnode.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
applied to u-boot-x86, thanks!

Device-tree rules require that aliases use a hyphen rather than a underscore. Update the uclass name to fit with this.
This allows device-tree aliases to be used to refer to cros-ec devices, for example:
aliases { cros-ec0 = &ec; cros-ec1 = &pd; };
Signed-off-by: Simon Glass sjg@chromium.org ---
Changes in v2: - Update the commit message to explain the implications on aliases
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 565de040fe9..382f8262863 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 Fri, Apr 26, 2019 at 11:59 AM 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.
This allows device-tree aliases to be used to refer to cros-ec devices, for example:
aliases { cros-ec0 = &ec; cros-ec1 = &pd; };
Thanks for adding the explanation here. But I was wondering since this is required by DT rules for the aliases node, do we have to require all UCLASS_DRIVERs to have name with hyphen instead of underscore?
Signed-off-by: Simon Glass sjg@chromium.org
Changes in v2:
- Update the commit message to explain the implications on aliases
drivers/misc/cros_ec.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
Regards, Bin

Hi Bin,
On Wed, 1 May 2019 at 06:00, Bin Meng bmeng.cn@gmail.com wrote:
Hi Simon,
On Fri, Apr 26, 2019 at 11:59 AM 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.
This allows device-tree aliases to be used to refer to cros-ec devices, for example:
aliases { cros-ec0 = &ec; cros-ec1 = &pd; };
Thanks for adding the explanation here. But I was wondering since this is required by DT rules for the aliases node, do we have to require all UCLASS_DRIVERs to have name with hyphen instead of underscore?
It might be good to have this rule, in case people want to use aliases.
Regards, Simon

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.
Note that the new logic is not quite the same as the old logic. It was previously assumed that checking for:
$(CONFIG_$(SPL_TPL_)OF_CONTROL) $(CONFIG_OF_SEPARATE) $(CONFIG_$(SPL_TPL_)OF_PLATDATA)
producing 'yy' meant that the first two were 'y' and the last was empty. Strictly speaking it would be possible for any two of the three to be 'y' and still yield the same result. However, that was not the intention of the new logic, since OF_PLATDATA always ensures that no device-tree file is included. So in effect the new logic is the same, with the addition of OF_HOSTFILE as an option for OP_SEPARATE.
Signed-off-by: Simon Glass sjg@chromium.org ---
Changes in v2: - Add a better explanation of the logic change, in the commit message
scripts/Makefile.spl | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-)
diff --git a/scripts/Makefile.spl b/scripts/Makefile.spl index 56dbbe127ba..8d76a2d4007 100644 --- a/scripts/Makefile.spl +++ b/scripts/Makefile.spl @@ -253,8 +253,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

On Fri, Apr 26, 2019 at 11:59 AM 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.
Note that the new logic is not quite the same as the old logic. It was previously assumed that checking for:
$(CONFIG_$(SPL_TPL_)OF_CONTROL) $(CONFIG_OF_SEPARATE) $(CONFIG_$(SPL_TPL_)OF_PLATDATA)
producing 'yy' meant that the first two were 'y' and the last was empty. Strictly speaking it would be possible for any two of the three to be 'y' and still yield the same result. However, that was not the intention of the new logic, since OF_PLATDATA always ensures that no device-tree file is included. So in effect the new logic is the same, with the addition of OF_HOSTFILE as an option for OP_SEPARATE.
Signed-off-by: Simon Glass sjg@chromium.org
Changes in v2:
- Add a better explanation of the logic change, in the commit message
scripts/Makefile.spl | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-)
Reviewed-by: Bin Meng bmeng.cn@gmail.com

On Wed, May 1, 2019 at 8:13 PM Bin Meng bmeng.cn@gmail.com wrote:
On Fri, Apr 26, 2019 at 11:59 AM 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.
Note that the new logic is not quite the same as the old logic. It was previously assumed that checking for:
$(CONFIG_$(SPL_TPL_)OF_CONTROL) $(CONFIG_OF_SEPARATE) $(CONFIG_$(SPL_TPL_)OF_PLATDATA)
producing 'yy' meant that the first two were 'y' and the last was empty. Strictly speaking it would be possible for any two of the three to be 'y' and still yield the same result. However, that was not the intention of the new logic, since OF_PLATDATA always ensures that no device-tree file is included. So in effect the new logic is the same, with the addition of OF_HOSTFILE as an option for OP_SEPARATE.
Signed-off-by: Simon Glass sjg@chromium.org
Changes in v2:
- Add a better explanation of the logic change, in the commit message
scripts/Makefile.spl | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-)
Reviewed-by: Bin Meng bmeng.cn@gmail.com
applied to u-boot-x86, thanks!

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.
Signed-off-by: Simon Glass sjg@chromium.org ---
Changes in v2: - Fix map output when section offset is not set (make it 0) - Add a test for sections with offsets
tools/binman/README | 7 +++++ tools/binman/bsection.py | 9 +++--- tools/binman/etype/section.py | 3 +- tools/binman/ftest.py | 18 ++++++++++++ tools/binman/test/101_sections_offset.dts | 35 +++++++++++++++++++++++ 5 files changed, 67 insertions(+), 5 deletions(-) create mode 100644 tools/binman/test/101_sections_offset.dts
diff --git a/tools/binman/README b/tools/binman/README index 04ed2b799c8..927fa856acf 100644 --- a/tools/binman/README +++ b/tools/binman/README @@ -342,6 +342,13 @@ size: Sets the image size in bytes, for example 'size = <0x100000>' for a 1MB image.
+offset: + This is similar to 'offset' in entries, setting the offset of a section + within the image or section containing it. The first byte of the section + is normally at offset 0. If 'offset' is not provided, binman sets it to + the end of the previous region, or the start of the image's entry area + (normally 0) if there is no previous region. + align-size: This sets the alignment of the image size. For example, to ensure that the image ends on a 512-byte boundary, use 'align-size = <512>'. diff --git a/tools/binman/bsection.py b/tools/binman/bsection.py index ccf2920c5bd..0ba542ee987 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: @@ -424,8 +425,8 @@ class Section(object): Args: fd: File to write the map to """ - Entry.WriteMapLine(fd, indent, self._name, self._offset, self._size, - self._image_pos) + Entry.WriteMapLine(fd, indent, self._name, self._offset or 0, + self._size, self._image_pos) for entry in self._entries.values(): entry.WriteMap(fd, indent + 1)
diff --git a/tools/binman/etype/section.py b/tools/binman/etype/section.py index 7f1b4136049..3681a484689 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)
diff --git a/tools/binman/ftest.py b/tools/binman/ftest.py index 75658c9a366..daea1ea1382 100644 --- a/tools/binman/ftest.py +++ b/tools/binman/ftest.py @@ -1783,6 +1783,24 @@ class TestFunctional(unittest.TestCase): data = self._DoReadFile('100_intel_refcode.dts') self.assertEqual(REFCODE_DATA, data[:len(REFCODE_DATA)])
+ def testSectionOffset(self): + """Tests use of a section with an offset""" + data, _, map_data, _ = self._DoReadFileDtb('101_sections_offset.dts', + map=True) + self.assertEqual('''ImagePos Offset Size Name +00000000 00000000 00000038 main-section +00000004 00000004 00000010 section@0 +00000004 00000000 00000004 u-boot +00000018 00000018 00000010 section@1 +00000018 00000000 00000004 u-boot +0000002c 0000002c 00000004 section@2 +0000002c 00000000 00000004 u-boot +''', map_data) + self.assertEqual(data, + 4 * chr(0x26) + U_BOOT_DATA + 12 * chr(0x21) + + 4 * chr(0x26) + U_BOOT_DATA + 12 * chr(0x61) + + 4 * chr(0x26) + U_BOOT_DATA + 8 * chr(0x26)) +
if __name__ == "__main__": unittest.main() diff --git a/tools/binman/test/101_sections_offset.dts b/tools/binman/test/101_sections_offset.dts new file mode 100644 index 00000000000..46708ff9b6b --- /dev/null +++ b/tools/binman/test/101_sections_offset.dts @@ -0,0 +1,35 @@ +// SPDX-License-Identifier: GPL-2.0+ + +/dts-v1/; + +/ { + #address-cells = <1>; + #size-cells = <1>; + + binman { + pad-byte = <0x26>; + size = <0x38>; + section@0 { + read-only; + offset = <0x4>; + size = <0x10>; + pad-byte = <0x21>; + + u-boot { + }; + }; + section@1 { + size = <0x10>; + pad-byte = <0x61>; + offset = <0x18>; + + u-boot { + }; + }; + section@2 { + offset = <0x2c>; + u-boot { + }; + }; + }; +};

On Fri, Apr 26, 2019 at 11:59 AM 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.
Signed-off-by: Simon Glass sjg@chromium.org
Changes in v2:
- Fix map output when section offset is not set (make it 0)
- Add a test for sections with offsets
tools/binman/README | 7 +++++ tools/binman/bsection.py | 9 +++--- tools/binman/etype/section.py | 3 +- tools/binman/ftest.py | 18 ++++++++++++ tools/binman/test/101_sections_offset.dts | 35 +++++++++++++++++++++++ 5 files changed, 67 insertions(+), 5 deletions(-) create mode 100644 tools/binman/test/101_sections_offset.dts
Reviewed-by: Bin Meng bmeng.cn@gmail.com

On Wed, May 1, 2019 at 8:13 PM Bin Meng bmeng.cn@gmail.com wrote:
On Fri, Apr 26, 2019 at 11:59 AM 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.
Signed-off-by: Simon Glass sjg@chromium.org
Changes in v2:
- Fix map output when section offset is not set (make it 0)
- Add a test for sections with offsets
tools/binman/README | 7 +++++ tools/binman/bsection.py | 9 +++--- tools/binman/etype/section.py | 3 +- tools/binman/ftest.py | 18 ++++++++++++ tools/binman/test/101_sections_offset.dts | 35 +++++++++++++++++++++++ 5 files changed, 67 insertions(+), 5 deletions(-) create mode 100644 tools/binman/test/101_sections_offset.dts
Reviewed-by: Bin Meng bmeng.cn@gmail.com
applied to u-boot-x86, thanks!

There is a typo in this header. Fix it.
Signed-off-by: Simon Glass sjg@chromium.org Reviewed-by: Bin Meng bmeng.cn@gmail.com ---
Changes in v2: None
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 a78a3316b6d..7be834788b9 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 Fri, Apr 26, 2019 at 11:59 AM Simon Glass sjg@chromium.org wrote:
There is a typo in this header. Fix it.
Signed-off-by: Simon Glass sjg@chromium.org Reviewed-by: Bin Meng bmeng.cn@gmail.com
Changes in v2: None
arch/x86/cpu/start64.S | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
applied to u-boot-x86, thanks!

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 Reviewed-by: Bin Meng bmeng.cn@gmail.com ---
Changes in v2: None
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 ea64c2ee57e..fefbf8f7282 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 Fri, Apr 26, 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 Reviewed-by: Bin Meng bmeng.cn@gmail.com
Changes in v2: None
arch/x86/cpu/mp_init.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-)
applied to u-boot-x86, thanks!

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 Reviewed-by: Bin Meng bmeng.cn@gmail.com ---
Changes in v2: None
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 3bde44ebf53..90b546e7410 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 6c063e82009..42abb23a9ed 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 670fcdc0093..c252192bf41 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 Fri, Apr 26, 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 Reviewed-by: Bin Meng bmeng.cn@gmail.com
Changes in v2: None
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(-)
applied to u-boot-x86, thanks!

Add labels for these nodes so that board DT files can reference them.
Signed-off-by: Simon Glass sjg@chromium.org Reviewed-by: Bin Meng bmeng.cn@gmail.com ---
Changes in v2: None
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 f979d83757c..555d0dd9608 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 1797e042daf..d0bbd84e509 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 Fri, Apr 26, 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 Reviewed-by: Bin Meng bmeng.cn@gmail.com
Changes in v2: None
arch/x86/dts/reset.dtsi | 2 +- arch/x86/dts/rtc.dtsi | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-)
applied to u-boot-x86, thanks!

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 Reviewed-by: Bin Meng bmeng.cn@gmail.com ---
Changes in v2: - Update the comment in fsp_cap.S too
arch/x86/cpu/intel_common/car.S | 2 +- arch/x86/lib/fsp/fsp_car.S | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/arch/x86/cpu/intel_common/car.S b/arch/x86/cpu/intel_common/car.S index 52a77bb2d18..00308dbdef9 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 */ diff --git a/arch/x86/lib/fsp/fsp_car.S b/arch/x86/lib/fsp/fsp_car.S index 48edc8362a7..8c54cea3db4 100644 --- a/arch/x86/lib/fsp/fsp_car.S +++ b/arch/x86/lib/fsp/fsp_car.S @@ -100,7 +100,7 @@ temp_ram_init_romstack: .long temp_ram_init_params temp_ram_init_params: _dt_ucode_base_size: - /* These next two fields are filled in by ifdtool */ + /* These next two fields are filled in by binman */ .globl ucode_base ucode_base: /* Declared in microcode.h */ .long 0 /* microcode base */

On Fri, Apr 26, 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 Reviewed-by: Bin Meng bmeng.cn@gmail.com
Changes in v2:
- Update the comment in fsp_cap.S too
arch/x86/cpu/intel_common/car.S | 2 +- arch/x86/lib/fsp/fsp_car.S | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-)
applied to u-boot-x86, thanks!

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 Reviewed-by: Bin Meng bmeng.cn@gmail.com ---
Changes in v2: None
arch/Kconfig | 31 +++++++++++++++++++++++++++++++ arch/x86/Kconfig | 1 - 2 files changed, 31 insertions(+), 1 deletion(-)
diff --git a/arch/Kconfig b/arch/Kconfig index 2f3d07c13a1..a1d1ac301d6 100644 --- a/arch/Kconfig +++ b/arch/Kconfig @@ -126,6 +126,8 @@ config SH
config X86 bool "x86 architecture" + select SUPPORT_SPL + select SUPPORT_TPL select CREATE_ARCH_SYMLINK select DM select DM_PCI @@ -164,6 +166,35 @@ config X86 imply USB_HOST_ETHER imply PCH
+ # 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" select CREATE_ARCH_SYMLINK diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig index e0520937751..185f0ef8c40 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 Fri, Apr 26, 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 Reviewed-by: Bin Meng bmeng.cn@gmail.com
Changes in v2: None
arch/Kconfig | 31 +++++++++++++++++++++++++++++++ arch/x86/Kconfig | 1 - 2 files changed, 31 insertions(+), 1 deletion(-)
applied to u-boot-x86, thanks!

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 Reviewed-by: Bin Meng bmeng.cn@gmail.com ---
Changes in v2: None
arch/x86/Kconfig | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-)
diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig index 185f0ef8c40..45a533625a6 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 Fri, Apr 26, 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 Reviewed-by: Bin Meng bmeng.cn@gmail.com
Changes in v2: None
arch/x86/Kconfig | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-)
applied to u-boot-x86, thanks!

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 Reviewed-by: Bin Meng bmeng.cn@gmail.com ---
Changes in v2: None
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 00000000000..4d18d59efed --- /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 Fri, Apr 26, 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 Reviewed-by: Bin Meng bmeng.cn@gmail.com
Changes in v2: None
arch/x86/include/asm/handoff.h | 15 +++++++++++++++ 1 file changed, 15 insertions(+) create mode 100644 arch/x86/include/asm/handoff.h
applied to u-boot-x86, thanks!

Add debugging during SDRAM init so that problems are easier to diagnose.
Signed-off-by: Simon Glass sjg@chromium.org Reviewed-by: Bin Meng bmeng.cn@gmail.com ---
Changes in v2: None
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 03a35bcf73f..1b9f9840c6f 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 Fri, Apr 26, 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 Reviewed-by: Bin Meng bmeng.cn@gmail.com
Changes in v2: None
arch/x86/cpu/broadwell/sdram.c | 32 ++++++++++++++++++++------------ 1 file changed, 20 insertions(+), 12 deletions(-)
applied to u-boot-x86, thanks!

At present, for broadwell, SDRAM is always set up in U-Boot proper since the 64-bit mode (which uses SDRAM init in SPL) is not supported.
Update the code to allow SDRAM init 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. It could later allow us to support 64-bit U-Boot on broadwell.
Signed-off-by: Simon Glass sjg@chromium.org ---
Changes in v2: - Update commit message to make it clear this patch is just for broadwell - Bring in sdram_console_tx_byte() to allow debugging
arch/x86/cpu/broadwell/Makefile | 2 +- arch/x86/cpu/broadwell/northbridge.c | 100 +++++++++++++++++++++++++++ arch/x86/cpu/broadwell/sdram.c | 93 ------------------------- 3 files changed, 101 insertions(+), 94 deletions(-)
diff --git a/arch/x86/cpu/broadwell/Makefile b/arch/x86/cpu/broadwell/Makefile index d3785aabdf2..d464507e6c0 100644 --- a/arch/x86/cpu/broadwell/Makefile +++ b/arch/x86/cpu/broadwell/Makefile @@ -13,4 +13,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 3055880bb77..4bcab785560 100644 --- a/arch/x86/cpu/broadwell/northbridge.c +++ b/arch/x86/cpu/broadwell/northbridge.c @@ -6,8 +6,108 @@ #include <common.h> #include <dm.h> #include <asm/io.h> +#include <asm/mrc_common.h> #include <asm/arch/iomap.h> #include <asm/arch/pch.h> +#include <asm/arch/pei_data.h> + +__weak asmlinkage void sdram_console_tx_byte(unsigned char byte) +{ +#ifdef DEBUG + putc(byte); +#endif +} + +void broadwell_fill_pei_data(struct pei_data *pei_data) +{ + pei_data->pei_version = PEI_VERSION; + pei_data->board_type = BOARD_TYPE_ULT; + pei_data->pciexbar = MCFG_BASE_ADDRESS; + pei_data->smbusbar = SMBUS_BASE_ADDRESS; + pei_data->ehcibar = EARLY_EHCI_BAR; + pei_data->xhcibar = EARLY_XHCI_BAR; + pei_data->gttbar = EARLY_GTT_BAR; + pei_data->pmbase = ACPI_BASE_ADDRESS; + pei_data->gpiobase = GPIO_BASE_ADDRESS; + pei_data->tseg_size = CONFIG_SMM_TSEG_SIZE; + pei_data->temp_mmio_base = EARLY_TEMP_MMIO; + pei_data->tx_byte = sdram_console_tx_byte; + pei_data->ddr_refresh_2x = 1; +} + +static void pei_data_usb2_port(struct pei_data *pei_data, int port, uint length, + uint enable, uint oc_pin, uint location) +{ + pei_data->usb2_ports[port].length = length; + pei_data->usb2_ports[port].enable = enable; + pei_data->usb2_ports[port].oc_pin = oc_pin; + pei_data->usb2_ports[port].location = location; +} + +static void pei_data_usb3_port(struct pei_data *pei_data, int port, uint enable, + uint oc_pin, uint fixed_eq) +{ + pei_data->usb3_ports[port].enable = enable; + pei_data->usb3_ports[port].oc_pin = oc_pin; + pei_data->usb3_ports[port].fixed_eq = fixed_eq; +} + +void mainboard_fill_pei_data(struct pei_data *pei_data) +{ + /* DQ byte map for Samus board */ + const u8 dq_map[2][6][2] = { + { { 0x0F, 0xF0 }, { 0x00, 0xF0 }, { 0x0F, 0xF0 }, + { 0x0F, 0x00 }, { 0xFF, 0x00 }, { 0xFF, 0x00 } }, + { { 0x0F, 0xF0 }, { 0x00, 0xF0 }, { 0x0F, 0xF0 }, + { 0x0F, 0x00 }, { 0xFF, 0x00 }, { 0xFF, 0x00 } } }; + /* DQS CPU<>DRAM map for Samus board */ + const u8 dqs_map[2][8] = { + { 2, 0, 1, 3, 6, 4, 7, 5 }, + { 2, 1, 0, 3, 6, 5, 4, 7 } }; + + pei_data->ec_present = 1; + + /* One installed DIMM per channel */ + pei_data->dimm_channel0_disabled = 2; + pei_data->dimm_channel1_disabled = 2; + + memcpy(pei_data->dq_map, dq_map, sizeof(dq_map)); + memcpy(pei_data->dqs_map, dqs_map, sizeof(dqs_map)); + + /* P0: HOST PORT */ + pei_data_usb2_port(pei_data, 0, 0x0080, 1, 0, + USB_PORT_BACK_PANEL); + /* P1: HOST PORT */ + pei_data_usb2_port(pei_data, 1, 0x0080, 1, 1, + USB_PORT_BACK_PANEL); + /* P2: RAIDEN */ + pei_data_usb2_port(pei_data, 2, 0x0080, 1, USB_OC_PIN_SKIP, + USB_PORT_BACK_PANEL); + /* P3: SD CARD */ + pei_data_usb2_port(pei_data, 3, 0x0040, 1, USB_OC_PIN_SKIP, + USB_PORT_INTERNAL); + /* P4: RAIDEN */ + pei_data_usb2_port(pei_data, 4, 0x0080, 1, USB_OC_PIN_SKIP, + USB_PORT_BACK_PANEL); + /* P5: WWAN (Disabled) */ + pei_data_usb2_port(pei_data, 5, 0x0000, 0, USB_OC_PIN_SKIP, + USB_PORT_SKIP); + /* P6: CAMERA */ + pei_data_usb2_port(pei_data, 6, 0x0040, 1, USB_OC_PIN_SKIP, + USB_PORT_INTERNAL); + /* P7: BT */ + pei_data_usb2_port(pei_data, 7, 0x0040, 1, USB_OC_PIN_SKIP, + USB_PORT_INTERNAL); + + /* P1: HOST PORT */ + pei_data_usb3_port(pei_data, 0, 1, 0, 0); + /* P2: HOST PORT */ + pei_data_usb3_port(pei_data, 1, 1, 1, 0); + /* P3: RAIDEN */ + pei_data_usb3_port(pei_data, 2, 1, USB_OC_PIN_SKIP, 0); + /* P4: RAIDEN */ + pei_data_usb3_port(pei_data, 3, 1, USB_OC_PIN_SKIP, 0); +}
static int broadwell_northbridge_early_init(struct udevice *dev) { diff --git a/arch/x86/cpu/broadwell/sdram.c b/arch/x86/cpu/broadwell/sdram.c index 1b9f9840c6f..b8450cc9d29 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) { /*

On Fri, Apr 26, 2019 at 12:00 PM Simon Glass sjg@chromium.org wrote:
At present, for broadwell, SDRAM is always set up in U-Boot proper since the 64-bit mode (which uses SDRAM init in SPL) is not supported.
Update the code to allow SDRAM init 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. It could later allow us to support 64-bit U-Boot on broadwell.
Signed-off-by: Simon Glass sjg@chromium.org
Changes in v2:
- Update commit message to make it clear this patch is just for broadwell
- Bring in sdram_console_tx_byte() to allow debugging
arch/x86/cpu/broadwell/Makefile | 2 +- arch/x86/cpu/broadwell/northbridge.c | 100 +++++++++++++++++++++++++++ arch/x86/cpu/broadwell/sdram.c | 93 ------------------------- 3 files changed, 101 insertions(+), 94 deletions(-)
Reviewed-by: Bin Meng bmeng.cn@gmail.com

On Wed, May 1, 2019 at 9:03 PM Bin Meng bmeng.cn@gmail.com wrote:
On Fri, Apr 26, 2019 at 12:00 PM Simon Glass sjg@chromium.org wrote:
At present, for broadwell, SDRAM is always set up in U-Boot proper since the 64-bit mode (which uses SDRAM init in SPL) is not supported.
Update the code to allow SDRAM init 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. It could later allow us to support 64-bit U-Boot on broadwell.
Signed-off-by: Simon Glass sjg@chromium.org
Changes in v2:
- Update commit message to make it clear this patch is just for broadwell
- Bring in sdram_console_tx_byte() to allow debugging
arch/x86/cpu/broadwell/Makefile | 2 +- arch/x86/cpu/broadwell/northbridge.c | 100 +++++++++++++++++++++++++++ arch/x86/cpu/broadwell/sdram.c | 93 ------------------------- 3 files changed, 101 insertions(+), 94 deletions(-)
Reviewed-by: Bin Meng bmeng.cn@gmail.com
applied to u-boot-x86, thanks!

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 Reviewed-by: Bin Meng bmeng.cn@gmail.com ---
Changes in v2: None
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 232fa40eb53..d53c7b863fb 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 b8450cc9d29..b31d78c092a 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 Fri, Apr 26, 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 Reviewed-by: Bin Meng bmeng.cn@gmail.com
Changes in v2: None
arch/x86/cpu/broadwell/cpu.c | 13 +++++++++++++ arch/x86/cpu/broadwell/sdram.c | 11 ----------- 2 files changed, 13 insertions(+), 11 deletions(-)
applied to u-boot-x86, thanks!

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 Reviewed-by: Bin Meng bmeng.cn@gmail.com ---
Changes in v2: None
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 d464507e6c0..8553615f67b 100644 --- a/arch/x86/cpu/broadwell/Makefile +++ b/arch/x86/cpu/broadwell/Makefile @@ -4,6 +4,7 @@
obj-y += adsp.o 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 d53c7b863fb..bb7c3614081 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 00000000000..c1db1845498 --- /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 Fri, Apr 26, 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 Reviewed-by: Bin Meng bmeng.cn@gmail.com
Changes in v2: None
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
applied to u-boot-x86, thanks!

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 ---
Changes in v2: - Add xorl to TPL code also - Update comments in start_from_tpl to correctly explain SPL state
arch/x86/Makefile | 12 ++++++ arch/x86/cpu/Makefile | 15 +++++++- arch/x86/cpu/start_from_spl.S | 71 +++++++++++++++++++++++++++++++++++ arch/x86/cpu/start_from_tpl.S | 49 ++++++++++++++++++++++++ 4 files changed, 146 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 fec14847cc5..9fd6cf2d3bb 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 54668aab240..85fd5e616ea 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 00000000000..4d4e5d0758d --- /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 00000000000..44b5363a685 --- /dev/null +++ b/arch/x86/cpu/start_from_tpl.S @@ -0,0 +1,49 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ +/* + * 32-bit x86 Startup Code when running from TPL + * + * Copyright 2018 Google, Inc + * Written by Simon Glass sjg@chromium.org + */ + +#include <config.h> + +.section .text.start +.code32 +.globl _start +.type _start, @function +_start: + /* Set up memory using the existing stack */ + mov %esp, %eax + call board_init_f_alloc_reserve + mov %eax, %esp + + call board_init_f_init_reserve + + xorl %eax, %eax + call board_init_f + call board_init_f_r + + /* Should not return here */ + jmp . + +.globl board_init_f_r_trampoline +.type board_init_f_r_trampoline, @function +board_init_f_r_trampoline: + /* + * TPL has been executed: SDRAM has been initialised, BSS has been + * cleared. + * + * %eax = Address of top of new stack + */ + + /* Stack grows down from top of SDRAM */ + movl %eax, %esp + + /* Re-enter SPL by calling board_init_f_r() */ + call board_init_f_r + +die: + hlt + jmp die + hlt

On Fri, Apr 26, 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
Changes in v2:
- Add xorl to TPL code also
- Update comments in start_from_tpl to correctly explain SPL state
arch/x86/Makefile | 12 ++++++ arch/x86/cpu/Makefile | 15 +++++++- arch/x86/cpu/start_from_spl.S | 71 +++++++++++++++++++++++++++++++++++ arch/x86/cpu/start_from_tpl.S | 49 ++++++++++++++++++++++++ 4 files changed, 146 insertions(+), 1 deletion(-) create mode 100644 arch/x86/cpu/start_from_spl.S create mode 100644 arch/x86/cpu/start_from_tpl.S
Reviewed-by: Bin Meng bmeng.cn@gmail.com

On Wed, May 1, 2019 at 9:03 PM Bin Meng bmeng.cn@gmail.com wrote:
On Fri, Apr 26, 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
Changes in v2:
- Add xorl to TPL code also
- Update comments in start_from_tpl to correctly explain SPL state
arch/x86/Makefile | 12 ++++++ arch/x86/cpu/Makefile | 15 +++++++- arch/x86/cpu/start_from_spl.S | 71 +++++++++++++++++++++++++++++++++++ arch/x86/cpu/start_from_tpl.S | 49 ++++++++++++++++++++++++ 4 files changed, 146 insertions(+), 1 deletion(-) create mode 100644 arch/x86/cpu/start_from_spl.S create mode 100644 arch/x86/cpu/start_from_tpl.S
Reviewed-by: Bin Meng bmeng.cn@gmail.com
applied to u-boot-x86, thanks!

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 Reviewed-by: Bin Meng bmeng.cn@gmail.com ---
Changes in v2: None
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 f2c7bb6041a..56497e4afe5 100644 --- a/Makefile +++ b/Makefile @@ -1380,6 +1380,7 @@ cmd_ldr = $(LD) $(LDFLAGS_$(@F)) \
u-boot.rom: u-boot-x86-16bit.bin u-boot.bin \ $(if $(CONFIG_SPL_X86_16BIT_INIT),spl/u-boot-spl.bin) \ + $(if $(CONFIG_TPL_X86_16BIT_INIT),tpl/u-boot-tpl.bin) \ $(if $(CONFIG_HAVE_REFCODE),refcode.bin) FORCE $(call if_changed,binman)
diff --git a/arch/x86/Makefile b/arch/x86/Makefile index 9fd6cf2d3bb..f1afc74fff8 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 bf798c287f3..80fbc7ab661 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 4e656dc4e5a..f20c0b810d3 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 8d76a2d4007..7af6b120b6c 100644 --- a/scripts/Makefile.spl +++ b/scripts/Makefile.spl @@ -228,7 +228,11 @@ ifeq ($(CONFIG_SYS_SOC),"at91") ALL-y += $(obj)/boot.bin endif
+ifdef CONFIG_TPL_BUILD +ALL-$(CONFIG_TPL_X86_16BIT_INIT) += $(obj)/u-boot-x86-16bit-tpl.bin +else ALL-$(CONFIG_SPL_X86_16BIT_INIT) += $(obj)/u-boot-x86-16bit-spl.bin +endif
ALL-$(CONFIG_ARCH_ZYNQ) += $(obj)/boot.bin ALL-$(CONFIG_ARCH_ZYNQMP) += $(obj)/boot.bin @@ -328,7 +332,7 @@ quiet_cmd_objcopy = OBJCOPY $@ cmd_objcopy = $(OBJCOPY) $(OBJCOPYFLAGS) $(OBJCOPYFLAGS_$(@F)) $< $@
OBJCOPYFLAGS_$(SPL_BIN)-nodtb.bin = $(SPL_OBJCFLAGS) -O binary \ - $(if $(CONFIG_SPL_X86_16BIT_INIT),-R .start16 -R .resetvec) + $(if $(CONFIG_$(SPL_TPL_)X86_16BIT_INIT),-R .start16 -R .resetvec)
$(obj)/$(SPL_BIN)-nodtb.bin: $(obj)/$(SPL_BIN) FORCE $(call if_changed,objcopy) @@ -337,6 +341,10 @@ OBJCOPYFLAGS_u-boot-x86-16bit-spl.bin := -O binary -j .start16 -j .resetvec $(obj)/u-boot-x86-16bit-spl.bin: $(obj)/u-boot-spl FORCE $(call if_changed,objcopy)
+OBJCOPYFLAGS_u-boot-x86-16bit-tpl.bin := -O binary -j .start16 -j .resetvec +$(obj)/u-boot-x86-16bit-tpl.bin: $(obj)/u-boot-tpl FORCE + $(call if_changed,objcopy) + LDFLAGS_$(SPL_BIN) += -T u-boot-spl.lds $(LDFLAGS_FINAL)
# Avoid 'Not enough room for program headers' error on binutils 2.28 onwards.

On Fri, Apr 26, 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 Reviewed-by: Bin Meng bmeng.cn@gmail.com
Changes in v2: None
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(-)
applied to u-boot-x86, thanks!

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 Reviewed-by: Bin Meng bmeng.cn@gmail.com ---
Changes in v2: None
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 8553615f67b..fbc778cda5f 100644 --- a/arch/x86/cpu/broadwell/Makefile +++ b/arch/x86/cpu/broadwell/Makefile @@ -5,6 +5,21 @@ obj-y += adsp.o 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 00000000000..c3d4a8d5477 --- /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 Fri, Apr 26, 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 Reviewed-by: Bin Meng bmeng.cn@gmail.com
Changes in v2: None
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
applied to u-boot-x86, thanks!

Allow broadwell to build for SPL and include the reference code.
Signed-off-by: Simon Glass sjg@chromium.org Reviewed-by: Bin Meng bmeng.cn@gmail.com ---
Changes in v2: None
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 fbc778cda5f..52d56c65be8 100644 --- a/arch/x86/cpu/broadwell/Makefile +++ b/arch/x86/cpu/broadwell/Makefile @@ -3,13 +3,14 @@ # Copyright (c) 2016 Google, Inc
obj-y += adsp.o -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 @@ -27,6 +28,6 @@ obj-y += northbridge.o obj-y += pch.o obj-y += pinctrl_broadwell.o obj-y += power_state.o -obj-y += refcode.o +obj-$(CONFIG_$(SPL_TPL_)X86_32BIT_INIT) += refcode.o obj-y += sata.o obj-$(CONFIG_$(SPL_TPL_)X86_32BIT_INIT) += sdram.o

On Fri, Apr 26, 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 Reviewed-by: Bin Meng bmeng.cn@gmail.com
Changes in v2: None
arch/x86/cpu/broadwell/Makefile | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-)
applied to u-boot-x86, thanks!

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 Reviewed-by: Bin Meng bmeng.cn@gmail.com ---
Changes in v2: None
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 80fbc7ab661..57cca0b930c 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 00000000000..a6233c75ce2 --- /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 Fri, Apr 26, 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 Reviewed-by: Bin Meng bmeng.cn@gmail.com
Changes in v2: None
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
applied to u-boot-x86, thanks!

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 Reviewed-by: Bin Meng bmeng.cn@gmail.com ---
Changes in v2: None
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 04783cd3292..40fda856ff4 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 2a8919885b7..f37a732a45c 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 Fri, Apr 26, 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 Reviewed-by: Bin Meng bmeng.cn@gmail.com
Changes in v2: None
arch/x86/include/asm/mrccache.h | 11 ++++++++++ arch/x86/lib/mrccache.c | 36 ++++++++++++++++++++++++--------- 2 files changed, 38 insertions(+), 9 deletions(-)
applied to u-boot-x86, thanks!

Add the required CPU code so that TPL builds correctly. Also update the SPL code to deal with being booted from TPL.
Reviewed-by: Bin Meng bmeng.cn@gmail.com Signed-off-by: Simon Glass sjg@chromium.org ---
Changes in v2: None
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 8cf59d14e7c..27432b28979 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 56fd680033b..436252dd831 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 7d290740bfa..5d5d1a9ca74 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 00000000000..492a2d65216 --- /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 ee546d8f893..f59ed8e28b1 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 4b9ddd6f258..59206fb24b1 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 Fri, Apr 26, 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.
Reviewed-by: Bin Meng bmeng.cn@gmail.com Signed-off-by: Simon Glass sjg@chromium.org
Changes in v2: None
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
This patch does not apply cleanly.
Applying: x86: Add a simple TPL implementation error: patch failed: include/configs/chromebook_link.h:20 error: include/configs/chromebook_link.h: patch does not apply error: patch failed: include/configs/qemu-x86.h:37 error: include/configs/qemu-x86.h: patch does not apply Patch failed at 0001 x86: Add a simple TPL implementation
Regards, Bin

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 Reviewed-by: Bin Meng bmeng.cn@gmail.com ---
Changes in v2: None
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 f37a732a45c..be107627b80 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 Fri, Apr 26, 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.
Signed-off-by: Simon Glass sjg@chromium.org Reviewed-by: Bin Meng bmeng.cn@gmail.com
Changes in v2: None
arch/x86/lib/mrccache.c | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-)
applied to u-boot-x86, thanks!

The EFI implementation of reset sits inside the driver and is called directly from outside the driver, breaking the normal driver-model conventions. Worse, it passed NULL as the device pointer, hoping that the called function won't use it, which breaks as soon as code is added to use it.
Separate out the implementation to improve the situation enough to allow a future patch to add new sysreset features.
Signed-off-by: Simon Glass sjg@chromium.org ---
Changes in v2: - Add new patch to separate out the EFI code in sysreset
drivers/sysreset/sysreset_x86.c | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-)
diff --git a/drivers/sysreset/sysreset_x86.c b/drivers/sysreset/sysreset_x86.c index 009f3766027..d484ec5de49 100644 --- a/drivers/sysreset/sysreset_x86.c +++ b/drivers/sysreset/sysreset_x86.c @@ -12,8 +12,7 @@ #include <asm/processor.h> #include <efi_loader.h>
-static __efi_runtime int x86_sysreset_request(struct udevice *dev, - enum sysreset_t type) +static int x86_sysreset_request(struct udevice *dev, enum sysreset_t type) { int value;
@@ -39,11 +38,18 @@ void __efi_runtime EFIAPI efi_reset_system( efi_status_t reset_status, unsigned long data_size, void *reset_data) { + int value; + + /* + * inline this code since we are not caused in the context of a + * udevice and passing NULL to x86_sysreset_request() is too horrible. + */ if (reset_type == EFI_RESET_COLD || reset_type == EFI_RESET_PLATFORM_SPECIFIC) - x86_sysreset_request(NULL, SYSRESET_COLD); - else if (reset_type == EFI_RESET_WARM) - x86_sysreset_request(NULL, SYSRESET_WARM); + value = SYS_RST | RST_CPU | FULL_RST; + else /* assume EFI_RESET_WARM since we cannot return an error */ + value = SYS_RST | RST_CPU; + outb(value, IO_PORT_RESET);
/* TODO EFI_RESET_SHUTDOWN */

+Heinrich,
On Fri, Apr 26, 2019 at 12:00 PM Simon Glass sjg@chromium.org wrote:
The EFI implementation of reset sits inside the driver and is called directly from outside the driver, breaking the normal driver-model conventions. Worse, it passed NULL as the device pointer, hoping that the called function won't use it, which breaks as soon as code is added to use it.
Separate out the implementation to improve the situation enough to allow a future patch to add new sysreset features.
Signed-off-by: Simon Glass sjg@chromium.org
Changes in v2:
- Add new patch to separate out the EFI code in sysreset
drivers/sysreset/sysreset_x86.c | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-)
diff --git a/drivers/sysreset/sysreset_x86.c b/drivers/sysreset/sysreset_x86.c index 009f3766027..d484ec5de49 100644 --- a/drivers/sysreset/sysreset_x86.c +++ b/drivers/sysreset/sysreset_x86.c @@ -12,8 +12,7 @@ #include <asm/processor.h> #include <efi_loader.h>
-static __efi_runtime int x86_sysreset_request(struct udevice *dev,
enum sysreset_t type)
I remember last time I tried when booting Linux from EFI loader on U-Boot, calling from kernel into the EFI runtime was broken. Not sure what the latest status is.
+static int x86_sysreset_request(struct udevice *dev, enum sysreset_t type) { int value;
@@ -39,11 +38,18 @@ void __efi_runtime EFIAPI efi_reset_system( efi_status_t reset_status, unsigned long data_size, void *reset_data) {
int value;
/*
* inline this code since we are not caused in the context of a
* udevice and passing NULL to x86_sysreset_request() is too horrible.
*/ if (reset_type == EFI_RESET_COLD || reset_type == EFI_RESET_PLATFORM_SPECIFIC)
x86_sysreset_request(NULL, SYSRESET_COLD);
else if (reset_type == EFI_RESET_WARM)
x86_sysreset_request(NULL, SYSRESET_WARM);
value = SYS_RST | RST_CPU | FULL_RST;
else /* assume EFI_RESET_WARM since we cannot return an error */
value = SYS_RST | RST_CPU;
outb(value, IO_PORT_RESET); /* TODO EFI_RESET_SHUTDOWN */
--
Reviewed-by: Bin Meng bmeng.cn@gmail.com

On 5/1/19 3:42 PM, Bin Meng wrote:
+Heinrich,
On Fri, Apr 26, 2019 at 12:00 PM Simon Glass sjg@chromium.org wrote:
The EFI implementation of reset sits inside the driver and is called directly from outside the driver, breaking the normal driver-model conventions. Worse, it passed NULL as the device pointer, hoping that the called function won't use it, which breaks as soon as code is added to use it.
Separate out the implementation to improve the situation enough to allow a future patch to add new sysreset features.
Signed-off-by: Simon Glass sjg@chromium.org
Changes in v2:
Add new patch to separate out the EFI code in sysreset
drivers/sysreset/sysreset_x86.c | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-)
diff --git a/drivers/sysreset/sysreset_x86.c b/drivers/sysreset/sysreset_x86.c index 009f3766027..d484ec5de49 100644 --- a/drivers/sysreset/sysreset_x86.c +++ b/drivers/sysreset/sysreset_x86.c @@ -12,8 +12,7 @@ #include <asm/processor.h> #include <efi_loader.h>
-static __efi_runtime int x86_sysreset_request(struct udevice *dev,
enum sysreset_t type)
I remember last time I tried when booting Linux from EFI loader on U-Boot, calling from kernel into the EFI runtime was broken. Not sure what the latest status is.
I have no x86 system using U-Boot. On ARM I am not aware of problems.
Last year I had no success booting up qemu-x86_defconfig with Linux via EFI. Maybe I should retry.
Best regards
Heinrich

Add a new ioctl() request to read information about the power-management system. This can be used to power off the device.
Signed-off-by: Simon Glass sjg@chromium.org ---
Changes in v2: - Add new patch to add an ioctl to read power-management info
include/pch.h | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+)
diff --git a/include/pch.h b/include/pch.h index 046a5fde3ab..0b44b66df9f 100644 --- a/include/pch.h +++ b/include/pch.h @@ -16,6 +16,9 @@ enum pch_req_t { /* Returns HDA config info if Azalia V1CTL enabled, -ENOENT if not */ PCH_REQ_HDA_CONFIG,
+ /* Fills out a struct pch_pmbase_info if available */ + PCH_REQ_PMBASE_INFO, + PCH_REQ_TEST1, /* Test requests for sandbox driver */ PCH_REQ_TEST2, PCH_REQ_TEST3, @@ -23,6 +26,21 @@ enum pch_req_t { PCH_REQ_COUNT, /* Number of ioctrls supported */ };
+/** + * struct pch_pmbase_info - Information filled in by PCH_REQ_PMBASE_INFO + * + * @pmbase: IO address of power-management controller + * @gpio0_en_ofs: Offset of GPIO0 enable register + * @pm1_sts_ofs: Offset of status register + * @pm1_cnt_ofs: Offset of control register + */ +struct pch_pmbase_info { + u16 base; + u8 gpio0_en_ofs; + u8 pm1_sts_ofs; + u8 pm1_cnt_ofs; +}; + /** * struct pch_ops - Operations for the Platform Controller Hub *

On Fri, Apr 26, 2019 at 12:00 PM Simon Glass sjg@chromium.org wrote:
Add a new ioctl() request to read information about the power-management system. This can be used to power off the device.
Signed-off-by: Simon Glass sjg@chromium.org
Changes in v2:
- Add new patch to add an ioctl to read power-management info
include/pch.h | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+)
Reviewed-by: Bin Meng bmeng.cn@gmail.com

On Wed, May 1, 2019 at 9:42 PM Bin Meng bmeng.cn@gmail.com wrote:
On Fri, Apr 26, 2019 at 12:00 PM Simon Glass sjg@chromium.org wrote:
Add a new ioctl() request to read information about the power-management system. This can be used to power off the device.
Signed-off-by: Simon Glass sjg@chromium.org
Changes in v2:
- Add new patch to add an ioctl to read power-management info
include/pch.h | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+)
Reviewed-by: Bin Meng bmeng.cn@gmail.com
applied to u-boot-x86, thanks!

Implement this ioctl() to support power off.
Signed-off-by: Simon Glass sjg@chromium.org ---
Changes in v2: - Add new patch to implement PCH_REQ_PMBASE_INFO on ivybridge
arch/x86/cpu/ivybridge/bd82x6x.c | 15 +++++++++++++++ 1 file changed, 15 insertions(+)
diff --git a/arch/x86/cpu/ivybridge/bd82x6x.c b/arch/x86/cpu/ivybridge/bd82x6x.c index ed9bce64168..1cb6cecda9e 100644 --- a/arch/x86/cpu/ivybridge/bd82x6x.c +++ b/arch/x86/cpu/ivybridge/bd82x6x.c @@ -229,6 +229,21 @@ static int bd82x6x_ioctl(struct udevice *dev, enum pch_req_t req, void *data, return -ENOENT;
return val & RCBA_AUDIO_CONFIG_MASK; + case PCH_REQ_PMBASE_INFO: { + struct pch_pmbase_info *pm = data; + int ret; + + /* Find the base address of the powermanagement registers */ + ret = dm_pci_read_config16(dev, 0x40, &pm->base); + if (ret) + return ret; + pm->base &= 0xfffe; + pm->gpio0_en_ofs = GPE0_EN; + pm->pm1_sts_ofs = PM1_STS; + pm->pm1_cnt_ofs = PM1_CNT; + + return 0; + } default: return -ENOSYS; }

On Fri, Apr 26, 2019 at 12:00 PM Simon Glass sjg@chromium.org wrote:
Implement this ioctl() to support power off.
Signed-off-by: Simon Glass sjg@chromium.org
Changes in v2:
- Add new patch to implement PCH_REQ_PMBASE_INFO on ivybridge
arch/x86/cpu/ivybridge/bd82x6x.c | 15 +++++++++++++++ 1 file changed, 15 insertions(+)
Reviewed-by: Bin Meng bmeng.cn@gmail.com

On Wed, May 1, 2019 at 9:42 PM Bin Meng bmeng.cn@gmail.com wrote:
On Fri, Apr 26, 2019 at 12:00 PM Simon Glass sjg@chromium.org wrote:
Implement this ioctl() to support power off.
Signed-off-by: Simon Glass sjg@chromium.org
Changes in v2:
- Add new patch to implement PCH_REQ_PMBASE_INFO on ivybridge
arch/x86/cpu/ivybridge/bd82x6x.c | 15 +++++++++++++++ 1 file changed, 15 insertions(+)
Reviewed-by: Bin Meng bmeng.cn@gmail.com
applied to u-boot-x86, thanks!

Implement this ioctl() to support power off.
Signed-off-by: Simon Glass sjg@chromium.org ---
Changes in v2: - Add new patch to implement PCH_REQ_PMBASE_INFO on broadwell
arch/x86/cpu/broadwell/pch.c | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+)
diff --git a/arch/x86/cpu/broadwell/pch.c b/arch/x86/cpu/broadwell/pch.c index 73d3d3b5154..e61efa7b16c 100644 --- a/arch/x86/cpu/broadwell/pch.c +++ b/arch/x86/cpu/broadwell/pch.c @@ -630,10 +630,35 @@ static int broadwell_get_gpio_base(struct udevice *dev, u32 *gbasep) return 0; }
+static int broadwell_ioctl(struct udevice *dev, enum pch_req_t req, void *data, + int size) +{ + switch (req) { + case PCH_REQ_PMBASE_INFO: { + struct pch_pmbase_info *pm = data; + int ret; + + /* Find the base address of the powermanagement registers */ + ret = dm_pci_read_config16(dev, 0x40, &pm->base); + if (ret) + return ret; + pm->base &= 0xfffe; + pm->gpio0_en_ofs = GPE0_EN(0); + pm->pm1_sts_ofs = PM1_STS; + pm->pm1_cnt_ofs = PM1_CNT; + + return 0; + } + default: + return -ENOSYS; + } +} + static const struct pch_ops broadwell_pch_ops = { .get_spi_base = broadwell_pch_get_spi_base, .set_spi_protect = broadwell_set_spi_protect, .get_gpio_base = broadwell_get_gpio_base, + .ioctl = broadwell_ioctl, };
static const struct udevice_id broadwell_pch_ids[] = {

On Fri, Apr 26, 2019 at 12:00 PM Simon Glass sjg@chromium.org wrote:
Implement this ioctl() to support power off.
Signed-off-by: Simon Glass sjg@chromium.org
Changes in v2:
- Add new patch to implement PCH_REQ_PMBASE_INFO on broadwell
arch/x86/cpu/broadwell/pch.c | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+)
Reviewed-by: Bin Meng bmeng.cn@gmail.com

On Wed, May 1, 2019 at 10:50 PM Bin Meng bmeng.cn@gmail.com wrote:
On Fri, Apr 26, 2019 at 12:00 PM Simon Glass sjg@chromium.org wrote:
Implement this ioctl() to support power off.
Signed-off-by: Simon Glass sjg@chromium.org
Changes in v2:
- Add new patch to implement PCH_REQ_PMBASE_INFO on broadwell
arch/x86/cpu/broadwell/pch.c | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+)
Reviewed-by: Bin Meng bmeng.cn@gmail.com
applied to u-boot-x86, thanks!

On modern x86 devices we can power the system off using the power- management features of the PCH. Add an implementation for this.
Signed-off-by: Simon Glass sjg@chromium.org ---
Changes in v2: - Add new patch to implement power-off if available
drivers/sysreset/sysreset_x86.c | 82 +++++++++++++++++++++++++++++++++ 1 file changed, 82 insertions(+)
diff --git a/drivers/sysreset/sysreset_x86.c b/drivers/sysreset/sysreset_x86.c index d484ec5de49..bd759aa8bf4 100644 --- a/drivers/sysreset/sysreset_x86.c +++ b/drivers/sysreset/sysreset_x86.c @@ -7,14 +7,80 @@
#include <common.h> #include <dm.h> +#include <pch.h> #include <sysreset.h> #include <asm/io.h> #include <asm/processor.h> #include <efi_loader.h>
+struct x86_sysreset_platdata { + struct udevice *pch; +}; + +#define PWRBTN_STS (1 << 8) + +#define SLP_EN (1 << 13) +#define SLP_TYP (7 << 10) +#define SLP_TYP_S5 7 + +/* + * Power down the machine by using the power management sleep control + * of the chipset. This will currently only work on Intel chipsets. + * However, adapting it to new chipsets is fairly simple. You will + * have to find the IO address of the power management register block + * in your southbridge, and look up the appropriate SLP_TYP_S5 value + * from your southbridge's data sheet. + * + * This function never returns. + */ +int pch_sysreset_power_off(struct udevice *dev) +{ + struct x86_sysreset_platdata *plat = dev_get_platdata(dev); + struct pch_pmbase_info pm; + u32 reg32; + int ret; + + if (!plat->pch) + return -ENOENT; + ret = pch_ioctl(plat->pch, PCH_REQ_PMBASE_INFO, &pm, sizeof(pm)); + if (ret) + return ret; + + + /* Mask interrupts or system might stay in a coma + * (not executing code anymore, but not powered off either) + */ + asm("cli"); + + /* + * Avoid any GPI waking the system from S5* or the system might stay in + * a coma + */ + outl(0x00000000, pm.base + pm.gpio0_en_ofs); + + /* Clear Power Button Status */ + outw(PWRBTN_STS, pm.base + pm.pm1_sts_ofs); + + /* PMBASE + 4, Bit 10-12, Sleeping Type, * set to 111 -> S5, soft_off */ + reg32 = inl(pm.base + pm.pm1_cnt_ofs); + + /* Set Sleeping Type to S5 (poweroff) */ + reg32 &= ~(SLP_EN | SLP_TYP); + reg32 |= SLP_TYP_S5; + outl(reg32, pm.base + pm.pm1_cnt_ofs); + + /* Now set the Sleep Enable bit */ + reg32 |= SLP_EN; + outl(reg32, pm.base + pm.pm1_cnt_ofs); + + for (;;) + asm("hlt"); +} + static int x86_sysreset_request(struct udevice *dev, enum sysreset_t type) { int value; + int ret;
switch (type) { case SYSRESET_WARM: @@ -23,6 +89,11 @@ static int x86_sysreset_request(struct udevice *dev, enum sysreset_t type) case SYSRESET_COLD: value = SYS_RST | RST_CPU | FULL_RST; break; + case SYSRESET_POWER_OFF: + ret = pch_sysreset_power_off(dev); + if (ret) + return ret; + return -EINPROGRESS; default: return -ENOSYS; } @@ -57,6 +128,15 @@ void __efi_runtime EFIAPI efi_reset_system( } #endif
+static int x86_sysreset_probe(struct udevice *dev) +{ + struct x86_sysreset_platdata *plat = dev_get_platdata(dev); + + /* Locate the PCH if there is one. It isn't essential */ + uclass_first_device(UCLASS_PCH, &plat->pch); + + return 0; +}
static const struct udevice_id x86_sysreset_ids[] = { { .compatible = "x86,reset" }, @@ -72,4 +152,6 @@ U_BOOT_DRIVER(x86_sysreset) = { .id = UCLASS_SYSRESET, .of_match = x86_sysreset_ids, .ops = &x86_sysreset_ops, + .probe = x86_sysreset_probe, + .platdata_auto_alloc_size = sizeof(struct x86_sysreset_platdata), };

Hi Simon,
On Fri, Apr 26, 2019 at 12:00 PM Simon Glass sjg@chromium.org wrote:
On modern x86 devices we can power the system off using the power- management features of the PCH. Add an implementation for this.
Signed-off-by: Simon Glass sjg@chromium.org
Changes in v2:
- Add new patch to implement power-off if available
drivers/sysreset/sysreset_x86.c | 82 +++++++++++++++++++++++++++++++++ 1 file changed, 82 insertions(+)
diff --git a/drivers/sysreset/sysreset_x86.c b/drivers/sysreset/sysreset_x86.c index d484ec5de49..bd759aa8bf4 100644 --- a/drivers/sysreset/sysreset_x86.c +++ b/drivers/sysreset/sysreset_x86.c @@ -7,14 +7,80 @@
#include <common.h> #include <dm.h> +#include <pch.h> #include <sysreset.h> #include <asm/io.h> #include <asm/processor.h> #include <efi_loader.h>
+struct x86_sysreset_platdata {
struct udevice *pch;
+};
+#define PWRBTN_STS (1 << 8)
+#define SLP_EN (1 << 13) +#define SLP_TYP (7 << 10) +#define SLP_TYP_S5 7
There are macros from acpi_s3.h that can be used directly here.
+/*
- Power down the machine by using the power management sleep control
- of the chipset. This will currently only work on Intel chipsets.
- However, adapting it to new chipsets is fairly simple. You will
- have to find the IO address of the power management register block
- in your southbridge, and look up the appropriate SLP_TYP_S5 value
- from your southbridge's data sheet.
- This function never returns.
- */
+int pch_sysreset_power_off(struct udevice *dev) +{
struct x86_sysreset_platdata *plat = dev_get_platdata(dev);
struct pch_pmbase_info pm;
u32 reg32;
int ret;
if (!plat->pch)
return -ENOENT;
ret = pch_ioctl(plat->pch, PCH_REQ_PMBASE_INFO, &pm, sizeof(pm));
if (ret)
return ret;
/* Mask interrupts or system might stay in a coma
nits: wrong multi-line comment format
* (not executing code anymore, but not powered off either)
*/
asm("cli");
/*
* Avoid any GPI waking the system from S5* or the system might stay in
* a coma
*/
outl(0x00000000, pm.base + pm.gpio0_en_ofs);
/* Clear Power Button Status */
outw(PWRBTN_STS, pm.base + pm.pm1_sts_ofs);
/* PMBASE + 4, Bit 10-12, Sleeping Type, * set to 111 -> S5, soft_off */
reg32 = inl(pm.base + pm.pm1_cnt_ofs);
/* Set Sleeping Type to S5 (poweroff) */
reg32 &= ~(SLP_EN | SLP_TYP);
reg32 |= SLP_TYP_S5;
outl(reg32, pm.base + pm.pm1_cnt_ofs);
/* Now set the Sleep Enable bit */
reg32 |= SLP_EN;
outl(reg32, pm.base + pm.pm1_cnt_ofs);
for (;;)
asm("hlt");
+}
static int x86_sysreset_request(struct udevice *dev, enum sysreset_t type) { int value;
int ret; switch (type) { case SYSRESET_WARM:
@@ -23,6 +89,11 @@ static int x86_sysreset_request(struct udevice *dev, enum sysreset_t type) case SYSRESET_COLD: value = SYS_RST | RST_CPU | FULL_RST; break;
case SYSRESET_POWER_OFF:
ret = pch_sysreset_power_off(dev);
if (ret)
return ret;
return -EINPROGRESS; default: return -ENOSYS; }
@@ -57,6 +128,15 @@ void __efi_runtime EFIAPI efi_reset_system( } #endif
+static int x86_sysreset_probe(struct udevice *dev) +{
struct x86_sysreset_platdata *plat = dev_get_platdata(dev);
/* Locate the PCH if there is one. It isn't essential */
uclass_first_device(UCLASS_PCH, &plat->pch);
return 0;
+}
static const struct udevice_id x86_sysreset_ids[] = { { .compatible = "x86,reset" }, @@ -72,4 +152,6 @@ U_BOOT_DRIVER(x86_sysreset) = { .id = UCLASS_SYSRESET, .of_match = x86_sysreset_ids, .ops = &x86_sysreset_ops,
.probe = x86_sysreset_probe,
.platdata_auto_alloc_size = sizeof(struct x86_sysreset_platdata),
};
Other than above two, Reviewed-by: Bin Meng bmeng.cn@gmail.com
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 Reviewed-by: Bin Meng bmeng.cn@gmail.com ---
Changes in v2: None
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 57cca0b930c..07f27c29ec7 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 Fri, Apr 26, 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 Reviewed-by: Bin Meng bmeng.cn@gmail.com
Changes in v2: None
arch/x86/cpu/intel_common/Makefile | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-)
applied to u-boot-x86, thanks!

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 Reviewed-by: Bin Meng bmeng.cn@gmail.com ---
Changes in v2: None
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 0481f453ca6..ac85278cdf0 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 Fri, Apr 26, 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 Reviewed-by: Bin Meng bmeng.cn@gmail.com
Changes in v2: None
arch/x86/lib/init_helpers.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-)
applied to u-boot-x86, thanks!

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 Reviewed-by: Bin Meng bmeng.cn@gmail.com ---
Changes in v2: None
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 832b1f901c6..5443a862ab5 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 Fri, Apr 26, 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 Reviewed-by: Bin Meng bmeng.cn@gmail.com
Changes in v2: None
arch/x86/lib/bootm.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
applied to u-boot-x86, thanks!

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 Reviewed-by: Bin Meng bmeng.cn@gmail.com ---
Changes in v2: None
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 7d9b75c2c45..2cede1211bb 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 Fri, Apr 26, 2019 at 12:00 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 Reviewed-by: Bin Meng bmeng.cn@gmail.com
Changes in v2: None
drivers/pci/pci_rom.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
applied to u-boot-x86, thanks!

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 ---
Changes in v2: None
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 bd759aa8bf4..b8876dc51e7 100644 --- a/drivers/sysreset/sysreset_x86.c +++ b/drivers/sysreset/sysreset_x86.c @@ -103,6 +103,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; +} + #ifdef CONFIG_EFI_LOADER void __efi_runtime EFIAPI efi_reset_system( enum efi_reset_type reset_type, @@ -145,6 +150,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) = {

On Fri, Apr 26, 2019 at 12:00 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.
Signed-off-by: Simon Glass sjg@chromium.org
Changes in v2: None
drivers/sysreset/sysreset_x86.c | 6 ++++++ 1 file changed, 6 insertions(+)
Reviewed-by: Bin Meng bmeng.cn@gmail.com

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 Reviewed-by: Bin Meng bmeng.cn@gmail.com ---
Changes in v2: None
doc/README.x86 | 14 ++++++++++++++ 1 file changed, 14 insertions(+)
diff --git a/doc/README.x86 b/doc/README.x86 index fa49cb8b8a2..d5224b75367 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:

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 Reviewed-by: Bin Meng bmeng.cn@gmail.com ---
Changes in v2: None
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 35211ed81b1..6664c3b7d36 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 @@ -540,7 +558,7 @@ compatible = "ehci-pci"; };
- pch@1f,0 { + pch: pch@1f,0 { reg = <0x0000f800 0 0 0 0>; compatible = "intel,broadwell-pch"; u-boot,dm-pre-reloc; @@ -559,17 +577,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", "jedec,spi-nor"; - 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>; }; @@ -609,7 +630,8 @@ #size-cells = <0>; u-boot,dm-pre-reloc; intel,gen-dec = <0x800 0xfc 0x900 0xfc>; - cros-ec@200 { + cros_ec: cros-ec { + u-boot,dm-pre-reloc; compatible = "google,cros-ec-lpc"; reg = <0x204 1 0x200 1 0x880 0x80>;
@@ -630,7 +652,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>; @@ -644,13 +666,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" }; };

Hi Simon,
On Fri, Apr 26, 2019 at 12:00 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 Reviewed-by: Bin Meng bmeng.cn@gmail.com
Changes in v2: None
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 35211ed81b1..6664c3b7d36 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
@@ -540,7 +558,7 @@ compatible = "ehci-pci"; };
pch@1f,0 {
pch: pch@1f,0 { reg = <0x0000f800 0 0 0 0>; compatible = "intel,broadwell-pch"; u-boot,dm-pre-reloc;
@@ -559,17 +577,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", "jedec,spi-nor";
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>; };
@@ -609,7 +630,8 @@ #size-cells = <0>; u-boot,dm-pre-reloc; intel,gen-dec = <0x800 0xfc 0x900 0xfc>;
cros-ec@200 {
cros_ec: cros-ec {
u-boot,dm-pre-reloc; compatible = "google,cros-ec-lpc"; reg = <0x204 1 0x200 1 0x880 0x80>;
@@ -630,7 +652,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>;
@@ -644,13 +666,21 @@ }; };
pch-reset {
compatible = "intel,pch-reset";
intel,pch = <&pch>;
};
I think you forgot to remove this node in v2.
[snip]
Regards, Bin

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 Reviewed-by: Bin Meng bmeng.cn@gmail.com ---
Changes in v2: None
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 6664c3b7d36..220bdebfc97 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"; @@ -581,7 +587,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>; @@ -675,6 +681,10 @@ u-boot,dm-pre-reloc; reg = <0xfed40000 0x5000>; compatible = "infineon,slb9635lpc"; + secdata { + u-boot,dm-pre-reloc; + compatible = "google,tpm-secdata"; + }; };
microcode { @@ -698,3 +708,13 @@ };
}; + +&rtc { + #address-cells = <1>; + #size-cells = <0>; + nvdata { + u-boot,dm-pre-reloc; + compatible = "google,cmos-nvdata"; + reg = <0x26>; + }; +};

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 ---
Changes in v2: None
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 1050236330a..70e9c8f7acd 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 Fri, Apr 26, 2019 at 12:00 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.
Signed-off-by: Simon Glass sjg@chromium.org
Changes in v2: None
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 1050236330a..70e9c8f7acd 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 {
};
nits: since TPL starts before SPL, can we put the TPL* nodes before SPL* nodes?
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
The magic number comparison does not look good.
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>; }; --
Regards, Bin

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 Reviewed-by: Bin Meng bmeng.cn@gmail.com ---
Changes in v2: None
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 70e9c8f7acd..5943619b863 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

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 Reviewed-by: Bin Meng bmeng.cn@gmail.com ---
Changes in v2: None
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 5943619b863..8bb1318a2ce 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

This is again too small, so increase it slightly.
Signed-off-by: Simon Glass sjg@chromium.org Reviewed-by: Bin Meng bmeng.cn@gmail.com ---
Changes in v2: None
configs/chromebook_samus_defconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/configs/chromebook_samus_defconfig b/configs/chromebook_samus_defconfig index 7e2453f2440..5f5db07b5a5 100644 --- a/configs/chromebook_samus_defconfig +++ b/configs/chromebook_samus_defconfig @@ -1,6 +1,6 @@ CONFIG_X86=y CONFIG_SYS_TEXT_BASE=0xFFE00000 -CONFIG_SYS_MALLOC_F_LEN=0x1c00 +CONFIG_SYS_MALLOC_F_LEN=0x1d00 CONFIG_DEBUG_UART_BOARD_INIT=y CONFIG_DEBUG_UART_BASE=0x3f8 CONFIG_DEBUG_UART_CLOCK=1843200

This reverts commit aec4298ccb337106fd0115b91d846a022fdf301d.
Unfortunately this has a dramatic impact on the pre-relocation memory used on x86 platforms (increasing it by 2KB) since it increases the overhead for each PCI device from 220 bytes to 412 bytes.
The offending line is in UCLASS_DRIVER(pci):
.per_device_auto_alloc_size = sizeof(struct pci_controller),
This means that all PCI devices have the controller struct associated with them. The solution is to move the regions[] member out of the array, makes its size dynamic, or split UCLASS_PCI into controllers and non-controllers, as the comment suggests.
For now, revert the commit to get things running again.
Signed-off-by: Simon Glass sjg@chromium.org ---
Changes in v2: None
include/pci.h | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-)
diff --git a/include/pci.h b/include/pci.h index 066238a9c3c..508f7bca81c 100644 --- a/include/pci.h +++ b/include/pci.h @@ -546,11 +546,7 @@ extern void pci_cfgfunc_do_nothing(struct pci_controller* hose, pci_dev_t dev, extern void pci_cfgfunc_config_device(struct pci_controller* hose, pci_dev_t dev, struct pci_config_table *);
-#ifdef CONFIG_NR_DRAM_BANKS -#define MAX_PCI_REGIONS (CONFIG_NR_DRAM_BANKS + 7) -#else -#define MAX_PCI_REGIONS 7 -#endif +#define MAX_PCI_REGIONS 7
#define INDIRECT_TYPE_NO_PCIE_LINK 1

+Thierry
On Fri, Apr 26, 2019 at 12:00 PM Simon Glass sjg@chromium.org wrote:
This reverts commit aec4298ccb337106fd0115b91d846a022fdf301d.
Unfortunately this has a dramatic impact on the pre-relocation memory used on x86 platforms (increasing it by 2KB) since it increases the overhead for each PCI device from 220 bytes to 412 bytes.
The offending line is in UCLASS_DRIVER(pci):
.per_device_auto_alloc_size = sizeof(struct pci_controller),
This means that all PCI devices have the controller struct associated with them. The solution is to move the regions[] member out of the array, makes its size dynamic, or split UCLASS_PCI into controllers and non-controllers, as the comment suggests.
For now, revert the commit to get things running again.
Signed-off-by: Simon Glass sjg@chromium.org
Changes in v2: None
include/pci.h | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-)
Reviewed-by: Bin Meng bmeng.cn@gmail.com

On Thu, May 02, 2019 at 12:09:49AM +0800, Bin Meng wrote:
+Thierry
On Fri, Apr 26, 2019 at 12:00 PM Simon Glass sjg@chromium.org wrote:
This reverts commit aec4298ccb337106fd0115b91d846a022fdf301d.
Unfortunately this has a dramatic impact on the pre-relocation memory used on x86 platforms (increasing it by 2KB) since it increases the overhead for each PCI device from 220 bytes to 412 bytes.
The offending line is in UCLASS_DRIVER(pci):
.per_device_auto_alloc_size = sizeof(struct pci_controller),
This means that all PCI devices have the controller struct associated with them. The solution is to move the regions[] member out of the array, makes its size dynamic, or split UCLASS_PCI into controllers and non-controllers, as the comment suggests.
For now, revert the commit to get things running again.
Signed-off-by: Simon Glass sjg@chromium.org
Changes in v2: None
include/pci.h | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-)
Reviewed-by: Bin Meng bmeng.cn@gmail.com
Ugh... so we're trading one regression for another? Can we not live with the 2 KiB increase on x86 until this has been properly fixed? Currently this will cause Jetson TX2 to crash if it starts using PCI.
Thierry

Hi Thierry,
On Thu, 2 May 2019 at 03:25, Thierry Reding treding@nvidia.com wrote:
On Thu, May 02, 2019 at 12:09:49AM +0800, Bin Meng wrote:
+Thierry
On Fri, Apr 26, 2019 at 12:00 PM Simon Glass sjg@chromium.org wrote:
This reverts commit aec4298ccb337106fd0115b91d846a022fdf301d.
Unfortunately this has a dramatic impact on the pre-relocation memory used on x86 platforms (increasing it by 2KB) since it increases the overhead for each PCI device from 220 bytes to 412 bytes.
The offending line is in UCLASS_DRIVER(pci):
.per_device_auto_alloc_size = sizeof(struct pci_controller),
This means that all PCI devices have the controller struct associated with them. The solution is to move the regions[] member out of the array, makes its size dynamic, or split UCLASS_PCI into controllers and non-controllers, as the comment suggests.
For now, revert the commit to get things running again.
Signed-off-by: Simon Glass sjg@chromium.org
Changes in v2: None
include/pci.h | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-)
Reviewed-by: Bin Meng bmeng.cn@gmail.com
Ugh... so we're trading one regression for another? Can we not live with the 2 KiB increase on x86 until this has been properly fixed? Currently this will cause Jetson TX2 to crash if it starts using PCI.
Unfortunately this breaks several boards since we are out of memory.
I think this needs a better solution to reduce the memory usage down to sensible levels. This is something I should have considered when implementing the PCI uclass, but unfortunately I did not.
Regards, Simon

Hi Simon, Thierry,
On Fri, May 3, 2019 at 12:22 AM Simon Glass sjg@chromium.org wrote:
Hi Thierry,
On Thu, 2 May 2019 at 03:25, Thierry Reding treding@nvidia.com wrote:
On Thu, May 02, 2019 at 12:09:49AM +0800, Bin Meng wrote:
+Thierry
On Fri, Apr 26, 2019 at 12:00 PM Simon Glass sjg@chromium.org wrote:
This reverts commit aec4298ccb337106fd0115b91d846a022fdf301d.
Unfortunately this has a dramatic impact on the pre-relocation memory used on x86 platforms (increasing it by 2KB) since it increases the overhead for each PCI device from 220 bytes to 412 bytes.
The offending line is in UCLASS_DRIVER(pci):
.per_device_auto_alloc_size = sizeof(struct pci_controller),
This means that all PCI devices have the controller struct associated with them. The solution is to move the regions[] member out of the array, makes its size dynamic, or split UCLASS_PCI into controllers and non-controllers, as the comment suggests.
For now, revert the commit to get things running again.
Signed-off-by: Simon Glass sjg@chromium.org
Changes in v2: None
include/pci.h | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-)
Reviewed-by: Bin Meng bmeng.cn@gmail.com
Ugh... so we're trading one regression for another? Can we not live with the 2 KiB increase on x86 until this has been properly fixed? Currently this will cause Jetson TX2 to crash if it starts using PCI.
Unfortunately this breaks several boards since we are out of memory.
I think this needs a better solution to reduce the memory usage down to sensible levels. This is something I should have considered when implementing the PCI uclass, but unfortunately I did not.
Could you please suggest whether I should apply this revert patch for now?
Regards, Bin

Hi Bin,
On Tue, 7 May 2019 at 03:28, Bin Meng bmeng.cn@gmail.com wrote:
Hi Simon, Thierry,
On Fri, May 3, 2019 at 12:22 AM Simon Glass sjg@chromium.org wrote:
Hi Thierry,
On Thu, 2 May 2019 at 03:25, Thierry Reding treding@nvidia.com wrote:
On Thu, May 02, 2019 at 12:09:49AM +0800, Bin Meng wrote:
+Thierry
On Fri, Apr 26, 2019 at 12:00 PM Simon Glass sjg@chromium.org wrote:
This reverts commit aec4298ccb337106fd0115b91d846a022fdf301d.
Unfortunately this has a dramatic impact on the pre-relocation memory used on x86 platforms (increasing it by 2KB) since it increases the overhead for each PCI device from 220 bytes to 412 bytes.
The offending line is in UCLASS_DRIVER(pci):
.per_device_auto_alloc_size = sizeof(struct pci_controller),
This means that all PCI devices have the controller struct associated with them. The solution is to move the regions[] member out of the array, makes its size dynamic, or split UCLASS_PCI into controllers and non-controllers, as the comment suggests.
For now, revert the commit to get things running again.
Signed-off-by: Simon Glass sjg@chromium.org
Changes in v2: None
include/pci.h | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-)
Reviewed-by: Bin Meng bmeng.cn@gmail.com
Ugh... so we're trading one regression for another? Can we not live with the 2 KiB increase on x86 until this has been properly fixed? Currently this will cause Jetson TX2 to crash if it starts using PCI.
Unfortunately this breaks several boards since we are out of memory.
I think this needs a better solution to reduce the memory usage down to sensible levels. This is something I should have considered when implementing the PCI uclass, but unfortunately I did not.
Could you please suggest whether I should apply this revert patch for now?
I suggest a temporary revert since this breaks some x86 boards.
I think the real fix is to reduce the memory used by PCI devices. Thierry, do you have time to look at this?
Regards, Simon

Hi Simon,
On Wed, May 8, 2019 at 11:04 AM Simon Glass sjg@chromium.org wrote:
Hi Bin,
On Tue, 7 May 2019 at 03:28, Bin Meng bmeng.cn@gmail.com wrote:
Hi Simon, Thierry,
On Fri, May 3, 2019 at 12:22 AM Simon Glass sjg@chromium.org wrote:
Hi Thierry,
On Thu, 2 May 2019 at 03:25, Thierry Reding treding@nvidia.com wrote:
On Thu, May 02, 2019 at 12:09:49AM +0800, Bin Meng wrote:
+Thierry
On Fri, Apr 26, 2019 at 12:00 PM Simon Glass sjg@chromium.org wrote:
This reverts commit aec4298ccb337106fd0115b91d846a022fdf301d.
Unfortunately this has a dramatic impact on the pre-relocation memory used on x86 platforms (increasing it by 2KB) since it increases the overhead for each PCI device from 220 bytes to 412 bytes.
The offending line is in UCLASS_DRIVER(pci):
.per_device_auto_alloc_size = sizeof(struct pci_controller),
This means that all PCI devices have the controller struct associated with them. The solution is to move the regions[] member out of the array, makes its size dynamic, or split UCLASS_PCI into controllers and non-controllers, as the comment suggests.
For now, revert the commit to get things running again.
Signed-off-by: Simon Glass sjg@chromium.org
Changes in v2: None
include/pci.h | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-)
Reviewed-by: Bin Meng bmeng.cn@gmail.com
Ugh... so we're trading one regression for another? Can we not live with the 2 KiB increase on x86 until this has been properly fixed? Currently this will cause Jetson TX2 to crash if it starts using PCI.
Unfortunately this breaks several boards since we are out of memory.
I think this needs a better solution to reduce the memory usage down to sensible levels. This is something I should have considered when implementing the PCI uclass, but unfortunately I did not.
Could you please suggest whether I should apply this revert patch for now?
I suggest a temporary revert since this breaks some x86 boards.
I think the real fix is to reduce the memory used by PCI devices. Thierry, do you have time to look at this?
OK, I will apply this patch then.
Regards, Bin

On Tue, May 07, 2019 at 09:04:16PM -0600, Simon Glass wrote:
Hi Bin,
On Tue, 7 May 2019 at 03:28, Bin Meng bmeng.cn@gmail.com wrote:
Hi Simon, Thierry,
On Fri, May 3, 2019 at 12:22 AM Simon Glass sjg@chromium.org wrote:
Hi Thierry,
On Thu, 2 May 2019 at 03:25, Thierry Reding treding@nvidia.com wrote:
On Thu, May 02, 2019 at 12:09:49AM +0800, Bin Meng wrote:
+Thierry
On Fri, Apr 26, 2019 at 12:00 PM Simon Glass sjg@chromium.org wrote:
This reverts commit aec4298ccb337106fd0115b91d846a022fdf301d.
Unfortunately this has a dramatic impact on the pre-relocation memory used on x86 platforms (increasing it by 2KB) since it increases the overhead for each PCI device from 220 bytes to 412 bytes.
The offending line is in UCLASS_DRIVER(pci):
.per_device_auto_alloc_size = sizeof(struct pci_controller),
This means that all PCI devices have the controller struct associated with them. The solution is to move the regions[] member out of the array, makes its size dynamic, or split UCLASS_PCI into controllers and non-controllers, as the comment suggests.
For now, revert the commit to get things running again.
Signed-off-by: Simon Glass sjg@chromium.org
Changes in v2: None
include/pci.h | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-)
Reviewed-by: Bin Meng bmeng.cn@gmail.com
Ugh... so we're trading one regression for another? Can we not live with the 2 KiB increase on x86 until this has been properly fixed? Currently this will cause Jetson TX2 to crash if it starts using PCI.
Unfortunately this breaks several boards since we are out of memory.
I think this needs a better solution to reduce the memory usage down to sensible levels. This is something I should have considered when implementing the PCI uclass, but unfortunately I did not.
Could you please suggest whether I should apply this revert patch for now?
I suggest a temporary revert since this breaks some x86 boards.
I think the real fix is to reduce the memory used by PCI devices. Thierry, do you have time to look at this?
Not right away. I may get around to this within a couple of weeks maybe.
Thierry

With the move to Kconfig this option should be set in Kconfig, not in the config header file. Move it.
Signed-off-by: Simon Glass sjg@chromium.org ---
Changes in v2: - Add new patch to enable the RTC in Kconfig
arch/Kconfig | 1 + configs/chromebook_link_defconfig | 1 + include/configs/x86-common.h | 1 - 3 files changed, 2 insertions(+), 1 deletion(-)
diff --git a/arch/Kconfig b/arch/Kconfig index a1d1ac301d6..2a93b72dbc4 100644 --- a/arch/Kconfig +++ b/arch/Kconfig @@ -165,6 +165,7 @@ config X86 imply USB_ETHER_SMSC95XX imply USB_HOST_ETHER imply PCH + imply RTC_MC146818
# Thing to enable for when SPL/TPL are enabled: SPL imply SPL_DM diff --git a/configs/chromebook_link_defconfig b/configs/chromebook_link_defconfig index 6058dfaf0f2..b1c5095ec92 100644 --- a/configs/chromebook_link_defconfig +++ b/configs/chromebook_link_defconfig @@ -53,6 +53,7 @@ CONFIG_DM_I2C=y CONFIG_SYS_I2C_INTEL=y CONFIG_CROS_EC=y CONFIG_CROS_EC_LPC=y +CONFIG_RTC_MC146818=y CONFIG_SYS_NS16550=y CONFIG_SOUND=y CONFIG_SPI=y diff --git a/include/configs/x86-common.h b/include/configs/x86-common.h index 4180b25f977..7fcf76a6bf2 100644 --- a/include/configs/x86-common.h +++ b/include/configs/x86-common.h @@ -36,7 +36,6 @@ /*----------------------------------------------------------------------- * Real Time Clock Configuration */ -#define CONFIG_RTC_MC146818 #define CONFIG_SYS_ISA_IO_BASE_ADDRESS 0 #define CONFIG_SYS_ISA_IO CONFIG_SYS_ISA_IO_BASE_ADDRESS

Hi Simon,
On Fri, Apr 26, 2019 at 12:00 PM Simon Glass sjg@chromium.org wrote:
With the move to Kconfig this option should be set in Kconfig, not in the config header file. Move it.
Signed-off-by: Simon Glass sjg@chromium.org
Changes in v2:
- Add new patch to enable the RTC in Kconfig
arch/Kconfig | 1 + configs/chromebook_link_defconfig | 1 + include/configs/x86-common.h | 1 - 3 files changed, 2 insertions(+), 1 deletion(-)
diff --git a/arch/Kconfig b/arch/Kconfig index a1d1ac301d6..2a93b72dbc4 100644 --- a/arch/Kconfig +++ b/arch/Kconfig @@ -165,6 +165,7 @@ config X86 imply USB_ETHER_SMSC95XX imply USB_HOST_ETHER imply PCH
imply RTC_MC146818 # Thing to enable for when SPL/TPL are enabled: SPL imply SPL_DM
diff --git a/configs/chromebook_link_defconfig b/configs/chromebook_link_defconfig index 6058dfaf0f2..b1c5095ec92 100644 --- a/configs/chromebook_link_defconfig +++ b/configs/chromebook_link_defconfig @@ -53,6 +53,7 @@ CONFIG_DM_I2C=y CONFIG_SYS_I2C_INTEL=y CONFIG_CROS_EC=y CONFIG_CROS_EC_LPC=y +CONFIG_RTC_MC146818=y
This has been implied in arch/Kconfig above, why adding another one here?
CONFIG_SYS_NS16550=y CONFIG_SOUND=y CONFIG_SPI=y
Regards, Bin

The memory map currently omits the environment and the MRC region. Add these in for completeness.
Signed-off-by: Simon Glass sjg@chromium.org ---
Changes in v2: None
doc/README.x86 | 2 ++ 1 file changed, 2 insertions(+)
diff --git a/doc/README.x86 b/doc/README.x86 index d5224b75367..8e0a3f36edf 100644 --- a/doc/README.x86 +++ b/doc/README.x86 @@ -195,6 +195,8 @@ Flash map for samus / broadwell: ffed0000 SYS_TEXT_BASE ffea0000 X86_REFCODE_ADDR ffe70000 SPL_TEXT_BASE + ffbf8000 CONFIG_ENV_OFFSET (environemnt offset) + ffbe0000 rw-mrc-cache (Memory-reference-code cache) ffa00000 <spare> ff801000 intel-me (address set by descriptor.bin) ff800000 intel-descriptor

Hi Simon,
On Fri, Apr 26, 2019 at 12:00 PM Simon Glass sjg@chromium.org wrote:
The memory map currently omits the environment and the MRC region. Add these in for completeness.
I think the commit tile should be updated to add the "samus" tag.
Signed-off-by: Simon Glass sjg@chromium.org
Changes in v2: None
doc/README.x86 | 2 ++ 1 file changed, 2 insertions(+)
Reviewed-by: Bin Meng bmeng.cn@gmail.com
Regards, Bin

The early init should only happen once. Update the probe method to deal with TPL, SPL and U-Boot proper.
Signed-off-by: Simon Glass sjg@chromium.org ---
Changes in v2: - Add a new patch to update PCH to work in TPL
arch/x86/cpu/broadwell/pch.c | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-)
diff --git a/arch/x86/cpu/broadwell/pch.c b/arch/x86/cpu/broadwell/pch.c index e61efa7b16c..a48945adf11 100644 --- a/arch/x86/cpu/broadwell/pch.c +++ b/arch/x86/cpu/broadwell/pch.c @@ -599,10 +599,16 @@ static int broadwell_pch_init(struct udevice *dev)
static int broadwell_pch_probe(struct udevice *dev) { - if (!(gd->flags & GD_FLG_RELOC)) - return broadwell_pch_early_init(dev); - else + if (CONFIG_IS_ENABLED(X86_32BIT_INIT)) { + if (!(gd->flags & GD_FLG_RELOC)) + return broadwell_pch_early_init(dev); + else + return broadwell_pch_init(dev); + } else if (IS_ENABLED(CONFIG_SPL) && !IS_ENABLED(CONFIG_SPL_BUILD)) { return broadwell_pch_init(dev); + } else { + return 0; + } }
static int broadwell_pch_get_spi_base(struct udevice *dev, ulong *sbasep)

On Fri, Apr 26, 2019 at 12:00 PM Simon Glass sjg@chromium.org wrote:
The early init should only happen once. Update the probe method to deal with TPL, SPL and U-Boot proper.
Signed-off-by: Simon Glass sjg@chromium.org
Changes in v2:
- Add a new patch to update PCH to work in TPL
arch/x86/cpu/broadwell/pch.c | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-)
Reviewed-by: Bin Meng bmeng.cn@gmail.com

When TPL finishes it needs to jump to SPL with the stack set up correctly. Add a function to handle this.
Signed-off-by: Simon Glass sjg@chromium.org ---
Changes in v2: - Add a new patch allowing jumping from TPL to SPL
arch/x86/cpu/start.S | 13 +++++++++++++ 1 file changed, 13 insertions(+)
diff --git a/arch/x86/cpu/start.S b/arch/x86/cpu/start.S index 30fa7def464..4a82add76b7 100644 --- a/arch/x86/cpu/start.S +++ b/arch/x86/cpu/start.S @@ -190,6 +190,19 @@ board_init_f_r_trampoline: /* Re-enter U-Boot by calling board_init_f_r() */ call board_init_f_r
+#ifdef CONFIG_TPL +.globl jump_to_spl +.type jump_to_spl, @function +jump_to_spl: + /* Reset stack to the top of CAR space */ + movl $(CONFIG_SYS_CAR_ADDR + CONFIG_SYS_CAR_SIZE - 4), %esp +#ifdef CONFIG_DCACHE_RAM_MRC_VAR_SIZE + subl $CONFIG_DCACHE_RAM_MRC_VAR_SIZE, %esp +#endif + + jmp *%eax +#endif + die: hlt jmp die

Hi Simon,
On Fri, Apr 26, 2019 at 12:00 PM Simon Glass sjg@chromium.org wrote:
When TPL finishes it needs to jump to SPL with the stack set up correctly. Add a function to handle this.
Signed-off-by: Simon Glass sjg@chromium.org
Changes in v2:
- Add a new patch allowing jumping from TPL to SPL
arch/x86/cpu/start.S | 13 +++++++++++++ 1 file changed, 13 insertions(+)
Reviewed-by: Bin Meng bmeng.cn@gmail.com
But I don't see any patch in this series that makes use of this new jump_to_spl()?
Regards, Bin

Hi Bin,
On Wed, 1 May 2019 at 10:17, Bin Meng bmeng.cn@gmail.com wrote:
Hi Simon,
On Fri, Apr 26, 2019 at 12:00 PM Simon Glass sjg@chromium.org wrote:
When TPL finishes it needs to jump to SPL with the stack set up correctly. Add a function to handle this.
Signed-off-by: Simon Glass sjg@chromium.org
Changes in v2:
- Add a new patch allowing jumping from TPL to SPL
arch/x86/cpu/start.S | 13 +++++++++++++ 1 file changed, 13 insertions(+)
Reviewed-by: Bin Meng bmeng.cn@gmail.com
But I don't see any patch in this series that makes use of this new jump_to_spl()?
This is called from arch/x86/lib/tpl.c:
x86: Add a simple TPL implementation
Regards, Simon

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.
Reviewed-by: Bin Meng bmeng.cn@gmail.com Signed-off-by: Simon Glass sjg@chromium.org Reviewed-by: Bin Meng bmeng.cn@gmail.com ---
Changes in v2: - Sort defconfig and adjust it to build after rebase on maste
board/google/Kconfig | 8 +++ board/google/chromebook_samus/Kconfig | 14 +++- board/google/chromebook_samus/MAINTAINERS | 7 ++ configs/chromebook_samus_tpl_defconfig | 81 +++++++++++++++++++++++ include/configs/chromebook_samus.h | 3 + 5 files changed, 111 insertions(+), 2 deletions(-) create mode 100644 configs/chromebook_samus_tpl_defconfig
diff --git a/board/google/Kconfig b/board/google/Kconfig index d98a5e818fc..679a0f10239 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 afbfe53deb4..90c23cba1be 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 5500e46b408..ca4b16500af 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 00000000000..c586804e705 --- /dev/null +++ b/configs/chromebook_samus_tpl_defconfig @@ -0,0 +1,81 @@ +CONFIG_X86=y +CONFIG_SYS_TEXT_BASE=0xffed0000 +CONFIG_SYS_MALLOC_F_LEN=0x1a00 +CONFIG_NR_DRAM_BANKS=8 +CONFIG_DEBUG_UART_BOARD_INIT=y +CONFIG_DEBUG_UART_BASE=0x3f8 +CONFIG_DEBUG_UART_CLOCK=1843200 +CONFIG_VENDOR_GOOGLE=y +CONFIG_TARGET_CHROMEBOOK_SAMUS_TPL=y +CONFIG_DEBUG_UART=y +CONFIG_HAVE_MRC=y +CONFIG_HAVE_REFCODE=y +CONFIG_SMP=y +CONFIG_HAVE_VGA_BIOS=y +CONFIG_BOOTSTAGE=y +CONFIG_BOOTSTAGE_REPORT=y +CONFIG_USE_BOOTARGS=y +CONFIG_BOOTARGS="root=/dev/sdb3 init=/sbin/init rootwait ro" +CONFIG_SYS_CONSOLE_INFO_QUIET=y +CONFIG_MISC_INIT_R=y +CONFIG_DISPLAY_BOARDINFO_LATE=y +CONFIG_LAST_STAGE_INIT=y +CONFIG_BLOBLIST=y +CONFIG_BLOBLIST_SIZE=0x1000 +CONFIG_BLOBLIST_ADDR=0xff7c0000 +CONFIG_HANDOFF=y +CONFIG_SPL_SEPARATE_BSS=y +CONFIG_SPL_NET_SUPPORT=y +CONFIG_SPL_PCI=y +CONFIG_SPL_PCH_SUPPORT=y +CONFIG_TPL_PCI=y +CONFIG_TPL_PCH_SUPPORT=y +CONFIG_HUSH_PARSER=y +CONFIG_CMD_CPU=y +# CONFIG_CMD_FLASH is not set +CONFIG_CMD_GPIO=y +CONFIG_CMD_I2C=y +CONFIG_CMD_PART=y +CONFIG_CMD_SATA=y +CONFIG_CMD_SF=y +CONFIG_CMD_SPI=y +CONFIG_CMD_USB=y +# CONFIG_CMD_SETEXPR is not set +CONFIG_CMD_TIME=y +CONFIG_CMD_SOUND=y +CONFIG_CMD_BOOTSTAGE=y +CONFIG_CMD_TPM=y +CONFIG_CMD_TPM_TEST=y +CONFIG_CMD_EXT2=y +CONFIG_CMD_EXT4=y +CONFIG_CMD_EXT4_WRITE=y +CONFIG_CMD_FAT=y +CONFIG_CMD_FS_GENERIC=y +CONFIG_MAC_PARTITION=y +# CONFIG_SPL_MAC_PARTITION is not set +# CONFIG_SPL_DOS_PARTITION is not set +CONFIG_ISO_PARTITION=y +CONFIG_EFI_PARTITION=y +# CONFIG_SPL_EFI_PARTITION is not set +CONFIG_DEFAULT_DEVICE_TREE="chromebook_samus" +# CONFIG_NET is not set +CONFIG_REGMAP=y +CONFIG_SYSCON=y +CONFIG_CPU=y +CONFIG_DM_I2C=y +CONFIG_SYS_I2C_DW=y +CONFIG_TPL_MISC=y +CONFIG_CROS_EC=y +CONFIG_CROS_EC_LPC=y +CONFIG_SYS_NS16550=y +CONFIG_SOUND=y +CONFIG_SOUND_I8254=y +CONFIG_SOUND_RT5677=y +CONFIG_SPI=y +CONFIG_TPM_TIS_LPC=y +CONFIG_USB_STORAGE=y +CONFIG_USB_KEYBOARD=y +CONFIG_FRAMEBUFFER_SET_VESA_MODE=y +CONFIG_FRAMEBUFFER_VESA_MODE_11A=y +CONFIG_CONSOLE_SCROLL_LINES=5 +CONFIG_TPM=y diff --git a/include/configs/chromebook_samus.h b/include/configs/chromebook_samus.h index ccb2fe8caad..610be1e7b5e 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 */

Hi Simon,
On Fri, Apr 26, 2019 at 11:59 AM 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.
I've applied 32 patches in this series to u-boot-x86/master. Remaining patches need to rebase on that.
Regards, Bin
participants (4)
-
Bin Meng
-
Heinrich Schuchardt
-
Simon Glass
-
Thierry Reding