[U-Boot] [PATCH v2 00/38] x86: Various modifications to prepare for FSP2

Quite a bit of minor refactoring is needed to prepare for using FSP2 in U-Boot. This series consists of a number of small changes to this end.
It is the last series before apollolake support is added.
Changes include: - Allowing drivers to be used in TPL/SPL - Moving common FSP code into a common directory - Support for memory-mapped flash on newer Intel chips - Passing the HOB list from SPL to U-Boot proper
This series is available at u-boot-dm/x86-working
Changes in v2: - Fix the Kconfig condition to avoid build errors on snow - Add the missing header file - Add support for of-platdata for TPL - Rename the fast SPI headers - Rebase to master
Simon Glass (38): binman: Pass the toolpath to binman from the main Makefile binman: Allow selection of logging verbosity dm: gpio: Allow control of GPIO uclass in SPL mtd: spi: Add 'struct spi_flash {' to the code serial: ns16550: Allow serial to enabled/disabled in SPL spl: Correct priority selection for image loaders spl: Avoid checking for Ctrl-C in SPL with print_buffer() spl: handoff: Correct Kconfig condition for SPL and TPL spl: Add an arch-specific hook for writing to SPL handoff spl: Set up the bloblist in board_init_r() spl: Add a function to determine the U-Boot phase x86: spi: Add a driver for the Intel Fast SPI interface spi: sandbox: Add a test driver for sandbox SPI flash spi: Add support for memory-mapped flash x86: sysreset: Allow reset driver to be included in SPL/TPL x86: Rename some FSP functions to have an fsp_ prefix x86: fsp: Create a common fsp_support.h header x86: fsp: Use if() instead of #ifdef x86: fsp: Tidy up comment style a little x86: fsp: Move common dram functions into a common file x86: Move common fsp functions into a common file x86: fsp: Move common support functions into a common file efi: Move inline functions to unconditional part of header x86: fsp: Add a few more definitions for FSP2 x86: fsp: Add access to variable MRC data x86: Move common Intel CPU info code into a function x86: Add binman symbols to the image x86: pci: Add a function to clear and set PCI config regs x86: spl: Use hang() instead of a while() loop x86: spl: Reduce priority of the basic SPL image loader x86: spl: Move broadwell-specific code out of generic x86 spl x86: fsp: Save usable RAM and hob_list in the handoff area x86: fsp: Allow the HOBs to be used after relocation x86: Change condition for using CAR x86: Add more comments to the start-up code x86: Add support for booting from Fast SPI x86: Add various MTRR indexes and values x86: Rename turbo ratio MSR to MSR_TURBO_RATIO_LIMIT
Makefile | 4 +- arch/sandbox/cpu/spl.c | 7 + arch/sandbox/dts/test.dts | 4 + arch/x86/Kconfig | 8 + arch/x86/cpu/baytrail/fsp_configs.c | 2 +- arch/x86/cpu/braswell/fsp_configs.c | 2 +- arch/x86/cpu/broadwell/cpu.c | 5 + arch/x86/cpu/broadwell/cpu_full.c | 18 +- arch/x86/cpu/cpu.c | 6 + arch/x86/cpu/intel_common/Makefile | 1 + arch/x86/cpu/intel_common/cpu.c | 13 + arch/x86/cpu/intel_common/cpu_from_spl.c | 6 + arch/x86/cpu/intel_common/fast_spi.c | 48 +++ arch/x86/cpu/ivybridge/fsp_configs.c | 2 +- arch/x86/cpu/ivybridge/model_206ax.c | 8 +- arch/x86/cpu/pci.c | 19 ++ arch/x86/cpu/queensbay/fsp_configs.c | 2 +- arch/x86/cpu/start.S | 16 +- arch/x86/cpu/start_from_spl.S | 5 +- arch/x86/cpu/start_from_tpl.S | 3 +- arch/x86/cpu/u-boot-spl.lds | 6 + arch/x86/include/asm/cpu_common.h | 11 + arch/x86/include/asm/fsp/fsp_hob.h | 4 + arch/x86/include/asm/fsp/fsp_infoheader.h | 15 +- arch/x86/include/asm/fsp/fsp_support.h | 174 +++++++++++ arch/x86/include/asm/fsp1/fsp_support.h | 147 +-------- arch/x86/include/asm/handoff.h | 8 + arch/x86/include/asm/hob.h | 26 +- arch/x86/include/asm/msr-index.h | 24 +- arch/x86/include/asm/mtrr.h | 1 + arch/x86/include/asm/pci.h | 40 +++ arch/x86/include/asm/spl.h | 4 +- arch/x86/lib/Makefile | 1 + arch/x86/lib/fsp/Makefile | 7 + arch/x86/lib/fsp/fsp_common.c | 104 +++++++ arch/x86/lib/fsp/fsp_dram.c | 100 ++++++ arch/x86/lib/fsp/fsp_support.c | 199 ++++++++++++ arch/x86/lib/fsp1/fsp_car.S | 10 +- arch/x86/lib/fsp1/fsp_common.c | 96 +----- arch/x86/lib/fsp1/fsp_dram.c | 88 +----- arch/x86/lib/fsp1/fsp_support.c | 181 +---------- arch/x86/lib/hob.c | 19 +- arch/x86/lib/spl.c | 13 +- arch/x86/lib/tpl.c | 7 +- cmd/x86/fsp.c | 2 +- common/spl/Kconfig | 4 +- common/spl/spl.c | 47 +-- configs/slimbootloader_defconfig | 1 + drivers/gpio/Kconfig | 22 ++ drivers/gpio/Makefile | 2 +- drivers/mtd/spi/Kconfig | 9 + drivers/mtd/spi/Makefile | 3 +- drivers/mtd/spi/intel_fast_spi.c | 360 ++++++++++++++++++++++ drivers/mtd/spi/sandbox_direct.c | 110 +++++++ drivers/mtd/spi/sf-uclass.c | 11 + drivers/pci/pci-uclass.c | 2 +- drivers/serial/ns16550.c | 6 +- drivers/sysreset/Kconfig | 12 + drivers/sysreset/Makefile | 2 +- include/config_uncmd_spl.h | 1 - include/efi_loader.h | 10 +- include/handoff.h | 13 + include/linux/mtd/spi-nor.h | 8 +- include/spi_flash.h | 27 ++ include/spl.h | 64 +++- lib/display_options.c | 2 + test/dm/sf.c | 51 +++ tools/binman/README | 6 + 68 files changed, 1662 insertions(+), 577 deletions(-) create mode 100644 arch/x86/cpu/intel_common/fast_spi.c create mode 100644 arch/x86/include/asm/fsp/fsp_support.h create mode 100644 arch/x86/lib/fsp/Makefile create mode 100644 arch/x86/lib/fsp/fsp_common.c create mode 100644 arch/x86/lib/fsp/fsp_dram.c create mode 100644 arch/x86/lib/fsp/fsp_support.c create mode 100644 drivers/mtd/spi/intel_fast_spi.c create mode 100644 drivers/mtd/spi/sandbox_direct.c

Pass in the toolpath in case binman needs to use tools compiled in the U-Boot tools/ directory.
Signed-off-by: Simon Glass sjg@chromium.org ---
Changes in v2: None
Makefile | 1 + 1 file changed, 1 insertion(+)
diff --git a/Makefile b/Makefile index 0178cdffddb..c5caec8267e 100644 --- a/Makefile +++ b/Makefile @@ -1213,6 +1213,7 @@ u-boot.ldr: u-boot # Use 'make BINMAN_DEBUG=1' to enable debugging quiet_cmd_binman = BINMAN $@ cmd_binman = $(srctree)/tools/binman/binman $(if $(BINMAN_DEBUG),-D) \ + --toolpath $(objtree)/tools \ build -u -d u-boot.dtb -O . -m \ -I . -I $(srctree) -I $(srctree)/board/$(BOARDDIR) \ $(BINMAN_$(@F))

On Wed, Sep 25, 2019 at 10:12 PM Simon Glass sjg@chromium.org wrote:
Pass in the toolpath in case binman needs to use tools compiled in the U-Boot tools/ directory.
Signed-off-by: Simon Glass sjg@chromium.org
Changes in v2: None
Makefile | 1 + 1 file changed, 1 insertion(+)
Reviewed-by: Bin Meng bmeng.cn@gmail.com

On Wed, Oct 2, 2019 at 9:55 PM Bin Meng bmeng.cn@gmail.com wrote:
On Wed, Sep 25, 2019 at 10:12 PM Simon Glass sjg@chromium.org wrote:
Pass in the toolpath in case binman needs to use tools compiled in the U-Boot tools/ directory.
Signed-off-by: Simon Glass sjg@chromium.org
Changes in v2: None
Makefile | 1 + 1 file changed, 1 insertion(+)
Reviewed-by: Bin Meng bmeng.cn@gmail.com
applied to u-boot-x86/next, thanks!

Support a new BINMAN_VERBOSE option to the build, to allow passing the -v flag to binman.
Signed-off-by: Simon Glass sjg@chromium.org ---
Changes in v2: None
Makefile | 3 ++- tools/binman/README | 6 ++++++ 2 files changed, 8 insertions(+), 1 deletion(-)
diff --git a/Makefile b/Makefile index c5caec8267e..fd390e19458 100644 --- a/Makefile +++ b/Makefile @@ -1214,7 +1214,8 @@ u-boot.ldr: u-boot quiet_cmd_binman = BINMAN $@ cmd_binman = $(srctree)/tools/binman/binman $(if $(BINMAN_DEBUG),-D) \ --toolpath $(objtree)/tools \ - build -u -d u-boot.dtb -O . -m \ + $(if $(BINMAN_VERBOSE),-v$(BINMAN_VERBOSE)) \ + build -u -d u-boot.dtb -O . -m \ -I . -I $(srctree) -I $(srctree)/board/$(BOARDDIR) \ $(BINMAN_$(@F))
diff --git a/tools/binman/README b/tools/binman/README index b4f6392ab74..8e0f0a8c55b 100644 --- a/tools/binman/README +++ b/tools/binman/README @@ -934,6 +934,12 @@ BINMAN_DEBUG=1 to your build: make sandbox_defconfig make BINMAN_DEBUG=1
+To enable verbose logging from binman, base BINMAN_VERBOSE to your build, which +adds a -v<level> option to the call to binman: + + make sandbox_defconfig + make BINMAN_VERBOSE=5 +
History / Credits -----------------

On Wed, Sep 25, 2019 at 10:12 PM Simon Glass sjg@chromium.org wrote:
Support a new BINMAN_VERBOSE option to the build, to allow passing the -v flag to binman.
Signed-off-by: Simon Glass sjg@chromium.org
Changes in v2: None
Makefile | 3 ++- tools/binman/README | 6 ++++++ 2 files changed, 8 insertions(+), 1 deletion(-)
diff --git a/Makefile b/Makefile index c5caec8267e..fd390e19458 100644 --- a/Makefile +++ b/Makefile @@ -1214,7 +1214,8 @@ u-boot.ldr: u-boot quiet_cmd_binman = BINMAN $@ cmd_binman = $(srctree)/tools/binman/binman $(if $(BINMAN_DEBUG),-D) \ --toolpath $(objtree)/tools \
build -u -d u-boot.dtb -O . -m \
$(if $(BINMAN_VERBOSE),-v$(BINMAN_VERBOSE)) \
build -u -d u-boot.dtb -O . -m \ -I . -I $(srctree) -I $(srctree)/board/$(BOARDDIR) \ $(BINMAN_$(@F))
diff --git a/tools/binman/README b/tools/binman/README index b4f6392ab74..8e0f0a8c55b 100644 --- a/tools/binman/README +++ b/tools/binman/README @@ -934,6 +934,12 @@ BINMAN_DEBUG=1 to your build: make sandbox_defconfig make BINMAN_DEBUG=1
+To enable verbose logging from binman, base BINMAN_VERBOSE to your build, which +adds a -v<level> option to the call to binman:
- make sandbox_defconfig
I don't see sandbox_defconfig enables BINMAN. Shouldn't it be qemu-x86_defconfig?
- make BINMAN_VERBOSE=5
History / Credits
--
Other than that, Reviewed-by: Bin Meng bmeng.cn@gmail.com Tested-by: Bin Meng bmeng.cn@gmail.com
Regards, Bin

On Wed, Oct 2, 2019 at 9:56 PM Bin Meng bmeng.cn@gmail.com wrote:
On Wed, Sep 25, 2019 at 10:12 PM Simon Glass sjg@chromium.org wrote:
Support a new BINMAN_VERBOSE option to the build, to allow passing the -v flag to binman.
Signed-off-by: Simon Glass sjg@chromium.org
Changes in v2: None
Makefile | 3 ++- tools/binman/README | 6 ++++++ 2 files changed, 8 insertions(+), 1 deletion(-)
diff --git a/Makefile b/Makefile index c5caec8267e..fd390e19458 100644 --- a/Makefile +++ b/Makefile @@ -1214,7 +1214,8 @@ u-boot.ldr: u-boot quiet_cmd_binman = BINMAN $@ cmd_binman = $(srctree)/tools/binman/binman $(if $(BINMAN_DEBUG),-D) \ --toolpath $(objtree)/tools \
build -u -d u-boot.dtb -O . -m \
$(if $(BINMAN_VERBOSE),-v$(BINMAN_VERBOSE)) \
build -u -d u-boot.dtb -O . -m \ -I . -I $(srctree) -I $(srctree)/board/$(BOARDDIR) \ $(BINMAN_$(@F))
diff --git a/tools/binman/README b/tools/binman/README index b4f6392ab74..8e0f0a8c55b 100644 --- a/tools/binman/README +++ b/tools/binman/README @@ -934,6 +934,12 @@ BINMAN_DEBUG=1 to your build: make sandbox_defconfig make BINMAN_DEBUG=1
+To enable verbose logging from binman, base BINMAN_VERBOSE to your build, which +adds a -v<level> option to the call to binman:
- make sandbox_defconfig
I don't see sandbox_defconfig enables BINMAN. Shouldn't it be qemu-x86_defconfig?
I will send a separate patch to correct the defconfig.
- make BINMAN_VERBOSE=5
History / Credits
--
Other than that, Reviewed-by: Bin Meng bmeng.cn@gmail.com Tested-by: Bin Meng bmeng.cn@gmail.com
applied to u-boot-x86/next, thanks!

At present if CONFIG_SPL_GPIO_SUPPORT is enabled then the GPIO uclass is included in SPL/TPL without any control for boards. Some boards may want to disable this to reduce code size where GPIOs are not needed in SPL or TPL.
Add a new Kconfig option to permit this. Default it to 'y' so that existing boards work correctly. This allows us to remove the hack in config_uncmd_spl.h (eventually that file should be removed).
Signed-off-by: Simon Glass sjg@chromium.org ---
Changes in v2: - Fix the Kconfig condition to avoid build errors on snow
drivers/gpio/Kconfig | 22 ++++++++++++++++++++++ drivers/gpio/Makefile | 2 +- include/config_uncmd_spl.h | 1 - 3 files changed, 23 insertions(+), 2 deletions(-)
diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig index f2dabb554fa..11a242d7aa8 100644 --- a/drivers/gpio/Kconfig +++ b/drivers/gpio/Kconfig @@ -14,6 +14,28 @@ config DM_GPIO particular GPIOs that they provide. The uclass interface is defined in include/asm-generic/gpio.h.
+config SPL_DM_GPIO + bool "Enable Driver Model for GPIO drivers in SPL" + depends on DM_GPIO && SPL_DM && SPL_GPIO_SUPPORT + default y + help + Enable driver model for GPIO access. The standard GPIO + interface (gpio_get_value(), etc.) is then implemented by + the GPIO uclass. Drivers provide methods to query the + particular GPIOs that they provide. The uclass interface + is defined in include/asm-generic/gpio.h. + +config TPL_DM_GPIO + bool "Enable Driver Model for GPIO drivers in TPL" + depends on DM_GPIO && TPL_DM && TPL_GPIO_SUPPORT + default y + help + Enable driver model for GPIO access. The standard GPIO + interface (gpio_get_value(), etc.) is then implemented by + the GPIO uclass. Drivers provide methods to query the + particular GPIOs that they provide. The uclass interface + is defined in include/asm-generic/gpio.h. + config GPIO_HOG bool "Enable GPIO hog support" depends on DM_GPIO diff --git a/drivers/gpio/Makefile b/drivers/gpio/Makefile index 4a8aa0ff6fe..56e9374e308 100644 --- a/drivers/gpio/Makefile +++ b/drivers/gpio/Makefile @@ -7,7 +7,7 @@ ifndef CONFIG_SPL_BUILD obj-$(CONFIG_DWAPB_GPIO) += dwapb_gpio.o obj-$(CONFIG_AXP_GPIO) += axp_gpio.o endif -obj-$(CONFIG_DM_GPIO) += gpio-uclass.o +obj-$(CONFIG_$(SPL_TPL_)DM_GPIO) += gpio-uclass.o
obj-$(CONFIG_$(SPL_)DM_PCA953X) += pca953x_gpio.o obj-$(CONFIG_DM_74X164) += 74x164_gpio.o diff --git a/include/config_uncmd_spl.h b/include/config_uncmd_spl.h index c2f9735ce79..31da6215b3a 100644 --- a/include/config_uncmd_spl.h +++ b/include/config_uncmd_spl.h @@ -12,7 +12,6 @@
#ifndef CONFIG_SPL_DM #undef CONFIG_DM_SERIAL -#undef CONFIG_DM_GPIO #undef CONFIG_DM_I2C #undef CONFIG_DM_SPI #endif

On Wed, Sep 25, 2019 at 10:12 PM Simon Glass sjg@chromium.org wrote:
At present if CONFIG_SPL_GPIO_SUPPORT is enabled then the GPIO uclass is included in SPL/TPL without any control for boards. Some boards may want to disable this to reduce code size where GPIOs are not needed in SPL or TPL.
Add a new Kconfig option to permit this. Default it to 'y' so that existing boards work correctly. This allows us to remove the hack in config_uncmd_spl.h (eventually that file should be removed).
Signed-off-by: Simon Glass sjg@chromium.org
Changes in v2:
- Fix the Kconfig condition to avoid build errors on snow
drivers/gpio/Kconfig | 22 ++++++++++++++++++++++ drivers/gpio/Makefile | 2 +- include/config_uncmd_spl.h | 1 - 3 files changed, 23 insertions(+), 2 deletions(-)
diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig index f2dabb554fa..11a242d7aa8 100644 --- a/drivers/gpio/Kconfig +++ b/drivers/gpio/Kconfig @@ -14,6 +14,28 @@ config DM_GPIO particular GPIOs that they provide. The uclass interface is defined in include/asm-generic/gpio.h.
+config SPL_DM_GPIO
bool "Enable Driver Model for GPIO drivers in SPL"
depends on DM_GPIO && SPL_DM && SPL_GPIO_SUPPORT
default y
help
Enable driver model for GPIO access. The standard GPIO
nits: Enable driver model for GPIO access in SPL.
interface (gpio_get_value(), etc.) is then implemented by
the GPIO uclass. Drivers provide methods to query the
particular GPIOs that they provide. The uclass interface
is defined in include/asm-generic/gpio.h.
+config TPL_DM_GPIO
bool "Enable Driver Model for GPIO drivers in TPL"
depends on DM_GPIO && TPL_DM && TPL_GPIO_SUPPORT
default y
help
Enable driver model for GPIO access. The standard GPIO
nits: Enable driver model for GPIO access in TPL.
interface (gpio_get_value(), etc.) is then implemented by
the GPIO uclass. Drivers provide methods to query the
particular GPIOs that they provide. The uclass interface
is defined in include/asm-generic/gpio.h.
config GPIO_HOG bool "Enable GPIO hog support" depends on DM_GPIO diff --git a/drivers/gpio/Makefile b/drivers/gpio/Makefile index 4a8aa0ff6fe..56e9374e308 100644 --- a/drivers/gpio/Makefile +++ b/drivers/gpio/Makefile @@ -7,7 +7,7 @@ ifndef CONFIG_SPL_BUILD obj-$(CONFIG_DWAPB_GPIO) += dwapb_gpio.o obj-$(CONFIG_AXP_GPIO) += axp_gpio.o endif -obj-$(CONFIG_DM_GPIO) += gpio-uclass.o +obj-$(CONFIG_$(SPL_TPL_)DM_GPIO) += gpio-uclass.o
obj-$(CONFIG_$(SPL_)DM_PCA953X) += pca953x_gpio.o obj-$(CONFIG_DM_74X164) += 74x164_gpio.o diff --git a/include/config_uncmd_spl.h b/include/config_uncmd_spl.h index c2f9735ce79..31da6215b3a 100644 --- a/include/config_uncmd_spl.h +++ b/include/config_uncmd_spl.h @@ -12,7 +12,6 @@
#ifndef CONFIG_SPL_DM #undef CONFIG_DM_SERIAL -#undef CONFIG_DM_GPIO #undef CONFIG_DM_I2C #undef CONFIG_DM_SPI
#endif
Other than that, Reviewed-by: Bin Meng bmeng.cn@gmail.com

On Wed, Oct 2, 2019 at 9:56 PM Bin Meng bmeng.cn@gmail.com wrote:
On Wed, Sep 25, 2019 at 10:12 PM Simon Glass sjg@chromium.org wrote:
At present if CONFIG_SPL_GPIO_SUPPORT is enabled then the GPIO uclass is included in SPL/TPL without any control for boards. Some boards may want to disable this to reduce code size where GPIOs are not needed in SPL or TPL.
Add a new Kconfig option to permit this. Default it to 'y' so that existing boards work correctly. This allows us to remove the hack in config_uncmd_spl.h (eventually that file should be removed).
Signed-off-by: Simon Glass sjg@chromium.org
Changes in v2:
- Fix the Kconfig condition to avoid build errors on snow
drivers/gpio/Kconfig | 22 ++++++++++++++++++++++ drivers/gpio/Makefile | 2 +- include/config_uncmd_spl.h | 1 - 3 files changed, 23 insertions(+), 2 deletions(-)
diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig index f2dabb554fa..11a242d7aa8 100644 --- a/drivers/gpio/Kconfig +++ b/drivers/gpio/Kconfig @@ -14,6 +14,28 @@ config DM_GPIO particular GPIOs that they provide. The uclass interface is defined in include/asm-generic/gpio.h.
+config SPL_DM_GPIO
bool "Enable Driver Model for GPIO drivers in SPL"
depends on DM_GPIO && SPL_DM && SPL_GPIO_SUPPORT
default y
help
Enable driver model for GPIO access. The standard GPIO
nits: Enable driver model for GPIO access in SPL.
interface (gpio_get_value(), etc.) is then implemented by
the GPIO uclass. Drivers provide methods to query the
particular GPIOs that they provide. The uclass interface
is defined in include/asm-generic/gpio.h.
+config TPL_DM_GPIO
bool "Enable Driver Model for GPIO drivers in TPL"
depends on DM_GPIO && TPL_DM && TPL_GPIO_SUPPORT
default y
help
Enable driver model for GPIO access. The standard GPIO
nits: Enable driver model for GPIO access in TPL.
interface (gpio_get_value(), etc.) is then implemented by
the GPIO uclass. Drivers provide methods to query the
particular GPIOs that they provide. The uclass interface
is defined in include/asm-generic/gpio.h.
config GPIO_HOG bool "Enable GPIO hog support" depends on DM_GPIO diff --git a/drivers/gpio/Makefile b/drivers/gpio/Makefile index 4a8aa0ff6fe..56e9374e308 100644 --- a/drivers/gpio/Makefile +++ b/drivers/gpio/Makefile @@ -7,7 +7,7 @@ ifndef CONFIG_SPL_BUILD obj-$(CONFIG_DWAPB_GPIO) += dwapb_gpio.o obj-$(CONFIG_AXP_GPIO) += axp_gpio.o endif -obj-$(CONFIG_DM_GPIO) += gpio-uclass.o +obj-$(CONFIG_$(SPL_TPL_)DM_GPIO) += gpio-uclass.o
obj-$(CONFIG_$(SPL_)DM_PCA953X) += pca953x_gpio.o obj-$(CONFIG_DM_74X164) += 74x164_gpio.o diff --git a/include/config_uncmd_spl.h b/include/config_uncmd_spl.h index c2f9735ce79..31da6215b3a 100644 --- a/include/config_uncmd_spl.h +++ b/include/config_uncmd_spl.h @@ -12,7 +12,6 @@
#ifndef CONFIG_SPL_DM #undef CONFIG_DM_SERIAL -#undef CONFIG_DM_GPIO #undef CONFIG_DM_I2C #undef CONFIG_DM_SPI
#endif
Other than that, Reviewed-by: Bin Meng bmeng.cn@gmail.com
Fixed the nits, and applied to u-boot-x86/next, thanks!

Hi Simon,
On Thu, Oct 3, 2019 at 10:02 AM Bin Meng bmeng.cn@gmail.com wrote:
On Wed, Oct 2, 2019 at 9:56 PM Bin Meng bmeng.cn@gmail.com wrote:
On Wed, Sep 25, 2019 at 10:12 PM Simon Glass sjg@chromium.org wrote:
At present if CONFIG_SPL_GPIO_SUPPORT is enabled then the GPIO uclass is included in SPL/TPL without any control for boards. Some boards may want to disable this to reduce code size where GPIOs are not needed in SPL or TPL.
Add a new Kconfig option to permit this. Default it to 'y' so that existing boards work correctly. This allows us to remove the hack in config_uncmd_spl.h (eventually that file should be removed).
Signed-off-by: Simon Glass sjg@chromium.org
Changes in v2:
- Fix the Kconfig condition to avoid build errors on snow
drivers/gpio/Kconfig | 22 ++++++++++++++++++++++ drivers/gpio/Makefile | 2 +- include/config_uncmd_spl.h | 1 - 3 files changed, 23 insertions(+), 2 deletions(-)
diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig index f2dabb554fa..11a242d7aa8 100644 --- a/drivers/gpio/Kconfig +++ b/drivers/gpio/Kconfig @@ -14,6 +14,28 @@ config DM_GPIO particular GPIOs that they provide. The uclass interface is defined in include/asm-generic/gpio.h.
+config SPL_DM_GPIO
bool "Enable Driver Model for GPIO drivers in SPL"
depends on DM_GPIO && SPL_DM && SPL_GPIO_SUPPORT
default y
help
Enable driver model for GPIO access. The standard GPIO
nits: Enable driver model for GPIO access in SPL.
interface (gpio_get_value(), etc.) is then implemented by
the GPIO uclass. Drivers provide methods to query the
particular GPIOs that they provide. The uclass interface
is defined in include/asm-generic/gpio.h.
+config TPL_DM_GPIO
bool "Enable Driver Model for GPIO drivers in TPL"
depends on DM_GPIO && TPL_DM && TPL_GPIO_SUPPORT
default y
help
Enable driver model for GPIO access. The standard GPIO
nits: Enable driver model for GPIO access in TPL.
interface (gpio_get_value(), etc.) is then implemented by
the GPIO uclass. Drivers provide methods to query the
particular GPIOs that they provide. The uclass interface
is defined in include/asm-generic/gpio.h.
config GPIO_HOG bool "Enable GPIO hog support" depends on DM_GPIO diff --git a/drivers/gpio/Makefile b/drivers/gpio/Makefile index 4a8aa0ff6fe..56e9374e308 100644 --- a/drivers/gpio/Makefile +++ b/drivers/gpio/Makefile @@ -7,7 +7,7 @@ ifndef CONFIG_SPL_BUILD obj-$(CONFIG_DWAPB_GPIO) += dwapb_gpio.o obj-$(CONFIG_AXP_GPIO) += axp_gpio.o endif -obj-$(CONFIG_DM_GPIO) += gpio-uclass.o +obj-$(CONFIG_$(SPL_TPL_)DM_GPIO) += gpio-uclass.o
obj-$(CONFIG_$(SPL_)DM_PCA953X) += pca953x_gpio.o obj-$(CONFIG_DM_74X164) += 74x164_gpio.o diff --git a/include/config_uncmd_spl.h b/include/config_uncmd_spl.h index c2f9735ce79..31da6215b3a 100644 --- a/include/config_uncmd_spl.h +++ b/include/config_uncmd_spl.h @@ -12,7 +12,6 @@
#ifndef CONFIG_SPL_DM #undef CONFIG_DM_SERIAL -#undef CONFIG_DM_GPIO #undef CONFIG_DM_I2C #undef CONFIG_DM_SPI
#endif
Other than that, Reviewed-by: Bin Meng bmeng.cn@gmail.com
Fixed the nits, and applied to u-boot-x86/next, thanks!
Unfortunately this patch breaks a number of ARM boards. See https://gitlab.denx.de/u-boot/custodians/u-boot-x86/-/jobs/15885 https://gitlab.denx.de/u-boot/custodians/u-boot-x86/-/jobs/16012
I will have to drop this patch from the queue.
Regards, Bin

At present spi_flash is defined to be spi_nor which is confusing since it is not possible to find the 'spi_flash' by normal text search. Add a comment to help with this.
Signed-off-by: Simon Glass sjg@chromium.org ---
Changes in v2: None
include/linux/mtd/spi-nor.h | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-)
diff --git a/include/linux/mtd/spi-nor.h b/include/linux/mtd/spi-nor.h index 709b49d3936..f9964a76645 100644 --- a/include/linux/mtd/spi-nor.h +++ b/include/linux/mtd/spi-nor.h @@ -246,7 +246,13 @@ enum spi_nor_option_flags { */ struct flash_info;
-/* TODO: Remove, once all users of spi_flash interface are moved to MTD */ +/* + * TODO: Remove, once all users of spi_flash interface are moved to MTD + * + * struct spi_flash { + * Defined below (keep this text to enable searching for spi_flash decl) + * } + */ #define spi_flash spi_nor
/**

On Wed, Sep 25, 2019 at 10:12 PM Simon Glass sjg@chromium.org wrote:
At present spi_flash is defined to be spi_nor which is confusing since it is not possible to find the 'spi_flash' by normal text search. Add a comment to help with this.
Signed-off-by: Simon Glass sjg@chromium.org
Changes in v2: None
include/linux/mtd/spi-nor.h | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-)
Reviewed-by: Bin Meng bmeng.cn@gmail.com

On Wed, Oct 2, 2019 at 9:56 PM Bin Meng bmeng.cn@gmail.com wrote:
On Wed, Sep 25, 2019 at 10:12 PM Simon Glass sjg@chromium.org wrote:
At present spi_flash is defined to be spi_nor which is confusing since it is not possible to find the 'spi_flash' by normal text search. Add a comment to help with this.
Signed-off-by: Simon Glass sjg@chromium.org
Changes in v2: None
include/linux/mtd/spi-nor.h | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-)
Reviewed-by: Bin Meng bmeng.cn@gmail.com
applied to u-boot-x86/next, thanks!

At present this driver uses the wrong condition for including the code and drivers in SPL/TPL. Update it so that the code is only included if DM_SERIAL is enabled for SPL/TPL.
Signed-off-by: Simon Glass sjg@chromium.org ---
Changes in v2: None
drivers/serial/ns16550.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/drivers/serial/ns16550.c b/drivers/serial/ns16550.c index 6cf2be8f2b8..01f334938ea 100644 --- a/drivers/serial/ns16550.c +++ b/drivers/serial/ns16550.c @@ -21,7 +21,7 @@ DECLARE_GLOBAL_DATA_PTR; #define UART_MCRVAL (UART_MCR_DTR | \ UART_MCR_RTS) /* RTS/DTR */
-#ifndef CONFIG_DM_SERIAL +#if !CONFIG_IS_ENABLED(DM_SERIAL) #ifdef CONFIG_SYS_NS16550_PORT_MAPPED #define serial_out(x, y) outb(x, (ulong)y) #define serial_in(y) inb((ulong)y) @@ -86,7 +86,7 @@ static inline int serial_in_shift(void *addr, int shift) #endif }
-#ifdef CONFIG_DM_SERIAL +#if CONFIG_IS_ENABLED(DM_SERIAL)
#ifndef CONFIG_SYS_NS16550_CLK #define CONFIG_SYS_NS16550_CLK 0 @@ -301,7 +301,7 @@ DEBUG_UART_FUNCS
#endif
-#ifdef CONFIG_DM_SERIAL +#if CONFIG_IS_ENABLED(DM_SERIAL) static int ns16550_serial_putc(struct udevice *dev, const char ch) { struct NS16550 *const com_port = dev_get_priv(dev);

On Wed, Sep 25, 2019 at 10:12 PM Simon Glass sjg@chromium.org wrote:
At present this driver uses the wrong condition for including the code and drivers in SPL/TPL. Update it so that the code is only included if DM_SERIAL is enabled for SPL/TPL.
Signed-off-by: Simon Glass sjg@chromium.org
Changes in v2: None
drivers/serial/ns16550.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-)
Reviewed-by: Bin Meng bmeng.cn@gmail.com

On Wed, Oct 2, 2019 at 9:56 PM Bin Meng bmeng.cn@gmail.com wrote:
On Wed, Sep 25, 2019 at 10:12 PM Simon Glass sjg@chromium.org wrote:
At present this driver uses the wrong condition for including the code and drivers in SPL/TPL. Update it so that the code is only included if DM_SERIAL is enabled for SPL/TPL.
Signed-off-by: Simon Glass sjg@chromium.org
Changes in v2: None
drivers/serial/ns16550.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-)
Reviewed-by: Bin Meng bmeng.cn@gmail.com
applied to u-boot-x86/next, thanks!

At present the name of the image comes first in the linker-list symbol used. This means that the name of the function sets the sort order, which is not the intention.
Update it to put the board device type first, then the priority. This produces the expected behaviour.
Signed-off-by: Simon Glass sjg@chromium.org ---
Changes in v2: None
include/spl.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/include/spl.h b/include/spl.h index e4640f3830b..4bc35cb0e77 100644 --- a/include/spl.h +++ b/include/spl.h @@ -254,14 +254,14 @@ struct spl_image_loader { */ #ifdef CONFIG_SPL_LIBCOMMON_SUPPORT #define SPL_LOAD_IMAGE_METHOD(_name, _priority, _boot_device, _method) \ - SPL_LOAD_IMAGE(_method ## _priority ## _boot_device) = { \ + SPL_LOAD_IMAGE(_boot_device ## _priority ## _method) = { \ .name = _name, \ .boot_device = _boot_device, \ .load_image = _method, \ } #else #define SPL_LOAD_IMAGE_METHOD(_name, _priority, _boot_device, _method) \ - SPL_LOAD_IMAGE(_method ## _priority ## _boot_device) = { \ + SPL_LOAD_IMAGE(_boot_device ## _priority ## _method) = { \ .boot_device = _boot_device, \ .load_image = _method, \ }

On Wed, Sep 25, 2019 at 4:15 PM Simon Glass sjg@chromium.org wrote:
At present the name of the image comes first in the linker-list symbol used. This means that the name of the function sets the sort order, which is not the intention.
Update it to put the board device type first, then the priority. This
Did you mean "boot device type"?
Regards, Simon
produces the expected behaviour.
Signed-off-by: Simon Glass sjg@chromium.org
Changes in v2: None
include/spl.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/include/spl.h b/include/spl.h index e4640f3830b..4bc35cb0e77 100644 --- a/include/spl.h +++ b/include/spl.h @@ -254,14 +254,14 @@ struct spl_image_loader { */ #ifdef CONFIG_SPL_LIBCOMMON_SUPPORT #define SPL_LOAD_IMAGE_METHOD(_name, _priority, _boot_device, _method) \
SPL_LOAD_IMAGE(_method ## _priority ## _boot_device) = { \
SPL_LOAD_IMAGE(_boot_device ## _priority ## _method) = { \ .name = _name, \ .boot_device = _boot_device, \ .load_image = _method, \ }
#else #define SPL_LOAD_IMAGE_METHOD(_name, _priority, _boot_device, _method) \
SPL_LOAD_IMAGE(_method ## _priority ## _boot_device) = { \
SPL_LOAD_IMAGE(_boot_device ## _priority ## _method) = { \ .boot_device = _boot_device, \ .load_image = _method, \ }
-- 2.23.0.444.g18eeb5a265-goog
U-Boot mailing list U-Boot@lists.denx.de https://lists.denx.de/listinfo/u-boot

We don't have a console in SPL so it doesn't make sense to check for Ctrl-C when printing a memory dump. Skip this so that print_buffer() can be used in SPL.
Signed-off-by: Simon Glass sjg@chromium.org ---
Changes in v2: None
lib/display_options.c | 2 ++ 1 file changed, 2 insertions(+)
diff --git a/lib/display_options.c b/lib/display_options.c index cff20f37552..ec16d75e0e4 100644 --- a/lib/display_options.c +++ b/lib/display_options.c @@ -205,8 +205,10 @@ int print_buffer(ulong addr, const void *data, uint width, uint count, addr += thislinelen * width; count -= thislinelen;
+#ifndef CONFIG_SPL_BUILD if (ctrlc()) return -1; +#endif }
return 0;

On Wed, Sep 25, 2019 at 10:12 PM Simon Glass sjg@chromium.org wrote:
We don't have a console in SPL so it doesn't make sense to check for Ctrl-C when printing a memory dump. Skip this so that print_buffer() can be used in SPL.
Signed-off-by: Simon Glass sjg@chromium.org
Changes in v2: None
lib/display_options.c | 2 ++ 1 file changed, 2 insertions(+)
Reviewed-by: Bin Meng bmeng.cn@gmail.com

On Wed, Oct 2, 2019 at 9:58 PM Bin Meng bmeng.cn@gmail.com wrote:
On Wed, Sep 25, 2019 at 10:12 PM Simon Glass sjg@chromium.org wrote:
We don't have a console in SPL so it doesn't make sense to check for Ctrl-C when printing a memory dump. Skip this so that print_buffer() can be used in SPL.
Signed-off-by: Simon Glass sjg@chromium.org
Changes in v2: None
lib/display_options.c | 2 ++ 1 file changed, 2 insertions(+)
Reviewed-by: Bin Meng bmeng.cn@gmail.com
applied to u-boot-x86/next, thanks!

At present these options can be enabled when bloblist is not enabled for SPL or TPL. This is incorrect as SPL handoff requires bloblist. Fix it.
Signed-off-by: Simon Glass sjg@chromium.org ---
Changes in v2: None
common/spl/Kconfig | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/common/spl/Kconfig b/common/spl/Kconfig index f467eca2be7..62b93c112b1 100644 --- a/common/spl/Kconfig +++ b/common/spl/Kconfig @@ -115,7 +115,7 @@ if SPL
config SPL_HANDOFF bool "Pass hand-off information from SPL to U-Boot proper" - depends on HANDOFF + depends on HANDOFF && SPL_BLOBLIST default y help This option enables SPL to write handoff information. This can be @@ -1185,7 +1185,7 @@ if TPL
config TPL_HANDOFF bool "Pass hand-off information from TPL to SPL and U-Boot proper" - depends on HANDOFF + depends on HANDOFF && TPL_BLOBLIST default y help This option enables TPL to write handoff information. This can be

On Wed, Sep 25, 2019 at 10:12 PM Simon Glass sjg@chromium.org wrote:
At present these options can be enabled when bloblist is not enabled for SPL or TPL. This is incorrect as SPL handoff requires bloblist. Fix it.
Signed-off-by: Simon Glass sjg@chromium.org
Changes in v2: None
common/spl/Kconfig | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
Reviewed-by: Bin Meng bmeng.cn@gmail.com

On Wed, Oct 2, 2019 at 9:58 PM Bin Meng bmeng.cn@gmail.com wrote:
On Wed, Sep 25, 2019 at 10:12 PM Simon Glass sjg@chromium.org wrote:
At present these options can be enabled when bloblist is not enabled for SPL or TPL. This is incorrect as SPL handoff requires bloblist. Fix it.
Signed-off-by: Simon Glass sjg@chromium.org
Changes in v2: None
common/spl/Kconfig | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
Reviewed-by: Bin Meng bmeng.cn@gmail.com
applied to u-boot-x86/next, thanks!

At present there is an arch-specific area in the SPL handoff area intended for use by arch-specific code, but there is no explicit call to fill in this data. Add a hook for this.
Also use the hook to remove the sandbox-specific test code from write_spl_handoff().
Signed-off-by: Simon Glass sjg@chromium.org ---
Changes in v2: None
arch/sandbox/cpu/spl.c | 7 +++++++ common/spl/spl.c | 12 +++++++++--- include/handoff.h | 13 +++++++++++++ 3 files changed, 29 insertions(+), 3 deletions(-)
diff --git a/arch/sandbox/cpu/spl.c b/arch/sandbox/cpu/spl.c index 4f415c71d63..44c68a39bc6 100644 --- a/arch/sandbox/cpu/spl.c +++ b/arch/sandbox/cpu/spl.c @@ -78,3 +78,10 @@ void __noreturn jump_to_image_no_args(struct spl_image_info *spl_image) } hang(); } + +int handoff_arch_save(struct spl_handoff *ho) +{ + ho->arch.magic = TEST_HANDOFF_MAGIC; + + return 0; +} diff --git a/common/spl/spl.c b/common/spl/spl.c index 082fa2bd94d..730cd6b3084 100644 --- a/common/spl/spl.c +++ b/common/spl/spl.c @@ -356,17 +356,23 @@ static int setup_spl_handoff(void) return 0; }
+__weak int handoff_arch_save(struct spl_handoff *ho) +{ + return 0; +} + static int write_spl_handoff(void) { struct spl_handoff *ho; + int ret;
ho = bloblist_find(BLOBLISTT_SPL_HANDOFF, sizeof(struct spl_handoff)); if (!ho) return -ENOENT; handoff_save_dram(ho); -#ifdef CONFIG_SANDBOX - ho->arch.magic = TEST_HANDOFF_MAGIC; -#endif + ret = handoff_arch_save(ho); + if (ret) + return ret; debug(SPL_TPL_PROMPT "Wrote SPL handoff\n");
return 0; diff --git a/include/handoff.h b/include/handoff.h index aacb0f5ebf2..75d19b1f6e5 100644 --- a/include/handoff.h +++ b/include/handoff.h @@ -31,6 +31,19 @@ struct spl_handoff { void handoff_save_dram(struct spl_handoff *ho); void handoff_load_dram_size(struct spl_handoff *ho); void handoff_load_dram_banks(struct spl_handoff *ho); + +/** + * handoff_arch_save() - Save arch-specific info into the handoff area + * + * This is defined to an empty function by default, but arch-specific code can + * define it to write to spi_handoff->arch. It is called from + * write_spl_handoff(). + * + * @ho: Handoff area to fill in + * @return 0 if OK, -ve on error + */ +int handoff_arch_save(struct spl_handoff *ho); + #endif
#endif

On Wed, Sep 25, 2019 at 10:12 PM Simon Glass sjg@chromium.org wrote:
At present there is an arch-specific area in the SPL handoff area intended for use by arch-specific code, but there is no explicit call to fill in this data. Add a hook for this.
Also use the hook to remove the sandbox-specific test code from write_spl_handoff().
Signed-off-by: Simon Glass sjg@chromium.org
Changes in v2: None
arch/sandbox/cpu/spl.c | 7 +++++++ common/spl/spl.c | 12 +++++++++--- include/handoff.h | 13 +++++++++++++ 3 files changed, 29 insertions(+), 3 deletions(-)
Reviewed-by: Bin Meng bmeng.cn@gmail.com

On Wed, Oct 2, 2019 at 9:58 PM Bin Meng bmeng.cn@gmail.com wrote:
On Wed, Sep 25, 2019 at 10:12 PM Simon Glass sjg@chromium.org wrote:
At present there is an arch-specific area in the SPL handoff area intended for use by arch-specific code, but there is no explicit call to fill in this data. Add a hook for this.
Also use the hook to remove the sandbox-specific test code from write_spl_handoff().
Signed-off-by: Simon Glass sjg@chromium.org
Changes in v2: None
arch/sandbox/cpu/spl.c | 7 +++++++ common/spl/spl.c | 12 +++++++++--- include/handoff.h | 13 +++++++++++++ 3 files changed, 29 insertions(+), 3 deletions(-)
Reviewed-by: Bin Meng bmeng.cn@gmail.com
applied to u-boot-x86/next, thanks!

At present the bloblist is set up in spl_common_init() which can be called from spl_early_init(), i.e. before SDRAM is ready. This prevents the bloblist from being located in SDRAM, which is useful on some platforms where SRAM is inaccessible after U-Boot relocates (e.g. x86 CAR region).
It doesn't serve much purpose to have the bloblist available early, since very little is known about the platform then, and the handoff info is written when SPL is about to jump to U-Boot.
Move the code to board_init_r() to avoid any restrictions.
Signed-off-by: Simon Glass sjg@chromium.org ---
Changes in v2: None
common/spl/spl.c | 35 ++++++++++++++++++----------------- 1 file changed, 18 insertions(+), 17 deletions(-)
diff --git a/common/spl/spl.c b/common/spl/spl.c index 730cd6b3084..5fdd6d0d032 100644 --- a/common/spl/spl.c +++ b/common/spl/spl.c @@ -410,23 +410,6 @@ static int spl_common_init(bool setup_malloc) return ret; } #endif - if (CONFIG_IS_ENABLED(BLOBLIST)) { - ret = bloblist_init(); - if (ret) { - debug("%s: Failed to set up bloblist: ret=%d\n", - __func__, ret); - return ret; - } - } - if (CONFIG_IS_ENABLED(HANDOFF)) { - int ret; - - ret = setup_spl_handoff(); - if (ret) { - puts(SPL_TPL_PROMPT "Cannot set up SPL handoff\n"); - hang(); - } - } if (CONFIG_IS_ENABLED(OF_CONTROL) && !CONFIG_IS_ENABLED(OF_PLATDATA)) { ret = fdtdec_setup(); if (ret) { @@ -604,6 +587,24 @@ void board_init_r(gd_t *dummy1, ulong dummy2) */ timer_init(); #endif + if (CONFIG_IS_ENABLED(BLOBLIST)) { + ret = bloblist_init(); + if (ret) { + debug("%s: Failed to set up bloblist: ret=%d\n", + __func__, ret); + puts(SPL_TPL_PROMPT "Cannot set up bloblist\n"); + hang(); + } + } + if (CONFIG_IS_ENABLED(HANDOFF)) { + int ret; + + ret = setup_spl_handoff(); + if (ret) { + puts(SPL_TPL_PROMPT "Cannot set up SPL handoff\n"); + hang(); + } + }
#if CONFIG_IS_ENABLED(BOARD_INIT) spl_board_init();

On Wed, Sep 25, 2019 at 10:12 PM Simon Glass sjg@chromium.org wrote:
At present the bloblist is set up in spl_common_init() which can be called from spl_early_init(), i.e. before SDRAM is ready. This prevents the bloblist from being located in SDRAM, which is useful on some platforms where SRAM is inaccessible after U-Boot relocates (e.g. x86 CAR region).
It doesn't serve much purpose to have the bloblist available early, since very little is known about the platform then, and the handoff info is written when SPL is about to jump to U-Boot.
Move the code to board_init_r() to avoid any restrictions.
Signed-off-by: Simon Glass sjg@chromium.org
Changes in v2: None
common/spl/spl.c | 35 ++++++++++++++++++----------------- 1 file changed, 18 insertions(+), 17 deletions(-)
Reviewed-by: Bin Meng bmeng.cn@gmail.com

On Wed, Oct 2, 2019 at 9:58 PM Bin Meng bmeng.cn@gmail.com wrote:
On Wed, Sep 25, 2019 at 10:12 PM Simon Glass sjg@chromium.org wrote:
At present the bloblist is set up in spl_common_init() which can be called from spl_early_init(), i.e. before SDRAM is ready. This prevents the bloblist from being located in SDRAM, which is useful on some platforms where SRAM is inaccessible after U-Boot relocates (e.g. x86 CAR region).
It doesn't serve much purpose to have the bloblist available early, since very little is known about the platform then, and the handoff info is written when SPL is about to jump to U-Boot.
Move the code to board_init_r() to avoid any restrictions.
Signed-off-by: Simon Glass sjg@chromium.org
Changes in v2: None
common/spl/spl.c | 35 ++++++++++++++++++----------------- 1 file changed, 18 insertions(+), 17 deletions(-)
Reviewed-by: Bin Meng bmeng.cn@gmail.com
applied to u-boot-x86/next, thanks!

U-Boot is built in three phases: TPL, SPL and U-Boot proper. Sometimes it is necessary to use different init code depending on the phase. For example, TPL might do very basic CPU init, SPL might do a little more and U-Boot proper might bring the CPU up to full speed and enable all cores.
Add a function which allows easy determination of the current phase being built.
Signed-off-by: Simon Glass sjg@chromium.org ---
Changes in v2: None
include/spl.h | 60 +++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 60 insertions(+)
diff --git a/include/spl.h b/include/spl.h index 4bc35cb0e77..2869c9dc702 100644 --- a/include/spl.h +++ b/include/spl.h @@ -49,6 +49,66 @@ static inline bool u_boot_first_phase(void) return false; }
+enum u_boot_phase { + PHASE_TPL, + PHASE_SPL, + PHASE_U_BOOT, +}; + +/** + * spl_phase() - Find out the phase of U-Boot + * + * This can be used to avoid #ifdef logic and use if() instead. + * + * For example, to include code only in TPL, you might do: + * + * #ifdef CONFIG_TPL_BUILD + * ... + * #endif + * + * but with this you can use: + * + * if (spl_phase() == PHASE_TPL) { + * ... + * } + * + * To include code only in SPL, you might do: + * + * #if defined(CONFIG_SPL_BUILD) && !defined(CONFIG_TPL_BUILD) + * ... + * #endif + * + * but with this you can use: + * + * if (spl_phase() == PHASE_SPL) { + * ... + * } + * + * To include code only in U-Boot proper, you might do: + * + * #ifndef CONFIG_SPL_BUILD + * ... + * #endif + * + * but with this you can use: + * + * if (spl_phase() == PHASE_U_BOOT) { + * ... + * } + * + * @return U-Boot phase + */ +static inline enum u_boot_phase spl_phase(void) +{ +#ifdef CONFIG_TPL_BUILD + return PHASE_TPL; +#elif CONFIG_SPL_BUILD + return PHASE_SPL; +#else + return PHASE_U_BOOT; +#endif +} + /* A string name for SPL or TPL */ #ifdef CONFIG_SPL_BUILD # ifdef CONFIG_TPL_BUILD

On Wed, Sep 25, 2019 at 10:12 PM Simon Glass sjg@chromium.org wrote:
U-Boot is built in three phases: TPL, SPL and U-Boot proper. Sometimes it is necessary to use different init code depending on the phase. For example, TPL might do very basic CPU init, SPL might do a little more and U-Boot proper might bring the CPU up to full speed and enable all cores.
Add a function which allows easy determination of the current phase being built.
Signed-off-by: Simon Glass sjg@chromium.org
Changes in v2: None
include/spl.h | 60 +++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 60 insertions(+)
Reviewed-by: Bin Meng bmeng.cn@gmail.com

On Wed, Oct 2, 2019 at 9:58 PM Bin Meng bmeng.cn@gmail.com wrote:
On Wed, Sep 25, 2019 at 10:12 PM Simon Glass sjg@chromium.org wrote:
U-Boot is built in three phases: TPL, SPL and U-Boot proper. Sometimes it is necessary to use different init code depending on the phase. For example, TPL might do very basic CPU init, SPL might do a little more and U-Boot proper might bring the CPU up to full speed and enable all cores.
Add a function which allows easy determination of the current phase being built.
Signed-off-by: Simon Glass sjg@chromium.org
Changes in v2: None
include/spl.h | 60 +++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 60 insertions(+)
Reviewed-by: Bin Meng bmeng.cn@gmail.com
applied to u-boot-x86/next, thanks!

This provides access to SPI flash both through a read-only memory map and with operations to erase and write flash. It supports 4KB or 64KB erase sizes.
This driver is used by Apollolake.
Signed-off-by: Simon Glass sjg@chromium.org ---
Changes in v2: - Add the missing header file - Add support for of-platdata for TPL
drivers/mtd/spi/Kconfig | 9 + drivers/mtd/spi/Makefile | 1 + drivers/mtd/spi/intel_fast_spi.c | 360 +++++++++++++++++++++++++++++++ 3 files changed, 370 insertions(+) create mode 100644 drivers/mtd/spi/intel_fast_spi.c
diff --git a/drivers/mtd/spi/Kconfig b/drivers/mtd/spi/Kconfig index d3b007a731d..4a184bbc826 100644 --- a/drivers/mtd/spi/Kconfig +++ b/drivers/mtd/spi/Kconfig @@ -78,6 +78,15 @@ config SF_DEFAULT_SPEED speed and mode from platdata values computed from available node.
+config SPI_FLASH_INTEL_FAST + bool "Intel Fast SPI interface" + depends on DM_SPI_FLASH + help + Add support for Intel Fast SPI interface, as used on Apollolake. + This current only supports reading from SPI, enough to load SPL or + U-Boot proper from SPI flash. Future work may enable write and erase + operations. + if SPI_FLASH
config SPI_FLASH_SFDP_SUPPORT diff --git a/drivers/mtd/spi/Makefile b/drivers/mtd/spi/Makefile index 20db1015d9e..11a8f55132a 100644 --- a/drivers/mtd/spi/Makefile +++ b/drivers/mtd/spi/Makefile @@ -19,5 +19,6 @@ endif
obj-$(CONFIG_SPI_FLASH) += spi-nor.o obj-$(CONFIG_SPI_FLASH_DATAFLASH) += sf_dataflash.o +obj-$(CONFIG_SPI_FLASH_INTEL_FAST) += intel_fast_spi.o obj-$(CONFIG_SPI_FLASH_MTD) += sf_mtd.o obj-$(CONFIG_SPI_FLASH_SANDBOX) += sandbox.o diff --git a/drivers/mtd/spi/intel_fast_spi.c b/drivers/mtd/spi/intel_fast_spi.c new file mode 100644 index 00000000000..7074669c938 --- /dev/null +++ b/drivers/mtd/spi/intel_fast_spi.c @@ -0,0 +1,360 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Intel 'Fast SPI' support + * + * Copyright 2019 Google LLC + */ + +#include <common.h> +#include <dm.h> +#include <dt-structs.h> +#include <pci.h> +#include <spi_flash.h> +#include <spl.h> +#include <asm/io.h> +#include <asm/pci.h> +#include <asm/arch/fast_spi.h> +#include <asm/arch/iomap.h> + +struct fast_spi_platdata { +#if CONFIG_IS_ENABLED(OF_PLATDATA) + struct dtd_intel_fast_spi dtplat; +#endif + ulong mmio_base; + pci_dev_t bdf; +}; + +struct fast_spi_priv { + struct fast_spi_regs *regs; + uint page_size; + uint flash_size; + uint map_offset; + ulong map_base; + size_t map_size; +}; + +enum { + /* Erase size options */ + ERASE_SIZE_SM = 4 << 10, + ERASE_SIZE_LG = 64 << 10, +}; + +/* + * The hardware datasheet is not clear on what HORD values actually do. It + * seems that HORD_SFDP provides access to the first 8 bytes of the SFDP, which + * is the signature and revision fields. HORD_JEDEC provides access to the + * actual flash parameters, and is most likely what you want to use when + * probing the flash from software. + * It's okay to rely on SFDP, since the SPI flash controller requires an SFDP + * 1.5 or newer compliant FAST_SPI flash chip. + * NOTE: Due to the register layout of the hardware, all accesses will be + * aligned to a 4 byte boundary. + */ +static u32 read_sfdp_param(struct fast_spi_priv *priv, uint sfdp_reg) +{ + u32 ptinx_index = sfdp_reg & SPIBAR_PTINX_IDX_MASK; + + writel(ptinx_index | SPIBAR_PTINX_HORD_JEDEC, &priv->regs->ptinx); + + return readl(&priv->regs->ptdata); +} + +/* Fill FDATAn FIFO in preparation for a write transaction */ +static void fill_xfer_fifo(struct fast_spi_priv *priv, const void *data, + size_t len) +{ + memcpy(priv->regs->fdata, data, len); +} + +/* Drain FDATAn FIFO after a read transaction populates data */ +static void drain_xfer_fifo(struct fast_spi_priv *priv, void *dest, size_t len) +{ + memcpy(dest, priv->regs->fdata, len); +} + +/* Fire up a transfer using the hardware sequencer */ +static void start_hwseq_xfer(struct fast_spi_priv *priv, u32 hsfsts_cycle, + u32 offset, size_t len) +{ + /* Make sure all W1C status bits get cleared */ + u32 hsfsts = SPIBAR_HSFSTS_W1C_BITS; + + /* Set up transaction parameters */ + hsfsts |= hsfsts_cycle & SPIBAR_HSFSTS_FCYCLE_MASK; + hsfsts |= SPIBAR_HSFSTS_FDBC(len - 1); + + writel(offset, &priv->regs->faddr); + writel(hsfsts | SPIBAR_HSFSTS_FGO, &priv->regs->hsfsts_ctl); +} + +static int wait_for_hwseq_xfer(struct fast_spi_priv *priv, u32 offset) +{ + ulong start; + u32 hsfsts; + + start = get_timer(0); + do { + hsfsts = readl(&priv->regs->hsfsts_ctl); + + if (hsfsts & SPIBAR_HSFSTS_FCERR) { + debug("SPI transaction error at offset %x HSFSTS = %08x\n", + offset, hsfsts); + return -EIO; + } + + if (hsfsts & SPIBAR_HSFSTS_FDONE) + return 0; + } while ((int)get_timer(start) < SPIBAR_HWSEQ_XFER_TIMEOUT_MS); + + debug("SPI transaction timeout at offset %x HSFSTS = %08x, timer %d\n", + offset, hsfsts, (uint)get_timer(start)); + return -ETIMEDOUT; +} + +/* Execute FAST_SPI flash transfer. This is a blocking call */ +static int exec_sync_hwseq_xfer(struct fast_spi_priv *priv, + u32 hsfsts_cycle, u32 offset, + size_t len) +{ + start_hwseq_xfer(priv, hsfsts_cycle, offset, len); + + return wait_for_hwseq_xfer(priv, offset); +} + +/* + * Ensure read/write xfer len is not greater than SPIBAR_FDATA_FIFO_SIZE and + * that the operation does not cross page boundary. + */ +static size_t get_xfer_len(const struct fast_spi_priv *priv, u32 offset, + size_t len) +{ + size_t xfer_len = min(len, (size_t)SPIBAR_FDATA_FIFO_SIZE); + size_t bytes_left = ALIGN(offset, priv->page_size) - offset; + + if (bytes_left) + xfer_len = min(xfer_len, bytes_left); + + return xfer_len; +} + +static int fast_spi_flash_erase(struct udevice *dev, u32 offset, size_t len) +{ + struct fast_spi_priv *priv = dev_get_priv(dev); + int ret; + size_t erase_size; + u32 erase_cycle; + + if (!IS_ALIGNED(offset, ERASE_SIZE_SM) || + !IS_ALIGNED(len, ERASE_SIZE_SM)) { + debug("SPI erase region not sector-aligned\n"); + return -EINVAL; + } + + while (len) { + if (IS_ALIGNED(offset, ERASE_SIZE_LG) && len >= ERASE_SIZE_LG) { + erase_size = ERASE_SIZE_LG; + erase_cycle = SPIBAR_HSFSTS_CYCLE_64K_ERASE; + } else { + erase_size = ERASE_SIZE_SM; + erase_cycle = SPIBAR_HSFSTS_CYCLE_4K_ERASE; + } + debug("Erasing flash addr %x + %x\n", offset, (uint)erase_size); + + ret = exec_sync_hwseq_xfer(priv, erase_cycle, offset, 0); + if (ret) + return ret; + + offset += erase_size; + len -= erase_size; + } + + return 0; +} + +static int fast_spi_read(struct udevice *dev, u32 offset, size_t len, void *buf) +{ + struct fast_spi_priv *priv = dev_get_priv(dev); + + debug("%s: read at offset %x\n", __func__, offset); + while (len) { + size_t xfer_len = get_xfer_len(priv, offset, len); + int ret; + + ret = exec_sync_hwseq_xfer(priv, SPIBAR_HSFSTS_CYCLE_READ, + offset, xfer_len); + if (ret) + return ret; + + drain_xfer_fifo(priv, buf, xfer_len); + + offset += xfer_len; + buf += xfer_len; + len -= xfer_len; + } + + return 0; +} + +static int fast_spi_flash_write(struct udevice *dev, u32 addr, size_t len, + const void *buf) +{ + struct fast_spi_priv *priv = dev_get_priv(dev); + const u8 *data = buf; + size_t xfer_len; + int ret; + + while (len) { + xfer_len = get_xfer_len(priv, addr, len); + fill_xfer_fifo(priv, data, xfer_len); + + ret = exec_sync_hwseq_xfer(priv, SPIBAR_HSFSTS_CYCLE_WRITE, + addr, xfer_len); + if (ret) + return ret; + + addr += xfer_len; + data += xfer_len; + len -= xfer_len; + } + + return 0; +} + +static int fast_spi_get_mmap(struct udevice *dev, ulong *map_basep, + size_t *map_sizep, u32 *offsetp) +{ + struct fast_spi_priv *priv = dev_get_priv(dev); + + if (priv) { + *map_basep = priv->map_base; + *map_sizep = priv->map_size; + *offsetp = priv->map_offset; + } else { + return fast_spi_get_bios_mmap(map_basep, map_sizep, offsetp); + } + + return 0; +} + +static void fast_spi_early_init(struct udevice *dev) +{ + struct fast_spi_platdata *plat = dev_get_platdata(dev); + pci_dev_t pdev = plat->bdf; + + /* Clear BIT 1-2 SPI Command Register */ + //remove + pci_x86_clrset_config(pdev, PCI_COMMAND, PCI_COMMAND_MASTER | + PCI_COMMAND_MEMORY, 0, PCI_SIZE_8); + + /* Program Temporary BAR for SPI */ + pci_x86_write_config(pdev, PCI_BASE_ADDRESS_0, + plat->mmio_base | PCI_BASE_ADDRESS_SPACE_MEMORY, + PCI_SIZE_32); + + /* Enable Bus Master and MMIO Space */ + pci_x86_clrset_config(pdev, PCI_COMMAND, 0, PCI_COMMAND_MASTER | + PCI_COMMAND_MEMORY, PCI_SIZE_8); + + /* + * Disable the BIOS write protect so write commands are allowed. + * Enable Prefetching and caching. + */ + pci_x86_clrset_config(pdev, SPIBAR_BIOS_CONTROL, + SPIBAR_BIOS_CONTROL_EISS | + SPIBAR_BIOS_CONTROL_CACHE_DISABLE, + SPIBAR_BIOS_CONTROL_WPD | + SPIBAR_BIOS_CONTROL_PREFETCH_ENABLE, PCI_SIZE_8); +} + +static int fast_spi_ofdata_to_platdata(struct udevice *dev) +{ + struct fast_spi_platdata *plat = dev_get_platdata(dev); + +#if !CONFIG_IS_ENABLED(OF_PLATDATA) + int ret; + + if (spl_phase() == PHASE_TPL) { + u32 base[2]; + + /* TPL sets up the initial BAR */ + ret = dev_read_u32_array(dev, "early-regs", base, + ARRAY_SIZE(base)); + if (ret) + return log_msg_ret("Missing/short early-regs", ret); + plat->mmio_base = base[0]; + plat->bdf = pci_x86_get_devfn(dev); + if (plat->bdf < 0) + return log_msg_ret("Cannot get p2sb PCI address", + plat->bdf); + } else { + plat->mmio_base = dev_read_addr_pci(dev); + /* Don't set BDF since it should not be used */ + if (plat->mmio_base == FDT_ADDR_T_NONE) + return -EINVAL; + } +#else + plat->mmio_base = plat->dtplat.early_regs[0]; + plat->bdf = pci_x86_ofplat_get_devfn(plat->dtplat.reg[0]); +#endif + + return 0; +} + +static int fast_spi_probe(struct udevice *dev) +{ + struct fast_spi_platdata *plat = dev_get_platdata(dev); + struct spi_flash *flash = dev_get_uclass_priv(dev); + struct fast_spi_priv *priv = dev_get_priv(dev); + u32 flash_bits; + ulong base; + + if (spl_phase() == PHASE_TPL) + fast_spi_early_init(dev); + + priv->regs = (struct fast_spi_regs *)plat->mmio_base; + + /* + * bytes = (bits + 1) / 8; + * But we need to do the addition in a way which doesn't overflow for + * 4 Gb devices (flash_bits == 0xffffffff). + */ + flash_bits = read_sfdp_param(priv, 0x04); + flash->size = (flash_bits >> 3) + 1; + + /* Can erase both 4 KiB and 64 KiB chunks. Declare the smaller size */ + flash->sector_size = 4 << 10; + flash->page_size = 256; + + base = fast_spi_get_bios_region(priv->regs, &priv->map_size); + priv->map_base = (u32)-priv->map_size - base; + priv->map_offset = base; + + debug("FAST SPI at %lx, size %x with mapping %x, size %x\n", + plat->mmio_base, flash->size, (uint)priv->map_base, + priv->map_size); + + return 0; +} + +static const struct dm_spi_flash_ops fast_spi_ops = { + .read = fast_spi_read, + .write = fast_spi_flash_write, + .erase = fast_spi_flash_erase, + .get_mmap = fast_spi_get_mmap, +}; + +static const struct udevice_id fast_spi_ids[] = { + { .compatible = "intel,fast-spi" }, + { } +}; + +U_BOOT_DRIVER(intel_fast_spi) = { + .name = "intel_fast_spi", + .id = UCLASS_SPI_FLASH, + .of_match = fast_spi_ids, + .ofdata_to_platdata = fast_spi_ofdata_to_platdata, + .probe = fast_spi_probe, + .platdata_auto_alloc_size = sizeof(struct fast_spi_platdata), + .priv_auto_alloc_size = sizeof(struct fast_spi_priv), + .ops = &fast_spi_ops, +};

Hi Simon,
On Wed, Sep 25, 2019 at 10:12 PM Simon Glass sjg@chromium.org wrote:
This provides access to SPI flash both through a read-only memory map and with operations to erase and write flash. It supports 4KB or 64KB erase sizes.
I read the SPI controller chapter in the datasheet of apollolake as well as some latest x86 desktop processors and believe they are compatible with the existing LPC SPI controller, the one used in ICH7 and ICH9. In fact, in Linux, these SPI controllers are supported by the same intel-spi-pci.c driver (probe interface, PCI), and is actually using the same intel-spi.c core driver.
So I think we should consider expanding the existing ICH SPI driver in U-Boot to support the PCI variants too.
This driver is used by Apollolake.
Signed-off-by: Simon Glass sjg@chromium.org
Changes in v2:
- Add the missing header file
- Add support for of-platdata for TPL
drivers/mtd/spi/Kconfig | 9 + drivers/mtd/spi/Makefile | 1 + drivers/mtd/spi/intel_fast_spi.c | 360 +++++++++++++++++++++++++++++++ 3 files changed, 370 insertions(+) create mode 100644 drivers/mtd/spi/intel_fast_spi.c
diff --git a/drivers/mtd/spi/Kconfig b/drivers/mtd/spi/Kconfig index d3b007a731d..4a184bbc826 100644 --- a/drivers/mtd/spi/Kconfig +++ b/drivers/mtd/spi/Kconfig @@ -78,6 +78,15 @@ config SF_DEFAULT_SPEED speed and mode from platdata values computed from available node.
+config SPI_FLASH_INTEL_FAST
bool "Intel Fast SPI interface"
depends on DM_SPI_FLASH
help
Add support for Intel Fast SPI interface, as used on Apollolake.
This current only supports reading from SPI, enough to load SPL or
U-Boot proper from SPI flash. Future work may enable write and erase
operations.
if SPI_FLASH
config SPI_FLASH_SFDP_SUPPORT diff --git a/drivers/mtd/spi/Makefile b/drivers/mtd/spi/Makefile index 20db1015d9e..11a8f55132a 100644 --- a/drivers/mtd/spi/Makefile +++ b/drivers/mtd/spi/Makefile @@ -19,5 +19,6 @@ endif
obj-$(CONFIG_SPI_FLASH) += spi-nor.o obj-$(CONFIG_SPI_FLASH_DATAFLASH) += sf_dataflash.o +obj-$(CONFIG_SPI_FLASH_INTEL_FAST) += intel_fast_spi.o obj-$(CONFIG_SPI_FLASH_MTD) += sf_mtd.o obj-$(CONFIG_SPI_FLASH_SANDBOX) += sandbox.o diff --git a/drivers/mtd/spi/intel_fast_spi.c b/drivers/mtd/spi/intel_fast_spi.c new file mode 100644 index 00000000000..7074669c938 --- /dev/null +++ b/drivers/mtd/spi/intel_fast_spi.c @@ -0,0 +1,360 @@ +// SPDX-License-Identifier: GPL-2.0+ +/*
- Intel 'Fast SPI' support
- Copyright 2019 Google LLC
- */
+#include <common.h> +#include <dm.h> +#include <dt-structs.h> +#include <pci.h> +#include <spi_flash.h> +#include <spl.h> +#include <asm/io.h> +#include <asm/pci.h> +#include <asm/arch/fast_spi.h> +#include <asm/arch/iomap.h>
+struct fast_spi_platdata { +#if CONFIG_IS_ENABLED(OF_PLATDATA)
struct dtd_intel_fast_spi dtplat;
+#endif
ulong mmio_base;
pci_dev_t bdf;
+};
+struct fast_spi_priv {
struct fast_spi_regs *regs;
uint page_size;
uint flash_size;
uint map_offset;
ulong map_base;
size_t map_size;
+};
+enum {
/* Erase size options */
ERASE_SIZE_SM = 4 << 10,
ERASE_SIZE_LG = 64 << 10,
+};
+/*
- The hardware datasheet is not clear on what HORD values actually do. It
- seems that HORD_SFDP provides access to the first 8 bytes of the SFDP, which
- is the signature and revision fields. HORD_JEDEC provides access to the
- actual flash parameters, and is most likely what you want to use when
- probing the flash from software.
- It's okay to rely on SFDP, since the SPI flash controller requires an SFDP
- 1.5 or newer compliant FAST_SPI flash chip.
- NOTE: Due to the register layout of the hardware, all accesses will be
- aligned to a 4 byte boundary.
- */
+static u32 read_sfdp_param(struct fast_spi_priv *priv, uint sfdp_reg) +{
u32 ptinx_index = sfdp_reg & SPIBAR_PTINX_IDX_MASK;
writel(ptinx_index | SPIBAR_PTINX_HORD_JEDEC, &priv->regs->ptinx);
return readl(&priv->regs->ptdata);
+}
+/* Fill FDATAn FIFO in preparation for a write transaction */ +static void fill_xfer_fifo(struct fast_spi_priv *priv, const void *data,
size_t len)
+{
memcpy(priv->regs->fdata, data, len);
+}
+/* Drain FDATAn FIFO after a read transaction populates data */ +static void drain_xfer_fifo(struct fast_spi_priv *priv, void *dest, size_t len) +{
memcpy(dest, priv->regs->fdata, len);
+}
+/* Fire up a transfer using the hardware sequencer */ +static void start_hwseq_xfer(struct fast_spi_priv *priv, u32 hsfsts_cycle,
u32 offset, size_t len)
+{
/* Make sure all W1C status bits get cleared */
u32 hsfsts = SPIBAR_HSFSTS_W1C_BITS;
/* Set up transaction parameters */
hsfsts |= hsfsts_cycle & SPIBAR_HSFSTS_FCYCLE_MASK;
hsfsts |= SPIBAR_HSFSTS_FDBC(len - 1);
writel(offset, &priv->regs->faddr);
writel(hsfsts | SPIBAR_HSFSTS_FGO, &priv->regs->hsfsts_ctl);
+}
+static int wait_for_hwseq_xfer(struct fast_spi_priv *priv, u32 offset) +{
ulong start;
u32 hsfsts;
start = get_timer(0);
do {
hsfsts = readl(&priv->regs->hsfsts_ctl);
if (hsfsts & SPIBAR_HSFSTS_FCERR) {
debug("SPI transaction error at offset %x HSFSTS = %08x\n",
offset, hsfsts);
return -EIO;
}
if (hsfsts & SPIBAR_HSFSTS_FDONE)
return 0;
} while ((int)get_timer(start) < SPIBAR_HWSEQ_XFER_TIMEOUT_MS);
debug("SPI transaction timeout at offset %x HSFSTS = %08x, timer %d\n",
offset, hsfsts, (uint)get_timer(start));
return -ETIMEDOUT;
+}
+/* Execute FAST_SPI flash transfer. This is a blocking call */ +static int exec_sync_hwseq_xfer(struct fast_spi_priv *priv,
u32 hsfsts_cycle, u32 offset,
size_t len)
+{
start_hwseq_xfer(priv, hsfsts_cycle, offset, len);
return wait_for_hwseq_xfer(priv, offset);
+}
+/*
- Ensure read/write xfer len is not greater than SPIBAR_FDATA_FIFO_SIZE and
- that the operation does not cross page boundary.
- */
+static size_t get_xfer_len(const struct fast_spi_priv *priv, u32 offset,
size_t len)
+{
size_t xfer_len = min(len, (size_t)SPIBAR_FDATA_FIFO_SIZE);
size_t bytes_left = ALIGN(offset, priv->page_size) - offset;
if (bytes_left)
xfer_len = min(xfer_len, bytes_left);
return xfer_len;
+}
+static int fast_spi_flash_erase(struct udevice *dev, u32 offset, size_t len) +{
struct fast_spi_priv *priv = dev_get_priv(dev);
int ret;
size_t erase_size;
u32 erase_cycle;
if (!IS_ALIGNED(offset, ERASE_SIZE_SM) ||
!IS_ALIGNED(len, ERASE_SIZE_SM)) {
debug("SPI erase region not sector-aligned\n");
return -EINVAL;
}
while (len) {
if (IS_ALIGNED(offset, ERASE_SIZE_LG) && len >= ERASE_SIZE_LG) {
erase_size = ERASE_SIZE_LG;
erase_cycle = SPIBAR_HSFSTS_CYCLE_64K_ERASE;
} else {
erase_size = ERASE_SIZE_SM;
erase_cycle = SPIBAR_HSFSTS_CYCLE_4K_ERASE;
}
debug("Erasing flash addr %x + %x\n", offset, (uint)erase_size);
ret = exec_sync_hwseq_xfer(priv, erase_cycle, offset, 0);
if (ret)
return ret;
offset += erase_size;
len -= erase_size;
}
return 0;
+}
+static int fast_spi_read(struct udevice *dev, u32 offset, size_t len, void *buf) +{
struct fast_spi_priv *priv = dev_get_priv(dev);
debug("%s: read at offset %x\n", __func__, offset);
while (len) {
size_t xfer_len = get_xfer_len(priv, offset, len);
int ret;
ret = exec_sync_hwseq_xfer(priv, SPIBAR_HSFSTS_CYCLE_READ,
offset, xfer_len);
if (ret)
return ret;
drain_xfer_fifo(priv, buf, xfer_len);
offset += xfer_len;
buf += xfer_len;
len -= xfer_len;
}
return 0;
+}
+static int fast_spi_flash_write(struct udevice *dev, u32 addr, size_t len,
const void *buf)
+{
struct fast_spi_priv *priv = dev_get_priv(dev);
const u8 *data = buf;
size_t xfer_len;
int ret;
while (len) {
xfer_len = get_xfer_len(priv, addr, len);
fill_xfer_fifo(priv, data, xfer_len);
ret = exec_sync_hwseq_xfer(priv, SPIBAR_HSFSTS_CYCLE_WRITE,
addr, xfer_len);
if (ret)
return ret;
addr += xfer_len;
data += xfer_len;
len -= xfer_len;
}
return 0;
+}
+static int fast_spi_get_mmap(struct udevice *dev, ulong *map_basep,
size_t *map_sizep, u32 *offsetp)
+{
struct fast_spi_priv *priv = dev_get_priv(dev);
if (priv) {
*map_basep = priv->map_base;
*map_sizep = priv->map_size;
*offsetp = priv->map_offset;
} else {
return fast_spi_get_bios_mmap(map_basep, map_sizep, offsetp);
}
return 0;
+}
+static void fast_spi_early_init(struct udevice *dev) +{
struct fast_spi_platdata *plat = dev_get_platdata(dev);
pci_dev_t pdev = plat->bdf;
/* Clear BIT 1-2 SPI Command Register */
//remove
pci_x86_clrset_config(pdev, PCI_COMMAND, PCI_COMMAND_MASTER |
PCI_COMMAND_MEMORY, 0, PCI_SIZE_8);
/* Program Temporary BAR for SPI */
pci_x86_write_config(pdev, PCI_BASE_ADDRESS_0,
plat->mmio_base | PCI_BASE_ADDRESS_SPACE_MEMORY,
PCI_SIZE_32);
/* Enable Bus Master and MMIO Space */
pci_x86_clrset_config(pdev, PCI_COMMAND, 0, PCI_COMMAND_MASTER |
PCI_COMMAND_MEMORY, PCI_SIZE_8);
/*
* Disable the BIOS write protect so write commands are allowed.
* Enable Prefetching and caching.
*/
pci_x86_clrset_config(pdev, SPIBAR_BIOS_CONTROL,
SPIBAR_BIOS_CONTROL_EISS |
SPIBAR_BIOS_CONTROL_CACHE_DISABLE,
SPIBAR_BIOS_CONTROL_WPD |
SPIBAR_BIOS_CONTROL_PREFETCH_ENABLE, PCI_SIZE_8);
I wonder why are these needed, IIUC we rely on FSP2 to initialize the SoC and I believe for SPI these are some basic settings and registers should have already be programmed to sane values, no?
+}
+static int fast_spi_ofdata_to_platdata(struct udevice *dev) +{
struct fast_spi_platdata *plat = dev_get_platdata(dev);
+#if !CONFIG_IS_ENABLED(OF_PLATDATA)
int ret;
if (spl_phase() == PHASE_TPL) {
u32 base[2];
/* TPL sets up the initial BAR */
ret = dev_read_u32_array(dev, "early-regs", base,
ARRAY_SIZE(base));
if (ret)
return log_msg_ret("Missing/short early-regs", ret);
plat->mmio_base = base[0];
plat->bdf = pci_x86_get_devfn(dev);
if (plat->bdf < 0)
return log_msg_ret("Cannot get p2sb PCI address",
plat->bdf);
} else {
plat->mmio_base = dev_read_addr_pci(dev);
/* Don't set BDF since it should not be used */
if (plat->mmio_base == FDT_ADDR_T_NONE)
return -EINVAL;
}
+#else
plat->mmio_base = plat->dtplat.early_regs[0];
plat->bdf = pci_x86_ofplat_get_devfn(plat->dtplat.reg[0]);
+#endif
return 0;
+}
+static int fast_spi_probe(struct udevice *dev) +{
struct fast_spi_platdata *plat = dev_get_platdata(dev);
struct spi_flash *flash = dev_get_uclass_priv(dev);
struct fast_spi_priv *priv = dev_get_priv(dev);
u32 flash_bits;
ulong base;
if (spl_phase() == PHASE_TPL)
fast_spi_early_init(dev);
priv->regs = (struct fast_spi_regs *)plat->mmio_base;
/*
* bytes = (bits + 1) / 8;
* But we need to do the addition in a way which doesn't overflow for
* 4 Gb devices (flash_bits == 0xffffffff).
*/
flash_bits = read_sfdp_param(priv, 0x04);
flash->size = (flash_bits >> 3) + 1;
/* Can erase both 4 KiB and 64 KiB chunks. Declare the smaller size */
flash->sector_size = 4 << 10;
flash->page_size = 256;
base = fast_spi_get_bios_region(priv->regs, &priv->map_size);
priv->map_base = (u32)-priv->map_size - base;
priv->map_offset = base;
debug("FAST SPI at %lx, size %x with mapping %x, size %x\n",
plat->mmio_base, flash->size, (uint)priv->map_base,
priv->map_size);
return 0;
+}
+static const struct dm_spi_flash_ops fast_spi_ops = {
.read = fast_spi_read,
.write = fast_spi_flash_write,
.erase = fast_spi_flash_erase,
.get_mmap = fast_spi_get_mmap,
+};
+static const struct udevice_id fast_spi_ids[] = {
{ .compatible = "intel,fast-spi" },
{ }
+};
+U_BOOT_DRIVER(intel_fast_spi) = {
.name = "intel_fast_spi",
.id = UCLASS_SPI_FLASH,
.of_match = fast_spi_ids,
.ofdata_to_platdata = fast_spi_ofdata_to_platdata,
.probe = fast_spi_probe,
.platdata_auto_alloc_size = sizeof(struct fast_spi_platdata),
.priv_auto_alloc_size = sizeof(struct fast_spi_priv),
.ops = &fast_spi_ops,
+};
Regards, Bin

Hi Bin,
On Wed, 9 Oct 2019 at 07:10, Bin Meng bmeng.cn@gmail.com wrote:
Hi Simon,
On Wed, Sep 25, 2019 at 10:12 PM Simon Glass sjg@chromium.org wrote:
This provides access to SPI flash both through a read-only memory map and with operations to erase and write flash. It supports 4KB or 64KB erase sizes.
I read the SPI controller chapter in the datasheet of apollolake as well as some latest x86 desktop processors and believe they are compatible with the existing LPC SPI controller, the one used in ICH7 and ICH9. In fact, in Linux, these SPI controllers are supported by the same intel-spi-pci.c driver (probe interface, PCI), and is actually using the same intel-spi.c core driver.
So I think we should consider expanding the existing ICH SPI driver in U-Boot to support the PCI variants too.
As discussed elsewhere I'll give this another try.
This driver is used by Apollolake.
Signed-off-by: Simon Glass sjg@chromium.org
Changes in v2:
- Add the missing header file
- Add support for of-platdata for TPL
drivers/mtd/spi/Kconfig | 9 + drivers/mtd/spi/Makefile | 1 + drivers/mtd/spi/intel_fast_spi.c | 360 +++++++++++++++++++++++++++++++ 3 files changed, 370 insertions(+) create mode 100644 drivers/mtd/spi/intel_fast_spi.c
[..]
+static void fast_spi_early_init(struct udevice *dev) +{
struct fast_spi_platdata *plat = dev_get_platdata(dev);
pci_dev_t pdev = plat->bdf;
/* Clear BIT 1-2 SPI Command Register */
//remove
pci_x86_clrset_config(pdev, PCI_COMMAND, PCI_COMMAND_MASTER |
PCI_COMMAND_MEMORY, 0, PCI_SIZE_8);
/* Program Temporary BAR for SPI */
pci_x86_write_config(pdev, PCI_BASE_ADDRESS_0,
plat->mmio_base |
PCI_BASE_ADDRESS_SPACE_MEMORY,
PCI_SIZE_32);
/* Enable Bus Master and MMIO Space */
pci_x86_clrset_config(pdev, PCI_COMMAND, 0, PCI_COMMAND_MASTER |
PCI_COMMAND_MEMORY, PCI_SIZE_8);
/*
* Disable the BIOS write protect so write commands are allowed.
* Enable Prefetching and caching.
*/
pci_x86_clrset_config(pdev, SPIBAR_BIOS_CONTROL,
SPIBAR_BIOS_CONTROL_EISS |
SPIBAR_BIOS_CONTROL_CACHE_DISABLE,
SPIBAR_BIOS_CONTROL_WPD |
SPIBAR_BIOS_CONTROL_PREFETCH_ENABLE,
PCI_SIZE_8);
I wonder why are these needed, IIUC we rely on FSP2 to initialize the SoC and I believe for SPI these are some basic settings and registers should have already be programmed to sane values, no?
Which part of the FSP2? This code is executed in TPL so no part of the FSP has been executed yet. Even when we figure out how to run FSP-T (which will run befor ethis code) I am not sure that the FSP will do this.
Regards, Simon

Hi Simon,
On Sat, Oct 19, 2019 at 10:44 AM Simon Glass sjg@chromium.org wrote:
Hi Bin,
On Wed, 9 Oct 2019 at 07:10, Bin Meng bmeng.cn@gmail.com wrote:
Hi Simon,
On Wed, Sep 25, 2019 at 10:12 PM Simon Glass sjg@chromium.org wrote:
This provides access to SPI flash both through a read-only memory map and with operations to erase and write flash. It supports 4KB or 64KB erase sizes.
I read the SPI controller chapter in the datasheet of apollolake as well as some latest x86 desktop processors and believe they are compatible with the existing LPC SPI controller, the one used in ICH7 and ICH9. In fact, in Linux, these SPI controllers are supported by the same intel-spi-pci.c driver (probe interface, PCI), and is actually using the same intel-spi.c core driver.
So I think we should consider expanding the existing ICH SPI driver in U-Boot to support the PCI variants too.
As discussed elsewhere I'll give this another try.
This driver is used by Apollolake.
Signed-off-by: Simon Glass sjg@chromium.org
Changes in v2:
- Add the missing header file
- Add support for of-platdata for TPL
drivers/mtd/spi/Kconfig | 9 + drivers/mtd/spi/Makefile | 1 + drivers/mtd/spi/intel_fast_spi.c | 360 +++++++++++++++++++++++++++++++ 3 files changed, 370 insertions(+) create mode 100644 drivers/mtd/spi/intel_fast_spi.c
[..]
+static void fast_spi_early_init(struct udevice *dev) +{
struct fast_spi_platdata *plat = dev_get_platdata(dev);
pci_dev_t pdev = plat->bdf;
/* Clear BIT 1-2 SPI Command Register */
//remove
pci_x86_clrset_config(pdev, PCI_COMMAND, PCI_COMMAND_MASTER |
PCI_COMMAND_MEMORY, 0, PCI_SIZE_8);
/* Program Temporary BAR for SPI */
pci_x86_write_config(pdev, PCI_BASE_ADDRESS_0,
plat->mmio_base | PCI_BASE_ADDRESS_SPACE_MEMORY,
PCI_SIZE_32);
/* Enable Bus Master and MMIO Space */
pci_x86_clrset_config(pdev, PCI_COMMAND, 0, PCI_COMMAND_MASTER |
PCI_COMMAND_MEMORY, PCI_SIZE_8);
/*
* Disable the BIOS write protect so write commands are allowed.
* Enable Prefetching and caching.
*/
pci_x86_clrset_config(pdev, SPIBAR_BIOS_CONTROL,
SPIBAR_BIOS_CONTROL_EISS |
SPIBAR_BIOS_CONTROL_CACHE_DISABLE,
SPIBAR_BIOS_CONTROL_WPD |
SPIBAR_BIOS_CONTROL_PREFETCH_ENABLE, PCI_SIZE_8);
I wonder why are these needed, IIUC we rely on FSP2 to initialize the SoC and I believe for SPI these are some basic settings and registers should have already be programmed to sane values, no?
Which part of the FSP2? This code is executed in TPL so no part of the FSP has been executed yet. Even when we figure out how to run FSP-T (which will run befor ethis code) I am not sure that the FSP will do this.
Per the FSP2 spec, such silicon specific initialization are covered by FSP-S. I am not sure if SPI specific registers are touched by FSP-T as well.
Regards, Bin

Hi Bin,
On Sun, 20 Oct 2019 at 20:34, Bin Meng bmeng.cn@gmail.com wrote:
Hi Simon,
On Sat, Oct 19, 2019 at 10:44 AM Simon Glass sjg@chromium.org wrote:
Hi Bin,
On Wed, 9 Oct 2019 at 07:10, Bin Meng bmeng.cn@gmail.com wrote:
Hi Simon,
On Wed, Sep 25, 2019 at 10:12 PM Simon Glass sjg@chromium.org wrote:
This provides access to SPI flash both through a read-only memory map and with operations to erase and write flash. It supports 4KB or 64KB erase sizes.
I read the SPI controller chapter in the datasheet of apollolake as well as some latest x86 desktop processors and believe they are compatible with the existing LPC SPI controller, the one used in ICH7 and ICH9. In fact, in Linux, these SPI controllers are supported by the same intel-spi-pci.c driver (probe interface, PCI), and is actually using the same intel-spi.c core driver.
So I think we should consider expanding the existing ICH SPI driver in U-Boot to support the PCI variants too.
As discussed elsewhere I'll give this another try.
This driver is used by Apollolake.
Signed-off-by: Simon Glass sjg@chromium.org
Changes in v2:
- Add the missing header file
- Add support for of-platdata for TPL
drivers/mtd/spi/Kconfig | 9 + drivers/mtd/spi/Makefile | 1 + drivers/mtd/spi/intel_fast_spi.c | 360 +++++++++++++++++++++++++++++++ 3 files changed, 370 insertions(+) create mode 100644 drivers/mtd/spi/intel_fast_spi.c
[..]
+static void fast_spi_early_init(struct udevice *dev) +{
struct fast_spi_platdata *plat = dev_get_platdata(dev);
pci_dev_t pdev = plat->bdf;
/* Clear BIT 1-2 SPI Command Register */
//remove
pci_x86_clrset_config(pdev, PCI_COMMAND, PCI_COMMAND_MASTER |
PCI_COMMAND_MEMORY, 0, PCI_SIZE_8);
/* Program Temporary BAR for SPI */
pci_x86_write_config(pdev, PCI_BASE_ADDRESS_0,
plat->mmio_base | PCI_BASE_ADDRESS_SPACE_MEMORY,
PCI_SIZE_32);
/* Enable Bus Master and MMIO Space */
pci_x86_clrset_config(pdev, PCI_COMMAND, 0, PCI_COMMAND_MASTER |
PCI_COMMAND_MEMORY, PCI_SIZE_8);
/*
* Disable the BIOS write protect so write commands are allowed.
* Enable Prefetching and caching.
*/
pci_x86_clrset_config(pdev, SPIBAR_BIOS_CONTROL,
SPIBAR_BIOS_CONTROL_EISS |
SPIBAR_BIOS_CONTROL_CACHE_DISABLE,
SPIBAR_BIOS_CONTROL_WPD |
SPIBAR_BIOS_CONTROL_PREFETCH_ENABLE, PCI_SIZE_8);
I wonder why are these needed, IIUC we rely on FSP2 to initialize the SoC and I believe for SPI these are some basic settings and registers should have already be programmed to sane values, no?
Which part of the FSP2? This code is executed in TPL so no part of the FSP has been executed yet. Even when we figure out how to run FSP-T (which will run befor ethis code) I am not sure that the FSP will do this.
Per the FSP2 spec, such silicon specific initialization are covered by FSP-S. I am not sure if SPI specific registers are touched by FSP-T as well.
Yes it is possible. I suppose we will find out when we get FSP-S support added. But it is a bridge too far for me at present.
Regards, Simon

At present SPI-flash testing relies on a sandbox driver which emulates the SPI bus and implements a flash chip behind that emulated bus.
This provides good coverage but can only implement features supported by the SPI bus.
Add a new 'direct' SPI flash which is implemented directly by sandbox. This allows us to write a very simple test of the uclass interface.
Signed-off-by: Simon Glass sjg@chromium.org ---
Changes in v2: None
arch/sandbox/dts/test.dts | 4 ++ drivers/mtd/spi/Makefile | 2 +- drivers/mtd/spi/sandbox_direct.c | 99 ++++++++++++++++++++++++++++++++ test/dm/sf.c | 42 ++++++++++++++ 4 files changed, 146 insertions(+), 1 deletion(-) create mode 100644 drivers/mtd/spi/sandbox_direct.c
diff --git a/arch/sandbox/dts/test.dts b/arch/sandbox/dts/test.dts index 27b0baab278..208551d7c19 100644 --- a/arch/sandbox/dts/test.dts +++ b/arch/sandbox/dts/test.dts @@ -619,6 +619,10 @@ }; };
+ spi-flash@0 { + compatible = "sandbox,spi-flash-direct"; + }; + syscon0: syscon@0 { compatible = "sandbox,syscon0"; reg = <0x10 16>; diff --git a/drivers/mtd/spi/Makefile b/drivers/mtd/spi/Makefile index 11a8f55132a..c700258254b 100644 --- a/drivers/mtd/spi/Makefile +++ b/drivers/mtd/spi/Makefile @@ -21,4 +21,4 @@ obj-$(CONFIG_SPI_FLASH) += spi-nor.o obj-$(CONFIG_SPI_FLASH_DATAFLASH) += sf_dataflash.o obj-$(CONFIG_SPI_FLASH_INTEL_FAST) += intel_fast_spi.o obj-$(CONFIG_SPI_FLASH_MTD) += sf_mtd.o -obj-$(CONFIG_SPI_FLASH_SANDBOX) += sandbox.o +obj-$(CONFIG_SPI_FLASH_SANDBOX) += sandbox.o sandbox_direct.o diff --git a/drivers/mtd/spi/sandbox_direct.c b/drivers/mtd/spi/sandbox_direct.c new file mode 100644 index 00000000000..43d8907710c --- /dev/null +++ b/drivers/mtd/spi/sandbox_direct.c @@ -0,0 +1,99 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Simulate a flash chip without an underlying SPI layer. Behaviour is only + * useful for testing. + * + * Copyright 2019 Google LLC + * + * Licensed under the GPL-2 or later. + */ + +#define LOG_CATEGORY UCLASS_SPI_FLASH + +#include <common.h> +#include <dm.h> +#include <spi_flash.h> + +/** + * struct sandbox_direct_priv - private data for this driver + * + * @read_byte: Byte to return when reading from the driver + */ +struct sandbox_direct_priv { + char read_byte; + int write_prot; +}; + +static int sandbox_direct_read(struct udevice *dev, u32 offset, size_t len, + void *buf) +{ + struct sandbox_direct_priv *priv = dev_get_priv(dev); + + if (offset == 1) + return -EIO; + memset(buf, priv->read_byte, len); + + return 0; +} + +static int sandbox_direct_write(struct udevice *dev, u32 offset, size_t len, + const void *buf) +{ + struct sandbox_direct_priv *priv = dev_get_priv(dev); + + if (offset == 1) + return -EIO; + if (len > 0) + priv->read_byte = *(u8 *)buf; + + return 0; +} + +static int sandbox_direct_erase(struct udevice *dev, u32 offset, size_t len) +{ + struct sandbox_direct_priv *priv = dev_get_priv(dev); + + if (offset == 1) + return -EIO; + if (len > 0) + priv->read_byte = 'c'; + + return 0; +} + +static int sandbox_direct_get_sw_write_prot(struct udevice *dev) +{ + struct sandbox_direct_priv *priv = dev_get_priv(dev); + + return priv->write_prot++ ? 1 : 0; +} + +static int sandbox_direct_probe(struct udevice *dev) +{ + struct sandbox_direct_priv *priv = dev_get_priv(dev); + + priv->read_byte = 'a'; + + return 0; +} + +static struct dm_spi_flash_ops sandbox_direct_ops = { + .read = sandbox_direct_read, + .write = sandbox_direct_write, + .erase = sandbox_direct_erase, + .get_sw_write_prot = sandbox_direct_get_sw_write_prot, +}; + +static const struct udevice_id sandbox_direct_ids[] = { + { .compatible = "sandbox,spi-flash-direct" }, + { } +}; + +U_BOOT_DRIVER(sandbox_sf_direct) = { + .name = "sandbox_sf_direct", + .id = UCLASS_SPI_FLASH, + .of_match = sandbox_direct_ids, + .probe = sandbox_direct_probe, + .ops = &sandbox_direct_ops, + .priv_auto_alloc_size = sizeof(struct sandbox_direct_priv), +}; diff --git a/test/dm/sf.c b/test/dm/sf.c index 3788d59052e..56277954c23 100644 --- a/test/dm/sf.c +++ b/test/dm/sf.c @@ -14,8 +14,13 @@ #include <asm/test.h> #include <dm/test.h> #include <dm/util.h> +#include <dm/uclass.h> #include <test/ut.h>
+enum { + BUF_SIZE = 4, +}; + /* Simple test of sandbox SPI flash */ static int dm_test_spi_flash(struct unit_test_state *uts) { @@ -91,3 +96,40 @@ static int dm_test_spi_flash_func(struct unit_test_state *uts) return 0; } DM_TEST(dm_test_spi_flash_func, DM_TESTF_SCAN_PDATA | DM_TESTF_SCAN_FDT); + +/* Test of the direct SPI flash interface (no SPI layer) */ +static int dm_test_spi_flash_direct(struct unit_test_state *uts) +{ + struct udevice *dev; + char buf[BUF_SIZE]; + int i; + + ut_assertok(uclass_get_device(UCLASS_SPI_FLASH, 1, &dev)); + + /* Check the read call */ + ut_asserteq(-EIO, spi_flash_read_dm(dev, 1, BUF_SIZE, buf)); + ut_assertok(spi_flash_read_dm(dev, 0, BUF_SIZE, buf)); + for (i = 0; i < BUF_SIZE; i++) + ut_asserteq('a', buf[i]); + + /* Check the write call */ + ut_asserteq(-EIO, spi_flash_write_dm(dev, 1, BUF_SIZE, buf)); + ut_assertok(spi_flash_write_dm(dev, 0, 1, "b")); + ut_assertok(spi_flash_read_dm(dev, 0, BUF_SIZE, buf)); + for (i = 0; i < BUF_SIZE; i++) + ut_asserteq('b', buf[i]); + + /* Check erase */ + ut_asserteq(-EIO, spi_flash_erase_dm(dev, 1, BUF_SIZE)); + ut_assertok(spi_flash_erase_dm(dev, 0, 1)); + ut_assertok(spi_flash_read_dm(dev, 0, BUF_SIZE, buf)); + for (i = 0; i < BUF_SIZE; i++) + ut_asserteq('c', buf[i]); + + /* Check write protection */ + ut_asserteq(0, spl_flash_get_sw_write_prot(dev)); + ut_asserteq(1, spl_flash_get_sw_write_prot(dev)); + + return 0; +} +DM_TEST(dm_test_spi_flash_direct, DM_TESTF_SCAN_PDATA | DM_TESTF_SCAN_FDT);

Hi Simon,
On Wed, Sep 25, 2019 at 10:12 PM Simon Glass sjg@chromium.org wrote:
At present SPI-flash testing relies on a sandbox driver which emulates the SPI bus and implements a flash chip behind that emulated bus.
This provides good coverage but can only implement features supported by the SPI bus.
Add a new 'direct' SPI flash which is implemented directly by sandbox. This allows us to write a very simple test of the uclass interface.
Signed-off-by: Simon Glass sjg@chromium.org
Changes in v2: None
arch/sandbox/dts/test.dts | 4 ++ drivers/mtd/spi/Makefile | 2 +- drivers/mtd/spi/sandbox_direct.c | 99 ++++++++++++++++++++++++++++++++ test/dm/sf.c | 42 ++++++++++++++ 4 files changed, 146 insertions(+), 1 deletion(-) create mode 100644 drivers/mtd/spi/sandbox_direct.c
diff --git a/arch/sandbox/dts/test.dts b/arch/sandbox/dts/test.dts index 27b0baab278..208551d7c19 100644 --- a/arch/sandbox/dts/test.dts +++ b/arch/sandbox/dts/test.dts @@ -619,6 +619,10 @@ }; };
spi-flash@0 {
compatible = "sandbox,spi-flash-direct";
};
syscon0: syscon@0 { compatible = "sandbox,syscon0"; reg = <0x10 16>;
diff --git a/drivers/mtd/spi/Makefile b/drivers/mtd/spi/Makefile index 11a8f55132a..c700258254b 100644 --- a/drivers/mtd/spi/Makefile +++ b/drivers/mtd/spi/Makefile @@ -21,4 +21,4 @@ obj-$(CONFIG_SPI_FLASH) += spi-nor.o obj-$(CONFIG_SPI_FLASH_DATAFLASH) += sf_dataflash.o obj-$(CONFIG_SPI_FLASH_INTEL_FAST) += intel_fast_spi.o obj-$(CONFIG_SPI_FLASH_MTD) += sf_mtd.o -obj-$(CONFIG_SPI_FLASH_SANDBOX) += sandbox.o +obj-$(CONFIG_SPI_FLASH_SANDBOX) += sandbox.o sandbox_direct.o diff --git a/drivers/mtd/spi/sandbox_direct.c b/drivers/mtd/spi/sandbox_direct.c new file mode 100644 index 00000000000..43d8907710c --- /dev/null +++ b/drivers/mtd/spi/sandbox_direct.c @@ -0,0 +1,99 @@ +// SPDX-License-Identifier: GPL-2.0+ +/*
- Simulate a flash chip without an underlying SPI layer. Behaviour is only
- useful for testing.
- Copyright 2019 Google LLC
- Licensed under the GPL-2 or later.
- */
+#define LOG_CATEGORY UCLASS_SPI_FLASH
+#include <common.h> +#include <dm.h> +#include <spi_flash.h>
+/**
- struct sandbox_direct_priv - private data for this driver
- @read_byte: Byte to return when reading from the driver
- */
+struct sandbox_direct_priv {
char read_byte;
Just 'byte'? Since it stores a byte that is not only for "read", but also for "write"
int write_prot;
+};
+static int sandbox_direct_read(struct udevice *dev, u32 offset, size_t len,
void *buf)
+{
struct sandbox_direct_priv *priv = dev_get_priv(dev);
if (offset == 1)
return -EIO;
memset(buf, priv->read_byte, len);
return 0;
+}
+static int sandbox_direct_write(struct udevice *dev, u32 offset, size_t len,
const void *buf)
+{
struct sandbox_direct_priv *priv = dev_get_priv(dev);
if (offset == 1)
return -EIO;
No "priv->write_prot" check?
if (len > 0)
priv->read_byte = *(u8 *)buf;
return 0;
+}
+static int sandbox_direct_erase(struct udevice *dev, u32 offset, size_t len) +{
struct sandbox_direct_priv *priv = dev_get_priv(dev);
if (offset == 1)
return -EIO;
if (len > 0)
priv->read_byte = 'c';
return 0;
+}
+static int sandbox_direct_get_sw_write_prot(struct udevice *dev) +{
struct sandbox_direct_priv *priv = dev_get_priv(dev);
return priv->write_prot++ ? 1 : 0;
+}
+static int sandbox_direct_probe(struct udevice *dev) +{
struct sandbox_direct_priv *priv = dev_get_priv(dev);
priv->read_byte = 'a';
return 0;
+}
+static struct dm_spi_flash_ops sandbox_direct_ops = {
.read = sandbox_direct_read,
.write = sandbox_direct_write,
.erase = sandbox_direct_erase,
.get_sw_write_prot = sandbox_direct_get_sw_write_prot,
+};
+static const struct udevice_id sandbox_direct_ids[] = {
{ .compatible = "sandbox,spi-flash-direct" },
{ }
+};
+U_BOOT_DRIVER(sandbox_sf_direct) = {
.name = "sandbox_sf_direct",
.id = UCLASS_SPI_FLASH,
.of_match = sandbox_direct_ids,
.probe = sandbox_direct_probe,
.ops = &sandbox_direct_ops,
.priv_auto_alloc_size = sizeof(struct sandbox_direct_priv),
+}; diff --git a/test/dm/sf.c b/test/dm/sf.c index 3788d59052e..56277954c23 100644 --- a/test/dm/sf.c +++ b/test/dm/sf.c @@ -14,8 +14,13 @@ #include <asm/test.h> #include <dm/test.h> #include <dm/util.h> +#include <dm/uclass.h> #include <test/ut.h>
+enum {
BUF_SIZE = 4,
+};
/* Simple test of sandbox SPI flash */ static int dm_test_spi_flash(struct unit_test_state *uts) { @@ -91,3 +96,40 @@ static int dm_test_spi_flash_func(struct unit_test_state *uts) return 0; } DM_TEST(dm_test_spi_flash_func, DM_TESTF_SCAN_PDATA | DM_TESTF_SCAN_FDT);
+/* Test of the direct SPI flash interface (no SPI layer) */ +static int dm_test_spi_flash_direct(struct unit_test_state *uts) +{
struct udevice *dev;
char buf[BUF_SIZE];
int i;
ut_assertok(uclass_get_device(UCLASS_SPI_FLASH, 1, &dev));
/* Check the read call */
ut_asserteq(-EIO, spi_flash_read_dm(dev, 1, BUF_SIZE, buf));
ut_assertok(spi_flash_read_dm(dev, 0, BUF_SIZE, buf));
for (i = 0; i < BUF_SIZE; i++)
ut_asserteq('a', buf[i]);
/* Check the write call */
ut_asserteq(-EIO, spi_flash_write_dm(dev, 1, BUF_SIZE, buf));
ut_assertok(spi_flash_write_dm(dev, 0, 1, "b"));
ut_assertok(spi_flash_read_dm(dev, 0, BUF_SIZE, buf));
for (i = 0; i < BUF_SIZE; i++)
ut_asserteq('b', buf[i]);
/* Check erase */
ut_asserteq(-EIO, spi_flash_erase_dm(dev, 1, BUF_SIZE));
ut_assertok(spi_flash_erase_dm(dev, 0, 1));
ut_assertok(spi_flash_read_dm(dev, 0, BUF_SIZE, buf));
for (i = 0; i < BUF_SIZE; i++)
ut_asserteq('c', buf[i]);
/* Check write protection */
ut_asserteq(0, spl_flash_get_sw_write_prot(dev));
ut_asserteq(1, spl_flash_get_sw_write_prot(dev));
return 0;
+}
+DM_TEST(dm_test_spi_flash_direct, DM_TESTF_SCAN_PDATA | DM_TESTF_SCAN_FDT);
Regards, Bin

On x86 platforms the SPI flash can be mapped into memory so that the contents can be read with normal memory accesses.
Add a new SPI flash method to find the location of the SPI flash in memory. This differs from the existing device-tree "memory-map" mechanism in that the location can be discovered at run-time.
Signed-off-by: Simon Glass sjg@chromium.org ---
Changes in v2: None
drivers/mtd/spi/sandbox_direct.c | 11 +++++++++++ drivers/mtd/spi/sf-uclass.c | 11 +++++++++++ include/spi_flash.h | 27 +++++++++++++++++++++++++++ test/dm/sf.c | 9 +++++++++ 4 files changed, 58 insertions(+)
diff --git a/drivers/mtd/spi/sandbox_direct.c b/drivers/mtd/spi/sandbox_direct.c index 43d8907710c..fb515edcb7c 100644 --- a/drivers/mtd/spi/sandbox_direct.c +++ b/drivers/mtd/spi/sandbox_direct.c @@ -68,6 +68,16 @@ static int sandbox_direct_get_sw_write_prot(struct udevice *dev) return priv->write_prot++ ? 1 : 0; }
+static int sandbox_direct_get_mmap(struct udevice *dev, ulong *map_basep, + size_t *map_sizep, u32 *offsetp) +{ + *map_basep = 0x1000; + *map_sizep = 0x2000; + *offsetp = 0x100; + + return 0; +} + static int sandbox_direct_probe(struct udevice *dev) { struct sandbox_direct_priv *priv = dev_get_priv(dev); @@ -82,6 +92,7 @@ static struct dm_spi_flash_ops sandbox_direct_ops = { .write = sandbox_direct_write, .erase = sandbox_direct_erase, .get_sw_write_prot = sandbox_direct_get_sw_write_prot, + .get_mmap = sandbox_direct_get_mmap, };
static const struct udevice_id sandbox_direct_ids[] = { diff --git a/drivers/mtd/spi/sf-uclass.c b/drivers/mtd/spi/sf-uclass.c index 719a2fd23ae..127ec7e7aa6 100644 --- a/drivers/mtd/spi/sf-uclass.c +++ b/drivers/mtd/spi/sf-uclass.c @@ -28,6 +28,17 @@ int spi_flash_erase_dm(struct udevice *dev, u32 offset, size_t len) return log_ret(sf_get_ops(dev)->erase(dev, offset, len)); }
+int spi_flash_get_mmap(struct udevice *dev, ulong *map_basep, size_t *map_sizep, + u32 *offsetp) +{ + struct dm_spi_flash_ops *ops = sf_get_ops(dev); + + if (!ops->get_mmap) + return -ENOSYS; + + return ops->get_mmap(dev, map_basep, map_sizep, offsetp); +} + int spl_flash_get_sw_write_prot(struct udevice *dev) { struct dm_spi_flash_ops *ops = sf_get_ops(dev); diff --git a/include/spi_flash.h b/include/spi_flash.h index 55b4721813a..840189e22c7 100644 --- a/include/spi_flash.h +++ b/include/spi_flash.h @@ -47,6 +47,19 @@ struct dm_spi_flash_ops { * other -ve value on error */ int (*get_sw_write_prot)(struct udevice *dev); + + /** + * get_mmap() - Get memory-mapped SPI + * + * @dev: SPI flash device + * @map_basep: Returns base memory address for mapped SPI + * @map_sizep: Returns size of mapped SPI + * @offsetp: Returns start offset of SPI flash where the map works + * correctly (offsets before this are not visible) + * @return 0 if OK, -EFAULT if memory mapping is not available + */ + int (*get_mmap)(struct udevice *dev, ulong *map_basep, + size_t *map_sizep, u32 *offsetp); };
/* Access the serial operations for a device */ @@ -88,6 +101,20 @@ int spi_flash_write_dm(struct udevice *dev, u32 offset, size_t len, */ int spi_flash_erase_dm(struct udevice *dev, u32 offset, size_t len);
+/** + * spi_flash_get_mmap() - Get memory-mapped SPI + * + * @dev: SPI flash device + * @map_basep: Returns base memory address for mapped SPI + * @map_sizep: Returns size of mapped SPI + * @offsetp: Returns start offset of SPI flash where the map works + * correctly (offsets before this are not visible) + * @return 0 if OK, -ENOSYS if no operation, -EFAULT if memory mapping is not + * available + */ +int spi_flash_get_mmap(struct udevice *dev, ulong *map_basep, size_t *map_sizep, + u32 *offsetp); + /** * spl_flash_get_sw_write_prot() - Check state of software write-protect feature * diff --git a/test/dm/sf.c b/test/dm/sf.c index 56277954c23..f8f9e717720 100644 --- a/test/dm/sf.c +++ b/test/dm/sf.c @@ -102,6 +102,9 @@ static int dm_test_spi_flash_direct(struct unit_test_state *uts) { struct udevice *dev; char buf[BUF_SIZE]; + size_t map_size; + ulong map_base; + u32 offset; int i;
ut_assertok(uclass_get_device(UCLASS_SPI_FLASH, 1, &dev)); @@ -130,6 +133,12 @@ static int dm_test_spi_flash_direct(struct unit_test_state *uts) ut_asserteq(0, spl_flash_get_sw_write_prot(dev)); ut_asserteq(1, spl_flash_get_sw_write_prot(dev));
+ /* Check mapping */ + ut_assertok(spi_flash_get_mmap(dev, &map_base, &map_size, &offset)); + ut_asserteq(0x1000, map_base); + ut_asserteq(0x2000, map_size); + ut_asserteq(0x100, offset); + return 0; } DM_TEST(dm_test_spi_flash_direct, DM_TESTF_SCAN_PDATA | DM_TESTF_SCAN_FDT);

Hi Simon,
On Wed, Sep 25, 2019 at 10:12 PM Simon Glass sjg@chromium.org wrote:
On x86 platforms the SPI flash can be mapped into memory so that the contents can be read with normal memory accesses.
Add a new SPI flash method to find the location of the SPI flash in memory. This differs from the existing device-tree "memory-map" mechanism in that the location can be discovered at run-time.
Signed-off-by: Simon Glass sjg@chromium.org
Changes in v2: None
drivers/mtd/spi/sandbox_direct.c | 11 +++++++++++ drivers/mtd/spi/sf-uclass.c | 11 +++++++++++ include/spi_flash.h | 27 +++++++++++++++++++++++++++ test/dm/sf.c | 9 +++++++++ 4 files changed, 58 insertions(+)
diff --git a/drivers/mtd/spi/sandbox_direct.c b/drivers/mtd/spi/sandbox_direct.c index 43d8907710c..fb515edcb7c 100644 --- a/drivers/mtd/spi/sandbox_direct.c +++ b/drivers/mtd/spi/sandbox_direct.c @@ -68,6 +68,16 @@ static int sandbox_direct_get_sw_write_prot(struct udevice *dev) return priv->write_prot++ ? 1 : 0; }
+static int sandbox_direct_get_mmap(struct udevice *dev, ulong *map_basep,
size_t *map_sizep, u32 *offsetp)
+{
*map_basep = 0x1000;
*map_sizep = 0x2000;
*offsetp = 0x100;
return 0;
+}
static int sandbox_direct_probe(struct udevice *dev) { struct sandbox_direct_priv *priv = dev_get_priv(dev); @@ -82,6 +92,7 @@ static struct dm_spi_flash_ops sandbox_direct_ops = { .write = sandbox_direct_write, .erase = sandbox_direct_erase, .get_sw_write_prot = sandbox_direct_get_sw_write_prot,
.get_mmap = sandbox_direct_get_mmap,
};
static const struct udevice_id sandbox_direct_ids[] = { diff --git a/drivers/mtd/spi/sf-uclass.c b/drivers/mtd/spi/sf-uclass.c index 719a2fd23ae..127ec7e7aa6 100644 --- a/drivers/mtd/spi/sf-uclass.c +++ b/drivers/mtd/spi/sf-uclass.c @@ -28,6 +28,17 @@ int spi_flash_erase_dm(struct udevice *dev, u32 offset, size_t len) return log_ret(sf_get_ops(dev)->erase(dev, offset, len)); }
+int spi_flash_get_mmap(struct udevice *dev, ulong *map_basep, size_t *map_sizep,
u32 *offsetp)
+{
struct dm_spi_flash_ops *ops = sf_get_ops(dev);
if (!ops->get_mmap)
return -ENOSYS;
return ops->get_mmap(dev, map_basep, map_sizep, offsetp);
+}
int spl_flash_get_sw_write_prot(struct udevice *dev) { struct dm_spi_flash_ops *ops = sf_get_ops(dev); diff --git a/include/spi_flash.h b/include/spi_flash.h index 55b4721813a..840189e22c7 100644 --- a/include/spi_flash.h +++ b/include/spi_flash.h @@ -47,6 +47,19 @@ struct dm_spi_flash_ops { * other -ve value on error */ int (*get_sw_write_prot)(struct udevice *dev);
/**
* get_mmap() - Get memory-mapped SPI
*
* @dev: SPI flash device
* @map_basep: Returns base memory address for mapped SPI
* @map_sizep: Returns size of mapped SPI
* @offsetp: Returns start offset of SPI flash where the map works
* correctly (offsets before this are not visible)
* @return 0 if OK, -EFAULT if memory mapping is not available
*/
I feel odd to add such an op to the flash op, as memory address is not determined by the flash itself, but the SPI flash controller. We probably should add the op to the SPI flash controller instead.
int (*get_mmap)(struct udevice *dev, ulong *map_basep,
size_t *map_sizep, u32 *offsetp);
};
/* Access the serial operations for a device */ @@ -88,6 +101,20 @@ int spi_flash_write_dm(struct udevice *dev, u32 offset, size_t len, */ int spi_flash_erase_dm(struct udevice *dev, u32 offset, size_t len);
+/**
- spi_flash_get_mmap() - Get memory-mapped SPI
- @dev: SPI flash device
- @map_basep: Returns base memory address for mapped SPI
- @map_sizep: Returns size of mapped SPI
- @offsetp: Returns start offset of SPI flash where the map works
correctly (offsets before this are not visible)
- @return 0 if OK, -ENOSYS if no operation, -EFAULT if memory mapping is not
available
- */
+int spi_flash_get_mmap(struct udevice *dev, ulong *map_basep, size_t *map_sizep,
u32 *offsetp);
/**
- spl_flash_get_sw_write_prot() - Check state of software write-protect feature
diff --git a/test/dm/sf.c b/test/dm/sf.c index 56277954c23..f8f9e717720 100644 --- a/test/dm/sf.c +++ b/test/dm/sf.c @@ -102,6 +102,9 @@ static int dm_test_spi_flash_direct(struct unit_test_state *uts) { struct udevice *dev; char buf[BUF_SIZE];
size_t map_size;
ulong map_base;
u32 offset; int i; ut_assertok(uclass_get_device(UCLASS_SPI_FLASH, 1, &dev));
@@ -130,6 +133,12 @@ static int dm_test_spi_flash_direct(struct unit_test_state *uts) ut_asserteq(0, spl_flash_get_sw_write_prot(dev)); ut_asserteq(1, spl_flash_get_sw_write_prot(dev));
/* Check mapping */
ut_assertok(spi_flash_get_mmap(dev, &map_base, &map_size, &offset));
ut_asserteq(0x1000, map_base);
ut_asserteq(0x2000, map_size);
ut_asserteq(0x100, offset);
return 0;
} DM_TEST(dm_test_spi_flash_direct, DM_TESTF_SCAN_PDATA | DM_TESTF_SCAN_FDT); --
Regards, Bin

Hi Bin,
On Wed, 9 Oct 2019 at 07:55, Bin Meng bmeng.cn@gmail.com wrote:
Hi Simon,
On Wed, Sep 25, 2019 at 10:12 PM Simon Glass sjg@chromium.org wrote:
On x86 platforms the SPI flash can be mapped into memory so that the contents can be read with normal memory accesses.
Add a new SPI flash method to find the location of the SPI flash in memory. This differs from the existing device-tree "memory-map" mechanism in that the location can be discovered at run-time.
Signed-off-by: Simon Glass sjg@chromium.org
Changes in v2: None
drivers/mtd/spi/sandbox_direct.c | 11 +++++++++++ drivers/mtd/spi/sf-uclass.c | 11 +++++++++++ include/spi_flash.h | 27 +++++++++++++++++++++++++++ test/dm/sf.c | 9 +++++++++ 4 files changed, 58 insertions(+)
diff --git a/drivers/mtd/spi/sandbox_direct.c b/drivers/mtd/spi/sandbox_direct.c index 43d8907710c..fb515edcb7c 100644 --- a/drivers/mtd/spi/sandbox_direct.c +++ b/drivers/mtd/spi/sandbox_direct.c @@ -68,6 +68,16 @@ static int sandbox_direct_get_sw_write_prot(struct udevice *dev) return priv->write_prot++ ? 1 : 0; }
+static int sandbox_direct_get_mmap(struct udevice *dev, ulong *map_basep,
size_t *map_sizep, u32 *offsetp)
+{
*map_basep = 0x1000;
*map_sizep = 0x2000;
*offsetp = 0x100;
return 0;
+}
static int sandbox_direct_probe(struct udevice *dev) { struct sandbox_direct_priv *priv = dev_get_priv(dev); @@ -82,6 +92,7 @@ static struct dm_spi_flash_ops sandbox_direct_ops = { .write = sandbox_direct_write, .erase = sandbox_direct_erase, .get_sw_write_prot = sandbox_direct_get_sw_write_prot,
.get_mmap = sandbox_direct_get_mmap,
};
static const struct udevice_id sandbox_direct_ids[] = { diff --git a/drivers/mtd/spi/sf-uclass.c b/drivers/mtd/spi/sf-uclass.c index 719a2fd23ae..127ec7e7aa6 100644 --- a/drivers/mtd/spi/sf-uclass.c +++ b/drivers/mtd/spi/sf-uclass.c @@ -28,6 +28,17 @@ int spi_flash_erase_dm(struct udevice *dev, u32 offset, size_t len) return log_ret(sf_get_ops(dev)->erase(dev, offset, len)); }
+int spi_flash_get_mmap(struct udevice *dev, ulong *map_basep, size_t *map_sizep,
u32 *offsetp)
+{
struct dm_spi_flash_ops *ops = sf_get_ops(dev);
if (!ops->get_mmap)
return -ENOSYS;
return ops->get_mmap(dev, map_basep, map_sizep, offsetp);
+}
int spl_flash_get_sw_write_prot(struct udevice *dev) { struct dm_spi_flash_ops *ops = sf_get_ops(dev); diff --git a/include/spi_flash.h b/include/spi_flash.h index 55b4721813a..840189e22c7 100644 --- a/include/spi_flash.h +++ b/include/spi_flash.h @@ -47,6 +47,19 @@ struct dm_spi_flash_ops { * other -ve value on error */ int (*get_sw_write_prot)(struct udevice *dev);
/**
* get_mmap() - Get memory-mapped SPI
*
* @dev: SPI flash device
* @map_basep: Returns base memory address for mapped SPI
* @map_sizep: Returns size of mapped SPI
* @offsetp: Returns start offset of SPI flash where the map works
* correctly (offsets before this are not visible)
* @return 0 if OK, -EFAULT if memory mapping is not available
*/
I feel odd to add such an op to the flash op, as memory address is not determined by the flash itself, but the SPI flash controller. We probably should add the op to the SPI flash controller instead.
So do you think this should be added to UCLASS_SPI?
As it stands we don't actually use that uclass with this SPI flash driver - it implements the SPI_FLASH interface directly.
But given that I'm going to try to use the same ich.c driver this should be easy enough.
I've just found the weird mem_ops argument within struct dm_spi_ops...oh dear.
- Simon

Hi Simon,
On Sat, Oct 12, 2019 at 11:08 AM Simon Glass sjg@chromium.org wrote:
Hi Bin,
On Wed, 9 Oct 2019 at 07:55, Bin Meng bmeng.cn@gmail.com wrote:
Hi Simon,
On Wed, Sep 25, 2019 at 10:12 PM Simon Glass sjg@chromium.org wrote:
On x86 platforms the SPI flash can be mapped into memory so that the contents can be read with normal memory accesses.
Add a new SPI flash method to find the location of the SPI flash in memory. This differs from the existing device-tree "memory-map" mechanism in that the location can be discovered at run-time.
Signed-off-by: Simon Glass sjg@chromium.org
Changes in v2: None
drivers/mtd/spi/sandbox_direct.c | 11 +++++++++++ drivers/mtd/spi/sf-uclass.c | 11 +++++++++++ include/spi_flash.h | 27 +++++++++++++++++++++++++++ test/dm/sf.c | 9 +++++++++ 4 files changed, 58 insertions(+)
diff --git a/drivers/mtd/spi/sandbox_direct.c b/drivers/mtd/spi/sandbox_direct.c index 43d8907710c..fb515edcb7c 100644 --- a/drivers/mtd/spi/sandbox_direct.c +++ b/drivers/mtd/spi/sandbox_direct.c @@ -68,6 +68,16 @@ static int sandbox_direct_get_sw_write_prot(struct udevice *dev) return priv->write_prot++ ? 1 : 0; }
+static int sandbox_direct_get_mmap(struct udevice *dev, ulong *map_basep,
size_t *map_sizep, u32 *offsetp)
+{
*map_basep = 0x1000;
*map_sizep = 0x2000;
*offsetp = 0x100;
return 0;
+}
static int sandbox_direct_probe(struct udevice *dev) { struct sandbox_direct_priv *priv = dev_get_priv(dev); @@ -82,6 +92,7 @@ static struct dm_spi_flash_ops sandbox_direct_ops = { .write = sandbox_direct_write, .erase = sandbox_direct_erase, .get_sw_write_prot = sandbox_direct_get_sw_write_prot,
.get_mmap = sandbox_direct_get_mmap,
};
static const struct udevice_id sandbox_direct_ids[] = { diff --git a/drivers/mtd/spi/sf-uclass.c b/drivers/mtd/spi/sf-uclass.c index 719a2fd23ae..127ec7e7aa6 100644 --- a/drivers/mtd/spi/sf-uclass.c +++ b/drivers/mtd/spi/sf-uclass.c @@ -28,6 +28,17 @@ int spi_flash_erase_dm(struct udevice *dev, u32 offset, size_t len) return log_ret(sf_get_ops(dev)->erase(dev, offset, len)); }
+int spi_flash_get_mmap(struct udevice *dev, ulong *map_basep, size_t *map_sizep,
u32 *offsetp)
+{
struct dm_spi_flash_ops *ops = sf_get_ops(dev);
if (!ops->get_mmap)
return -ENOSYS;
return ops->get_mmap(dev, map_basep, map_sizep, offsetp);
+}
int spl_flash_get_sw_write_prot(struct udevice *dev) { struct dm_spi_flash_ops *ops = sf_get_ops(dev); diff --git a/include/spi_flash.h b/include/spi_flash.h index 55b4721813a..840189e22c7 100644 --- a/include/spi_flash.h +++ b/include/spi_flash.h @@ -47,6 +47,19 @@ struct dm_spi_flash_ops { * other -ve value on error */ int (*get_sw_write_prot)(struct udevice *dev);
/**
* get_mmap() - Get memory-mapped SPI
*
* @dev: SPI flash device
* @map_basep: Returns base memory address for mapped SPI
* @map_sizep: Returns size of mapped SPI
* @offsetp: Returns start offset of SPI flash where the map works
* correctly (offsets before this are not visible)
* @return 0 if OK, -EFAULT if memory mapping is not available
*/
I feel odd to add such an op to the flash op, as memory address is not determined by the flash itself, but the SPI flash controller. We probably should add the op to the SPI flash controller instead.
So do you think this should be added to UCLASS_SPI?
Yes, I think so. Jagan, what's your recommendation?
As it stands we don't actually use that uclass with this SPI flash driver - it implements the SPI_FLASH interface directly.
But given that I'm going to try to use the same ich.c driver this should be easy enough.
I've just found the weird mem_ops argument within struct dm_spi_ops...oh dear.
The mem_ops was added by Vignesh. I believe that was derived from the Linux kernel.
Regards, Bin

Hi Simon,
On 12/10/19 10:03 AM, Bin Meng wrote:
Hi Simon,
On Sat, Oct 12, 2019 at 11:08 AM Simon Glass sjg@chromium.org wrote:
Hi Bin,
On Wed, 9 Oct 2019 at 07:55, Bin Meng bmeng.cn@gmail.com wrote:
Hi Simon,
On Wed, Sep 25, 2019 at 10:12 PM Simon Glass sjg@chromium.org wrote:
On x86 platforms the SPI flash can be mapped into memory so that the contents can be read with normal memory accesses.
Add a new SPI flash method to find the location of the SPI flash in memory. This differs from the existing device-tree "memory-map" mechanism in that the location can be discovered at run-time.
Whats is the usecase? Why can't spi_flash_read() be used instead? Flash + Controller driver can underneath take care of using memory mapped mode to read data from flash right while making sure that access is within valid window?
Signed-off-by: Simon Glass sjg@chromium.org
Changes in v2: None
drivers/mtd/spi/sandbox_direct.c | 11 +++++++++++ drivers/mtd/spi/sf-uclass.c | 11 +++++++++++ include/spi_flash.h | 27 +++++++++++++++++++++++++++ test/dm/sf.c | 9 +++++++++ 4 files changed, 58 insertions(+)
diff --git a/drivers/mtd/spi/sandbox_direct.c b/drivers/mtd/spi/sandbox_direct.c index 43d8907710c..fb515edcb7c 100644 --- a/drivers/mtd/spi/sandbox_direct.c +++ b/drivers/mtd/spi/sandbox_direct.c @@ -68,6 +68,16 @@ static int sandbox_direct_get_sw_write_prot(struct udevice *dev) return priv->write_prot++ ? 1 : 0; }
+static int sandbox_direct_get_mmap(struct udevice *dev, ulong *map_basep,
size_t *map_sizep, u32 *offsetp)
+{
*map_basep = 0x1000;
*map_sizep = 0x2000;
*offsetp = 0x100;
return 0;
+}
static int sandbox_direct_probe(struct udevice *dev) { struct sandbox_direct_priv *priv = dev_get_priv(dev); @@ -82,6 +92,7 @@ static struct dm_spi_flash_ops sandbox_direct_ops = { .write = sandbox_direct_write, .erase = sandbox_direct_erase, .get_sw_write_prot = sandbox_direct_get_sw_write_prot,
.get_mmap = sandbox_direct_get_mmap,
};
static const struct udevice_id sandbox_direct_ids[] = { diff --git a/drivers/mtd/spi/sf-uclass.c b/drivers/mtd/spi/sf-uclass.c index 719a2fd23ae..127ec7e7aa6 100644 --- a/drivers/mtd/spi/sf-uclass.c +++ b/drivers/mtd/spi/sf-uclass.c @@ -28,6 +28,17 @@ int spi_flash_erase_dm(struct udevice *dev, u32 offset, size_t len) return log_ret(sf_get_ops(dev)->erase(dev, offset, len)); }
+int spi_flash_get_mmap(struct udevice *dev, ulong *map_basep, size_t *map_sizep,
u32 *offsetp)
+{
struct dm_spi_flash_ops *ops = sf_get_ops(dev);
if (!ops->get_mmap)
return -ENOSYS;
return ops->get_mmap(dev, map_basep, map_sizep, offsetp);
+}
int spl_flash_get_sw_write_prot(struct udevice *dev) { struct dm_spi_flash_ops *ops = sf_get_ops(dev); diff --git a/include/spi_flash.h b/include/spi_flash.h index 55b4721813a..840189e22c7 100644 --- a/include/spi_flash.h +++ b/include/spi_flash.h @@ -47,6 +47,19 @@ struct dm_spi_flash_ops { * other -ve value on error */ int (*get_sw_write_prot)(struct udevice *dev);
/**
* get_mmap() - Get memory-mapped SPI
*
* @dev: SPI flash device
* @map_basep: Returns base memory address for mapped SPI
* @map_sizep: Returns size of mapped SPI
* @offsetp: Returns start offset of SPI flash where the map works
* correctly (offsets before this are not visible)
* @return 0 if OK, -EFAULT if memory mapping is not available
*/
I feel odd to add such an op to the flash op, as memory address is not determined by the flash itself, but the SPI flash controller. We probably should add the op to the SPI flash controller instead.
So do you think this should be added to UCLASS_SPI?
Yes, I think so. Jagan, what's your recommendation?
As it stands we don't actually use that uclass with this SPI flash driver - it implements the SPI_FLASH interface directly.
But given that I'm going to try to use the same ich.c driver this should be easy enough.
I've just found the weird mem_ops argument within struct dm_spi_ops...oh dear.
The mem_ops was added by Vignesh. I believe that was derived from the Linux kernel.
Some SPI controllers provide interfaces to work with any type of SPI flashes like SPI NOR, SPI NAND, SPI SRAM etc. They may also provide specialized accelerated interface to work with them. spi_mem_ops abstracts these details and provides flash agnostic interface b/w flash driver and SPI controller. This means single SPI controller driver can support different variety of SPI flashes such as SPI NOR (QSPI/OSPI), SPI NAND, etc Most drivers implementing spi_mem_ops provide memory mapped access to flash as well. (I see ich.c does too).
If this HW is a generic SPI controller that can talk to any or subset of SPI NOR flashes (such as the ones listed in drivers/mtd/spi/spi-nor-ids.c) and provides a way to configure commands for SPI Flash operations, then this needs to be modeled as SPI controller implementing spi_mem_ops. spi-nor-core.c will take care flash details.
Regards, Bin

Hi Vignesh,
On Wed, 16 Oct 2019 at 04:28, Vignesh Raghavendra vigneshr@ti.com wrote:
Hi Simon,
On 12/10/19 10:03 AM, Bin Meng wrote:
Hi Simon,
On Sat, Oct 12, 2019 at 11:08 AM Simon Glass sjg@chromium.org wrote:
Hi Bin,
On Wed, 9 Oct 2019 at 07:55, Bin Meng bmeng.cn@gmail.com wrote:
Hi Simon,
On Wed, Sep 25, 2019 at 10:12 PM Simon Glass sjg@chromium.org wrote:
On x86 platforms the SPI flash can be mapped into memory so that the contents can be read with normal memory accesses.
Add a new SPI flash method to find the location of the SPI flash in memory. This differs from the existing device-tree "memory-map" mechanism in that the location can be discovered at run-time.
Whats is the usecase? Why can't spi_flash_read() be used instead? Flash + Controller driver can underneath take care of using memory mapped mode to read data from flash right while making sure that access is within valid window?
This used to be implemented but is not supported anymore. I think we should wait until the DM SPI flash migration is complete before trying again.
Also it is not just reading. The data is used in-place in some cases, so we do want to know the map region.
Signed-off-by: Simon Glass sjg@chromium.org
Changes in v2: None
drivers/mtd/spi/sandbox_direct.c | 11 +++++++++++ drivers/mtd/spi/sf-uclass.c | 11 +++++++++++ include/spi_flash.h | 27 +++++++++++++++++++++++++++ test/dm/sf.c | 9 +++++++++ 4 files changed, 58 insertions(+)
diff --git a/drivers/mtd/spi/sandbox_direct.c b/drivers/mtd/spi/sandbox_direct.c index 43d8907710c..fb515edcb7c 100644 --- a/drivers/mtd/spi/sandbox_direct.c +++ b/drivers/mtd/spi/sandbox_direct.c @@ -68,6 +68,16 @@ static int sandbox_direct_get_sw_write_prot(struct udevice *dev) return priv->write_prot++ ? 1 : 0; }
+static int sandbox_direct_get_mmap(struct udevice *dev, ulong *map_basep,
size_t *map_sizep, u32 *offsetp)
+{
*map_basep = 0x1000;
*map_sizep = 0x2000;
*offsetp = 0x100;
return 0;
+}
static int sandbox_direct_probe(struct udevice *dev) { struct sandbox_direct_priv *priv = dev_get_priv(dev); @@ -82,6 +92,7 @@ static struct dm_spi_flash_ops sandbox_direct_ops = { .write = sandbox_direct_write, .erase = sandbox_direct_erase, .get_sw_write_prot = sandbox_direct_get_sw_write_prot,
.get_mmap = sandbox_direct_get_mmap,
};
static const struct udevice_id sandbox_direct_ids[] = { diff --git a/drivers/mtd/spi/sf-uclass.c b/drivers/mtd/spi/sf-uclass.c index 719a2fd23ae..127ec7e7aa6 100644 --- a/drivers/mtd/spi/sf-uclass.c +++ b/drivers/mtd/spi/sf-uclass.c @@ -28,6 +28,17 @@ int spi_flash_erase_dm(struct udevice *dev, u32 offset, size_t len) return log_ret(sf_get_ops(dev)->erase(dev, offset, len)); }
+int spi_flash_get_mmap(struct udevice *dev, ulong *map_basep, size_t *map_sizep,
u32 *offsetp)
+{
struct dm_spi_flash_ops *ops = sf_get_ops(dev);
if (!ops->get_mmap)
return -ENOSYS;
return ops->get_mmap(dev, map_basep, map_sizep, offsetp);
+}
int spl_flash_get_sw_write_prot(struct udevice *dev) { struct dm_spi_flash_ops *ops = sf_get_ops(dev); diff --git a/include/spi_flash.h b/include/spi_flash.h index 55b4721813a..840189e22c7 100644 --- a/include/spi_flash.h +++ b/include/spi_flash.h @@ -47,6 +47,19 @@ struct dm_spi_flash_ops { * other -ve value on error */ int (*get_sw_write_prot)(struct udevice *dev);
/**
* get_mmap() - Get memory-mapped SPI
*
* @dev: SPI flash device
* @map_basep: Returns base memory address for mapped SPI
* @map_sizep: Returns size of mapped SPI
* @offsetp: Returns start offset of SPI flash where the map works
* correctly (offsets before this are not visible)
* @return 0 if OK, -EFAULT if memory mapping is not available
*/
I feel odd to add such an op to the flash op, as memory address is not determined by the flash itself, but the SPI flash controller. We probably should add the op to the SPI flash controller instead.
So do you think this should be added to UCLASS_SPI?
Yes, I think so. Jagan, what's your recommendation?
As it stands we don't actually use that uclass with this SPI flash driver - it implements the SPI_FLASH interface directly.
But given that I'm going to try to use the same ich.c driver this should be easy enough.
I've just found the weird mem_ops argument within struct dm_spi_ops...oh dear.
The mem_ops was added by Vignesh. I believe that was derived from the Linux kernel.
The problem is that it is ops within ops so doesn't follow driver model.
Some SPI controllers provide interfaces to work with any type of SPI flashes like SPI NOR, SPI NAND, SPI SRAM etc. They may also provide specialized accelerated interface to work with them. spi_mem_ops abstracts these details and provides flash agnostic interface b/w flash driver and SPI controller. This means single SPI controller driver can support different variety of SPI flashes such as SPI NOR (QSPI/OSPI), SPI NAND, etc Most drivers implementing spi_mem_ops provide memory mapped access to flash as well. (I see ich.c does too).
If this HW is a generic SPI controller that can talk to any or subset of SPI NOR flashes (such as the ones listed in drivers/mtd/spi/spi-nor-ids.c) and provides a way to configure commands for SPI Flash operations, then this needs to be modeled as SPI controller implementing spi_mem_ops. spi-nor-core.c will take care flash details.
Yes I'm going to try to make use of the existing ish driver as Bin suggested. That might help avoid 'working around' the driver.
Regards, Simon

Hi Simon,
On 16/10/19 10:10 PM, Simon Glass wrote:
Hi Vignesh,
On Wed, 16 Oct 2019 at 04:28, Vignesh Raghavendra vigneshr@ti.com wrote:
Hi Simon,
On 12/10/19 10:03 AM, Bin Meng wrote:
Hi Simon,
On Sat, Oct 12, 2019 at 11:08 AM Simon Glass sjg@chromium.org wrote:
Hi Bin,
On Wed, 9 Oct 2019 at 07:55, Bin Meng bmeng.cn@gmail.com wrote:
Hi Simon,
On Wed, Sep 25, 2019 at 10:12 PM Simon Glass sjg@chromium.org wrote:
On x86 platforms the SPI flash can be mapped into memory so that the contents can be read with normal memory accesses.
Add a new SPI flash method to find the location of the SPI flash in memory. This differs from the existing device-tree "memory-map" mechanism in that the location can be discovered at run-time.
Whats is the usecase? Why can't spi_flash_read() be used instead? Flash + Controller driver can underneath take care of using memory mapped mode to read data from flash right while making sure that access is within valid window?
This used to be implemented but is not supported anymore. I think we should wait until the DM SPI flash migration is complete before trying again.
Also it is not just reading. The data is used in-place in some cases, so we do want to know the map region.
I am fine with the idea. Just wanted to know the motivation.
Signed-off-by: Simon Glass sjg@chromium.org
Changes in v2: None
drivers/mtd/spi/sandbox_direct.c | 11 +++++++++++ drivers/mtd/spi/sf-uclass.c | 11 +++++++++++ include/spi_flash.h | 27 +++++++++++++++++++++++++++ test/dm/sf.c | 9 +++++++++ 4 files changed, 58 insertions(+)
diff --git a/drivers/mtd/spi/sandbox_direct.c b/drivers/mtd/spi/sandbox_direct.c index 43d8907710c..fb515edcb7c 100644 --- a/drivers/mtd/spi/sandbox_direct.c +++ b/drivers/mtd/spi/sandbox_direct.c @@ -68,6 +68,16 @@ static int sandbox_direct_get_sw_write_prot(struct udevice *dev) return priv->write_prot++ ? 1 : 0; }
+static int sandbox_direct_get_mmap(struct udevice *dev, ulong *map_basep,
size_t *map_sizep, u32 *offsetp)
+{
*map_basep = 0x1000;
*map_sizep = 0x2000;
*offsetp = 0x100;
return 0;
+}
static int sandbox_direct_probe(struct udevice *dev) { struct sandbox_direct_priv *priv = dev_get_priv(dev); @@ -82,6 +92,7 @@ static struct dm_spi_flash_ops sandbox_direct_ops = { .write = sandbox_direct_write, .erase = sandbox_direct_erase, .get_sw_write_prot = sandbox_direct_get_sw_write_prot,
.get_mmap = sandbox_direct_get_mmap,
};
static const struct udevice_id sandbox_direct_ids[] = { diff --git a/drivers/mtd/spi/sf-uclass.c b/drivers/mtd/spi/sf-uclass.c index 719a2fd23ae..127ec7e7aa6 100644 --- a/drivers/mtd/spi/sf-uclass.c +++ b/drivers/mtd/spi/sf-uclass.c @@ -28,6 +28,17 @@ int spi_flash_erase_dm(struct udevice *dev, u32 offset, size_t len) return log_ret(sf_get_ops(dev)->erase(dev, offset, len)); }
+int spi_flash_get_mmap(struct udevice *dev, ulong *map_basep, size_t *map_sizep,
u32 *offsetp)
+{
struct dm_spi_flash_ops *ops = sf_get_ops(dev);
if (!ops->get_mmap)
return -ENOSYS;
return ops->get_mmap(dev, map_basep, map_sizep, offsetp);
+}
int spl_flash_get_sw_write_prot(struct udevice *dev) { struct dm_spi_flash_ops *ops = sf_get_ops(dev); diff --git a/include/spi_flash.h b/include/spi_flash.h index 55b4721813a..840189e22c7 100644 --- a/include/spi_flash.h +++ b/include/spi_flash.h @@ -47,6 +47,19 @@ struct dm_spi_flash_ops { * other -ve value on error */ int (*get_sw_write_prot)(struct udevice *dev);
/**
* get_mmap() - Get memory-mapped SPI
*
* @dev: SPI flash device
* @map_basep: Returns base memory address for mapped SPI
* @map_sizep: Returns size of mapped SPI
* @offsetp: Returns start offset of SPI flash where the map works
* correctly (offsets before this are not visible)
* @return 0 if OK, -EFAULT if memory mapping is not available
*/
I feel odd to add such an op to the flash op, as memory address is not determined by the flash itself, but the SPI flash controller. We probably should add the op to the SPI flash controller instead.
So do you think this should be added to UCLASS_SPI?
Yes, I think so. Jagan, what's your recommendation?
As it stands we don't actually use that uclass with this SPI flash driver - it implements the SPI_FLASH interface directly.
But given that I'm going to try to use the same ich.c driver this should be easy enough.
I've just found the weird mem_ops argument within struct dm_spi_ops...oh dear.
The mem_ops was added by Vignesh. I believe that was derived from the Linux kernel.
spi_mem_ops in U-Boot was added by Miquel while introducing SPI NAND support in U-Boot, but I extended its usage to SPI NOR devices as well.
The problem is that it is ops within ops so doesn't follow driver model.
Hmm, why is that so? ops within ops is not unheard of and is common in kernel as well. This actually allows to grouping of similar operations into simple structs and thus improves readability.
-- Regards Vignesh

Hi Vignesh,
On Fri, 18 Oct 2019 at 02:50, Vignesh Raghavendra vigneshr@ti.com wrote:
[..]
As it stands we don't actually use that uclass with this SPI flash driver - it implements the SPI_FLASH interface directly.
But given that I'm going to try to use the same ich.c driver this should be easy enough.
I've just found the weird mem_ops argument within struct dm_spi_ops...oh dear.
The mem_ops was added by Vignesh. I believe that was derived from the Linux kernel.
spi_mem_ops in U-Boot was added by Miquel while introducing SPI NAND support in U-Boot, but I extended its usage to SPI NOR devices as well.
The problem is that it is ops within ops so doesn't follow driver model.
Hmm, why is that so? ops within ops is not unheard of and is common in kernel as well. This actually allows to grouping of similar operations into simple structs and thus improves readability.
It is not used elsewhere in driver model though.
Also there are no tests. How can we get some tests in there?
Regards, Simon

Hi Vignesh,
On Wed, 16 Oct 2019 at 04:28, Vignesh Raghavendra vigneshr@ti.com wrote:
Hi Simon,
On 12/10/19 10:03 AM, Bin Meng wrote:
Hi Simon,
On Sat, Oct 12, 2019 at 11:08 AM Simon Glass sjg@chromium.org wrote:
Hi Bin,
On Wed, 9 Oct 2019 at 07:55, Bin Meng bmeng.cn@gmail.com wrote:
Hi Simon,
On Wed, Sep 25, 2019 at 10:12 PM Simon Glass sjg@chromium.org wrote:
On x86 platforms the SPI flash can be mapped into memory so that the contents can be read with normal memory accesses.
Add a new SPI flash method to find the location of the SPI flash in memory. This differs from the existing device-tree "memory-map" mechanism in that the location can be discovered at run-time.
Whats is the usecase? Why can't spi_flash_read() be used instead? Flash + Controller driver can underneath take care of using memory mapped mode to read data from flash right while making sure that access is within valid window?
I can see spi_flash_read_dm() but it does not support returning a pointer to the data, only reading it.
Also I cannot find any documentation about any of this. I've been looking in the doc/ directory.
I found the spi_mem.h file but it doesn't mention the meaning of the in and out buffer pointers so I don't know how to use them.
Is there an API missing or just comments/documentation?
Regards, Simon

Hi,
On Thu, 17 Oct 2019 at 08:28, Simon Glass sjg@chromium.org wrote:
Hi Vignesh,
On Wed, 16 Oct 2019 at 04:28, Vignesh Raghavendra vigneshr@ti.com wrote:
Hi Simon,
On 12/10/19 10:03 AM, Bin Meng wrote:
Hi Simon,
On Sat, Oct 12, 2019 at 11:08 AM Simon Glass sjg@chromium.org wrote:
Hi Bin,
On Wed, 9 Oct 2019 at 07:55, Bin Meng bmeng.cn@gmail.com wrote:
Hi Simon,
On Wed, Sep 25, 2019 at 10:12 PM Simon Glass sjg@chromium.org wrote:
On x86 platforms the SPI flash can be mapped into memory so that the contents can be read with normal memory accesses.
Add a new SPI flash method to find the location of the SPI flash in memory. This differs from the existing device-tree "memory-map" mechanism in that the location can be discovered at run-time.
Whats is the usecase? Why can't spi_flash_read() be used instead? Flash + Controller driver can underneath take care of using memory mapped mode to read data from flash right while making sure that access is within valid window?
I can see spi_flash_read_dm() but it does not support returning a pointer to the data, only reading it.
Also I cannot find any documentation about any of this. I've been looking in the doc/ directory.
I found the spi_mem.h file but it doesn't mention the meaning of the in and out buffer pointers so I don't know how to use them.
Is there an API missing or just comments/documentation?
Apart from this I have found that the ich_spi driver does not work for APL since it apparently only supports 'hardware sequencing'. I did try getting software sequencing to work, but no dice.
In addition, I found that enabling SPI flash, etc. added about 6KB of code!
So I think it might be best to have two SPI drivers for x86 - one for software sequencing and one for hardware?
Regards, Simon

Hi Simon,
On Fri, Oct 18, 2019 at 10:22 AM Simon Glass sjg@chromium.org wrote:
Hi,
On Thu, 17 Oct 2019 at 08:28, Simon Glass sjg@chromium.org wrote:
Hi Vignesh,
On Wed, 16 Oct 2019 at 04:28, Vignesh Raghavendra vigneshr@ti.com wrote:
Hi Simon,
On 12/10/19 10:03 AM, Bin Meng wrote:
Hi Simon,
On Sat, Oct 12, 2019 at 11:08 AM Simon Glass sjg@chromium.org wrote:
Hi Bin,
On Wed, 9 Oct 2019 at 07:55, Bin Meng bmeng.cn@gmail.com wrote:
Hi Simon,
On Wed, Sep 25, 2019 at 10:12 PM Simon Glass sjg@chromium.org wrote: > > On x86 platforms the SPI flash can be mapped into memory so that the > contents can be read with normal memory accesses. > > Add a new SPI flash method to find the location of the SPI flash in > memory. This differs from the existing device-tree "memory-map" mechanism > in that the location can be discovered at run-time. >
Whats is the usecase? Why can't spi_flash_read() be used instead? Flash + Controller driver can underneath take care of using memory mapped mode to read data from flash right while making sure that access is within valid window?
I can see spi_flash_read_dm() but it does not support returning a pointer to the data, only reading it.
Also I cannot find any documentation about any of this. I've been looking in the doc/ directory.
I found the spi_mem.h file but it doesn't mention the meaning of the in and out buffer pointers so I don't know how to use them.
Is there an API missing or just comments/documentation?
Apart from this I have found that the ich_spi driver does not work for APL since it apparently only supports 'hardware sequencing'. I did try getting software sequencing to work, but no dice.
In addition, I found that enabling SPI flash, etc. added about 6KB of code!
So I think it might be best to have two SPI drivers for x86 - one for software sequencing and one for hardware?
So if this is true, I think we can create Kconfig options (HW_SEQ and SW_SEQ) for ICH SPI driver, and select either one in the SoC Kconfig file.
But I see from the Linux kernel driver, it has:
300static int intel_spi_init(struct intel_spi *ispi) 301{ 302 u32 opmenu0, opmenu1, lvscc, uvscc, val; 303 int i; 304 305 switch (ispi->info->type) { 306 case INTEL_SPI_BYT: 307 ispi->sregs = ispi->base + BYT_SSFSTS_CTL; 308 ispi->pregs = ispi->base + BYT_PR; 309 ispi->nregions = BYT_FREG_NUM; 310 ispi->pr_num = BYT_PR_NUM; 311 ispi->swseq_reg = true; 312 313 if (writeable) { 314 /* Disable write protection */ 315 val = readl(ispi->base + BYT_BCR); 316 if (!(val & BYT_BCR_WPD)) { 317 val |= BYT_BCR_WPD; 318 writel(val, ispi->base + BYT_BCR); 319 val = readl(ispi->base + BYT_BCR); 320 } 321 322 ispi->writeable = !!(val & BYT_BCR_WPD); 323 } 324 325 break; 326 327 case INTEL_SPI_LPT: 328 ispi->sregs = ispi->base + LPT_SSFSTS_CTL; 329 ispi->pregs = ispi->base + LPT_PR; 330 ispi->nregions = LPT_FREG_NUM; 331 ispi->pr_num = LPT_PR_NUM; 332 ispi->swseq_reg = true; 333 break; 334 335 case INTEL_SPI_BXT: 336 ispi->sregs = ispi->base + BXT_SSFSTS_CTL; 337 ispi->pregs = ispi->base + BXT_PR; 338 ispi->nregions = BXT_FREG_NUM; 339 ispi->pr_num = BXT_PR_NUM; 340 ispi->erase_64k = true; 341 break;
So for INTEL_SPI_BXT (which is for ApolloLake I believe) ispi->swseq_reg is not set to true which means it uses hardware sequencer, which seems to contradict with what you found.
Regards, Bin

Hi Bin,
On Thu, 17 Oct 2019 at 20:32, Bin Meng bmeng.cn@gmail.com wrote:
Hi Simon,
On Fri, Oct 18, 2019 at 10:22 AM Simon Glass sjg@chromium.org wrote:
Hi,
On Thu, 17 Oct 2019 at 08:28, Simon Glass sjg@chromium.org wrote:
Hi Vignesh,
On Wed, 16 Oct 2019 at 04:28, Vignesh Raghavendra vigneshr@ti.com wrote:
Hi Simon,
On 12/10/19 10:03 AM, Bin Meng wrote:
Hi Simon,
On Sat, Oct 12, 2019 at 11:08 AM Simon Glass sjg@chromium.org wrote:
Hi Bin,
On Wed, 9 Oct 2019 at 07:55, Bin Meng bmeng.cn@gmail.com wrote: > > Hi Simon, > > On Wed, Sep 25, 2019 at 10:12 PM Simon Glass sjg@chromium.org wrote: >> >> On x86 platforms the SPI flash can be mapped into memory so that the >> contents can be read with normal memory accesses. >> >> Add a new SPI flash method to find the location of the SPI flash in >> memory. This differs from the existing device-tree "memory-map" mechanism >> in that the location can be discovered at run-time. >>
Whats is the usecase? Why can't spi_flash_read() be used instead? Flash + Controller driver can underneath take care of using memory mapped mode to read data from flash right while making sure that access is within valid window?
I can see spi_flash_read_dm() but it does not support returning a pointer to the data, only reading it.
Also I cannot find any documentation about any of this. I've been looking in the doc/ directory.
I found the spi_mem.h file but it doesn't mention the meaning of the in and out buffer pointers so I don't know how to use them.
Is there an API missing or just comments/documentation?
Apart from this I have found that the ich_spi driver does not work for APL since it apparently only supports 'hardware sequencing'. I did try getting software sequencing to work, but no dice.
In addition, I found that enabling SPI flash, etc. added about 6KB of code!
So I think it might be best to have two SPI drivers for x86 - one for software sequencing and one for hardware?
So if this is true, I think we can create Kconfig options (HW_SEQ and SW_SEQ) for ICH SPI driver, and select either one in the SoC Kconfig file.
I think at least for TPL I'm going to need to bypass all the code as it is just too big for TPL. What do you think?
Should we have a separate HW SEQ driver? If you look at the HW SEQ driver I have, it is very little code.
Or are you saying we should have a combined driver with Kconfig options to enable either or both of SW SEQ and HW SEQ?
One other wrinkle is that I have to have a separate driver anyway, since of-platdata requires it. It is not possible to use of-platdata in a generic driver since the struct definitions rely on the compatible string.
But I see from the Linux kernel driver, it has:
300static int intel_spi_init(struct intel_spi *ispi) 301{ 302 u32 opmenu0, opmenu1, lvscc, uvscc, val; 303 int i; 304 305 switch (ispi->info->type) { 306 case INTEL_SPI_BYT: 307 ispi->sregs = ispi->base + BYT_SSFSTS_CTL; 308 ispi->pregs = ispi->base + BYT_PR; 309 ispi->nregions = BYT_FREG_NUM; 310 ispi->pr_num = BYT_PR_NUM; 311 ispi->swseq_reg = true; 312 313 if (writeable) { 314 /* Disable write protection */ 315 val = readl(ispi->base + BYT_BCR); 316 if (!(val & BYT_BCR_WPD)) { 317 val |= BYT_BCR_WPD; 318 writel(val, ispi->base + BYT_BCR); 319 val = readl(ispi->base + BYT_BCR); 320 } 321 322 ispi->writeable = !!(val & BYT_BCR_WPD); 323 } 324 325 break; 326 327 case INTEL_SPI_LPT: 328 ispi->sregs = ispi->base + LPT_SSFSTS_CTL; 329 ispi->pregs = ispi->base + LPT_PR; 330 ispi->nregions = LPT_FREG_NUM; 331 ispi->pr_num = LPT_PR_NUM; 332 ispi->swseq_reg = true; 333 break; 334 335 case INTEL_SPI_BXT: 336 ispi->sregs = ispi->base + BXT_SSFSTS_CTL; 337 ispi->pregs = ispi->base + BXT_PR; 338 ispi->nregions = BXT_FREG_NUM; 339 ispi->pr_num = BXT_PR_NUM; 340 ispi->erase_64k = true; 341 break;
So for INTEL_SPI_BXT (which is for ApolloLake I believe) ispi->swseq_reg is not set to true which means it uses hardware sequencer, which seems to contradict with what you found.
I found that it only supports hardware sequencing, so this matches.
Regards, Simon

Hi Simon,
On Fri, Oct 18, 2019 at 10:14 PM Simon Glass sjg@chromium.org wrote:
Hi Bin,
On Thu, 17 Oct 2019 at 20:32, Bin Meng bmeng.cn@gmail.com wrote:
Hi Simon,
On Fri, Oct 18, 2019 at 10:22 AM Simon Glass sjg@chromium.org wrote:
Hi,
On Thu, 17 Oct 2019 at 08:28, Simon Glass sjg@chromium.org wrote:
Hi Vignesh,
On Wed, 16 Oct 2019 at 04:28, Vignesh Raghavendra vigneshr@ti.com wrote:
Hi Simon,
On 12/10/19 10:03 AM, Bin Meng wrote:
Hi Simon,
On Sat, Oct 12, 2019 at 11:08 AM Simon Glass sjg@chromium.org wrote: > > Hi Bin, > > On Wed, 9 Oct 2019 at 07:55, Bin Meng bmeng.cn@gmail.com wrote: >> >> Hi Simon, >> >> On Wed, Sep 25, 2019 at 10:12 PM Simon Glass sjg@chromium.org wrote: >>> >>> On x86 platforms the SPI flash can be mapped into memory so that the >>> contents can be read with normal memory accesses. >>> >>> Add a new SPI flash method to find the location of the SPI flash in >>> memory. This differs from the existing device-tree "memory-map" mechanism >>> in that the location can be discovered at run-time. >>>
Whats is the usecase? Why can't spi_flash_read() be used instead? Flash + Controller driver can underneath take care of using memory mapped mode to read data from flash right while making sure that access is within valid window?
I can see spi_flash_read_dm() but it does not support returning a pointer to the data, only reading it.
Also I cannot find any documentation about any of this. I've been looking in the doc/ directory.
I found the spi_mem.h file but it doesn't mention the meaning of the in and out buffer pointers so I don't know how to use them.
Is there an API missing or just comments/documentation?
Apart from this I have found that the ich_spi driver does not work for APL since it apparently only supports 'hardware sequencing'. I did try getting software sequencing to work, but no dice.
In addition, I found that enabling SPI flash, etc. added about 6KB of code!
So I think it might be best to have two SPI drivers for x86 - one for software sequencing and one for hardware?
So if this is true, I think we can create Kconfig options (HW_SEQ and SW_SEQ) for ICH SPI driver, and select either one in the SoC Kconfig file.
I think at least for TPL I'm going to need to bypass all the code as it is just too big for TPL. What do you think?
So what about other boards/drivers? Say we have drv_foo.c, is the best practice to create a separate drv_foo_tpl.c for use with TPL?
Should we have a separate HW SEQ driver? If you look at the HW SEQ driver I have, it is very little code.
Or are you saying we should have a combined driver with Kconfig options to enable either or both of SW SEQ and HW SEQ?
Yes I was suggesting enable either or both SW and HW SEQ in the same driver.
One other wrinkle is that I have to have a separate driver anyway, since of-platdata requires it. It is not possible to use of-platdata in a generic driver since the struct definitions rely on the compatible string.
But I see from the Linux kernel driver, it has:
300static int intel_spi_init(struct intel_spi *ispi) 301{ 302 u32 opmenu0, opmenu1, lvscc, uvscc, val; 303 int i; 304 305 switch (ispi->info->type) { 306 case INTEL_SPI_BYT: 307 ispi->sregs = ispi->base + BYT_SSFSTS_CTL; 308 ispi->pregs = ispi->base + BYT_PR; 309 ispi->nregions = BYT_FREG_NUM; 310 ispi->pr_num = BYT_PR_NUM; 311 ispi->swseq_reg = true; 312 313 if (writeable) { 314 /* Disable write protection */ 315 val = readl(ispi->base + BYT_BCR); 316 if (!(val & BYT_BCR_WPD)) { 317 val |= BYT_BCR_WPD; 318 writel(val, ispi->base + BYT_BCR); 319 val = readl(ispi->base + BYT_BCR); 320 } 321 322 ispi->writeable = !!(val & BYT_BCR_WPD); 323 } 324 325 break; 326 327 case INTEL_SPI_LPT: 328 ispi->sregs = ispi->base + LPT_SSFSTS_CTL; 329 ispi->pregs = ispi->base + LPT_PR; 330 ispi->nregions = LPT_FREG_NUM; 331 ispi->pr_num = LPT_PR_NUM; 332 ispi->swseq_reg = true; 333 break; 334 335 case INTEL_SPI_BXT: 336 ispi->sregs = ispi->base + BXT_SSFSTS_CTL; 337 ispi->pregs = ispi->base + BXT_PR; 338 ispi->nregions = BXT_FREG_NUM; 339 ispi->pr_num = BXT_PR_NUM; 340 ispi->erase_64k = true; 341 break;
So for INTEL_SPI_BXT (which is for ApolloLake I believe) ispi->swseq_reg is not set to true which means it uses hardware sequencer, which seems to contradict with what you found.
I found that it only supports hardware sequencing, so this matches.
OK, I see. So the BXT only supports HW SEQ while LPT and BYT support both SW and HW SEQ.
Regards, Bin

Hi Bin,
On Fri, 18 Oct 2019 at 09:38, Bin Meng bmeng.cn@gmail.com wrote:
Hi Simon,
On Fri, Oct 18, 2019 at 10:14 PM Simon Glass sjg@chromium.org wrote:
Hi Bin,
On Thu, 17 Oct 2019 at 20:32, Bin Meng bmeng.cn@gmail.com wrote:
Hi Simon,
On Fri, Oct 18, 2019 at 10:22 AM Simon Glass sjg@chromium.org wrote:
Hi,
On Thu, 17 Oct 2019 at 08:28, Simon Glass sjg@chromium.org wrote:
Hi Vignesh,
On Wed, 16 Oct 2019 at 04:28, Vignesh Raghavendra vigneshr@ti.com wrote:
Hi Simon,
On 12/10/19 10:03 AM, Bin Meng wrote: > Hi Simon, > > On Sat, Oct 12, 2019 at 11:08 AM Simon Glass sjg@chromium.org wrote: >> >> Hi Bin, >> >> On Wed, 9 Oct 2019 at 07:55, Bin Meng bmeng.cn@gmail.com wrote: >>> >>> Hi Simon, >>> >>> On Wed, Sep 25, 2019 at 10:12 PM Simon Glass sjg@chromium.org wrote: >>>> >>>> On x86 platforms the SPI flash can be mapped into memory so that the >>>> contents can be read with normal memory accesses. >>>> >>>> Add a new SPI flash method to find the location of the SPI flash in >>>> memory. This differs from the existing device-tree "memory-map" mechanism >>>> in that the location can be discovered at run-time. >>>>
Whats is the usecase? Why can't spi_flash_read() be used instead? Flash + Controller driver can underneath take care of using memory mapped mode to read data from flash right while making sure that access is within valid window?
I can see spi_flash_read_dm() but it does not support returning a pointer to the data, only reading it.
Also I cannot find any documentation about any of this. I've been looking in the doc/ directory.
I found the spi_mem.h file but it doesn't mention the meaning of the in and out buffer pointers so I don't know how to use them.
Is there an API missing or just comments/documentation?
Apart from this I have found that the ich_spi driver does not work for APL since it apparently only supports 'hardware sequencing'. I did try getting software sequencing to work, but no dice.
In addition, I found that enabling SPI flash, etc. added about 6KB of code!
So I think it might be best to have two SPI drivers for x86 - one for software sequencing and one for hardware?
So if this is true, I think we can create Kconfig options (HW_SEQ and SW_SEQ) for ICH SPI driver, and select either one in the SoC Kconfig file.
I think at least for TPL I'm going to need to bypass all the code as it is just too big for TPL. What do you think?
So what about other boards/drivers? Say we have drv_foo.c, is the best practice to create a separate drv_foo_tpl.c for use with TPL?
Yes, although in general we can export the functions from the core driver, so the TPL one becomes pretty bare-bones - e.g. it handles platdata but uses the operations of the core drivers.
Should we have a separate HW SEQ driver? If you look at the HW SEQ driver I have, it is very little code.
Or are you saying we should have a combined driver with Kconfig options to enable either or both of SW SEQ and HW SEQ?
Yes I was suggesting enable either or both SW and HW SEQ in the same driver.
OK I will take a look at that.
My code-size concern still stands though, but let's see how it looks.
One other wrinkle is that I have to have a separate driver anyway, since of-platdata requires it. It is not possible to use of-platdata in a generic driver since the struct definitions rely on the compatible string.
But I see from the Linux kernel driver, it has:
300static int intel_spi_init(struct intel_spi *ispi) 301{ 302 u32 opmenu0, opmenu1, lvscc, uvscc, val; 303 int i; 304 305 switch (ispi->info->type) { 306 case INTEL_SPI_BYT: 307 ispi->sregs = ispi->base + BYT_SSFSTS_CTL; 308 ispi->pregs = ispi->base + BYT_PR; 309 ispi->nregions = BYT_FREG_NUM; 310 ispi->pr_num = BYT_PR_NUM; 311 ispi->swseq_reg = true; 312 313 if (writeable) { 314 /* Disable write protection */ 315 val = readl(ispi->base + BYT_BCR); 316 if (!(val & BYT_BCR_WPD)) { 317 val |= BYT_BCR_WPD; 318 writel(val, ispi->base + BYT_BCR); 319 val = readl(ispi->base + BYT_BCR); 320 } 321 322 ispi->writeable = !!(val & BYT_BCR_WPD); 323 } 324 325 break; 326 327 case INTEL_SPI_LPT: 328 ispi->sregs = ispi->base + LPT_SSFSTS_CTL; 329 ispi->pregs = ispi->base + LPT_PR; 330 ispi->nregions = LPT_FREG_NUM; 331 ispi->pr_num = LPT_PR_NUM; 332 ispi->swseq_reg = true; 333 break; 334 335 case INTEL_SPI_BXT: 336 ispi->sregs = ispi->base + BXT_SSFSTS_CTL; 337 ispi->pregs = ispi->base + BXT_PR; 338 ispi->nregions = BXT_FREG_NUM; 339 ispi->pr_num = BXT_PR_NUM; 340 ispi->erase_64k = true; 341 break;
So for INTEL_SPI_BXT (which is for ApolloLake I believe) ispi->swseq_reg is not set to true which means it uses hardware sequencer, which seems to contradict with what you found.
I found that it only supports hardware sequencing, so this matches.
OK, I see. So the BXT only supports HW SEQ while LPT and BYT support both SW and HW SEQ.
OK, ta. How do I look up what LPT and BYT are?
Regards, Simon

Hi Simon,
On Sat, Oct 19, 2019 at 4:37 AM Simon Glass sjg@chromium.org wrote:
Hi Bin,
On Fri, 18 Oct 2019 at 09:38, Bin Meng bmeng.cn@gmail.com wrote:
Hi Simon,
On Fri, Oct 18, 2019 at 10:14 PM Simon Glass sjg@chromium.org wrote:
Hi Bin,
On Thu, 17 Oct 2019 at 20:32, Bin Meng bmeng.cn@gmail.com wrote:
Hi Simon,
On Fri, Oct 18, 2019 at 10:22 AM Simon Glass sjg@chromium.org wrote:
Hi,
On Thu, 17 Oct 2019 at 08:28, Simon Glass sjg@chromium.org wrote:
Hi Vignesh,
On Wed, 16 Oct 2019 at 04:28, Vignesh Raghavendra vigneshr@ti.com wrote: > > Hi Simon, > > On 12/10/19 10:03 AM, Bin Meng wrote: > > Hi Simon, > > > > On Sat, Oct 12, 2019 at 11:08 AM Simon Glass sjg@chromium.org wrote: > >> > >> Hi Bin, > >> > >> On Wed, 9 Oct 2019 at 07:55, Bin Meng bmeng.cn@gmail.com wrote: > >>> > >>> Hi Simon, > >>> > >>> On Wed, Sep 25, 2019 at 10:12 PM Simon Glass sjg@chromium.org wrote: > >>>> > >>>> On x86 platforms the SPI flash can be mapped into memory so that the > >>>> contents can be read with normal memory accesses. > >>>> > >>>> Add a new SPI flash method to find the location of the SPI flash in > >>>> memory. This differs from the existing device-tree "memory-map" mechanism > >>>> in that the location can be discovered at run-time. > >>>> > > Whats is the usecase? Why can't spi_flash_read() be used instead? > Flash + Controller driver can underneath take care of using memory > mapped mode to read data from flash right while making sure that access > is within valid window?
I can see spi_flash_read_dm() but it does not support returning a pointer to the data, only reading it.
Also I cannot find any documentation about any of this. I've been looking in the doc/ directory.
I found the spi_mem.h file but it doesn't mention the meaning of the in and out buffer pointers so I don't know how to use them.
Is there an API missing or just comments/documentation?
Apart from this I have found that the ich_spi driver does not work for APL since it apparently only supports 'hardware sequencing'. I did try getting software sequencing to work, but no dice.
In addition, I found that enabling SPI flash, etc. added about 6KB of code!
So I think it might be best to have two SPI drivers for x86 - one for software sequencing and one for hardware?
So if this is true, I think we can create Kconfig options (HW_SEQ and SW_SEQ) for ICH SPI driver, and select either one in the SoC Kconfig file.
I think at least for TPL I'm going to need to bypass all the code as it is just too big for TPL. What do you think?
So what about other boards/drivers? Say we have drv_foo.c, is the best practice to create a separate drv_foo_tpl.c for use with TPL?
Yes, although in general we can export the functions from the core driver, so the TPL one becomes pretty bare-bones - e.g. it handles platdata but uses the operations of the core drivers.
Should we have a separate HW SEQ driver? If you look at the HW SEQ driver I have, it is very little code.
Or are you saying we should have a combined driver with Kconfig options to enable either or both of SW SEQ and HW SEQ?
Yes I was suggesting enable either or both SW and HW SEQ in the same driver.
OK I will take a look at that.
My code-size concern still stands though, but let's see how it looks.
One other wrinkle is that I have to have a separate driver anyway, since of-platdata requires it. It is not possible to use of-platdata in a generic driver since the struct definitions rely on the compatible string.
But I see from the Linux kernel driver, it has:
300static int intel_spi_init(struct intel_spi *ispi) 301{ 302 u32 opmenu0, opmenu1, lvscc, uvscc, val; 303 int i; 304 305 switch (ispi->info->type) { 306 case INTEL_SPI_BYT: 307 ispi->sregs = ispi->base + BYT_SSFSTS_CTL; 308 ispi->pregs = ispi->base + BYT_PR; 309 ispi->nregions = BYT_FREG_NUM; 310 ispi->pr_num = BYT_PR_NUM; 311 ispi->swseq_reg = true; 312 313 if (writeable) { 314 /* Disable write protection */ 315 val = readl(ispi->base + BYT_BCR); 316 if (!(val & BYT_BCR_WPD)) { 317 val |= BYT_BCR_WPD; 318 writel(val, ispi->base + BYT_BCR); 319 val = readl(ispi->base + BYT_BCR); 320 } 321 322 ispi->writeable = !!(val & BYT_BCR_WPD); 323 } 324 325 break; 326 327 case INTEL_SPI_LPT: 328 ispi->sregs = ispi->base + LPT_SSFSTS_CTL; 329 ispi->pregs = ispi->base + LPT_PR; 330 ispi->nregions = LPT_FREG_NUM; 331 ispi->pr_num = LPT_PR_NUM; 332 ispi->swseq_reg = true; 333 break; 334 335 case INTEL_SPI_BXT: 336 ispi->sregs = ispi->base + BXT_SSFSTS_CTL; 337 ispi->pregs = ispi->base + BXT_PR; 338 ispi->nregions = BXT_FREG_NUM; 339 ispi->pr_num = BXT_PR_NUM; 340 ispi->erase_64k = true; 341 break;
So for INTEL_SPI_BXT (which is for ApolloLake I believe) ispi->swseq_reg is not set to true which means it uses hardware sequencer, which seems to contradict with what you found.
I found that it only supports hardware sequencing, so this matches.
OK, I see. So the BXT only supports HW SEQ while LPT and BYT support both SW and HW SEQ.
OK, ta. How do I look up what LPT and BYT are?
I think LPT stands Linx Point (the PCH chipset that desktop processors use) and BYT stands BayTrail which U-Boot already supports.
Regards, Bin

Hi Bin,
On Sun, 20 Oct 2019 at 20:29, Bin Meng bmeng.cn@gmail.com wrote:
Hi Simon,
On Sat, Oct 19, 2019 at 4:37 AM Simon Glass sjg@chromium.org wrote:
Hi Bin,
On Fri, 18 Oct 2019 at 09:38, Bin Meng bmeng.cn@gmail.com wrote:
Hi Simon,
On Fri, Oct 18, 2019 at 10:14 PM Simon Glass sjg@chromium.org wrote:
Hi Bin,
On Thu, 17 Oct 2019 at 20:32, Bin Meng bmeng.cn@gmail.com wrote:
Hi Simon,
On Fri, Oct 18, 2019 at 10:22 AM Simon Glass sjg@chromium.org wrote:
Hi,
On Thu, 17 Oct 2019 at 08:28, Simon Glass sjg@chromium.org wrote: > > Hi Vignesh, > > On Wed, 16 Oct 2019 at 04:28, Vignesh Raghavendra vigneshr@ti.com wrote: > > > > Hi Simon, > > > > On 12/10/19 10:03 AM, Bin Meng wrote: > > > Hi Simon, > > > > > > On Sat, Oct 12, 2019 at 11:08 AM Simon Glass sjg@chromium.org wrote: > > >> > > >> Hi Bin, > > >> > > >> On Wed, 9 Oct 2019 at 07:55, Bin Meng bmeng.cn@gmail.com wrote: > > >>> > > >>> Hi Simon, > > >>> > > >>> On Wed, Sep 25, 2019 at 10:12 PM Simon Glass sjg@chromium.org wrote: > > >>>> > > >>>> On x86 platforms the SPI flash can be mapped into memory so that the > > >>>> contents can be read with normal memory accesses. > > >>>> > > >>>> Add a new SPI flash method to find the location of the SPI flash in > > >>>> memory. This differs from the existing device-tree "memory-map" mechanism > > >>>> in that the location can be discovered at run-time. > > >>>> > > > > Whats is the usecase? Why can't spi_flash_read() be used instead? > > Flash + Controller driver can underneath take care of using memory > > mapped mode to read data from flash right while making sure that access > > is within valid window? > > I can see spi_flash_read_dm() but it does not support returning a > pointer to the data, only reading it. > > Also I cannot find any documentation about any of this. I've been > looking in the doc/ directory. > > I found the spi_mem.h file but it doesn't mention the meaning of the > in and out buffer pointers so I don't know how to use them. > > Is there an API missing or just comments/documentation?
Apart from this I have found that the ich_spi driver does not work for APL since it apparently only supports 'hardware sequencing'. I did try getting software sequencing to work, but no dice.
In addition, I found that enabling SPI flash, etc. added about 6KB of code!
So I think it might be best to have two SPI drivers for x86 - one for software sequencing and one for hardware?
So if this is true, I think we can create Kconfig options (HW_SEQ and SW_SEQ) for ICH SPI driver, and select either one in the SoC Kconfig file.
I think at least for TPL I'm going to need to bypass all the code as it is just too big for TPL. What do you think?
So what about other boards/drivers? Say we have drv_foo.c, is the best practice to create a separate drv_foo_tpl.c for use with TPL?
Yes, although in general we can export the functions from the core driver, so the TPL one becomes pretty bare-bones - e.g. it handles platdata but uses the operations of the core drivers.
Should we have a separate HW SEQ driver? If you look at the HW SEQ driver I have, it is very little code.
Or are you saying we should have a combined driver with Kconfig options to enable either or both of SW SEQ and HW SEQ?
Yes I was suggesting enable either or both SW and HW SEQ in the same driver.
OK I will take a look at that.
My code-size concern still stands though, but let's see how it looks.
One other wrinkle is that I have to have a separate driver anyway, since of-platdata requires it. It is not possible to use of-platdata in a generic driver since the struct definitions rely on the compatible string.
But I see from the Linux kernel driver, it has:
300static int intel_spi_init(struct intel_spi *ispi) 301{ 302 u32 opmenu0, opmenu1, lvscc, uvscc, val; 303 int i; 304 305 switch (ispi->info->type) { 306 case INTEL_SPI_BYT: 307 ispi->sregs = ispi->base + BYT_SSFSTS_CTL; 308 ispi->pregs = ispi->base + BYT_PR; 309 ispi->nregions = BYT_FREG_NUM; 310 ispi->pr_num = BYT_PR_NUM; 311 ispi->swseq_reg = true; 312 313 if (writeable) { 314 /* Disable write protection */ 315 val = readl(ispi->base + BYT_BCR); 316 if (!(val & BYT_BCR_WPD)) { 317 val |= BYT_BCR_WPD; 318 writel(val, ispi->base + BYT_BCR); 319 val = readl(ispi->base + BYT_BCR); 320 } 321 322 ispi->writeable = !!(val & BYT_BCR_WPD); 323 } 324 325 break; 326 327 case INTEL_SPI_LPT: 328 ispi->sregs = ispi->base + LPT_SSFSTS_CTL; 329 ispi->pregs = ispi->base + LPT_PR; 330 ispi->nregions = LPT_FREG_NUM; 331 ispi->pr_num = LPT_PR_NUM; 332 ispi->swseq_reg = true; 333 break; 334 335 case INTEL_SPI_BXT: 336 ispi->sregs = ispi->base + BXT_SSFSTS_CTL; 337 ispi->pregs = ispi->base + BXT_PR; 338 ispi->nregions = BXT_FREG_NUM; 339 ispi->pr_num = BXT_PR_NUM; 340 ispi->erase_64k = true; 341 break;
So for INTEL_SPI_BXT (which is for ApolloLake I believe) ispi->swseq_reg is not set to true which means it uses hardware sequencer, which seems to contradict with what you found.
I found that it only supports hardware sequencing, so this matches.
OK, I see. So the BXT only supports HW SEQ while LPT and BYT support both SW and HW SEQ.
OK, ta. How do I look up what LPT and BYT are?
I think LPT stands Linx Point (the PCH chipset that desktop processors use) and BYT stands BayTrail which U-Boot already supports.
OK ta.
BTW I'm just preparing the new series. It will be v3 as I have brought in some patches from the other series which was v2.
Regards, Simon

On 18/10/19 7:52 AM, Simon Glass wrote:
Hi,
On Thu, 17 Oct 2019 at 08:28, Simon Glass sjg@chromium.org wrote:
Hi Vignesh,
On Wed, 16 Oct 2019 at 04:28, Vignesh Raghavendra vigneshr@ti.com wrote:
Hi Simon,
On 12/10/19 10:03 AM, Bin Meng wrote:
Hi Simon,
On Sat, Oct 12, 2019 at 11:08 AM Simon Glass sjg@chromium.org wrote:
Hi Bin,
On Wed, 9 Oct 2019 at 07:55, Bin Meng bmeng.cn@gmail.com wrote:
Hi Simon,
On Wed, Sep 25, 2019 at 10:12 PM Simon Glass sjg@chromium.org wrote: > > On x86 platforms the SPI flash can be mapped into memory so that the > contents can be read with normal memory accesses. > > Add a new SPI flash method to find the location of the SPI flash in > memory. This differs from the existing device-tree "memory-map" mechanism > in that the location can be discovered at run-time. >
Whats is the usecase? Why can't spi_flash_read() be used instead? Flash + Controller driver can underneath take care of using memory mapped mode to read data from flash right while making sure that access is within valid window?
I can see spi_flash_read_dm() but it does not support returning a pointer to the data, only reading it.
No, I was merely suggesting to use spi_flash_read_dm() (which underneath can be implemented by spi_mem_ops) to get data from flash instead of using get_mmap() to get MMIO pointer and then reading the data using that potiner.
Also I cannot find any documentation about any of this. I've been looking in the doc/ directory.
I found the spi_mem.h file but it doesn't mention the meaning of the in and out buffer pointers so I don't know how to use them.
Is there an API missing or just comments/documentation?
spi-mem.h has struct and APIs documented as kerneldoc: https://elixir.bootlin.com/u-boot/latest/source/include/spi-mem.h#L72 https://elixir.bootlin.com/u-boot/latest/source/include/spi-mem.h#L168
Note that clients should still use spi_flash_*() APIs to interact with flash. spi_mem_ops are not an alternative to spi_flash_*() APIs which are used by other drivers to read/write data from/to flash. This continues to be the same.
Apart from this I have found that the ich_spi driver does not work for APL since it apparently only supports 'hardware sequencing'. I did try getting software sequencing to work, but no dice.
In addition, I found that enabling SPI flash, etc. added about 6KB of code!
So I think it might be best to have two SPI drivers for x86 - one for software sequencing and one for hardware?
Regards, Simon

Hi Vignesh,
On Fri, 18 Oct 2019 at 03:48, Vignesh Raghavendra vigneshr@ti.com wrote:
On 18/10/19 7:52 AM, Simon Glass wrote:
Hi,
On Thu, 17 Oct 2019 at 08:28, Simon Glass sjg@chromium.org wrote:
Hi Vignesh,
On Wed, 16 Oct 2019 at 04:28, Vignesh Raghavendra vigneshr@ti.com wrote:
Hi Simon,
On 12/10/19 10:03 AM, Bin Meng wrote:
Hi Simon,
On Sat, Oct 12, 2019 at 11:08 AM Simon Glass sjg@chromium.org wrote:
Hi Bin,
On Wed, 9 Oct 2019 at 07:55, Bin Meng bmeng.cn@gmail.com wrote: > > Hi Simon, > > On Wed, Sep 25, 2019 at 10:12 PM Simon Glass sjg@chromium.org wrote: >> >> On x86 platforms the SPI flash can be mapped into memory so that the >> contents can be read with normal memory accesses. >> >> Add a new SPI flash method to find the location of the SPI flash in >> memory. This differs from the existing device-tree "memory-map" mechanism >> in that the location can be discovered at run-time. >>
Whats is the usecase? Why can't spi_flash_read() be used instead? Flash + Controller driver can underneath take care of using memory mapped mode to read data from flash right while making sure that access is within valid window?
I can see spi_flash_read_dm() but it does not support returning a pointer to the data, only reading it.
No, I was merely suggesting to use spi_flash_read_dm() (which underneath can be implemented by spi_mem_ops) to get data from flash instead of using get_mmap() to get MMIO pointer and then reading the data using that potiner.
OK I see.
Also I cannot find any documentation about any of this. I've been looking in the doc/ directory.
I found the spi_mem.h file but it doesn't mention the meaning of the in and out buffer pointers so I don't know how to use them.
Is there an API missing or just comments/documentation?
spi-mem.h has struct and APIs documented as kerneldoc: https://elixir.bootlin.com/u-boot/latest/source/include/spi-mem.h#L72 https://elixir.bootlin.com/u-boot/latest/source/include/spi-mem.h#L168
Yes I see that, but these appear to be undocumented, or not documented enough to understand their purpose/use:
opcode in out
Could you please update that?
Note that clients should still use spi_flash_*() APIs to interact with flash. spi_mem_ops are not an alternative to spi_flash_*() APIs which are used by other drivers to read/write data from/to flash. This continues to be the same.
OK.
Regards, Simon

At present this driver is always included in SPL and TPL, if U-Boot proper enables it. Update the Makefile to provide full control using the existing Kconfig options.
Signed-off-by: Simon Glass sjg@chromium.org ---
Changes in v2: None
drivers/sysreset/Kconfig | 12 ++++++++++++ drivers/sysreset/Makefile | 2 +- 2 files changed, 13 insertions(+), 1 deletion(-)
diff --git a/drivers/sysreset/Kconfig b/drivers/sysreset/Kconfig index f565ae03109..dcce2be6412 100644 --- a/drivers/sysreset/Kconfig +++ b/drivers/sysreset/Kconfig @@ -107,6 +107,18 @@ config SYSRESET_X86 help Reboot support for generic x86 processor reset.
+config SYSRESET_SPL_X86 + bool "Enable support for x86 processor reboot driver in SPL" + depends on X86 + help + Reboot support for generic x86 processor reset. + +config SYSRESET_TPL_X86 + bool "Enable support for x86 processor reboot driver in TPL" + depends on X86 + help + Reboot support for generic x86 processor reset. + config SYSRESET_MCP83XX bool "Enable support MPC83xx SoC family reboot driver" help diff --git a/drivers/sysreset/Makefile b/drivers/sysreset/Makefile index cf01492295f..fff4a184a02 100644 --- a/drivers/sysreset/Makefile +++ b/drivers/sysreset/Makefile @@ -16,5 +16,5 @@ obj-$(CONFIG_SYSRESET_SOCFPGA_S10) += sysreset_socfpga_s10.o obj-$(CONFIG_SYSRESET_TI_SCI) += sysreset-ti-sci.o obj-$(CONFIG_SYSRESET_SYSCON) += sysreset_syscon.o obj-$(CONFIG_SYSRESET_WATCHDOG) += sysreset_watchdog.o -obj-$(CONFIG_SYSRESET_X86) += sysreset_x86.o +obj-$(CONFIG_$(SPL_TPL_)SYSRESET_X86) += sysreset_x86.o obj-$(CONFIG_TARGET_XTFPGA) += sysreset_xtfpga.o

On Wed, Sep 25, 2019 at 10:12 PM Simon Glass sjg@chromium.org wrote:
At present this driver is always included in SPL and TPL, if U-Boot proper enables it. Update the Makefile to provide full control using the existing Kconfig options.
Signed-off-by: Simon Glass sjg@chromium.org
Changes in v2: None
drivers/sysreset/Kconfig | 12 ++++++++++++ drivers/sysreset/Makefile | 2 +- 2 files changed, 13 insertions(+), 1 deletion(-)
Reviewed-by: Bin Meng bmeng.cn@gmail.com

On Wed, Oct 2, 2019 at 10:06 PM Bin Meng bmeng.cn@gmail.com wrote:
On Wed, Sep 25, 2019 at 10:12 PM Simon Glass sjg@chromium.org wrote:
At present this driver is always included in SPL and TPL, if U-Boot proper enables it. Update the Makefile to provide full control using the existing Kconfig options.
Signed-off-by: Simon Glass sjg@chromium.org
Changes in v2: None
drivers/sysreset/Kconfig | 12 ++++++++++++ drivers/sysreset/Makefile | 2 +- 2 files changed, 13 insertions(+), 1 deletion(-)
Reviewed-by: Bin Meng bmeng.cn@gmail.com
applied to u-boot-x86/next, thanks!

Given these exported function an fsp_ prefix since they are declared in an fsp.h header.
Signed-off-by: Simon Glass sjg@chromium.org ---
Changes in v2: None
arch/x86/cpu/baytrail/fsp_configs.c | 2 +- arch/x86/cpu/braswell/fsp_configs.c | 2 +- arch/x86/cpu/ivybridge/fsp_configs.c | 2 +- arch/x86/cpu/queensbay/fsp_configs.c | 2 +- arch/x86/include/asm/fsp1/fsp_support.h | 6 +++--- arch/x86/lib/fsp1/fsp_car.S | 10 +++++----- arch/x86/lib/fsp1/fsp_support.c | 14 +++++++------- cmd/x86/fsp.c | 2 +- 8 files changed, 20 insertions(+), 20 deletions(-)
diff --git a/arch/x86/cpu/baytrail/fsp_configs.c b/arch/x86/cpu/baytrail/fsp_configs.c index 5b5d66aa5e9..1d1948c91a8 100644 --- a/arch/x86/cpu/baytrail/fsp_configs.c +++ b/arch/x86/cpu/baytrail/fsp_configs.c @@ -27,7 +27,7 @@ __weak void update_fsp_azalia_configs(struct azalia_config **azalia) * If the device tree does not specify an integer setting, use the default * provided in Intel's Baytrail_FSP_Gold4.tgz release FSP/BayleyBayFsp.bsf file. */ -void update_fsp_configs(struct fsp_config_data *config, +void fsp_update_configs(struct fsp_config_data *config, struct fspinit_rtbuf *rt_buf) { struct upd_region *fsp_upd = &config->fsp_upd; diff --git a/arch/x86/cpu/braswell/fsp_configs.c b/arch/x86/cpu/braswell/fsp_configs.c index 607e333f21c..60101d742d1 100644 --- a/arch/x86/cpu/braswell/fsp_configs.c +++ b/arch/x86/cpu/braswell/fsp_configs.c @@ -40,7 +40,7 @@ __weak void update_fsp_gpio_configs(struct gpio_family **family, * If the device tree does not specify an integer setting, use the default * provided in Intel's Braswell release FSP/BraswellFsp.bsf file. */ -void update_fsp_configs(struct fsp_config_data *config, +void fsp_update_configs(struct fsp_config_data *config, struct fspinit_rtbuf *rt_buf) { struct upd_region *fsp_upd = &config->fsp_upd; diff --git a/arch/x86/cpu/ivybridge/fsp_configs.c b/arch/x86/cpu/ivybridge/fsp_configs.c index 773c2b2a0ae..0e6453c8477 100644 --- a/arch/x86/cpu/ivybridge/fsp_configs.c +++ b/arch/x86/cpu/ivybridge/fsp_configs.c @@ -9,7 +9,7 @@
DECLARE_GLOBAL_DATA_PTR;
-void update_fsp_configs(struct fsp_config_data *config, +void fsp_update_configs(struct fsp_config_data *config, struct fspinit_rtbuf *rt_buf) { struct platform_config *plat_config = &config->plat_config; diff --git a/arch/x86/cpu/queensbay/fsp_configs.c b/arch/x86/cpu/queensbay/fsp_configs.c index 0dd1901e07b..381edd07615 100644 --- a/arch/x86/cpu/queensbay/fsp_configs.c +++ b/arch/x86/cpu/queensbay/fsp_configs.c @@ -7,7 +7,7 @@ #include <common.h> #include <asm/fsp1/fsp_support.h>
-void update_fsp_configs(struct fsp_config_data *config, +void fsp_update_configs(struct fsp_config_data *config, struct fspinit_rtbuf *rt_buf) { /* Initialize runtime buffer for fsp_init() */ diff --git a/arch/x86/include/asm/fsp1/fsp_support.h b/arch/x86/include/asm/fsp1/fsp_support.h index d69c0a4986a..b84fbeace7e 100644 --- a/arch/x86/include/asm/fsp1/fsp_support.h +++ b/arch/x86/include/asm/fsp1/fsp_support.h @@ -29,7 +29,7 @@ struct fsp_config_data; * * This routine jumps to the C version of FSP continuation function */ -void asm_continuation(void); +void fsp_asm_continuation(void);
/** * FSP initialization complete @@ -56,7 +56,7 @@ void fsp_continue(u32 status, void *hob_list); * * @retval: the offset of FSP header. If signature is invalid, returns 0. */ -struct fsp_header *find_fsp_header(void); +struct fsp_header *fsp_find_header(void);
/** * FSP initialization wrapper function. @@ -176,7 +176,7 @@ void *fsp_get_graphics_info(const void *hob_list, u32 *len); * * @return: None */ -void update_fsp_configs(struct fsp_config_data *config, +void fsp_update_configs(struct fsp_config_data *config, struct fspinit_rtbuf *rt_buf);
/** diff --git a/arch/x86/lib/fsp1/fsp_car.S b/arch/x86/lib/fsp1/fsp_car.S index 8c54cea3db4..a64a6534357 100644 --- a/arch/x86/lib/fsp1/fsp_car.S +++ b/arch/x86/lib/fsp1/fsp_car.S @@ -20,10 +20,10 @@ car_init:
car_init_start: post_code(POST_CAR_START) - lea find_fsp_header_romstack, %esp - jmp find_fsp_header + lea fsp_find_header_romstack, %esp + jmp fsp_find_header
-find_fsp_header_ret: +fsp_find_header_ret: /* EAX points to FSP_INFO_HEADER */ mov %eax, %ebp
@@ -91,8 +91,8 @@ die: * contain the function return address as well as the parameters. */ .balign 4 -find_fsp_header_romstack: - .long find_fsp_header_ret +fsp_find_header_romstack: + .long fsp_find_header_ret
.balign 4 temp_ram_init_romstack: diff --git a/arch/x86/lib/fsp1/fsp_support.c b/arch/x86/lib/fsp1/fsp_support.c index 019a42f53fe..b5b7d664a1e 100644 --- a/arch/x86/lib/fsp1/fsp_support.c +++ b/arch/x86/lib/fsp1/fsp_support.c @@ -8,7 +8,7 @@ #include <asm/fsp1/fsp_support.h> #include <asm/post.h>
-struct fsp_header *__attribute__((optimize("O0"))) find_fsp_header(void) +struct fsp_header *__attribute__((optimize("O0"))) fsp_find_header(void) { /* * This function may be called before the a stack is established, @@ -93,7 +93,7 @@ void fsp_init(u32 stack_top, u32 boot_mode, void *nvs_buf) struct upd_region *fsp_upd; #endif
- fsp_hdr = find_fsp_header(); + fsp_hdr = fsp_find_header(); if (fsp_hdr == NULL) { /* No valid FSP info header was found */ panic("Invalid FSP header"); @@ -124,12 +124,12 @@ void fsp_init(u32 stack_top, u32 boot_mode, void *nvs_buf) memset(&rt_buf, 0, sizeof(struct fspinit_rtbuf));
/* Override any configuration if required */ - update_fsp_configs(&config_data, &rt_buf); + fsp_update_configs(&config_data, &rt_buf);
memset(¶ms, 0, sizeof(struct fsp_init_params)); params.nvs_buf = nvs_buf; params.rt_buf = (struct fspinit_rtbuf *)&rt_buf; - params.continuation = (fsp_continuation_f)asm_continuation; + params.continuation = (fsp_continuation_f)fsp_asm_continuation;
init = (fsp_init_f)(fsp_hdr->img_base + fsp_hdr->fsp_init); params_ptr = ¶ms; @@ -146,8 +146,8 @@ void fsp_init(u32 stack_top, u32 boot_mode, void *nvs_buf) asm volatile ( "pushl %0;" "call *%%eax;" - ".global asm_continuation;" - "asm_continuation:;" + ".global fsp_asm_continuation;" + "fsp_asm_continuation:;" "movl 4(%%esp), %%eax;" /* status */ "movl 8(%%esp), %%edx;" /* hob_list */ "jmp fsp_continue;" @@ -173,7 +173,7 @@ u32 fsp_notify(struct fsp_header *fsp_hdr, u32 phase) u32 status;
if (!fsp_hdr) - fsp_hdr = (struct fsp_header *)find_fsp_header(); + fsp_hdr = (struct fsp_header *)fsp_find_header();
if (fsp_hdr == NULL) { /* No valid FSP info header */ diff --git a/cmd/x86/fsp.c b/cmd/x86/fsp.c index fb27624422c..b3b663021bc 100644 --- a/cmd/x86/fsp.c +++ b/cmd/x86/fsp.c @@ -11,7 +11,7 @@ DECLARE_GLOBAL_DATA_PTR;
static int do_hdr(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) { - struct fsp_header *hdr = find_fsp_header(); + struct fsp_header *hdr = fsp_find_header(); u32 img_addr = hdr->img_base; char *sign = (char *)&hdr->sign; int i;

On Wed, Sep 25, 2019 at 10:12 PM Simon Glass sjg@chromium.org wrote:
Given these exported function an fsp_ prefix since they are declared in an fsp.h header.
Signed-off-by: Simon Glass sjg@chromium.org
Changes in v2: None
arch/x86/cpu/baytrail/fsp_configs.c | 2 +- arch/x86/cpu/braswell/fsp_configs.c | 2 +- arch/x86/cpu/ivybridge/fsp_configs.c | 2 +- arch/x86/cpu/queensbay/fsp_configs.c | 2 +- arch/x86/include/asm/fsp1/fsp_support.h | 6 +++--- arch/x86/lib/fsp1/fsp_car.S | 10 +++++----- arch/x86/lib/fsp1/fsp_support.c | 14 +++++++------- cmd/x86/fsp.c | 2 +- 8 files changed, 20 insertions(+), 20 deletions(-)
Reviewed-by: Bin Meng bmeng.cn@gmail.com

On Wed, Oct 2, 2019 at 10:06 PM Bin Meng bmeng.cn@gmail.com wrote:
On Wed, Sep 25, 2019 at 10:12 PM Simon Glass sjg@chromium.org wrote:
Given these exported function an fsp_ prefix since they are declared in an fsp.h header.
Signed-off-by: Simon Glass sjg@chromium.org
Changes in v2: None
arch/x86/cpu/baytrail/fsp_configs.c | 2 +- arch/x86/cpu/braswell/fsp_configs.c | 2 +- arch/x86/cpu/ivybridge/fsp_configs.c | 2 +- arch/x86/cpu/queensbay/fsp_configs.c | 2 +- arch/x86/include/asm/fsp1/fsp_support.h | 6 +++--- arch/x86/lib/fsp1/fsp_car.S | 10 +++++----- arch/x86/lib/fsp1/fsp_support.c | 14 +++++++------- cmd/x86/fsp.c | 2 +- 8 files changed, 20 insertions(+), 20 deletions(-)
Reviewed-by: Bin Meng bmeng.cn@gmail.com
applied to u-boot-x86/next, thanks!

Many support functions are common between FSP1 and FSP2. Add a new header to handle this.
Signed-off-by: Simon Glass sjg@chromium.org ---
Changes in v2: None
arch/x86/include/asm/fsp/fsp_support.h | 128 ++++++++++++++++++++++++ arch/x86/include/asm/fsp1/fsp_support.h | 123 +---------------------- drivers/pci/pci-uclass.c | 2 +- 3 files changed, 132 insertions(+), 121 deletions(-) create mode 100644 arch/x86/include/asm/fsp/fsp_support.h
diff --git a/arch/x86/include/asm/fsp/fsp_support.h b/arch/x86/include/asm/fsp/fsp_support.h new file mode 100644 index 00000000000..0ecd5cb6c5d --- /dev/null +++ b/arch/x86/include/asm/fsp/fsp_support.h @@ -0,0 +1,128 @@ +/* SPDX-License-Identifier: Intel */ +/* + * Copyright (C) 2013, Intel Corporation + * Copyright (C) 2014, Bin Meng bmeng.cn@gmail.com + */ + +#ifndef __FSP_SUPPORT_H__ +#define __FSP_SUPPORT_H__ + +#include <asm/fsp/fsp_bootmode.h> +#include <asm/fsp/fsp_fv.h> +#include <asm/fsp/fsp_hob.h> +#include <asm/fsp/fsp_infoheader.h> +#include <asm/fsp/fsp_types.h> +#include <asm/fsp_arch.h> +#include <asm/fsp/fsp_azalia.h> + +#define FSP_LOWMEM_BASE 0x100000UL +#define FSP_HIGHMEM_BASE 0x100000000ULL +#define UPD_TERMINATOR 0x55AA + +struct fspinit_rtbuf; +struct fsp_config_data; + +/** + * Find FSP header offset in FSP image + * + * @retval: the offset of FSP header. If signature is invalid, returns 0. + */ +struct fsp_header *fsp_find_header(void); + +/** + * FSP notification wrapper function + * + * @fsp_hdr: Pointer to FSP information header + * @phase: FSP initialization phase defined in enum fsp_phase + * + * @retval: compatible status code with EFI_STATUS defined in PI spec + */ +u32 fsp_notify(struct fsp_header *fsp_hdr, u32 phase); + +/** + * This function retrieves the top of usable low memory. + * + * @hob_list: A HOB list pointer. + * + * @retval: Usable low memory top. + */ +u32 fsp_get_usable_lowmem_top(const void *hob_list); + +/** + * This function retrieves the top of usable high memory. + * + * @hob_list: A HOB list pointer. + * + * @retval: Usable high memory top. + */ +u64 fsp_get_usable_highmem_top(const void *hob_list); + +/** + * This function retrieves a special reserved memory region. + * + * @hob_list: A HOB list pointer. + * @len: A pointer to the GUID HOB data buffer length. + * If the GUID HOB is located, the length will be updated. + * @guid: A pointer to the owner guild. + * + * @retval: Reserved region start address. + * 0 if this region does not exist. + */ +u64 fsp_get_reserved_mem_from_guid(const void *hob_list, + u64 *len, const efi_guid_t *guid); + +/** + * This function retrieves the FSP reserved normal memory. + * + * @hob_list: A HOB list pointer. + * @len: A pointer to the FSP reserved memory length buffer. + * If the GUID HOB is located, the length will be updated. + * @retval: FSP reserved memory base + * 0 if this region does not exist. + */ +u32 fsp_get_fsp_reserved_mem(const void *hob_list, u32 *len); + +/** + * This function retrieves the TSEG reserved normal memory. + * + * @hob_list: A HOB list pointer. + * @len: A pointer to the TSEG reserved memory length buffer. + * If the GUID HOB is located, the length will be updated. + * + * @retval NULL: Failed to find the TSEG reserved memory. + * @retval others: TSEG reserved memory base. + */ +u32 fsp_get_tseg_reserved_mem(const void *hob_list, u32 *len); + +/** + * This function retrieves FSP Non-volatile Storage HOB buffer and size. + * + * @hob_list: A HOB list pointer. + * @len: A pointer to the NVS data buffer length. + * If the HOB is located, the length will be updated. + * + * @retval NULL: Failed to find the NVS HOB. + * @retval others: FSP NVS data buffer pointer. + */ +void *fsp_get_nvs_data(const void *hob_list, u32 *len); + +/** + * This function retrieves graphics information. + * + * @hob_list: A HOB list pointer. + * @len: A pointer to the graphics info HOB length. + * If the HOB is located, the length will be updated. + * + * @retval NULL: Failed to find the graphics info HOB. + * @retval others: A pointer to struct hob_graphics_info. + */ +void *fsp_get_graphics_info(const void *hob_list, u32 *len); + +/** + * fsp_init_phase_pci() - Tell the FSP that we have completed PCI init + * + * @return 0 if OK, -EPERM if the FSP gave an error. + */ +int fsp_init_phase_pci(void); + +#endif diff --git a/arch/x86/include/asm/fsp1/fsp_support.h b/arch/x86/include/asm/fsp1/fsp_support.h index b84fbeace7e..15c3a462e2e 100644 --- a/arch/x86/include/asm/fsp1/fsp_support.h +++ b/arch/x86/include/asm/fsp1/fsp_support.h @@ -4,25 +4,11 @@ * Copyright (C) 2014, Bin Meng bmeng.cn@gmail.com */
-#ifndef __FSP_SUPPORT_H__ -#define __FSP_SUPPORT_H__ +#ifndef __FSP1_SUPPORT_H__ +#define __FSP1_SUPPORT_H__
-#include <asm/fsp/fsp_bootmode.h> -#include <asm/fsp/fsp_fv.h> -#include <asm/fsp/fsp_hob.h> -#include <asm/fsp/fsp_infoheader.h> -#include <asm/fsp/fsp_types.h> +#include <asm/fsp/fsp_support.h> #include "fsp_ffs.h" -#include <asm/fsp_arch.h> -#include <asm/fsp/fsp_azalia.h> - -#define FSP_LOWMEM_BASE 0x100000UL -#define FSP_HIGHMEM_BASE 0x100000000ULL -#define UPD_TERMINATOR 0x55AA - -/* Forward declarations for update_fsp_configs() */ -struct fspinit_rtbuf; -struct fsp_config_data;
/** * FSP Continuation assembly helper routine @@ -51,13 +37,6 @@ void fsp_init_done(void *hob_list); */ void fsp_continue(u32 status, void *hob_list);
-/** - * Find FSP header offset in FSP image - * - * @retval: the offset of FSP header. If signature is invalid, returns 0. - */ -struct fsp_header *fsp_find_header(void); - /** * FSP initialization wrapper function. * @@ -67,83 +46,6 @@ struct fsp_header *fsp_find_header(void); */ void fsp_init(u32 stack_top, u32 boot_mode, void *nvs_buf);
-/** - * FSP notification wrapper function - * - * @fsp_hdr: Pointer to FSP information header - * @phase: FSP initialization phase defined in enum fsp_phase - * - * @retval: compatible status code with EFI_STATUS defined in PI spec - */ -u32 fsp_notify(struct fsp_header *fsp_hdr, u32 phase); - -/** - * This function retrieves the top of usable low memory. - * - * @hob_list: A HOB list pointer. - * - * @retval: Usable low memory top. - */ -u32 fsp_get_usable_lowmem_top(const void *hob_list); - -/** - * This function retrieves the top of usable high memory. - * - * @hob_list: A HOB list pointer. - * - * @retval: Usable high memory top. - */ -u64 fsp_get_usable_highmem_top(const void *hob_list); - -/** - * This function retrieves a special reserved memory region. - * - * @hob_list: A HOB list pointer. - * @len: A pointer to the GUID HOB data buffer length. - * If the GUID HOB is located, the length will be updated. - * @guid: A pointer to the owner guild. - * - * @retval: Reserved region start address. - * 0 if this region does not exist. - */ -u64 fsp_get_reserved_mem_from_guid(const void *hob_list, - u64 *len, const efi_guid_t *guid); - -/** - * This function retrieves the FSP reserved normal memory. - * - * @hob_list: A HOB list pointer. - * @len: A pointer to the FSP reserved memory length buffer. - * If the GUID HOB is located, the length will be updated. - * @retval: FSP reserved memory base - * 0 if this region does not exist. - */ -u32 fsp_get_fsp_reserved_mem(const void *hob_list, u32 *len); - -/** - * This function retrieves the TSEG reserved normal memory. - * - * @hob_list: A HOB list pointer. - * @len: A pointer to the TSEG reserved memory length buffer. - * If the GUID HOB is located, the length will be updated. - * - * @retval NULL: Failed to find the TSEG reserved memory. - * @retval others: TSEG reserved memory base. - */ -u32 fsp_get_tseg_reserved_mem(const void *hob_list, u32 *len); - -/** - * This function retrieves FSP Non-volatile Storage HOB buffer and size. - * - * @hob_list: A HOB list pointer. - * @len: A pointer to the NVS data buffer length. - * If the HOB is located, the length will be updated. - * - * @retval NULL: Failed to find the NVS HOB. - * @retval others: FSP NVS data buffer pointer. - */ -void *fsp_get_nvs_data(const void *hob_list, u32 *len); - /** * This function retrieves Bootloader temporary stack buffer and size. * @@ -156,18 +58,6 @@ void *fsp_get_nvs_data(const void *hob_list, u32 *len); */ void *fsp_get_bootloader_tmp_mem(const void *hob_list, u32 *len);
-/** - * This function retrieves graphics information. - * - * @hob_list: A HOB list pointer. - * @len: A pointer to the graphics info HOB length. - * If the HOB is located, the length will be updated. - * - * @retval NULL: Failed to find the graphics info HOB. - * @retval others: A pointer to struct hob_graphics_info. - */ -void *fsp_get_graphics_info(const void *hob_list, u32 *len); - /** * This function overrides the default configurations of FSP. * @@ -179,11 +69,4 @@ void *fsp_get_graphics_info(const void *hob_list, u32 *len); void fsp_update_configs(struct fsp_config_data *config, struct fspinit_rtbuf *rt_buf);
-/** - * fsp_init_phase_pci() - Tell the FSP that we have completed PCI init - * - * @return 0 if OK, -EPERM if the FSP gave an error. - */ -int fsp_init_phase_pci(void); - #endif diff --git a/drivers/pci/pci-uclass.c b/drivers/pci/pci-uclass.c index b73d0cd70a7..ab3e1310eb5 100644 --- a/drivers/pci/pci-uclass.c +++ b/drivers/pci/pci-uclass.c @@ -12,7 +12,7 @@ #include <dm/device-internal.h> #include <dm/lists.h> #if defined(CONFIG_X86) && defined(CONFIG_HAVE_FSP) -#include <asm/fsp1/fsp_support.h> +#include <asm/fsp/fsp_support.h> #endif #include "pci_internal.h"

On Wed, Sep 25, 2019 at 10:12 PM Simon Glass sjg@chromium.org wrote:
Many support functions are common between FSP1 and FSP2. Add a new header to handle this.
Signed-off-by: Simon Glass sjg@chromium.org
Changes in v2: None
arch/x86/include/asm/fsp/fsp_support.h | 128 ++++++++++++++++++++++++ arch/x86/include/asm/fsp1/fsp_support.h | 123 +---------------------- drivers/pci/pci-uclass.c | 2 +- 3 files changed, 132 insertions(+), 121 deletions(-) create mode 100644 arch/x86/include/asm/fsp/fsp_support.h
Reviewed-by: Bin Meng bmeng.cn@gmail.com

On Wed, Oct 2, 2019 at 10:06 PM Bin Meng bmeng.cn@gmail.com wrote:
On Wed, Sep 25, 2019 at 10:12 PM Simon Glass sjg@chromium.org wrote:
Many support functions are common between FSP1 and FSP2. Add a new header to handle this.
Signed-off-by: Simon Glass sjg@chromium.org
Changes in v2: None
arch/x86/include/asm/fsp/fsp_support.h | 128 ++++++++++++++++++++++++ arch/x86/include/asm/fsp1/fsp_support.h | 123 +---------------------- drivers/pci/pci-uclass.c | 2 +- 3 files changed, 132 insertions(+), 121 deletions(-) create mode 100644 arch/x86/include/asm/fsp/fsp_support.h
Reviewed-by: Bin Meng bmeng.cn@gmail.com
Fixed the rebase conflicts, and
applied to u-boot-x86/next, thanks!

Update a few #ifdefs to if() to improve build coverage.
Signed-off-by: Simon Glass sjg@chromium.org ---
Changes in v2: None
arch/x86/lib/fsp1/fsp_common.c | 9 ++++----- arch/x86/lib/fsp1/fsp_dram.c | 8 ++------ 2 files changed, 6 insertions(+), 11 deletions(-)
diff --git a/arch/x86/lib/fsp1/fsp_common.c b/arch/x86/lib/fsp1/fsp_common.c index 591eef7b813..bfd76dccbab 100644 --- a/arch/x86/lib/fsp1/fsp_common.c +++ b/arch/x86/lib/fsp1/fsp_common.c @@ -116,11 +116,10 @@ int arch_fsp_init(void) #endif
if (!gd->arch.hob_list) { -#ifdef CONFIG_ENABLE_MRC_CACHE - nvs = fsp_prepare_mrc_cache(); -#else - nvs = NULL; -#endif + if (IS_ENABLED(CONFIG_ENABLE_MRC_CACHE)) + nvs = fsp_prepare_mrc_cache(); + else + nvs = NULL;
#ifdef CONFIG_HAVE_ACPI_RESUME if (prev_sleep_state == ACPI_S3) { diff --git a/arch/x86/lib/fsp1/fsp_dram.c b/arch/x86/lib/fsp1/fsp_dram.c index 3bf65b495ca..961e963362a 100644 --- a/arch/x86/lib/fsp1/fsp_dram.c +++ b/arch/x86/lib/fsp1/fsp_dram.c @@ -29,13 +29,9 @@ int dram_init(void) hdr = get_next_hob(hdr); }
- gd->ram_size = ram_size; - post_code(POST_DRAM); - -#ifdef CONFIG_ENABLE_MRC_CACHE - gd->arch.mrc_output = fsp_get_nvs_data(gd->arch.hob_list, + if (IS_ENABLED(CONFIG_ENABLE_MRC_CACHE)) + gd->arch.mrc_output = fsp_get_nvs_data(gd->arch.hob_list, &gd->arch.mrc_output_len); -#endif
return 0; }

On Wed, Sep 25, 2019 at 10:12 PM Simon Glass sjg@chromium.org wrote:
Update a few #ifdefs to if() to improve build coverage.
Signed-off-by: Simon Glass sjg@chromium.org
Changes in v2: None
arch/x86/lib/fsp1/fsp_common.c | 9 ++++----- arch/x86/lib/fsp1/fsp_dram.c | 8 ++------ 2 files changed, 6 insertions(+), 11 deletions(-)
diff --git a/arch/x86/lib/fsp1/fsp_common.c b/arch/x86/lib/fsp1/fsp_common.c index 591eef7b813..bfd76dccbab 100644 --- a/arch/x86/lib/fsp1/fsp_common.c +++ b/arch/x86/lib/fsp1/fsp_common.c @@ -116,11 +116,10 @@ int arch_fsp_init(void) #endif
if (!gd->arch.hob_list) {
-#ifdef CONFIG_ENABLE_MRC_CACHE
nvs = fsp_prepare_mrc_cache();
-#else
nvs = NULL;
-#endif
if (IS_ENABLED(CONFIG_ENABLE_MRC_CACHE))
nvs = fsp_prepare_mrc_cache();
else
nvs = NULL;
#ifdef CONFIG_HAVE_ACPI_RESUME if (prev_sleep_state == ACPI_S3) { diff --git a/arch/x86/lib/fsp1/fsp_dram.c b/arch/x86/lib/fsp1/fsp_dram.c index 3bf65b495ca..961e963362a 100644 --- a/arch/x86/lib/fsp1/fsp_dram.c +++ b/arch/x86/lib/fsp1/fsp_dram.c @@ -29,13 +29,9 @@ int dram_init(void) hdr = get_next_hob(hdr); }
gd->ram_size = ram_size;
post_code(POST_DRAM);
These should not be removed.
I will fix this when applying.
-#ifdef CONFIG_ENABLE_MRC_CACHE
gd->arch.mrc_output = fsp_get_nvs_data(gd->arch.hob_list,
if (IS_ENABLED(CONFIG_ENABLE_MRC_CACHE))
gd->arch.mrc_output = fsp_get_nvs_data(gd->arch.hob_list, &gd->arch.mrc_output_len);
-#endif
return 0;
}
Reviewed-by: Bin Meng bmeng.cn@gmail.com

On Thu, Oct 3, 2019 at 4:16 PM Bin Meng bmeng.cn@gmail.com wrote:
On Wed, Sep 25, 2019 at 10:12 PM Simon Glass sjg@chromium.org wrote:
Update a few #ifdefs to if() to improve build coverage.
Signed-off-by: Simon Glass sjg@chromium.org
Changes in v2: None
arch/x86/lib/fsp1/fsp_common.c | 9 ++++----- arch/x86/lib/fsp1/fsp_dram.c | 8 ++------ 2 files changed, 6 insertions(+), 11 deletions(-)
diff --git a/arch/x86/lib/fsp1/fsp_common.c b/arch/x86/lib/fsp1/fsp_common.c index 591eef7b813..bfd76dccbab 100644 --- a/arch/x86/lib/fsp1/fsp_common.c +++ b/arch/x86/lib/fsp1/fsp_common.c @@ -116,11 +116,10 @@ int arch_fsp_init(void) #endif
if (!gd->arch.hob_list) {
-#ifdef CONFIG_ENABLE_MRC_CACHE
nvs = fsp_prepare_mrc_cache();
-#else
nvs = NULL;
-#endif
if (IS_ENABLED(CONFIG_ENABLE_MRC_CACHE))
nvs = fsp_prepare_mrc_cache();
else
nvs = NULL;
#ifdef CONFIG_HAVE_ACPI_RESUME if (prev_sleep_state == ACPI_S3) { diff --git a/arch/x86/lib/fsp1/fsp_dram.c b/arch/x86/lib/fsp1/fsp_dram.c index 3bf65b495ca..961e963362a 100644 --- a/arch/x86/lib/fsp1/fsp_dram.c +++ b/arch/x86/lib/fsp1/fsp_dram.c @@ -29,13 +29,9 @@ int dram_init(void) hdr = get_next_hob(hdr); }
gd->ram_size = ram_size;
post_code(POST_DRAM);
These should not be removed.
I will fix this when applying.
-#ifdef CONFIG_ENABLE_MRC_CACHE
gd->arch.mrc_output = fsp_get_nvs_data(gd->arch.hob_list,
if (IS_ENABLED(CONFIG_ENABLE_MRC_CACHE))
gd->arch.mrc_output = fsp_get_nvs_data(gd->arch.hob_list, &gd->arch.mrc_output_len);
-#endif
return 0;
}
Reviewed-by: Bin Meng bmeng.cn@gmail.com
Fixed the issues, and
applied to u-boot-x86/next, thanks!

The comments in the FSP code use a different style from the rest of the x86 code. I am not sure it this is intentional.
Signed-off-by: Simon Glass sjg@chromium.org ---
Changes in v2: None
arch/x86/include/asm/fsp/fsp_support.h | 42 ++++++++++++------------- arch/x86/include/asm/fsp1/fsp_support.h | 30 ++++++++++++------ arch/x86/include/asm/hob.h | 18 +++++------ arch/x86/lib/hob.c | 8 ++--- 4 files changed, 54 insertions(+), 44 deletions(-)
diff --git a/arch/x86/include/asm/fsp/fsp_support.h b/arch/x86/include/asm/fsp/fsp_support.h index 0ecd5cb6c5d..8d29f9f5e4b 100644 --- a/arch/x86/include/asm/fsp/fsp_support.h +++ b/arch/x86/include/asm/fsp/fsp_support.h @@ -23,98 +23,98 @@ struct fspinit_rtbuf; struct fsp_config_data;
/** - * Find FSP header offset in FSP image + * fsp_find_header() - Find FSP header offset in FSP image * - * @retval: the offset of FSP header. If signature is invalid, returns 0. + * @return the offset of FSP header. If signature is invalid, returns 0. */ struct fsp_header *fsp_find_header(void);
/** - * FSP notification wrapper function + * fsp_notify() - FSP notification wrapper function * * @fsp_hdr: Pointer to FSP information header * @phase: FSP initialization phase defined in enum fsp_phase * - * @retval: compatible status code with EFI_STATUS defined in PI spec + * @return compatible status code with EFI_STATUS defined in PI spec */ u32 fsp_notify(struct fsp_header *fsp_hdr, u32 phase);
/** - * This function retrieves the top of usable low memory. + * fsp_get_usable_lowmem_top() - retrieves the top of usable low memory * * @hob_list: A HOB list pointer. * - * @retval: Usable low memory top. + * @return Usable low memory top. */ u32 fsp_get_usable_lowmem_top(const void *hob_list);
/** - * This function retrieves the top of usable high memory. + * fsp_get_usable_highmem_top() - retrieves the top of usable high memory * * @hob_list: A HOB list pointer. * - * @retval: Usable high memory top. + * @return Usable high memory top. */ u64 fsp_get_usable_highmem_top(const void *hob_list);
/** - * This function retrieves a special reserved memory region. + * fsp_get_reserved_mem_from_guid() - retrieves a special reserved memory region * * @hob_list: A HOB list pointer. * @len: A pointer to the GUID HOB data buffer length. * If the GUID HOB is located, the length will be updated. * @guid: A pointer to the owner guild. * - * @retval: Reserved region start address. + * @return Reserved region start address. * 0 if this region does not exist. */ u64 fsp_get_reserved_mem_from_guid(const void *hob_list, u64 *len, const efi_guid_t *guid);
/** - * This function retrieves the FSP reserved normal memory. + * fsp_get_fsp_reserved_mem() - retrieves the FSP reserved normal memory * * @hob_list: A HOB list pointer. * @len: A pointer to the FSP reserved memory length buffer. * If the GUID HOB is located, the length will be updated. - * @retval: FSP reserved memory base + * @return FSP reserved memory base * 0 if this region does not exist. */ u32 fsp_get_fsp_reserved_mem(const void *hob_list, u32 *len);
/** - * This function retrieves the TSEG reserved normal memory. + * fsp_get_tseg_reserved_mem() - retrieves the TSEG reserved normal memory * * @hob_list: A HOB list pointer. * @len: A pointer to the TSEG reserved memory length buffer. * If the GUID HOB is located, the length will be updated. * - * @retval NULL: Failed to find the TSEG reserved memory. - * @retval others: TSEG reserved memory base. + * @return NULL: Failed to find the TSEG reserved memory. + * @return others: TSEG reserved memory base. */ u32 fsp_get_tseg_reserved_mem(const void *hob_list, u32 *len);
/** - * This function retrieves FSP Non-volatile Storage HOB buffer and size. + * fsp_get_nvs_data() - retrieves FSP Non-volatile Storage HOB buffer and size * * @hob_list: A HOB list pointer. * @len: A pointer to the NVS data buffer length. * If the HOB is located, the length will be updated. * - * @retval NULL: Failed to find the NVS HOB. - * @retval others: FSP NVS data buffer pointer. + * @return NULL: Failed to find the NVS HOB. + * @return others: FSP NVS data buffer pointer. */ void *fsp_get_nvs_data(const void *hob_list, u32 *len);
/** - * This function retrieves graphics information. + * fsp_get_graphics_info() - retrieves graphics information. * * @hob_list: A HOB list pointer. * @len: A pointer to the graphics info HOB length. * If the HOB is located, the length will be updated. * - * @retval NULL: Failed to find the graphics info HOB. - * @retval others: A pointer to struct hob_graphics_info. + * @return NULL: Failed to find the graphics info HOB. + * @return others: A pointer to struct hob_graphics_info. */ void *fsp_get_graphics_info(const void *hob_list, u32 *len);
diff --git a/arch/x86/include/asm/fsp1/fsp_support.h b/arch/x86/include/asm/fsp1/fsp_support.h index 15c3a462e2e..236c167fc86 100644 --- a/arch/x86/include/asm/fsp1/fsp_support.h +++ b/arch/x86/include/asm/fsp1/fsp_support.h @@ -11,14 +11,14 @@ #include "fsp_ffs.h"
/** - * FSP Continuation assembly helper routine + * fsp_asm_continuation() - FSP Continuation assembly helper routine * * This routine jumps to the C version of FSP continuation function */ void fsp_asm_continuation(void);
/** - * FSP initialization complete + * fsp_init_done() - FSP initialization complete * * This is the function that indicates FSP initialization is complete and jumps * back to the bootloader with HOB list pointer as the parameter. @@ -28,17 +28,17 @@ void fsp_asm_continuation(void); void fsp_init_done(void *hob_list);
/** - * FSP Continuation function + * fsp_continue() - FSP Continuation function * * @status: Always 0 * @hob_list: HOB list pointer * - * @retval: Never returns + * @return Never returns */ void fsp_continue(u32 status, void *hob_list);
/** - * FSP initialization wrapper function. + * fsp_init() - FSP initialization wrapper function * * @stack_top: bootloader stack top address * @boot_mode: boot mode defined in fsp_bootmode.h @@ -47,24 +47,34 @@ void fsp_continue(u32 status, void *hob_list); void fsp_init(u32 stack_top, u32 boot_mode, void *nvs_buf);
/** - * This function retrieves Bootloader temporary stack buffer and size. + * fsp_notify() - FSP notification wrapper function + * + * @fsp_hdr: Pointer to FSP information header + * @phase: FSP initialization phase defined in enum fsp_phase + * + * @return compatible status code with EFI_STATUS defined in PI spec + */ +u32 fsp_notify(struct fsp_header *fsp_hdr, u32 phase); + +/** + * fsp_get_bootloader_tmp_mem() - retrieves temporary stack buffer and size * * @hob_list: A HOB list pointer. * @len: A pointer to the bootloader temporary stack length. * If the HOB is located, the length will be updated. * - * @retval NULL: Failed to find the bootloader temporary stack HOB. - * @retval others: Bootloader temporary stackbuffer pointer. + * @return NULL: Failed to find the bootloader temporary stack HOB. + * @return others: Bootloader temporary stackbuffer pointer. */ void *fsp_get_bootloader_tmp_mem(const void *hob_list, u32 *len);
/** - * This function overrides the default configurations of FSP. + * fsp_update_configs() - overrides the default configurations of FSP * * @config: A pointer to the FSP configuration data structure * @rt_buf: A pointer to the FSP runtime buffer data structure * - * @return: None + * @return None */ void fsp_update_configs(struct fsp_config_data *config, struct fspinit_rtbuf *rt_buf); diff --git a/arch/x86/include/asm/hob.h b/arch/x86/include/asm/hob.h index b4239821aaa..72151ea045e 100644 --- a/arch/x86/include/asm/hob.h +++ b/arch/x86/include/asm/hob.h @@ -135,7 +135,7 @@ struct hob_guid { * * @hdr: A pointer to a HOB. * - * @return: A pointer to the next HOB in the HOB list. + * @return A pointer to the next HOB in the HOB list. */ static inline const struct hob_header *get_next_hob(const struct hob_header *hdr) @@ -152,8 +152,8 @@ static inline const struct hob_header *get_next_hob(const struct hob_header * * @hdr: A pointer to a HOB. * - * @retval true: The HOB specified by hdr is the last HOB in the HOB list. - * @retval false: The HOB specified by hdr is not the last HOB in the HOB list. + * @return true: The HOB specified by hdr is the last HOB in the HOB list. + * @return false: The HOB specified by hdr is not the last HOB in the HOB list. */ static inline bool end_of_hob(const struct hob_header *hdr) { @@ -169,7 +169,7 @@ static inline bool end_of_hob(const struct hob_header *hdr) * * @hdr: A pointer to a HOB. * - * @return: A pointer to the data buffer in a HOB. + * @return A pointer to the data buffer in a HOB. */ static inline void *get_guid_hob_data(const struct hob_header *hdr) { @@ -185,7 +185,7 @@ static inline void *get_guid_hob_data(const struct hob_header *hdr) * * @hdr: A pointer to a HOB. * - * @return: The size of the data buffer. + * @return The size of the data buffer. */ static inline u16 get_guid_hob_data_size(const struct hob_header *hdr) { @@ -198,7 +198,7 @@ static inline u16 get_guid_hob_data_size(const struct hob_header *hdr) * @type: HOB type to search * @hob_list: A pointer to the HOB list * - * @retval: A HOB object with matching type; Otherwise NULL. + *@return A HOB object with matching type; Otherwise NULL. */ const struct hob_header *hob_get_next_hob(uint type, const void *hob_list);
@@ -208,7 +208,7 @@ const struct hob_header *hob_get_next_hob(uint type, const void *hob_list); * @guid: GUID to search * @hob_list: A pointer to the HOB list * - * @retval: A HOB object with matching GUID; Otherwise NULL. + *@return A HOB object with matching GUID; Otherwise NULL. */ const struct hob_header *hob_get_next_guid_hob(const efi_guid_t *guid, const void *hob_list); @@ -221,8 +221,8 @@ const struct hob_header *hob_get_next_guid_hob(const efi_guid_t *guid, * If the GUID HOB is located, the length will be updated. * @guid A pointer to HOB GUID. * - * @retval NULL: Failed to find the GUID HOB. - * @retval others: GUID HOB data buffer pointer. + * @return NULL: Failed to find the GUID HOB. + * @return others: GUID HOB data buffer pointer. */ void *hob_get_guid_hob_data(const void *hob_list, u32 *len, const efi_guid_t *guid); diff --git a/arch/x86/lib/hob.c b/arch/x86/lib/hob.c index dcee29b04cf..f2c47240ee8 100644 --- a/arch/x86/lib/hob.c +++ b/arch/x86/lib/hob.c @@ -13,7 +13,7 @@ * @type: HOB type to search * @hob_list: A pointer to the HOB list * - * @retval: A HOB object with matching type; Otherwise NULL. + * @return A HOB object with matching type; Otherwise NULL. */ const struct hob_header *hob_get_next_hob(uint type, const void *hob_list) { @@ -38,7 +38,7 @@ const struct hob_header *hob_get_next_hob(uint type, const void *hob_list) * @guid: GUID to search * @hob_list: A pointer to the HOB list * - * @retval: A HOB object with matching GUID; Otherwise NULL. + * @return A HOB object with matching GUID; Otherwise NULL. */ const struct hob_header *hob_get_next_guid_hob(const efi_guid_t *guid, const void *hob_list) @@ -65,8 +65,8 @@ const struct hob_header *hob_get_next_guid_hob(const efi_guid_t *guid, * If the GUID HOB is located, the length will be updated. * @guid A pointer to HOB GUID. * - * @retval NULL: Failed to find the GUID HOB. - * @retval others: GUID HOB data buffer pointer. + * @return NULL: Failed to find the GUID HOB. + * @return others: GUID HOB data buffer pointer. */ void *hob_get_guid_hob_data(const void *hob_list, u32 *len, const efi_guid_t *guid)

Hi Simon,
On Wed, Sep 25, 2019 at 10:12 PM Simon Glass sjg@chromium.org wrote:
The comments in the FSP code use a different style from the rest of the x86 code. I am not sure it this is intentional.
I guess it's because when it was written I was not familiar with the documenting style :)
Signed-off-by: Simon Glass sjg@chromium.org
Changes in v2: None
arch/x86/include/asm/fsp/fsp_support.h | 42 ++++++++++++------------- arch/x86/include/asm/fsp1/fsp_support.h | 30 ++++++++++++------ arch/x86/include/asm/hob.h | 18 +++++------ arch/x86/lib/hob.c | 8 ++--- 4 files changed, 54 insertions(+), 44 deletions(-)
[snip]
diff --git a/arch/x86/include/asm/hob.h b/arch/x86/include/asm/hob.h index b4239821aaa..72151ea045e 100644 --- a/arch/x86/include/asm/hob.h +++ b/arch/x86/include/asm/hob.h @@ -135,7 +135,7 @@ struct hob_guid {
- @hdr: A pointer to a HOB.
- @return: A pointer to the next HOB in the HOB list.
*/
- @return A pointer to the next HOB in the HOB list.
static inline const struct hob_header *get_next_hob(const struct hob_header *hdr) @@ -152,8 +152,8 @@ static inline const struct hob_header *get_next_hob(const struct hob_header
- @hdr: A pointer to a HOB.
- @retval true: The HOB specified by hdr is the last HOB in the HOB list.
- @retval false: The HOB specified by hdr is not the last HOB in the HOB list.
- @return true: The HOB specified by hdr is the last HOB in the HOB list.
*/
- @return false: The HOB specified by hdr is not the last HOB in the HOB list.
static inline bool end_of_hob(const struct hob_header *hdr) { @@ -169,7 +169,7 @@ static inline bool end_of_hob(const struct hob_header *hdr)
- @hdr: A pointer to a HOB.
- @return: A pointer to the data buffer in a HOB.
*/
- @return A pointer to the data buffer in a HOB.
static inline void *get_guid_hob_data(const struct hob_header *hdr) { @@ -185,7 +185,7 @@ static inline void *get_guid_hob_data(const struct hob_header *hdr)
- @hdr: A pointer to a HOB.
- @return: The size of the data buffer.
*/
- @return The size of the data buffer.
static inline u16 get_guid_hob_data_size(const struct hob_header *hdr) { @@ -198,7 +198,7 @@ static inline u16 get_guid_hob_data_size(const struct hob_header *hdr)
- @type: HOB type to search
- @hob_list: A pointer to the HOB list
- @retval: A HOB object with matching type; Otherwise NULL.
- *@return A HOB object with matching type; Otherwise NULL.
should have a space between * and @
*/ const struct hob_header *hob_get_next_hob(uint type, const void *hob_list);
@@ -208,7 +208,7 @@ const struct hob_header *hob_get_next_hob(uint type, const void *hob_list);
- @guid: GUID to search
- @hob_list: A pointer to the HOB list
- @retval: A HOB object with matching GUID; Otherwise NULL.
- *@return A HOB object with matching GUID; Otherwise NULL.
should have a space between * and @
*/ const struct hob_header *hob_get_next_guid_hob(const efi_guid_t *guid, const void *hob_list); @@ -221,8 +221,8 @@ const struct hob_header *hob_get_next_guid_hob(const efi_guid_t *guid,
If the GUID HOB is located, the length will be updated.
- @guid A pointer to HOB GUID.
- @retval NULL: Failed to find the GUID HOB.
- @retval others: GUID HOB data buffer pointer.
- @return NULL: Failed to find the GUID HOB.
*/
- @return others: GUID HOB data buffer pointer.
void *hob_get_guid_hob_data(const void *hob_list, u32 *len, const efi_guid_t *guid); diff --git a/arch/x86/lib/hob.c b/arch/x86/lib/hob.c index dcee29b04cf..f2c47240ee8 100644 --- a/arch/x86/lib/hob.c +++ b/arch/x86/lib/hob.c @@ -13,7 +13,7 @@
- @type: HOB type to search
- @hob_list: A pointer to the HOB list
- @retval: A HOB object with matching type; Otherwise NULL.
*/
- @return A HOB object with matching type; Otherwise NULL.
const struct hob_header *hob_get_next_hob(uint type, const void *hob_list) { @@ -38,7 +38,7 @@ const struct hob_header *hob_get_next_hob(uint type, const void *hob_list)
- @guid: GUID to search
- @hob_list: A pointer to the HOB list
- @retval: A HOB object with matching GUID; Otherwise NULL.
*/
- @return A HOB object with matching GUID; Otherwise NULL.
const struct hob_header *hob_get_next_guid_hob(const efi_guid_t *guid, const void *hob_list) @@ -65,8 +65,8 @@ const struct hob_header *hob_get_next_guid_hob(const efi_guid_t *guid,
If the GUID HOB is located, the length will be updated.
- @guid A pointer to HOB GUID.
- @retval NULL: Failed to find the GUID HOB.
- @retval others: GUID HOB data buffer pointer.
- @return NULL: Failed to find the GUID HOB.
*/
- @return others: GUID HOB data buffer pointer.
void *hob_get_guid_hob_data(const void *hob_list, u32 *len, const efi_guid_t *guid) --
Other than above,
Reviewed-by: Bin Meng bmeng.cn@gmail.com
Regards, Bin

On Wed, Oct 2, 2019 at 10:06 PM Bin Meng bmeng.cn@gmail.com wrote:
Hi Simon,
On Wed, Sep 25, 2019 at 10:12 PM Simon Glass sjg@chromium.org wrote:
The comments in the FSP code use a different style from the rest of the x86 code. I am not sure it this is intentional.
I guess it's because when it was written I was not familiar with the documenting style :)
Signed-off-by: Simon Glass sjg@chromium.org
Changes in v2: None
arch/x86/include/asm/fsp/fsp_support.h | 42 ++++++++++++------------- arch/x86/include/asm/fsp1/fsp_support.h | 30 ++++++++++++------ arch/x86/include/asm/hob.h | 18 +++++------ arch/x86/lib/hob.c | 8 ++--- 4 files changed, 54 insertions(+), 44 deletions(-)
[snip]
diff --git a/arch/x86/include/asm/hob.h b/arch/x86/include/asm/hob.h index b4239821aaa..72151ea045e 100644 --- a/arch/x86/include/asm/hob.h +++ b/arch/x86/include/asm/hob.h @@ -135,7 +135,7 @@ struct hob_guid {
- @hdr: A pointer to a HOB.
- @return: A pointer to the next HOB in the HOB list.
*/
- @return A pointer to the next HOB in the HOB list.
static inline const struct hob_header *get_next_hob(const struct hob_header *hdr) @@ -152,8 +152,8 @@ static inline const struct hob_header *get_next_hob(const struct hob_header
- @hdr: A pointer to a HOB.
- @retval true: The HOB specified by hdr is the last HOB in the HOB list.
- @retval false: The HOB specified by hdr is not the last HOB in the HOB list.
- @return true: The HOB specified by hdr is the last HOB in the HOB list.
*/
- @return false: The HOB specified by hdr is not the last HOB in the HOB list.
static inline bool end_of_hob(const struct hob_header *hdr) { @@ -169,7 +169,7 @@ static inline bool end_of_hob(const struct hob_header *hdr)
- @hdr: A pointer to a HOB.
- @return: A pointer to the data buffer in a HOB.
*/
- @return A pointer to the data buffer in a HOB.
static inline void *get_guid_hob_data(const struct hob_header *hdr) { @@ -185,7 +185,7 @@ static inline void *get_guid_hob_data(const struct hob_header *hdr)
- @hdr: A pointer to a HOB.
- @return: The size of the data buffer.
*/
- @return The size of the data buffer.
static inline u16 get_guid_hob_data_size(const struct hob_header *hdr) { @@ -198,7 +198,7 @@ static inline u16 get_guid_hob_data_size(const struct hob_header *hdr)
- @type: HOB type to search
- @hob_list: A pointer to the HOB list
- @retval: A HOB object with matching type; Otherwise NULL.
- *@return A HOB object with matching type; Otherwise NULL.
should have a space between * and @
*/ const struct hob_header *hob_get_next_hob(uint type, const void *hob_list);
@@ -208,7 +208,7 @@ const struct hob_header *hob_get_next_hob(uint type, const void *hob_list);
- @guid: GUID to search
- @hob_list: A pointer to the HOB list
- @retval: A HOB object with matching GUID; Otherwise NULL.
- *@return A HOB object with matching GUID; Otherwise NULL.
should have a space between * and @
*/ const struct hob_header *hob_get_next_guid_hob(const efi_guid_t *guid, const void *hob_list); @@ -221,8 +221,8 @@ const struct hob_header *hob_get_next_guid_hob(const efi_guid_t *guid,
If the GUID HOB is located, the length will be updated.
- @guid A pointer to HOB GUID.
- @retval NULL: Failed to find the GUID HOB.
- @retval others: GUID HOB data buffer pointer.
- @return NULL: Failed to find the GUID HOB.
*/
- @return others: GUID HOB data buffer pointer.
void *hob_get_guid_hob_data(const void *hob_list, u32 *len, const efi_guid_t *guid); diff --git a/arch/x86/lib/hob.c b/arch/x86/lib/hob.c index dcee29b04cf..f2c47240ee8 100644 --- a/arch/x86/lib/hob.c +++ b/arch/x86/lib/hob.c @@ -13,7 +13,7 @@
- @type: HOB type to search
- @hob_list: A pointer to the HOB list
- @retval: A HOB object with matching type; Otherwise NULL.
*/
- @return A HOB object with matching type; Otherwise NULL.
const struct hob_header *hob_get_next_hob(uint type, const void *hob_list) { @@ -38,7 +38,7 @@ const struct hob_header *hob_get_next_hob(uint type, const void *hob_list)
- @guid: GUID to search
- @hob_list: A pointer to the HOB list
- @retval: A HOB object with matching GUID; Otherwise NULL.
*/
- @return A HOB object with matching GUID; Otherwise NULL.
const struct hob_header *hob_get_next_guid_hob(const efi_guid_t *guid, const void *hob_list) @@ -65,8 +65,8 @@ const struct hob_header *hob_get_next_guid_hob(const efi_guid_t *guid,
If the GUID HOB is located, the length will be updated.
- @guid A pointer to HOB GUID.
- @retval NULL: Failed to find the GUID HOB.
- @retval others: GUID HOB data buffer pointer.
- @return NULL: Failed to find the GUID HOB.
*/
- @return others: GUID HOB data buffer pointer.
void *hob_get_guid_hob_data(const void *hob_list, u32 *len, const efi_guid_t *guid) --
Other than above,
Fixed the 2 comment style issues above, and resolved the rebase conflicts, and
Reviewed-by: Bin Meng bmeng.cn@gmail.com
applied to u-boot-x86/next, thanks!

Most of the DRAM functionality can be shared between FSP1 and FSP2. Move it into a shared file.
Signed-off-by: Simon Glass sjg@chromium.org ---
Changes in v2: None
arch/x86/include/asm/fsp/fsp_support.h | 9 +++ arch/x86/lib/Makefile | 1 + arch/x86/lib/fsp/Makefile | 5 ++ arch/x86/lib/fsp/fsp_dram.c | 90 ++++++++++++++++++++++++++ arch/x86/lib/fsp1/fsp_dram.c | 80 ++--------------------- 5 files changed, 111 insertions(+), 74 deletions(-) create mode 100644 arch/x86/lib/fsp/Makefile create mode 100644 arch/x86/lib/fsp/fsp_dram.c
diff --git a/arch/x86/include/asm/fsp/fsp_support.h b/arch/x86/include/asm/fsp/fsp_support.h index 8d29f9f5e4b..8f8795415d0 100644 --- a/arch/x86/include/asm/fsp/fsp_support.h +++ b/arch/x86/include/asm/fsp/fsp_support.h @@ -125,4 +125,13 @@ void *fsp_get_graphics_info(const void *hob_list, u32 *len); */ int fsp_init_phase_pci(void);
+/** + * fsp_scan_for_ram_size() - Scan the HOB list to find the RAM size + * + * This sets gd->ram_size based on what it finds. + * + * @return 0 if OK, -ve on error + */ +int fsp_scan_for_ram_size(void); + #endif diff --git a/arch/x86/lib/Makefile b/arch/x86/lib/Makefile index a8c7448ee45..ca0ca1066b0 100644 --- a/arch/x86/lib/Makefile +++ b/arch/x86/lib/Makefile @@ -43,6 +43,7 @@ ifndef CONFIG_SPL_BUILD obj-$(CONFIG_CMD_ZBOOT) += zimage.o endif obj-$(CONFIG_USE_HOB) += hob.o +obj-$(CONFIG_HAVE_FSP) += fsp/ obj-$(CONFIG_FSP_VERSION1) += fsp1/ obj-$(CONFIG_FSP_VERSION2) += fsp2/
diff --git a/arch/x86/lib/fsp/Makefile b/arch/x86/lib/fsp/Makefile new file mode 100644 index 00000000000..e2160653def --- /dev/null +++ b/arch/x86/lib/fsp/Makefile @@ -0,0 +1,5 @@ +# SPDX-License-Identifier: GPL-2.0+ +# +# Copyright 2019 Google LLC + +obj-y += fsp_dram.o diff --git a/arch/x86/lib/fsp/fsp_dram.c b/arch/x86/lib/fsp/fsp_dram.c new file mode 100644 index 00000000000..8fe1e0bf73d --- /dev/null +++ b/arch/x86/lib/fsp/fsp_dram.c @@ -0,0 +1,90 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright (C) 2014, Bin Meng bmeng.cn@gmail.com + */ + +#include <common.h> +#include <handoff.h> +#include <asm/fsp/fsp_support.h> +#include <asm/e820.h> +#include <asm/mrccache.h> +#include <asm/post.h> + +DECLARE_GLOBAL_DATA_PTR; + +int fsp_scan_for_ram_size(void) +{ + phys_size_t ram_size = 0; + const struct hob_header *hdr; + struct hob_res_desc *res_desc; + + hdr = gd->arch.hob_list; + while (!end_of_hob(hdr)) { + if (hdr->type == HOB_TYPE_RES_DESC) { + res_desc = (struct hob_res_desc *)hdr; + if (res_desc->type == RES_SYS_MEM || + res_desc->type == RES_MEM_RESERVED) + ram_size += res_desc->len; + } + hdr = get_next_hob(hdr); + } + + gd->ram_size = ram_size; + post_code(POST_DRAM); + + return 0; +}; + +int dram_init_banksize(void) +{ + gd->bd->bi_dram[0].start = 0; + gd->bd->bi_dram[0].size = gd->ram_size; + + return 0; +} + +unsigned int install_e820_map(unsigned int max_entries, + struct e820_entry *entries) +{ + unsigned int num_entries = 0; + const struct hob_header *hdr; + struct hob_res_desc *res_desc; + + hdr = gd->arch.hob_list; + + while (!end_of_hob(hdr)) { + if (hdr->type == HOB_TYPE_RES_DESC) { + res_desc = (struct hob_res_desc *)hdr; + entries[num_entries].addr = res_desc->phys_start; + entries[num_entries].size = res_desc->len; + + if (res_desc->type == RES_SYS_MEM) + entries[num_entries].type = E820_RAM; + else if (res_desc->type == RES_MEM_RESERVED) + entries[num_entries].type = E820_RESERVED; + + num_entries++; + } + hdr = get_next_hob(hdr); + } + + /* Mark PCIe ECAM address range as reserved */ + entries[num_entries].addr = CONFIG_PCIE_ECAM_BASE; + entries[num_entries].size = CONFIG_PCIE_ECAM_SIZE; + entries[num_entries].type = E820_RESERVED; + num_entries++; + +#ifdef CONFIG_HAVE_ACPI_RESUME + /* + * Everything between U-Boot's stack and ram top needs to be + * reserved in order for ACPI S3 resume to work. + */ + entries[num_entries].addr = gd->start_addr_sp - CONFIG_STACK_SIZE; + entries[num_entries].size = gd->ram_top - gd->start_addr_sp + + CONFIG_STACK_SIZE; + entries[num_entries].type = E820_RESERVED; + num_entries++; +#endif + + return num_entries; +} diff --git a/arch/x86/lib/fsp1/fsp_dram.c b/arch/x86/lib/fsp1/fsp_dram.c index 961e963362a..6a3349b42af 100644 --- a/arch/x86/lib/fsp1/fsp_dram.c +++ b/arch/x86/lib/fsp1/fsp_dram.c @@ -4,30 +4,16 @@ */
#include <common.h> -#include <asm/fsp1/fsp_support.h> -#include <asm/e820.h> -#include <asm/mrccache.h> -#include <asm/post.h> - -DECLARE_GLOBAL_DATA_PTR; +#include <asm/fsp/fsp_support.h>
int dram_init(void) { - phys_size_t ram_size = 0; - const struct hob_header *hdr; - struct hob_res_desc *res_desc; + int ret;
- hdr = gd->arch.hob_list; - while (!end_of_hob(hdr)) { - if (hdr->type == HOB_TYPE_RES_DESC) { - res_desc = (struct hob_res_desc *)hdr; - if (res_desc->type == RES_SYS_MEM || - res_desc->type == RES_MEM_RESERVED) { - ram_size += res_desc->len; - } - } - hdr = get_next_hob(hdr); - } + /* The FSP has already set up DRAM, so grab the info we need */ + ret = fsp_scan_for_ram_size(); + if (ret) + return ret;
if (IS_ENABLED(CONFIG_ENABLE_MRC_CACHE)) gd->arch.mrc_output = fsp_get_nvs_data(gd->arch.hob_list, @@ -36,14 +22,6 @@ int dram_init(void) return 0; }
-int dram_init_banksize(void) -{ - gd->bd->bi_dram[0].start = 0; - gd->bd->bi_dram[0].size = gd->ram_size; - - return 0; -} - /* * This function looks for the highest region of memory lower than 4GB which * has enough space for U-Boot where U-Boot is aligned on a page boundary. @@ -56,49 +34,3 @@ ulong board_get_usable_ram_top(ulong total_size) { return fsp_get_usable_lowmem_top(gd->arch.hob_list); } - -unsigned int install_e820_map(unsigned int max_entries, - struct e820_entry *entries) -{ - unsigned int num_entries = 0; - const struct hob_header *hdr; - struct hob_res_desc *res_desc; - - hdr = gd->arch.hob_list; - - while (!end_of_hob(hdr)) { - if (hdr->type == HOB_TYPE_RES_DESC) { - res_desc = (struct hob_res_desc *)hdr; - entries[num_entries].addr = res_desc->phys_start; - entries[num_entries].size = res_desc->len; - - if (res_desc->type == RES_SYS_MEM) - entries[num_entries].type = E820_RAM; - else if (res_desc->type == RES_MEM_RESERVED) - entries[num_entries].type = E820_RESERVED; - - num_entries++; - } - hdr = get_next_hob(hdr); - } - - /* Mark PCIe ECAM address range as reserved */ - entries[num_entries].addr = CONFIG_PCIE_ECAM_BASE; - entries[num_entries].size = CONFIG_PCIE_ECAM_SIZE; - entries[num_entries].type = E820_RESERVED; - num_entries++; - -#ifdef CONFIG_HAVE_ACPI_RESUME - /* - * Everything between U-Boot's stack and ram top needs to be - * reserved in order for ACPI S3 resume to work. - */ - entries[num_entries].addr = gd->start_addr_sp - CONFIG_STACK_SIZE; - entries[num_entries].size = gd->ram_top - gd->start_addr_sp + \ - CONFIG_STACK_SIZE; - entries[num_entries].type = E820_RESERVED; - num_entries++; -#endif - - return num_entries; -}

On Wed, Sep 25, 2019 at 10:13 PM Simon Glass sjg@chromium.org wrote:
Most of the DRAM functionality can be shared between FSP1 and FSP2. Move it into a shared file.
Signed-off-by: Simon Glass sjg@chromium.org
Changes in v2: None
arch/x86/include/asm/fsp/fsp_support.h | 9 +++ arch/x86/lib/Makefile | 1 + arch/x86/lib/fsp/Makefile | 5 ++ arch/x86/lib/fsp/fsp_dram.c | 90 ++++++++++++++++++++++++++ arch/x86/lib/fsp1/fsp_dram.c | 80 ++--------------------- 5 files changed, 111 insertions(+), 74 deletions(-) create mode 100644 arch/x86/lib/fsp/Makefile create mode 100644 arch/x86/lib/fsp/fsp_dram.c
Reviewed-by: Bin Meng bmeng.cn@gmail.com

On Wed, Oct 2, 2019 at 10:06 PM Bin Meng bmeng.cn@gmail.com wrote:
On Wed, Sep 25, 2019 at 10:13 PM Simon Glass sjg@chromium.org wrote:
Most of the DRAM functionality can be shared between FSP1 and FSP2. Move it into a shared file.
Signed-off-by: Simon Glass sjg@chromium.org
Changes in v2: None
arch/x86/include/asm/fsp/fsp_support.h | 9 +++ arch/x86/lib/Makefile | 1 + arch/x86/lib/fsp/Makefile | 5 ++ arch/x86/lib/fsp/fsp_dram.c | 90 ++++++++++++++++++++++++++ arch/x86/lib/fsp1/fsp_dram.c | 80 ++--------------------- 5 files changed, 111 insertions(+), 74 deletions(-) create mode 100644 arch/x86/lib/fsp/Makefile create mode 100644 arch/x86/lib/fsp/fsp_dram.c
Reviewed-by: Bin Meng bmeng.cn@gmail.com
Rebase the patch against u-boot-x86/next to get it applied cleanly, and
applied to u-boot-x86/next, thanks!

Some of this file can be shared between FSP1 and FSP2. Move it into a shared file.
Signed-off-by: Simon Glass sjg@chromium.org ---
Changes in v2: None
arch/x86/include/asm/fsp/fsp_support.h | 17 ++++ arch/x86/include/asm/fsp1/fsp_support.h | 10 --- arch/x86/lib/fsp/Makefile | 1 + arch/x86/lib/fsp/fsp_common.c | 104 ++++++++++++++++++++++++ arch/x86/lib/fsp1/fsp_common.c | 87 -------------------- 5 files changed, 122 insertions(+), 97 deletions(-) create mode 100644 arch/x86/lib/fsp/fsp_common.c
diff --git a/arch/x86/include/asm/fsp/fsp_support.h b/arch/x86/include/asm/fsp/fsp_support.h index 8f8795415d0..6320fe0906c 100644 --- a/arch/x86/include/asm/fsp/fsp_support.h +++ b/arch/x86/include/asm/fsp/fsp_support.h @@ -134,4 +134,21 @@ int fsp_init_phase_pci(void); */ int fsp_scan_for_ram_size(void);
+/** + * fsp_prepare_mrc_cache() - Find the DRAM training data from the MRC cache + * + * @return pointer to data, or NULL if no cache or no data found in the cache + */ +void *fsp_prepare_mrc_cache(void); + +/** + * fsp_notify() - FSP notification wrapper function + * + * @fsp_hdr: Pointer to FSP information header + * @phase: FSP initialization phase defined in enum fsp_phase + * + * @return compatible status code with EFI_STATUS defined in PI spec + */ +u32 fsp_notify(struct fsp_header *fsp_hdr, u32 phase); + #endif diff --git a/arch/x86/include/asm/fsp1/fsp_support.h b/arch/x86/include/asm/fsp1/fsp_support.h index 236c167fc86..a44a5504a4f 100644 --- a/arch/x86/include/asm/fsp1/fsp_support.h +++ b/arch/x86/include/asm/fsp1/fsp_support.h @@ -46,16 +46,6 @@ void fsp_continue(u32 status, void *hob_list); */ void fsp_init(u32 stack_top, u32 boot_mode, void *nvs_buf);
-/** - * fsp_notify() - FSP notification wrapper function - * - * @fsp_hdr: Pointer to FSP information header - * @phase: FSP initialization phase defined in enum fsp_phase - * - * @return compatible status code with EFI_STATUS defined in PI spec - */ -u32 fsp_notify(struct fsp_header *fsp_hdr, u32 phase); - /** * fsp_get_bootloader_tmp_mem() - retrieves temporary stack buffer and size * diff --git a/arch/x86/lib/fsp/Makefile b/arch/x86/lib/fsp/Makefile index e2160653def..e7a8427c2ec 100644 --- a/arch/x86/lib/fsp/Makefile +++ b/arch/x86/lib/fsp/Makefile @@ -2,4 +2,5 @@ # # Copyright 2019 Google LLC
+obj-y += fsp_common.o obj-y += fsp_dram.o diff --git a/arch/x86/lib/fsp/fsp_common.c b/arch/x86/lib/fsp/fsp_common.c new file mode 100644 index 00000000000..6678d75ffd5 --- /dev/null +++ b/arch/x86/lib/fsp/fsp_common.c @@ -0,0 +1,104 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright (C) 2014, Bin Meng bmeng.cn@gmail.com + */ + +#include <common.h> +#include <dm.h> +#include <errno.h> +#include <rtc.h> +#include <asm/acpi_s3.h> +#include <asm/cmos_layout.h> +#include <asm/early_cmos.h> +#include <asm/io.h> +#include <asm/mrccache.h> +#include <asm/post.h> +#include <asm/processor.h> +#include <asm/fsp/fsp_support.h> + +DECLARE_GLOBAL_DATA_PTR; + +int checkcpu(void) +{ + return 0; +} + +int print_cpuinfo(void) +{ + post_code(POST_CPU_INFO); + return default_print_cpuinfo(); +} + +int fsp_init_phase_pci(void) +{ + u32 status; + + /* call into FspNotify */ + debug("Calling into FSP (notify phase INIT_PHASE_PCI): "); + status = fsp_notify(NULL, INIT_PHASE_PCI); + if (status) + debug("fail, error code %x\n", status); + else + debug("OK\n"); + + return status ? -EPERM : 0; +} + +void board_final_cleanup(void) +{ + u32 status; + + /* call into FspNotify */ + debug("Calling into FSP (notify phase INIT_PHASE_BOOT): "); + status = fsp_notify(NULL, INIT_PHASE_BOOT); + if (status) + debug("fail, error code %x\n", status); + else + debug("OK\n"); +} + +void *fsp_prepare_mrc_cache(void) +{ + struct mrc_data_container *cache; + struct mrc_region entry; + int ret; + + ret = mrccache_get_region(NULL, &entry); + if (ret) + return NULL; + + cache = mrccache_find_current(&entry); + if (!cache) + return NULL; + + debug("%s: mrc cache at %p, size %x checksum %04x\n", __func__, + cache->data, cache->data_size, cache->checksum); + + return cache->data; +} + +#ifdef CONFIG_HAVE_ACPI_RESUME +int fsp_save_s3_stack(void) +{ + struct udevice *dev; + int ret; + + if (gd->arch.prev_sleep_state == ACPI_S3) + return 0; + + ret = uclass_get_device(UCLASS_RTC, 0, &dev); + if (ret) { + debug("Cannot find RTC: err=%d\n", ret); + return -ENODEV; + } + + /* Save the stack address to CMOS */ + ret = rtc_write32(dev, CMOS_FSP_STACK_ADDR, gd->start_addr_sp); + if (ret) { + debug("Save stack address to CMOS: err=%d\n", ret); + return -EIO; + } + + return 0; +} +#endif diff --git a/arch/x86/lib/fsp1/fsp_common.c b/arch/x86/lib/fsp1/fsp_common.c index bfd76dccbab..285ef72ebf8 100644 --- a/arch/x86/lib/fsp1/fsp_common.c +++ b/arch/x86/lib/fsp1/fsp_common.c @@ -18,93 +18,6 @@
DECLARE_GLOBAL_DATA_PTR;
-int checkcpu(void) -{ - return 0; -} - -int print_cpuinfo(void) -{ - post_code(POST_CPU_INFO); - return default_print_cpuinfo(); -} - -int fsp_init_phase_pci(void) -{ - u32 status; - - /* call into FspNotify */ - debug("Calling into FSP (notify phase INIT_PHASE_PCI): "); - status = fsp_notify(NULL, INIT_PHASE_PCI); - if (status) - debug("fail, error code %x\n", status); - else - debug("OK\n"); - - return status ? -EPERM : 0; -} - -void board_final_cleanup(void) -{ - u32 status; - - /* call into FspNotify */ - debug("Calling into FSP (notify phase INIT_PHASE_BOOT): "); - status = fsp_notify(NULL, INIT_PHASE_BOOT); - if (status) - debug("fail, error code %x\n", status); - else - debug("OK\n"); - - return; -} - -static __maybe_unused void *fsp_prepare_mrc_cache(void) -{ - struct mrc_data_container *cache; - struct mrc_region entry; - int ret; - - ret = mrccache_get_region(NULL, &entry); - if (ret) - return NULL; - - cache = mrccache_find_current(&entry); - if (!cache) - return NULL; - - debug("%s: mrc cache at %p, size %x checksum %04x\n", __func__, - cache->data, cache->data_size, cache->checksum); - - return cache->data; -} - -#ifdef CONFIG_HAVE_ACPI_RESUME -int fsp_save_s3_stack(void) -{ - struct udevice *dev; - int ret; - - if (gd->arch.prev_sleep_state == ACPI_S3) - return 0; - - ret = uclass_get_device(UCLASS_RTC, 0, &dev); - if (ret) { - debug("Cannot find RTC: err=%d\n", ret); - return -ENODEV; - } - - /* Save the stack address to CMOS */ - ret = rtc_write32(dev, CMOS_FSP_STACK_ADDR, gd->start_addr_sp); - if (ret) { - debug("Save stack address to CMOS: err=%d\n", ret); - return -EIO; - } - - return 0; -} -#endif - int arch_fsp_init(void) { void *nvs;

On Wed, Sep 25, 2019 at 10:12 PM Simon Glass sjg@chromium.org wrote:
Some of this file can be shared between FSP1 and FSP2. Move it into a shared file.
Signed-off-by: Simon Glass sjg@chromium.org
Changes in v2: None
arch/x86/include/asm/fsp/fsp_support.h | 17 ++++ arch/x86/include/asm/fsp1/fsp_support.h | 10 --- arch/x86/lib/fsp/Makefile | 1 + arch/x86/lib/fsp/fsp_common.c | 104 ++++++++++++++++++++++++ arch/x86/lib/fsp1/fsp_common.c | 87 -------------------- 5 files changed, 122 insertions(+), 97 deletions(-) create mode 100644 arch/x86/lib/fsp/fsp_common.c
Reviewed-by: Bin Meng bmeng.cn@gmail.com

On Wed, Oct 2, 2019 at 10:06 PM Bin Meng bmeng.cn@gmail.com wrote:
On Wed, Sep 25, 2019 at 10:12 PM Simon Glass sjg@chromium.org wrote:
Some of this file can be shared between FSP1 and FSP2. Move it into a shared file.
Signed-off-by: Simon Glass sjg@chromium.org
Changes in v2: None
arch/x86/include/asm/fsp/fsp_support.h | 17 ++++ arch/x86/include/asm/fsp1/fsp_support.h | 10 --- arch/x86/lib/fsp/Makefile | 1 + arch/x86/lib/fsp/fsp_common.c | 104 ++++++++++++++++++++++++ arch/x86/lib/fsp1/fsp_common.c | 87 -------------------- 5 files changed, 122 insertions(+), 97 deletions(-) create mode 100644 arch/x86/lib/fsp/fsp_common.c
Reviewed-by: Bin Meng bmeng.cn@gmail.com
applied to u-boot-x86/next, thanks!

Some of this file can be shared between FSP1 and FSP2. Move it into a shared file.
Signed-off-by: Simon Glass sjg@chromium.org ---
Changes in v2: None
arch/x86/lib/fsp/Makefile | 1 + arch/x86/lib/fsp/fsp_support.c | 176 ++++++++++++++++++++++++++++++++ arch/x86/lib/fsp1/fsp_support.c | 167 ------------------------------ 3 files changed, 177 insertions(+), 167 deletions(-) create mode 100644 arch/x86/lib/fsp/fsp_support.c
diff --git a/arch/x86/lib/fsp/Makefile b/arch/x86/lib/fsp/Makefile index e7a8427c2ec..9e348564737 100644 --- a/arch/x86/lib/fsp/Makefile +++ b/arch/x86/lib/fsp/Makefile @@ -4,3 +4,4 @@
obj-y += fsp_common.o obj-y += fsp_dram.o +obj-y += fsp_support.o diff --git a/arch/x86/lib/fsp/fsp_support.c b/arch/x86/lib/fsp/fsp_support.c new file mode 100644 index 00000000000..014de35e563 --- /dev/null +++ b/arch/x86/lib/fsp/fsp_support.c @@ -0,0 +1,176 @@ +// SPDX-License-Identifier: Intel +/* + * Copyright (C) 2013, Intel Corporation + * Copyright (C) 2014, Bin Meng bmeng.cn@gmail.com + */ + +#include <common.h> +#include <asm/fsp1/fsp_support.h> +#include <asm/post.h> + +u32 fsp_get_usable_lowmem_top(const void *hob_list) +{ + const struct hob_header *hdr; + struct hob_res_desc *res_desc; + phys_addr_t phys_start; + u32 top; +#ifdef CONFIG_FSP_BROKEN_HOB + struct hob_mem_alloc *res_mem; + phys_addr_t mem_base = 0; +#endif + + /* Get the HOB list for processing */ + hdr = hob_list; + + /* * Collect memory ranges */ + top = FSP_LOWMEM_BASE; + while (!end_of_hob(hdr)) { + if (hdr->type == HOB_TYPE_RES_DESC) { + res_desc = (struct hob_res_desc *)hdr; + if (res_desc->type == RES_SYS_MEM) { + phys_start = res_desc->phys_start; + /* Need memory above 1MB to be collected here */ + if (phys_start >= FSP_LOWMEM_BASE && + phys_start < (phys_addr_t)FSP_HIGHMEM_BASE) + top += (u32)(res_desc->len); + } + } + +#ifdef CONFIG_FSP_BROKEN_HOB + /* + * Find out the lowest memory base address allocated by FSP + * for the boot service data + */ + if (hdr->type == HOB_TYPE_MEM_ALLOC) { + res_mem = (struct hob_mem_alloc *)hdr; + if (!mem_base) + mem_base = res_mem->mem_base; + if (res_mem->mem_base < mem_base) + mem_base = res_mem->mem_base; + } +#endif + + hdr = get_next_hob(hdr); + } + +#ifdef CONFIG_FSP_BROKEN_HOB + /* + * Check whether the memory top address is below the FSP HOB list. + * If not, use the lowest memory base address allocated by FSP as + * the memory top address. This is to prevent U-Boot relocation + * overwrites the important boot service data which is used by FSP, + * otherwise the subsequent call to fsp_notify() will fail. + */ + if (top > (u32)hob_list) { + debug("Adjust memory top address due to a buggy FSP\n"); + top = (u32)mem_base; + } +#endif + + return top; +} + +u64 fsp_get_usable_highmem_top(const void *hob_list) +{ + const struct hob_header *hdr; + struct hob_res_desc *res_desc; + phys_addr_t phys_start; + u64 top; + + /* Get the HOB list for processing */ + hdr = hob_list; + + /* Collect memory ranges */ + top = FSP_HIGHMEM_BASE; + while (!end_of_hob(hdr)) { + if (hdr->type == HOB_TYPE_RES_DESC) { + res_desc = (struct hob_res_desc *)hdr; + if (res_desc->type == RES_SYS_MEM) { + phys_start = res_desc->phys_start; + /* Need memory above 4GB to be collected here */ + if (phys_start >= (phys_addr_t)FSP_HIGHMEM_BASE) + top += (u32)(res_desc->len); + } + } + hdr = get_next_hob(hdr); + } + + return top; +} + +u64 fsp_get_reserved_mem_from_guid(const void *hob_list, u64 *len, + const efi_guid_t *guid) +{ + const struct hob_header *hdr; + struct hob_res_desc *res_desc; + + /* Get the HOB list for processing */ + hdr = hob_list; + + /* Collect memory ranges */ + while (!end_of_hob(hdr)) { + if (hdr->type == HOB_TYPE_RES_DESC) { + res_desc = (struct hob_res_desc *)hdr; + if (res_desc->type == RES_MEM_RESERVED) { + if (!guidcmp(&res_desc->owner, guid)) { + if (len) + *len = (u32)(res_desc->len); + + return (u64)(res_desc->phys_start); + } + } + } + hdr = get_next_hob(hdr); + } + + return 0; +} + +u32 fsp_get_fsp_reserved_mem(const void *hob_list, u32 *len) +{ + const efi_guid_t guid = FSP_HOB_RESOURCE_OWNER_FSP_GUID; + u64 length; + u32 base; + + base = (u32)fsp_get_reserved_mem_from_guid(hob_list, + &length, &guid); + if (len && base) + *len = (u32)length; + + return base; +} + +u32 fsp_get_tseg_reserved_mem(const void *hob_list, u32 *len) +{ + const efi_guid_t guid = FSP_HOB_RESOURCE_OWNER_TSEG_GUID; + u64 length; + u32 base; + + base = (u32)fsp_get_reserved_mem_from_guid(hob_list, + &length, &guid); + if (len && base) + *len = (u32)length; + + return base; +} + +void *fsp_get_nvs_data(const void *hob_list, u32 *len) +{ + const efi_guid_t guid = FSP_NON_VOLATILE_STORAGE_HOB_GUID; + + return hob_get_guid_hob_data(hob_list, len, &guid); +} + +void *fsp_get_bootloader_tmp_mem(const void *hob_list, u32 *len) +{ + const efi_guid_t guid = FSP_BOOTLOADER_TEMP_MEM_HOB_GUID; + + return hob_get_guid_hob_data(hob_list, len, &guid); +} + +void *fsp_get_graphics_info(const void *hob_list, u32 *len) +{ + const efi_guid_t guid = FSP_GRAPHICS_INFO_HOB_GUID; + + return hob_get_guid_hob_data(hob_list, len, &guid); +} diff --git a/arch/x86/lib/fsp1/fsp_support.c b/arch/x86/lib/fsp1/fsp_support.c index b5b7d664a1e..c7a2c73846b 100644 --- a/arch/x86/lib/fsp1/fsp_support.c +++ b/arch/x86/lib/fsp1/fsp_support.c @@ -197,170 +197,3 @@ u32 fsp_notify(struct fsp_header *fsp_hdr, u32 phase)
return status; } - -u32 fsp_get_usable_lowmem_top(const void *hob_list) -{ - const struct hob_header *hdr; - struct hob_res_desc *res_desc; - phys_addr_t phys_start; - u32 top; -#ifdef CONFIG_FSP_BROKEN_HOB - struct hob_mem_alloc *res_mem; - phys_addr_t mem_base = 0; -#endif - - /* Get the HOB list for processing */ - hdr = hob_list; - - /* * Collect memory ranges */ - top = FSP_LOWMEM_BASE; - while (!end_of_hob(hdr)) { - if (hdr->type == HOB_TYPE_RES_DESC) { - res_desc = (struct hob_res_desc *)hdr; - if (res_desc->type == RES_SYS_MEM) { - phys_start = res_desc->phys_start; - /* Need memory above 1MB to be collected here */ - if (phys_start >= FSP_LOWMEM_BASE && - phys_start < (phys_addr_t)FSP_HIGHMEM_BASE) - top += (u32)(res_desc->len); - } - } - -#ifdef CONFIG_FSP_BROKEN_HOB - /* - * Find out the lowest memory base address allocated by FSP - * for the boot service data - */ - if (hdr->type == HOB_TYPE_MEM_ALLOC) { - res_mem = (struct hob_mem_alloc *)hdr; - if (!mem_base) - mem_base = res_mem->mem_base; - if (res_mem->mem_base < mem_base) - mem_base = res_mem->mem_base; - } -#endif - - hdr = get_next_hob(hdr); - } - -#ifdef CONFIG_FSP_BROKEN_HOB - /* - * Check whether the memory top address is below the FSP HOB list. - * If not, use the lowest memory base address allocated by FSP as - * the memory top address. This is to prevent U-Boot relocation - * overwrites the important boot service data which is used by FSP, - * otherwise the subsequent call to fsp_notify() will fail. - */ - if (top > (u32)hob_list) { - debug("Adjust memory top address due to a buggy FSP\n"); - top = (u32)mem_base; - } -#endif - - return top; -} - -u64 fsp_get_usable_highmem_top(const void *hob_list) -{ - const struct hob_header *hdr; - struct hob_res_desc *res_desc; - phys_addr_t phys_start; - u64 top; - - /* Get the HOB list for processing */ - hdr = hob_list; - - /* Collect memory ranges */ - top = FSP_HIGHMEM_BASE; - while (!end_of_hob(hdr)) { - if (hdr->type == HOB_TYPE_RES_DESC) { - res_desc = (struct hob_res_desc *)hdr; - if (res_desc->type == RES_SYS_MEM) { - phys_start = res_desc->phys_start; - /* Need memory above 4GB to be collected here */ - if (phys_start >= (phys_addr_t)FSP_HIGHMEM_BASE) - top += (u32)(res_desc->len); - } - } - hdr = get_next_hob(hdr); - } - - return top; -} - -u64 fsp_get_reserved_mem_from_guid(const void *hob_list, u64 *len, - const efi_guid_t *guid) -{ - const struct hob_header *hdr; - struct hob_res_desc *res_desc; - - /* Get the HOB list for processing */ - hdr = hob_list; - - /* Collect memory ranges */ - while (!end_of_hob(hdr)) { - if (hdr->type == HOB_TYPE_RES_DESC) { - res_desc = (struct hob_res_desc *)hdr; - if (res_desc->type == RES_MEM_RESERVED) { - if (!guidcmp(&res_desc->owner, guid)) { - if (len) - *len = (u32)(res_desc->len); - - return (u64)(res_desc->phys_start); - } - } - } - hdr = get_next_hob(hdr); - } - - return 0; -} - -u32 fsp_get_fsp_reserved_mem(const void *hob_list, u32 *len) -{ - const efi_guid_t guid = FSP_HOB_RESOURCE_OWNER_FSP_GUID; - u64 length; - u32 base; - - base = (u32)fsp_get_reserved_mem_from_guid(hob_list, - &length, &guid); - if ((len != 0) && (base != 0)) - *len = (u32)length; - - return base; -} - -u32 fsp_get_tseg_reserved_mem(const void *hob_list, u32 *len) -{ - const efi_guid_t guid = FSP_HOB_RESOURCE_OWNER_TSEG_GUID; - u64 length; - u32 base; - - base = (u32)fsp_get_reserved_mem_from_guid(hob_list, - &length, &guid); - if ((len != 0) && (base != 0)) - *len = (u32)length; - - return base; -} - -void *fsp_get_nvs_data(const void *hob_list, u32 *len) -{ - const efi_guid_t guid = FSP_NON_VOLATILE_STORAGE_HOB_GUID; - - return hob_get_guid_hob_data(hob_list, len, &guid); -} - -void *fsp_get_bootloader_tmp_mem(const void *hob_list, u32 *len) -{ - const efi_guid_t guid = FSP_BOOTLOADER_TEMP_MEM_HOB_GUID; - - return hob_get_guid_hob_data(hob_list, len, &guid); -} - -void *fsp_get_graphics_info(const void *hob_list, u32 *len) -{ - const efi_guid_t guid = FSP_GRAPHICS_INFO_HOB_GUID; - - return hob_get_guid_hob_data(hob_list, len, &guid); -}

On Wed, Sep 25, 2019 at 10:12 PM Simon Glass sjg@chromium.org wrote:
Some of this file can be shared between FSP1 and FSP2. Move it into a shared file.
Signed-off-by: Simon Glass sjg@chromium.org
Changes in v2: None
arch/x86/lib/fsp/Makefile | 1 + arch/x86/lib/fsp/fsp_support.c | 176 ++++++++++++++++++++++++++++++++ arch/x86/lib/fsp1/fsp_support.c | 167 ------------------------------ 3 files changed, 177 insertions(+), 167 deletions(-) create mode 100644 arch/x86/lib/fsp/fsp_support.c
Reviewed-by: Bin Meng bmeng.cn@gmail.com

On Wed, Oct 2, 2019 at 10:06 PM Bin Meng bmeng.cn@gmail.com wrote:
On Wed, Sep 25, 2019 at 10:12 PM Simon Glass sjg@chromium.org wrote:
Some of this file can be shared between FSP1 and FSP2. Move it into a shared file.
Signed-off-by: Simon Glass sjg@chromium.org
Changes in v2: None
arch/x86/lib/fsp/Makefile | 1 + arch/x86/lib/fsp/fsp_support.c | 176 ++++++++++++++++++++++++++++++++ arch/x86/lib/fsp1/fsp_support.c | 167 ------------------------------ 3 files changed, 177 insertions(+), 167 deletions(-) create mode 100644 arch/x86/lib/fsp/fsp_support.c
Reviewed-by: Bin Meng bmeng.cn@gmail.com
applied to u-boot-x86/next, thanks!

At present these two functions are defined in efi_loader.h but only if CONFIG_EFI_LOADER is enabled. But these are functions that are useful to other code, such as that which deals with Intel Handoff Blocks (HOBs).
Move these to the top of the function.
Possibly ascii2unicode() should not be an inline function, since this might impact code size.
Signed-off-by: Simon Glass sjg@chromium.org --- In general it seems to be bad form to include parts of headers conditionally.
Changes in v2: None
include/efi_loader.h | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-)
diff --git a/include/efi_loader.h b/include/efi_loader.h index 53b369945b4..381da80cdce 100644 --- a/include/efi_loader.h +++ b/include/efi_loader.h @@ -12,6 +12,11 @@ #include <part_efi.h> #include <efi_api.h>
+static inline int guidcmp(const void *g1, const void *g2) +{ + return memcmp(g1, g2, sizeof(efi_guid_t)); +} + /* No need for efi loader support in SPL */ #if CONFIG_IS_ENABLED(EFI_LOADER)
@@ -563,11 +568,6 @@ efi_status_t efi_dp_from_name(const char *dev, const char *devnr, (((_dp)->type == DEVICE_PATH_TYPE_##_type) && \ ((_dp)->sub_type == DEVICE_PATH_SUB_TYPE_##_subtype))
-static inline int guidcmp(const void *g1, const void *g2) -{ - return memcmp(g1, g2, sizeof(efi_guid_t)); -} - /* * Use these to indicate that your code / data should go into the EFI runtime * section and thus still be available when the OS is running

On Wed, Sep 25, 2019 at 10:13 PM Simon Glass sjg@chromium.org wrote:
At present these two functions are defined in efi_loader.h but only if CONFIG_EFI_LOADER is enabled. But these are functions that are useful to other code, such as that which deals with Intel Handoff Blocks (HOBs).
Move these to the top of the function.
Possibly ascii2unicode() should not be an inline function, since this might impact code size.
Signed-off-by: Simon Glass sjg@chromium.org
In general it seems to be bad form to include parts of headers conditionally.
Changes in v2: None
include/efi_loader.h | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-)
Reviewed-by: Bin Meng bmeng.cn@gmail.com

On Wed, Oct 2, 2019 at 10:07 PM Bin Meng bmeng.cn@gmail.com wrote:
On Wed, Sep 25, 2019 at 10:13 PM Simon Glass sjg@chromium.org wrote:
At present these two functions are defined in efi_loader.h but only if CONFIG_EFI_LOADER is enabled. But these are functions that are useful to other code, such as that which deals with Intel Handoff Blocks (HOBs).
Move these to the top of the function.
Possibly ascii2unicode() should not be an inline function, since this might impact code size.
Signed-off-by: Simon Glass sjg@chromium.org
In general it seems to be bad form to include parts of headers conditionally.
Changes in v2: None
include/efi_loader.h | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-)
Reviewed-by: Bin Meng bmeng.cn@gmail.com
applied to u-boot-x86/next, thanks!

Add definitions for the FSP signature and the FSP init phase.
Signed-off-by: Simon Glass sjg@chromium.org ---
Changes in v2: None
arch/x86/include/asm/fsp/fsp_infoheader.h | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-)
diff --git a/arch/x86/include/asm/fsp/fsp_infoheader.h b/arch/x86/include/asm/fsp/fsp_infoheader.h index 86f78014b7b..e72c052ed1e 100644 --- a/arch/x86/include/asm/fsp/fsp_infoheader.h +++ b/arch/x86/include/asm/fsp/fsp_infoheader.h @@ -33,6 +33,19 @@ struct __packed fsp_header { #define FSP_HEADER_REVISION_1 1 #define FSP_HEADER_REVISION_2 2
-#define FSP_ATTR_GRAPHICS_SUPPORT (1 << 0) +enum fsp_type { + FSP_ATTR_COMP_TYPE_FSP_T = 1, + FSP_ATTR_COMP_TYPE_FSP_M = 2, + FSP_ATTR_COMP_TYPE_FSP_S = 3, +}; + +enum { + FSP_ATTR_GRAPHICS_SUPPORT = 1 << 0, + FSP_ATTR_COMP_TYPE_SHIFT = 28, + FSP_ATTR_COMP_TYPE_MASK = 0xfU << FSP_ATTR_COMP_TYPE_SHIFT, + +}; + +#define EFI_FSPH_SIGNATURE SIGNATURE_32('F', 'S', 'P', 'H')
#endif

On Wed, Sep 25, 2019 at 10:13 PM Simon Glass sjg@chromium.org wrote:
Add definitions for the FSP signature and the FSP init phase.
Signed-off-by: Simon Glass sjg@chromium.org
Changes in v2: None
arch/x86/include/asm/fsp/fsp_infoheader.h | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-)
Reviewed-by: Bin Meng bmeng.cn@gmail.com

On Wed, Oct 2, 2019 at 10:07 PM Bin Meng bmeng.cn@gmail.com wrote:
On Wed, Sep 25, 2019 at 10:13 PM Simon Glass sjg@chromium.org wrote:
Add definitions for the FSP signature and the FSP init phase.
Signed-off-by: Simon Glass sjg@chromium.org
Changes in v2: None
arch/x86/include/asm/fsp/fsp_infoheader.h | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-)
Reviewed-by: Bin Meng bmeng.cn@gmail.com
applied to u-boot-x86/next, thanks!

With FSP2 the non-volatile storage used by the FSP to init memory can be split into a fixed piece (determined at compile time) and a variable piece (determined at run time). Add support for reading the latter.
Signed-off-by: Simon Glass sjg@chromium.org ---
Changes in v2: None
arch/x86/include/asm/fsp/fsp_hob.h | 4 ++++ arch/x86/include/asm/fsp/fsp_support.h | 12 ++++++++++++ arch/x86/lib/fsp/fsp_support.c | 7 +++++++ 3 files changed, 23 insertions(+)
diff --git a/arch/x86/include/asm/fsp/fsp_hob.h b/arch/x86/include/asm/fsp/fsp_hob.h index 3bb79c4b67a..d248520e972 100644 --- a/arch/x86/include/asm/fsp/fsp_hob.h +++ b/arch/x86/include/asm/fsp/fsp_hob.h @@ -69,6 +69,10 @@ struct __packed hob_graphics_info { EFI_GUID(0x721acf02, 0x4d77, 0x4c2a, \ 0xb3, 0xdc, 0x27, 0x0b, 0x7b, 0xa9, 0xe4, 0xb0)
+#define FSP_VARIABLE_NV_DATA_HOB_GUID \ + EFI_GUID(0xa034147d, 0x690c, 0x4154, \ + 0x8d, 0xe6, 0xc0, 0x44, 0x64, 0x1d, 0xe9, 0x42) + #define FSP_BOOTLOADER_TEMP_MEM_HOB_GUID \ EFI_GUID(0xbbcff46c, 0xc8d3, 0x4113, \ 0x89, 0x85, 0xb9, 0xd4, 0xf3, 0xb3, 0xf6, 0x4e) diff --git a/arch/x86/include/asm/fsp/fsp_support.h b/arch/x86/include/asm/fsp/fsp_support.h index 6320fe0906c..4f93cb2a136 100644 --- a/arch/x86/include/asm/fsp/fsp_support.h +++ b/arch/x86/include/asm/fsp/fsp_support.h @@ -106,6 +106,18 @@ u32 fsp_get_tseg_reserved_mem(const void *hob_list, u32 *len); */ void *fsp_get_nvs_data(const void *hob_list, u32 *len);
+/** + * fsp_get_var_nvs_data() - get FSP variable Non-volatile Storage HOB buffer + * + * @hob_list: A HOB list pointer. + * @len: A pointer to the NVS data buffer length. + * If the HOB is located, the length will be updated. + * + * @return NULL: Failed to find the NVS HOB. + * @return others: FSP NVS data buffer pointer. + */ +void *fsp_get_var_nvs_data(const void *hob_list, u32 *len); + /** * fsp_get_graphics_info() - retrieves graphics information. * diff --git a/arch/x86/lib/fsp/fsp_support.c b/arch/x86/lib/fsp/fsp_support.c index 014de35e563..983888fd743 100644 --- a/arch/x86/lib/fsp/fsp_support.c +++ b/arch/x86/lib/fsp/fsp_support.c @@ -161,6 +161,13 @@ void *fsp_get_nvs_data(const void *hob_list, u32 *len) return hob_get_guid_hob_data(hob_list, len, &guid); }
+void *fsp_get_var_nvs_data(const void *hob_list, u32 *len) +{ + const efi_guid_t guid = FSP_VARIABLE_NV_DATA_HOB_GUID; + + return hob_get_guid_hob_data(hob_list, len, &guid); +} + void *fsp_get_bootloader_tmp_mem(const void *hob_list, u32 *len) { const efi_guid_t guid = FSP_BOOTLOADER_TEMP_MEM_HOB_GUID;

On Wed, Sep 25, 2019 at 10:13 PM Simon Glass sjg@chromium.org wrote:
With FSP2 the non-volatile storage used by the FSP to init memory can be split into a fixed piece (determined at compile time) and a variable piece (determined at run time). Add support for reading the latter.
Signed-off-by: Simon Glass sjg@chromium.org
Changes in v2: None
arch/x86/include/asm/fsp/fsp_hob.h | 4 ++++ arch/x86/include/asm/fsp/fsp_support.h | 12 ++++++++++++ arch/x86/lib/fsp/fsp_support.c | 7 +++++++ 3 files changed, 23 insertions(+)
Reviewed-by: Bin Meng bmeng.cn@gmail.com

On Wed, Oct 2, 2019 at 10:07 PM Bin Meng bmeng.cn@gmail.com wrote:
On Wed, Sep 25, 2019 at 10:13 PM Simon Glass sjg@chromium.org wrote:
With FSP2 the non-volatile storage used by the FSP to init memory can be split into a fixed piece (determined at compile time) and a variable piece (determined at run time). Add support for reading the latter.
Signed-off-by: Simon Glass sjg@chromium.org
Changes in v2: None
arch/x86/include/asm/fsp/fsp_hob.h | 4 ++++ arch/x86/include/asm/fsp/fsp_support.h | 12 ++++++++++++ arch/x86/lib/fsp/fsp_support.c | 7 +++++++ 3 files changed, 23 insertions(+)
Reviewed-by: Bin Meng bmeng.cn@gmail.com
applied to u-boot-x86/next, thanks!

Add cpu_intel_get_info() to find out the CPU info on modern Intel CPUs.
Signed-off-by: Simon Glass sjg@chromium.org ---
Changes in v2: None
arch/x86/cpu/broadwell/cpu_full.c | 9 +-------- arch/x86/cpu/intel_common/cpu.c | 13 +++++++++++++ arch/x86/cpu/ivybridge/model_206ax.c | 8 ++------ arch/x86/include/asm/cpu_common.h | 11 +++++++++++ 4 files changed, 27 insertions(+), 14 deletions(-)
diff --git a/arch/x86/cpu/broadwell/cpu_full.c b/arch/x86/cpu/broadwell/cpu_full.c index c1db1845498..d8b84826586 100644 --- a/arch/x86/cpu/broadwell/cpu_full.c +++ b/arch/x86/cpu/broadwell/cpu_full.c @@ -645,14 +645,7 @@ void cpu_set_power_limits(int power_limit_1_time)
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; + return cpu_intel_get_info(info, BROADWELL_BCLK); }
static int broadwell_get_count(struct udevice *dev) diff --git a/arch/x86/cpu/intel_common/cpu.c b/arch/x86/cpu/intel_common/cpu.c index d0ac17808c3..9357626b5a6 100644 --- a/arch/x86/cpu/intel_common/cpu.c +++ b/arch/x86/cpu/intel_common/cpu.c @@ -4,6 +4,7 @@ */
#include <common.h> +#include <cpu.h> #include <dm.h> #include <errno.h> #include <asm/cpu_common.h> @@ -110,3 +111,15 @@ int cpu_set_flex_ratio_to_tdp_nominal(void) /* Not reached */ return -EINVAL; } + +int cpu_intel_get_info(struct cpu_info *info, int bclk) +{ + msr_t msr; + + msr = msr_read(IA32_PERF_CTL); + info->cpu_freq = ((msr.lo >> 8) & 0xff) * bclk * 1000000; + info->features = 1 << CPU_FEAT_L1_CACHE | 1 << CPU_FEAT_MMU | + 1 << CPU_FEAT_UCODE | 1 << CPU_FEAT_DEVICE_ID; + + return 0; +} diff --git a/arch/x86/cpu/ivybridge/model_206ax.c b/arch/x86/cpu/ivybridge/model_206ax.c index 6edc3e233c2..68e78e9478b 100644 --- a/arch/x86/cpu/ivybridge/model_206ax.c +++ b/arch/x86/cpu/ivybridge/model_206ax.c @@ -12,6 +12,7 @@ #include <fdtdec.h> #include <malloc.h> #include <asm/cpu.h> +#include <asm/cpu_common.h> #include <asm/cpu_x86.h> #include <asm/msr.h> #include <asm/msr-index.h> @@ -436,12 +437,7 @@ static int model_206ax_init(struct udevice *dev)
static int model_206ax_get_info(struct udevice *dev, struct cpu_info *info) { - msr_t msr; - - msr = msr_read(MSR_IA32_PERF_CTL); - info->cpu_freq = ((msr.lo >> 8) & 0xff) * SANDYBRIDGE_BCLK * 1000000; - info->features = 1 << CPU_FEAT_L1_CACHE | 1 << CPU_FEAT_MMU | - 1 << CPU_FEAT_UCODE; + return cpu_intel_get_info(info, SANDYBRIDGE_BCLK);
return 0; } diff --git a/arch/x86/include/asm/cpu_common.h b/arch/x86/include/asm/cpu_common.h index 4c91a5daced..0d560262d5a 100644 --- a/arch/x86/include/asm/cpu_common.h +++ b/arch/x86/include/asm/cpu_common.h @@ -8,6 +8,8 @@
#define IA32_PERF_CTL 0x199
+struct cpu_info; + /** * cpu_common_init() - Set up common CPU init * @@ -31,4 +33,13 @@ int cpu_common_init(void); */ int cpu_set_flex_ratio_to_tdp_nominal(void);
+/** + * cpu_intel_get_info() - Obtain CPU info for Intel CPUs + * + * Most Intel CPUs use the same MSR to obtain the clock speed, and use the same + * features. This function fills in these values, given the value of the base + * clock in MHz (typically this should be set to 100). + */ +int cpu_intel_get_info(struct cpu_info *info, int bclk_mz); + #endif

On Wed, Sep 25, 2019 at 10:13 PM Simon Glass sjg@chromium.org wrote:
Add cpu_intel_get_info() to find out the CPU info on modern Intel CPUs.
Signed-off-by: Simon Glass sjg@chromium.org
Changes in v2: None
arch/x86/cpu/broadwell/cpu_full.c | 9 +-------- arch/x86/cpu/intel_common/cpu.c | 13 +++++++++++++ arch/x86/cpu/ivybridge/model_206ax.c | 8 ++------ arch/x86/include/asm/cpu_common.h | 11 +++++++++++ 4 files changed, 27 insertions(+), 14 deletions(-)
[snip]
diff --git a/arch/x86/include/asm/cpu_common.h b/arch/x86/include/asm/cpu_common.h index 4c91a5daced..0d560262d5a 100644 --- a/arch/x86/include/asm/cpu_common.h +++ b/arch/x86/include/asm/cpu_common.h @@ -8,6 +8,8 @@
#define IA32_PERF_CTL 0x199
+struct cpu_info;
/**
- cpu_common_init() - Set up common CPU init
@@ -31,4 +33,13 @@ int cpu_common_init(void); */ int cpu_set_flex_ratio_to_tdp_nominal(void);
+/**
- cpu_intel_get_info() - Obtain CPU info for Intel CPUs
- Most Intel CPUs use the same MSR to obtain the clock speed, and use the same
- features. This function fills in these values, given the value of the base
- clock in MHz (typically this should be set to 100).
nits: please add parameter and return value descriptions.
- */
+int cpu_intel_get_info(struct cpu_info *info, int bclk_mz);
#endif
Other than that, Reviewed-by: Bin Meng bmeng.cn@gmail.com

On Wed, Oct 2, 2019 at 10:07 PM Bin Meng bmeng.cn@gmail.com wrote:
On Wed, Sep 25, 2019 at 10:13 PM Simon Glass sjg@chromium.org wrote:
Add cpu_intel_get_info() to find out the CPU info on modern Intel CPUs.
Signed-off-by: Simon Glass sjg@chromium.org
Changes in v2: None
arch/x86/cpu/broadwell/cpu_full.c | 9 +-------- arch/x86/cpu/intel_common/cpu.c | 13 +++++++++++++ arch/x86/cpu/ivybridge/model_206ax.c | 8 ++------ arch/x86/include/asm/cpu_common.h | 11 +++++++++++ 4 files changed, 27 insertions(+), 14 deletions(-)
[snip]
diff --git a/arch/x86/include/asm/cpu_common.h b/arch/x86/include/asm/cpu_common.h index 4c91a5daced..0d560262d5a 100644 --- a/arch/x86/include/asm/cpu_common.h +++ b/arch/x86/include/asm/cpu_common.h @@ -8,6 +8,8 @@
#define IA32_PERF_CTL 0x199
+struct cpu_info;
/**
- cpu_common_init() - Set up common CPU init
@@ -31,4 +33,13 @@ int cpu_common_init(void); */ int cpu_set_flex_ratio_to_tdp_nominal(void);
+/**
- cpu_intel_get_info() - Obtain CPU info for Intel CPUs
- Most Intel CPUs use the same MSR to obtain the clock speed, and use the same
- features. This function fills in these values, given the value of the base
- clock in MHz (typically this should be set to 100).
nits: please add parameter and return value descriptions.
Added parameter and return value descriptions, and
- */
+int cpu_intel_get_info(struct cpu_info *info, int bclk_mz);
#endif
Other than that, Reviewed-by: Bin Meng bmeng.cn@gmail.com
applied to u-boot-x86/next, thanks!

It is useful in SPL and TPL to access symbols from binman, such as the position and size of an entry in the ROM. Collect these symbols together in the SPL binaries.
Signed-off-by: Simon Glass sjg@chromium.org ---
Changes in v2: None
arch/x86/cpu/u-boot-spl.lds | 6 ++++++ 1 file changed, 6 insertions(+)
diff --git a/arch/x86/cpu/u-boot-spl.lds b/arch/x86/cpu/u-boot-spl.lds index f20c0b810d3..c1e9bfbf66f 100644 --- a/arch/x86/cpu/u-boot-spl.lds +++ b/arch/x86/cpu/u-boot-spl.lds @@ -35,6 +35,12 @@ SECTIONS . = ALIGN(4); __data_end = .; __init_end = .; + . = ALIGN(4); + .binman_sym_table : { + __binman_sym_start = .; + KEEP(*(SORT(.binman_sym*))); + __binman_sym_end = .; + }
_image_binary_end = .;

On Wed, Sep 25, 2019 at 10:13 PM Simon Glass sjg@chromium.org wrote:
It is useful in SPL and TPL to access symbols from binman, such as the position and size of an entry in the ROM. Collect these symbols together in the SPL binaries.
Signed-off-by: Simon Glass sjg@chromium.org
Changes in v2: None
arch/x86/cpu/u-boot-spl.lds | 6 ++++++ 1 file changed, 6 insertions(+)
Reviewed-by: Bin Meng bmeng.cn@gmail.com

On Wed, Oct 2, 2019 at 10:07 PM Bin Meng bmeng.cn@gmail.com wrote:
On Wed, Sep 25, 2019 at 10:13 PM Simon Glass sjg@chromium.org wrote:
It is useful in SPL and TPL to access symbols from binman, such as the position and size of an entry in the ROM. Collect these symbols together in the SPL binaries.
Signed-off-by: Simon Glass sjg@chromium.org
Changes in v2: None
arch/x86/cpu/u-boot-spl.lds | 6 ++++++ 1 file changed, 6 insertions(+)
Reviewed-by: Bin Meng bmeng.cn@gmail.com
applied to u-boot-x86/next, thanks!

At present the x86 pre-DM equivalent of pci_bus_clrset_config32() does not exist. Add it to simplify PCI init code on x86.
Also add the missing functions to this header.
Signed-off-by: Simon Glass sjg@chromium.org ---
Changes in v2: None
arch/x86/cpu/pci.c | 19 ++++++++++++++++++ arch/x86/include/asm/pci.h | 40 ++++++++++++++++++++++++++++++++++++++ 2 files changed, 59 insertions(+)
diff --git a/arch/x86/cpu/pci.c b/arch/x86/cpu/pci.c index c6218250e16..0ccde194d9a 100644 --- a/arch/x86/cpu/pci.c +++ b/arch/x86/cpu/pci.c @@ -16,6 +16,10 @@ #include <asm/io.h> #include <asm/pci.h>
+/* + * TODO(sjg@chromium.org): Drop the first parameter from each of these + * functions since it is not used. + */ int pci_x86_read_config(struct udevice *bus, pci_dev_t bdf, uint offset, ulong *valuep, enum pci_size_t size) { @@ -54,6 +58,21 @@ int pci_x86_write_config(struct udevice *bus, pci_dev_t bdf, uint offset, return 0; }
+int pci_x86_clrset_config(struct udevice *bus, pci_dev_t bdf, uint offset, + ulong clr, ulong set, enum pci_size_t size) +{ + ulong value; + int ret; + + ret = pci_x86_read_config(bus, bdf, offset, &value, size); + if (ret) + return ret; + value &= ~clr; + value |= set; + + return pci_x86_write_config(bus, bdf, offset, value, size); +} + void pci_assign_irqs(int bus, int device, u8 irq[4]) { pci_dev_t bdf; diff --git a/arch/x86/include/asm/pci.h b/arch/x86/include/asm/pci.h index 118ac937d93..fb1edf3df76 100644 --- a/arch/x86/include/asm/pci.h +++ b/arch/x86/include/asm/pci.h @@ -17,12 +17,52 @@
#ifndef __ASSEMBLY__
+/** + * pci_x86_read_config() - Read a configuration value from a device + * + * This function can be called before PCI is set up in driver model. + * + * @bus: Bus to read from (ignored, can be NULL) + * @bdf: PCI device address: bus, device and function -see PCI_BDF() + * @offset: Register offset to read + * @valuep: Place to put the returned value + * @size: Access size + * @return 0 if OK, -ve on error + */ int pci_x86_read_config(struct udevice *bus, pci_dev_t bdf, uint offset, ulong *valuep, enum pci_size_t size);
+/** + * pci_bus_write_config() - Write a configuration value to a device + * + * This function can be called before PCI is set up in driver model. + * + * @bus: Bus to read from (ignored, can be NULL) + * @bdf: PCI device address: bus, device and function -see PCI_BDF() + * @offset: Register offset to write + * @value: Value to write + * @size: Access size + * @return 0 if OK, -ve on error + */ int pci_x86_write_config(struct udevice *bus, pci_dev_t bdf, uint offset, ulong value, enum pci_size_t size);
+/** + * pci_bus_clrset_config32() - Update a configuration value for a device + * + * The register at @offset is updated to (oldvalue & ~clr) | set. This function + * can be called before PCI is set up in driver model. + * + * @bus: Bus to read from (ignored, can be NULL) + * @bdf: PCI device address: bus, device and function -see PCI_BDF() + * @offset: Register offset to update + * @clr: Bits to clear + * @set: Bits to set + * @return 0 if OK, -ve on error + */ +int pci_x86_clrset_config(struct udevice *bus, pci_dev_t bdf, uint offset, + ulong clr, ulong set, enum pci_size_t size); + /** * Assign IRQ number to a PCI device *

On Wed, Sep 25, 2019 at 10:13 PM Simon Glass sjg@chromium.org wrote:
At present the x86 pre-DM equivalent of pci_bus_clrset_config32() does not exist. Add it to simplify PCI init code on x86.
Also add the missing functions to this header.
Signed-off-by: Simon Glass sjg@chromium.org
Changes in v2: None
arch/x86/cpu/pci.c | 19 ++++++++++++++++++ arch/x86/include/asm/pci.h | 40 ++++++++++++++++++++++++++++++++++++++ 2 files changed, 59 insertions(+)
Reviewed-by: Bin Meng bmeng.cn@gmail.com

On Wed, Oct 2, 2019 at 10:07 PM Bin Meng bmeng.cn@gmail.com wrote:
On Wed, Sep 25, 2019 at 10:13 PM Simon Glass sjg@chromium.org wrote:
At present the x86 pre-DM equivalent of pci_bus_clrset_config32() does not exist. Add it to simplify PCI init code on x86.
Also add the missing functions to this header.
Signed-off-by: Simon Glass sjg@chromium.org
Changes in v2: None
arch/x86/cpu/pci.c | 19 ++++++++++++++++++ arch/x86/include/asm/pci.h | 40 ++++++++++++++++++++++++++++++++++++++ 2 files changed, 59 insertions(+)
Reviewed-by: Bin Meng bmeng.cn@gmail.com
applied to u-boot-x86/next, thanks!

Use the standard hang() function when booting fails since this implements the defined U-Boot behaviour for this situation.
Signed-off-by: Simon Glass sjg@chromium.org ---
Changes in v2: None
arch/x86/lib/spl.c | 3 +-- arch/x86/lib/tpl.c | 3 +-- 2 files changed, 2 insertions(+), 4 deletions(-)
diff --git a/arch/x86/lib/spl.c b/arch/x86/lib/spl.c index 5d5d1a9ca74..01a96d294bb 100644 --- a/arch/x86/lib/spl.c +++ b/arch/x86/lib/spl.c @@ -183,8 +183,7 @@ void __noreturn jump_to_image_no_args(struct spl_image_info *spl_image) printf("Jumping to 64-bit U-Boot: Note many features are missing\n"); ret = cpu_jump_to_64bit_uboot(spl_image->entry_point); debug("ret=%d\n", ret); - while (1) - ; + hang(); } #endif
diff --git a/arch/x86/lib/tpl.c b/arch/x86/lib/tpl.c index 492a2d65216..3e662a8bdaf 100644 --- a/arch/x86/lib/tpl.c +++ b/arch/x86/lib/tpl.c @@ -108,8 +108,7 @@ 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) - ; + hang(); }
void spl_board_init(void)

On Wed, Sep 25, 2019 at 10:13 PM Simon Glass sjg@chromium.org wrote:
Use the standard hang() function when booting fails since this implements the defined U-Boot behaviour for this situation.
Signed-off-by: Simon Glass sjg@chromium.org
Changes in v2: None
arch/x86/lib/spl.c | 3 +-- arch/x86/lib/tpl.c | 3 +-- 2 files changed, 2 insertions(+), 4 deletions(-)
Reviewed-by: Bin Meng bmeng.cn@gmail.com

On Wed, Oct 2, 2019 at 10:07 PM Bin Meng bmeng.cn@gmail.com wrote:
On Wed, Sep 25, 2019 at 10:13 PM Simon Glass sjg@chromium.org wrote:
Use the standard hang() function when booting fails since this implements the defined U-Boot behaviour for this situation.
Signed-off-by: Simon Glass sjg@chromium.org
Changes in v2: None
arch/x86/lib/spl.c | 3 +-- arch/x86/lib/tpl.c | 3 +-- 2 files changed, 2 insertions(+), 4 deletions(-)
Reviewed-by: Bin Meng bmeng.cn@gmail.com
applied to u-boot-x86/next, thanks!

This image loader works on systems where the flash is directly mapped to the last part of the 32-bit address space. On recent Intel systems (such as apollolake) this is not the case.
Reduce the priority of this loader so that another one can override it.
While we are here, rename the loader to BOOT_DEVICE_SPI_MMAP since BOOT_DEVICE_BOARD is not very descriptive.
Signed-off-by: Simon Glass sjg@chromium.org ---
Changes in v2: None
arch/x86/include/asm/spl.h | 3 +-- arch/x86/lib/spl.c | 5 +++-- arch/x86/lib/tpl.c | 4 ++-- 3 files changed, 6 insertions(+), 6 deletions(-)
diff --git a/arch/x86/include/asm/spl.h b/arch/x86/include/asm/spl.h index 27432b28979..1bef4877eb3 100644 --- a/arch/x86/include/asm/spl.h +++ b/arch/x86/include/asm/spl.h @@ -10,8 +10,7 @@ #define CONFIG_SPL_BOARD_LOAD_IMAGE
enum { - BOOT_DEVICE_SPI = 10, - BOOT_DEVICE_BOARD, + BOOT_DEVICE_SPI_MMAP = 10, BOOT_DEVICE_CROS_VBOOT, };
diff --git a/arch/x86/lib/spl.c b/arch/x86/lib/spl.c index 01a96d294bb..a7394913035 100644 --- a/arch/x86/lib/spl.c +++ b/arch/x86/lib/spl.c @@ -11,6 +11,7 @@ #include <asm/mrccache.h> #include <asm/mtrr.h> #include <asm/processor.h> +#include <asm/spl.h> #include <asm-generic/sections.h>
DECLARE_GLOBAL_DATA_PTR; @@ -142,7 +143,7 @@ void board_init_f_r(void)
u32 spl_boot_device(void) { - return BOOT_DEVICE_BOARD; + return BOOT_DEVICE_SPI_MMAP; }
int spl_start_uboot(void) @@ -168,7 +169,7 @@ static int spl_board_load_image(struct spl_image_info *spl_image,
return 0; } -SPL_LOAD_IMAGE_METHOD("SPI", 0, BOOT_DEVICE_BOARD, spl_board_load_image); +SPL_LOAD_IMAGE_METHOD("SPI", 5, BOOT_DEVICE_SPI_MMAP, spl_board_load_image);
int spl_spi_load_image(void) { diff --git a/arch/x86/lib/tpl.c b/arch/x86/lib/tpl.c index 3e662a8bdaf..cfefa78045e 100644 --- a/arch/x86/lib/tpl.c +++ b/arch/x86/lib/tpl.c @@ -71,7 +71,7 @@ void board_init_f_r(void) u32 spl_boot_device(void) { return IS_ENABLED(CONFIG_CHROMEOS) ? BOOT_DEVICE_CROS_VBOOT : - BOOT_DEVICE_BOARD; + BOOT_DEVICE_SPI_MMAP; }
int spl_start_uboot(void) @@ -97,7 +97,7 @@ static int spl_board_load_image(struct spl_image_info *spl_image,
return 0; } -SPL_LOAD_IMAGE_METHOD("SPI", 0, BOOT_DEVICE_BOARD, spl_board_load_image); +SPL_LOAD_IMAGE_METHOD("SPI", 5, BOOT_DEVICE_SPI_MMAP, spl_board_load_image);
int spl_spi_load_image(void) {

On Wed, Sep 25, 2019 at 10:13 PM Simon Glass sjg@chromium.org wrote:
This image loader works on systems where the flash is directly mapped to the last part of the 32-bit address space. On recent Intel systems (such as apollolake) this is not the case.
Reduce the priority of this loader so that another one can override it.
While we are here, rename the loader to BOOT_DEVICE_SPI_MMAP since BOOT_DEVICE_BOARD is not very descriptive.
Signed-off-by: Simon Glass sjg@chromium.org
Changes in v2: None
arch/x86/include/asm/spl.h | 3 +-- arch/x86/lib/spl.c | 5 +++-- arch/x86/lib/tpl.c | 4 ++-- 3 files changed, 6 insertions(+), 6 deletions(-)
Reviewed-by: Bin Meng bmeng.cn@gmail.com

On Wed, Oct 2, 2019 at 10:07 PM Bin Meng bmeng.cn@gmail.com wrote:
On Wed, Sep 25, 2019 at 10:13 PM Simon Glass sjg@chromium.org wrote:
This image loader works on systems where the flash is directly mapped to the last part of the 32-bit address space. On recent Intel systems (such as apollolake) this is not the case.
Reduce the priority of this loader so that another one can override it.
While we are here, rename the loader to BOOT_DEVICE_SPI_MMAP since BOOT_DEVICE_BOARD is not very descriptive.
Signed-off-by: Simon Glass sjg@chromium.org
Changes in v2: None
arch/x86/include/asm/spl.h | 3 +-- arch/x86/lib/spl.c | 5 +++-- arch/x86/lib/tpl.c | 4 ++-- 3 files changed, 6 insertions(+), 6 deletions(-)
Reviewed-by: Bin Meng bmeng.cn@gmail.com
applied to u-boot-x86/next, thanks!

When TPL is running, broadwell needs to do different init from SPL. There is no need for this code to be in the generic x86 SPL file, so move it to arch_cpu_init().
Signed-off-by: Simon Glass sjg@chromium.org ---
Changes in v2: None
arch/x86/cpu/broadwell/cpu.c | 5 +++++ arch/x86/cpu/broadwell/cpu_full.c | 7 +++++++ arch/x86/lib/spl.c | 5 ----- 3 files changed, 12 insertions(+), 5 deletions(-)
diff --git a/arch/x86/cpu/broadwell/cpu.c b/arch/x86/cpu/broadwell/cpu.c index bb7c3614081..bba8cd1e942 100644 --- a/arch/x86/cpu/broadwell/cpu.c +++ b/arch/x86/cpu/broadwell/cpu.c @@ -67,7 +67,12 @@ int arch_cpu_init(void) { post_code(POST_CPU_INIT);
+#ifdef CONFIG_TPL + /* Do a mini-init if TPL has already done the full init */ + return x86_cpu_reinit_f(); +#else return x86_cpu_init_f(); +#endif }
int checkcpu(void) diff --git a/arch/x86/cpu/broadwell/cpu_full.c b/arch/x86/cpu/broadwell/cpu_full.c index d8b84826586..bd0b2037fa1 100644 --- a/arch/x86/cpu/broadwell/cpu_full.c +++ b/arch/x86/cpu/broadwell/cpu_full.c @@ -81,6 +81,13 @@ static const u8 power_limit_time_msr_to_sec[] = { [0x11] = 128, };
+#if defined(CONFIG_SPL_BUILD) && !defined(CONFIG_TPL_BUILD) +int arch_cpu_init(void) +{ + return 0; +} +#endif + /* * 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/lib/spl.c b/arch/x86/lib/spl.c index a7394913035..2baac913837 100644 --- a/arch/x86/lib/spl.c +++ b/arch/x86/lib/spl.c @@ -40,12 +40,7 @@ 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;

On Wed, Sep 25, 2019 at 10:13 PM Simon Glass sjg@chromium.org wrote:
When TPL is running, broadwell needs to do different init from SPL. There is no need for this code to be in the generic x86 SPL file, so move it to arch_cpu_init().
Signed-off-by: Simon Glass sjg@chromium.org
Changes in v2: None
arch/x86/cpu/broadwell/cpu.c | 5 +++++ arch/x86/cpu/broadwell/cpu_full.c | 7 +++++++ arch/x86/lib/spl.c | 5 ----- 3 files changed, 12 insertions(+), 5 deletions(-)
Reviewed-by: Bin Meng bmeng.cn@gmail.com

On Wed, Oct 2, 2019 at 10:07 PM Bin Meng bmeng.cn@gmail.com wrote:
On Wed, Sep 25, 2019 at 10:13 PM Simon Glass sjg@chromium.org wrote:
When TPL is running, broadwell needs to do different init from SPL. There is no need for this code to be in the generic x86 SPL file, so move it to arch_cpu_init().
Signed-off-by: Simon Glass sjg@chromium.org
Changes in v2: None
arch/x86/cpu/broadwell/cpu.c | 5 +++++ arch/x86/cpu/broadwell/cpu_full.c | 7 +++++++ arch/x86/lib/spl.c | 5 ----- 3 files changed, 12 insertions(+), 5 deletions(-)
Reviewed-by: Bin Meng bmeng.cn@gmail.com
applied to u-boot-x86/next, thanks!

The useable RAM is calculated when the RAM is inited. Save this value so that it can be easily used in U-Boot proper.
Also save a pointer to the hob list so that it is accessible (before relocation only) in U-Boot proper. This avoids having to scan it in SPL, for everything U-Boot proper might need later.
Signed-off-by: Simon Glass sjg@chromium.org ---
Changes in v2: None
arch/x86/cpu/intel_common/cpu_from_spl.c | 6 ++++++ arch/x86/include/asm/handoff.h | 8 ++++++++ arch/x86/lib/fsp/fsp_dram.c | 10 ++++++++++ 3 files changed, 24 insertions(+)
diff --git a/arch/x86/cpu/intel_common/cpu_from_spl.c b/arch/x86/cpu/intel_common/cpu_from_spl.c index a6233c75ce2..b7bb524162f 100644 --- a/arch/x86/cpu/intel_common/cpu_from_spl.c +++ b/arch/x86/cpu/intel_common/cpu_from_spl.c @@ -6,6 +6,7 @@ #include <common.h> #include <dm.h> #include <errno.h> +#include <handoff.h> #include <asm/cpu_common.h> #include <asm/intel_regs.h> #include <asm/lapic.h> @@ -21,6 +22,11 @@ int arch_cpu_init(void) { int ret;
+#if CONFIG_IS_ENABLED(HANDOFF) && IS_ENABLED(CONFIG_USE_HOB) + struct spl_handoff *ho = gd->spl_handoff; + + gd->arch.hob_list = ho->arch.hob_list; +#endif ret = x86_cpu_reinit_f();
return ret; diff --git a/arch/x86/include/asm/handoff.h b/arch/x86/include/asm/handoff.h index 4d18d59efed..aec49b9b815 100644 --- a/arch/x86/include/asm/handoff.h +++ b/arch/x86/include/asm/handoff.h @@ -9,7 +9,15 @@ #ifndef __x86_asm_handoff_h #define __x86_asm_handoff_h
+/** + * struct arch_spl_handoff - architecture-specific handoff info + * + * @usable_ram_top: Value returned by board_get_usable_ram_top() in SPL + * @hob_list: Start of FSP hand-off blocks (HOBs) + */ struct arch_spl_handoff { + ulong usable_ram_top; + void *hob_list; };
#endif diff --git a/arch/x86/lib/fsp/fsp_dram.c b/arch/x86/lib/fsp/fsp_dram.c index 8fe1e0bf73d..38cc25839ec 100644 --- a/arch/x86/lib/fsp/fsp_dram.c +++ b/arch/x86/lib/fsp/fsp_dram.c @@ -88,3 +88,13 @@ unsigned int install_e820_map(unsigned int max_entries,
return num_entries; } + +#if CONFIG_IS_ENABLED(HANDOFF) +int handoff_arch_save(struct spl_handoff *ho) +{ + ho->arch.usable_ram_top = fsp_get_usable_lowmem_top(gd->arch.hob_list); + ho->arch.hob_list = gd->arch.hob_list; + + return 0; +} +#endif

Hi Simon,
On Wed, Sep 25, 2019 at 10:13 PM Simon Glass sjg@chromium.org wrote:
The useable RAM is calculated when the RAM is inited. Save this value so that it can be easily used in U-Boot proper.
Also save a pointer to the hob list so that it is accessible (before relocation only) in U-Boot proper. This avoids having to scan it in SPL, for everything U-Boot proper might need later.
Signed-off-by: Simon Glass sjg@chromium.org
Changes in v2: None
arch/x86/cpu/intel_common/cpu_from_spl.c | 6 ++++++ arch/x86/include/asm/handoff.h | 8 ++++++++ arch/x86/lib/fsp/fsp_dram.c | 10 ++++++++++ 3 files changed, 24 insertions(+)
diff --git a/arch/x86/cpu/intel_common/cpu_from_spl.c b/arch/x86/cpu/intel_common/cpu_from_spl.c index a6233c75ce2..b7bb524162f 100644 --- a/arch/x86/cpu/intel_common/cpu_from_spl.c +++ b/arch/x86/cpu/intel_common/cpu_from_spl.c @@ -6,6 +6,7 @@ #include <common.h> #include <dm.h> #include <errno.h> +#include <handoff.h> #include <asm/cpu_common.h> #include <asm/intel_regs.h> #include <asm/lapic.h> @@ -21,6 +22,11 @@ int arch_cpu_init(void) { int ret;
+#if CONFIG_IS_ENABLED(HANDOFF) && IS_ENABLED(CONFIG_USE_HOB)
struct spl_handoff *ho = gd->spl_handoff;
gd->arch.hob_list = ho->arch.hob_list;
We should guard the access to gd->arch.hob_list with #ifdef CONFIG_USE_HOB.
+#endif ret = x86_cpu_reinit_f();
return ret;
diff --git a/arch/x86/include/asm/handoff.h b/arch/x86/include/asm/handoff.h index 4d18d59efed..aec49b9b815 100644 --- a/arch/x86/include/asm/handoff.h +++ b/arch/x86/include/asm/handoff.h @@ -9,7 +9,15 @@ #ifndef __x86_asm_handoff_h #define __x86_asm_handoff_h
+/**
- struct arch_spl_handoff - architecture-specific handoff info
- @usable_ram_top: Value returned by board_get_usable_ram_top() in SPL
- @hob_list: Start of FSP hand-off blocks (HOBs)
- */
struct arch_spl_handoff {
ulong usable_ram_top;
void *hob_list;
ditto
};
#endif diff --git a/arch/x86/lib/fsp/fsp_dram.c b/arch/x86/lib/fsp/fsp_dram.c index 8fe1e0bf73d..38cc25839ec 100644 --- a/arch/x86/lib/fsp/fsp_dram.c +++ b/arch/x86/lib/fsp/fsp_dram.c @@ -88,3 +88,13 @@ unsigned int install_e820_map(unsigned int max_entries,
return num_entries;
}
+#if CONFIG_IS_ENABLED(HANDOFF) +int handoff_arch_save(struct spl_handoff *ho) +{
ho->arch.usable_ram_top = fsp_get_usable_lowmem_top(gd->arch.hob_list);
ho->arch.hob_list = gd->arch.hob_list;
ditto
return 0;
+}
+#endif
Regards, Bin

On Wed, Oct 2, 2019 at 10:07 PM Bin Meng bmeng.cn@gmail.com wrote:
Hi Simon,
On Wed, Sep 25, 2019 at 10:13 PM Simon Glass sjg@chromium.org wrote:
The useable RAM is calculated when the RAM is inited. Save this value so that it can be easily used in U-Boot proper.
Also save a pointer to the hob list so that it is accessible (before relocation only) in U-Boot proper. This avoids having to scan it in SPL, for everything U-Boot proper might need later.
Signed-off-by: Simon Glass sjg@chromium.org
Changes in v2: None
arch/x86/cpu/intel_common/cpu_from_spl.c | 6 ++++++ arch/x86/include/asm/handoff.h | 8 ++++++++ arch/x86/lib/fsp/fsp_dram.c | 10 ++++++++++ 3 files changed, 24 insertions(+)
diff --git a/arch/x86/cpu/intel_common/cpu_from_spl.c b/arch/x86/cpu/intel_common/cpu_from_spl.c index a6233c75ce2..b7bb524162f 100644 --- a/arch/x86/cpu/intel_common/cpu_from_spl.c +++ b/arch/x86/cpu/intel_common/cpu_from_spl.c @@ -6,6 +6,7 @@ #include <common.h> #include <dm.h> #include <errno.h> +#include <handoff.h> #include <asm/cpu_common.h> #include <asm/intel_regs.h> #include <asm/lapic.h> @@ -21,6 +22,11 @@ int arch_cpu_init(void) { int ret;
+#if CONFIG_IS_ENABLED(HANDOFF) && IS_ENABLED(CONFIG_USE_HOB)
struct spl_handoff *ho = gd->spl_handoff;
gd->arch.hob_list = ho->arch.hob_list;
We should guard the access to gd->arch.hob_list with #ifdef CONFIG_USE_HOB.
+#endif ret = x86_cpu_reinit_f();
return ret;
diff --git a/arch/x86/include/asm/handoff.h b/arch/x86/include/asm/handoff.h index 4d18d59efed..aec49b9b815 100644 --- a/arch/x86/include/asm/handoff.h +++ b/arch/x86/include/asm/handoff.h @@ -9,7 +9,15 @@ #ifndef __x86_asm_handoff_h #define __x86_asm_handoff_h
+/**
- struct arch_spl_handoff - architecture-specific handoff info
- @usable_ram_top: Value returned by board_get_usable_ram_top() in SPL
- @hob_list: Start of FSP hand-off blocks (HOBs)
- */
struct arch_spl_handoff {
ulong usable_ram_top;
void *hob_list;
ditto
};
#endif diff --git a/arch/x86/lib/fsp/fsp_dram.c b/arch/x86/lib/fsp/fsp_dram.c index 8fe1e0bf73d..38cc25839ec 100644 --- a/arch/x86/lib/fsp/fsp_dram.c +++ b/arch/x86/lib/fsp/fsp_dram.c @@ -88,3 +88,13 @@ unsigned int install_e820_map(unsigned int max_entries,
return num_entries;
}
+#if CONFIG_IS_ENABLED(HANDOFF) +int handoff_arch_save(struct spl_handoff *ho) +{
ho->arch.usable_ram_top = fsp_get_usable_lowmem_top(gd->arch.hob_list);
ho->arch.hob_list = gd->arch.hob_list;
ditto
return 0;
+}
+#endif
I will fix the above issues when applying.
Reviewed-by: Bin Meng bmeng.cn@gmail.com

On Fri, Oct 4, 2019 at 11:06 AM Bin Meng bmeng.cn@gmail.com wrote:
On Wed, Oct 2, 2019 at 10:07 PM Bin Meng bmeng.cn@gmail.com wrote:
Hi Simon,
On Wed, Sep 25, 2019 at 10:13 PM Simon Glass sjg@chromium.org wrote:
The useable RAM is calculated when the RAM is inited. Save this value so that it can be easily used in U-Boot proper.
Also save a pointer to the hob list so that it is accessible (before relocation only) in U-Boot proper. This avoids having to scan it in SPL, for everything U-Boot proper might need later.
Signed-off-by: Simon Glass sjg@chromium.org
Changes in v2: None
arch/x86/cpu/intel_common/cpu_from_spl.c | 6 ++++++ arch/x86/include/asm/handoff.h | 8 ++++++++ arch/x86/lib/fsp/fsp_dram.c | 10 ++++++++++ 3 files changed, 24 insertions(+)
diff --git a/arch/x86/cpu/intel_common/cpu_from_spl.c b/arch/x86/cpu/intel_common/cpu_from_spl.c index a6233c75ce2..b7bb524162f 100644 --- a/arch/x86/cpu/intel_common/cpu_from_spl.c +++ b/arch/x86/cpu/intel_common/cpu_from_spl.c @@ -6,6 +6,7 @@ #include <common.h> #include <dm.h> #include <errno.h> +#include <handoff.h> #include <asm/cpu_common.h> #include <asm/intel_regs.h> #include <asm/lapic.h> @@ -21,6 +22,11 @@ int arch_cpu_init(void) { int ret;
+#if CONFIG_IS_ENABLED(HANDOFF) && IS_ENABLED(CONFIG_USE_HOB)
struct spl_handoff *ho = gd->spl_handoff;
gd->arch.hob_list = ho->arch.hob_list;
We should guard the access to gd->arch.hob_list with #ifdef CONFIG_USE_HOB.
+#endif ret = x86_cpu_reinit_f();
return ret;
diff --git a/arch/x86/include/asm/handoff.h b/arch/x86/include/asm/handoff.h index 4d18d59efed..aec49b9b815 100644 --- a/arch/x86/include/asm/handoff.h +++ b/arch/x86/include/asm/handoff.h @@ -9,7 +9,15 @@ #ifndef __x86_asm_handoff_h #define __x86_asm_handoff_h
+/**
- struct arch_spl_handoff - architecture-specific handoff info
- @usable_ram_top: Value returned by board_get_usable_ram_top() in SPL
- @hob_list: Start of FSP hand-off blocks (HOBs)
- */
struct arch_spl_handoff {
ulong usable_ram_top;
void *hob_list;
ditto
};
#endif diff --git a/arch/x86/lib/fsp/fsp_dram.c b/arch/x86/lib/fsp/fsp_dram.c index 8fe1e0bf73d..38cc25839ec 100644 --- a/arch/x86/lib/fsp/fsp_dram.c +++ b/arch/x86/lib/fsp/fsp_dram.c @@ -88,3 +88,13 @@ unsigned int install_e820_map(unsigned int max_entries,
return num_entries;
}
+#if CONFIG_IS_ENABLED(HANDOFF) +int handoff_arch_save(struct spl_handoff *ho) +{
ho->arch.usable_ram_top = fsp_get_usable_lowmem_top(gd->arch.hob_list);
ho->arch.hob_list = gd->arch.hob_list;
ditto
return 0;
+}
+#endif
I will fix the above issues when applying.
Fixed the issues, and
Reviewed-by: Bin Meng bmeng.cn@gmail.com
applied to u-boot-x86/next, thanks!

Allocate memory for the HOBs and copy them before relocation. This ensures that they can still be accessed after relocation.
This is needed when relocating the HOB within U-Boot.
Signed-off-by: Simon Glass sjg@chromium.org ---
Changes in v2: None
arch/x86/cpu/cpu.c | 6 ++++++ arch/x86/include/asm/fsp/fsp_support.h | 8 ++++++++ arch/x86/include/asm/hob.h | 8 ++++++++ arch/x86/lib/fsp/fsp_support.c | 16 ++++++++++++++++ arch/x86/lib/hob.c | 11 +++++++++++ 5 files changed, 49 insertions(+)
diff --git a/arch/x86/cpu/cpu.c b/arch/x86/cpu/cpu.c index 290ee084e5e..e0b24c8df29 100644 --- a/arch/x86/cpu/cpu.c +++ b/arch/x86/cpu/cpu.c @@ -42,6 +42,9 @@ #include <asm/interrupt.h> #include <asm/tables.h> #include <linux/compiler.h> +#ifdef CONFIG_HAVE_FSP +#include <asm/fsp/fsp_support.h> +#endif
DECLARE_GLOBAL_DATA_PTR;
@@ -262,6 +265,9 @@ int reserve_arch(void) #ifdef CONFIG_ENABLE_MRC_CACHE mrccache_reserve(); #endif +#ifdef CONFIG_HAVE_FSP + fsp_reserve(); +#endif
#ifdef CONFIG_SEABIOS high_table_reserve(); diff --git a/arch/x86/include/asm/fsp/fsp_support.h b/arch/x86/include/asm/fsp/fsp_support.h index 4f93cb2a136..2424bc1f5f9 100644 --- a/arch/x86/include/asm/fsp/fsp_support.h +++ b/arch/x86/include/asm/fsp/fsp_support.h @@ -163,4 +163,12 @@ void *fsp_prepare_mrc_cache(void); */ u32 fsp_notify(struct fsp_header *fsp_hdr, u32 phase);
+/** + * fsp_reserve() - Relocation the HOBs + * + * Make space for the HOBs in the new memory and copy them there. This must be + * called from board_init_f() along with the 'reserve' functions. + */ +void fsp_reserve(void); + #endif diff --git a/arch/x86/include/asm/hob.h b/arch/x86/include/asm/hob.h index 72151ea045e..6b00d24071a 100644 --- a/arch/x86/include/asm/hob.h +++ b/arch/x86/include/asm/hob.h @@ -227,4 +227,12 @@ const struct hob_header *hob_get_next_guid_hob(const efi_guid_t *guid, void *hob_get_guid_hob_data(const void *hob_list, u32 *len, const efi_guid_t *guid);
+/** + * hob_get_size() - Get the total size of the HOB data + * + * This scans the list and returns the number of bytes oocupied by the HOB list. + * This can be used to copy the list to somewhere else in memory. + */ +uint hob_get_size(const void *hob_list); + #endif /* __HOB_H__ */ diff --git a/arch/x86/lib/fsp/fsp_support.c b/arch/x86/lib/fsp/fsp_support.c index 983888fd743..8063b8f7a5f 100644 --- a/arch/x86/lib/fsp/fsp_support.c +++ b/arch/x86/lib/fsp/fsp_support.c @@ -181,3 +181,19 @@ void *fsp_get_graphics_info(const void *hob_list, u32 *len)
return hob_get_guid_hob_data(hob_list, len, &guid); } + +void fsp_reserve(void) +{ + void *new_hobs; + uint hob_size; + + hob_size = hob_get_size(gd->arch.hob_list); + gd->start_addr_sp -= hob_size; + new_hobs = (void *)gd->start_addr_sp; + memcpy(new_hobs, gd->arch.hob_list, hob_size); + + gd->start_addr_sp &= ~0xf; + debug("Copying FSP HOBs from %p to %p, size %x\n", gd->arch.hob_list, + new_hobs, hob_size); + gd->arch.hob_list = new_hobs; +} diff --git a/arch/x86/lib/hob.c b/arch/x86/lib/hob.c index f2c47240ee8..43c53f4bbb3 100644 --- a/arch/x86/lib/hob.c +++ b/arch/x86/lib/hob.c @@ -82,3 +82,14 @@ void *hob_get_guid_hob_data(const void *hob_list, u32 *len,
return get_guid_hob_data(guid_hob); } + +uint hob_get_size(const void *hob_list) +{ + const struct hob_header *hdr; + + for (hdr = hob_list; !end_of_hob(hdr); hdr = get_next_hob(hdr)) + ; + hdr++; + + return (void *)hdr - hob_list; +}

Hi Simon,
On Wed, Sep 25, 2019 at 10:13 PM Simon Glass sjg@chromium.org wrote:
Allocate memory for the HOBs and copy them before relocation. This ensures that they can still be accessed after relocation.
This is needed when relocating the HOB within U-Boot.
Signed-off-by: Simon Glass sjg@chromium.org
Changes in v2: None
arch/x86/cpu/cpu.c | 6 ++++++ arch/x86/include/asm/fsp/fsp_support.h | 8 ++++++++ arch/x86/include/asm/hob.h | 8 ++++++++ arch/x86/lib/fsp/fsp_support.c | 16 ++++++++++++++++ arch/x86/lib/hob.c | 11 +++++++++++ 5 files changed, 49 insertions(+)
Why is this patch needed?
The HOBs are currently available after relocation already. See cmd/x86/hob.c
Regards, Bin

Hi Bin,
On Thu, 3 Oct 2019 at 20:23, Bin Meng bmeng.cn@gmail.com wrote:
Hi Simon,
On Wed, Sep 25, 2019 at 10:13 PM Simon Glass sjg@chromium.org wrote:
Allocate memory for the HOBs and copy them before relocation. This ensures that they can still be accessed after relocation.
This is needed when relocating the HOB within U-Boot.
Signed-off-by: Simon Glass sjg@chromium.org
Changes in v2: None
arch/x86/cpu/cpu.c | 6 ++++++ arch/x86/include/asm/fsp/fsp_support.h | 8 ++++++++ arch/x86/include/asm/hob.h | 8 ++++++++ arch/x86/lib/fsp/fsp_support.c | 16 ++++++++++++++++ arch/x86/lib/hob.c | 11 +++++++++++ 5 files changed, 49 insertions(+)
Why is this patch needed?
The HOBs are currently available after relocation already. See cmd/x86/hob.c
Yes, unfortunately this was due to another problem that I had, and I never came back and dropped this patch before sending. Sorry about that.
Regards, Simon

At present we assume that CAR (Cache-as-RAM) is used if HOBs (Hand-off bLocks) are not, since HOBs typically indicate that an FSP is in use, and FSPs handle the CAR init.
However this is a bit indirect, and for FSP2 machines which use their own CAR implementation (such as apollolake) but use the FSP for other functions, the logic is wrong.
To fix this, add a dedicated Kconfig option to indicate when CAR is used.
Signed-off-by: Simon Glass sjg@chromium.org ---
Changes in v2: None
arch/x86/Kconfig | 8 ++++++++ arch/x86/cpu/start.S | 4 ++-- configs/slimbootloader_defconfig | 1 + 3 files changed, 11 insertions(+), 2 deletions(-)
diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig index 314f8def7a4..47bf28c434f 100644 --- a/arch/x86/Kconfig +++ b/arch/x86/Kconfig @@ -364,6 +364,14 @@ config HAVE_FSP Note: Without this binary U-Boot will not be able to set up its SDRAM so will not boot.
+config USE_CAR + bool "Use Cache-As-RAM (CAR) to get temporary RAM at start-up" + default y if !HAVE_FSP + help + Select this option if your board uses CAR init code, typically in a + car.S file, to get some initial memory for code execution. This is + common with Intel CPUs which don't use FSP. + choice prompt "FSP version" depends on HAVE_FSP diff --git a/arch/x86/cpu/start.S b/arch/x86/cpu/start.S index 3c9bdf2a9d6..9b763942743 100644 --- a/arch/x86/cpu/start.S +++ b/arch/x86/cpu/start.S @@ -90,7 +90,7 @@ early_board_init_ret: jmp car_init .globl car_init_ret car_init_ret: -#ifndef CONFIG_USE_HOB +#ifdef CONFIG_USE_CAR /* * We now have CONFIG_SYS_CAR_SIZE bytes of Cache-As-RAM (or SRAM, * or fully initialised SDRAM - we really don't care which) @@ -130,7 +130,7 @@ car_init_ret:
/* Get address of global_data */ mov %fs:0, %edx -#ifdef CONFIG_USE_HOB +#if defined(CONFIG_USE_HOB) && !defined(CONFIG_USE_CAR) /* Store the HOB list if we have one */ test %esi, %esi jz skip_hob diff --git a/configs/slimbootloader_defconfig b/configs/slimbootloader_defconfig index f9fecff45ea..3cbb83c7a47 100644 --- a/configs/slimbootloader_defconfig +++ b/configs/slimbootloader_defconfig @@ -18,3 +18,4 @@ CONFIG_REGMAP=y CONFIG_SYSCON=y # CONFIG_PCI_PNP is not set CONFIG_CONSOLE_SCROLL_LINES=5 +# CONFIG_USE_CAR is not set

On Wed, Sep 25, 2019 at 10:13 PM Simon Glass sjg@chromium.org wrote:
At present we assume that CAR (Cache-as-RAM) is used if HOBs (Hand-off bLocks) are not, since HOBs typically indicate that an FSP is in use, and
nits: blocks
FSPs handle the CAR init.
However this is a bit indirect, and for FSP2 machines which use their own CAR implementation (such as apollolake) but use the FSP for other functions, the logic is wrong.
To fix this, add a dedicated Kconfig option to indicate when CAR is used.
Signed-off-by: Simon Glass sjg@chromium.org
Changes in v2: None
arch/x86/Kconfig | 8 ++++++++ arch/x86/cpu/start.S | 4 ++-- configs/slimbootloader_defconfig | 1 + 3 files changed, 11 insertions(+), 2 deletions(-)
Reviewed-by: Bin Meng bmeng.cn@gmail.com

On Wed, Oct 2, 2019 at 10:07 PM Bin Meng bmeng.cn@gmail.com wrote:
On Wed, Sep 25, 2019 at 10:13 PM Simon Glass sjg@chromium.org wrote:
At present we assume that CAR (Cache-as-RAM) is used if HOBs (Hand-off bLocks) are not, since HOBs typically indicate that an FSP is in use, and
nits: blocks
FSPs handle the CAR init.
However this is a bit indirect, and for FSP2 machines which use their own CAR implementation (such as apollolake) but use the FSP for other functions, the logic is wrong.
To fix this, add a dedicated Kconfig option to indicate when CAR is used.
Signed-off-by: Simon Glass sjg@chromium.org
Changes in v2: None
arch/x86/Kconfig | 8 ++++++++ arch/x86/cpu/start.S | 4 ++-- configs/slimbootloader_defconfig | 1 + 3 files changed, 11 insertions(+), 2 deletions(-)
Reviewed-by: Bin Meng bmeng.cn@gmail.com
applied to u-boot-x86/next, thanks!

The full start-up sequence (TPL->SPL->U-Boot) can be a bit confusing since each phase has its own 'start' file. Add comments to explain this.
Signed-off-by: Simon Glass sjg@chromium.org ---
Changes in v2: None
arch/x86/cpu/start.S | 12 ++++++++++++ arch/x86/cpu/start_from_spl.S | 5 +++-- arch/x86/cpu/start_from_tpl.S | 3 ++- 3 files changed, 17 insertions(+), 3 deletions(-)
diff --git a/arch/x86/cpu/start.S b/arch/x86/cpu/start.S index 9b763942743..01524635e9c 100644 --- a/arch/x86/cpu/start.S +++ b/arch/x86/cpu/start.S @@ -2,6 +2,18 @@ /* * U-Boot - x86 Startup Code * + * This is always the first code to run from the U-Boot source. To spell it out: + * + * 1. When TPL (Tertiary Program Loader) is enabled, the boot flow is + * TPL->SPL->U-Boot and this file is used for TPL. Then start_from_tpl.S is used + * for SPL and start_from_spl.S is used for U-Boot proper. + * + * 2. When SPL (Secondary Program Loader) is enabled, but not TPL, the boot + * flow is SPL->U-Boot and this file is used for SPL. Then start_from_spl.S is + * used for U-Boot proper. + * + * 3. When neither TPL nor SPL is used, this file is used for U-Boot proper. + * * (C) Copyright 2008-2011 * Graeme Russ, graeme.russ@gmail.com * diff --git a/arch/x86/cpu/start_from_spl.S b/arch/x86/cpu/start_from_spl.S index 4d4e5d0758d..a73b4d7c459 100644 --- a/arch/x86/cpu/start_from_spl.S +++ b/arch/x86/cpu/start_from_spl.S @@ -1,7 +1,8 @@ /* SPDX-License-Identifier: GPL-2.0+ */ /* - * 32-bit x86 Startup Code when running from SPL - * + * 32-bit x86 Startup Code when running from SPL. This is the startup code in + * U-Boot proper, when SPL is used. + * Copyright 2018 Google, Inc * Written by Simon Glass sjg@chromium.org */ diff --git a/arch/x86/cpu/start_from_tpl.S b/arch/x86/cpu/start_from_tpl.S index 44b5363a685..9a4974a5f1b 100644 --- a/arch/x86/cpu/start_from_tpl.S +++ b/arch/x86/cpu/start_from_tpl.S @@ -1,6 +1,7 @@ /* SPDX-License-Identifier: GPL-2.0+ */ /* - * 32-bit x86 Startup Code when running from TPL + * 32-bit x86 Startup Code when running from TPL. This is the startup code in + * SPL, when TPL is used. * * Copyright 2018 Google, Inc * Written by Simon Glass sjg@chromium.org

On Wed, Sep 25, 2019 at 10:13 PM Simon Glass sjg@chromium.org wrote:
The full start-up sequence (TPL->SPL->U-Boot) can be a bit confusing since each phase has its own 'start' file. Add comments to explain this.
Signed-off-by: Simon Glass sjg@chromium.org
Changes in v2: None
arch/x86/cpu/start.S | 12 ++++++++++++ arch/x86/cpu/start_from_spl.S | 5 +++-- arch/x86/cpu/start_from_tpl.S | 3 ++- 3 files changed, 17 insertions(+), 3 deletions(-)
Reviewed-by: Bin Meng bmeng.cn@gmail.com

On Wed, Oct 2, 2019 at 10:07 PM Bin Meng bmeng.cn@gmail.com wrote:
On Wed, Sep 25, 2019 at 10:13 PM Simon Glass sjg@chromium.org wrote:
The full start-up sequence (TPL->SPL->U-Boot) can be a bit confusing since each phase has its own 'start' file. Add comments to explain this.
Signed-off-by: Simon Glass sjg@chromium.org
Changes in v2: None
arch/x86/cpu/start.S | 12 ++++++++++++ arch/x86/cpu/start_from_spl.S | 5 +++-- arch/x86/cpu/start_from_tpl.S | 3 ++- 3 files changed, 17 insertions(+), 3 deletions(-)
Reviewed-by: Bin Meng bmeng.cn@gmail.com
applied to u-boot-x86/next, thanks!

Most x86 CPUs use a mechanism where the SPI flash is mapped into the very top of 32-bit address space, so that it can be executed in place and read simply by copying from memory. For an 8MB ROM the mapping starts at 0xff800000.
However some recent Intel CPUs do not use a simple 1:1 memory map. Instead the map starts at a different address and not all of the SPI flash is accessible through the map. This 'Fast SPI' feature requires that U-Boot check the location of the map. It is also possible (optionally) to read from the SPI flash using a driver.
Add support for booting from Fast SPI. The memory-mapped version is used by both TPL and SPL on apollolake.
Signed-off-by: Simon Glass sjg@chromium.org ---
Changes in v2: - Rename the fast SPI headers
arch/x86/cpu/intel_common/Makefile | 1 + arch/x86/cpu/intel_common/fast_spi.c | 48 ++++++++++++++++++++++++++++ arch/x86/include/asm/spl.h | 1 + 3 files changed, 50 insertions(+) create mode 100644 arch/x86/cpu/intel_common/fast_spi.c
diff --git a/arch/x86/cpu/intel_common/Makefile b/arch/x86/cpu/intel_common/Makefile index 07f27c29ec7..2de567dd9fe 100644 --- a/arch/x86/cpu/intel_common/Makefile +++ b/arch/x86/cpu/intel_common/Makefile @@ -9,6 +9,7 @@ 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-$(CONFIG_SPI_FLASH_INTEL_FAST) += fast_spi.o obj-y += lpc.o ifndef CONFIG_TARGET_EFI_APP obj-$(CONFIG_$(SPL_TPL_)X86_32BIT_INIT) += microcode.o diff --git a/arch/x86/cpu/intel_common/fast_spi.c b/arch/x86/cpu/intel_common/fast_spi.c new file mode 100644 index 00000000000..a7334ecf1a3 --- /dev/null +++ b/arch/x86/cpu/intel_common/fast_spi.c @@ -0,0 +1,48 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright 2019 Google LLC + */ + +#include <common.h> +#include <asm/io.h> +#include <asm/pci.h> +#include <asm/arch/fast_spi.h> +#include <asm/arch/iomap.h> + +/* + * Returns bios_start and fills in size of the BIOS region. + */ +ulong fast_spi_get_bios_region(struct fast_spi_regs *regs, size_t *bios_size) +{ + ulong bios_start, bios_end; + + /* + * BIOS_BFPREG provides info about BIOS-Flash Primary Region Base and + * Limit. Base and Limit fields are in units of 4K. + */ + u32 val = readl(®s->bfp); + + bios_start = (val & SPIBAR_BFPREG_PRB_MASK) << 12; + bios_end = (((val & SPIBAR_BFPREG_PRL_MASK) >> + SPIBAR_BFPREG_PRL_SHIFT) + 1) << 12; + *bios_size = bios_end - bios_start; + + return bios_start; +} + +int fast_spi_get_bios_mmap(ulong *map_basep, size_t *map_sizep, uint *offsetp) +{ + struct fast_spi_regs *regs; + ulong bar, base, mmio_base; + + /* Special case to find mapping without probing the device */ + pci_x86_read_config(NULL, PCH_DEV_SPI, PCI_BASE_ADDRESS_0, &bar, + PCI_SIZE_32); + mmio_base = bar & PCI_BASE_ADDRESS_MEM_MASK; + regs = (struct fast_spi_regs *)mmio_base; + base = fast_spi_get_bios_region(regs, map_sizep); + *map_basep = (u32)-*map_sizep - base; + *offsetp = base; + + return 0; +} diff --git a/arch/x86/include/asm/spl.h b/arch/x86/include/asm/spl.h index 1bef4877eb3..cc6cac08f23 100644 --- a/arch/x86/include/asm/spl.h +++ b/arch/x86/include/asm/spl.h @@ -11,6 +11,7 @@
enum { BOOT_DEVICE_SPI_MMAP = 10, + BOOT_DEVICE_FAST_SPI, BOOT_DEVICE_CROS_VBOOT, };

On Wed, Sep 25, 2019 at 10:13 PM Simon Glass sjg@chromium.org wrote:
Most x86 CPUs use a mechanism where the SPI flash is mapped into the very top of 32-bit address space, so that it can be executed in place and read simply by copying from memory. For an 8MB ROM the mapping starts at 0xff800000.
However some recent Intel CPUs do not use a simple 1:1 memory map. Instead the map starts at a different address and not all of the SPI flash is accessible through the map. This 'Fast SPI' feature requires that U-Boot check the location of the map. It is also possible (optionally) to read from the SPI flash using a driver.
Add support for booting from Fast SPI. The memory-mapped version is used by both TPL and SPL on apollolake.
Signed-off-by: Simon Glass sjg@chromium.org
Changes in v2:
- Rename the fast SPI headers
arch/x86/cpu/intel_common/Makefile | 1 + arch/x86/cpu/intel_common/fast_spi.c | 48 ++++++++++++++++++++++++++++ arch/x86/include/asm/spl.h | 1 + 3 files changed, 50 insertions(+) create mode 100644 arch/x86/cpu/intel_common/fast_spi.c
diff --git a/arch/x86/cpu/intel_common/Makefile b/arch/x86/cpu/intel_common/Makefile index 07f27c29ec7..2de567dd9fe 100644 --- a/arch/x86/cpu/intel_common/Makefile +++ b/arch/x86/cpu/intel_common/Makefile @@ -9,6 +9,7 @@ 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-$(CONFIG_SPI_FLASH_INTEL_FAST) += fast_spi.o obj-y += lpc.o ifndef CONFIG_TARGET_EFI_APP obj-$(CONFIG_$(SPL_TPL_)X86_32BIT_INIT) += microcode.o diff --git a/arch/x86/cpu/intel_common/fast_spi.c b/arch/x86/cpu/intel_common/fast_spi.c new file mode 100644 index 00000000000..a7334ecf1a3 --- /dev/null +++ b/arch/x86/cpu/intel_common/fast_spi.c @@ -0,0 +1,48 @@ +// SPDX-License-Identifier: GPL-2.0 +/*
- Copyright 2019 Google LLC
- */
+#include <common.h> +#include <asm/io.h> +#include <asm/pci.h> +#include <asm/arch/fast_spi.h> +#include <asm/arch/iomap.h>
+/*
- Returns bios_start and fills in size of the BIOS region.
- */
+ulong fast_spi_get_bios_region(struct fast_spi_regs *regs, size_t *bios_size)
I suspect we need a public header file for these 2 APIs?
+{
ulong bios_start, bios_end;
/*
* BIOS_BFPREG provides info about BIOS-Flash Primary Region Base and
* Limit. Base and Limit fields are in units of 4K.
*/
u32 val = readl(®s->bfp);
bios_start = (val & SPIBAR_BFPREG_PRB_MASK) << 12;
bios_end = (((val & SPIBAR_BFPREG_PRL_MASK) >>
SPIBAR_BFPREG_PRL_SHIFT) + 1) << 12;
*bios_size = bios_end - bios_start;
return bios_start;
+}
+int fast_spi_get_bios_mmap(ulong *map_basep, size_t *map_sizep, uint *offsetp) +{
struct fast_spi_regs *regs;
ulong bar, base, mmio_base;
/* Special case to find mapping without probing the device */
pci_x86_read_config(NULL, PCH_DEV_SPI, PCI_BASE_ADDRESS_0, &bar,
PCI_SIZE_32);
mmio_base = bar & PCI_BASE_ADDRESS_MEM_MASK;
regs = (struct fast_spi_regs *)mmio_base;
base = fast_spi_get_bios_region(regs, map_sizep);
*map_basep = (u32)-*map_sizep - base;
*offsetp = base;
return 0;
+} diff --git a/arch/x86/include/asm/spl.h b/arch/x86/include/asm/spl.h index 1bef4877eb3..cc6cac08f23 100644 --- a/arch/x86/include/asm/spl.h +++ b/arch/x86/include/asm/spl.h @@ -11,6 +11,7 @@
enum { BOOT_DEVICE_SPI_MMAP = 10,
BOOT_DEVICE_FAST_SPI, BOOT_DEVICE_CROS_VBOOT,
};
--
Regards, Bin

Hi Bin,
On Wed, 2 Oct 2019 at 08:08, Bin Meng bmeng.cn@gmail.com wrote:
On Wed, Sep 25, 2019 at 10:13 PM Simon Glass sjg@chromium.org wrote:
Most x86 CPUs use a mechanism where the SPI flash is mapped into the very top of 32-bit address space, so that it can be executed in place and read simply by copying from memory. For an 8MB ROM the mapping starts at 0xff800000.
However some recent Intel CPUs do not use a simple 1:1 memory map. Instead the map starts at a different address and not all of the SPI flash is accessible through the map. This 'Fast SPI' feature requires that U-Boot check the location of the map. It is also possible (optionally) to read from the SPI flash using a driver.
Add support for booting from Fast SPI. The memory-mapped version is used by both TPL and SPL on apollolake.
Signed-off-by: Simon Glass sjg@chromium.org
Changes in v2:
- Rename the fast SPI headers
arch/x86/cpu/intel_common/Makefile | 1 + arch/x86/cpu/intel_common/fast_spi.c | 48 ++++++++++++++++++++++++++++ arch/x86/include/asm/spl.h | 1 + 3 files changed, 50 insertions(+) create mode 100644 arch/x86/cpu/intel_common/fast_spi.c
diff --git a/arch/x86/cpu/intel_common/Makefile b/arch/x86/cpu/intel_common/Makefile index 07f27c29ec7..2de567dd9fe 100644 --- a/arch/x86/cpu/intel_common/Makefile +++ b/arch/x86/cpu/intel_common/Makefile @@ -9,6 +9,7 @@ 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-$(CONFIG_SPI_FLASH_INTEL_FAST) += fast_spi.o obj-y += lpc.o ifndef CONFIG_TARGET_EFI_APP obj-$(CONFIG_$(SPL_TPL_)X86_32BIT_INIT) += microcode.o diff --git a/arch/x86/cpu/intel_common/fast_spi.c b/arch/x86/cpu/intel_common/fast_spi.c new file mode 100644 index 00000000000..a7334ecf1a3 --- /dev/null +++ b/arch/x86/cpu/intel_common/fast_spi.c @@ -0,0 +1,48 @@ +// SPDX-License-Identifier: GPL-2.0 +/*
- Copyright 2019 Google LLC
- */
+#include <common.h> +#include <asm/io.h> +#include <asm/pci.h> +#include <asm/arch/fast_spi.h> +#include <asm/arch/iomap.h>
+/*
- Returns bios_start and fills in size of the BIOS region.
- */
+ulong fast_spi_get_bios_region(struct fast_spi_regs *regs, size_t *bios_size)
I suspect we need a public header file for these 2 APIs?
Yes but I've added it in a separate patch since it is apollolake-specific.
But based on your other comments I wonder if I can fix that and use the generic driver.
Regards, Simon

Add some new MTRRs used by Apollolake as well as a mask for the MTRR type.
Signed-off-by: Simon Glass sjg@chromium.org ---
Changes in v2: None
arch/x86/include/asm/msr-index.h | 22 ++++++++++++++++++++++ arch/x86/include/asm/mtrr.h | 1 + 2 files changed, 23 insertions(+)
diff --git a/arch/x86/include/asm/msr-index.h b/arch/x86/include/asm/msr-index.h index 9c1dbe61d59..1a02d8c8fe5 100644 --- a/arch/x86/include/asm/msr-index.h +++ b/arch/x86/include/asm/msr-index.h @@ -43,6 +43,12 @@ #define MSR_PIC_MSG_CONTROL 0x2e #define PLATFORM_INFO_SET_TDP (1 << 29)
+#define MSR_MTRR_CAP_MSR 0x0fe +#define MSR_MTRR_CAP_SMRR (1 << 11) +#define MSR_MTRR_CAP_WC (1 << 10) +#define MSR_MTRR_CAP_FIX (1 << 8) +#define MSR_MTRR_CAP_VCNT 0xff + #define MSR_IA32_PERFCTR0 0x000000c1 #define MSR_IA32_PERFCTR1 0x000000c2 #define MSR_FSB_FREQ 0x000000cd @@ -67,6 +73,11 @@ #define ENABLE_ULFM_AUTOCM_MASK (1 << 2) #define ENABLE_INDP_AUTOCM_MASK (1 << 3)
+#define MSR_EMULATE_PM_TIMER 0x121 +#define EMULATE_DELAY_OFFSET_VALUE 20 +#define EMULATE_PM_TMR_EN (1 << 16) +#define EMULATE_DELAY_VALUE 0x13 + #define MSR_IA32_SYSENTER_CS 0x00000174 #define MSR_IA32_SYSENTER_ESP 0x00000175 #define MSR_IA32_SYSENTER_EIP 0x00000176 @@ -78,9 +89,14 @@ #define MSR_FLEX_RATIO 0x194 #define FLEX_RATIO_LOCK (1 << 20) #define FLEX_RATIO_EN (1 << 16) +/* This is burst mode BIT 38 in IA32_MISC_ENABLE MSR at offset 1A0h */ +#define BURST_MODE_DISABLE (1 << 6)
#define MSR_IA32_MISC_ENABLES 0x000001a0 #define MSR_TEMPERATURE_TARGET 0x1a2 +#define MSR_PREFETCH_CTL 0x1a4 +#define PREFETCH_L1_DISABLE (1 << 0) +#define PREFETCH_L2_DISABLE (1 << 2) #define MSR_OFFCORE_RSP_0 0x000001a6 #define MSR_OFFCORE_RSP_1 0x000001a7 #define MSR_MISC_PWR_MGMT 0x1aa @@ -600,6 +616,12 @@ #define MSR_IA32_VMX_TRUE_ENTRY_CTLS 0x00000490 #define MSR_IA32_VMX_VMFUNC 0x00000491
+#define MSR_IA32_PQR_ASSOC 0xc8f +/* MSR bits 33:32 encode slot number 0-3 */ +#define MSR_IA32_PQR_ASSOC_MASK (1 << 0 | 1 << 1) + +#define MSR_L2_QOS_MASK(reg) (0xd10 + (reg)) + /* VMX_BASIC bits and bitmasks */ #define VMX_BASIC_VMCS_SIZE_SHIFT 32 #define VMX_BASIC_64 0x0001000000000000LLU diff --git a/arch/x86/include/asm/mtrr.h b/arch/x86/include/asm/mtrr.h index 2d897f82ef7..6f29e75ce65 100644 --- a/arch/x86/include/asm/mtrr.h +++ b/arch/x86/include/asm/mtrr.h @@ -25,6 +25,7 @@ #define MTRR_CAP_FIX (1 << 8) #define MTRR_CAP_VCNT_MASK 0xff
+#define MTRR_DEF_TYPE_MASK 0xff #define MTRR_DEF_TYPE_EN (1 << 11) #define MTRR_DEF_TYPE_FIX_EN (1 << 10)

On Wed, Sep 25, 2019 at 10:13 PM Simon Glass sjg@chromium.org wrote:
Add some new MTRRs used by Apollolake as well as a mask for the MTRR type.
Signed-off-by: Simon Glass sjg@chromium.org
Changes in v2: None
arch/x86/include/asm/msr-index.h | 22 ++++++++++++++++++++++ arch/x86/include/asm/mtrr.h | 1 + 2 files changed, 23 insertions(+)
Reviewed-by: Bin Meng bmeng.cn@gmail.com

On Wed, Oct 2, 2019 at 10:08 PM Bin Meng bmeng.cn@gmail.com wrote:
On Wed, Sep 25, 2019 at 10:13 PM Simon Glass sjg@chromium.org wrote:
Add some new MTRRs used by Apollolake as well as a mask for the MTRR type.
Signed-off-by: Simon Glass sjg@chromium.org
Changes in v2: None
arch/x86/include/asm/msr-index.h | 22 ++++++++++++++++++++++ arch/x86/include/asm/mtrr.h | 1 + 2 files changed, 23 insertions(+)
Reviewed-by: Bin Meng bmeng.cn@gmail.com
applied to u-boot-x86/next, thanks!

This MSR number is used on most modern Intel processors, so drop the confusing NHM prefix (which might mean Nehalem).
Signed-off-by: Simon Glass sjg@chromium.org ---
Changes in v2: - Rebase to master
arch/x86/cpu/broadwell/cpu_full.c | 2 +- arch/x86/include/asm/msr-index.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/arch/x86/cpu/broadwell/cpu_full.c b/arch/x86/cpu/broadwell/cpu_full.c index bd0b2037fa1..9686cf5e0e7 100644 --- a/arch/x86/cpu/broadwell/cpu_full.c +++ b/arch/x86/cpu/broadwell/cpu_full.c @@ -346,7 +346,7 @@ static void set_max_ratio(void)
/* Check for configurable TDP option */ if (turbo_get_state() == TURBO_ENABLED) { - msr = msr_read(MSR_NHM_TURBO_RATIO_LIMIT); + msr = msr_read(MSR_TURBO_RATIO_LIMIT); perf_ctl.lo = (msr.lo & 0xff) << 8; } else if (cpu_config_tdp_levels()) { /* Set to nominal TDP ratio */ diff --git a/arch/x86/include/asm/msr-index.h b/arch/x86/include/asm/msr-index.h index 1a02d8c8fe5..7cb78beafa1 100644 --- a/arch/x86/include/asm/msr-index.h +++ b/arch/x86/include/asm/msr-index.h @@ -101,7 +101,7 @@ #define MSR_OFFCORE_RSP_1 0x000001a7 #define MSR_MISC_PWR_MGMT 0x1aa #define MISC_PWR_MGMT_EIST_HW_DIS (1 << 0) -#define MSR_NHM_TURBO_RATIO_LIMIT 0x000001ad +#define MSR_TURBO_RATIO_LIMIT 0x000001ad #define MSR_IVT_TURBO_RATIO_LIMIT 0x000001ae
#define MSR_IA32_ENERGY_PERFORMANCE_BIAS 0x1b0

On Wed, Sep 25, 2019 at 10:13 PM Simon Glass sjg@chromium.org wrote:
This MSR number is used on most modern Intel processors, so drop the confusing NHM prefix (which might mean Nehalem).
Signed-off-by: Simon Glass sjg@chromium.org
Changes in v2:
- Rebase to master
arch/x86/cpu/broadwell/cpu_full.c | 2 +- arch/x86/include/asm/msr-index.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/arch/x86/cpu/broadwell/cpu_full.c b/arch/x86/cpu/broadwell/cpu_full.c index bd0b2037fa1..9686cf5e0e7 100644 --- a/arch/x86/cpu/broadwell/cpu_full.c +++ b/arch/x86/cpu/broadwell/cpu_full.c @@ -346,7 +346,7 @@ static void set_max_ratio(void)
/* Check for configurable TDP option */ if (turbo_get_state() == TURBO_ENABLED) {
msr = msr_read(MSR_NHM_TURBO_RATIO_LIMIT);
msr = msr_read(MSR_TURBO_RATIO_LIMIT); perf_ctl.lo = (msr.lo & 0xff) << 8; } else if (cpu_config_tdp_levels()) { /* Set to nominal TDP ratio */
diff --git a/arch/x86/include/asm/msr-index.h b/arch/x86/include/asm/msr-index.h index 1a02d8c8fe5..7cb78beafa1 100644 --- a/arch/x86/include/asm/msr-index.h +++ b/arch/x86/include/asm/msr-index.h @@ -101,7 +101,7 @@ #define MSR_OFFCORE_RSP_1 0x000001a7 #define MSR_MISC_PWR_MGMT 0x1aa #define MISC_PWR_MGMT_EIST_HW_DIS (1 << 0) -#define MSR_NHM_TURBO_RATIO_LIMIT 0x000001ad +#define MSR_TURBO_RATIO_LIMIT 0x000001ad #define MSR_IVT_TURBO_RATIO_LIMIT 0x000001ae
How about dropping this one too? It's not used in U-Boot.
#define MSR_IA32_ENERGY_PERFORMANCE_BIAS 0x1b0
Reviewed-by: Bin Meng bmeng.cn@gmail.com

On Wed, Oct 2, 2019 at 10:08 PM Bin Meng bmeng.cn@gmail.com wrote:
On Wed, Sep 25, 2019 at 10:13 PM Simon Glass sjg@chromium.org wrote:
This MSR number is used on most modern Intel processors, so drop the confusing NHM prefix (which might mean Nehalem).
Signed-off-by: Simon Glass sjg@chromium.org
Changes in v2:
- Rebase to master
arch/x86/cpu/broadwell/cpu_full.c | 2 +- arch/x86/include/asm/msr-index.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/arch/x86/cpu/broadwell/cpu_full.c b/arch/x86/cpu/broadwell/cpu_full.c index bd0b2037fa1..9686cf5e0e7 100644 --- a/arch/x86/cpu/broadwell/cpu_full.c +++ b/arch/x86/cpu/broadwell/cpu_full.c @@ -346,7 +346,7 @@ static void set_max_ratio(void)
/* Check for configurable TDP option */ if (turbo_get_state() == TURBO_ENABLED) {
msr = msr_read(MSR_NHM_TURBO_RATIO_LIMIT);
msr = msr_read(MSR_TURBO_RATIO_LIMIT); perf_ctl.lo = (msr.lo & 0xff) << 8; } else if (cpu_config_tdp_levels()) { /* Set to nominal TDP ratio */
diff --git a/arch/x86/include/asm/msr-index.h b/arch/x86/include/asm/msr-index.h index 1a02d8c8fe5..7cb78beafa1 100644 --- a/arch/x86/include/asm/msr-index.h +++ b/arch/x86/include/asm/msr-index.h @@ -101,7 +101,7 @@ #define MSR_OFFCORE_RSP_1 0x000001a7 #define MSR_MISC_PWR_MGMT 0x1aa #define MISC_PWR_MGMT_EIST_HW_DIS (1 << 0) -#define MSR_NHM_TURBO_RATIO_LIMIT 0x000001ad +#define MSR_TURBO_RATIO_LIMIT 0x000001ad #define MSR_IVT_TURBO_RATIO_LIMIT 0x000001ae
How about dropping this one too? It's not used in U-Boot.
Dropped this, and
#define MSR_IA32_ENERGY_PERFORMANCE_BIAS 0x1b0
Reviewed-by: Bin Meng bmeng.cn@gmail.com
applied to u-boot-x86/next, thanks!
participants (4)
-
Bin Meng
-
Simon Glass
-
Simon Goldschmidt
-
Vignesh Raghavendra