From 33965c7e18a44b1b15c83921393a9cfc123f0e90 Mon Sep 17 00:00:00 2001 From: Harald Seiler Date: Wed, 6 Jul 2022 13:19:10 +0200 Subject: [PATCH 01/13] console: Add option to keep it silent until env is loaded Add a config-option which forces the console to stay silent until the proper environment is loaded from flash. This is important when the default environment does not silence the console but no output must be printed when 'silent' is set in the flash environment. After the environment from flash is loaded, the console will be silenced/unsilenced depending on it. If PRE_CONSOLE_BUFFER is also used, the buffer will now be flushed if the console should not be silenced. Signed-off-by: Harald Seiler Reviewed-by: Simon Glass --- common/Kconfig | 10 ++++++++++ common/console.c | 5 +++++ 2 files changed, 15 insertions(+) diff --git a/common/Kconfig b/common/Kconfig index 8c71d3c972..73e3fe3657 100644 --- a/common/Kconfig +++ b/common/Kconfig @@ -164,6 +164,16 @@ config SILENT_CONSOLE_UPDATE_ON_RELOC (e.g. NAND). This option makes the value of the 'silent' environment variable take effect at relocation. +config SILENT_CONSOLE_UNTIL_ENV + bool "Keep console silent until environment is loaded" + depends on SILENT_CONSOLE + help + This option makes sure U-Boot will never use the console unless the + environment from flash does not contain the 'silent' variable. If + set, the console is kept silent until after the environment was + loaded. Use this in combination with PRE_CONSOLE_BUFFER to print out + earlier messages after loading the environment when allowed. + config PRE_CONSOLE_BUFFER bool "Buffer characters before the console is available" help diff --git a/common/console.c b/common/console.c index 10ab361d00..e4301a4932 100644 --- a/common/console.c +++ b/common/console.c @@ -970,6 +970,11 @@ static bool console_update_silent(void) if (!IS_ENABLED(CONFIG_SILENT_CONSOLE)) return false; + if (IS_ENABLED(CONFIG_SILENT_CONSOLE_UNTIL_ENV) && !(gd->flags & GD_FLG_ENV_READY)) { + gd->flags |= GD_FLG_SILENT; + return false; + } + if (env_get("silent")) { gd->flags |= GD_FLG_SILENT; return false; From c40e021b83d9db9aec736a0cb992fd84d2e63c02 Mon Sep 17 00:00:00 2001 From: chenzhipeng Date: Tue, 6 Dec 2022 17:24:38 +0800 Subject: [PATCH 02/13] cmd: spi: Judge the number of added parameters When only sspi is entered, help information can be printed. Signed-off-by: chenzhipeng Reviewed-by: Simon Glass --- cmd/spi.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/cmd/spi.c b/cmd/spi.c index 454ebe37d7..f30018f33b 100644 --- a/cmd/spi.c +++ b/cmd/spi.c @@ -112,6 +112,9 @@ int do_spi(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[]) if ((flag & CMD_FLAG_REPEAT) == 0) { + if (argc < 2) + return CMD_RET_USAGE; + if (argc >= 2) { mode = CONFIG_DEFAULT_SPI_MODE; bus = dectoul(argv[1], &cp); From cf7aa035433a73969a8e7b8e3261410bdeb0a214 Mon Sep 17 00:00:00 2001 From: Nikita Shubin Date: Mon, 12 Dec 2022 11:03:35 +0300 Subject: [PATCH 03/13] common: spl: ram: fix return code Instead of always retuning success, return actual result of load_simple_fit_image or spl_parse_image_header, otherwise we might end up jumping on uninitialized spl_image->entry_point. Signed-off-by: Nikita Shubin Reviewed-by: Stefan Roese --- common/spl/spl_ram.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/common/spl/spl_ram.c b/common/spl/spl_ram.c index 5753bd228f..8139a20327 100644 --- a/common/spl/spl_ram.c +++ b/common/spl/spl_ram.c @@ -38,12 +38,13 @@ static int spl_ram_load_image(struct spl_image_info *spl_image, struct spl_boot_device *bootdev) { struct legacy_img_hdr *header; + int ret; header = (struct legacy_img_hdr *)CONFIG_SPL_LOAD_FIT_ADDRESS; if (CONFIG_IS_ENABLED(IMAGE_PRE_LOAD)) { unsigned long addr = (unsigned long)header; - int ret = image_pre_load(addr); + ret = image_pre_load(addr); if (ret) return ret; @@ -64,7 +65,7 @@ static int spl_ram_load_image(struct spl_image_info *spl_image, debug("Found FIT\n"); load.bl_len = 1; load.read = spl_ram_load_read; - spl_load_simple_fit(spl_image, &load, 0, header); + ret = spl_load_simple_fit(spl_image, &load, 0, header); } else { ulong u_boot_pos = spl_get_image_pos(); @@ -85,10 +86,10 @@ static int spl_ram_load_image(struct spl_image_info *spl_image, } header = (struct legacy_img_hdr *)map_sysmem(u_boot_pos, 0); - spl_parse_image_header(spl_image, bootdev, header); + ret = spl_parse_image_header(spl_image, bootdev, header); } - return 0; + return ret; } #if CONFIG_IS_ENABLED(RAM_DEVICE) SPL_LOAD_IMAGE_METHOD("RAM", 0, BOOT_DEVICE_RAM, spl_ram_load_image); From 0d795c356a8ac1d878ea5f0ebd5e222bf14d26ed Mon Sep 17 00:00:00 2001 From: Kshitiz Varshney Date: Thu, 22 Dec 2022 09:50:27 +0100 Subject: [PATCH 04/13] Uboot RNG Driver using Data Co-processor This commit introduces Random number generator to uboot. It uses DCP driver for number generation. RNG driver can be invoked by using below command on uboot prompt:- rng Signed-off-by: Kshitiz Varshney Reviewed-by: Ye Li Reviewed-by: Simon Glass --- drivers/crypto/fsl/Kconfig | 10 ++ drivers/crypto/fsl/Makefile | 1 + drivers/crypto/fsl/dcp_rng.c | 182 +++++++++++++++++++++++++++++++++++ 3 files changed, 193 insertions(+) create mode 100644 drivers/crypto/fsl/dcp_rng.c diff --git a/drivers/crypto/fsl/Kconfig b/drivers/crypto/fsl/Kconfig index b04c70183d..91a51cc5fe 100644 --- a/drivers/crypto/fsl/Kconfig +++ b/drivers/crypto/fsl/Kconfig @@ -73,3 +73,13 @@ config FSL_CAAM_RNG reseeded from the TRNG every time random data is generated. endif + +config FSL_DCP_RNG + bool "Enable Random Number Generator support" + depends on DM_RNG + default n + help + Enable support for the hardware based random number generator + module of the DCP. It uses the True Random Number Generator (TRNG) + and a Pseudo-Random Number Generator (PRNG) to achieve a true + randomness and cryptographic strength. diff --git a/drivers/crypto/fsl/Makefile b/drivers/crypto/fsl/Makefile index f9c3ccecfc..7a2543e16c 100644 --- a/drivers/crypto/fsl/Makefile +++ b/drivers/crypto/fsl/Makefile @@ -7,4 +7,5 @@ obj-$(CONFIG_FSL_CAAM) += jr.o fsl_hash.o jobdesc.o error.o obj-$(CONFIG_CMD_BLOB)$(CONFIG_IMX_CAAM_DEK_ENCAP) += fsl_blob.o obj-$(CONFIG_RSA_FREESCALE_EXP) += fsl_rsa.o obj-$(CONFIG_FSL_CAAM_RNG) += rng.o +obj-$(CONFIG_FSL_DCP_RNG) += dcp_rng.o obj-$(CONFIG_FSL_MFGPROT) += fsl_mfgprot.o diff --git a/drivers/crypto/fsl/dcp_rng.c b/drivers/crypto/fsl/dcp_rng.c new file mode 100644 index 0000000000..3170696015 --- /dev/null +++ b/drivers/crypto/fsl/dcp_rng.c @@ -0,0 +1,182 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/* + * RNG driver for Freescale RNGC + * + * Copyright 2022 NXP + * + * Based on RNGC driver in drivers/char/hw_random/imx-rngc.c in Linux + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define DCP_RNG_MAX_FIFO_STORE_SIZE 4 +#define RNGC_VER_ID 0x0 +#define RNGC_COMMAND 0x4 +#define RNGC_CONTROL 0x8 +#define RNGC_STATUS 0xC +#define RNGC_ERROR 0x10 +#define RNGC_FIFO 0x14 + +/* the fields in the ver id register */ +#define RNGC_TYPE_SHIFT 28 + +/* the rng_type field */ +#define RNGC_TYPE_RNGB 0x1 +#define RNGC_TYPE_RNGC 0x2 + +#define RNGC_CMD_CLR_ERR 0x20 +#define RNGC_CMD_SEED 0x2 + +#define RNGC_CTRL_AUTO_SEED 0x10 + +#define RNGC_STATUS_ERROR 0x10000 +#define RNGC_STATUS_FIFO_LEVEL_MASK 0xf00 +#define RNGC_STATUS_FIFO_LEVEL_SHIFT 8 +#define RNGC_STATUS_SEED_DONE 0x20 +#define RNGC_STATUS_ST_DONE 0x10 + +#define RNGC_ERROR_STATUS_STAT_ERR 0x8 + +#define RNGC_TIMEOUT 3000000U /* 3 sec */ + +struct imx_rngc_priv { + unsigned long base; +}; + +static int rngc_read(struct udevice *dev, void *data, size_t len) +{ + struct imx_rngc_priv *priv = dev_get_priv(dev); + u8 buffer[DCP_RNG_MAX_FIFO_STORE_SIZE]; + u32 status, level; + size_t size; + + while (len) { + status = readl(priv->base + RNGC_STATUS); + + /* is there some error while reading this random number? */ + if (status & RNGC_STATUS_ERROR) + break; + /* how many random numbers are in FIFO? [0-16] */ + level = (status & RNGC_STATUS_FIFO_LEVEL_MASK) >> + RNGC_STATUS_FIFO_LEVEL_SHIFT; + + if (level) { + /* retrieve a random number from FIFO */ + *(u32 *)buffer = readl(priv->base + RNGC_FIFO); + size = min(len, sizeof(u32)); + memcpy(data, buffer, size); + data += size; + len -= size; + } + } + + return len ? -EIO : 0; +} + +static int rngc_init(struct imx_rngc_priv *priv) +{ + u32 cmd, ctrl, status, err_reg = 0; + unsigned long long timeval = 0; + unsigned long long timeout = RNGC_TIMEOUT; + + /* clear error */ + cmd = readl(priv->base + RNGC_COMMAND); + writel(cmd | RNGC_CMD_CLR_ERR, priv->base + RNGC_COMMAND); + + /* create seed, repeat while there is some statistical error */ + do { + /* seed creation */ + cmd = readl(priv->base + RNGC_COMMAND); + writel(cmd | RNGC_CMD_SEED, priv->base + RNGC_COMMAND); + + udelay(1); + timeval += 1; + + status = readl(priv->base + RNGC_STATUS); + err_reg = readl(priv->base + RNGC_ERROR); + + if (status & (RNGC_STATUS_SEED_DONE | RNGC_STATUS_ST_DONE)) + break; + + if (timeval > timeout) { + debug("rngc timed out\n"); + return -ETIMEDOUT; + } + } while (err_reg == RNGC_ERROR_STATUS_STAT_ERR); + + if (err_reg) + return -EIO; + + /* + * enable automatic seeding, the rngc creates a new seed automatically + * after serving 2^20 random 160-bit words + */ + ctrl = readl(priv->base + RNGC_CONTROL); + ctrl |= RNGC_CTRL_AUTO_SEED; + writel(ctrl, priv->base + RNGC_CONTROL); + return 0; +} + +static int rngc_probe(struct udevice *dev) +{ + struct imx_rngc_priv *priv = dev_get_priv(dev); + fdt_addr_t addr; + u32 ver_id; + u8 rng_type; + int ret; + + addr = dev_read_addr(dev); + if (addr == FDT_ADDR_T_NONE) { + ret = -EINVAL; + goto err; + } + + priv->base = addr; + ver_id = readl(priv->base + RNGC_VER_ID); + rng_type = ver_id >> RNGC_TYPE_SHIFT; + /* + * This driver supports only RNGC and RNGB. (There's a different + * driver for RNGA.) + */ + if (rng_type != RNGC_TYPE_RNGC && rng_type != RNGC_TYPE_RNGB) { + ret = -ENODEV; + goto err; + } + + ret = rngc_init(priv); + if (ret) + goto err; + + return 0; + +err: + printf("%s error = %d\n", __func__, ret); + return ret; +} + +static const struct dm_rng_ops rngc_ops = { + .read = rngc_read, +}; + +static const struct udevice_id rngc_dt_ids[] = { + { .compatible = "fsl,imx25-rngb" }, + { } +}; + +U_BOOT_DRIVER(dcp_rng) = { + .name = "dcp_rng", + .id = UCLASS_RNG, + .of_match = rngc_dt_ids, + .ops = &rngc_ops, + .probe = rngc_probe, + .priv_auto = sizeof(struct imx_rngc_priv), + .flags = DM_FLAG_ALLOC_PRIV_DMA, +}; From 81ceb1695a04f6bee4f74dec12e78d57759d0715 Mon Sep 17 00:00:00 2001 From: Kshitiz Varshney Date: Thu, 22 Dec 2022 09:50:28 +0100 Subject: [PATCH 05/13] Added dcp_rng driver initialization code This commit initializes dcp_rng device driver inside arch_misc_init() function. Signed-off-by: Kshitiz Varshney Reviewed-by: Ye Li --- arch/arm/mach-imx/mx6/soc.c | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/arch/arm/mach-imx/mx6/soc.c b/arch/arm/mach-imx/mx6/soc.c index 08f47cf03d..c2875e727c 100644 --- a/arch/arm/mach-imx/mx6/soc.c +++ b/arch/arm/mach-imx/mx6/soc.c @@ -746,6 +746,16 @@ int arch_misc_init(void) if (ret) printf("Failed to initialize caam_jr: %d\n", ret); } + + if (IS_ENABLED(CONFIG_FSL_DCP_RNG)) { + struct udevice *dev; + int ret; + + ret = uclass_get_device_by_driver(UCLASS_RNG, DM_DRIVER_GET(dcp_rng), &dev); + if (ret) + printf("Failed to initialize dcp rng: %d\n", ret); + } + setup_serial_number(); return 0; } From 7fb4aa14d4e8435e149b560bed33a8ad78897463 Mon Sep 17 00:00:00 2001 From: Kshitiz Varshney Date: Thu, 22 Dec 2022 09:50:29 +0100 Subject: [PATCH 06/13] Added configs required for dcp_rng driver This commit adds configs required for using dcp_rng driver in imx6ull defconfig files. Signed-off-by: Kshitiz Varshney Reviewed-by: Ye Li --- configs/mx6ull_14x14_evk_defconfig | 4 ++++ configs/mx6ull_14x14_evk_plugin_defconfig | 4 ++++ 2 files changed, 8 insertions(+) diff --git a/configs/mx6ull_14x14_evk_defconfig b/configs/mx6ull_14x14_evk_defconfig index 65db621f15..881bc27a69 100644 --- a/configs/mx6ull_14x14_evk_defconfig +++ b/configs/mx6ull_14x14_evk_defconfig @@ -65,3 +65,7 @@ CONFIG_DM_SPI=y CONFIG_FSL_QSPI=y CONFIG_SOFT_SPI=y CONFIG_IMX_THERMAL=y +CONFIG_ARCH_MISC_INIT=y +CONFIG_DM_RNG=y +CONFIG_CMD_RNG=y +CONFIG_FSL_DCP_RNG=y diff --git a/configs/mx6ull_14x14_evk_plugin_defconfig b/configs/mx6ull_14x14_evk_plugin_defconfig index 55ddd7eabb..5e6766282e 100644 --- a/configs/mx6ull_14x14_evk_plugin_defconfig +++ b/configs/mx6ull_14x14_evk_plugin_defconfig @@ -64,3 +64,7 @@ CONFIG_DM_SPI=y CONFIG_FSL_QSPI=y CONFIG_SOFT_SPI=y CONFIG_IMX_THERMAL=y +CONFIG_ARCH_MISC_INIT=y +CONFIG_DM_RNG=y +CONFIG_CMD_RNG=y +CONFIG_FSL_DCP_RNG=y From 0998a20cfc6b57e271d597153e39439c37034206 Mon Sep 17 00:00:00 2001 From: Sean Anderson Date: Thu, 29 Dec 2022 11:52:59 -0500 Subject: [PATCH 07/13] misc: fs_loader: Add function to get the chosen loader The fs_loader device is used to pull in settings via the chosen node. However, there was no library function for this, so arria10 was doing it explicitly. This function subsumes that, and uses ofnode_get_chosen_node instead of navigating the device tree directly. Because fs_loader pulls its config from the environment by default, it's fine to create a device with nothing backing it at all. Doing this allows enabling CONFIG_FS_LOADER without needing to modify the device tree. Signed-off-by: Sean Anderson Reviewed-by: Simon Glass Reviewed-by: Ramon Fried --- arch/arm/mach-k3/common.c | 2 +- arch/arm/mach-omap2/boot-common.c | 2 +- drivers/fpga/socfpga_arria10.c | 28 +++------------------------- drivers/misc/fs_loader.c | 27 +++++++++++++++++++++++++++ include/fs_loader.h | 12 ++++++++++++ 5 files changed, 44 insertions(+), 27 deletions(-) diff --git a/arch/arm/mach-k3/common.c b/arch/arm/mach-k3/common.c index d5e1f8e2e7..a2adb791f6 100644 --- a/arch/arm/mach-k3/common.c +++ b/arch/arm/mach-k3/common.c @@ -181,7 +181,7 @@ int load_firmware(char *name_fw, char *name_loadaddr, u32 *loadaddr) if (!*loadaddr) return 0; - if (!uclass_get_device(UCLASS_FS_FIRMWARE_LOADER, 0, &fsdev)) { + if (!get_fs_loader(&fsdev)) { size = request_firmware_into_buf(fsdev, name, (void *)*loadaddr, 0, 0); } diff --git a/arch/arm/mach-omap2/boot-common.c b/arch/arm/mach-omap2/boot-common.c index d104f23b3e..9a342a1bf9 100644 --- a/arch/arm/mach-omap2/boot-common.c +++ b/arch/arm/mach-omap2/boot-common.c @@ -214,7 +214,7 @@ int load_firmware(char *name_fw, u32 *loadaddr) if (!*loadaddr) return 0; - if (!uclass_get_device(UCLASS_FS_FIRMWARE_LOADER, 0, &fsdev)) { + if (!get_fs_loader(&fsdev)) { size = request_firmware_into_buf(fsdev, name_fw, (void *)*loadaddr, 0, 0); } diff --git a/drivers/fpga/socfpga_arria10.c b/drivers/fpga/socfpga_arria10.c index 3b785e67d0..96b195063e 100644 --- a/drivers/fpga/socfpga_arria10.c +++ b/drivers/fpga/socfpga_arria10.c @@ -777,42 +777,20 @@ int socfpga_loadfs(fpga_fs_info *fpga_fsinfo, const void *buf, size_t bsize, { struct fpga_loadfs_info fpga_loadfs; struct udevice *dev; - int status, ret, size; + int status, ret; u32 buffer = (uintptr_t)buf; size_t buffer_sizebytes = bsize; size_t buffer_sizebytes_ori = bsize; size_t total_sizeof_image = 0; ofnode node; - const fdt32_t *phandle_p; - u32 phandle; node = get_fpga_mgr_ofnode(ofnode_null()); - - if (ofnode_valid(node)) { - phandle_p = ofnode_get_property(node, "firmware-loader", &size); - if (!phandle_p) { - node = ofnode_path("/chosen"); - if (!ofnode_valid(node)) { - debug("FPGA: /chosen node was not found.\n"); - return -ENOENT; - } - - phandle_p = ofnode_get_property(node, "firmware-loader", - &size); - if (!phandle_p) { - debug("FPGA: firmware-loader property was not"); - debug(" found.\n"); - return -ENOENT; - } - } - } else { + if (!ofnode_valid(node)) { debug("FPGA: FPGA manager node was not found.\n"); return -ENOENT; } - phandle = fdt32_to_cpu(*phandle_p); - ret = uclass_get_device_by_phandle_id(UCLASS_FS_FIRMWARE_LOADER, - phandle, &dev); + ret = get_fs_loader(&dev); if (ret) return ret; diff --git a/drivers/misc/fs_loader.c b/drivers/misc/fs_loader.c index 5b4d03639c..ccf5c7a803 100644 --- a/drivers/misc/fs_loader.c +++ b/drivers/misc/fs_loader.c @@ -15,6 +15,8 @@ #include #include #include +#include +#include #include #include #include @@ -297,6 +299,31 @@ U_BOOT_DRIVER(fs_loader) = { .priv_auto = sizeof(struct firmware), }; +static struct device_plat default_plat = { 0 }; + +int get_fs_loader(struct udevice **dev) +{ + int ret; + ofnode node = ofnode_get_chosen_node("firmware-loader"); + + if (ofnode_valid(node)) + return uclass_get_device_by_ofnode(UCLASS_FS_FIRMWARE_LOADER, + node, dev); + + /* Try the first device if none was chosen */ + ret = uclass_first_device_err(UCLASS_FS_FIRMWARE_LOADER, dev); + if (ret != -ENODEV) + return ret; + + /* Just create a new device */ + ret = device_bind(dm_root(), DM_DRIVER_GET(fs_loader), "default-loader", + &default_plat, ofnode_null(), dev); + if (ret) + return ret; + + return device_probe(*dev); +} + UCLASS_DRIVER(fs_loader) = { .id = UCLASS_FS_FIRMWARE_LOADER, .name = "fs-loader", diff --git a/include/fs_loader.h b/include/fs_loader.h index 8de7cb18dc..5eb5b7ab4a 100644 --- a/include/fs_loader.h +++ b/include/fs_loader.h @@ -52,4 +52,16 @@ struct device_plat { int request_firmware_into_buf(struct udevice *dev, const char *name, void *buf, size_t size, u32 offset); + +/** + * get_fs_loader() - Get the chosen filesystem loader + * @dev: Where to store the device + * + * This gets a filesystem loader device based on the value of + * /chosen/firmware-loader. If no such property exists, it returns a + * firmware loader which is configured by environmental variables. + * + * Return: 0 on success, negative value on error + */ +int get_fs_loader(struct udevice **dev); #endif From e4f0cc5ddf6ad24e06fcd6a25bbaaf3d55fa0899 Mon Sep 17 00:00:00 2001 From: Sean Anderson Date: Thu, 29 Dec 2022 11:53:00 -0500 Subject: [PATCH 08/13] net: fm: Add firmware name parameter In order to read the firmware from the filesystem, we need a file name. Read the firmware name from the device tree, using the firmware-name property. This property is commonly used in Linux to determine the correct name to use (and can be seen in several device trees in U-Boot). Signed-off-by: Sean Anderson Reviewed-by: Ramon Fried --- drivers/net/fm/fm.c | 15 ++++++++++++--- drivers/net/fm/fm.h | 2 +- 2 files changed, 13 insertions(+), 4 deletions(-) diff --git a/drivers/net/fm/fm.c b/drivers/net/fm/fm.c index 055dd61fbe..457200e766 100644 --- a/drivers/net/fm/fm.c +++ b/drivers/net/fm/fm.c @@ -8,6 +8,7 @@ #include #include #include +#include #include #include #include @@ -353,7 +354,7 @@ static void fm_init_qmi(struct fm_qmi_common *qmi) /* Init common part of FM, index is fm num# like fm as above */ #ifdef CONFIG_TFABOOT -int fm_init_common(int index, struct ccsr_fman *reg) +int fm_init_common(int index, struct ccsr_fman *reg, const char *firmware_name) { int rc; void *addr = NULL; @@ -448,7 +449,7 @@ int fm_init_common(int index, struct ccsr_fman *reg) return fm_init_bmi(index, ®->fm_bmi_common); } #else -int fm_init_common(int index, struct ccsr_fman *reg) +int fm_init_common(int index, struct ccsr_fman *reg, const char *firmware_name) { int rc; #if defined(CONFIG_SYS_QE_FMAN_FW_IN_NOR) @@ -561,6 +562,8 @@ static const struct udevice_id fman_ids[] = { static int fman_probe(struct udevice *dev) { + const char *firmware_name = NULL; + int ret; struct fman_priv *priv = dev_get_priv(dev); priv->reg = (struct ccsr_fman *)(uintptr_t)dev_read_addr(dev); @@ -570,7 +573,13 @@ static int fman_probe(struct udevice *dev) return -EINVAL; } - return fm_init_common(priv->fman_id, priv->reg); + ret = dev_read_string_index(dev, "firmware-name", 0, &firmware_name); + if (ret && ret != -EINVAL) { + dev_dbg(dev, "Could not read firmware-name\n"); + return ret; + } + + return fm_init_common(priv->fman_id, priv->reg, firmware_name); } static int fman_remove(struct udevice *dev) diff --git a/drivers/net/fm/fm.h b/drivers/net/fm/fm.h index ba858cc24b..a2d5b03429 100644 --- a/drivers/net/fm/fm.h +++ b/drivers/net/fm/fm.h @@ -106,7 +106,7 @@ struct fm_port_global_pram { void *fm_muram_alloc(int fm_idx, size_t size, ulong align); void *fm_muram_base(int fm_idx); -int fm_init_common(int index, struct ccsr_fman *reg); +int fm_init_common(int index, struct ccsr_fman *reg, const char *firmware_name); int fm_eth_initialize(struct ccsr_fman *reg, struct fm_eth_info *info); phy_interface_t fman_port_enet_if(enum fm_port port); void fman_disable_port(enum fm_port port); From f4426fd68d604fc3f823979d7f643938894df167 Mon Sep 17 00:00:00 2001 From: Sean Anderson Date: Thu, 29 Dec 2022 11:53:01 -0500 Subject: [PATCH 09/13] net: fm: Support loading firmware from a filesystem This adds a new method to load Fman firmware from a filesystem. This allows users to use regular files instead of hard-coded offsets for the firmware. Signed-off-by: Sean Anderson Reviewed-by: Ramon Fried --- drivers/net/fm/fm.c | 25 ++++++++++++++++++++++++- drivers/qe/Kconfig | 4 ++++ 2 files changed, 28 insertions(+), 1 deletion(-) diff --git a/drivers/net/fm/fm.c b/drivers/net/fm/fm.c index 457200e766..e1fba24471 100644 --- a/drivers/net/fm/fm.c +++ b/drivers/net/fm/fm.c @@ -5,6 +5,7 @@ */ #include #include +#include #include #include #include @@ -452,7 +453,29 @@ int fm_init_common(int index, struct ccsr_fman *reg, const char *firmware_name) int fm_init_common(int index, struct ccsr_fman *reg, const char *firmware_name) { int rc; -#if defined(CONFIG_SYS_QE_FMAN_FW_IN_NOR) +#if defined(CONFIG_SYS_QE_FMAN_FW_IN_FS) + struct udevice *fs_loader; + void *addr = malloc(CONFIG_SYS_QE_FMAN_FW_LENGTH); + + if (!addr) + return -ENOMEM; + + rc = get_fs_loader(&fs_loader); + if (rc) { + debug("could not get fs loader: %d\n", rc); + return rc; + } + + if (!firmware_name) + firmware_name = "fman.itb"; + + rc = request_firmware_into_buf(fs_loader, firmware_name, addr, + CONFIG_SYS_QE_FMAN_FW_LENGTH, 0); + if (rc < 0) { + debug("could not request %s: %d\n", firmware_name, rc); + return rc; + } +#elif defined(CONFIG_SYS_QE_FMAN_FW_IN_NOR) void *addr = (void *)CONFIG_SYS_FMAN_FW_ADDR; #elif defined(CONFIG_SYS_QE_FMAN_FW_IN_NAND) size_t fw_length = CONFIG_SYS_QE_FMAN_FW_LENGTH; diff --git a/drivers/qe/Kconfig b/drivers/qe/Kconfig index c44a81f69a..89a75c175b 100644 --- a/drivers/qe/Kconfig +++ b/drivers/qe/Kconfig @@ -27,6 +27,10 @@ choice depends on FMAN_ENET || QE default SYS_QE_FMAN_FW_IN_ROM +config SYS_QE_FMAN_FW_IN_FS + depends on FS_LOADER && FMAN_ENET + bool "Filesystem" + config SYS_QE_FMAN_FW_IN_NOR bool "NOR flash" From ea3d28ec31d64cd059683947746ac71c8a90a1f9 Mon Sep 17 00:00:00 2001 From: Harald Seiler Date: Thu, 5 Jan 2023 01:08:47 +0100 Subject: [PATCH 10/13] Revert "time: add weak annotation to timer_read_counter declaration" This reverts commit 65ba7add0d609bbd035b8d42fafdaf428ac24751. A weak extern is a nasty sight to behold: If the symbol is never defined, on ARM, the linker will replace the function call with a NOP. This behavior isn't well documented but there are at least some hints to it [1]. When timer_read_counter() is not defined, this obviously does the wrong thing here and it does so silently. The consequence is that a board without timer_read_counter() will sleep for random amounts and generally have erratic get_ticks() values. Drop the __weak annotation of the extern so a linker error is raised when timer_read_counter() is not defined. This is okay, the original reason for the reverted change - breaking the sandbox build - no longer applies. Final sidenote: This was the only weak extern in the entire tree at this time as far as I can tell. I guess we should avoid introduction of them again as they are obviously a very big footgun. [1]: https://stackoverflow.com/questions/31203402/gcc-behavior-for-unresolved-weak-functions Fixes: 65ba7add0d60 ("time: add weak annotation to timer_read_counter declaration") Reported-by: Serge Bazanski Signed-off-by: Harald Seiler --- lib/time.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/time.c b/lib/time.c index 82350260ea..0c95d12f61 100644 --- a/lib/time.c +++ b/lib/time.c @@ -63,7 +63,7 @@ ulong timer_get_boot_us(void) } #else -extern unsigned long __weak timer_read_counter(void); +extern unsigned long timer_read_counter(void); #endif #if CONFIG_IS_ENABLED(TIMER) From d0ba0ca45a49d6a062d0bc94b3380ea9b9616284 Mon Sep 17 00:00:00 2001 From: Marek Vasut Date: Thu, 5 Jan 2023 14:08:23 +0100 Subject: [PATCH 11/13] distro_bootcmd: Set distro_bootpart_uuid for block devices The assignment of block device nodes in Linux is not deterministic by default, i.e. a newly added eMMC controller or other block device can change the assignment of /dev/mmcblkN (or other block device node like e.g. /dev/sdXy) and prevent the system from picking the correct block device for root filesystem in case the root filesystem is specified on kernel command line using 'root=/dev/mmcblkNpM' (or 'root=/dev/sdXy' etc.). One way out is to derive PARTUUID in U-Boot, which is unique identifier of a partition, and pass that as root=PARTUUID= to Linux via kernel command line. Linux would then find the partition using PARTUUID, no matter on which block device the partition resides and which node was assigned to that block device. Derive the PARTUUID before scanning for extlinux presence and assign it into distro_bootpart_uuid environment variable, which can then be used in extlinux.conf kernel command line specifier. Note that it is not possible to do this in scan_dev_for_extlinux script because this script is called from scan_dev_for_boot script, which is called for both block devices as well as UBI volumes, and we can not derive PARTUUID for UBI volumes. Signed-off-by: Marek Vasut --- include/config_distro_bootcmd.h | 3 +++ 1 file changed, 3 insertions(+) diff --git a/include/config_distro_bootcmd.h b/include/config_distro_bootcmd.h index c3a2414b91..9d2a225e7e 100644 --- a/include/config_distro_bootcmd.h +++ b/include/config_distro_bootcmd.h @@ -521,6 +521,9 @@ "if fstype ${devtype} " \ "${devnum}:${distro_bootpart} " \ "bootfstype; then " \ + "part uuid ${devtype} " \ + "${devnum}:${distro_bootpart} " \ + "distro_bootpart_uuid ; " \ "run scan_dev_for_boot; " \ "fi; " \ "done; " \ From 942918f2acd3634dee7813f7b9f801ffd54d9f2e Mon Sep 17 00:00:00 2001 From: Quentin Schulz Date: Thu, 22 Sep 2022 17:53:25 +0200 Subject: [PATCH 12/13] dm: fix probing of all devices that have u-boot, dm-pre-reloc in SPL/TPL Currently, dm_probe_devices checks that the flags of the device contains DM_FLAG_PRE_RELOC. However DM_FLAG_PRE_RELOC is a driver - and not a device - flag. This means that the check in pre_reloc_only mode would always fail. Instead, what was aimed to be checked is that either the driver of the device has the flag set, or that the device has the u-boot,dm-pre-reloc Device Tree property set. So let's fix the check to allow u-boot,dm-pre-reloc devices to be probed. Cc: Quentin Schulz Signed-off-by: Quentin Schulz --- drivers/core/root.c | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/drivers/core/root.c b/drivers/core/root.c index f24ddfa521..c4fb48548b 100644 --- a/drivers/core/root.c +++ b/drivers/core/root.c @@ -363,20 +363,22 @@ void *dm_priv_to_rw(void *priv) static int dm_probe_devices(struct udevice *dev, bool pre_reloc_only) { - u32 mask = DM_FLAG_PROBE_AFTER_BIND; - u32 flags = dev_get_flags(dev); + ofnode node = dev_ofnode(dev); struct udevice *child; int ret; - if (pre_reloc_only) - mask |= DM_FLAG_PRE_RELOC; + if (pre_reloc_only && + (!ofnode_valid(node) || !ofnode_pre_reloc(node)) && + !(dev->driver->flags & DM_FLAG_PRE_RELOC)) + goto probe_children; - if ((flags & mask) == mask) { + if (dev_get_flags(dev) & DM_FLAG_PROBE_AFTER_BIND) { ret = device_probe(dev); if (ret) return ret; } +probe_children: list_for_each_entry(child, &dev->child_head, sibling_node) dm_probe_devices(child, pre_reloc_only); From 48b3ecbedf8208845ac5956a3fb8817269fafedd Mon Sep 17 00:00:00 2001 From: Marek Vasut Date: Thu, 22 Sep 2022 17:53:26 +0200 Subject: [PATCH 13/13] gpio: Get rid of gpio_hog_probe_all() The gpio_hog_probe_all() functionality can be perfectly well replaced by DM_FLAG_PROBE_AFTER_BIND DM flag, which would trigger .probe() callback of each GPIO hog driver instance after .bind() and thus configure the hogged GPIO accordingly. Signed-off-by: Marek Vasut Signed-off-by: Quentin Schulz Reviewed-by: Patrick Delaunay Reviewed-by: Samuel Holland --- common/board_r.c | 3 --- common/spl/spl.c | 3 --- doc/README.gpio | 6 ++---- drivers/gpio/gpio-uclass.c | 31 ++++++++----------------------- include/asm-generic/gpio.h | 8 -------- 5 files changed, 10 insertions(+), 41 deletions(-) diff --git a/common/board_r.c b/common/board_r.c index 42060ee709..3618acad43 100644 --- a/common/board_r.c +++ b/common/board_r.c @@ -756,9 +756,6 @@ static init_fnc_t init_sequence_r[] = { initr_status_led, #endif /* PPC has a udelay(20) here dating from 2002. Why? */ -#if defined(CONFIG_GPIO_HOG) - gpio_hog_probe_all, -#endif #ifdef CONFIG_BOARD_LATE_INIT board_late_init, #endif diff --git a/common/spl/spl.c b/common/spl/spl.c index 4668367b68..a630e79866 100644 --- a/common/spl/spl.c +++ b/common/spl/spl.c @@ -786,9 +786,6 @@ void board_init_r(gd_t *dummy1, ulong dummy2) } } - if (CONFIG_IS_ENABLED(GPIO_HOG)) - gpio_hog_probe_all(); - #if CONFIG_IS_ENABLED(BOARD_INIT) spl_board_init(); #endif diff --git a/doc/README.gpio b/doc/README.gpio index 548ff37b8c..d253f654fa 100644 --- a/doc/README.gpio +++ b/doc/README.gpio @@ -2,10 +2,8 @@ GPIO hog (CONFIG_GPIO_HOG) -------- -All the GPIO hog are initialized in gpio_hog_probe_all() function called in -board_r.c just before board_late_init() but you can also acces directly to -the gpio with gpio_hog_lookup_name(). - +All the GPIO hog are initialized using DM_FLAG_PROBE_AFTER_BIND DM flag +after bind(). Example, for the device tree: diff --git a/drivers/gpio/gpio-uclass.c b/drivers/gpio/gpio-uclass.c index 3a6ef3b01d..dbebf3a53e 100644 --- a/drivers/gpio/gpio-uclass.c +++ b/drivers/gpio/gpio-uclass.c @@ -311,34 +311,11 @@ static int gpio_hog_probe(struct udevice *dev) return 0; } -int gpio_hog_probe_all(void) -{ - struct udevice *dev; - int ret; - int retval = 0; - - for (uclass_first_device(UCLASS_NOP, &dev); - dev; - uclass_find_next_device(&dev)) { - if (dev->driver == DM_DRIVER_GET(gpio_hog)) { - ret = device_probe(dev); - if (ret) { - printf("Failed to probe device %s err: %d\n", - dev->name, ret); - retval = ret; - } - } - } - - return retval; -} - int gpio_hog_lookup_name(const char *name, struct gpio_desc **desc) { struct udevice *dev; *desc = NULL; - gpio_hog_probe_all(); if (!uclass_get_device_by_name(UCLASS_NOP, name, &dev)) { struct gpio_hog_priv *priv = dev_get_priv(dev); @@ -1505,9 +1482,17 @@ static int gpio_post_bind(struct udevice *dev) &child); if (ret) return ret; + + /* + * Make sure gpio-hogs are probed after bind + * since hogs can be essential to the hardware + * system. + */ + dev_or_flags(child, DM_FLAG_PROBE_AFTER_BIND); } } } + return 0; } diff --git a/include/asm-generic/gpio.h b/include/asm-generic/gpio.h index 0fcf70983f..dd0bdf2315 100644 --- a/include/asm-generic/gpio.h +++ b/include/asm-generic/gpio.h @@ -461,14 +461,6 @@ int dm_gpio_lookup_name(const char *name, struct gpio_desc *desc); */ int gpio_hog_lookup_name(const char *name, struct gpio_desc **desc); -/** - * gpio_hog_probe_all() - probe all gpio devices with - * gpio-hog subnodes. - * - * @return: Returns return value from device_probe() - */ -int gpio_hog_probe_all(void); - /** * gpio_lookup_name - Look up a GPIO name and return its details *