[U-Boot] [PATCH 00/13] System Firmware Loader for TI K3 family SoCs

TI K3 SoCs like the AM654x devices are fundamentally dependent on a firmware called SYSFW (System Firmware) being loaded into the dedicated DMSC (Device Management and Security Controller) processor to provide various services via TISCI (Texas Instruments System Control Interface) to manage device aspects such as core bringup, power, clocks, security, and so on across the entire SoC.
Currently public U-Boot does not boot on an actual AM654x EVM due to the missing loading and startup of SYSFW, with this being the only piece missing preventing a successful boot from SD/MMC-type media. This gap is addressed with this patch series.
Note that the loading and starting of SYSFW is done in the context of board_init_f() in SPL which poses some unique challenges due to the very constrained nature of this environment (minimal amount of SRAM, no DDR yet available).
In order to be as lean as possible on resource use an approach was chosen that extends the existing SPL loader framework to be usable beyond the usual "loading U-Boot" use case. While this patch series only makes changes to the MMC/SD card loader framework to support eMMC/MMC/SD FS- and sector/partition-based RAW boot at this time we have this solution in production today but extended to SPI/OSPI and Y-Modem without any issues.
While I also have a working solution based on the existing FS loader framework this has its own challenges, namely by its very nature only addressing a subset of our use cases (no eMMC/SD RAW boot support for example), being heavier on resource usage (needing to use ENV to pass parameters), and not addressing the need to probe the boot peripheral. This particular framework works well for use cases requiring to load firmware from FS-based media once DDR is up and U-Boot is in a more "initialized" state but it is not a one-fits all solution for very early use in SPL board_init_f() accross different boot modes.
Andreas Dannenberg (10): mmc: k3_arasan: Allow driver to probe without PDs specified spl: Allow skipping clearing BSS during relocation spl: Make image loader infrastructure more universal arm: K3: Introduce System Firmware loader framework armV7R: K3: am654: Allow using SPL BSS pre-relocation armv7R: K3: am654: Use full malloc implementation in SPL armV7R: K3: am654: Load SYSFW binary and config from boot media configs: am65x_evm_r5: All sysfw to be loaded via MMC configs: am65x_hs_evm_r5: All sysfw to be loaded via MMC configs: am65x_hs_evm: Add Support for eMMC boot
Faiz Abbas (2): configs: am65x_evm: Add Support for eMMC boot am65x: README: Add eMMC layout and flash instructions
Lokesh Vutla (1): armv7R: dts: k3: am654: Update mmc nodes for loading sysfw
arch/arm/dts/k3-am654-r5-base-board.dts | 18 ++ arch/arm/lib/crt0.S | 3 + arch/arm/mach-k3/Kconfig | 40 +++ arch/arm/mach-k3/Makefile | 1 + arch/arm/mach-k3/am6_init.c | 34 ++- arch/arm/mach-k3/include/mach/sysfw-loader.h | 12 + arch/arm/mach-k3/sysfw-loader.c | 263 +++++++++++++++++++ board/ti/am65x/Kconfig | 1 + board/ti/am65x/README | 52 ++++ common/spl/Kconfig | 13 + common/spl/spl_fit.c | 14 + common/spl/spl_mmc.c | 76 ++++-- configs/am65x_evm_a53_defconfig | 2 + configs/am65x_evm_r5_defconfig | 7 +- configs/am65x_hs_evm_a53_defconfig | 2 + configs/am65x_hs_evm_r5_defconfig | 7 +- drivers/mmc/k3_arsan_sdhci.c | 16 +- include/configs/am65x_evm.h | 30 ++- include/spl.h | 26 ++ 19 files changed, 577 insertions(+), 40 deletions(-) create mode 100644 arch/arm/mach-k3/include/mach/sysfw-loader.h create mode 100644 arch/arm/mach-k3/sysfw-loader.c

We would like to use the driver even without power domains being specified for cases such as during early boot when the required power domains have already gotten enabled by the SoC's boot ROM and such explicit initialization is not needed and possible.
Signed-off-by: Andreas Dannenberg dannenberg@ti.com --- drivers/mmc/k3_arsan_sdhci.c | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-)
diff --git a/drivers/mmc/k3_arsan_sdhci.c b/drivers/mmc/k3_arsan_sdhci.c index d5f2857382..785ba135c7 100644 --- a/drivers/mmc/k3_arsan_sdhci.c +++ b/drivers/mmc/k3_arsan_sdhci.c @@ -31,14 +31,14 @@ static int k3_arasan_sdhci_probe(struct udevice *dev) int ret;
ret = power_domain_get_by_index(dev, &sdhci_pwrdmn, 0); - if (ret) { - dev_err(dev, "failed to get power domain\n"); - return ret; - } - - ret = power_domain_on(&sdhci_pwrdmn); - if (ret) { - dev_err(dev, "Power domain on failed\n"); + if (!ret) { + ret = power_domain_on(&sdhci_pwrdmn); + if (ret) { + dev_err(dev, "Power domain on failed\n"); + return ret; + } + } else if (ret != -ENOENT && ret != -ENODEV && ret != -ENOSYS) { + dev_err(dev, "power_domain_get() failed: %d\n", ret); return ret; }

On Tue, May 07, 2019 at 12:25:30PM -0500, Andreas Dannenberg wrote:
We would like to use the driver even without power domains being specified for cases such as during early boot when the required power domains have already gotten enabled by the SoC's boot ROM and such explicit initialization is not needed and possible.
Signed-off-by: Andreas Dannenberg dannenberg@ti.com
Reviewed-by: Tom Rini trini@konsulko.com

On some platform we have sufficient memory available early on to allow setting up and using a basic BSS prior to relocation. In order to be able to preserve data written to BSS during early startup add a Kconfig option allowing to skip the clearing of the BSS section during setting up of the final environment / relocation.
Signed-off-by: Andreas Dannenberg dannenberg@ti.com --- arch/arm/lib/crt0.S | 3 +++ common/spl/Kconfig | 13 +++++++++++++ 2 files changed, 16 insertions(+)
diff --git a/arch/arm/lib/crt0.S b/arch/arm/lib/crt0.S index fe312db690..17645469fc 100644 --- a/arch/arm/lib/crt0.S +++ b/arch/arm/lib/crt0.S @@ -124,6 +124,8 @@ here: movne sp, r0 movne r9, r0 # endif + +#if !CONFIG_IS_ENABLED(SKIP_CLEAR_BSS) ldr r0, =__bss_start /* this is auto-relocated! */
#ifdef CONFIG_USE_ARCH_MEMSET @@ -141,6 +143,7 @@ clbss_l:cmp r0, r1 /* while not at end of BSS */ addlo r0, r0, #4 /* move to next */ blo clbss_l #endif +#endif
#if ! defined(CONFIG_SPL_BUILD) bl coloured_LED_init diff --git a/common/spl/Kconfig b/common/spl/Kconfig index dd078fe79d..f9eb1a0e31 100644 --- a/common/spl/Kconfig +++ b/common/spl/Kconfig @@ -188,6 +188,19 @@ config TPL_BANNER_PRINT info. Disabling this option could be useful to reduce SPL boot time (e.g. approx. 6 ms faster, when output on i.MX6 with 115200 baud).
+ +config SPL_SKIP_CLEAR_BSS + depends on ARM && !ARM64 + bool "Skips clearing BSS section during environment setup / relocation" + help + On some platform we have sufficient memory available early on to + allow setting up and using a basic BSS prior to relocation. In order + to preserve data written to BSS during early startup use use this + option to skip the clearing of the BSS section. Note that activating + this option implies that you are responsible for clearing the BSS + section yourself, otherwise you will most likely end up with an + invalid post-relocation environment. + config SPL_DISPLAY_PRINT bool "Display a board-specific message in SPL" help

On Tue, May 07, 2019 at 12:25:31PM -0500, Andreas Dannenberg wrote:
On some platform we have sufficient memory available early on to allow setting up and using a basic BSS prior to relocation. In order to be able to preserve data written to BSS during early startup add a Kconfig option allowing to skip the clearing of the BSS section during setting up of the final environment / relocation.
Signed-off-by: Andreas Dannenberg dannenberg@ti.com
Reviewed-by: Tom Rini trini@konsulko.com

The current U-Boot SPL image loader infrastructure is very powerful, able to initialize and load from a variety of boot media however it is strongly geared towards loading specific types of images in a very specific way. To address the need being able to use this infrastructure to load arbitrary image files go ahead and refactor it as follows:
- Refactor existing spl_mmc_load_image function into superset function, accepting additional arguments such as filenames and media load offset (same concept can also be applied toother spl_XXX_load_image functions) - Extend the loader function to "remember" their peripheral initialization status so that the init is only done once during the boot process, - Extend the FIT image loading function to allow skipping the parsing/ processing of the FIT contents (so that this can be done separately in a more customized fashion) - Populate the SPL_LOAD_IMAGE_METHOD() list with a trampoline function, invoking the newly refactored superset functions in a way to maintain compatibility with the existing behavior
This refactoring initially covers MMC/SD card loading (RAW and FS-based).
Signed-off-by: Andreas Dannenberg dannenberg@ti.com --- common/spl/spl_fit.c | 14 ++++++++ common/spl/spl_mmc.c | 76 +++++++++++++++++++++++++++++--------------- include/spl.h | 26 +++++++++++++++ 3 files changed, 91 insertions(+), 25 deletions(-)
diff --git a/common/spl/spl_fit.c b/common/spl/spl_fit.c index 87ecf0bb9e..969f7775c1 100644 --- a/common/spl/spl_fit.c +++ b/common/spl/spl_fit.c @@ -340,6 +340,16 @@ static int spl_fit_image_get_os(const void *fit, int noffset, uint8_t *os) #endif }
+/* + * Weak default function to allow customizing SPL fit loading for load-only + * use cases by allowing to skip the parsing/processing of the FIT contents + * (so that this can be done separately in a more customized fashion) + */ +__weak bool spl_load_simple_fit_skip_processing(void) +{ + return false; +} + int spl_load_simple_fit(struct spl_image_info *spl_image, struct spl_load_info *info, ulong sector, void *fit) { @@ -389,6 +399,10 @@ int spl_load_simple_fit(struct spl_image_info *spl_image, if (count == 0) return -EIO;
+ /* skip further processing if requested to enable load-only use cases */ + if (spl_load_simple_fit_skip_processing()) + return 0; + /* find the node holding the images information */ images = fdt_path_offset(fit, FIT_IMAGES_PATH); if (images < 0) { diff --git a/common/spl/spl_mmc.c b/common/spl/spl_mmc.c index 324d91c884..b3619889f7 100644 --- a/common/spl/spl_mmc.c +++ b/common/spl/spl_mmc.c @@ -151,7 +151,8 @@ static int spl_mmc_find_device(struct mmc **mmcp, u32 boot_device)
#ifdef CONFIG_SYS_MMCSD_RAW_MODE_U_BOOT_USE_PARTITION static int mmc_load_image_raw_partition(struct spl_image_info *spl_image, - struct mmc *mmc, int partition) + struct mmc *mmc, int partition, + unsigned long sector) { disk_partition_t info; int err; @@ -180,8 +181,7 @@ static int mmc_load_image_raw_partition(struct spl_image_info *spl_image, }
#ifdef CONFIG_SYS_MMCSD_RAW_MODE_U_BOOT_USE_SECTOR - return mmc_load_image_raw_sector(spl_image, mmc, - info.start + CONFIG_SYS_MMCSD_RAW_MODE_U_BOOT_SECTOR); + return mmc_load_image_raw_sector(spl_image, mmc, info.start + sector); #else return mmc_load_image_raw_sector(spl_image, mmc, info.start); #endif @@ -234,7 +234,8 @@ static int mmc_load_image_raw_os(struct spl_image_info *spl_image, #endif
#ifdef CONFIG_SYS_MMCSD_FS_BOOT_PARTITION -static int spl_mmc_do_fs_boot(struct spl_image_info *spl_image, struct mmc *mmc) +static int spl_mmc_do_fs_boot(struct spl_image_info *spl_image, struct mmc *mmc, + const char *filename) { int err = -ENOSYS;
@@ -248,7 +249,7 @@ static int spl_mmc_do_fs_boot(struct spl_image_info *spl_image, struct mmc *mmc) #ifdef CONFIG_SPL_FS_LOAD_PAYLOAD_NAME err = spl_load_image_fat(spl_image, mmc_get_blk_desc(mmc), CONFIG_SYS_MMCSD_FS_BOOT_PARTITION, - CONFIG_SPL_FS_LOAD_PAYLOAD_NAME); + filename); if (!err) return err; #endif @@ -263,7 +264,7 @@ static int spl_mmc_do_fs_boot(struct spl_image_info *spl_image, struct mmc *mmc) #ifdef CONFIG_SPL_FS_LOAD_PAYLOAD_NAME err = spl_load_image_ext(spl_image, mmc_get_blk_desc(mmc), CONFIG_SYS_MMCSD_FS_BOOT_PARTITION, - CONFIG_SPL_FS_LOAD_PAYLOAD_NAME); + filename); if (!err) return err; #endif @@ -276,7 +277,8 @@ static int spl_mmc_do_fs_boot(struct spl_image_info *spl_image, struct mmc *mmc) return err; } #else -static int spl_mmc_do_fs_boot(struct spl_image_info *spl_image, struct mmc *mmc) +static int spl_mmc_do_fs_boot(struct spl_image_info *spl_image, struct mmc *mmc, + const char *filename) { return -ENOSYS; } @@ -301,24 +303,31 @@ int spl_boot_partition(const u32 boot_device) } #endif
-int spl_mmc_load_image(struct spl_image_info *spl_image, - struct spl_boot_device *bootdev) +int spl_mmc_load(struct spl_image_info *spl_image, + struct spl_boot_device *bootdev, + const char *filename, + int raw_part, + unsigned long raw_sect) { - struct mmc *mmc = NULL; + static struct mmc *mmc; u32 boot_mode; int err = 0; __maybe_unused int part;
- err = spl_mmc_find_device(&mmc, bootdev->boot_device); - if (err) - return err; + /* Perform peripheral init only once */ + if (!mmc) { + err = spl_mmc_find_device(&mmc, bootdev->boot_device); + if (err) + return err;
- err = mmc_init(mmc); - if (err) { + err = mmc_init(mmc); + if (err) { + mmc = NULL; #ifdef CONFIG_SPL_LIBCOMMON_SUPPORT - printf("spl: mmc init failed with error: %d\n", err); + printf("spl: mmc init failed with error: %d\n", err); #endif - return err; + return err; + } }
boot_mode = spl_boot_mode(bootdev->boot_device); @@ -356,17 +365,13 @@ int spl_mmc_load_image(struct spl_image_info *spl_image, return err; } #ifdef CONFIG_SYS_MMCSD_RAW_MODE_U_BOOT_USE_PARTITION - err = spl_boot_partition(bootdev->boot_device); - if (!err) - return err; - - err = mmc_load_image_raw_partition(spl_image, mmc, err); + err = mmc_load_image_raw_partition(spl_image, mmc, raw_part, + raw_sect); if (!err) return err; #endif #ifdef CONFIG_SYS_MMCSD_RAW_MODE_U_BOOT_USE_SECTOR - err = mmc_load_image_raw_sector(spl_image, mmc, - CONFIG_SYS_MMCSD_RAW_MODE_U_BOOT_SECTOR); + err = mmc_load_image_raw_sector(spl_image, mmc, raw_sect); if (!err) return err; #endif @@ -374,7 +379,7 @@ int spl_mmc_load_image(struct spl_image_info *spl_image, case MMCSD_MODE_FS: debug("spl: mmc boot mode: fs\n");
- err = spl_mmc_do_fs_boot(spl_image, mmc); + err = spl_mmc_do_fs_boot(spl_image, mmc, filename); if (!err) return err;
@@ -388,6 +393,27 @@ int spl_mmc_load_image(struct spl_image_info *spl_image, return err; }
+int spl_mmc_load_image(struct spl_image_info *spl_image, + struct spl_boot_device *bootdev) +{ + return spl_mmc_load(spl_image, bootdev, +#ifdef CONFIG_SPL_FS_LOAD_PAYLOAD_NAME + CONFIG_SPL_FS_LOAD_PAYLOAD_NAME, +#else + NULL, +#endif +#ifdef CONFIG_SYS_MMCSD_RAW_MODE_U_BOOT_PARTITION + spl_boot_partition(bootdev->boot_device), +#else + 0, +#endif +#ifdef CONFIG_SYS_MMCSD_RAW_MODE_U_BOOT_SECTOR + CONFIG_SYS_MMCSD_RAW_MODE_U_BOOT_SECTOR); +#else + 0); +#endif +} + SPL_LOAD_IMAGE_METHOD("MMC1", 0, BOOT_DEVICE_MMC1, spl_mmc_load_image); SPL_LOAD_IMAGE_METHOD("MMC2", 0, BOOT_DEVICE_MMC2, spl_mmc_load_image); SPL_LOAD_IMAGE_METHOD("MMC2_2", 0, BOOT_DEVICE_MMC2_2, spl_mmc_load_image); diff --git a/include/spl.h b/include/spl.h index f09909e189..94ca5d5c6a 100644 --- a/include/spl.h +++ b/include/spl.h @@ -108,6 +108,15 @@ struct spl_load_info { */ binman_sym_extern(ulong, u_boot_any, image_pos);
+/** + * spl_load_simple_fit_skip_processing() - Hook to allow skipping the FIT + * image processing during spl_load_simple_fit(). + * + * Return true to skip FIT processing, false to preserve the full code flow + * of spl_load_simple_fit(). + */ +bool spl_load_simple_fit_skip_processing(void); + /** * spl_load_simple_fit() - Loads a fit image from a device. * @spl_image: Image description to set up @@ -330,6 +339,23 @@ int spl_dfu_cmd(int usbctrl, char *dfu_alt_info, char *interface, char *devstr); int spl_mmc_load_image(struct spl_image_info *spl_image, struct spl_boot_device *bootdev);
+/** + * spl_mmc_load() - Load an image file from MMC/SD media + * + * @param spl_image Image data filled in by loading process + * @param bootdev Describes which device to load from + * @param filename Name of file to load (in FS mode) + * @param raw_part Partition to load from (in RAW mode) + * @param raw_sect Sector to load from (in RAW mode) + * + * @return 0 on success, otherwise error code + */ +int spl_mmc_load(struct spl_image_info *spl_image, + struct spl_boot_device *bootdev, + const char *filename, + int raw_part, + unsigned long raw_sect); + /** * spl_invoke_atf - boot using an ARM trusted firmware image */

On Tue, May 07, 2019 at 12:25:32PM -0500, Andreas Dannenberg wrote:
The current U-Boot SPL image loader infrastructure is very powerful, able to initialize and load from a variety of boot media however it is strongly geared towards loading specific types of images in a very specific way. To address the need being able to use this infrastructure to load arbitrary image files go ahead and refactor it as follows:
- Refactor existing spl_mmc_load_image function into superset function, accepting additional arguments such as filenames and media load offset (same concept can also be applied toother spl_XXX_load_image functions)
- Extend the loader function to "remember" their peripheral initialization status so that the init is only done once during the boot process,
- Extend the FIT image loading function to allow skipping the parsing/ processing of the FIT contents (so that this can be done separately in a more customized fashion)
- Populate the SPL_LOAD_IMAGE_METHOD() list with a trampoline function, invoking the newly refactored superset functions in a way to maintain compatibility with the existing behavior
This refactoring initially covers MMC/SD card loading (RAW and FS-based).
Signed-off-by: Andreas Dannenberg dannenberg@ti.com
Reviewed-by: Tom Rini trini@konsulko.com

Introduce a framework that allows loading the System Firmware (SYSFW) binary as well as the associated configuration data from an image tree blob named "sysfw.itb" from an FS-based MMC boot media or from an MMC RAW mode partition or sector.
To simplify the handling of and loading from the different boot media we tap into the existing U-Boot SPL framework usually used for loading U-Boot by building on an earlier commit that exposes some of that functionality.
Note that this initial implementation only supports FS and RAW-based eMMC/SD card boot.
Signed-off-by: Andreas Dannenberg dannenberg@ti.com Signed-off-by: Lokesh Vutla lokeshvutla@ti.com --- arch/arm/mach-k3/Kconfig | 40 +++ arch/arm/mach-k3/Makefile | 1 + arch/arm/mach-k3/include/mach/sysfw-loader.h | 12 + arch/arm/mach-k3/sysfw-loader.c | 263 +++++++++++++++++++ 4 files changed, 316 insertions(+) create mode 100644 arch/arm/mach-k3/include/mach/sysfw-loader.h create mode 100644 arch/arm/mach-k3/sysfw-loader.c
diff --git a/arch/arm/mach-k3/Kconfig b/arch/arm/mach-k3/Kconfig index e677a2e01b..f1731dda58 100644 --- a/arch/arm/mach-k3/Kconfig +++ b/arch/arm/mach-k3/Kconfig @@ -58,6 +58,46 @@ config SYS_K3_BOOT_CORE_ID int default 16
+config K3_LOAD_SYSFW + bool + depends on SPL + default n + +config K3_SYSFW_IMAGE_NAME + string "File name of SYSFW firmware and configuration blob" + depends on K3_LOAD_SYSFW + default "sysfw.itb" + help + Filename of the combined System Firmware and configuration image tree + blob to be loaded when booting from a filesystem. + +config K3_SYSFW_IMAGE_MMCSD_RAW_MODE_SECT + hex "MMC sector to load SYSFW firmware and configuration blob from" + depends on K3_LOAD_SYSFW && SYS_MMCSD_RAW_MODE_U_BOOT_USE_SECTOR + default 0x3600 + help + Address on the MMC to load the combined System Firmware and + configuration image tree blob from, when the MMC is being used + in raw mode. Units: MMC sectors (1 sector = 512 bytes). + +config K3_SYSFW_IMAGE_MMCSD_RAW_MODE_PART + hex "MMC partition to load SYSFW firmware and configuration blob from" + depends on K3_LOAD_SYSFW && SYS_MMCSD_RAW_MODE_U_BOOT_USE_PARTITION + default 2 + help + Partition on the MMC to the combined System Firmware and configuration + image tree blob from, when the MMC is being used in raw mode. + +config K3_SYSFW_IMAGE_SIZE_MAX + int "Amount of memory dynamically allocated for loading SYSFW blob" + depends on K3_LOAD_SYSFW + default 269000 + help + Amount of memory reserved through dynamic allocation at runtime for + loading the combined System Firmware and configuration image tree + blob. Keep it as tight as possible, as this directly affects the + overall SPL memory footprint. + config SYS_K3_SPL_ATF bool "Start Cortex-A from SPL" depends on SPL && CPU_V7R diff --git a/arch/arm/mach-k3/Makefile b/arch/arm/mach-k3/Makefile index 0c3a4f7db1..6c895400c2 100644 --- a/arch/arm/mach-k3/Makefile +++ b/arch/arm/mach-k3/Makefile @@ -7,4 +7,5 @@ obj-$(CONFIG_SOC_K3_AM6) += am6_init.o obj-$(CONFIG_ARM64) += arm64-mmu.o obj-$(CONFIG_CPU_V7R) += r5_mpu.o lowlevel_init.o obj-$(CONFIG_TI_SECURE_DEVICE) += security.o +obj-$(CONFIG_K3_LOAD_SYSFW) += sysfw-loader.o obj-y += common.o diff --git a/arch/arm/mach-k3/include/mach/sysfw-loader.h b/arch/arm/mach-k3/include/mach/sysfw-loader.h new file mode 100644 index 0000000000..36eb265348 --- /dev/null +++ b/arch/arm/mach-k3/include/mach/sysfw-loader.h @@ -0,0 +1,12 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ +/* + * Copyright (C) 2019 Texas Instruments Incorporated - http://www.ti.com/ + * Andreas Dannenberg dannenberg@ti.com + */ + +#ifndef _SYSFW_LOADER_H_ +#define _SYSFW_LOADER_H_ + +void k3_sysfw_loader(void (*config_pm_done_callback)(void)); + +#endif diff --git a/arch/arm/mach-k3/sysfw-loader.c b/arch/arm/mach-k3/sysfw-loader.c new file mode 100644 index 0000000000..a222266c27 --- /dev/null +++ b/arch/arm/mach-k3/sysfw-loader.c @@ -0,0 +1,263 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * K3: System Firmware Loader + * + * Copyright (C) 2019 Texas Instruments Incorporated - http://www.ti.com/ + * Andreas Dannenberg dannenberg@ti.com + */ + +#include <common.h> +#include <spl.h> +#include <malloc.h> +#include <remoteproc.h> +#include <linux/soc/ti/ti_sci_protocol.h> +#include <asm/arch/sys_proto.h> + +/* Name of the FIT image nodes for SYSFW and its config data */ +#define SYSFW_FIRMWARE "sysfw.bin" +#define SYSFW_CFG_BOARD "board-cfg.bin" +#define SYSFW_CFG_PM "pm-cfg.bin" +#define SYSFW_CFG_RM "rm-cfg.bin" +#define SYSFW_CFG_SEC "sec-cfg.bin" + +#ifdef CONFIG_SPL_BUILD + +static bool sysfw_loaded; +static void *sysfw_load_address; + +/* + * Populate SPL hook to override the default load address used by the SPL + * loader function with a custom address for SYSFW loading. + */ +struct image_header *spl_get_load_buffer(ssize_t offset, size_t size) +{ + if (sysfw_loaded) + return (struct image_header *)(CONFIG_SYS_TEXT_BASE + offset); + else if (sysfw_load_address) + return sysfw_load_address; + else + panic("SYSFW load address not defined!"); +} + +/* + * Populate SPL hook to skip the default SPL loader FIT post-processing steps + * during SYSFW loading and return to the calling function so we can perform + * our own custom processing. + */ +bool spl_load_simple_fit_skip_processing(void) +{ + return !sysfw_loaded; +} + +static int fit_get_data_by_name(const void *fit, int images, const char *name, + const void **addr, size_t *size) +{ + int node_offset; + + node_offset = fdt_subnode_offset(fit, images, name); + if (node_offset < 0) + return -ENOENT; + + return fit_image_get_data(fit, node_offset, addr, size); +} + +static void k3_sysfw_load_using_fit(void *fit) +{ + int images; + const void *sysfw_addr; + size_t sysfw_size; + int ret; + + /* Find the node holding the images information */ + images = fdt_path_offset(fit, FIT_IMAGES_PATH); + if (images < 0) + panic("Cannot find /images node (%d)\n", images); + + /* Extract System Firmware (SYSFW) image from FIT */ + ret = fit_get_data_by_name(fit, images, SYSFW_FIRMWARE, + &sysfw_addr, &sysfw_size); + if (ret < 0) + panic("Error accessing %s node in FIT (%d)\n", SYSFW_FIRMWARE, + ret); + + /* + * Start up system controller firmware + * + * It is assumed that remoteproc device 0 is the corresponding + * system-controller that runs SYSFW. Make sure DT reflects the same. + */ + ret = rproc_dev_init(0); + if (ret) + panic("rproc failed to be initialized (%d)\n", ret); + + ret = rproc_load(0, (ulong)sysfw_addr, (ulong)sysfw_size); + if (ret) + panic("Firmware failed to start on rproc (%d)\n", ret); + + ret = rproc_start(0); + if (ret) + panic("Firmware init failed on rproc (%d)\n", ret); +} + +static void k3_sysfw_configure_using_fit(void *fit, + struct ti_sci_handle *ti_sci) +{ + struct ti_sci_board_ops *board_ops = &ti_sci->ops.board_ops; + int images; + const void *cfg_fragment_addr; + size_t cfg_fragment_size; + int ret; + + /* Find the node holding the images information */ + images = fdt_path_offset(fit, FIT_IMAGES_PATH); + if (images < 0) + panic("Cannot find /images node (%d)\n", images); + + /* Extract board configuration from FIT */ + ret = fit_get_data_by_name(fit, images, SYSFW_CFG_BOARD, + &cfg_fragment_addr, &cfg_fragment_size); + if (ret < 0) + panic("Error accessing %s node in FIT (%d)\n", SYSFW_CFG_BOARD, + ret); + + /* Apply board configuration to SYSFW */ + ret = board_ops->board_config(ti_sci, + (u64)(u32)cfg_fragment_addr, + (u32)cfg_fragment_size); + if (ret) + panic("Failed to set board configuration (%d)\n", ret); + + /* Extract power/clock (PM) specific configuration from FIT */ + ret = fit_get_data_by_name(fit, images, SYSFW_CFG_PM, + &cfg_fragment_addr, &cfg_fragment_size); + if (ret < 0) + panic("Error accessing %s node in FIT (%d)\n", SYSFW_CFG_PM, + ret); + + /* Apply power/clock (PM) specific configuration to SYSFW */ + ret = board_ops->board_config_pm(ti_sci, + (u64)(u32)cfg_fragment_addr, + (u32)cfg_fragment_size); + if (ret) + panic("Failed to set board PM configuration (%d)\n", ret); + + /* Extract resource management (RM) specific configuration from FIT */ + ret = fit_get_data_by_name(fit, images, SYSFW_CFG_RM, + &cfg_fragment_addr, &cfg_fragment_size); + if (ret < 0) + panic("Error accessing %s node in FIT (%d)\n", SYSFW_CFG_RM, + ret); + + /* Apply resource management (RM) configuration to SYSFW */ + ret = board_ops->board_config_rm(ti_sci, + (u64)(u32)cfg_fragment_addr, + (u32)cfg_fragment_size); + if (ret) + panic("Failed to set board RM configuration (%d)\n", ret); + + /* Extract security specific configuration from FIT */ + ret = fit_get_data_by_name(fit, images, SYSFW_CFG_SEC, + &cfg_fragment_addr, &cfg_fragment_size); + if (ret < 0) + panic("Error accessing %s node in FIT (%d)\n", SYSFW_CFG_SEC, + ret); + + /* Apply security configuration to SYSFW */ + ret = board_ops->board_config_security(ti_sci, + (u64)(u32)cfg_fragment_addr, + (u32)cfg_fragment_size); + if (ret) + panic("Failed to set board security configuration (%d)\n", + ret); +} + +void k3_sysfw_loader(void (*config_pm_done_callback)(void)) +{ + struct spl_image_info spl_image = { 0 }; + struct spl_boot_device bootdev = { 0 }; + struct ti_sci_handle *ti_sci; + int ret; + + /* Reserve a block of aligned memory for loading the SYSFW image */ + sysfw_load_address = memalign(ARCH_DMA_MINALIGN, + CONFIG_K3_SYSFW_IMAGE_SIZE_MAX); + if (!sysfw_load_address) + panic("Error allocating %u bytes of memory for SYSFW image\n", + CONFIG_K3_SYSFW_IMAGE_SIZE_MAX); + + debug("%s: allocated %u bytes at 0x%p\n", __func__, + CONFIG_K3_SYSFW_IMAGE_SIZE_MAX, sysfw_load_address); + + /* Set load address for legacy modes that bypass spl_get_load_buffer */ + spl_image.load_addr = (uintptr_t)sysfw_load_address; + + bootdev.boot_device = spl_boot_device(); + + /* Load combined System Controller firmware and config data image */ + switch (bootdev.boot_device) { +#if CONFIG_IS_ENABLED(MMC_SUPPORT) + case BOOT_DEVICE_MMC1: + case BOOT_DEVICE_MMC2: + case BOOT_DEVICE_MMC2_2: + ret = spl_mmc_load(&spl_image, &bootdev, +#ifdef CONFIG_K3_SYSFW_IMAGE_NAME + CONFIG_K3_SYSFW_IMAGE_NAME, +#else + NULL, +#endif +#ifdef CONFIG_K3_SYSFW_IMAGE_MMCSD_RAW_MODE_PART + CONFIG_K3_SYSFW_IMAGE_MMCSD_RAW_MODE_PART, +#else + 0, +#endif +#ifdef CONFIG_K3_SYSFW_IMAGE_MMCSD_RAW_MODE_SECT + CONFIG_K3_SYSFW_IMAGE_MMCSD_RAW_MODE_SECT); +#else + 0); +#endif + break; +#endif + default: + panic("Loading SYSFW image from device %u not supported!\n", + bootdev.boot_device); + } + + if (ret) + panic("Error %d occurred during loading SYSFW image!\n", ret); + + /* + * Now that SYSFW got loaded set helper flag to restore regular SPL + * loader behavior so we can later boot into the next stage as expected. + */ + sysfw_loaded = true; + + /* Ensure the SYSFW image is in FIT format */ + if (image_get_magic((const image_header_t *)sysfw_load_address) != + FDT_MAGIC) + panic("SYSFW image not in FIT format!\n"); + + /* Extract and start SYSFW */ + k3_sysfw_load_using_fit(sysfw_load_address); + + /* Get handle for accessing SYSFW services */ + ti_sci = get_ti_sci_handle(); + + /* Parse and apply the different SYSFW configuration fragments */ + k3_sysfw_configure_using_fit(sysfw_load_address, ti_sci); + + /* + * Now that all clocks and PM aspects are setup, invoke a user- + * provided callback function. Usually this callback would be used + * to setup or re-configure the U-Boot console UART. + */ + if (config_pm_done_callback) + config_pm_done_callback(); + + /* Output System Firmware version info */ + printf("SYSFW ABI: %d.%d (firmware rev 0x%04x '%.*s')\n", + ti_sci->version.abi_major, ti_sci->version.abi_minor, + ti_sci->version.firmware_revision, + sizeof(ti_sci->version.firmware_description), + ti_sci->version.firmware_description); +} +#endif

On 07.05.19 19:25, Andreas Dannenberg wrote:
Introduce a framework that allows loading the System Firmware (SYSFW) binary as well as the associated configuration data from an image tree blob named "sysfw.itb" from an FS-based MMC boot media or from an MMC RAW mode partition or sector.
To simplify the handling of and loading from the different boot media we tap into the existing U-Boot SPL framework usually used for loading U-Boot by building on an earlier commit that exposes some of that functionality.
Note that this initial implementation only supports FS and RAW-based eMMC/SD card boot.
Signed-off-by: Andreas Dannenberg dannenberg@ti.com Signed-off-by: Lokesh Vutla lokeshvutla@ti.com
Without having a too deep understanding of this, all this stuff looks like it would be similar to drivers/misc/fs_loader.c?
Could it build on top of that?
Regards, Simon
arch/arm/mach-k3/Kconfig | 40 +++ arch/arm/mach-k3/Makefile | 1 + arch/arm/mach-k3/include/mach/sysfw-loader.h | 12 + arch/arm/mach-k3/sysfw-loader.c | 263 +++++++++++++++++++ 4 files changed, 316 insertions(+) create mode 100644 arch/arm/mach-k3/include/mach/sysfw-loader.h create mode 100644 arch/arm/mach-k3/sysfw-loader.c
diff --git a/arch/arm/mach-k3/Kconfig b/arch/arm/mach-k3/Kconfig index e677a2e01b..f1731dda58 100644 --- a/arch/arm/mach-k3/Kconfig +++ b/arch/arm/mach-k3/Kconfig @@ -58,6 +58,46 @@ config SYS_K3_BOOT_CORE_ID int default 16
+config K3_LOAD_SYSFW
- bool
- depends on SPL
- default n
+config K3_SYSFW_IMAGE_NAME
- string "File name of SYSFW firmware and configuration blob"
- depends on K3_LOAD_SYSFW
- default "sysfw.itb"
- help
Filename of the combined System Firmware and configuration image tree
blob to be loaded when booting from a filesystem.
+config K3_SYSFW_IMAGE_MMCSD_RAW_MODE_SECT
- hex "MMC sector to load SYSFW firmware and configuration blob from"
- depends on K3_LOAD_SYSFW && SYS_MMCSD_RAW_MODE_U_BOOT_USE_SECTOR
- default 0x3600
- help
Address on the MMC to load the combined System Firmware and
configuration image tree blob from, when the MMC is being used
in raw mode. Units: MMC sectors (1 sector = 512 bytes).
+config K3_SYSFW_IMAGE_MMCSD_RAW_MODE_PART
- hex "MMC partition to load SYSFW firmware and configuration blob from"
- depends on K3_LOAD_SYSFW && SYS_MMCSD_RAW_MODE_U_BOOT_USE_PARTITION
- default 2
- help
Partition on the MMC to the combined System Firmware and configuration
image tree blob from, when the MMC is being used in raw mode.
+config K3_SYSFW_IMAGE_SIZE_MAX
- int "Amount of memory dynamically allocated for loading SYSFW blob"
- depends on K3_LOAD_SYSFW
- default 269000
- help
Amount of memory reserved through dynamic allocation at runtime for
loading the combined System Firmware and configuration image tree
blob. Keep it as tight as possible, as this directly affects the
overall SPL memory footprint.
- config SYS_K3_SPL_ATF bool "Start Cortex-A from SPL" depends on SPL && CPU_V7R
diff --git a/arch/arm/mach-k3/Makefile b/arch/arm/mach-k3/Makefile index 0c3a4f7db1..6c895400c2 100644 --- a/arch/arm/mach-k3/Makefile +++ b/arch/arm/mach-k3/Makefile @@ -7,4 +7,5 @@ obj-$(CONFIG_SOC_K3_AM6) += am6_init.o obj-$(CONFIG_ARM64) += arm64-mmu.o obj-$(CONFIG_CPU_V7R) += r5_mpu.o lowlevel_init.o obj-$(CONFIG_TI_SECURE_DEVICE) += security.o +obj-$(CONFIG_K3_LOAD_SYSFW) += sysfw-loader.o obj-y += common.o diff --git a/arch/arm/mach-k3/include/mach/sysfw-loader.h b/arch/arm/mach-k3/include/mach/sysfw-loader.h new file mode 100644 index 0000000000..36eb265348 --- /dev/null +++ b/arch/arm/mach-k3/include/mach/sysfw-loader.h @@ -0,0 +1,12 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ +/*
- Copyright (C) 2019 Texas Instruments Incorporated - http://www.ti.com/
- Andreas Dannenberg dannenberg@ti.com
- */
+#ifndef _SYSFW_LOADER_H_ +#define _SYSFW_LOADER_H_
+void k3_sysfw_loader(void (*config_pm_done_callback)(void));
+#endif diff --git a/arch/arm/mach-k3/sysfw-loader.c b/arch/arm/mach-k3/sysfw-loader.c new file mode 100644 index 0000000000..a222266c27 --- /dev/null +++ b/arch/arm/mach-k3/sysfw-loader.c @@ -0,0 +1,263 @@ +// SPDX-License-Identifier: GPL-2.0+ +/*
- K3: System Firmware Loader
- Copyright (C) 2019 Texas Instruments Incorporated - http://www.ti.com/
- Andreas Dannenberg dannenberg@ti.com
- */
+#include <common.h> +#include <spl.h> +#include <malloc.h> +#include <remoteproc.h> +#include <linux/soc/ti/ti_sci_protocol.h> +#include <asm/arch/sys_proto.h>
+/* Name of the FIT image nodes for SYSFW and its config data */ +#define SYSFW_FIRMWARE "sysfw.bin" +#define SYSFW_CFG_BOARD "board-cfg.bin" +#define SYSFW_CFG_PM "pm-cfg.bin" +#define SYSFW_CFG_RM "rm-cfg.bin" +#define SYSFW_CFG_SEC "sec-cfg.bin"
+#ifdef CONFIG_SPL_BUILD
+static bool sysfw_loaded; +static void *sysfw_load_address;
+/*
- Populate SPL hook to override the default load address used by the SPL
- loader function with a custom address for SYSFW loading.
- */
+struct image_header *spl_get_load_buffer(ssize_t offset, size_t size) +{
- if (sysfw_loaded)
return (struct image_header *)(CONFIG_SYS_TEXT_BASE + offset);
- else if (sysfw_load_address)
return sysfw_load_address;
- else
panic("SYSFW load address not defined!");
+}
+/*
- Populate SPL hook to skip the default SPL loader FIT post-processing steps
- during SYSFW loading and return to the calling function so we can perform
- our own custom processing.
- */
+bool spl_load_simple_fit_skip_processing(void) +{
- return !sysfw_loaded;
+}
+static int fit_get_data_by_name(const void *fit, int images, const char *name,
const void **addr, size_t *size)
+{
- int node_offset;
- node_offset = fdt_subnode_offset(fit, images, name);
- if (node_offset < 0)
return -ENOENT;
- return fit_image_get_data(fit, node_offset, addr, size);
+}
+static void k3_sysfw_load_using_fit(void *fit) +{
- int images;
- const void *sysfw_addr;
- size_t sysfw_size;
- int ret;
- /* Find the node holding the images information */
- images = fdt_path_offset(fit, FIT_IMAGES_PATH);
- if (images < 0)
panic("Cannot find /images node (%d)\n", images);
- /* Extract System Firmware (SYSFW) image from FIT */
- ret = fit_get_data_by_name(fit, images, SYSFW_FIRMWARE,
&sysfw_addr, &sysfw_size);
- if (ret < 0)
panic("Error accessing %s node in FIT (%d)\n", SYSFW_FIRMWARE,
ret);
- /*
* Start up system controller firmware
*
* It is assumed that remoteproc device 0 is the corresponding
* system-controller that runs SYSFW. Make sure DT reflects the same.
*/
- ret = rproc_dev_init(0);
- if (ret)
panic("rproc failed to be initialized (%d)\n", ret);
- ret = rproc_load(0, (ulong)sysfw_addr, (ulong)sysfw_size);
- if (ret)
panic("Firmware failed to start on rproc (%d)\n", ret);
- ret = rproc_start(0);
- if (ret)
panic("Firmware init failed on rproc (%d)\n", ret);
+}
+static void k3_sysfw_configure_using_fit(void *fit,
struct ti_sci_handle *ti_sci)
+{
- struct ti_sci_board_ops *board_ops = &ti_sci->ops.board_ops;
- int images;
- const void *cfg_fragment_addr;
- size_t cfg_fragment_size;
- int ret;
- /* Find the node holding the images information */
- images = fdt_path_offset(fit, FIT_IMAGES_PATH);
- if (images < 0)
panic("Cannot find /images node (%d)\n", images);
- /* Extract board configuration from FIT */
- ret = fit_get_data_by_name(fit, images, SYSFW_CFG_BOARD,
&cfg_fragment_addr, &cfg_fragment_size);
- if (ret < 0)
panic("Error accessing %s node in FIT (%d)\n", SYSFW_CFG_BOARD,
ret);
- /* Apply board configuration to SYSFW */
- ret = board_ops->board_config(ti_sci,
(u64)(u32)cfg_fragment_addr,
(u32)cfg_fragment_size);
- if (ret)
panic("Failed to set board configuration (%d)\n", ret);
- /* Extract power/clock (PM) specific configuration from FIT */
- ret = fit_get_data_by_name(fit, images, SYSFW_CFG_PM,
&cfg_fragment_addr, &cfg_fragment_size);
- if (ret < 0)
panic("Error accessing %s node in FIT (%d)\n", SYSFW_CFG_PM,
ret);
- /* Apply power/clock (PM) specific configuration to SYSFW */
- ret = board_ops->board_config_pm(ti_sci,
(u64)(u32)cfg_fragment_addr,
(u32)cfg_fragment_size);
- if (ret)
panic("Failed to set board PM configuration (%d)\n", ret);
- /* Extract resource management (RM) specific configuration from FIT */
- ret = fit_get_data_by_name(fit, images, SYSFW_CFG_RM,
&cfg_fragment_addr, &cfg_fragment_size);
- if (ret < 0)
panic("Error accessing %s node in FIT (%d)\n", SYSFW_CFG_RM,
ret);
- /* Apply resource management (RM) configuration to SYSFW */
- ret = board_ops->board_config_rm(ti_sci,
(u64)(u32)cfg_fragment_addr,
(u32)cfg_fragment_size);
- if (ret)
panic("Failed to set board RM configuration (%d)\n", ret);
- /* Extract security specific configuration from FIT */
- ret = fit_get_data_by_name(fit, images, SYSFW_CFG_SEC,
&cfg_fragment_addr, &cfg_fragment_size);
- if (ret < 0)
panic("Error accessing %s node in FIT (%d)\n", SYSFW_CFG_SEC,
ret);
- /* Apply security configuration to SYSFW */
- ret = board_ops->board_config_security(ti_sci,
(u64)(u32)cfg_fragment_addr,
(u32)cfg_fragment_size);
- if (ret)
panic("Failed to set board security configuration (%d)\n",
ret);
+}
+void k3_sysfw_loader(void (*config_pm_done_callback)(void)) +{
- struct spl_image_info spl_image = { 0 };
- struct spl_boot_device bootdev = { 0 };
- struct ti_sci_handle *ti_sci;
- int ret;
- /* Reserve a block of aligned memory for loading the SYSFW image */
- sysfw_load_address = memalign(ARCH_DMA_MINALIGN,
CONFIG_K3_SYSFW_IMAGE_SIZE_MAX);
- if (!sysfw_load_address)
panic("Error allocating %u bytes of memory for SYSFW image\n",
CONFIG_K3_SYSFW_IMAGE_SIZE_MAX);
- debug("%s: allocated %u bytes at 0x%p\n", __func__,
CONFIG_K3_SYSFW_IMAGE_SIZE_MAX, sysfw_load_address);
- /* Set load address for legacy modes that bypass spl_get_load_buffer */
- spl_image.load_addr = (uintptr_t)sysfw_load_address;
- bootdev.boot_device = spl_boot_device();
- /* Load combined System Controller firmware and config data image */
- switch (bootdev.boot_device) {
+#if CONFIG_IS_ENABLED(MMC_SUPPORT)
- case BOOT_DEVICE_MMC1:
- case BOOT_DEVICE_MMC2:
- case BOOT_DEVICE_MMC2_2:
ret = spl_mmc_load(&spl_image, &bootdev,
+#ifdef CONFIG_K3_SYSFW_IMAGE_NAME
CONFIG_K3_SYSFW_IMAGE_NAME,
+#else
NULL,
+#endif +#ifdef CONFIG_K3_SYSFW_IMAGE_MMCSD_RAW_MODE_PART
CONFIG_K3_SYSFW_IMAGE_MMCSD_RAW_MODE_PART,
+#else
0,
+#endif +#ifdef CONFIG_K3_SYSFW_IMAGE_MMCSD_RAW_MODE_SECT
CONFIG_K3_SYSFW_IMAGE_MMCSD_RAW_MODE_SECT);
+#else
0);
+#endif
break;
+#endif
- default:
panic("Loading SYSFW image from device %u not supported!\n",
bootdev.boot_device);
- }
- if (ret)
panic("Error %d occurred during loading SYSFW image!\n", ret);
- /*
* Now that SYSFW got loaded set helper flag to restore regular SPL
* loader behavior so we can later boot into the next stage as expected.
*/
- sysfw_loaded = true;
- /* Ensure the SYSFW image is in FIT format */
- if (image_get_magic((const image_header_t *)sysfw_load_address) !=
FDT_MAGIC)
panic("SYSFW image not in FIT format!\n");
- /* Extract and start SYSFW */
- k3_sysfw_load_using_fit(sysfw_load_address);
- /* Get handle for accessing SYSFW services */
- ti_sci = get_ti_sci_handle();
- /* Parse and apply the different SYSFW configuration fragments */
- k3_sysfw_configure_using_fit(sysfw_load_address, ti_sci);
- /*
* Now that all clocks and PM aspects are setup, invoke a user-
* provided callback function. Usually this callback would be used
* to setup or re-configure the U-Boot console UART.
*/
- if (config_pm_done_callback)
config_pm_done_callback();
- /* Output System Firmware version info */
- printf("SYSFW ABI: %d.%d (firmware rev 0x%04x '%.*s')\n",
ti_sci->version.abi_major, ti_sci->version.abi_minor,
ti_sci->version.firmware_revision,
sizeof(ti_sci->version.firmware_description),
ti_sci->version.firmware_description);
+} +#endif

Hi Simon,
On Tue, May 07, 2019 at 08:16:07PM +0200, Simon Goldschmidt wrote:
On 07.05.19 19:25, Andreas Dannenberg wrote:
Introduce a framework that allows loading the System Firmware (SYSFW) binary as well as the associated configuration data from an image tree blob named "sysfw.itb" from an FS-based MMC boot media or from an MMC RAW mode partition or sector.
To simplify the handling of and loading from the different boot media we tap into the existing U-Boot SPL framework usually used for loading U-Boot by building on an earlier commit that exposes some of that functionality.
Note that this initial implementation only supports FS and RAW-based eMMC/SD card boot.
Signed-off-by: Andreas Dannenberg dannenberg@ti.com Signed-off-by: Lokesh Vutla lokeshvutla@ti.com
Without having a too deep understanding of this, all this stuff looks like it would be similar to drivers/misc/fs_loader.c?
Could it build on top of that?
Yes and no. Can you please review the associated cover letter, it addresses this very question which I expected to get raised.
Thanks, Andreas
Regards, Simon
arch/arm/mach-k3/Kconfig | 40 +++ arch/arm/mach-k3/Makefile | 1 + arch/arm/mach-k3/include/mach/sysfw-loader.h | 12 + arch/arm/mach-k3/sysfw-loader.c | 263 +++++++++++++++++++ 4 files changed, 316 insertions(+) create mode 100644 arch/arm/mach-k3/include/mach/sysfw-loader.h create mode 100644 arch/arm/mach-k3/sysfw-loader.c
diff --git a/arch/arm/mach-k3/Kconfig b/arch/arm/mach-k3/Kconfig index e677a2e01b..f1731dda58 100644 --- a/arch/arm/mach-k3/Kconfig +++ b/arch/arm/mach-k3/Kconfig @@ -58,6 +58,46 @@ config SYS_K3_BOOT_CORE_ID int default 16 +config K3_LOAD_SYSFW
- bool
- depends on SPL
- default n
+config K3_SYSFW_IMAGE_NAME
- string "File name of SYSFW firmware and configuration blob"
- depends on K3_LOAD_SYSFW
- default "sysfw.itb"
- help
Filename of the combined System Firmware and configuration image tree
blob to be loaded when booting from a filesystem.
+config K3_SYSFW_IMAGE_MMCSD_RAW_MODE_SECT
- hex "MMC sector to load SYSFW firmware and configuration blob from"
- depends on K3_LOAD_SYSFW && SYS_MMCSD_RAW_MODE_U_BOOT_USE_SECTOR
- default 0x3600
- help
Address on the MMC to load the combined System Firmware and
configuration image tree blob from, when the MMC is being used
in raw mode. Units: MMC sectors (1 sector = 512 bytes).
+config K3_SYSFW_IMAGE_MMCSD_RAW_MODE_PART
- hex "MMC partition to load SYSFW firmware and configuration blob from"
- depends on K3_LOAD_SYSFW && SYS_MMCSD_RAW_MODE_U_BOOT_USE_PARTITION
- default 2
- help
Partition on the MMC to the combined System Firmware and configuration
image tree blob from, when the MMC is being used in raw mode.
+config K3_SYSFW_IMAGE_SIZE_MAX
- int "Amount of memory dynamically allocated for loading SYSFW blob"
- depends on K3_LOAD_SYSFW
- default 269000
- help
Amount of memory reserved through dynamic allocation at runtime for
loading the combined System Firmware and configuration image tree
blob. Keep it as tight as possible, as this directly affects the
overall SPL memory footprint.
- config SYS_K3_SPL_ATF bool "Start Cortex-A from SPL" depends on SPL && CPU_V7R
diff --git a/arch/arm/mach-k3/Makefile b/arch/arm/mach-k3/Makefile index 0c3a4f7db1..6c895400c2 100644 --- a/arch/arm/mach-k3/Makefile +++ b/arch/arm/mach-k3/Makefile @@ -7,4 +7,5 @@ obj-$(CONFIG_SOC_K3_AM6) += am6_init.o obj-$(CONFIG_ARM64) += arm64-mmu.o obj-$(CONFIG_CPU_V7R) += r5_mpu.o lowlevel_init.o obj-$(CONFIG_TI_SECURE_DEVICE) += security.o +obj-$(CONFIG_K3_LOAD_SYSFW) += sysfw-loader.o obj-y += common.o diff --git a/arch/arm/mach-k3/include/mach/sysfw-loader.h b/arch/arm/mach-k3/include/mach/sysfw-loader.h new file mode 100644 index 0000000000..36eb265348 --- /dev/null +++ b/arch/arm/mach-k3/include/mach/sysfw-loader.h @@ -0,0 +1,12 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ +/*
- Copyright (C) 2019 Texas Instruments Incorporated - http://www.ti.com/
- Andreas Dannenberg dannenberg@ti.com
- */
+#ifndef _SYSFW_LOADER_H_ +#define _SYSFW_LOADER_H_
+void k3_sysfw_loader(void (*config_pm_done_callback)(void));
+#endif diff --git a/arch/arm/mach-k3/sysfw-loader.c b/arch/arm/mach-k3/sysfw-loader.c new file mode 100644 index 0000000000..a222266c27 --- /dev/null +++ b/arch/arm/mach-k3/sysfw-loader.c @@ -0,0 +1,263 @@ +// SPDX-License-Identifier: GPL-2.0+ +/*
- K3: System Firmware Loader
- Copyright (C) 2019 Texas Instruments Incorporated - http://www.ti.com/
- Andreas Dannenberg dannenberg@ti.com
- */
+#include <common.h> +#include <spl.h> +#include <malloc.h> +#include <remoteproc.h> +#include <linux/soc/ti/ti_sci_protocol.h> +#include <asm/arch/sys_proto.h>
+/* Name of the FIT image nodes for SYSFW and its config data */ +#define SYSFW_FIRMWARE "sysfw.bin" +#define SYSFW_CFG_BOARD "board-cfg.bin" +#define SYSFW_CFG_PM "pm-cfg.bin" +#define SYSFW_CFG_RM "rm-cfg.bin" +#define SYSFW_CFG_SEC "sec-cfg.bin"
+#ifdef CONFIG_SPL_BUILD
+static bool sysfw_loaded; +static void *sysfw_load_address;
+/*
- Populate SPL hook to override the default load address used by the SPL
- loader function with a custom address for SYSFW loading.
- */
+struct image_header *spl_get_load_buffer(ssize_t offset, size_t size) +{
- if (sysfw_loaded)
return (struct image_header *)(CONFIG_SYS_TEXT_BASE + offset);
- else if (sysfw_load_address)
return sysfw_load_address;
- else
panic("SYSFW load address not defined!");
+}
+/*
- Populate SPL hook to skip the default SPL loader FIT post-processing steps
- during SYSFW loading and return to the calling function so we can perform
- our own custom processing.
- */
+bool spl_load_simple_fit_skip_processing(void) +{
- return !sysfw_loaded;
+}
+static int fit_get_data_by_name(const void *fit, int images, const char *name,
const void **addr, size_t *size)
+{
- int node_offset;
- node_offset = fdt_subnode_offset(fit, images, name);
- if (node_offset < 0)
return -ENOENT;
- return fit_image_get_data(fit, node_offset, addr, size);
+}
+static void k3_sysfw_load_using_fit(void *fit) +{
- int images;
- const void *sysfw_addr;
- size_t sysfw_size;
- int ret;
- /* Find the node holding the images information */
- images = fdt_path_offset(fit, FIT_IMAGES_PATH);
- if (images < 0)
panic("Cannot find /images node (%d)\n", images);
- /* Extract System Firmware (SYSFW) image from FIT */
- ret = fit_get_data_by_name(fit, images, SYSFW_FIRMWARE,
&sysfw_addr, &sysfw_size);
- if (ret < 0)
panic("Error accessing %s node in FIT (%d)\n", SYSFW_FIRMWARE,
ret);
- /*
* Start up system controller firmware
*
* It is assumed that remoteproc device 0 is the corresponding
* system-controller that runs SYSFW. Make sure DT reflects the same.
*/
- ret = rproc_dev_init(0);
- if (ret)
panic("rproc failed to be initialized (%d)\n", ret);
- ret = rproc_load(0, (ulong)sysfw_addr, (ulong)sysfw_size);
- if (ret)
panic("Firmware failed to start on rproc (%d)\n", ret);
- ret = rproc_start(0);
- if (ret)
panic("Firmware init failed on rproc (%d)\n", ret);
+}
+static void k3_sysfw_configure_using_fit(void *fit,
struct ti_sci_handle *ti_sci)
+{
- struct ti_sci_board_ops *board_ops = &ti_sci->ops.board_ops;
- int images;
- const void *cfg_fragment_addr;
- size_t cfg_fragment_size;
- int ret;
- /* Find the node holding the images information */
- images = fdt_path_offset(fit, FIT_IMAGES_PATH);
- if (images < 0)
panic("Cannot find /images node (%d)\n", images);
- /* Extract board configuration from FIT */
- ret = fit_get_data_by_name(fit, images, SYSFW_CFG_BOARD,
&cfg_fragment_addr, &cfg_fragment_size);
- if (ret < 0)
panic("Error accessing %s node in FIT (%d)\n", SYSFW_CFG_BOARD,
ret);
- /* Apply board configuration to SYSFW */
- ret = board_ops->board_config(ti_sci,
(u64)(u32)cfg_fragment_addr,
(u32)cfg_fragment_size);
- if (ret)
panic("Failed to set board configuration (%d)\n", ret);
- /* Extract power/clock (PM) specific configuration from FIT */
- ret = fit_get_data_by_name(fit, images, SYSFW_CFG_PM,
&cfg_fragment_addr, &cfg_fragment_size);
- if (ret < 0)
panic("Error accessing %s node in FIT (%d)\n", SYSFW_CFG_PM,
ret);
- /* Apply power/clock (PM) specific configuration to SYSFW */
- ret = board_ops->board_config_pm(ti_sci,
(u64)(u32)cfg_fragment_addr,
(u32)cfg_fragment_size);
- if (ret)
panic("Failed to set board PM configuration (%d)\n", ret);
- /* Extract resource management (RM) specific configuration from FIT */
- ret = fit_get_data_by_name(fit, images, SYSFW_CFG_RM,
&cfg_fragment_addr, &cfg_fragment_size);
- if (ret < 0)
panic("Error accessing %s node in FIT (%d)\n", SYSFW_CFG_RM,
ret);
- /* Apply resource management (RM) configuration to SYSFW */
- ret = board_ops->board_config_rm(ti_sci,
(u64)(u32)cfg_fragment_addr,
(u32)cfg_fragment_size);
- if (ret)
panic("Failed to set board RM configuration (%d)\n", ret);
- /* Extract security specific configuration from FIT */
- ret = fit_get_data_by_name(fit, images, SYSFW_CFG_SEC,
&cfg_fragment_addr, &cfg_fragment_size);
- if (ret < 0)
panic("Error accessing %s node in FIT (%d)\n", SYSFW_CFG_SEC,
ret);
- /* Apply security configuration to SYSFW */
- ret = board_ops->board_config_security(ti_sci,
(u64)(u32)cfg_fragment_addr,
(u32)cfg_fragment_size);
- if (ret)
panic("Failed to set board security configuration (%d)\n",
ret);
+}
+void k3_sysfw_loader(void (*config_pm_done_callback)(void)) +{
- struct spl_image_info spl_image = { 0 };
- struct spl_boot_device bootdev = { 0 };
- struct ti_sci_handle *ti_sci;
- int ret;
- /* Reserve a block of aligned memory for loading the SYSFW image */
- sysfw_load_address = memalign(ARCH_DMA_MINALIGN,
CONFIG_K3_SYSFW_IMAGE_SIZE_MAX);
- if (!sysfw_load_address)
panic("Error allocating %u bytes of memory for SYSFW image\n",
CONFIG_K3_SYSFW_IMAGE_SIZE_MAX);
- debug("%s: allocated %u bytes at 0x%p\n", __func__,
CONFIG_K3_SYSFW_IMAGE_SIZE_MAX, sysfw_load_address);
- /* Set load address for legacy modes that bypass spl_get_load_buffer */
- spl_image.load_addr = (uintptr_t)sysfw_load_address;
- bootdev.boot_device = spl_boot_device();
- /* Load combined System Controller firmware and config data image */
- switch (bootdev.boot_device) {
+#if CONFIG_IS_ENABLED(MMC_SUPPORT)
- case BOOT_DEVICE_MMC1:
- case BOOT_DEVICE_MMC2:
- case BOOT_DEVICE_MMC2_2:
ret = spl_mmc_load(&spl_image, &bootdev,
+#ifdef CONFIG_K3_SYSFW_IMAGE_NAME
CONFIG_K3_SYSFW_IMAGE_NAME,
+#else
NULL,
+#endif +#ifdef CONFIG_K3_SYSFW_IMAGE_MMCSD_RAW_MODE_PART
CONFIG_K3_SYSFW_IMAGE_MMCSD_RAW_MODE_PART,
+#else
0,
+#endif +#ifdef CONFIG_K3_SYSFW_IMAGE_MMCSD_RAW_MODE_SECT
CONFIG_K3_SYSFW_IMAGE_MMCSD_RAW_MODE_SECT);
+#else
0);
+#endif
break;
+#endif
- default:
panic("Loading SYSFW image from device %u not supported!\n",
bootdev.boot_device);
- }
- if (ret)
panic("Error %d occurred during loading SYSFW image!\n", ret);
- /*
* Now that SYSFW got loaded set helper flag to restore regular SPL
* loader behavior so we can later boot into the next stage as expected.
*/
- sysfw_loaded = true;
- /* Ensure the SYSFW image is in FIT format */
- if (image_get_magic((const image_header_t *)sysfw_load_address) !=
FDT_MAGIC)
panic("SYSFW image not in FIT format!\n");
- /* Extract and start SYSFW */
- k3_sysfw_load_using_fit(sysfw_load_address);
- /* Get handle for accessing SYSFW services */
- ti_sci = get_ti_sci_handle();
- /* Parse and apply the different SYSFW configuration fragments */
- k3_sysfw_configure_using_fit(sysfw_load_address, ti_sci);
- /*
* Now that all clocks and PM aspects are setup, invoke a user-
* provided callback function. Usually this callback would be used
* to setup or re-configure the U-Boot console UART.
*/
- if (config_pm_done_callback)
config_pm_done_callback();
- /* Output System Firmware version info */
- printf("SYSFW ABI: %d.%d (firmware rev 0x%04x '%.*s')\n",
ti_sci->version.abi_major, ti_sci->version.abi_minor,
ti_sci->version.firmware_revision,
sizeof(ti_sci->version.firmware_description),
ti_sci->version.firmware_description);
+} +#endif

On 07.05.19 21:17, Andreas Dannenberg wrote:
Hi Simon,
On Tue, May 07, 2019 at 08:16:07PM +0200, Simon Goldschmidt wrote:
On 07.05.19 19:25, Andreas Dannenberg wrote:
Introduce a framework that allows loading the System Firmware (SYSFW) binary as well as the associated configuration data from an image tree blob named "sysfw.itb" from an FS-based MMC boot media or from an MMC RAW mode partition or sector.
To simplify the handling of and loading from the different boot media we tap into the existing U-Boot SPL framework usually used for loading U-Boot by building on an earlier commit that exposes some of that functionality.
Note that this initial implementation only supports FS and RAW-based eMMC/SD card boot.
Signed-off-by: Andreas Dannenberg dannenberg@ti.com Signed-off-by: Lokesh Vutla lokeshvutla@ti.com
Without having a too deep understanding of this, all this stuff looks like it would be similar to drivers/misc/fs_loader.c?
Could it build on top of that?
Yes and no. Can you please review the associated cover letter, it addresses this very question which I expected to get raised.
Ah, ok. Indeed I seemed to skip those lines when reading the cover letter, sorry.
Regards, Simon
Thanks, Andreas
Regards, Simon
arch/arm/mach-k3/Kconfig | 40 +++ arch/arm/mach-k3/Makefile | 1 + arch/arm/mach-k3/include/mach/sysfw-loader.h | 12 + arch/arm/mach-k3/sysfw-loader.c | 263 +++++++++++++++++++ 4 files changed, 316 insertions(+) create mode 100644 arch/arm/mach-k3/include/mach/sysfw-loader.h create mode 100644 arch/arm/mach-k3/sysfw-loader.c
diff --git a/arch/arm/mach-k3/Kconfig b/arch/arm/mach-k3/Kconfig index e677a2e01b..f1731dda58 100644 --- a/arch/arm/mach-k3/Kconfig +++ b/arch/arm/mach-k3/Kconfig @@ -58,6 +58,46 @@ config SYS_K3_BOOT_CORE_ID int default 16 +config K3_LOAD_SYSFW
- bool
- depends on SPL
- default n
+config K3_SYSFW_IMAGE_NAME
- string "File name of SYSFW firmware and configuration blob"
- depends on K3_LOAD_SYSFW
- default "sysfw.itb"
- help
Filename of the combined System Firmware and configuration image tree
blob to be loaded when booting from a filesystem.
+config K3_SYSFW_IMAGE_MMCSD_RAW_MODE_SECT
- hex "MMC sector to load SYSFW firmware and configuration blob from"
- depends on K3_LOAD_SYSFW && SYS_MMCSD_RAW_MODE_U_BOOT_USE_SECTOR
- default 0x3600
- help
Address on the MMC to load the combined System Firmware and
configuration image tree blob from, when the MMC is being used
in raw mode. Units: MMC sectors (1 sector = 512 bytes).
+config K3_SYSFW_IMAGE_MMCSD_RAW_MODE_PART
- hex "MMC partition to load SYSFW firmware and configuration blob from"
- depends on K3_LOAD_SYSFW && SYS_MMCSD_RAW_MODE_U_BOOT_USE_PARTITION
- default 2
- help
Partition on the MMC to the combined System Firmware and configuration
image tree blob from, when the MMC is being used in raw mode.
+config K3_SYSFW_IMAGE_SIZE_MAX
- int "Amount of memory dynamically allocated for loading SYSFW blob"
- depends on K3_LOAD_SYSFW
- default 269000
- help
Amount of memory reserved through dynamic allocation at runtime for
loading the combined System Firmware and configuration image tree
blob. Keep it as tight as possible, as this directly affects the
overall SPL memory footprint.
- config SYS_K3_SPL_ATF bool "Start Cortex-A from SPL" depends on SPL && CPU_V7R
diff --git a/arch/arm/mach-k3/Makefile b/arch/arm/mach-k3/Makefile index 0c3a4f7db1..6c895400c2 100644 --- a/arch/arm/mach-k3/Makefile +++ b/arch/arm/mach-k3/Makefile @@ -7,4 +7,5 @@ obj-$(CONFIG_SOC_K3_AM6) += am6_init.o obj-$(CONFIG_ARM64) += arm64-mmu.o obj-$(CONFIG_CPU_V7R) += r5_mpu.o lowlevel_init.o obj-$(CONFIG_TI_SECURE_DEVICE) += security.o +obj-$(CONFIG_K3_LOAD_SYSFW) += sysfw-loader.o obj-y += common.o diff --git a/arch/arm/mach-k3/include/mach/sysfw-loader.h b/arch/arm/mach-k3/include/mach/sysfw-loader.h new file mode 100644 index 0000000000..36eb265348 --- /dev/null +++ b/arch/arm/mach-k3/include/mach/sysfw-loader.h @@ -0,0 +1,12 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ +/*
- Copyright (C) 2019 Texas Instruments Incorporated - http://www.ti.com/
- Andreas Dannenberg dannenberg@ti.com
- */
+#ifndef _SYSFW_LOADER_H_ +#define _SYSFW_LOADER_H_
+void k3_sysfw_loader(void (*config_pm_done_callback)(void));
+#endif diff --git a/arch/arm/mach-k3/sysfw-loader.c b/arch/arm/mach-k3/sysfw-loader.c new file mode 100644 index 0000000000..a222266c27 --- /dev/null +++ b/arch/arm/mach-k3/sysfw-loader.c @@ -0,0 +1,263 @@ +// SPDX-License-Identifier: GPL-2.0+ +/*
- K3: System Firmware Loader
- Copyright (C) 2019 Texas Instruments Incorporated - http://www.ti.com/
- Andreas Dannenberg dannenberg@ti.com
- */
+#include <common.h> +#include <spl.h> +#include <malloc.h> +#include <remoteproc.h> +#include <linux/soc/ti/ti_sci_protocol.h> +#include <asm/arch/sys_proto.h>
+/* Name of the FIT image nodes for SYSFW and its config data */ +#define SYSFW_FIRMWARE "sysfw.bin" +#define SYSFW_CFG_BOARD "board-cfg.bin" +#define SYSFW_CFG_PM "pm-cfg.bin" +#define SYSFW_CFG_RM "rm-cfg.bin" +#define SYSFW_CFG_SEC "sec-cfg.bin"
+#ifdef CONFIG_SPL_BUILD
+static bool sysfw_loaded; +static void *sysfw_load_address;
+/*
- Populate SPL hook to override the default load address used by the SPL
- loader function with a custom address for SYSFW loading.
- */
+struct image_header *spl_get_load_buffer(ssize_t offset, size_t size) +{
- if (sysfw_loaded)
return (struct image_header *)(CONFIG_SYS_TEXT_BASE + offset);
- else if (sysfw_load_address)
return sysfw_load_address;
- else
panic("SYSFW load address not defined!");
+}
+/*
- Populate SPL hook to skip the default SPL loader FIT post-processing steps
- during SYSFW loading and return to the calling function so we can perform
- our own custom processing.
- */
+bool spl_load_simple_fit_skip_processing(void) +{
- return !sysfw_loaded;
+}
+static int fit_get_data_by_name(const void *fit, int images, const char *name,
const void **addr, size_t *size)
+{
- int node_offset;
- node_offset = fdt_subnode_offset(fit, images, name);
- if (node_offset < 0)
return -ENOENT;
- return fit_image_get_data(fit, node_offset, addr, size);
+}
+static void k3_sysfw_load_using_fit(void *fit) +{
- int images;
- const void *sysfw_addr;
- size_t sysfw_size;
- int ret;
- /* Find the node holding the images information */
- images = fdt_path_offset(fit, FIT_IMAGES_PATH);
- if (images < 0)
panic("Cannot find /images node (%d)\n", images);
- /* Extract System Firmware (SYSFW) image from FIT */
- ret = fit_get_data_by_name(fit, images, SYSFW_FIRMWARE,
&sysfw_addr, &sysfw_size);
- if (ret < 0)
panic("Error accessing %s node in FIT (%d)\n", SYSFW_FIRMWARE,
ret);
- /*
* Start up system controller firmware
*
* It is assumed that remoteproc device 0 is the corresponding
* system-controller that runs SYSFW. Make sure DT reflects the same.
*/
- ret = rproc_dev_init(0);
- if (ret)
panic("rproc failed to be initialized (%d)\n", ret);
- ret = rproc_load(0, (ulong)sysfw_addr, (ulong)sysfw_size);
- if (ret)
panic("Firmware failed to start on rproc (%d)\n", ret);
- ret = rproc_start(0);
- if (ret)
panic("Firmware init failed on rproc (%d)\n", ret);
+}
+static void k3_sysfw_configure_using_fit(void *fit,
struct ti_sci_handle *ti_sci)
+{
- struct ti_sci_board_ops *board_ops = &ti_sci->ops.board_ops;
- int images;
- const void *cfg_fragment_addr;
- size_t cfg_fragment_size;
- int ret;
- /* Find the node holding the images information */
- images = fdt_path_offset(fit, FIT_IMAGES_PATH);
- if (images < 0)
panic("Cannot find /images node (%d)\n", images);
- /* Extract board configuration from FIT */
- ret = fit_get_data_by_name(fit, images, SYSFW_CFG_BOARD,
&cfg_fragment_addr, &cfg_fragment_size);
- if (ret < 0)
panic("Error accessing %s node in FIT (%d)\n", SYSFW_CFG_BOARD,
ret);
- /* Apply board configuration to SYSFW */
- ret = board_ops->board_config(ti_sci,
(u64)(u32)cfg_fragment_addr,
(u32)cfg_fragment_size);
- if (ret)
panic("Failed to set board configuration (%d)\n", ret);
- /* Extract power/clock (PM) specific configuration from FIT */
- ret = fit_get_data_by_name(fit, images, SYSFW_CFG_PM,
&cfg_fragment_addr, &cfg_fragment_size);
- if (ret < 0)
panic("Error accessing %s node in FIT (%d)\n", SYSFW_CFG_PM,
ret);
- /* Apply power/clock (PM) specific configuration to SYSFW */
- ret = board_ops->board_config_pm(ti_sci,
(u64)(u32)cfg_fragment_addr,
(u32)cfg_fragment_size);
- if (ret)
panic("Failed to set board PM configuration (%d)\n", ret);
- /* Extract resource management (RM) specific configuration from FIT */
- ret = fit_get_data_by_name(fit, images, SYSFW_CFG_RM,
&cfg_fragment_addr, &cfg_fragment_size);
- if (ret < 0)
panic("Error accessing %s node in FIT (%d)\n", SYSFW_CFG_RM,
ret);
- /* Apply resource management (RM) configuration to SYSFW */
- ret = board_ops->board_config_rm(ti_sci,
(u64)(u32)cfg_fragment_addr,
(u32)cfg_fragment_size);
- if (ret)
panic("Failed to set board RM configuration (%d)\n", ret);
- /* Extract security specific configuration from FIT */
- ret = fit_get_data_by_name(fit, images, SYSFW_CFG_SEC,
&cfg_fragment_addr, &cfg_fragment_size);
- if (ret < 0)
panic("Error accessing %s node in FIT (%d)\n", SYSFW_CFG_SEC,
ret);
- /* Apply security configuration to SYSFW */
- ret = board_ops->board_config_security(ti_sci,
(u64)(u32)cfg_fragment_addr,
(u32)cfg_fragment_size);
- if (ret)
panic("Failed to set board security configuration (%d)\n",
ret);
+}
+void k3_sysfw_loader(void (*config_pm_done_callback)(void)) +{
- struct spl_image_info spl_image = { 0 };
- struct spl_boot_device bootdev = { 0 };
- struct ti_sci_handle *ti_sci;
- int ret;
- /* Reserve a block of aligned memory for loading the SYSFW image */
- sysfw_load_address = memalign(ARCH_DMA_MINALIGN,
CONFIG_K3_SYSFW_IMAGE_SIZE_MAX);
- if (!sysfw_load_address)
panic("Error allocating %u bytes of memory for SYSFW image\n",
CONFIG_K3_SYSFW_IMAGE_SIZE_MAX);
- debug("%s: allocated %u bytes at 0x%p\n", __func__,
CONFIG_K3_SYSFW_IMAGE_SIZE_MAX, sysfw_load_address);
- /* Set load address for legacy modes that bypass spl_get_load_buffer */
- spl_image.load_addr = (uintptr_t)sysfw_load_address;
- bootdev.boot_device = spl_boot_device();
- /* Load combined System Controller firmware and config data image */
- switch (bootdev.boot_device) {
+#if CONFIG_IS_ENABLED(MMC_SUPPORT)
- case BOOT_DEVICE_MMC1:
- case BOOT_DEVICE_MMC2:
- case BOOT_DEVICE_MMC2_2:
ret = spl_mmc_load(&spl_image, &bootdev,
+#ifdef CONFIG_K3_SYSFW_IMAGE_NAME
CONFIG_K3_SYSFW_IMAGE_NAME,
+#else
NULL,
+#endif +#ifdef CONFIG_K3_SYSFW_IMAGE_MMCSD_RAW_MODE_PART
CONFIG_K3_SYSFW_IMAGE_MMCSD_RAW_MODE_PART,
+#else
0,
+#endif +#ifdef CONFIG_K3_SYSFW_IMAGE_MMCSD_RAW_MODE_SECT
CONFIG_K3_SYSFW_IMAGE_MMCSD_RAW_MODE_SECT);
+#else
0);
+#endif
break;
+#endif
- default:
panic("Loading SYSFW image from device %u not supported!\n",
bootdev.boot_device);
- }
- if (ret)
panic("Error %d occurred during loading SYSFW image!\n", ret);
- /*
* Now that SYSFW got loaded set helper flag to restore regular SPL
* loader behavior so we can later boot into the next stage as expected.
*/
- sysfw_loaded = true;
- /* Ensure the SYSFW image is in FIT format */
- if (image_get_magic((const image_header_t *)sysfw_load_address) !=
FDT_MAGIC)
panic("SYSFW image not in FIT format!\n");
- /* Extract and start SYSFW */
- k3_sysfw_load_using_fit(sysfw_load_address);
- /* Get handle for accessing SYSFW services */
- ti_sci = get_ti_sci_handle();
- /* Parse and apply the different SYSFW configuration fragments */
- k3_sysfw_configure_using_fit(sysfw_load_address, ti_sci);
- /*
* Now that all clocks and PM aspects are setup, invoke a user-
* provided callback function. Usually this callback would be used
* to setup or re-configure the U-Boot console UART.
*/
- if (config_pm_done_callback)
config_pm_done_callback();
- /* Output System Firmware version info */
- printf("SYSFW ABI: %d.%d (firmware rev 0x%04x '%.*s')\n",
ti_sci->version.abi_major, ti_sci->version.abi_minor,
ti_sci->version.firmware_revision,
sizeof(ti_sci->version.firmware_description),
ti_sci->version.firmware_description);
+} +#endif

On Tue, May 07, 2019 at 12:25:33PM -0500, Andreas Dannenberg wrote:
Introduce a framework that allows loading the System Firmware (SYSFW) binary as well as the associated configuration data from an image tree blob named "sysfw.itb" from an FS-based MMC boot media or from an MMC RAW mode partition or sector.
To simplify the handling of and loading from the different boot media we tap into the existing U-Boot SPL framework usually used for loading U-Boot by building on an earlier commit that exposes some of that functionality.
Note that this initial implementation only supports FS and RAW-based eMMC/SD card boot.
[snip]
diff --git a/arch/arm/mach-k3/Kconfig b/arch/arm/mach-k3/Kconfig index e677a2e01b..f1731dda58 100644 --- a/arch/arm/mach-k3/Kconfig +++ b/arch/arm/mach-k3/Kconfig @@ -58,6 +58,46 @@ config SYS_K3_BOOT_CORE_ID int default 16
+config K3_LOAD_SYSFW
- bool
- depends on SPL
- default n
'n' is already default, you can drop this.
[snip]
+config K3_SYSFW_IMAGE_SIZE_MAX
- int "Amount of memory dynamically allocated for loading SYSFW blob"
- depends on K3_LOAD_SYSFW
- default 269000
- help
Amount of memory reserved through dynamic allocation at runtime for
loading the combined System Firmware and configuration image tree
blob. Keep it as tight as possible, as this directly affects the
overall SPL memory footprint.
This is missing a unit, and is 'int' really the best choice here (and really, I guess, 262.6KiB as a default) ?
[snip]
diff --git a/arch/arm/mach-k3/Makefile b/arch/arm/mach-k3/Makefile index 0c3a4f7db1..6c895400c2 100644 --- a/arch/arm/mach-k3/Makefile +++ b/arch/arm/mach-k3/Makefile @@ -7,4 +7,5 @@ obj-$(CONFIG_SOC_K3_AM6) += am6_init.o obj-$(CONFIG_ARM64) += arm64-mmu.o obj-$(CONFIG_CPU_V7R) += r5_mpu.o lowlevel_init.o obj-$(CONFIG_TI_SECURE_DEVICE) += security.o +obj-$(CONFIG_K3_LOAD_SYSFW) += sysfw-loader.o obj-y += common.o
[snip]
diff --git a/arch/arm/mach-k3/sysfw-loader.c b/arch/arm/mach-k3/sysfw-loader.c new file mode 100644 index 0000000000..a222266c27 --- /dev/null +++ b/arch/arm/mach-k3/sysfw-loader.c @@ -0,0 +1,263 @@
[snip]
+#ifdef CONFIG_SPL_BUILD
[snip of the whole body of the file]
+#endif
We should be using something else in the Makefile, typically: obj-$(CONFIG_SPL_BUILD) += sysfw-loader.o should work.

Hi Tom,
On Wed, May 15, 2019 at 11:17:22AM -0400, Tom Rini wrote:
On Tue, May 07, 2019 at 12:25:33PM -0500, Andreas Dannenberg wrote:
Introduce a framework that allows loading the System Firmware (SYSFW) binary as well as the associated configuration data from an image tree blob named "sysfw.itb" from an FS-based MMC boot media or from an MMC RAW mode partition or sector.
To simplify the handling of and loading from the different boot media we tap into the existing U-Boot SPL framework usually used for loading U-Boot by building on an earlier commit that exposes some of that functionality.
Note that this initial implementation only supports FS and RAW-based eMMC/SD card boot.
[snip]
diff --git a/arch/arm/mach-k3/Kconfig b/arch/arm/mach-k3/Kconfig index e677a2e01b..f1731dda58 100644 --- a/arch/arm/mach-k3/Kconfig +++ b/arch/arm/mach-k3/Kconfig @@ -58,6 +58,46 @@ config SYS_K3_BOOT_CORE_ID int default 16
+config K3_LOAD_SYSFW
- bool
- depends on SPL
- default n
'n' is already default, you can drop this.
Ok sure.
[snip]
+config K3_SYSFW_IMAGE_SIZE_MAX
- int "Amount of memory dynamically allocated for loading SYSFW blob"
- depends on K3_LOAD_SYSFW
- default 269000
- help
Amount of memory reserved through dynamic allocation at runtime for
loading the combined System Firmware and configuration image tree
blob. Keep it as tight as possible, as this directly affects the
overall SPL memory footprint.
This is missing a unit, and is 'int' really the best choice here (and really, I guess, 262.6KiB as a default) ?
Will add a unit.
As for the specific value, in our R5 SPL memory is very very tight. The value used here is basically used for a malloc(), and any extra byte allocated will be "wasted" and not available for stack etc. Also our SYSFW image that is loaded is fixed size (except some +/-100 odd bytes if the configuration data is changed that's part of the same SYSFW.ITB blob), so a rather tailored size makes sense here.
[snip]
diff --git a/arch/arm/mach-k3/Makefile b/arch/arm/mach-k3/Makefile index 0c3a4f7db1..6c895400c2 100644 --- a/arch/arm/mach-k3/Makefile +++ b/arch/arm/mach-k3/Makefile @@ -7,4 +7,5 @@ obj-$(CONFIG_SOC_K3_AM6) += am6_init.o obj-$(CONFIG_ARM64) += arm64-mmu.o obj-$(CONFIG_CPU_V7R) += r5_mpu.o lowlevel_init.o obj-$(CONFIG_TI_SECURE_DEVICE) += security.o +obj-$(CONFIG_K3_LOAD_SYSFW) += sysfw-loader.o obj-y += common.o
[snip]
diff --git a/arch/arm/mach-k3/sysfw-loader.c b/arch/arm/mach-k3/sysfw-loader.c new file mode 100644 index 0000000000..a222266c27 --- /dev/null +++ b/arch/arm/mach-k3/sysfw-loader.c @@ -0,0 +1,263 @@
[snip]
+#ifdef CONFIG_SPL_BUILD
[snip of the whole body of the file]
+#endif
We should be using something else in the Makefile, typically: obj-$(CONFIG_SPL_BUILD) += sysfw-loader.o should work.
Well, it won't work like this. We need to make the building of the SYSFW loader code depending on a CONFIG. This is because for K3 family devices we build the U-Boot tree into three distinct images [1]:
1) SPL image for running on an R5 (our first stage) 2) SPL image for running on an A53 (our second stage) 3) U-Boot (proper) image for running on an A53 (third stage)
With the change you proposed sysfw-loader.o will get build for A53 SPL where it is neither needed nor wanted, causing build failures.
What we would need is something like (CONFIG_K3_LOAD_SYSFW && CONFIG_SPL_BUILD) to conditionally build that object if we want to get rid of the #ifdef/#endif in sysfw-loader.c I suppose.
Thanks, Andreas
[1] https://github.com/u-boot/u-boot/blob/master/board/ti/am65x/README

On Wed, May 15, 2019 at 04:39:22PM -0500, Andreas Dannenberg wrote:
Hi Tom,
On Wed, May 15, 2019 at 11:17:22AM -0400, Tom Rini wrote:
On Tue, May 07, 2019 at 12:25:33PM -0500, Andreas Dannenberg wrote:
Introduce a framework that allows loading the System Firmware (SYSFW) binary as well as the associated configuration data from an image tree blob named "sysfw.itb" from an FS-based MMC boot media or from an MMC RAW mode partition or sector.
To simplify the handling of and loading from the different boot media we tap into the existing U-Boot SPL framework usually used for loading U-Boot by building on an earlier commit that exposes some of that functionality.
Note that this initial implementation only supports FS and RAW-based eMMC/SD card boot.
[snip]
diff --git a/arch/arm/mach-k3/Kconfig b/arch/arm/mach-k3/Kconfig index e677a2e01b..f1731dda58 100644 --- a/arch/arm/mach-k3/Kconfig +++ b/arch/arm/mach-k3/Kconfig @@ -58,6 +58,46 @@ config SYS_K3_BOOT_CORE_ID int default 16
+config K3_LOAD_SYSFW
- bool
- depends on SPL
- default n
'n' is already default, you can drop this.
Ok sure.
[snip]
+config K3_SYSFW_IMAGE_SIZE_MAX
- int "Amount of memory dynamically allocated for loading SYSFW blob"
- depends on K3_LOAD_SYSFW
- default 269000
- help
Amount of memory reserved through dynamic allocation at runtime for
loading the combined System Firmware and configuration image tree
blob. Keep it as tight as possible, as this directly affects the
overall SPL memory footprint.
This is missing a unit, and is 'int' really the best choice here (and really, I guess, 262.6KiB as a default) ?
Will add a unit.
As for the specific value, in our R5 SPL memory is very very tight. The value used here is basically used for a malloc(), and any extra byte allocated will be "wasted" and not available for stack etc. Also our SYSFW image that is loaded is fixed size (except some +/-100 odd bytes if the configuration data is changed that's part of the same SYSFW.ITB blob), so a rather tailored size makes sense here.
Right, that makes sense. But how did you get to that not-exactly-"round" number rather than say 0x41A00 or some other slightly smaller value in hex? If 0x41AC8 is right, then, OK, it's right. It just seems strange at first.
[snip]
diff --git a/arch/arm/mach-k3/Makefile b/arch/arm/mach-k3/Makefile index 0c3a4f7db1..6c895400c2 100644 --- a/arch/arm/mach-k3/Makefile +++ b/arch/arm/mach-k3/Makefile @@ -7,4 +7,5 @@ obj-$(CONFIG_SOC_K3_AM6) += am6_init.o obj-$(CONFIG_ARM64) += arm64-mmu.o obj-$(CONFIG_CPU_V7R) += r5_mpu.o lowlevel_init.o obj-$(CONFIG_TI_SECURE_DEVICE) += security.o +obj-$(CONFIG_K3_LOAD_SYSFW) += sysfw-loader.o obj-y += common.o
[snip]
diff --git a/arch/arm/mach-k3/sysfw-loader.c b/arch/arm/mach-k3/sysfw-loader.c new file mode 100644 index 0000000000..a222266c27 --- /dev/null +++ b/arch/arm/mach-k3/sysfw-loader.c @@ -0,0 +1,263 @@
[snip]
+#ifdef CONFIG_SPL_BUILD
[snip of the whole body of the file]
+#endif
We should be using something else in the Makefile, typically: obj-$(CONFIG_SPL_BUILD) += sysfw-loader.o should work.
Well, it won't work like this. We need to make the building of the SYSFW loader code depending on a CONFIG. This is because for K3 family devices we build the U-Boot tree into three distinct images [1]:
Then you do: ifeq ($(CONFIG_SPL_BUILD),y) obj-$(CONFIG_K3_LOAD_SYSFW) += sysfs-loader.o endif
As seen in other places, as we do not whole-body ifdef code. Thanks!

Hi Tom,
On Wed, May 15, 2019 at 05:50:31PM -0400, Tom Rini wrote:
On Wed, May 15, 2019 at 04:39:22PM -0500, Andreas Dannenberg wrote:
Hi Tom,
On Wed, May 15, 2019 at 11:17:22AM -0400, Tom Rini wrote:
On Tue, May 07, 2019 at 12:25:33PM -0500, Andreas Dannenberg wrote:
Introduce a framework that allows loading the System Firmware (SYSFW) binary as well as the associated configuration data from an image tree blob named "sysfw.itb" from an FS-based MMC boot media or from an MMC RAW mode partition or sector.
To simplify the handling of and loading from the different boot media we tap into the existing U-Boot SPL framework usually used for loading U-Boot by building on an earlier commit that exposes some of that functionality.
Note that this initial implementation only supports FS and RAW-based eMMC/SD card boot.
[snip]
diff --git a/arch/arm/mach-k3/Kconfig b/arch/arm/mach-k3/Kconfig index e677a2e01b..f1731dda58 100644 --- a/arch/arm/mach-k3/Kconfig +++ b/arch/arm/mach-k3/Kconfig @@ -58,6 +58,46 @@ config SYS_K3_BOOT_CORE_ID int default 16
+config K3_LOAD_SYSFW
- bool
- depends on SPL
- default n
'n' is already default, you can drop this.
Ok sure.
[snip]
+config K3_SYSFW_IMAGE_SIZE_MAX
- int "Amount of memory dynamically allocated for loading SYSFW blob"
- depends on K3_LOAD_SYSFW
- default 269000
- help
Amount of memory reserved through dynamic allocation at runtime for
loading the combined System Firmware and configuration image tree
blob. Keep it as tight as possible, as this directly affects the
overall SPL memory footprint.
This is missing a unit, and is 'int' really the best choice here (and really, I guess, 262.6KiB as a default) ?
I think 'int' is a more natural fit as this is to reserve memory for the 'sysfw.itb' blob we load from media. This blob is build outside U-Boot using the "System Firmware Image Generator" project [1], and if after build somebody does an 'll' in the build directory the file size would show up as decimal, and that's what needs to fit inside K3_SYSFW_IMAGE_SIZE_MAX.
Will add a unit.
As for the specific value, in our R5 SPL memory is very very tight. The value used here is basically used for a malloc(), and any extra byte allocated will be "wasted" and not available for stack etc. Also our SYSFW image that is loaded is fixed size (except some +/-100 odd bytes if the configuration data is changed that's part of the same SYSFW.ITB blob), so a rather tailored size makes sense here.
Right, that makes sense. But how did you get to that not-exactly-"round" number rather than say 0x41A00 or some other slightly smaller value in hex? If 0x41AC8 is right, then, OK, it's right. It just seems strange at first.
The sysfw.itb blob consumed by the SYSFW loader comprises a fixed component (the SYSFW itself), plus a few smaller chunks of variable data containing user configuration data. During initial development the combined size of this ITB was about 264,900 bytes, and 4KB was added as slack to accommodate configuration changes, resulting in what looks like the arbitrary number under discussion. The sysfw.itb blob has actually since grown in size but there is still plenty of space for it to further grow if needed. Since we use this value already in production since last year with no issues I'd rather leave it alone (due to using stack based malloc in R5 SPL increasing that value would directly decrease available stack space with our R5 SPL memory layout where the stack is growing down towards the R5 SPL image itself).
[snip]
diff --git a/arch/arm/mach-k3/Makefile b/arch/arm/mach-k3/Makefile index 0c3a4f7db1..6c895400c2 100644 --- a/arch/arm/mach-k3/Makefile +++ b/arch/arm/mach-k3/Makefile @@ -7,4 +7,5 @@ obj-$(CONFIG_SOC_K3_AM6) += am6_init.o obj-$(CONFIG_ARM64) += arm64-mmu.o obj-$(CONFIG_CPU_V7R) += r5_mpu.o lowlevel_init.o obj-$(CONFIG_TI_SECURE_DEVICE) += security.o +obj-$(CONFIG_K3_LOAD_SYSFW) += sysfw-loader.o obj-y += common.o
[snip]
diff --git a/arch/arm/mach-k3/sysfw-loader.c b/arch/arm/mach-k3/sysfw-loader.c new file mode 100644 index 0000000000..a222266c27 --- /dev/null +++ b/arch/arm/mach-k3/sysfw-loader.c @@ -0,0 +1,263 @@
[snip]
+#ifdef CONFIG_SPL_BUILD
[snip of the whole body of the file]
+#endif
We should be using something else in the Makefile, typically: obj-$(CONFIG_SPL_BUILD) += sysfw-loader.o should work.
Well, it won't work like this. We need to make the building of the SYSFW loader code depending on a CONFIG. This is because for K3 family devices we build the U-Boot tree into three distinct images [1]:
Then you do: ifeq ($(CONFIG_SPL_BUILD),y) obj-$(CONFIG_K3_LOAD_SYSFW) += sysfs-loader.o endif
As seen in other places, as we do not whole-body ifdef code. Thanks!
Great suggestion, works like a champ.
-- Andreas Dannenberg Texas Instruments Inc
[1] http://git.ti.com/gitweb/?p=processor-firmware/system-firmware-image-gen.git...

Hi Tom,
On Thu, May 16, 2019 at 10:47:30AM -0500, Andreas Dannenberg wrote:
Hi Tom,
On Wed, May 15, 2019 at 05:50:31PM -0400, Tom Rini wrote:
On Wed, May 15, 2019 at 04:39:22PM -0500, Andreas Dannenberg wrote:
Hi Tom,
On Wed, May 15, 2019 at 11:17:22AM -0400, Tom Rini wrote:
On Tue, May 07, 2019 at 12:25:33PM -0500, Andreas Dannenberg wrote:
Introduce a framework that allows loading the System Firmware (SYSFW) binary as well as the associated configuration data from an image tree blob named "sysfw.itb" from an FS-based MMC boot media or from an MMC RAW mode partition or sector.
To simplify the handling of and loading from the different boot media we tap into the existing U-Boot SPL framework usually used for loading U-Boot by building on an earlier commit that exposes some of that functionality.
Note that this initial implementation only supports FS and RAW-based eMMC/SD card boot.
[snip]
diff --git a/arch/arm/mach-k3/Kconfig b/arch/arm/mach-k3/Kconfig index e677a2e01b..f1731dda58 100644 --- a/arch/arm/mach-k3/Kconfig +++ b/arch/arm/mach-k3/Kconfig @@ -58,6 +58,46 @@ config SYS_K3_BOOT_CORE_ID int default 16
+config K3_LOAD_SYSFW
- bool
- depends on SPL
- default n
'n' is already default, you can drop this.
Ok sure.
[snip]
+config K3_SYSFW_IMAGE_SIZE_MAX
- int "Amount of memory dynamically allocated for loading SYSFW blob"
- depends on K3_LOAD_SYSFW
- default 269000
- help
Amount of memory reserved through dynamic allocation at runtime for
loading the combined System Firmware and configuration image tree
blob. Keep it as tight as possible, as this directly affects the
overall SPL memory footprint.
This is missing a unit, and is 'int' really the best choice here (and really, I guess, 262.6KiB as a default) ?
I think 'int' is a more natural fit as this is to reserve memory for the 'sysfw.itb' blob we load from media. This blob is build outside U-Boot using the "System Firmware Image Generator" project [1], and if after build somebody does an 'll' in the build directory the file size would show up as decimal, and that's what needs to fit inside K3_SYSFW_IMAGE_SIZE_MAX.
Will add a unit.
As for the specific value, in our R5 SPL memory is very very tight. The value used here is basically used for a malloc(), and any extra byte allocated will be "wasted" and not available for stack etc. Also our SYSFW image that is loaded is fixed size (except some +/-100 odd bytes if the configuration data is changed that's part of the same SYSFW.ITB blob), so a rather tailored size makes sense here.
Right, that makes sense. But how did you get to that not-exactly-"round" number rather than say 0x41A00 or some other slightly smaller value in hex? If 0x41AC8 is right, then, OK, it's right. It just seems strange at first.
The sysfw.itb blob consumed by the SYSFW loader comprises a fixed component (the SYSFW itself), plus a few smaller chunks of variable data containing user configuration data. During initial development the combined size of this ITB was about 264,900 bytes, and 4KB was added as slack to accommodate configuration changes, resulting in what looks like the arbitrary number under discussion. The sysfw.itb blob has actually since grown in size but there is still plenty of space for it to further grow if needed. Since we use this value already in production since last year with no issues I'd rather leave it alone (due to using stack based malloc in R5 SPL increasing that value would directly decrease available stack space with our R5 SPL memory layout where the stack is growing down towards the R5 SPL image itself).
Small clarification, the size of the early malloc pool is of course controlled by CONFIG_SYS_MALLOC_F_LEN with K3_SYSFW_IMAGE_SIZE_MAX using the majority of it. However CONFIG_SYS_MALLOC_F_LEN is dimensioned such to "tightly wrap" both K3_SYSFW_IMAGE_SIZE_MAX and other users of the early malloc pool (fat fs is a major one), so the principle is the same. I'd rather leave K3_SYSFW_IMAGE_SIZE_MAX as it stands.
Some more details on the memory usage to follow...
-- Andreas Dannenberg Texas Instruments Inc

On Thu, May 16, 2019 at 02:14:19PM -0500, Andreas Dannenberg wrote:
Hi Tom,
On Thu, May 16, 2019 at 10:47:30AM -0500, Andreas Dannenberg wrote:
Hi Tom,
On Wed, May 15, 2019 at 05:50:31PM -0400, Tom Rini wrote:
On Wed, May 15, 2019 at 04:39:22PM -0500, Andreas Dannenberg wrote:
Hi Tom,
On Wed, May 15, 2019 at 11:17:22AM -0400, Tom Rini wrote:
On Tue, May 07, 2019 at 12:25:33PM -0500, Andreas Dannenberg wrote:
Introduce a framework that allows loading the System Firmware (SYSFW) binary as well as the associated configuration data from an image tree blob named "sysfw.itb" from an FS-based MMC boot media or from an MMC RAW mode partition or sector.
To simplify the handling of and loading from the different boot media we tap into the existing U-Boot SPL framework usually used for loading U-Boot by building on an earlier commit that exposes some of that functionality.
Note that this initial implementation only supports FS and RAW-based eMMC/SD card boot.
[snip]
diff --git a/arch/arm/mach-k3/Kconfig b/arch/arm/mach-k3/Kconfig index e677a2e01b..f1731dda58 100644 --- a/arch/arm/mach-k3/Kconfig +++ b/arch/arm/mach-k3/Kconfig @@ -58,6 +58,46 @@ config SYS_K3_BOOT_CORE_ID int default 16
+config K3_LOAD_SYSFW
- bool
- depends on SPL
- default n
'n' is already default, you can drop this.
Ok sure.
[snip]
+config K3_SYSFW_IMAGE_SIZE_MAX
- int "Amount of memory dynamically allocated for loading SYSFW blob"
- depends on K3_LOAD_SYSFW
- default 269000
- help
Amount of memory reserved through dynamic allocation at runtime for
loading the combined System Firmware and configuration image tree
blob. Keep it as tight as possible, as this directly affects the
overall SPL memory footprint.
This is missing a unit, and is 'int' really the best choice here (and really, I guess, 262.6KiB as a default) ?
I think 'int' is a more natural fit as this is to reserve memory for the 'sysfw.itb' blob we load from media. This blob is build outside U-Boot using the "System Firmware Image Generator" project [1], and if after build somebody does an 'll' in the build directory the file size would show up as decimal, and that's what needs to fit inside K3_SYSFW_IMAGE_SIZE_MAX.
Will add a unit.
As for the specific value, in our R5 SPL memory is very very tight. The value used here is basically used for a malloc(), and any extra byte allocated will be "wasted" and not available for stack etc. Also our SYSFW image that is loaded is fixed size (except some +/-100 odd bytes if the configuration data is changed that's part of the same SYSFW.ITB blob), so a rather tailored size makes sense here.
Right, that makes sense. But how did you get to that not-exactly-"round" number rather than say 0x41A00 or some other slightly smaller value in hex? If 0x41AC8 is right, then, OK, it's right. It just seems strange at first.
The sysfw.itb blob consumed by the SYSFW loader comprises a fixed component (the SYSFW itself), plus a few smaller chunks of variable data containing user configuration data. During initial development the combined size of this ITB was about 264,900 bytes, and 4KB was added as slack to accommodate configuration changes, resulting in what looks like the arbitrary number under discussion. The sysfw.itb blob has actually since grown in size but there is still plenty of space for it to further grow if needed. Since we use this value already in production since last year with no issues I'd rather leave it alone (due to using stack based malloc in R5 SPL increasing that value would directly decrease available stack space with our R5 SPL memory layout where the stack is growing down towards the R5 SPL image itself).
Small clarification, the size of the early malloc pool is of course controlled by CONFIG_SYS_MALLOC_F_LEN with K3_SYSFW_IMAGE_SIZE_MAX using the majority of it. However CONFIG_SYS_MALLOC_F_LEN is dimensioned such to "tightly wrap" both K3_SYSFW_IMAGE_SIZE_MAX and other users of the early malloc pool (fat fs is a major one), so the principle is the same. I'd rather leave K3_SYSFW_IMAGE_SIZE_MAX as it stands.
Some more details on the memory usage to follow...
That's a very helpful explanation, thanks!

In order to be able to use more advanced driver functionality which often relies on having BSS initialized during early boot prior to relocation several things need to be in place:
1) Memory needs to be available for BSS to use. For this, we locate BSS at the top of the MCU SRAM area, with the stack starting right below it, 2) We need to zero-initialize BSS ourselves which will we do during board_init_f(), 3) We would also like to skip the implicit zero-initialization as part of SPL relocation, so that already initialized variables will carry over post-relocation. We will do this with a separate commit by turning on the respective CONFIG option.
In this commit we also clean up the assignment of the initial SP address as part of the refactoring, taking into account the pre-decrement post- increment nature in which the SP is used on ARM.
Signed-off-by: Andreas Dannenberg dannenberg@ti.com --- arch/arm/mach-k3/am6_init.c | 7 +++++++ include/configs/am65x_evm.h | 25 +++++++++++++++++++++++-- 2 files changed, 30 insertions(+), 2 deletions(-)
diff --git a/arch/arm/mach-k3/am6_init.c b/arch/arm/mach-k3/am6_init.c index 60a580305d..dfa6d60adf 100644 --- a/arch/arm/mach-k3/am6_init.c +++ b/arch/arm/mach-k3/am6_init.c @@ -78,6 +78,13 @@ void board_init_f(ulong dummy)
#ifdef CONFIG_CPU_V7R setup_k3_mpu_regions(); + + /* + * When running SPL on R5 we are using SRAM for BSS to have globals + * and static variables etc. working prior to relocation. Since this + * means we need to self-manage BSS, clear that section now. + */ + memset(__bss_start, 0, __bss_end - __bss_start); #endif
/* Init DM early in-order to invoke system controller */ diff --git a/include/configs/am65x_evm.h b/include/configs/am65x_evm.h index b043bf886b..cff60a8444 100644 --- a/include/configs/am65x_evm.h +++ b/include/configs/am65x_evm.h @@ -19,6 +19,29 @@ #define CONFIG_SYS_SDRAM_BASE1 0x880000000
/* SPL Loader Configuration */ +#ifdef CONFIG_TARGET_AM654_A53_EVM +#define CONFIG_SYS_INIT_SP_ADDR (CONFIG_SPL_TEXT_BASE + \ + CONFIG_SYS_K3_NON_SECURE_MSRAM_SIZE) +#else +/* + * Maximum size in memory allocated to the SPL BSS. Keep it as tight as + * possible (to allow the build to go through), as this directly affects + * our memory footprint. The less we use for BSS the more we have available + * for everything else. + */ +#define CONFIG_SPL_BSS_MAX_SIZE 0x5000 +/* + * Link BSS to be within SPL in a dedicated region located near the top of + * the MCU SRAM, this way making it available also before relocation. Note + * that we are not using the actual top of the MCU SRAM as there is a memory + * location filled in by the boot ROM that we want to read out without any + * interference from the C context. + */ +#define CONFIG_SPL_BSS_START_ADDR (CONFIG_SYS_K3_BOOT_PARAM_TABLE_INDEX -\ + CONFIG_SPL_BSS_MAX_SIZE) +/* Set the stack right below the SPL BSS section */ +#define CONFIG_SYS_INIT_SP_ADDR CONFIG_SPL_BSS_START_ADDR +#endif
#ifdef CONFIG_SYS_K3_SPL_ATF #define CONFIG_SPL_FS_LOAD_PAYLOAD_NAME "tispl.bin" @@ -29,8 +52,6 @@ #endif
#define CONFIG_SPL_MAX_SIZE CONFIG_SYS_K3_MAX_DOWNLODABLE_IMAGE_SIZE -#define CONFIG_SYS_INIT_SP_ADDR (CONFIG_SPL_TEXT_BASE + \ - CONFIG_SYS_K3_NON_SECURE_MSRAM_SIZE - 4)
#define CONFIG_SYS_BOOTM_LEN SZ_64M

Switch to using the full malloc scheme in post-relocation SPL to allow better utilization of available memory for example by allowing memory to get freed. Initially allocate a 16MB-sized region in DDR starting at address 0x84000000 for this purpose.
Signed-off-by: Andreas Dannenberg dannenberg@ti.com --- configs/am65x_evm_r5_defconfig | 1 - configs/am65x_hs_evm_r5_defconfig | 1 - include/configs/am65x_evm.h | 3 +++ 3 files changed, 3 insertions(+), 2 deletions(-)
diff --git a/configs/am65x_evm_r5_defconfig b/configs/am65x_evm_r5_defconfig index 8dce577cf7..3f4134b5f5 100644 --- a/configs/am65x_evm_r5_defconfig +++ b/configs/am65x_evm_r5_defconfig @@ -18,7 +18,6 @@ CONFIG_SPL_LOAD_FIT=y CONFIG_USE_BOOTCOMMAND=y # CONFIG_DISPLAY_CPUINFO is not set CONFIG_SPL_TEXT_BASE=0x41c00000 -CONFIG_SPL_SYS_MALLOC_SIMPLE=y CONFIG_SPL_STACK_R=y CONFIG_SPL_SEPARATE_BSS=y CONFIG_SPL_I2C_SUPPORT=y diff --git a/configs/am65x_hs_evm_r5_defconfig b/configs/am65x_hs_evm_r5_defconfig index 8d5d3590b2..d4d23416cc 100644 --- a/configs/am65x_hs_evm_r5_defconfig +++ b/configs/am65x_hs_evm_r5_defconfig @@ -20,7 +20,6 @@ CONFIG_SPL_FIT_IMAGE_POST_PROCESS=y CONFIG_USE_BOOTCOMMAND=y # CONFIG_DISPLAY_CPUINFO is not set CONFIG_SPL_TEXT_BASE=0x41c00000 -CONFIG_SPL_SYS_MALLOC_SIMPLE=y CONFIG_SPL_STACK_R=y CONFIG_SPL_SEPARATE_BSS=y CONFIG_SPL_I2C_SUPPORT=y diff --git a/include/configs/am65x_evm.h b/include/configs/am65x_evm.h index cff60a8444..a90f38edc9 100644 --- a/include/configs/am65x_evm.h +++ b/include/configs/am65x_evm.h @@ -41,6 +41,9 @@ CONFIG_SPL_BSS_MAX_SIZE) /* Set the stack right below the SPL BSS section */ #define CONFIG_SYS_INIT_SP_ADDR CONFIG_SPL_BSS_START_ADDR +/* Configure R5 SPL post-relocation malloc pool in DDR */ +#define CONFIG_SYS_SPL_MALLOC_START 0x84000000 +#define CONFIG_SYS_SPL_MALLOC_SIZE SZ_16M #endif
#ifdef CONFIG_SYS_K3_SPL_ATF

Use the System Firmware (SYSFW) loader framework to load and start the SYSFW as part of the AM654 early initialization sequence. While at it also initialize the WKUP_UART0 pinmux as it is used by SYSFW to print diagnostic messages.
Signed-off-by: Andreas Dannenberg dannenberg@ti.com --- arch/arm/mach-k3/am6_init.c | 27 ++++++++++++++++++++++++++- board/ti/am65x/Kconfig | 1 + 2 files changed, 27 insertions(+), 1 deletion(-)
diff --git a/arch/arm/mach-k3/am6_init.c b/arch/arm/mach-k3/am6_init.c index dfa6d60adf..08f2eb9438 100644 --- a/arch/arm/mach-k3/am6_init.c +++ b/arch/arm/mach-k3/am6_init.c @@ -10,8 +10,11 @@ #include <asm/io.h> #include <spl.h> #include <asm/arch/hardware.h> +#include <asm/arch/sysfw-loader.h> #include "common.h" #include <dm.h> +#include <dm/uclass-internal.h> +#include <dm/pinctrl.h>
#ifdef CONFIG_SPL_BUILD static void mmr_unlock(u32 base, u32 partition) @@ -63,7 +66,7 @@ static void store_boot_index_from_rom(void)
void board_init_f(ulong dummy) { -#if defined(CONFIG_K3_AM654_DDRSS) +#if defined(CONFIG_K3_LOAD_SYSFW) || defined(CONFIG_K3_AM654_DDRSS) struct udevice *dev; int ret; #endif @@ -90,8 +93,30 @@ void board_init_f(ulong dummy) /* Init DM early in-order to invoke system controller */ spl_early_init();
+#ifdef CONFIG_K3_LOAD_SYSFW + /* + * Process pinctrl for the serial0 a.k.a. WKUP_UART0 module and continue + * regardless of the result of pinctrl. Do this without probing the + * device, but instead by searching the device that would request the + * given sequence number if probed. The UART will be used by the system + * firmware (SYSFW) image for various purposes and SYSFW depends on us + * to initialize its pin settings. + */ + ret = uclass_find_device_by_seq(UCLASS_SERIAL, 0, true, &dev); + if (!ret) + pinctrl_select_state(dev, "default"); + + /* + * Load, start up, and configure system controller firmware. Provide + * the U-Boot console init function to the SYSFW post-PM configuration + * callback hook, effectively switching on (or over) the console + * output. + */ + k3_sysfw_loader(preloader_console_init); +#else /* Prepare console output */ preloader_console_init(); +#endif
#ifdef CONFIG_K3_AM654_DDRSS ret = uclass_get_device(UCLASS_RAM, 0, &dev); diff --git a/board/ti/am65x/Kconfig b/board/ti/am65x/Kconfig index 98172c28f5..60bb834aca 100644 --- a/board/ti/am65x/Kconfig +++ b/board/ti/am65x/Kconfig @@ -18,6 +18,7 @@ config TARGET_AM654_R5_EVM select CPU_V7R select SYS_THUMB_BUILD select SOC_K3_AM6 + select K3_LOAD_SYSFW select K3_AM654_DDRSS imply SYS_K3_SPL_ATF

From: Lokesh Vutla lokeshvutla@ti.com
In order to load the sysfw.itb from a mmc device, clocks should be hard coded to the same value as ROM configured frequency. Clock updates cannot happen at this point as sysfw is not yet available. So updating the clock properties for mmc nodes.
Signed-off-by: Lokesh Vutla lokeshvutla@ti.com Signed-off-by: Andreas Dannenberg dannenberg@ti.com --- arch/arm/dts/k3-am654-r5-base-board.dts | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+)
diff --git a/arch/arm/dts/k3-am654-r5-base-board.dts b/arch/arm/dts/k3-am654-r5-base-board.dts index a07038be70..94bdf57a14 100644 --- a/arch/arm/dts/k3-am654-r5-base-board.dts +++ b/arch/arm/dts/k3-am654-r5-base-board.dts @@ -96,6 +96,12 @@ u-boot,dm-spl; };
+ clk_200mhz: dummy_clock { + compatible = "fixed-clock"; + #clock-cells = <0>; + clock-frequency = <200000000>; + u-boot,dm-spl; + }; };
&dmsc { @@ -137,3 +143,15 @@ pinctrl-names = "default"; pinctrl-0 = <&wkup_vtt_pins_default>; }; + +&sdhci0 { + clock-names = "clk_xin"; + clocks = <&clk_200mhz>; + /delete-property/ power-domains; +}; + +&sdhci1 { + clock-names = "clk_xin"; + clocks = <&clk_200mhz>; + /delete-property/ power-domains; +};

Enable all the relevant configs that enables support for loading sysfw via MMC.
Signed-off-by: Andreas Dannenberg dannenberg@ti.com --- configs/am65x_evm_r5_defconfig | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-)
diff --git a/configs/am65x_evm_r5_defconfig b/configs/am65x_evm_r5_defconfig index 3f4134b5f5..6861a9f05b 100644 --- a/configs/am65x_evm_r5_defconfig +++ b/configs/am65x_evm_r5_defconfig @@ -3,7 +3,7 @@ CONFIG_ARCH_K3=y CONFIG_SPL_GPIO_SUPPORT=y CONFIG_SPL_LIBCOMMON_SUPPORT=y CONFIG_SPL_LIBGENERIC_SUPPORT=y -CONFIG_SYS_MALLOC_F_LEN=0x2000 +CONFIG_SYS_MALLOC_F_LEN=0x55000 CONFIG_SOC_K3_AM6=y CONFIG_TARGET_AM654_R5_EVM=y CONFIG_SPL_MMC_SUPPORT=y @@ -20,6 +20,7 @@ CONFIG_USE_BOOTCOMMAND=y CONFIG_SPL_TEXT_BASE=0x41c00000 CONFIG_SPL_STACK_R=y CONFIG_SPL_SEPARATE_BSS=y +CONFIG_SPL_SKIP_CLEAR_BSS=y CONFIG_SPL_I2C_SUPPORT=y CONFIG_SPL_DM_MAILBOX=y CONFIG_SPL_DM_RESET=y @@ -86,3 +87,4 @@ CONFIG_SYSRESET_TI_SCI=y CONFIG_TIMER=y CONFIG_SPL_TIMER=y CONFIG_OMAP_TIMER=y +CONFIG_FS_FAT_MAX_CLUSTSIZE=16384

Enable all the relevant configs that enables support for loading sysfw via MMC.
Signed-off-by: Andreas Dannenberg dannenberg@ti.com --- configs/am65x_hs_evm_r5_defconfig | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-)
diff --git a/configs/am65x_hs_evm_r5_defconfig b/configs/am65x_hs_evm_r5_defconfig index d4d23416cc..03b8bd0ec6 100644 --- a/configs/am65x_hs_evm_r5_defconfig +++ b/configs/am65x_hs_evm_r5_defconfig @@ -4,7 +4,7 @@ CONFIG_TI_SECURE_DEVICE=y CONFIG_SPL_GPIO_SUPPORT=y CONFIG_SPL_LIBCOMMON_SUPPORT=y CONFIG_SPL_LIBGENERIC_SUPPORT=y -CONFIG_SYS_MALLOC_F_LEN=0x2000 +CONFIG_SYS_MALLOC_F_LEN=0x55000 CONFIG_SOC_K3_AM6=y CONFIG_TARGET_AM654_R5_EVM=y CONFIG_SPL_MMC_SUPPORT=y @@ -22,6 +22,7 @@ CONFIG_USE_BOOTCOMMAND=y CONFIG_SPL_TEXT_BASE=0x41c00000 CONFIG_SPL_STACK_R=y CONFIG_SPL_SEPARATE_BSS=y +CONFIG_SPL_SKIP_CLEAR_BSS=y CONFIG_SPL_I2C_SUPPORT=y CONFIG_SPL_DM_MAILBOX=y CONFIG_SPL_DM_RESET=y @@ -88,3 +89,4 @@ CONFIG_SYSRESET_TI_SCI=y CONFIG_TIMER=y CONFIG_SPL_TIMER=y CONFIG_OMAP_TIMER=y +CONFIG_FS_FAT_MAX_CLUSTSIZE=16384

On Tue, 7 May 2019 at 11:26, Andreas Dannenberg dannenberg@ti.com wrote:
Enable all the relevant configs that enables support for loading sysfw via MMC.
Signed-off-by: Andreas Dannenberg dannenberg@ti.com
configs/am65x_hs_evm_r5_defconfig | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-)
Reviewed-by: Simon Glass sjg@chromium.org

From: Faiz Abbas faiz_abbas@ti.com
Add configs to support RAW boot mode in eMMC.
Signed-off-by: Faiz Abbas faiz_abbas@ti.com Signed-off-by: Andreas Dannenberg dannenberg@ti.com --- configs/am65x_evm_a53_defconfig | 2 ++ configs/am65x_evm_r5_defconfig | 2 ++ include/configs/am65x_evm.h | 2 ++ 3 files changed, 6 insertions(+)
diff --git a/configs/am65x_evm_a53_defconfig b/configs/am65x_evm_a53_defconfig index 101fae1456..0d9c4bf685 100644 --- a/configs/am65x_evm_a53_defconfig +++ b/configs/am65x_evm_a53_defconfig @@ -22,6 +22,8 @@ CONFIG_SPL_TEXT_BASE=0x80080000 CONFIG_SPL_SYS_MALLOC_SIMPLE=y CONFIG_SPL_STACK_R=y CONFIG_SPL_SEPARATE_BSS=y +CONFIG_SYS_MMCSD_RAW_MODE_U_BOOT_USE_SECTOR=y +CONFIG_SYS_MMCSD_RAW_MODE_U_BOOT_SECTOR=0x1400 CONFIG_SPL_I2C_SUPPORT=y CONFIG_SPL_DM_MAILBOX=y CONFIG_SPL_DM_RESET=y diff --git a/configs/am65x_evm_r5_defconfig b/configs/am65x_evm_r5_defconfig index 6861a9f05b..a23afaeb22 100644 --- a/configs/am65x_evm_r5_defconfig +++ b/configs/am65x_evm_r5_defconfig @@ -21,6 +21,8 @@ CONFIG_SPL_TEXT_BASE=0x41c00000 CONFIG_SPL_STACK_R=y CONFIG_SPL_SEPARATE_BSS=y CONFIG_SPL_SKIP_CLEAR_BSS=y +CONFIG_SYS_MMCSD_RAW_MODE_U_BOOT_USE_SECTOR=y +CONFIG_SYS_MMCSD_RAW_MODE_U_BOOT_SECTOR=0x400 CONFIG_SPL_I2C_SUPPORT=y CONFIG_SPL_DM_MAILBOX=y CONFIG_SPL_DM_RESET=y diff --git a/include/configs/am65x_evm.h b/include/configs/am65x_evm.h index a90f38edc9..56bd69a82a 100644 --- a/include/configs/am65x_evm.h +++ b/include/configs/am65x_evm.h @@ -92,6 +92,8 @@ EXTRA_ENV_AM65X_BOARD_SETTINGS \ EXTRA_ENV_AM65X_BOARD_SETTINGS_MMC
+#define CONFIG_SUPPORT_EMMC_BOOT + /* Now for the remaining common defines */ #include <configs/ti_armv7_common.h>

Add configs to support RAW boot mode in eMMC.
Signed-off-by: Andreas Dannenberg dannenberg@ti.com --- configs/am65x_hs_evm_a53_defconfig | 2 ++ configs/am65x_hs_evm_r5_defconfig | 2 ++ 2 files changed, 4 insertions(+)
diff --git a/configs/am65x_hs_evm_a53_defconfig b/configs/am65x_hs_evm_a53_defconfig index 7af0046ee3..6e226d9bff 100644 --- a/configs/am65x_hs_evm_a53_defconfig +++ b/configs/am65x_hs_evm_a53_defconfig @@ -25,6 +25,8 @@ CONFIG_SPL_TEXT_BASE=0x80080000 CONFIG_SPL_SYS_MALLOC_SIMPLE=y CONFIG_SPL_STACK_R=y CONFIG_SPL_SEPARATE_BSS=y +CONFIG_SYS_MMCSD_RAW_MODE_U_BOOT_USE_SECTOR=y +CONFIG_SYS_MMCSD_RAW_MODE_U_BOOT_SECTOR=0x1400 CONFIG_SPL_I2C_SUPPORT=y CONFIG_SPL_DM_MAILBOX=y CONFIG_SPL_DM_RESET=y diff --git a/configs/am65x_hs_evm_r5_defconfig b/configs/am65x_hs_evm_r5_defconfig index 03b8bd0ec6..c6a472d5e4 100644 --- a/configs/am65x_hs_evm_r5_defconfig +++ b/configs/am65x_hs_evm_r5_defconfig @@ -23,6 +23,8 @@ CONFIG_SPL_TEXT_BASE=0x41c00000 CONFIG_SPL_STACK_R=y CONFIG_SPL_SEPARATE_BSS=y CONFIG_SPL_SKIP_CLEAR_BSS=y +CONFIG_SYS_MMCSD_RAW_MODE_U_BOOT_USE_SECTOR=y +CONFIG_SYS_MMCSD_RAW_MODE_U_BOOT_SECTOR=0x400 CONFIG_SPL_I2C_SUPPORT=y CONFIG_SPL_DM_MAILBOX=y CONFIG_SPL_DM_RESET=y

From: Faiz Abbas faiz_abbas@ti.com
Add instructions for flashing boot images to the eMMC with a layout of the address where each image needs to be flashed.
Also add instructions to flash filesystem partition in user partition and boot kernel from the rootfs.
Signed-off-by: Faiz Abbas faiz_abbas@ti.com --- board/ti/am65x/README | 52 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 52 insertions(+)
diff --git a/board/ti/am65x/README b/board/ti/am65x/README index 0b82bd557b..16384e05ea 100644 --- a/board/ti/am65x/README +++ b/board/ti/am65x/README @@ -209,3 +209,55 @@ Image formats: | | Secure config | | | +-------------------+ | +-----------------------+ + +eMMC: +----- +ROM supports booting from eMMC from boot0 partition offset 0x0 + +Flashing images to eMMC: + +The following commands can be used to download tiboot3.bin, tispl.bin, +u-boot.img, and sysfw.itb from an SD card and write them to the eMMC boot0 +partition at respective addresses. + +=> mmc dev 0 1 +=> fatload mmc 1 ${loadaddr} tiboot3.bin +=> mmc write ${loadaddr} 0x0 0x400 +=> fatload mmc 1 ${loadaddr} tispl.bin +=> mmc write ${loadaddr} 0x400 0x1000 +=> fatload mmc 1 ${loadaddr} u-boot.img +=> mmc write ${loadaddr} 0x1400 0x2000 +=> fatload mmc 1 ${loadaddr} sysfw.itb +=> mmc write ${loadaddr} 0x3600 0x800 + +To give the ROM access to the boot partition, the following commands must be +used for the first time: +=> mmc partconf 0 1 1 1 +=> mmc bootbus 0 1 0 0 + +To create a software partition for the rootfs, the following command can be +used: +=> gpt write mmc 0 ${partitions} + +eMMC layout: + + boot0 partition (8 MB) user partition + 0x0+----------------------------------+ 0x0+-------------------------+ + | tiboot3.bin (512 KB) | | | + 0x400+----------------------------------+ | | + | tispl.bin (2 MB) | | | +0x1400+----------------------------------+ | rootfs | + | u-boot.img (4 MB) | | | +0x3400+----------------------------------+ | | + | environment (128 KB) | | | +0x3500+----------------------------------+ | | + | backup environment (128 KB) | | | +0x3600+----------------------------------+ | | + | sysfw (1 MB) | | | +0x3E00+----------------------------------+ +-------------------------+ + +Kernel image and DT are expected to be present in the /boot folder of rootfs. +To boot kernel from eMMC, use the following commands: +=> setenv mmcdev 0 +=> setenv bootpart 0 +=> boot

On 07.05.19 19:25, Andreas Dannenberg wrote:
TI K3 SoCs like the AM654x devices are fundamentally dependent on a firmware called SYSFW (System Firmware) being loaded into the dedicated DMSC (Device Management and Security Controller) processor to provide various services via TISCI (Texas Instruments System Control Interface) to manage device aspects such as core bringup, power, clocks, security, and so on across the entire SoC.
Currently public U-Boot does not boot on an actual AM654x EVM due to the missing loading and startup of SYSFW, with this being the only piece missing preventing a successful boot from SD/MMC-type media. This gap is addressed with this patch series.
Note that the loading and starting of SYSFW is done in the context of board_init_f() in SPL which poses some unique challenges due to the very constrained nature of this environment (minimal amount of SRAM, no DDR yet available).
In order to be as lean as possible on resource use an approach was chosen that extends the existing SPL loader framework to be usable beyond the usual "loading U-Boot" use case. While this patch series only makes changes to the MMC/SD card loader framework to support eMMC/MMC/SD FS- and sector/partition-based RAW boot at this time we have this solution in production today but extended to SPI/OSPI and Y-Modem without any issues.
While I also have a working solution based on the existing FS loader framework this has its own challenges, namely by its very nature only addressing a subset of our use cases (no eMMC/SD RAW boot support for example), being heavier on resource usage (needing to use ENV to pass parameters), and not addressing the need to probe the boot peripheral. This particular framework works well for use cases requiring to load firmware from FS-based media once DDR is up and U-Boot is in a more "initialized" state but it is not a one-fits all solution for very early use in SPL board_init_f() accross different boot modes.
And would it be an option to improve the loader (maybe dropping the "fs" from its name)? I think it's an "fs" loader because its idea has been copied from Linux. I think in U-Boot, it's more common to have things at a raw offset instead of a file system. Just thinking...
And the current state of that fs_loader is like it is because it fits its single user (socfpga stratix 10), I think.
Anyway, even if you do need yet another loader, would it make sense to create a common file instead of adding this in your arch/mach?
Regards, Simon
Andreas Dannenberg (10): mmc: k3_arasan: Allow driver to probe without PDs specified spl: Allow skipping clearing BSS during relocation spl: Make image loader infrastructure more universal arm: K3: Introduce System Firmware loader framework armV7R: K3: am654: Allow using SPL BSS pre-relocation armv7R: K3: am654: Use full malloc implementation in SPL armV7R: K3: am654: Load SYSFW binary and config from boot media configs: am65x_evm_r5: All sysfw to be loaded via MMC configs: am65x_hs_evm_r5: All sysfw to be loaded via MMC configs: am65x_hs_evm: Add Support for eMMC boot
Faiz Abbas (2): configs: am65x_evm: Add Support for eMMC boot am65x: README: Add eMMC layout and flash instructions
Lokesh Vutla (1): armv7R: dts: k3: am654: Update mmc nodes for loading sysfw
arch/arm/dts/k3-am654-r5-base-board.dts | 18 ++ arch/arm/lib/crt0.S | 3 + arch/arm/mach-k3/Kconfig | 40 +++ arch/arm/mach-k3/Makefile | 1 + arch/arm/mach-k3/am6_init.c | 34 ++- arch/arm/mach-k3/include/mach/sysfw-loader.h | 12 + arch/arm/mach-k3/sysfw-loader.c | 263 +++++++++++++++++++ board/ti/am65x/Kconfig | 1 + board/ti/am65x/README | 52 ++++ common/spl/Kconfig | 13 + common/spl/spl_fit.c | 14 + common/spl/spl_mmc.c | 76 ++++-- configs/am65x_evm_a53_defconfig | 2 + configs/am65x_evm_r5_defconfig | 7 +- configs/am65x_hs_evm_a53_defconfig | 2 + configs/am65x_hs_evm_r5_defconfig | 7 +- drivers/mmc/k3_arsan_sdhci.c | 16 +- include/configs/am65x_evm.h | 30 ++- include/spl.h | 26 ++ 19 files changed, 577 insertions(+), 40 deletions(-) create mode 100644 arch/arm/mach-k3/include/mach/sysfw-loader.h create mode 100644 arch/arm/mach-k3/sysfw-loader.c

On Tue, 2019-05-07 at 22:00 +0200, Simon Goldschmidt wrote:
On 07.05.19 19:25, Andreas Dannenberg wrote:
[...]
While I also have a working solution based on the existing FS loader framework this has its own challenges, namely by its very nature only addressing a subset of our use cases (no eMMC/SD RAW boot support for example),
IMO, it's actually not that hard to enhance RAW support, i think minimal changes are required. I have attached the patches about an example of loading RAW from QSPI that i have done locally last few week ago.
being heavier on resource usage (needing to use ENV to pass parameters),
ENV is optional, you can use DTS. For example loading FPGA bitstream from QSPI RAW:
/* DTS */ / { + aliases { + spi0 = &qspi; + }; + + fs_loader0: fs-loader { + u-boot,dm-pre-reloc; + compatible = "u-boot,fs-loader"; + sfconfig = <0 0 100000000 3>; + }; +}; + +&fpga_mgr { + u-boot,dm-pre-reloc; + firmware-loader = <&fs_loader0>; + altr,bitstream = "300000"; +};
and not addressing the need to probe the boot peripheral.
You can add more different probing method in function called "fs_loader_probe". Current fs_loader supports block(sdmmc, emmc, etc...) probing, and with the patches attached support QSPI probing.
Another idea come to mind, we can use fs_loader for loading FIT boot image into RAM, and boot from RAM with existing SPL loader framework, but i'm not sure this implementation fit to your use case?
This particular framework works well for use cases requiring to load firmware from FS-based media once DDR is up and U-Boot is in a more "initialized" state but it is not a one-fits all solution for very early use in SPL board_init_f() accross different boot modes.
And would it be an option to improve the loader (maybe dropping the "fs" from its name)? I think it's an "fs" loader because its idea has been copied from Linux. I think in U-Boot, it's more common to have things at a raw offset instead of a file system. Just thinking...
Current fs_loader only support filesystem, and i agree that it made sense to remove the "fs" once it supports the RAW offset as well.
Thanks.
Regards, TF
And the current state of that fs_loader is like it is because it fits its single user (socfpga stratix 10), I think.
Anyway, even if you do need yet another loader, would it make sense to create a common file instead of adding this in your arch/mach?
Regards, Simon
Andreas Dannenberg (10): mmc: k3_arasan: Allow driver to probe without PDs specified spl: Allow skipping clearing BSS during relocation spl: Make image loader infrastructure more universal arm: K3: Introduce System Firmware loader framework armV7R: K3: am654: Allow using SPL BSS pre-relocation armv7R: K3: am654: Use full malloc implementation in SPL armV7R: K3: am654: Load SYSFW binary and config from boot media configs: am65x_evm_r5: All sysfw to be loaded via MMC configs: am65x_hs_evm_r5: All sysfw to be loaded via MMC configs: am65x_hs_evm: Add Support for eMMC boot
Faiz Abbas (2): configs: am65x_evm: Add Support for eMMC boot am65x: README: Add eMMC layout and flash instructions
Lokesh Vutla (1): armv7R: dts: k3: am654: Update mmc nodes for loading sysfw
arch/arm/dts/k3-am654-r5-base-board.dts | 18 ++ arch/arm/lib/crt0.S | 3 + arch/arm/mach-k3/Kconfig | 40 +++ arch/arm/mach-k3/Makefile | 1 + arch/arm/mach-k3/am6_init.c | 34 ++- arch/arm/mach-k3/include/mach/sysfw-loader.h | 12 + arch/arm/mach-k3/sysfw-loader.c | 263 +++++++++++++++++++ board/ti/am65x/Kconfig | 1 + board/ti/am65x/README | 52 ++++ common/spl/Kconfig | 13 + common/spl/spl_fit.c | 14 + common/spl/spl_mmc.c | 76 ++++-- configs/am65x_evm_a53_defconfig | 2 + configs/am65x_evm_r5_defconfig | 7 +- configs/am65x_hs_evm_a53_defconfig | 2 + configs/am65x_hs_evm_r5_defconfig | 7 +- drivers/mmc/k3_arsan_sdhci.c | 16 +- include/configs/am65x_evm.h | 30 ++- include/spl.h | 26 ++ 19 files changed, 577 insertions(+), 40 deletions(-) create mode 100644 arch/arm/mach-k3/include/mach/sysfw-loader.h create mode 100644 arch/arm/mach-k3/sysfw-loader.c

Hi TF, thanks for chiming in. Comments inlined...
On Wed, May 08, 2019 at 04:31:35AM +0000, Chee, Tien Fong wrote:
On Tue, 2019-05-07 at 22:00 +0200, Simon Goldschmidt wrote:
On 07.05.19 19:25, Andreas Dannenberg wrote:
[...]
While I also have a working solution based on the existing FS loader framework this has its own challenges, namely by its very nature only addressing a subset of our use cases (no eMMC/SD RAW boot support for example),
IMO, it's actually not that hard to enhance RAW support, i think minimal changes are required. I have attached the patches about an example of loading RAW from QSPI that i have done locally last few week ago.
As your patches show, no it's not hard, it's more or less taking pieces from the SPL loader framework and refactoring them into the FS loader, creating a good and universal solution usable across SPL and U-Boot in environments that are not tightly constrained in terms of memory.
What I was going after is finding a way to load from different media "pre-relocation" SPL (board_init_f), with almost no memory available, where I have to agonize over every single KB available.
being heavier on resource usage (needing to use ENV to pass parameters),
ENV is optional, you can use DTS.
Is it? I had to update the FS loader framework when I experimented with it, please see attached patch. I had refactored it such that I can pass in all relevant data via platform data for the intial boot mode I was going after, so that I can dynamically configure it on the fly from early SPL board_init_f() based on boot media / boot mode, etc.
For example loading FPGA bitstream from QSPI RAW:
/* DTS */ / {
- aliases {
spi0 = &qspi;
- };
- fs_loader0: fs-loader {
u-boot,dm-pre-reloc;
compatible = "u-boot,fs-loader";
sfconfig = <0 0 100000000 3>;
- };
+};
+&fpga_mgr {
- u-boot,dm-pre-reloc;
- firmware-loader = <&fs_loader0>;
- altr,bitstream = "300000";
+};
The above hard-codes and duplicates information that is already known to U-Boot (CONFIG_SF_DEFAULT_*), and will do more of the same as this is being extended. How does one keep this consistent?
And how does this scale to support like 5 different boot modes using a single DTB? I guess one could populate 5 nodes, and then pick one based on boot mode during SPL execution, by extending the probe function accordingly.
and not addressing the need to probe the boot peripheral.
You can add more different probing method in function called "fs_loader_probe". Current fs_loader supports block(sdmmc, emmc, etc...) probing, and with the patches attached support QSPI probing.
Another idea come to mind, we can use fs_loader for loading FIT boot image into RAM, and boot from RAM with existing SPL loader framework, but i'm not sure this implementation fit to your use case?
Unfortunately for what I'm working on there is no space for this. It would be nice to be able to load our "System Firmware" alongside the next stage of U-Boot in a single FIT, and then just extact that firmware image similar to what CONFIG_SPL_FPGA_SUPPORT does in spl_fit.c. However I must load SYSFW and the U-Boot next stage as two steps (while bringing up DDR in-between....).
As I tried to explain in my earlier email to Simon, I almost see the minimally-intrusive extensions I did to the SPL loader framework via "spl: Make image loader infrastructure more universal" and the FS loader framework to be elements that are orthogonal and can both exist. Maybe FS loader can partially build upon the SPL loader foundation as well?
-- Andreas Dannenberg Texas Instruments Inc
This particular framework works well for use cases requiring to load firmware from FS-based media once DDR is up and U-Boot is in a more "initialized" state but it is not a one-fits all solution for very early use in SPL board_init_f() accross different boot modes.
And would it be an option to improve the loader (maybe dropping the "fs" from its name)? I think it's an "fs" loader because its idea has been copied from Linux. I think in U-Boot, it's more common to have things at a raw offset instead of a file system. Just thinking...
Current fs_loader only support filesystem, and i agree that it made sense to remove the "fs" once it supports the RAW offset as well.
Thanks.
Regards, TF
And the current state of that fs_loader is like it is because it fits its single user (socfpga stratix 10), I think.
Anyway, even if you do need yet another loader, would it make sense to create a common file instead of adding this in your arch/mach?
Regards, Simon
Andreas Dannenberg (10): mmc: k3_arasan: Allow driver to probe without PDs specified spl: Allow skipping clearing BSS during relocation spl: Make image loader infrastructure more universal arm: K3: Introduce System Firmware loader framework armV7R: K3: am654: Allow using SPL BSS pre-relocation armv7R: K3: am654: Use full malloc implementation in SPL armV7R: K3: am654: Load SYSFW binary and config from boot media configs: am65x_evm_r5: All sysfw to be loaded via MMC configs: am65x_hs_evm_r5: All sysfw to be loaded via MMC configs: am65x_hs_evm: Add Support for eMMC boot
Faiz Abbas (2): configs: am65x_evm: Add Support for eMMC boot am65x: README: Add eMMC layout and flash instructions
Lokesh Vutla (1): armv7R: dts: k3: am654: Update mmc nodes for loading sysfw
arch/arm/dts/k3-am654-r5-base-board.dts | 18 ++ arch/arm/lib/crt0.S | 3 + arch/arm/mach-k3/Kconfig | 40 +++ arch/arm/mach-k3/Makefile | 1 + arch/arm/mach-k3/am6_init.c | 34 ++- arch/arm/mach-k3/include/mach/sysfw-loader.h | 12 + arch/arm/mach-k3/sysfw-loader.c | 263 +++++++++++++++++++ board/ti/am65x/Kconfig | 1 + board/ti/am65x/README | 52 ++++ common/spl/Kconfig | 13 + common/spl/spl_fit.c | 14 + common/spl/spl_mmc.c | 76 ++++-- configs/am65x_evm_a53_defconfig | 2 + configs/am65x_evm_r5_defconfig | 7 +- configs/am65x_hs_evm_a53_defconfig | 2 + configs/am65x_hs_evm_r5_defconfig | 7 +- drivers/mmc/k3_arsan_sdhci.c | 16 +- include/configs/am65x_evm.h | 30 ++- include/spl.h | 26 ++ 19 files changed, 577 insertions(+), 40 deletions(-) create mode 100644 arch/arm/mach-k3/include/mach/sysfw-loader.h create mode 100644 arch/arm/mach-k3/sysfw-loader.c

On Wed, 2019-05-08 at 13:43 -0500, dannenberg@ti.com wrote:
Hi TF, thanks for chiming in. Comments inlined...
On Wed, May 08, 2019 at 04:31:35AM +0000, Chee, Tien Fong wrote:
On Tue, 2019-05-07 at 22:00 +0200, Simon Goldschmidt wrote:
On 07.05.19 19:25, Andreas Dannenberg wrote:
[...]
While I also have a working solution based on the existing FS loader framework this has its own challenges, namely by its very nature only addressing a subset of our use cases (no eMMC/SD RAW boot support for example),
IMO, it's actually not that hard to enhance RAW support, i think minimal changes are required. I have attached the patches about an example of loading RAW from QSPI that i have done locally last few week ago.
As your patches show, no it's not hard, it's more or less taking pieces from the SPL loader framework and refactoring them into the FS loader, creating a good and universal solution usable across SPL and U-Boot in environments that are not tightly constrained in terms of memory.
What I was going after is finding a way to load from different media "pre-relocation" SPL (board_init_f), with almost no memory available, where I have to agonize over every single KB available.
This is just a simple "loader", provide user flexibility of loading stuff in anywhere, from SPL to U-Boot. As long as DM is supported by the time running at "pre-relocation" SPL, then FS loader should be able to work.
being heavier on resource usage (needing to use ENV to pass parameters),
ENV is optional, you can use DTS.
Is it? I had to update the FS loader framework when I experimented with it, please see attached patch. I had refactored it such that I can pass in all relevant data via platform data for the intial boot mode I was going after, so that I can dynamically configure it on the fly from early SPL board_init_f() based on boot media / boot mode, etc.
Yes, you can tie up loader with target HW node for destination loading. For example, tie up with FPGA manager node, loading bistream file from MMC to FPGA manager.
Here is an example, but i put the fs loader phandle under chosen node because most files and images are stored in the same storage. http://git.denx.de/?p=u-boot/u-boot-socfpga.git;a=commit;h=0a42a132a4b8 46031df2c4a7d04692240ed34843
For example loading FPGA bitstream from QSPI RAW:
/* DTS */ / {
- aliases {
spi0 = &qspi;
- };
- fs_loader0: fs-loader {
u-boot,dm-pre-reloc;
compatible = "u-boot,fs-loader";
sfconfig = <0 0 100000000 3>;
- };
+};
+&fpga_mgr {
- u-boot,dm-pre-reloc;
- firmware-loader = <&fs_loader0>;
- altr,bitstream = "300000";
+};
The above hard-codes and duplicates information that is already known to U-Boot (CONFIG_SF_DEFAULT_*), and will do more of the same as this is being extended. How does one keep this consistent?
Current fs loader not support RAW loading yet, i'm not sure whether it should support it by adding more specific storage API(much more messy), or just fully support filesystem only with one generic filesystem abstract interface.
This example codes provide user opportunity to override the spi setting when running fs loader. CONFIG_SF_DEFAULT_* would be used by the drivers which are not running the fs loader.
And how does this scale to support like 5 different boot modes using a single DTB? I guess one could populate 5 nodes, and then pick one based on boot mode during SPL execution, by extending the probe function accordingly.
This is just a very simple fs loader. This is totally up to user how they want to scale it up, may be adding the function to populate the fs loader nodes, or loading the images based on boot storages ordering in DTS?
and not addressing the need to probe the boot peripheral.
You can add more different probing method in function called "fs_loader_probe". Current fs_loader supports block(sdmmc, emmc, etc...) probing, and with the patches attached support QSPI probing.
Another idea come to mind, we can use fs_loader for loading FIT boot image into RAM, and boot from RAM with existing SPL loader framework, but i'm not sure this implementation fit to your use case?
Unfortunately for what I'm working on there is no space for this. It would be nice to be able to load our "System Firmware" alongside the next stage of U-Boot in a single FIT, and then just extact that firmware image similar to what CONFIG_SPL_FPGA_SUPPORT does in spl_fit.c. However I must load SYSFW and the U-Boot next stage as two steps (while bringing up DDR in-between....).
As I tried to explain in my earlier email to Simon, I almost see the minimally-intrusive extensions I did to the SPL loader framework via "spl: Make image loader infrastructure more universal" and the FS loader framework to be elements that are orthogonal and can both exist. Maybe FS loader can partially build upon the SPL loader foundation as well?
Yes, fs loader can be in anywhere, it can be part of SPL loader framework as well. It can be as complement to SPL loader also.
Thanks.
TF.
-- Andreas Dannenberg Texas Instruments Inc
This particular framework works well for use cases requiring to load firmware from FS-based media once DDR is up and U-Boot is in a more "initialized" state but it is not a one-fits all solution for very early use in SPL board_init_f() accross different boot modes.
And would it be an option to improve the loader (maybe dropping the "fs" from its name)? I think it's an "fs" loader because its idea has been copied from Linux. I think in U-Boot, it's more common to have things at a raw offset instead of a file system. Just thinking...
Current fs_loader only support filesystem, and i agree that it made sense to remove the "fs" once it supports the RAW offset as well.
Thanks.
Regards, TF
And the current state of that fs_loader is like it is because it fits its single user (socfpga stratix 10), I think.
Anyway, even if you do need yet another loader, would it make sense to create a common file instead of adding this in your arch/mach?
Regards, Simon
Andreas Dannenberg (10): mmc: k3_arasan: Allow driver to probe without PDs specified spl: Allow skipping clearing BSS during relocation spl: Make image loader infrastructure more universal arm: K3: Introduce System Firmware loader framework armV7R: K3: am654: Allow using SPL BSS pre-relocation armv7R: K3: am654: Use full malloc implementation in SPL armV7R: K3: am654: Load SYSFW binary and config from boot media configs: am65x_evm_r5: All sysfw to be loaded via MMC configs: am65x_hs_evm_r5: All sysfw to be loaded via MMC configs: am65x_hs_evm: Add Support for eMMC boot
Faiz Abbas (2): configs: am65x_evm: Add Support for eMMC boot am65x: README: Add eMMC layout and flash instructions
Lokesh Vutla (1): armv7R: dts: k3: am654: Update mmc nodes for loading sysfw
arch/arm/dts/k3-am654-r5-base-board.dts | 18 ++ arch/arm/lib/crt0.S | 3 + arch/arm/mach-k3/Kconfig | 40 +++ arch/arm/mach-k3/Makefile | 1 + arch/arm/mach-k3/am6_init.c | 34 ++- arch/arm/mach-k3/include/mach/sysfw-loader.h | 12 + arch/arm/mach-k3/sysfw-loader.c | 263 +++++++++++++++++++ board/ti/am65x/Kconfig | 1 + board/ti/am65x/README | 52 ++++ common/spl/Kconfig | 13 + common/spl/spl_fit.c | 14 + common/spl/spl_mmc.c | 76 ++++-- configs/am65x_evm_a53_defconfig | 2 + configs/am65x_evm_r5_defconfig | 7 +- configs/am65x_hs_evm_a53_defconfig | 2 + configs/am65x_hs_evm_r5_defconfig | 7 +- drivers/mmc/k3_arsan_sdhci.c | 16 +- include/configs/am65x_evm.h | 30 ++- include/spl.h | 26 ++ 19 files changed, 577 insertions(+), 40 deletions(-) create mode 100644 arch/arm/mach-k3/include/mach/sysfw- loader.h create mode 100644 arch/arm/mach-k3/sysfw-loader.c

Hi TF,
On Mon, May 13, 2019 at 01:37:22PM +0000, Chee, Tien Fong wrote:
On Wed, 2019-05-08 at 13:43 -0500, dannenberg@ti.com wrote:
Hi TF, thanks for chiming in. Comments inlined...
On Wed, May 08, 2019 at 04:31:35AM +0000, Chee, Tien Fong wrote:
On Tue, 2019-05-07 at 22:00 +0200, Simon Goldschmidt wrote:
On 07.05.19 19:25, Andreas Dannenberg wrote:
[...]
While I also have a working solution based on the existing FS loader framework this has its own challenges, namely by its very nature only addressing a subset of our use cases (no eMMC/SD RAW boot support for example),
IMO, it's actually not that hard to enhance RAW support, i think minimal changes are required. I have attached the patches about an example of loading RAW from QSPI that i have done locally last few week ago.
As your patches show, no it's not hard, it's more or less taking pieces from the SPL loader framework and refactoring them into the FS loader, creating a good and universal solution usable across SPL and U-Boot in environments that are not tightly constrained in terms of memory.
What I was going after is finding a way to load from different media "pre-relocation" SPL (board_init_f), with almost no memory available, where I have to agonize over every single KB available.
This is just a simple "loader", provide user flexibility of loading stuff in anywhere, from SPL to U-Boot. As long as DM is supported by the time running at "pre-relocation" SPL, then FS loader should be able to work.
Understood. FS loader also relies on the peripheral being brought up. For MMC, from my SPL board_init_f() user code I had to do a sequence of mmc_initialize(), mmc_get_mmc_dev(), and mmc_init() before I could use the FS loader functionality - just like the U-Boot SPL loader is already doing this. Hence my concern with code duplication for certain use cases. Anyways I'll post my use of the FS loader as an RFC here soon so you can have a look at the whole thing if you like.
being heavier on resource usage (needing to use ENV to pass parameters),
ENV is optional, you can use DTS.
Is it? I had to update the FS loader framework when I experimented with it, please see attached patch. I had refactored it such that I can pass in all relevant data via platform data for the intial boot mode I was going after, so that I can dynamically configure it on the fly from early SPL board_init_f() based on boot media / boot mode, etc.
Yes, you can tie up loader with target HW node for destination loading. For example, tie up with FPGA manager node, loading bistream file from MMC to FPGA manager.
Here is an example, but i put the fs loader phandle under chosen node because most files and images are stored in the same storage. http://git.denx.de/?p=u-boot/u-boot-socfpga.git;a=commit;h=0a42a132a4b8 46031df2c4a7d04692240ed34843
Thanks for pointing to this example for DTS-based loading, I think I had seen this earlier when I looked for implementations using the FS loader framework.
For example loading FPGA bitstream from QSPI RAW:
/* DTS */ / {
- aliases {
spi0 = &qspi;
- };
- fs_loader0: fs-loader {
u-boot,dm-pre-reloc;
compatible = "u-boot,fs-loader";
sfconfig = <0 0 100000000 3>;
- };
+};
+&fpga_mgr {
- u-boot,dm-pre-reloc;
- firmware-loader = <&fs_loader0>;
- altr,bitstream = "300000";
+};
The above hard-codes and duplicates information that is already known to U-Boot (CONFIG_SF_DEFAULT_*), and will do more of the same as this is being extended. How does one keep this consistent?
Current fs loader not support RAW loading yet, i'm not sure whether it should support it by adding more specific storage API(much more messy), or just fully support filesystem only with one generic filesystem abstract interface.
This example codes provide user opportunity to override the spi setting when running fs loader. CONFIG_SF_DEFAULT_* would be used by the drivers which are not running the fs loader.
And how does this scale to support like 5 different boot modes using a single DTB? I guess one could populate 5 nodes, and then pick one based on boot mode during SPL execution, by extending the probe function accordingly.
This is just a very simple fs loader. This is totally up to user how they want to scale it up, may be adding the function to populate the fs loader nodes, or loading the images based on boot storages ordering in DTS?
This would require on-the-fly FDT manipulation. Again something that can be done, but challenging in tight environments. I'm not arguing against FS loader, it is very useful, we actually use it ourselves (not upstream yet) for use cases involving remote core program loading...
and not addressing the need to probe the boot peripheral.
You can add more different probing method in function called "fs_loader_probe". Current fs_loader supports block(sdmmc, emmc, etc...) probing, and with the patches attached support QSPI probing.
Another idea come to mind, we can use fs_loader for loading FIT boot image into RAM, and boot from RAM with existing SPL loader framework, but i'm not sure this implementation fit to your use case?
Unfortunately for what I'm working on there is no space for this. It would be nice to be able to load our "System Firmware" alongside the next stage of U-Boot in a single FIT, and then just extact that firmware image similar to what CONFIG_SPL_FPGA_SUPPORT does in spl_fit.c. However I must load SYSFW and the U-Boot next stage as two steps (while bringing up DDR in-between....).
As I tried to explain in my earlier email to Simon, I almost see the minimally-intrusive extensions I did to the SPL loader framework via "spl: Make image loader infrastructure more universal" and the FS loader framework to be elements that are orthogonal and can both exist. Maybe FS loader can partially build upon the SPL loader foundation as well?
Yes, fs loader can be in anywhere, it can be part of SPL loader framework as well. It can be as complement to SPL loader also.
Yes exactly.
Thanks,
-- Andreas Dannenberg Texas Instruments Inc

Hi Simon, comments inlined...
On Tue, May 07, 2019 at 10:00:03PM +0200, Simon Goldschmidt wrote:
On 07.05.19 19:25, Andreas Dannenberg wrote:
TI K3 SoCs like the AM654x devices are fundamentally dependent on a firmware called SYSFW (System Firmware) being loaded into the dedicated DMSC (Device Management and Security Controller) processor to provide various services via TISCI (Texas Instruments System Control Interface) to manage device aspects such as core bringup, power, clocks, security, and so on across the entire SoC.
Currently public U-Boot does not boot on an actual AM654x EVM due to the missing loading and startup of SYSFW, with this being the only piece missing preventing a successful boot from SD/MMC-type media. This gap is addressed with this patch series.
Note that the loading and starting of SYSFW is done in the context of board_init_f() in SPL which poses some unique challenges due to the very constrained nature of this environment (minimal amount of SRAM, no DDR yet available).
In order to be as lean as possible on resource use an approach was chosen that extends the existing SPL loader framework to be usable beyond the usual "loading U-Boot" use case. While this patch series only makes changes to the MMC/SD card loader framework to support eMMC/MMC/SD FS- and sector/partition-based RAW boot at this time we have this solution in production today but extended to SPI/OSPI and Y-Modem without any issues.
While I also have a working solution based on the existing FS loader framework this has its own challenges, namely by its very nature only addressing a subset of our use cases (no eMMC/SD RAW boot support for example), being heavier on resource usage (needing to use ENV to pass parameters), and not addressing the need to probe the boot peripheral. This particular framework works well for use cases requiring to load firmware from FS-based media once DDR is up and U-Boot is in a more "initialized" state but it is not a one-fits all solution for very early use in SPL board_init_f() accross different boot modes.
And would it be an option to improve the loader (maybe dropping the "fs" from its name)? I think it's an "fs" loader because its idea has been copied from Linux. I think in U-Boot, it's more common to have things at a raw offset instead of a file system. Just thinking...
Agreed this can be refactored and extended and would be useful - except for some very memory-constrained situations, see below.
And the current state of that fs_loader is like it is because it fits its single user (socfpga stratix 10), I think.
What I needed was something very small as even with the here proposed solution that heavily re-uses SPL loader code there is only about 61KB left at the moment in the SRAM memory region SPL executes from, and some of that 61KB will be used by the stack, and some will be used by other features still needing to get added to the SPL image unrelated to the loader functionality under discussion. So space is super tight, and literally every KB counts. I wish the environment was less constrained from a memory POV...
Anyway, even if you do need yet another loader, would it make sense to create a common file instead of adding this in your arch/mach?
Be careful not to be mislead from what I'm actually proposing here:
1) A method to load, start (via rproc) and configure the TI K3 System Firmware with the patch "arm: K3: Introduce System Firmware loader framework" under arch/mach. You can review this patch, 95% of this code is only applicable to TI K3 devices, and not any other device, platform, or vendor. The actual "loading" part you are concerned with is nothing more than a single call over to spl_mmc_load() located in the SPL framework. So the logical place for the "SYSFW Loader" is said arm/mach location.
2) A method to re-use most/all of the SPL loader code including peripheral init/probe functionality most commonly used for only loading U-Boot by exposing the core loader functions as an API. For MMC/SD, this is introduced with the patch "spl: Make image loader infrastructure more universal" and doesn't really add any code at all. This has the advantage of minimizing memory footprint and code duplication (FS loader replicates some of what the SPL loader does, and even more so if extended). I argue this method of opening up the SPL loader is actually orthogonal to the current FS loader framework, and the FS loader framework could as well tap into the SPL loader code as well as it extends and grows to avoid duplication.
-- Andreas Dannenberg Texas Instruments Inc
Regards, Simon
Andreas Dannenberg (10): mmc: k3_arasan: Allow driver to probe without PDs specified spl: Allow skipping clearing BSS during relocation spl: Make image loader infrastructure more universal arm: K3: Introduce System Firmware loader framework armV7R: K3: am654: Allow using SPL BSS pre-relocation armv7R: K3: am654: Use full malloc implementation in SPL armV7R: K3: am654: Load SYSFW binary and config from boot media configs: am65x_evm_r5: All sysfw to be loaded via MMC configs: am65x_hs_evm_r5: All sysfw to be loaded via MMC configs: am65x_hs_evm: Add Support for eMMC boot
Faiz Abbas (2): configs: am65x_evm: Add Support for eMMC boot am65x: README: Add eMMC layout and flash instructions
Lokesh Vutla (1): armv7R: dts: k3: am654: Update mmc nodes for loading sysfw
arch/arm/dts/k3-am654-r5-base-board.dts | 18 ++ arch/arm/lib/crt0.S | 3 + arch/arm/mach-k3/Kconfig | 40 +++ arch/arm/mach-k3/Makefile | 1 + arch/arm/mach-k3/am6_init.c | 34 ++- arch/arm/mach-k3/include/mach/sysfw-loader.h | 12 + arch/arm/mach-k3/sysfw-loader.c | 263 +++++++++++++++++++ board/ti/am65x/Kconfig | 1 + board/ti/am65x/README | 52 ++++ common/spl/Kconfig | 13 + common/spl/spl_fit.c | 14 + common/spl/spl_mmc.c | 76 ++++-- configs/am65x_evm_a53_defconfig | 2 + configs/am65x_evm_r5_defconfig | 7 +- configs/am65x_hs_evm_a53_defconfig | 2 + configs/am65x_hs_evm_r5_defconfig | 7 +- drivers/mmc/k3_arsan_sdhci.c | 16 +- include/configs/am65x_evm.h | 30 ++- include/spl.h | 26 ++ 19 files changed, 577 insertions(+), 40 deletions(-) create mode 100644 arch/arm/mach-k3/include/mach/sysfw-loader.h create mode 100644 arch/arm/mach-k3/sysfw-loader.c

Am 08.05.2019 um 20:04 schrieb Andreas Dannenberg:
Hi Simon, comments inlined...
On Tue, May 07, 2019 at 10:00:03PM +0200, Simon Goldschmidt wrote:
On 07.05.19 19:25, Andreas Dannenberg wrote:
TI K3 SoCs like the AM654x devices are fundamentally dependent on a firmware called SYSFW (System Firmware) being loaded into the dedicated DMSC (Device Management and Security Controller) processor to provide various services via TISCI (Texas Instruments System Control Interface) to manage device aspects such as core bringup, power, clocks, security, and so on across the entire SoC.
Currently public U-Boot does not boot on an actual AM654x EVM due to the missing loading and startup of SYSFW, with this being the only piece missing preventing a successful boot from SD/MMC-type media. This gap is addressed with this patch series.
Note that the loading and starting of SYSFW is done in the context of board_init_f() in SPL which poses some unique challenges due to the very constrained nature of this environment (minimal amount of SRAM, no DDR yet available).
In order to be as lean as possible on resource use an approach was chosen that extends the existing SPL loader framework to be usable beyond the usual "loading U-Boot" use case. While this patch series only makes changes to the MMC/SD card loader framework to support eMMC/MMC/SD FS- and sector/partition-based RAW boot at this time we have this solution in production today but extended to SPI/OSPI and Y-Modem without any issues.
While I also have a working solution based on the existing FS loader framework this has its own challenges, namely by its very nature only addressing a subset of our use cases (no eMMC/SD RAW boot support for example), being heavier on resource usage (needing to use ENV to pass parameters), and not addressing the need to probe the boot peripheral. This particular framework works well for use cases requiring to load firmware from FS-based media once DDR is up and U-Boot is in a more "initialized" state but it is not a one-fits all solution for very early use in SPL board_init_f() accross different boot modes.
And would it be an option to improve the loader (maybe dropping the "fs" from its name)? I think it's an "fs" loader because its idea has been copied from Linux. I think in U-Boot, it's more common to have things at a raw offset instead of a file system. Just thinking...
Agreed this can be refactored and extended and would be useful - except for some very memory-constrained situations, see below.
And the current state of that fs_loader is like it is because it fits its single user (socfpga stratix 10), I think.
What I needed was something very small as even with the here proposed solution that heavily re-uses SPL loader code there is only about 61KB left at the moment in the SRAM memory region SPL executes from, and some of that 61KB will be used by the stack, and some will be used by other features still needing to get added to the SPL image unrelated to the loader functionality under discussion. So space is super tight, and literally every KB counts. I wish the environment was less constrained from a memory POV...
I can understand your point on memory usage, but fs_loader started by Intel is used in SPL, too. And while they obviously aren't as tight with memory there (although I think this is pre DDR, too), I still think we should come up with *one* solution, not two.
Anyway, even if you do need yet another loader, would it make sense to create a common file instead of adding this in your arch/mach?
Be careful not to be mislead from what I'm actually proposing here:
- A method to load, start (via rproc) and configure the TI K3 System Firmware with the patch "arm: K3: Introduce System Firmware loader framework" under arch/mach. You can review this patch, 95% of this code is only applicable to TI K3 devices, and not any other device, platform, or vendor. The actual "loading" part you are concerned with is nothing more than a single call over to spl_mmc_load() located in the SPL framework. So the logical place for the "SYSFW Loader" is said arm/mach location.
OK.
- A method to re-use most/all of the SPL loader code including peripheral init/probe functionality most commonly used for only loading U-Boot by exposing the core loader functions as an API. For MMC/SD, this is introduced with the patch "spl: Make image loader infrastructure more universal" and doesn't really add any code at all. This has the advantage of minimizing memory footprint and code duplication (FS loader replicates some of what the SPL loader does, and even more so if extended). I argue this method of opening up the SPL loader is actually orthogonal to the current FS loader framework, and the FS loader framework could as well tap into the SPL loader code as well as it extends and grows to avoid duplication.
You're talking about 3/13 here? I think that's a good approach in general. Maybe the actual work left is making fs_loader use these loaders in SPL to deduplicate code?
Regards, Simon
-- Andreas Dannenberg Texas Instruments Inc
Regards, Simon
Andreas Dannenberg (10): mmc: k3_arasan: Allow driver to probe without PDs specified spl: Allow skipping clearing BSS during relocation spl: Make image loader infrastructure more universal arm: K3: Introduce System Firmware loader framework armV7R: K3: am654: Allow using SPL BSS pre-relocation armv7R: K3: am654: Use full malloc implementation in SPL armV7R: K3: am654: Load SYSFW binary and config from boot media configs: am65x_evm_r5: All sysfw to be loaded via MMC configs: am65x_hs_evm_r5: All sysfw to be loaded via MMC configs: am65x_hs_evm: Add Support for eMMC boot
Faiz Abbas (2): configs: am65x_evm: Add Support for eMMC boot am65x: README: Add eMMC layout and flash instructions
Lokesh Vutla (1): armv7R: dts: k3: am654: Update mmc nodes for loading sysfw
arch/arm/dts/k3-am654-r5-base-board.dts | 18 ++ arch/arm/lib/crt0.S | 3 + arch/arm/mach-k3/Kconfig | 40 +++ arch/arm/mach-k3/Makefile | 1 + arch/arm/mach-k3/am6_init.c | 34 ++- arch/arm/mach-k3/include/mach/sysfw-loader.h | 12 + arch/arm/mach-k3/sysfw-loader.c | 263 +++++++++++++++++++ board/ti/am65x/Kconfig | 1 + board/ti/am65x/README | 52 ++++ common/spl/Kconfig | 13 + common/spl/spl_fit.c | 14 + common/spl/spl_mmc.c | 76 ++++-- configs/am65x_evm_a53_defconfig | 2 + configs/am65x_evm_r5_defconfig | 7 +- configs/am65x_hs_evm_a53_defconfig | 2 + configs/am65x_hs_evm_r5_defconfig | 7 +- drivers/mmc/k3_arsan_sdhci.c | 16 +- include/configs/am65x_evm.h | 30 ++- include/spl.h | 26 ++ 19 files changed, 577 insertions(+), 40 deletions(-) create mode 100644 arch/arm/mach-k3/include/mach/sysfw-loader.h create mode 100644 arch/arm/mach-k3/sysfw-loader.c

On Tue, May 07, 2019 at 12:25:29PM -0500, Andreas Dannenberg wrote:
TI K3 SoCs like the AM654x devices are fundamentally dependent on a firmware called SYSFW (System Firmware) being loaded into the dedicated DMSC (Device Management and Security Controller) processor to provide various services via TISCI (Texas Instruments System Control Interface) to manage device aspects such as core bringup, power, clocks, security, and so on across the entire SoC.
[snip]
While I also have a working solution based on the existing FS loader framework this has its own challenges, namely by its very nature only addressing a subset of our use cases (no eMMC/SD RAW boot support for example), being heavier on resource usage (needing to use ENV to pass parameters), and not addressing the need to probe the boot peripheral. This particular framework works well for use cases requiring to load firmware from FS-based media once DDR is up and U-Boot is in a more "initialized" state but it is not a one-fits all solution for very early use in SPL board_init_f() accross different boot modes.
I think one thing that might help here is to post this alternative solution and provide the 'size' information for both series. In addition, build something like am335x_evm and socfpga_stratix10 for both series and include their before/after 'size' info too. Thanks!

Hi Tom,
On Wed, May 15, 2019 at 11:16:43AM -0400, Tom Rini wrote:
On Tue, May 07, 2019 at 12:25:29PM -0500, Andreas Dannenberg wrote:
TI K3 SoCs like the AM654x devices are fundamentally dependent on a firmware called SYSFW (System Firmware) being loaded into the dedicated DMSC (Device Management and Security Controller) processor to provide various services via TISCI (Texas Instruments System Control Interface) to manage device aspects such as core bringup, power, clocks, security, and so on across the entire SoC.
[snip]
While I also have a working solution based on the existing FS loader framework this has its own challenges, namely by its very nature only addressing a subset of our use cases (no eMMC/SD RAW boot support for example), being heavier on resource usage (needing to use ENV to pass parameters), and not addressing the need to probe the boot peripheral. This particular framework works well for use cases requiring to load firmware from FS-based media once DDR is up and U-Boot is in a more "initialized" state but it is not a one-fits all solution for very early use in SPL board_init_f() accross different boot modes.
I think one thing that might help here is to post this alternative solution and provide the 'size' information for both series. In addition, build something like am335x_evm and socfpga_stratix10 for both series and include their before/after 'size' info too. Thanks!
thanks for looking at this more closely. Sure, let me collect some data on this front and also post the alternative solution. It won't be a completely fair comparison however as the alternative solution only supports FS-based MMC boot, whereas the solution proposed here also supports eMMC/SD RAW boot, both partition and sector-based (and a combination thereof).
-- Andreas Dannenberg Texas Instruments Inc

Hi Tom,
On Wed, May 15, 2019 at 11:16:43AM -0400, Tom Rini wrote:
On Tue, May 07, 2019 at 12:25:29PM -0500, Andreas Dannenberg wrote:
TI K3 SoCs like the AM654x devices are fundamentally dependent on a firmware called SYSFW (System Firmware) being loaded into the dedicated DMSC (Device Management and Security Controller) processor to provide various services via TISCI (Texas Instruments System Control Interface) to manage device aspects such as core bringup, power, clocks, security, and so on across the entire SoC.
[snip]
While I also have a working solution based on the existing FS loader framework this has its own challenges, namely by its very nature only addressing a subset of our use cases (no eMMC/SD RAW boot support for example), being heavier on resource usage (needing to use ENV to pass parameters), and not addressing the need to probe the boot peripheral. This particular framework works well for use cases requiring to load firmware from FS-based media once DDR is up and U-Boot is in a more "initialized" state but it is not a one-fits all solution for very early use in SPL board_init_f() accross different boot modes.
I think one thing that might help here is to post this alternative solution and provide the 'size' information for both series. In addition, build something like am335x_evm and socfpga_stratix10 for both series and include their before/after 'size' info too. Thanks!
I collected some data how this series extending the SPL framework affects the size of the SPL, the increase is quite small nevertheless there is an increase that may or may not be an issue on certain platforms:
| SPL File | v2019.07-rc2 | plus SYSFW loader series ------------------+----------------+--------------+------------------------- am335x_evm | MLO | 109,884 | 109,964 (+120 bytes) socfpga_stratix10 | u-boot-spl.bin | 78,760 | 78,872 (+112 bytes)
Then, I also collected some data comparing how the SYSFW loader based on extending the SPL loader function (this patch series) stacks up against a basic FS loader-based implementation of the SYSFW loader functionality from an AM654 R5 SPL size POV:
What | SPL (tiboot3.bin) | Solution Size (bytes) --------------------------+-------------------+----------------------- No SYSFW Loader | 91,725 | 0 (base for comp) SPL loader-based solution | 93,265 | 1,540 FS loader-based solution | 95,417 | 3,692
Basically the FS loader-based solution is ~2x bigger than the SPL-loader based solution, while also dropping eMMC/SD partition- and sector-based RAW support. The difference between the solutions is 2,152 and will be even larger once RAW boot support is added in. Will post the FS loader- based solution for reference next.
One more word on why I am so concerned with memory. Below is a rough memory map of our SPL running on an R5 core out of on-chip MCU SRAM (512KB on AM654x). The stack during "pre-relocation" SPL is growing down towards where the actual SPL image is. Inside board_init_f() the SP currently sits at SP=0x41c25b10. The image size of an R5 SPL with the SPL loader-based solution as proposed with this patch series sits at 93,265 bytes, effectively leaving 61,119 bytes to be shared between features that are yet to get added to tiboot3.bin (such as board-detection EEPROM support, other early boot remote core loading, additions to dtb), and what can be used as stack by board_init_f() and its callees. Hence, every kilobyte really counts.
+-----------+ 0x41c8 0000 | BSS | CONFIG_SPL_BSS_MAX_SIZE=0x5000 +-----------+ | malloc | CONFIG_SYS_MALLOC_F_LEN=0x55000 +-----------+ | gd | +-----------+ | Stack | +-----------+ | | \ ~ ~ |== Room for stack growth | | / and R5 SPL feature +-----------+ additions | | |tiboot3.bin| | (SPL) | | | +-----------+ 0x41c0 0000
-- Andreas Dannenberg Texas Instruments Inc
participants (6)
-
Andreas Dannenberg
-
Chee, Tien Fong
-
dannenberg@ti.com
-
Simon Glass
-
Simon Goldschmidt
-
Tom Rini