[U-Boot] [PATCH v5 094/101] x86: apl: Add SPL loaders
Bin Meng
bmeng.cn at gmail.com
Mon Dec 2 08:06:53 CET 2019
Hi Simon,
On Mon, Nov 25, 2019 at 12:12 PM Simon Glass <sjg at chromium.org> wrote:
>
> Add loaders for SPL and TPL so that the next stage can be loaded from
> memory-mapped SPI or, failing that, the Fast SPI driver.
>
> Signed-off-by: Simon Glass <sjg at chromium.org>
>
> ---
>
> Changes in v5:
> - Add L2 cache flush functoin
> - Drop SAFETY_MARGIN
>
> Changes in v4: None
> Changes in v3:
> - Add a driver for APL SPI for TPL (using of-platdata)
> - Support TPL without CONFIG_TPL_SPI_SUPPORT
> - Support bootstage timing
>
> Changes in v2: None
>
> arch/x86/cpu/apollolake/Makefile | 2 +
> arch/x86/cpu/apollolake/spl.c | 197 +++++++++++++++++++++++++++++++
> 2 files changed, 199 insertions(+)
> create mode 100644 arch/x86/cpu/apollolake/spl.c
>
> diff --git a/arch/x86/cpu/apollolake/Makefile b/arch/x86/cpu/apollolake/Makefile
> index 875d454157..1fde400d77 100644
> --- a/arch/x86/cpu/apollolake/Makefile
> +++ b/arch/x86/cpu/apollolake/Makefile
> @@ -2,7 +2,9 @@
> #
> # Copyright 2019 Google LLC
>
> +obj-$(CONFIG_SPL_BUILD) += spl.o
> obj-$(CONFIG_SPL_BUILD) += systemagent.o
> +
> ifndef CONFIG_TPL_BUILD
> obj-y += punit.o
> endif
> diff --git a/arch/x86/cpu/apollolake/spl.c b/arch/x86/cpu/apollolake/spl.c
> new file mode 100644
> index 0000000000..2c8222524e
> --- /dev/null
> +++ b/arch/x86/cpu/apollolake/spl.c
> @@ -0,0 +1,197 @@
> +// SPDX-License-Identifier: GPL-2.0
> +/*
> + * Copyright 2019 Google LLC
> + */
> +
> +#include <common.h>
> +#include <binman_sym.h>
> +#include <dm.h>
> +#include <spi.h>
> +#include <spl.h>
> +#include <spi_flash.h>
> +#include <asm/fast_spi.h>
> +#include <asm/spl.h>
> +#include <asm/arch/cpu.h>
> +#include <asm/arch/iomap.h>
> +#include <dm/device-internal.h>
> +#include <dm/uclass-internal.h>
> +
> +binman_sym_declare(ulong, u_boot_spl, image_pos);
> +binman_sym_declare(ulong, u_boot_spl, size);
> +/* U-Boot image_pos is declared by common/spl/spl.c */
> +binman_sym_declare(ulong, u_boot_any, size);
So should the above 3 symbols be declared in common/spl/spl.c too?
> +
> +static ulong get_image_pos(void)
> +{
> + return spl_phase() == PHASE_TPL ?
> + binman_sym(ulong, u_boot_spl, image_pos) :
> + binman_sym(ulong, u_boot_any, image_pos);
> +}
> +
> +static ulong get_image_size(void)
> +{
> + return spl_phase() == PHASE_TPL ?
> + binman_sym(ulong, u_boot_spl, size) :
> + binman_sym(ulong, u_boot_any, size);
> +}
Looks these 2 functions are generic, so can we move these to common/spl/spl.c?
> +
> +/* This reads the next phase from mapped SPI flash */
> +static int rom_load_image(struct spl_image_info *spl_image,
> + struct spl_boot_device *bootdev)
> +{
> + ulong spl_pos = get_image_pos();
> + ulong spl_size = get_image_size();
> + struct udevice *dev;
> + ulong map_base;
> + size_t map_size;
> + uint offset;
> + int ret;
> +
> + spl_image->size = CONFIG_SYS_MONITOR_LEN; /* We don't know SPL size */
> + spl_image->entry_point = spl_phase() == PHASE_TPL ?
> + CONFIG_SPL_TEXT_BASE : CONFIG_SYS_TEXT_BASE;
> + spl_image->load_addr = spl_image->entry_point;
> + spl_image->os = IH_OS_U_BOOT;
> + spl_image->name = "U-Boot";
> + debug("Reading from mapped SPI %lx, size %lx", spl_pos, spl_size);
> +
> + if (CONFIG_IS_ENABLED(SPI_FLASH_SUPPORT)) {
> + ret = uclass_find_first_device(UCLASS_SPI_FLASH, &dev);
> + if (ret)
> + return log_msg_ret("spi_flash", ret);
> + if (!dev)
> + return log_msg_ret("spi_flash dev", -ENODEV);
> + ret = dm_spi_get_mmap(dev, &map_base, &map_size, &offset);
> + if (ret)
> + return log_msg_ret("mmap", ret);
> + } else {
> + ret = fast_spi_get_bios_mmap(PCH_DEV_SPI, &map_base, &map_size,
> + &offset);
> + if (ret)
> + return ret;
> + }
> + spl_pos += map_base & ~0xff000000;
> + debug(", base %lx, pos %lx\n", map_base, spl_pos);
> + bootstage_start(BOOTSTAGE_ID_ACCUM_MMAP_SPI, "mmap_spi");
> + memcpy((void *)spl_image->load_addr, (void *)spl_pos, spl_size);
> + cpu_flush_l1d_to_l2();
> + bootstage_accum(BOOTSTAGE_ID_ACCUM_MMAP_SPI);
> +
> + return 0;
> +}
> +SPL_LOAD_IMAGE_METHOD("Mapped SPI", 2, BOOT_DEVICE_SPI_MMAP, rom_load_image);
> +
> +#if CONFIG_IS_ENABLED(SPI_FLASH_SUPPORT)
> +
> +static int apl_flash_std_read(struct udevice *dev, u32 offset, size_t len,
> + void *buf)
> +{
> + struct spi_flash *flash = dev_get_uclass_priv(dev);
> + struct mtd_info *mtd = &flash->mtd;
> + size_t retlen;
> +
> + return log_ret(mtd->_read(mtd, offset, len, &retlen, buf));
> +}
> +
> +static int apl_flash_probe(struct udevice *dev)
> +{
> + return spi_flash_std_probe(dev);
> +}
> +
> +/*
> + * Manually set the parent of the SPI flash to SPI, since dtoc doesn't. We also
> + * need to allocate the parent_platdata since by the time this function is
> + * called device_bind() has already gone past that step.
> + */
> +static int apl_flash_bind(struct udevice *dev)
> +{
> + if (CONFIG_IS_ENABLED(OF_PLATDATA)) {
> + struct dm_spi_slave_platdata *plat;
> + struct udevice *spi;
> + int ret;
> +
> + ret = uclass_first_device_err(UCLASS_SPI, &spi);
> + if (ret)
> + return ret;
> + dev->parent = spi;
> +
> + plat = calloc(sizeof(*plat), 1);
> + if (!plat)
> + return -ENOMEM;
> + dev->parent_platdata = plat;
> + }
> +
> + return 0;
> +}
> +
> +static const struct dm_spi_flash_ops apl_flash_ops = {
> + .read = apl_flash_std_read,
> +};
> +
> +static const struct udevice_id apl_flash_ids[] = {
> + { .compatible = "jedec,spi-nor" },
> + { }
> +};
> +
> +U_BOOT_DRIVER(winbond_w25q128fw) = {
> + .name = "winbond_w25q128fw",
> + .id = UCLASS_SPI_FLASH,
> + .of_match = apl_flash_ids,
> + .bind = apl_flash_bind,
> + .probe = apl_flash_probe,
> + .priv_auto_alloc_size = sizeof(struct spi_flash),
> + .ops = &apl_flash_ops,
> +};
> +
> +/* This uses a SPI flash device to read the next phase */
> +static int spl_fast_spi_load_image(struct spl_image_info *spl_image,
> + struct spl_boot_device *bootdev)
> +{
> + ulong spl_pos = get_image_pos();
> + ulong spl_size = get_image_size();
> + struct udevice *dev;
> + int ret;
> +
> + ret = uclass_first_device_err(UCLASS_SPI_FLASH, &dev);
> + if (ret)
> + return ret;
> +
> + spl_image->size = CONFIG_SYS_MONITOR_LEN; /* We don't know SPL size */
> + spl_image->entry_point = spl_phase() == PHASE_TPL ?
> + CONFIG_SPL_TEXT_BASE : CONFIG_SYS_TEXT_BASE;
> + spl_image->load_addr = spl_image->entry_point;
> + spl_image->os = IH_OS_U_BOOT;
> + spl_image->name = "U-Boot";
> + spl_pos &= ~0xff000000;
> + debug("Reading from flash %lx, size %lx\n", spl_pos, spl_size);
> + ret = spi_flash_read_dm(dev, spl_pos, spl_size,
> + (void *)spl_image->load_addr);
> + cpu_flush_l1d_to_l2();
> + if (ret)
> + return ret;
> +
> + return 0;
> +}
> +SPL_LOAD_IMAGE_METHOD("Fast SPI", 1, BOOT_DEVICE_FAST_SPI,
> + spl_fast_spi_load_image);
> +
> +void board_boot_order(u32 *spl_boot_list)
> +{
> + bool use_spi_flash = BOOT_FROM_FAST_SPI_FLASH;
> +
> + if (use_spi_flash) {
> + spl_boot_list[0] = BOOT_DEVICE_FAST_SPI;
> + spl_boot_list[1] = BOOT_DEVICE_SPI_MMAP;
> + } else {
> + spl_boot_list[0] = BOOT_DEVICE_SPI_MMAP;
> + spl_boot_list[1] = BOOT_DEVICE_FAST_SPI;
> + }
> +}
> +
> +#else
> +
> +void board_boot_order(u32 *spl_boot_list)
> +{
> + spl_boot_list[0] = BOOT_DEVICE_SPI_MMAP;
> +}
> +#endif
> --
Regards,
Bin
More information about the U-Boot
mailing list