From 812aca5791404ad5df469fe3240638573e39e063 Mon Sep 17 00:00:00 2001 From: Peter Robinson Date: Tue, 21 Apr 2026 09:51:59 +0100 Subject: [PATCH 01/48] video: arm: rpi: Add brcm,bcm2712-hdmi0 compatible The 'brcm,bcm2712-hdmi0' compatible string is used on RPi5. There appears to be no change that impacts early boot output on the display controller so add the RPi5 compatible string. Signed-off-by: Peter Robinson Reviewed-by: Matthias Brugger --- drivers/video/bcm2835.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/video/bcm2835.c b/drivers/video/bcm2835.c index 0c81e606622..0e0cc1979eb 100644 --- a/drivers/video/bcm2835.c +++ b/drivers/video/bcm2835.c @@ -66,6 +66,7 @@ static int bcm2835_video_probe(struct udevice *dev) static const struct udevice_id bcm2835_video_ids[] = { { .compatible = "brcm,bcm2835-hdmi" }, { .compatible = "brcm,bcm2711-hdmi0" }, + { .compatible = "brcm,bcm2712-hdmi0" }, { .compatible = "brcm,bcm2708-fb" }, #if !IS_ENABLED(CONFIG_VIDEO_DT_SIMPLEFB) { .compatible = "simple-framebuffer" }, From 17ceb774a1854dd9632ee724266d29b907e51678 Mon Sep 17 00:00:00 2001 From: Peter Robinson Date: Tue, 21 Apr 2026 15:11:38 +0100 Subject: [PATCH 02/48] rpi_arm64: Enable MBEDTLS/LWIP/WGET and WGET_HTTPS Enable LWIP and HTTPS on the Raspberry Pi arm64 platform to be able to use it in the boot process. Signed-off-by: Peter Robinson Reviewed-by: Matthias Brugger --- configs/rpi_arm64_defconfig | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/configs/rpi_arm64_defconfig b/configs/rpi_arm64_defconfig index 69e8e72c5d7..90048a418f6 100644 --- a/configs/rpi_arm64_defconfig +++ b/configs/rpi_arm64_defconfig @@ -11,6 +11,7 @@ CONFIG_SYS_LOAD_ADDR=0x1000000 CONFIG_PCI=y CONFIG_EFI_RUNTIME_UPDATE_CAPSULE=y CONFIG_EFI_CAPSULE_FIRMWARE_RAW=y +CONFIG_EFI_HTTP_BOOT=y CONFIG_BOOTSTD_DEFAULTS=y CONFIG_OF_BOARD_SETUP=y CONFIG_FDT_SIMPLEFB=y @@ -26,11 +27,13 @@ CONFIG_CMD_GPIO=y CONFIG_CMD_MMC=y CONFIG_CMD_PCI=y CONFIG_CMD_USB=y +CONFIG_CMD_SNTP=y +CONFIG_WGET_HTTPS=y CONFIG_CMD_EFIDEBUG=y CONFIG_CMD_FS_UUID=y CONFIG_ENV_FAT_DEVICE_AND_PART="0:1" CONFIG_ENV_VARS_UBOOT_RUNTIME_CONFIG=y -CONFIG_TFTP_TSIZE=y +CONFIG_NET_LWIP=y CONFIG_DM_DMA=y CONFIG_DFU_MMC=y CONFIG_SYS_DFU_DATA_BUF_SIZE=0x100000 @@ -64,4 +67,5 @@ CONFIG_SYS_WHITE_ON_BLACK=y CONFIG_VIDEO_BCM2835=y CONFIG_CONSOLE_SCROLL_LINES=10 CONFIG_PHYS_TO_BUS=y +CONFIG_MBEDTLS_LIB=y # CONFIG_HEXDUMP is not set From 29c7796a718977ac78da7d381daec9828ec8c995 Mon Sep 17 00:00:00 2001 From: Liel Harel Date: Sun, 10 May 2026 00:06:07 +0300 Subject: [PATCH 03/48] mmc: bcm2835_sdhci: Parse generic MMC device tree properties The bcm2835 SDHCI driver sets up the MMC host configuration via sdhci_setup_cfg(), but does not parse generic MMC device tree properties. As a result, properties such as bus-width are ignored. On Raspberry Pi Compute Module 4, the eMMC node describes an 8-bit bus, but U-Boot initialized the device as 4-bit. Call mmc_of_parse() before sdhci_setup_cfg() so that generic MMC properties are folded into the host configuration before the MMC core selects the bus width. Before this change, mmc info reported: Bus Speed: 52000000 Bus Width: 4-bit After this change, mmc info reports: Bus Speed: 52000000 Bus Width: 8-bit Tested on Raspberry Pi Compute Module 4 with onboard eMMC. Signed-off-by: Liel Harel Reviewed-by: Peter Robinson Tested-by: Peter Robinson # on the CM4 as well --- drivers/mmc/bcm2835_sdhci.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/drivers/mmc/bcm2835_sdhci.c b/drivers/mmc/bcm2835_sdhci.c index 655d9902dfa..efa4d14f5da 100644 --- a/drivers/mmc/bcm2835_sdhci.c +++ b/drivers/mmc/bcm2835_sdhci.c @@ -219,6 +219,10 @@ static int bcm2835_sdhci_probe(struct udevice *dev) host->mmc = &plat->mmc; host->mmc->dev = dev; + ret = mmc_of_parse(dev, &plat->cfg); + if (ret) + return ret; + ret = sdhci_setup_cfg(&plat->cfg, host, emmc_freq, MIN_FREQ); if (ret) { debug("%s: Failed to setup SDHCI (err=%d)\n", __func__, ret); From 560d8f32703ffa748197f6b782884952697669ff Mon Sep 17 00:00:00 2001 From: Dario Binacchi Date: Mon, 18 May 2026 08:54:27 +0200 Subject: [PATCH 04/48] board: st: stm32mp15: support dynamic A/B bank bootup Following commit 4300f9f4c5d7 ("board: st: stm32mp25: support dynamic A/B bank bootup"), this patch enables automatic detection of the active A/B bank on STM32MP15 platforms by retrieving partition GUIDs from FWU metadata. This ensures the system correctly identifies the bootable partitions even in multi-bank scenarios, falling back to a standard bootable flag scan if the UUIDs are missing. To enable A/B bank bootup on STM32MP15 boards, add the following Kconfig options to the stm32mp15[_basic]_defconfig: CONFIG_FWU_MULTI_BANK_UPDATE=y CONFIG_FWU_MDATA=y CONFIG_FWU_NUM_BANKS=2 CONFIG_FWU_NUM_IMAGES_PER_BANK=3 CONFIG_CMD_FWU_METADATA=y CONFIG_FWU_MDATA_V2=y Signed-off-by: Dario Binacchi Reviewed-by: Patrice Chotard --- board/st/stm32mp1/stm32mp1.c | 33 +++++++++++++++++++++++++++ include/configs/stm32mp15_st_common.h | 15 ++++++++++++ 2 files changed, 48 insertions(+) diff --git a/board/st/stm32mp1/stm32mp1.c b/board/st/stm32mp1/stm32mp1.c index 88ede4e3910..8164a62e9a3 100644 --- a/board/st/stm32mp1/stm32mp1.c +++ b/board/st/stm32mp1/stm32mp1.c @@ -857,4 +857,37 @@ void fwu_plat_get_bootidx(uint *boot_idx) *boot_idx = (readl(TAMP_FWU_BOOT_INFO_REG) >> TAMP_FWU_BOOT_IDX_OFFSET) & TAMP_FWU_BOOT_IDX_MASK; } + +int fwu_platform_hook(struct udevice *dev, struct fwu_data *data) +{ + uint boot_idx; + efi_guid_t boot_uuid, root_uuid; + const efi_guid_t boot_type_guid = PARTITION_XBOOTLDR; + const efi_guid_t root_type_guid = + PARTITION_LINUX_FILE_SYSTEM_DATA_GUID; + char uuidbuf[UUID_STR_LEN + 1]; + int retb, retr; + + fwu_plat_get_bootidx(&boot_idx); + + retb = fwu_mdata_get_image_guid(&boot_uuid, &boot_type_guid, boot_idx); + retr = fwu_mdata_get_image_guid(&root_uuid, &root_type_guid, boot_idx); + + if (!retb && !retr) { + uuid_bin_to_str(boot_uuid.b, uuidbuf, UUID_STR_FORMAT_GUID); + env_set("boot_partuuid", uuidbuf); + + uuid_bin_to_str(root_uuid.b, uuidbuf, UUID_STR_FORMAT_GUID); + env_set("root_partuuid", uuidbuf); + } else if (!retb && retr) { + log_warning("%s: found boot GUID but missing root GUID (%d)\n", + __func__, retr); + } else if (!retr && retb) { + log_warning("%s: found root GUID but missing boot GUID (%d)\n", + __func__, retb); + } + + return 0; +} #endif /* CONFIG_FWU_MULTI_BANK_UPDATE */ + diff --git a/include/configs/stm32mp15_st_common.h b/include/configs/stm32mp15_st_common.h index 60838cb0e3f..7727e583fc7 100644 --- a/include/configs/stm32mp15_st_common.h +++ b/include/configs/stm32mp15_st_common.h @@ -8,7 +8,22 @@ #ifndef __CONFIG_STM32MP15_ST_COMMON_H__ #define __CONFIG_STM32MP15_ST_COMMON_H__ +#ifdef CONFIG_FWU_MULTI_BANK_UPDATE +#define SCAN_DEV_FOR_BOOT_PARTS \ + "setenv devplist; " \ + "env exists boot_partuuid && " \ + "part number ${devtype} ${devnum} ${boot_partuuid} devplist; " \ + "env exists devplist || " \ + "part list ${devtype} ${devnum} -bootable devplist; " + +#define ST_STM32MP15_FWU_ENV \ + "altbootcmd=${bootcmd}\0" +#else +#define ST_STM32MP15_FWU_ENV +#endif + #define STM32MP_BOARD_EXTRA_ENV \ + ST_STM32MP15_FWU_ENV \ "usb_pgood_delay=2000\0" \ "console=ttySTM0\0" \ "splashimage=" __stringify(CONFIG_SYS_LOAD_ADDR) "\0" \ From 4369c6a05035351089b09e26bd8f4915cd5f5d9f Mon Sep 17 00:00:00 2001 From: Dario Binacchi Date: Mon, 18 May 2026 08:54:28 +0200 Subject: [PATCH 05/48] board: st: factorize STM32MP FWU multi-bank support Factorize FWU multi-bank support code common to STM32MP1 and STM32MP2 platforms into a dedicated shared source file. No functional change intended. Signed-off-by: Dario Binacchi Reviewed-by: Patrice Chotard --- board/st/common/Makefile | 1 + board/st/common/stm32mp_fwu.c | 55 +++++++++++++++++++++++++++++++++++ board/st/stm32mp1/stm32mp1.c | 54 ---------------------------------- board/st/stm32mp2/stm32mp2.c | 53 --------------------------------- 4 files changed, 56 insertions(+), 107 deletions(-) create mode 100644 board/st/common/stm32mp_fwu.c diff --git a/board/st/common/Makefile b/board/st/common/Makefile index 122b13c3aa8..36dfaddfa0e 100644 --- a/board/st/common/Makefile +++ b/board/st/common/Makefile @@ -9,6 +9,7 @@ obj-$(CONFIG_PMIC_STPMIC1) += stpmic1.o ifeq ($(CONFIG_ARCH_STM32MP),y) obj-$(CONFIG_SET_DFU_ALT_INFO) += stm32mp_dfu.o obj-$(CONFIG_$(PHASE_)DFU_VIRT) += stm32mp_dfu_virt.o +obj-$(CONFIG_FWU_MULTI_BANK_UPDATE) += stm32mp_fwu.o endif obj-$(CONFIG_TYPEC_STUSB160X) += stusb160x.o diff --git a/board/st/common/stm32mp_fwu.c b/board/st/common/stm32mp_fwu.c new file mode 100644 index 00000000000..ac7ca6bdca2 --- /dev/null +++ b/board/st/common/stm32mp_fwu.c @@ -0,0 +1,55 @@ +// SPDX-License-Identifier: GPL-2.0+ OR BSD-3-Clause +/* + * Copyright (C) 2026 Amarula Solutions, Dario Binacchi + */ + +#include +#include +#include +/** + * fwu_plat_get_bootidx() - Get the value of the boot index + * @boot_idx: Boot index value + * + * Get the value of the bank(partition) from which the platform + * has booted. This value is passed to U-Boot from the earlier + * stage bootloader which loads and boots all the relevant + * firmware images + * + */ +void fwu_plat_get_bootidx(uint *boot_idx) +{ + *boot_idx = (readl(TAMP_FWU_BOOT_INFO_REG) >> + TAMP_FWU_BOOT_IDX_OFFSET) & TAMP_FWU_BOOT_IDX_MASK; +} + +int fwu_platform_hook(struct udevice *dev, struct fwu_data *data) +{ + uint boot_idx; + efi_guid_t boot_uuid, root_uuid; + const efi_guid_t boot_type_guid = PARTITION_XBOOTLDR; + const efi_guid_t root_type_guid = + PARTITION_LINUX_FILE_SYSTEM_DATA_GUID; + char uuidbuf[UUID_STR_LEN + 1]; + int retb, retr; + + fwu_plat_get_bootidx(&boot_idx); + + retb = fwu_mdata_get_image_guid(&boot_uuid, &boot_type_guid, boot_idx); + retr = fwu_mdata_get_image_guid(&root_uuid, &root_type_guid, boot_idx); + + if (!retb && !retr) { + uuid_bin_to_str(boot_uuid.b, uuidbuf, UUID_STR_FORMAT_GUID); + env_set("boot_partuuid", uuidbuf); + + uuid_bin_to_str(root_uuid.b, uuidbuf, UUID_STR_FORMAT_GUID); + env_set("root_partuuid", uuidbuf); + } else if (!retb && retr) { + log_warning("%s: found boot GUID but missing root GUID (%d)\n", + __func__, retr); + } else if (!retr && retb) { + log_warning("%s: found root GUID but missing boot GUID (%d)\n", + __func__, retb); + } + + return 0; +} diff --git a/board/st/stm32mp1/stm32mp1.c b/board/st/stm32mp1/stm32mp1.c index 8164a62e9a3..9b933a2ba0b 100644 --- a/board/st/stm32mp1/stm32mp1.c +++ b/board/st/stm32mp1/stm32mp1.c @@ -837,57 +837,3 @@ static void board_copro_image_process(ulong fw_image, size_t fw_size) } U_BOOT_FIT_LOADABLE_HANDLER(IH_TYPE_COPRO, board_copro_image_process); - -#if defined(CONFIG_FWU_MULTI_BANK_UPDATE) - -#include - -/** - * fwu_plat_get_bootidx() - Get the value of the boot index - * @boot_idx: Boot index value - * - * Get the value of the bank(partition) from which the platform - * has booted. This value is passed to U-Boot from the earlier - * stage bootloader which loads and boots all the relevant - * firmware images - * - */ -void fwu_plat_get_bootidx(uint *boot_idx) -{ - *boot_idx = (readl(TAMP_FWU_BOOT_INFO_REG) >> - TAMP_FWU_BOOT_IDX_OFFSET) & TAMP_FWU_BOOT_IDX_MASK; -} - -int fwu_platform_hook(struct udevice *dev, struct fwu_data *data) -{ - uint boot_idx; - efi_guid_t boot_uuid, root_uuid; - const efi_guid_t boot_type_guid = PARTITION_XBOOTLDR; - const efi_guid_t root_type_guid = - PARTITION_LINUX_FILE_SYSTEM_DATA_GUID; - char uuidbuf[UUID_STR_LEN + 1]; - int retb, retr; - - fwu_plat_get_bootidx(&boot_idx); - - retb = fwu_mdata_get_image_guid(&boot_uuid, &boot_type_guid, boot_idx); - retr = fwu_mdata_get_image_guid(&root_uuid, &root_type_guid, boot_idx); - - if (!retb && !retr) { - uuid_bin_to_str(boot_uuid.b, uuidbuf, UUID_STR_FORMAT_GUID); - env_set("boot_partuuid", uuidbuf); - - uuid_bin_to_str(root_uuid.b, uuidbuf, UUID_STR_FORMAT_GUID); - env_set("root_partuuid", uuidbuf); - } else if (!retb && retr) { - log_warning("%s: found boot GUID but missing root GUID (%d)\n", - __func__, retr); - } else if (!retr && retb) { - log_warning("%s: found root GUID but missing boot GUID (%d)\n", - __func__, retb); - } - - return 0; -} -#endif /* CONFIG_FWU_MULTI_BANK_UPDATE */ - diff --git a/board/st/stm32mp2/stm32mp2.c b/board/st/stm32mp2/stm32mp2.c index 5cbbbc322a3..7bc7d2a608f 100644 --- a/board/st/stm32mp2/stm32mp2.c +++ b/board/st/stm32mp2/stm32mp2.c @@ -188,56 +188,3 @@ void board_quiesce_devices(void) { led_boot_off(); } - -#if defined(CONFIG_FWU_MULTI_BANK_UPDATE) - -#include - -/** - * fwu_plat_get_bootidx() - Get the value of the boot index - * @boot_idx: Boot index value - * - * Get the value of the bank(partition) from which the platform - * has booted. This value is passed to U-Boot from the earlier - * stage bootloader which loads and boots all the relevant - * firmware images - * - */ -void fwu_plat_get_bootidx(uint *boot_idx) -{ - *boot_idx = (readl(TAMP_FWU_BOOT_INFO_REG) >> - TAMP_FWU_BOOT_IDX_OFFSET) & TAMP_FWU_BOOT_IDX_MASK; -} - -int fwu_platform_hook(struct udevice *dev, struct fwu_data *data) -{ - uint boot_idx; - efi_guid_t boot_uuid, root_uuid; - const efi_guid_t boot_type_guid = PARTITION_XBOOTLDR; - const efi_guid_t root_type_guid = - PARTITION_LINUX_FILE_SYSTEM_DATA_GUID; - char uuidbuf[UUID_STR_LEN + 1]; - int retb, retr; - - fwu_plat_get_bootidx(&boot_idx); - - retb = fwu_mdata_get_image_guid(&boot_uuid, &boot_type_guid, boot_idx); - retr = fwu_mdata_get_image_guid(&root_uuid, &root_type_guid, boot_idx); - - if (!retb && !retr) { - uuid_bin_to_str(boot_uuid.b, uuidbuf, UUID_STR_FORMAT_GUID); - env_set("boot_partuuid", uuidbuf); - - uuid_bin_to_str(root_uuid.b, uuidbuf, UUID_STR_FORMAT_GUID); - env_set("root_partuuid", uuidbuf); - } else if (!retb && retr) { - log_warning("%s: found boot GUID but missing root GUID (%d)\n", - __func__, retr); - } else if (!retr && retb) { - log_warning("%s: found root GUID but missing boot GUID (%d)\n", - __func__, retb); - } - - return 0; -} -#endif /* CONFIG_FWU_MULTI_BANK_UPDATE */ From 70456905ec52e480ae15dd78691451b7b4ba28ad Mon Sep 17 00:00:00 2001 From: Patrice Chotard Date: Mon, 18 May 2026 15:28:09 +0200 Subject: [PATCH 06/48] configs: stm32mp15: Increase SYS_MALLOC_F_LEN Using stm32mp15_defconfig with stm32mp157c-dk2-scmi.dtsi device tree with optee-4.10.0, we got: U-Boot 2026.07-rc2-00052-g215496fec59b (May 18 2026 - 15:05:34 +0200) CPU: STM32MP157CAC Rev.B Model: STMicroelectronics STM32MP157C-DK2 SCMI Discovery Board Board: stm32mp1 in trusted mode (st,stm32mp157c-dk2-scmi) alloc space exhausted ptr 80060 limit 80000 optee optee: PTA_BSEC invoke failed TEE err: 0, err:fffffff4 alloc space exhausted ptr 80040 limit 80000 alloc space exhausted ptr 80020 limit 80000 DRAM: alloc space exhausted ptr 80040 limit 80000 RAM init failed: -12 initcall_run_f(): initcall dram_init() failed CONFIG_SYS_MALLOC_F_LEN need to be increased to fix this issue Reported-by: Yann Gautier Signed-off-by: Patrice Chotard Reviewed-by: Patrick Delaunay --- configs/stm32mp15_defconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/configs/stm32mp15_defconfig b/configs/stm32mp15_defconfig index b9e44254087..cc4dfd9af70 100644 --- a/configs/stm32mp15_defconfig +++ b/configs/stm32mp15_defconfig @@ -1,7 +1,7 @@ CONFIG_ARM=y CONFIG_ARCH_STM32MP=y CONFIG_TFABOOT=y -CONFIG_SYS_MALLOC_F_LEN=0x80000 +CONFIG_SYS_MALLOC_F_LEN=0x90000 CONFIG_CUSTOM_SYS_INIT_SP_ADDR=0xc0100000 CONFIG_ENV_OFFSET=0x900000 CONFIG_ENV_SECT_SIZE=0x40000 From 5b2e264a7739e4139bd0039ffa9b4a2ff4d0a362 Mon Sep 17 00:00:00 2001 From: Lionel Debieve Date: Wed, 20 May 2026 18:07:13 +0200 Subject: [PATCH 07/48] configs: stm32mp15: enable WDT_ARM_SMC driver Enable the arm watchdog over SMC driver. This allows using a secure watchdog, based on IWDG1 peripheral and managed by OP-TEE. The driver will be probed if a watchdog node with "arm,smc-wdt" compatible is enabled. Signed-off-by: Lionel Debieve Signed-off-by: Yann Gautier Reviewed-by: Patrice Chotard --- configs/stm32mp15_defconfig | 1 + 1 file changed, 1 insertion(+) diff --git a/configs/stm32mp15_defconfig b/configs/stm32mp15_defconfig index cc4dfd9af70..53903376524 100644 --- a/configs/stm32mp15_defconfig +++ b/configs/stm32mp15_defconfig @@ -169,5 +169,6 @@ CONFIG_BMP_24BPP=y CONFIG_BMP_32BPP=y CONFIG_WDT=y CONFIG_WDT_STM32MP=y +CONFIG_WDT_ARM_SMC=y # CONFIG_BINMAN_FDT is not set CONFIG_ERRNO_STR=y From a3a09d28d52b7da7fa337c44526747399055c281 Mon Sep 17 00:00:00 2001 From: Yann Gautier Date: Wed, 20 May 2026 18:07:14 +0200 Subject: [PATCH 08/48] configs: stm32mp13: activate watchdog No watchdog was enabled for STM32MP13 platform. Add the required flags to support it. As done for STM32MP15 (in SCMI config) and STM32MP2x, we use the Arm SMC watchdog. The required nodes were already present in Linux imported DT files (stm32mp13.dtsi & stm32mp135f-dk.dts). To enable this SMC watchdog on other platforms based on STM32MP13, check that both the following flags are enabled in the dedicated config file: CONFIG_WDT=y CONFIG_WDT_ARM_SMC=y And that there is a node in Linux board DT that enables the feature, as it is done in stm32mp135f-dk.dts: &arm_wdt { timeout-sec = <32>; status = "okay"; }; Signed-off-by: Patrick Delaunay Signed-off-by: Yann Gautier Reviewed-by: Patrice Chotard --- configs/stm32mp13_defconfig | 2 ++ 1 file changed, 2 insertions(+) diff --git a/configs/stm32mp13_defconfig b/configs/stm32mp13_defconfig index 620a6da2efe..2ad57e23e44 100644 --- a/configs/stm32mp13_defconfig +++ b/configs/stm32mp13_defconfig @@ -113,4 +113,6 @@ CONFIG_USB_GADGET_MANUFACTURER="STMicroelectronics" CONFIG_USB_GADGET_VENDOR_NUM=0x0483 CONFIG_USB_GADGET_PRODUCT_NUM=0x5720 CONFIG_USB_GADGET_DWC2_OTG=y +CONFIG_WDT=y +CONFIG_WDT_ARM_SMC=y CONFIG_ERRNO_STR=y From d6ddbbb0008c4e59c5ce4c9d94265db966368462 Mon Sep 17 00:00:00 2001 From: Yann Gautier Date: Wed, 20 May 2026 18:07:15 +0200 Subject: [PATCH 09/48] ARM: dts: stm32: enable SMC watchdog for STM32MP15 SCMI config For this configuration, the watchdog (iwdg1) is secured and managed by OP-TEE. Add an watchdog node with arm,smc-wdt compatible, and disable iwdg2 node which is then no more used. Signed-off-by: Yann Gautier Reviewed-by: Patrice Chotard --- arch/arm/dts/stm32mp15-scmi-u-boot.dtsi | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/arch/arm/dts/stm32mp15-scmi-u-boot.dtsi b/arch/arm/dts/stm32mp15-scmi-u-boot.dtsi index 79494ecad90..600316205fc 100644 --- a/arch/arm/dts/stm32mp15-scmi-u-boot.dtsi +++ b/arch/arm/dts/stm32mp15-scmi-u-boot.dtsi @@ -21,6 +21,13 @@ pinctrl1 = &pinctrl_z; }; + arm_wdt: watchdog { + compatible = "arm,smc-wdt"; + arm,smc-id = <0xbc000000>; + timeout-sec = <32>; + status = "okay"; + }; + binman: binman { multiple-images; }; @@ -103,7 +110,7 @@ }; &iwdg2 { - bootph-all; + status = "disabled"; }; /* pre-reloc probe = reserve video frame buffer in video_reserve() */ From 0c035ff60c1e8caee7fccd2673ce75380dee825b Mon Sep 17 00:00:00 2001 From: Patrice Chotard Date: Tue, 24 Feb 2026 18:31:50 +0100 Subject: [PATCH 10/48] stm32mp2: update part number for STM32MP251/3 update part number for STM32MP251/3 for last cut revision. Signed-off-by: Patrice Chotard Reviewed-by: Patrick Delaunay --- arch/arm/mach-stm32mp/include/mach/sys_proto.h | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/arch/arm/mach-stm32mp/include/mach/sys_proto.h b/arch/arm/mach-stm32mp/include/mach/sys_proto.h index a875907ac3e..05ce869c428 100644 --- a/arch/arm/mach-stm32mp/include/mach/sys_proto.h +++ b/arch/arm/mach-stm32mp/include/mach/sys_proto.h @@ -61,20 +61,20 @@ /* ID for STM32MP25x = Device Part Number (RPN) (bit31:0) */ #define CPU_STM32MP257Cxx 0x00002000 #define CPU_STM32MP255Cxx 0x00082000 -#define CPU_STM32MP253Cxx 0x000B2004 -#define CPU_STM32MP251Cxx 0x000B3065 +#define CPU_STM32MP253Cxx 0x000B300C +#define CPU_STM32MP251Cxx 0x000B306D #define CPU_STM32MP257Axx 0x40002E00 #define CPU_STM32MP255Axx 0x40082E00 -#define CPU_STM32MP253Axx 0x400B2E04 -#define CPU_STM32MP251Axx 0x400B3E65 +#define CPU_STM32MP253Axx 0x400B3E0C +#define CPU_STM32MP251Axx 0x400B3E6D #define CPU_STM32MP257Fxx 0x80002000 #define CPU_STM32MP255Fxx 0x80082000 -#define CPU_STM32MP253Fxx 0x800B2004 -#define CPU_STM32MP251Fxx 0x800B3065 +#define CPU_STM32MP253Fxx 0x800B300C +#define CPU_STM32MP251Fxx 0x800B306D #define CPU_STM32MP257Dxx 0xC0002E00 #define CPU_STM32MP255Dxx 0xC0082E00 -#define CPU_STM32MP253Dxx 0xC00B2E04 -#define CPU_STM32MP251Dxx 0xC00B3E65 +#define CPU_STM32MP253Dxx 0xC00B3E0C +#define CPU_STM32MP251Dxx 0xC00B3E6D /* return CPU_STMP32MP...Xxx constants */ u32 get_cpu_type(void); From 29c40bb2a13ed1c294497044e2299cc0a511ce32 Mon Sep 17 00:00:00 2001 From: Prashant Kamble Date: Sun, 24 May 2026 15:36:21 +0530 Subject: [PATCH 11/48] nvme: fix dcache invalidation range in identify command When the identify buffer crosses a page boundary, PRP2 is used and dma_addr is advanced to the second page: dma_addr += (page_size - offset); The subsequent invalidate_dcache_range() calls then use the modified dma_addr instead of the original buffer start address. As a result, the beginning of the identify buffer is not invalidated and the invalidation range extends past the end of the buffer. Fix this by preserving the original DMA buffer address for cache invalidation. Suggested-by: Neil Armstrong Signed-off-by: Prashant Kamble Reviewed-by: Neil Armstrong Link: https://patch.msgid.link/20260524100625.11135-1-prashant.kamble223@gmail.com Signed-off-by: Neil Armstrong --- drivers/nvme/nvme.c | 26 ++++++++++++++++++++++---- 1 file changed, 22 insertions(+), 4 deletions(-) diff --git a/drivers/nvme/nvme.c b/drivers/nvme/nvme.c index 0631b190b97..da7dad9f52b 100644 --- a/drivers/nvme/nvme.c +++ b/drivers/nvme/nvme.c @@ -27,6 +27,23 @@ #define IO_TIMEOUT 30 #define MAX_PRP_POOL 512 +/** + * nvme_invalidate_cache_aligned() - invalidate cache with proper alignment + * + * Aligns cache invalidation to cacheline boundaries to ensure correct + * behavior even when the DMA buffer is not aligned to page boundaries. + * + * @addr: The start address of the buffer + * @length: The length of the buffer in bytes + */ +static inline void nvme_invalidate_cache_aligned(uintptr_t addr, int length) +{ + uintptr_t start_addr = addr & ~(ARCH_DMA_MINALIGN - 1); + uintptr_t end_addr = ALIGN(addr + length, ARCH_DMA_MINALIGN); + + invalidate_dcache_range(start_addr, end_addr); +} + static int nvme_wait_csts(struct nvme_dev *dev, u32 mask, u32 val) { int timeout; @@ -456,6 +473,7 @@ int nvme_identify(struct nvme_dev *dev, unsigned nsid, u32 page_size = dev->page_size; int offset = dma_addr & (page_size - 1); int length = sizeof(struct nvme_id_ctrl); + dma_addr_t orig_dma_addr = dma_addr; int ret; memset(&c, 0, sizeof(c)); @@ -473,13 +491,13 @@ int nvme_identify(struct nvme_dev *dev, unsigned nsid, c.identify.cns = cpu_to_le32(cns); - invalidate_dcache_range(dma_addr, - dma_addr + sizeof(struct nvme_id_ctrl)); + nvme_invalidate_cache_aligned((uintptr_t)orig_dma_addr, + sizeof(struct nvme_id_ctrl)); ret = nvme_submit_admin_cmd(dev, &c, NULL); if (!ret) - invalidate_dcache_range(dma_addr, - dma_addr + sizeof(struct nvme_id_ctrl)); + nvme_invalidate_cache_aligned((uintptr_t)orig_dma_addr, + sizeof(struct nvme_id_ctrl)); return ret; } From 61280341e926aee1787d9aedb358a43fad96e787 Mon Sep 17 00:00:00 2001 From: Prashant Kamble Date: Sun, 24 May 2026 21:17:14 +0530 Subject: [PATCH 12/48] nvme: avoid deleting uncreated queues nvme_create_queue() may issue Delete CQ or Delete SQ commands even when the corresponding queue creation failed. Avoid sending delete commands for queues that were never successfully created. Signed-off-by: Prashant Kamble Reviewed-by: Neil Armstrong Link: https://patch.msgid.link/20260524154718.16381-1-prashant.kamble223@gmail.com Signed-off-by: Neil Armstrong --- drivers/nvme/nvme.c | 12 +++--------- 1 file changed, 3 insertions(+), 9 deletions(-) diff --git a/drivers/nvme/nvme.c b/drivers/nvme/nvme.c index da7dad9f52b..30eba0bf7c7 100644 --- a/drivers/nvme/nvme.c +++ b/drivers/nvme/nvme.c @@ -298,11 +298,6 @@ static int nvme_delete_queue(struct nvme_dev *dev, u8 opcode, u16 id) return nvme_submit_admin_cmd(dev, &c, NULL); } -static int nvme_delete_sq(struct nvme_dev *dev, u16 sqid) -{ - return nvme_delete_queue(dev, nvme_admin_delete_sq, sqid); -} - static int nvme_delete_cq(struct nvme_dev *dev, u16 cqid) { return nvme_delete_queue(dev, nvme_admin_delete_cq, cqid); @@ -563,20 +558,19 @@ static int nvme_create_queue(struct nvme_queue *nvmeq, int qid) nvmeq->cq_vector = qid - 1; result = nvme_alloc_cq(dev, qid, nvmeq); if (result < 0) - goto release_cq; + goto release_ret; result = nvme_alloc_sq(dev, qid, nvmeq); if (result < 0) - goto release_sq; + goto release_cq; nvme_init_queue(nvmeq, qid); return result; - release_sq: - nvme_delete_sq(dev, qid); release_cq: nvme_delete_cq(dev, qid); + release_ret: return result; } From 11e056e3207d3b4eabebb1a7630b0195ee9eb5ee Mon Sep 17 00:00:00 2001 From: Prashant Kamble Date: Sun, 24 May 2026 20:27:16 +0530 Subject: [PATCH 13/48] nvme: free prp_pool on nvme_init() failure paths nvme_init() allocates prp_pool after configuring the admin queue, but some later error paths return without freeing it. Free prp_pool before freeing the queue array in the failure paths after nvme_setup_io_queues() and namespace ID buffer allocation. This fixes a memory leak during NVMe initialization failures. Signed-off-by: Prashant Kamble Reviewed-by: Neil Armstrong Link: https://patch.msgid.link/20260524145721.9206-1-prashant.kamble223@gmail.com Signed-off-by: Neil Armstrong --- drivers/nvme/nvme.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/drivers/nvme/nvme.c b/drivers/nvme/nvme.c index 30eba0bf7c7..980ca919632 100644 --- a/drivers/nvme/nvme.c +++ b/drivers/nvme/nvme.c @@ -880,14 +880,14 @@ int nvme_init(struct udevice *udev) if (!ndev->prp_pool) { ret = -ENOMEM; printf("Error: %s: Out of memory!\n", udev->name); - goto free_nvme; + goto free_queue; } ndev->prp_entry_num = MAX_PRP_POOL >> 3; ret = nvme_setup_io_queues(ndev); if (ret) { log_debug("Unable to setup I/O queues(err=%dE)\n", ret); - goto free_queue; + goto free_prp_pool; } nvme_get_info_from_identify(ndev); @@ -897,7 +897,7 @@ int nvme_init(struct udevice *udev) id = memalign(ndev->page_size, sizeof(struct nvme_id_ns)); if (!id) { ret = -ENOMEM; - goto free_queue; + goto free_prp_pool; } for (int i = 1; i <= ndev->nn; i++) { @@ -942,6 +942,8 @@ int nvme_init(struct udevice *udev) free_id: free(id); +free_prp_pool: + free((void *)ndev->prp_pool); free_queue: free((void *)ndev->queues); free_nvme: From 8de24e226d745c59972b1898df5cceacf0a7ad47 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20=C4=8Cerm=C3=A1k?= Date: Tue, 12 May 2026 14:24:35 +0200 Subject: [PATCH 14/48] mmc: bcmstb: Fix non-removable check in bcm2712 init MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit sdhci_brcmstb_init_2712() reads host->mmc->host_caps to decide whether to force card-detect for a non-removable eMMC, or to route the CD signal for a removable SD card. At the time this function runs from sdhci_bcmstb_probe(), however, host->mmc->host_caps is still zero, that field is only populated later by the MMC uclass, after the driver's probe returns. mmc_of_parse() has already filled plat->cfg.host_caps from the device tree by this point, so check that field instead. Without the fix, every BCM2712 SDHCI instance takes the else branch and writes SDIO_CFG_SD_PIN_SEL = SDIO_CFG_SD_PIN_SEL_CARD (0x02), including the non-removable eMMC on boards such as CM5 on Home Assistant Yellow. The SDIO_CFG block lies outside the SDHCI core's reset scope, so this value persists across SDHCI_RESET_ALL into the next stage. On the BCM2712, having SD_PIN_SEL set to "SD" when the Linux kernel performs its first set_power(MMC_POWER_UP) write racily prevents the SDHCI POWER_ON bit from latching (see [1] for the whole backstory) - the voltage bits stick but POWER_ON drops - which wedges the first CMD0 the full 10 s software timeout. On Home Assistant Yellow this manifested as a ~20 s eMMC probe delay on roughly one in two Linux boots when U-Boot was the previous stage. Booting directly from the Pi firmware (no U-Boot in between) left SD_PIN_SEL at its default and did not exhibit the race. Reading plat->cfg.host_caps lets init_2712 see the "non-removable" property and take the correct branch, leaving SD_PIN_SEL untouched for the eMMC. [1] https://github.com/home-assistant/operating-system/pull/3700#issuecomment-4430229511 Fixes: 10127cdbab64 ("mmc: bcmstb: Add support for bcm2712 SD controller") Signed-off-by: Jan Čermák Reviewed-by: Ivan T. Ivanov --- drivers/mmc/bcmstb_sdhci.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/mmc/bcmstb_sdhci.c b/drivers/mmc/bcmstb_sdhci.c index 7bddbebb162..f27b84a6ee4 100644 --- a/drivers/mmc/bcmstb_sdhci.c +++ b/drivers/mmc/bcmstb_sdhci.c @@ -56,7 +56,7 @@ struct sdhci_brcmstb_dev_priv { static int sdhci_brcmstb_init_2712(struct udevice *dev) { - struct sdhci_host *host = dev_get_priv(dev); + struct sdhci_bcmstb_plat *plat = dev_get_plat(dev); void *cfg_regs; u32 reg; @@ -65,8 +65,8 @@ static int sdhci_brcmstb_init_2712(struct udevice *dev) if (!cfg_regs) return -ENOENT; - if ((host->mmc->host_caps & MMC_CAP_NONREMOVABLE) || - (host->mmc->host_caps & MMC_CAP_NEEDS_POLL)) { + if ((plat->cfg.host_caps & MMC_CAP_NONREMOVABLE) || + (plat->cfg.host_caps & MMC_CAP_NEEDS_POLL)) { /* Force presence */ reg = readl(cfg_regs + SDIO_CFG_CTRL); reg &= ~SDIO_CFG_CTRL_SDCD_N_TEST_LEV; From 30b77f6aa146c96b831cb4ece038130b655b6a41 Mon Sep 17 00:00:00 2001 From: Tom Rini Date: Fri, 29 May 2026 09:59:31 -0600 Subject: [PATCH 15/48] CI: Sage: Drop rpi_arm64 lwIP variants With commit 17ceb774a185 ("rpi_arm64: Enable MBEDTLS/LWIP/WGET and WGET_HTTPS"), we can drop the tests for switching from the legacy stack to lwIP. Signed-off-by: Tom Rini --- .gitlab-ci-sage-lab.yml | 30 ++++++++---------------------- 1 file changed, 8 insertions(+), 22 deletions(-) diff --git a/.gitlab-ci-sage-lab.yml b/.gitlab-ci-sage-lab.yml index e9fa3e5f6f3..176d281868b 100644 --- a/.gitlab-ci-sage-lab.yml +++ b/.gitlab-ci-sage-lab.yml @@ -153,20 +153,13 @@ Raspberry Pi 4 (rpi_arm64): LABGRID_EXPORTER: "sage-exporter-rpi4-1" LG_PLACE: "rpi4-1" TEST_PY_BD: "rpi_arm64" - OVERRIDE: "-a UNIT_TEST -a ~CMD_EFIDEBUG -a CMD_BOOTMENU -a CMD_LOG -a ~CMD_BOOTEFI_SELFTEST -a CMD_TFTPPUT -a FIT -a FIT_SIGNATURE -a FIT_BEST_MATCH -a SYS_BOOTM_LEN=0x4000000 -a BOOTSTAGE -a BOOTSTAGE_STASH -a CMD_BOOTSTAGE -a BOOTSTAGE_STASH_ADDR=0x02400000" - -Raspberry Pi 4 (rpi_arm64, lwIP): - <<: *sage_lab_dfn - needs: [ "Raspberry Pi 4 (rpi_arm64)" ] - variables: - LABGRID_EXPORTER: "sage-exporter-rpi4-1" - LG_PLACE: "rpi4-1" - TEST_PY_BD: "rpi_arm64" - OVERRIDE: "-a UNIT_TEST -a ~CMD_EFIDEBUG -a CMD_BOOTMENU -a CMD_LOG -a ~CMD_BOOTEFI_SELFTEST -a FIT -a FIT_SIGNATURE -a FIT_BEST_MATCH -a SYS_BOOTM_LEN=0x4000000 -a BOOTSTAGE -a BOOTSTAGE_STASH -a CMD_BOOTSTAGE -a BOOTSTAGE_STASH_ADDR=0x02400000 -a NET_LWIP" + # DHCP is not being run first, needs to be investigated. + TEST_PY_TEST_SPEC: "not test_efi_helloworld_net_http" + OVERRIDE: "-a UNIT_TEST -a ~CMD_EFIDEBUG -a CMD_BOOTMENU -a CMD_LOG -a ~CMD_BOOTEFI_SELFTEST -a FIT -a FIT_SIGNATURE -a FIT_BEST_MATCH -a SYS_BOOTM_LEN=0x4000000 -a BOOTSTAGE -a BOOTSTAGE_STASH -a CMD_BOOTSTAGE -a BOOTSTAGE_STASH_ADDR=0x02400000" Raspberry Pi 4 (rpi_4_32b): <<: *sage_lab_dfn - needs: [ "Raspberry Pi 4 (rpi_arm64, lwIP)" ] + needs: [ "Raspberry Pi 4 (rpi_arm64)" ] variables: LABGRID_EXPORTER: "sage-exporter-rpi4-1" LG_PLACE: "rpi4-1" @@ -197,20 +190,13 @@ Raspberry Pi 3 (rpi_arm64): LABGRID_EXPORTER: "sage-exporter-rpi3-1" LG_PLACE: "rpi3-1" TEST_PY_BD: "rpi_arm64" - OVERRIDE: "-a UNIT_TEST -a ~CMD_EFIDEBUG -a CMD_BOOTMENU -a CMD_LOG -a ~CMD_BOOTEFI_SELFTEST -a CMD_TFTPPUT -a FIT -a FIT_SIGNATURE -a FIT_BEST_MATCH -a SYS_BOOTM_LEN=0x4000000 -a BOOTSTAGE -a BOOTSTAGE_STASH -a CMD_BOOTSTAGE -a BOOTSTAGE_STASH_ADDR=0x02400000" - -Raspberry Pi 3 (rpi_arm64, lwIP): - <<: *sage_lab_dfn - needs: [ "Raspberry Pi 3 (rpi_arm64)" ] - variables: - LABGRID_EXPORTER: "sage-exporter-rpi3-1" - LG_PLACE: "rpi3-1" - TEST_PY_BD: "rpi_arm64" - OVERRIDE: "-a UNIT_TEST -a ~CMD_EFIDEBUG -a CMD_BOOTMENU -a CMD_LOG -a ~CMD_BOOTEFI_SELFTEST -a FIT -a FIT_SIGNATURE -a FIT_BEST_MATCH -a SYS_BOOTM_LEN=0x4000000 -a BOOTSTAGE -a BOOTSTAGE_STASH -a CMD_BOOTSTAGE -a BOOTSTAGE_STASH_ADDR=0x02400000 -a NET_LWIP" + # DHCP is not being run first, needs to be investigated. + TEST_PY_TEST_SPEC: "not test_efi_helloworld_net_http" + OVERRIDE: "-a UNIT_TEST -a ~CMD_EFIDEBUG -a CMD_BOOTMENU -a CMD_LOG -a ~CMD_BOOTEFI_SELFTEST -a FIT -a FIT_SIGNATURE -a FIT_BEST_MATCH -a SYS_BOOTM_LEN=0x4000000 -a BOOTSTAGE -a BOOTSTAGE_STASH -a CMD_BOOTSTAGE -a BOOTSTAGE_STASH_ADDR=0x02400000" Raspberry Pi 3 (rpi_3_32b): <<: *sage_lab_dfn - needs: [ "Raspberry Pi 3 (rpi_arm64, lwIP)" ] + needs: [ "Raspberry Pi 3 (rpi_arm64)" ] variables: LABGRID_EXPORTER: "sage-exporter-rpi3-1" LG_PLACE: "rpi3-1" From c8523795d7967729c64292f9800d06952ee7b7ba Mon Sep 17 00:00:00 2001 From: Nguyen Tran Date: Mon, 25 May 2026 00:06:19 +0200 Subject: [PATCH 16/48] arm64: dts: renesas: r8a779md: Add support for R-Car M3Le R8A779MD Geist Add support for the Geist board based on the Renesas R8A779MD (M3Le) SoC, a register-compatible variant of the R8A77965 (M3N) with reduced peripherals. The Geist board design references the Renesas Salvator-X/XS boards, adapting their configuration for the R8A779MD SoC. The board will be switched to OF_UPSTREAM once the DTs land in upstream. Signed-off-by: Huy Bui Signed-off-by: Nguyen Tran Signed-off-by: Marek Vasut --- arch/arm/dts/Makefile | 3 + arch/arm/dts/r8a779md-geist-u-boot.dtsi | 59 ++ arch/arm/dts/r8a779md-geist.dts | 717 ++++++++++++++++++++++++ arch/arm/dts/r8a779md.dtsi | 59 ++ arch/arm/mach-renesas/Kconfig.rcar3 | 8 + arch/arm/mach-renesas/cpu_info.c | 13 + board/renesas/geist/Kconfig | 15 + board/renesas/geist/Makefile | 9 + board/renesas/geist/geist.c | 36 ++ configs/r8a779md_geist_defconfig | 75 +++ include/configs/geist.h | 18 + 11 files changed, 1012 insertions(+) create mode 100644 arch/arm/dts/r8a779md-geist-u-boot.dtsi create mode 100644 arch/arm/dts/r8a779md-geist.dts create mode 100644 arch/arm/dts/r8a779md.dtsi create mode 100644 board/renesas/geist/Kconfig create mode 100644 board/renesas/geist/Makefile create mode 100644 board/renesas/geist/geist.c create mode 100644 configs/r8a779md_geist_defconfig create mode 100644 include/configs/geist.h diff --git a/arch/arm/dts/Makefile b/arch/arm/dts/Makefile index 3cbb1f14d25..cf9046f6056 100644 --- a/arch/arm/dts/Makefile +++ b/arch/arm/dts/Makefile @@ -899,6 +899,9 @@ dtb-$(CONFIG_RZA1) += \ r7s72100-genmai.dtb \ r7s72100-gr-peach.dtb +dtb-$(CONFIG_RCAR_GEN3) += \ + r8a779md-geist.dtb + dtb-$(CONFIG_RCAR_GEN5) += \ r8a78000-ironhide-cm33.dtb diff --git a/arch/arm/dts/r8a779md-geist-u-boot.dtsi b/arch/arm/dts/r8a779md-geist-u-boot.dtsi new file mode 100644 index 00000000000..fbda218002a --- /dev/null +++ b/arch/arm/dts/r8a779md-geist-u-boot.dtsi @@ -0,0 +1,59 @@ +// SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +/* + * Device Tree Source extras for U-Boot for the Geist board with r8a779md + * + * Copyright (C) 2025-2026 Renesas Electronics Corp. + */ + +/ { + aliases { + spi0 = &rpc; + }; +}; + +&pfc { + qspi0_pins: qspi0 { + groups = "qspi0_ctrl", "qspi0_data4"; + function = "qspi0"; + }; +}; + +/* + * SPI access works only if TFA is built with RCAR_RPC_HYPERFLASH_LOCKED=0 + * and SPD=none , otherwise the RPC access is blocked either by TFA in case + * the former is set to 1, or by OPTEE-OS in case SPD=opteed . + */ +&rpc { + pinctrl-0 = <&qspi0_pins>; + pinctrl-names = "default"; + + #address-cells = <1>; + #size-cells = <0>; + spi-max-frequency = <40000000>; + status = "okay"; + + flash@0 { + compatible = "jedec,spi-nor"; + reg = <0>; + spi-max-frequency = <40000000>; + spi-tx-bus-width = <1>; + spi-rx-bus-width = <1>; + }; +}; + +&sdhi0 { + sd-uhs-sdr12; + sd-uhs-sdr25; + sd-uhs-sdr104; + max-frequency = <208000000>; +}; + +&sdhi2 { + mmc-ddr-1_8v; + mmc-hs200-1_8v; + max-frequency = <200000000>; +}; + +&vcc_sdhi0 { + u-boot,off-on-delay-us = <20000>; +}; diff --git a/arch/arm/dts/r8a779md-geist.dts b/arch/arm/dts/r8a779md-geist.dts new file mode 100644 index 00000000000..2921aba92a5 --- /dev/null +++ b/arch/arm/dts/r8a779md-geist.dts @@ -0,0 +1,717 @@ +// SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +/* + * Device Tree Source for the Geist board with R-Car M3Le + * + * Copyright (C) 2025-2026 Renesas Electronics Corp. + */ + +/dts-v1/; +#include +#include +#include "r8a779md.dtsi" + +/ { + model = "Renesas Geist board based on r8a779md"; + compatible = "renesas,geist", "renesas,r8a779md", "renesas,r8a77965"; + + aliases { + serial0 = &scif2; + serial1 = &hscif1; + ethernet0 = &avb; + mmc0 = &sdhi2; + mmc1 = &sdhi0; + }; + + chosen { + bootargs = "ignore_loglevel rw root=/dev/nfs ip=on"; + stdout-path = "serial0:115200n8"; + }; + + audio_clkout: audio-clkout { + /* + * This is same as <&rcar_sound 0> + * but needed to avoid cs2500/rcar_sound probe dead-lock + */ + compatible = "fixed-clock"; + #clock-cells = <0>; + clock-frequency = <12288000>; + }; + + backlight: backlight { + compatible = "pwm-backlight"; + pwms = <&pwm1 0 50000>; + + brightness-levels = <256 128 64 16 8 4 0>; + default-brightness-level = <6>; + + power-supply = <®_12v>; + enable-gpios = <&gpio6 7 GPIO_ACTIVE_HIGH>; + }; + + cvbs-in { + compatible = "composite-video-connector"; + label = "CVBS IN"; + + port { + cvbs_con: endpoint { + remote-endpoint = <&adv7482_ain7>; + }; + }; + }; + + hdmi-in { + compatible = "hdmi-connector"; + label = "HDMI IN"; + type = "a"; + + port { + hdmi_in_con: endpoint { + remote-endpoint = <&adv7482_hdmi>; + }; + }; + }; + + keys { + compatible = "gpio-keys"; + + pinctrl-0 = <&keys_pins>; + pinctrl-names = "default"; + + key-1 { + gpios = <&gpio5 17 GPIO_ACTIVE_LOW>; + linux,code = ; + label = "SW4-1"; + wakeup-source; + debounce-interval = <20>; + }; + + key-2 { + gpios = <&gpio5 20 GPIO_ACTIVE_LOW>; + linux,code = ; + label = "SW4-2"; + wakeup-source; + debounce-interval = <20>; + }; + + key-3 { + gpios = <&gpio5 22 GPIO_ACTIVE_LOW>; + linux,code = ; + label = "SW4-3"; + wakeup-source; + debounce-interval = <20>; + }; + + key-4 { + gpios = <&gpio5 23 GPIO_ACTIVE_LOW>; + linux,code = ; + label = "SW4-4"; + wakeup-source; + debounce-interval = <20>; + }; + + key-a { + gpios = <&gpio6 11 GPIO_ACTIVE_LOW>; + linux,code = ; + label = "TSW0"; + wakeup-source; + debounce-interval = <20>; + }; + + key-b { + gpios = <&gpio6 12 GPIO_ACTIVE_LOW>; + linux,code = ; + label = "TSW1"; + wakeup-source; + debounce-interval = <20>; + }; + + key-c { + gpios = <&gpio6 13 GPIO_ACTIVE_LOW>; + linux,code = ; + label = "TSW2"; + wakeup-source; + debounce-interval = <20>; + }; + }; + + memory@48000000 { + device_type = "memory"; + /* first 128MB is reserved for secure area. */ + reg = <0x0 0x48000000 0x0 0x78000000>; + }; + + memory@480000000 { + device_type = "memory"; + reg = <0x4 0x80000000 0x0 0x80000000>; + }; + + reg_1p8v: regulator-1p8v { + compatible = "regulator-fixed"; + regulator-name = "fixed-1.8V"; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + regulator-boot-on; + regulator-always-on; + }; + + reg_3p3v: regulator-3p3v { + compatible = "regulator-fixed"; + regulator-name = "fixed-3.3V"; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + regulator-boot-on; + regulator-always-on; + }; + + reg_12v: regulator-12v { + compatible = "regulator-fixed"; + regulator-name = "fixed-12V"; + regulator-min-microvolt = <12000000>; + regulator-max-microvolt = <12000000>; + regulator-boot-on; + regulator-always-on; + }; + + vbus0_usb2: regulator-vbus0-usb2 { + compatible = "regulator-fixed"; + + regulator-name = "USB20_VBUS0"; + regulator-min-microvolt = <5000000>; + regulator-max-microvolt = <5000000>; + + gpio = <&gpio6 16 GPIO_ACTIVE_HIGH>; + enable-active-high; + }; + + vcc_sdhi0: regulator-vcc-sdhi0 { + compatible = "regulator-fixed"; + + regulator-name = "SDHI0 Vcc"; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + + gpio = <&gpio5 2 GPIO_ACTIVE_HIGH>; + enable-active-high; + }; + + vccq_sdhi0: regulator-vccq-sdhi0 { + compatible = "regulator-gpio"; + + regulator-name = "SDHI0 VccQ"; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <3300000>; + + gpios = <&gpio5 1 GPIO_ACTIVE_HIGH>; + gpios-states = <1>; + states = <3300000 1>, <1800000 0>; + }; + + sound_card: sound { + compatible = "audio-graph-card"; + + label = "rcar-sound"; + dais = <&rsnd_port0>; /* AK4619 Audio Codec */ + }; + + x12_clk: x12-clock { + compatible = "fixed-clock"; + #clock-cells = <0>; + clock-frequency = <24576000>; + }; + + /* External DU dot clocks */ + x21_clk: x21-clock { + compatible = "fixed-clock"; + #clock-cells = <0>; + clock-frequency = <33000000>; + }; + + x22_clk: x22-clock { + compatible = "fixed-clock"; + #clock-cells = <0>; + clock-frequency = <33000000>; + }; + + x23_clk: x23-clock { + compatible = "fixed-clock"; + #clock-cells = <0>; + clock-frequency = <25000000>; + }; + + x3013_clk: x3013-clock { + compatible = "fixed-clock"; + #clock-cells = <0>; + clock-frequency = <25000000>; + }; +}; + +&audio_clk_a { + clock-frequency = <22579200>; +}; + +&avb { + pinctrl-0 = <&avb_pins>; + pinctrl-names = "default"; + phy-handle = <&phy0>; + tx-internal-delay-ps = <2000>; + status = "okay"; + + phy0: ethernet-phy@0 { + compatible = "ethernet-phy-id0022.1622"; + rxc-skew-ps = <1500>; + reg = <0>; + interrupts-extended = <&gpio2 11 IRQ_TYPE_LEVEL_LOW>; + reset-gpios = <&gpio2 10 GPIO_ACTIVE_LOW>; + reset-assert-us = <10000>; + reset-deassert-us = <300>; + }; +}; + +&csi40 { + status = "okay"; + + ports { + port@0 { + csi40_in: endpoint { + clock-lanes = <0>; + data-lanes = <1 2 3 4>; + remote-endpoint = <&adv7482_txa>; + }; + }; + }; +}; + +&ehci0 { + dr_mode = "otg"; + status = "okay"; +}; + +&extalr_clk { + clock-frequency = <32768>; +}; + +&extal_clk { + clock-frequency = <16666666>; +}; + +&hscif1 { + pinctrl-0 = <&hscif1_pins>; + pinctrl-names = "default"; + + uart-has-rtscts; + /* Please only enable hscif1 or scif1 */ + status = "okay"; +}; + +&hsusb { + dr_mode = "otg"; + status = "okay"; +}; + +&i2c2 { + pinctrl-0 = <&i2c2_pins>; + pinctrl-names = "default"; + clock-frequency = <100000>; + status = "okay"; + + ak4619: codec@10 { + compatible = "asahi-kasei,ak4619"; + reg = <0x10>; + clocks = <&rcar_sound 3>; + clock-names = "mclk"; + #sound-dai-cells = <0>; + + port { + ak4619_endpoint: endpoint { + remote-endpoint = <&rsnd_endpoint0>; + }; + }; + }; + + /* Pin-to-pin, register map, and control compatible with CS2000 and CS2200 */ + cs2500: clock-controller@4f { + #clock-cells = <0>; + compatible = "cirrus,cs2500", "cirrus,cs2000-cp"; + reg = <0x4f>; + clocks = <&audio_clkout>, <&x12_clk>; + clock-names = "clk_in", "ref_clk"; + + assigned-clocks = <&cs2500>; + assigned-clock-rates = <24576000>; /* 1/1 divide */ + }; +}; + +&i2c4 { + clock-frequency = <400000>; + status = "okay"; + + versaclock3: clock-controller@68 { + compatible = "renesas,5p35023"; + reg = <0x68>; + #clock-cells = <1>; + clocks = <&x3013_clk>; + assigned-clocks = <&versaclock3 4>, <&versaclock3 5>; + assigned-clock-rates = <100000000>, <100000000>; + }; + + versaclock5: clock-controller@6a { + compatible = "idt,5p49v5923"; + reg = <0x6a>; + #clock-cells = <1>; + clocks = <&x23_clk>; + clock-names = "xin"; + }; + + video-receiver@70 { + compatible = "adi,adv7482"; + reg = <0x70 0x71 0x72 0x73 0x74 0x75 + 0x60 0x61 0x62 0x63 0x64 0x65>; + reg-names = "main", "dpll", "cp", "hdmi", "edid", "repeater", + "infoframe", "cbus", "cec", "sdp", "txa", "txb" ; + + interrupts-extended = <&gpio6 30 IRQ_TYPE_LEVEL_LOW>, + <&gpio6 31 IRQ_TYPE_LEVEL_LOW>; + interrupt-names = "intrq1", "intrq2"; + + ports { + #address-cells = <1>; + #size-cells = <0>; + + port@7 { + reg = <7>; + + adv7482_ain7: endpoint { + remote-endpoint = <&cvbs_con>; + }; + }; + + port@8 { + reg = <8>; + + adv7482_hdmi: endpoint { + remote-endpoint = <&hdmi_in_con>; + }; + }; + + port@a { + reg = <10>; + + adv7482_txa: endpoint { + clock-lanes = <0>; + data-lanes = <1 2 3 4>; + remote-endpoint = <&csi40_in>; + }; + }; + }; + }; + + csa_vdd: adc@7c { + compatible = "maxim,max9611"; + reg = <0x7c>; + + shunt-resistor-micro-ohms = <5000>; + }; + + csa_dvfs: adc@7f { + compatible = "maxim,max9611"; + reg = <0x7f>; + + shunt-resistor-micro-ohms = <5000>; + }; +}; + +&i2c_dvfs { + status = "okay"; + + clock-frequency = <400000>; + + eeprom@50 { + compatible = "rohm,br24t01", "atmel,24c01"; + reg = <0x50>; + pagesize = <8>; + }; +}; + +&ohci0 { + dr_mode = "otg"; + status = "okay"; +}; + +&pcie_bus_clk { + clock-frequency = <100000000>; + status = "disabled"; +}; + +&pciec0 { + clocks = <&cpg CPG_MOD 319>, <&versaclock3 4>; + status = "okay"; +}; + +&pfc { + pinctrl-0 = <&scif_clk_pins>; + pinctrl-names = "default"; + + avb_pins: avb { + mux { + groups = "avb_link", "avb_mdio", "avb_mii"; + function = "avb"; + }; + + pins_mdio { + groups = "avb_mdio"; + drive-strength = <24>; + }; + + pins_mii_tx { + pins = "PIN_AVB_TX_CTL", "PIN_AVB_TXC", "PIN_AVB_TD0", + "PIN_AVB_TD1", "PIN_AVB_TD2", "PIN_AVB_TD3"; + drive-strength = <12>; + }; + }; + + hscif1_pins: hscif1 { + groups = "hscif1_data_a", "hscif1_ctrl_a"; + function = "hscif1"; + }; + + i2c2_pins: i2c2 { + groups = "i2c2_a"; + function = "i2c2"; + }; + + irq0_pins: irq0 { + groups = "intc_ex_irq0"; + function = "intc_ex"; + }; + + keys_pins: keys { + pins = "GP_5_17", "GP_5_20", "GP_5_22"; + bias-pull-up; + }; + + pwm1_pins: pwm1 { + groups = "pwm1_a"; + function = "pwm1"; + }; + + scif1_pins: scif1 { + groups = "scif1_data_a", "scif1_ctrl"; + function = "scif1"; + }; + + scif2_pins: scif2 { + groups = "scif2_data_a"; + function = "scif2"; + }; + + scif_clk_pins: scif_clk { + groups = "scif_clk_a"; + function = "scif_clk"; + }; + + sdhi0_pins: sd0 { + groups = "sdhi0_data4", "sdhi0_ctrl"; + function = "sdhi0"; + power-source = <3300>; + }; + + sdhi0_pins_uhs: sd0_uhs { + groups = "sdhi0_data4", "sdhi0_ctrl"; + function = "sdhi0"; + power-source = <1800>; + }; + + sdhi2_pins: sd2 { + groups = "sdhi2_data8", "sdhi2_ctrl", "sdhi2_ds"; + function = "sdhi2"; + power-source = <1800>; + }; + + sound_pins: sound { + groups = "ssi01239_ctrl", "ssi0_data", "ssi1_data_a"; + function = "ssi"; + }; + + sound_clk_pins: sound_clk { + groups = "audio_clk_a_a", "audio_clk_b_a", "audio_clk_c_a", + "audio_clkout_a", "audio_clkout3_a"; + function = "audio_clk"; + }; + + usb0_pins: usb0 { + groups = "usb0"; + function = "usb0"; + }; +}; + +&pwm1 { + pinctrl-0 = <&pwm1_pins>; + pinctrl-names = "default"; + + status = "okay"; +}; + +&rcar_sound { + pinctrl-0 = <&sound_pins>, <&sound_clk_pins>; + pinctrl-names = "default"; + + /* Single DAI */ + #sound-dai-cells = <0>; + + /* audio_clkout0/1/2/3 */ + #clock-cells = <1>; + clock-frequency = <12288000 11289600>; + + status = "okay"; + + /* update to */ + clocks = <&cpg CPG_MOD 1005>, + <&cpg CPG_MOD 1006>, <&cpg CPG_MOD 1007>, + <&cpg CPG_MOD 1008>, <&cpg CPG_MOD 1009>, + <&cpg CPG_MOD 1010>, <&cpg CPG_MOD 1011>, + <&cpg CPG_MOD 1012>, <&cpg CPG_MOD 1013>, + <&cpg CPG_MOD 1014>, <&cpg CPG_MOD 1015>, + <&cpg CPG_MOD 1022>, <&cpg CPG_MOD 1023>, + <&cpg CPG_MOD 1024>, <&cpg CPG_MOD 1025>, + <&cpg CPG_MOD 1026>, <&cpg CPG_MOD 1027>, + <&cpg CPG_MOD 1028>, <&cpg CPG_MOD 1029>, + <&cpg CPG_MOD 1030>, <&cpg CPG_MOD 1031>, + <&cpg CPG_MOD 1020>, <&cpg CPG_MOD 1021>, + <&cpg CPG_MOD 1020>, <&cpg CPG_MOD 1021>, + <&cpg CPG_MOD 1019>, <&cpg CPG_MOD 1018>, + <&audio_clk_a>, <&cs2500>, + <&audio_clk_c>, + <&cpg CPG_MOD 922>; + + ports { + #address-cells = <1>; + #size-cells = <0>; + + rsnd_port0: port@0 { + reg = <0>; + + rsnd_endpoint0: endpoint { + remote-endpoint = <&ak4619_endpoint>; + dai-format = "left_j"; + bitclock-master = <&rsnd_endpoint0>; + frame-master = <&rsnd_endpoint0>; + playback = <&ssi0>, <&src0>, <&dvc0>; + capture = <&ssi1>, <&src1>, <&dvc1>; + }; + }; + }; +}; + +&rwdt { + timeout-sec = <60>; + status = "okay"; +}; + +&scif1 { + pinctrl-0 = <&scif1_pins>; + pinctrl-names = "default"; + + uart-has-rtscts; + /* Please only enable hscif1 or scif1 */ + /* status = "okay"; */ +}; + +&scif2 { + pinctrl-0 = <&scif2_pins>; + pinctrl-names = "default"; + + status = "okay"; +}; + +&scif_clk { + clock-frequency = <14745600>; +}; + +&sdhi0 { + pinctrl-0 = <&sdhi0_pins>; + pinctrl-1 = <&sdhi0_pins_uhs>; + pinctrl-names = "default", "state_uhs"; + + vmmc-supply = <&vcc_sdhi0>; + vqmmc-supply = <&vccq_sdhi0>; + cd-gpios = <&gpio3 12 GPIO_ACTIVE_LOW>; + wp-gpios = <&gpio3 13 GPIO_ACTIVE_HIGH>; + bus-width = <4>; + sd-uhs-sdr50; + sd-uhs-sdr104; + status = "okay"; +}; + +&sdhi2 { + /* used for on-board 8bit eMMC */ + pinctrl-0 = <&sdhi2_pins>; + pinctrl-1 = <&sdhi2_pins>; + pinctrl-names = "default", "state_uhs"; + + vmmc-supply = <®_3p3v>; + vqmmc-supply = <®_1p8v>; + bus-width = <8>; + mmc-hs200-1_8v; + no-sd; + no-sdio; + non-removable; + fixed-emmc-driver-type = <1>; + full-pwr-cycle-in-suspend; + status = "okay"; +}; + +&ssi1 { + shared-pin; +}; + +&usb_extal_clk { + clock-frequency = <50000000>; +}; + +&usb2_phy0 { + pinctrl-0 = <&usb0_pins>; + pinctrl-names = "default"; + + vbus-supply = <&vbus0_usb2>; + status = "okay"; +}; + +&vin0 { + status = "okay"; +}; + +&vin1 { + status = "okay"; +}; + +&vin2 { + status = "okay"; +}; + +&vin3 { + status = "okay"; +}; + +&vin4 { + status = "okay"; +}; + +&vin5 { + status = "okay"; +}; + +&vin6 { + status = "okay"; +}; + +&vin7 { + status = "okay"; +}; + +&vspb { + status = "okay"; +}; + +&vspi0 { + status = "okay"; +}; diff --git a/arch/arm/dts/r8a779md.dtsi b/arch/arm/dts/r8a779md.dtsi new file mode 100644 index 00000000000..f3065414134 --- /dev/null +++ b/arch/arm/dts/r8a779md.dtsi @@ -0,0 +1,59 @@ +// SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +/* + * Device Tree Source for the R-Car M3Le (R8A779MD) SoC + * + * Copyright (C) 2025-2026 Renesas Electronics Corp. + */ + +#include "r8a77965.dtsi" + +/ { + compatible = "renesas,r8a779md", "renesas,r8a77965"; +}; + +/delete-node/ &csi20; +/delete-node/ &drif00; +/delete-node/ &drif01; +/delete-node/ &drif10; +/delete-node/ &drif11; +/delete-node/ &drif20; +/delete-node/ &drif21; +/delete-node/ &drif30; +/delete-node/ &drif31; +/delete-node/ &du; +/delete-node/ &ehci1; +/delete-node/ &hdmi0; +/delete-node/ &lvds0; +/delete-node/ &mlp; +/delete-node/ &ohci1; +/delete-node/ &pciec1; +/delete-node/ &sata; +/delete-node/ &usb2_phy1; +/delete-node/ &usb3_peri0; +/delete-node/ &usb3_phy0; +/delete-node/ &vin0csi20; +/delete-node/ &vin1csi20; +/delete-node/ &vin2csi20; +/delete-node/ &vin3csi20; +/delete-node/ &vin4csi20; +/delete-node/ &vin5csi20; +/delete-node/ &vin6csi20; +/delete-node/ &vin7csi20; +/delete-node/ &xhci0; + +&sdhi0 { + compatible = "renesas,sdhi-r8a779md", "renesas,rcar-gen3-sdhi"; +}; + +&sdhi1 { + compatible = "renesas,sdhi-r8a779md", "renesas,rcar-gen3-sdhi"; +}; + +&sdhi2 { + compatible = "renesas,sdhi-r8a779md", "renesas,rcar-gen3-sdhi"; +}; + +&sdhi3 { + compatible = "renesas,sdhi-r8a779md", "renesas,rcar-gen3-sdhi"; + no-mmc; +}; diff --git a/arch/arm/mach-renesas/Kconfig.rcar3 b/arch/arm/mach-renesas/Kconfig.rcar3 index 8479875178d..6bed7684fb8 100644 --- a/arch/arm/mach-renesas/Kconfig.rcar3 +++ b/arch/arm/mach-renesas/Kconfig.rcar3 @@ -164,12 +164,20 @@ config TARGET_ULCB help Support for Renesas R-Car Gen3 ULCB platform +config TARGET_GEIST + bool "Geist board" + imply R8A77965 + imply SYS_MALLOC_F + help + Support for Renesas R-Car Gen3 Geist platform + endchoice source "board/renesas/condor/Kconfig" source "board/renesas/draak/Kconfig" source "board/renesas/eagle/Kconfig" source "board/renesas/ebisu/Kconfig" +source "board/renesas/geist/Kconfig" source "board/renesas/salvator-x/Kconfig" source "board/renesas/ulcb/Kconfig" source "board/renesas/v3hsk/Kconfig" diff --git a/arch/arm/mach-renesas/cpu_info.c b/arch/arm/mach-renesas/cpu_info.c index f040d732a51..42183e2daa5 100644 --- a/arch/arm/mach-renesas/cpu_info.c +++ b/arch/arm/mach-renesas/cpu_info.c @@ -114,6 +114,8 @@ int arch_misc_init(void) int print_cpuinfo(void) { + const uintptr_t pfc_base = 0xe6060000; + void __iomem *rcar_m3nm3l_ident = (void __iomem *)pfc_base + 0x800; int i = renesas_cpuinfo_idx(); if (renesas_cpuinfo[i].cpu_type == RENESAS_CPU_TYPE_R8A7796 && @@ -123,6 +125,17 @@ int print_cpuinfo(void) return 0; } + /* + * M3Le PRR ID is the same as M3N , but PFC register 0x800 reads 0 + * on M3N and 1 on M3Le. Use this to discern M3Le from M3N . + */ + if (renesas_cpuinfo[i].cpu_type == RENESAS_CPU_TYPE_R8A77965 && + readl(rcar_m3nm3l_ident) == 1) { + printf("CPU: Renesas Electronics R8A779MD rev %d.%d\n", + renesas_get_cpu_rev_integer(), renesas_get_cpu_rev_fraction()); + return 0; + } + printf("CPU: Renesas Electronics %s rev %d.%d\n", get_cpu_name(i), renesas_get_cpu_rev_integer(), renesas_get_cpu_rev_fraction()); diff --git a/board/renesas/geist/Kconfig b/board/renesas/geist/Kconfig new file mode 100644 index 00000000000..da36be0942f --- /dev/null +++ b/board/renesas/geist/Kconfig @@ -0,0 +1,15 @@ +if TARGET_GEIST + +config SYS_SOC + default "renesas" + +config SYS_BOARD + default "geist" + +config SYS_VENDOR + default "renesas" + +config SYS_CONFIG_NAME + default "geist" + +endif diff --git a/board/renesas/geist/Makefile b/board/renesas/geist/Makefile new file mode 100644 index 00000000000..3e33c91e9e7 --- /dev/null +++ b/board/renesas/geist/Makefile @@ -0,0 +1,9 @@ +# +# Copyright (C) 2025-2026 Renesas Electronics Corporation +# +# SPDX-License-Identifier: GPL-2.0-only +# + +ifndef CONFIG_XPL_BUILD +obj-y += geist.o +endif diff --git a/board/renesas/geist/geist.c b/board/renesas/geist/geist.c new file mode 100644 index 00000000000..09241aed14c --- /dev/null +++ b/board/renesas/geist/geist.c @@ -0,0 +1,36 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * This file is Geist board support. + * + * Copyright (C) 2025-2026 Renesas Electronics Corporation + */ + +#include +#include +#include +#include + +#define HSUSB_MSTP704 BIT(4) /* HSUSB */ + +/* HSUSB block registers */ +#define HSUSB_REG_LPSTS 0xE6590102 +#define HSUSB_REG_LPSTS_SUSPM_NORMAL BIT(14) +#define HSUSB_REG_UGCTRL2 0xE6590184 +#define HSUSB_REG_UGCTRL2_USB0SEL 0x30 +#define HSUSB_REG_UGCTRL2_USB0SEL_EHCI 0x10 + +int board_init(void) +{ + /* USB1 pull-up */ + setbits_le32(PFC_PUEN6, PUEN_USB1_OVC | PUEN_USB1_PWEN); + + /* Configure the HSUSB block */ + mstp_clrbits_le32(SMSTPCR7, SMSTPCR7, HSUSB_MSTP704); + /* Choice USB0SEL */ + clrsetbits_le32(HSUSB_REG_UGCTRL2, HSUSB_REG_UGCTRL2_USB0SEL, + HSUSB_REG_UGCTRL2_USB0SEL_EHCI); + /* low power status */ + setbits_le16(HSUSB_REG_LPSTS, HSUSB_REG_LPSTS_SUSPM_NORMAL); + + return 0; +} diff --git a/configs/r8a779md_geist_defconfig b/configs/r8a779md_geist_defconfig new file mode 100644 index 00000000000..2d25690354b --- /dev/null +++ b/configs/r8a779md_geist_defconfig @@ -0,0 +1,75 @@ +#include + +# CONFIG_OF_UPSTREAM is not set + +CONFIG_ARM=y +CONFIG_ARCH_RENESAS=y +CONFIG_RCAR_GEN3=y +CONFIG_COUNTER_FREQUENCY=16666666 +CONFIG_ARCH_CPU_INIT=y +CONFIG_ENV_SIZE=0x20000 +CONFIG_ENV_OFFSET=0xFFFE0000 +CONFIG_DEFAULT_DEVICE_TREE="r8a779md-geist" +CONFIG_SPL_TEXT_BASE=0xe6338000 +CONFIG_TARGET_GEIST=y +CONFIG_SPL_HAVE_INIT_STACK=y +CONFIG_SPL_STACK=0xe6304000 +CONFIG_SPL_HAS_BSS_LINKER_SECTION=y +CONFIG_SPL_BSS_START_ADDR=0xe633f000 +CONFIG_SPL_BSS_MAX_SIZE=0x1000 +CONFIG_PCI=y +CONFIG_SYS_MONITOR_BASE=0x00000000 +# CONFIG_EFI_UNICODE_CAPITALIZATION is not set +# CONFIG_BOOTSTD is not set +CONFIG_USE_BOOTARGS=y +CONFIG_USE_BOOTCOMMAND=y +CONFIG_BOOTCOMMAND="setexpr dloadaddr ${loadaddr} + 0x200000 && setexpr dloadaddr ${dloadaddr} \\\\& 0xffc00000 && setexpr kloadaddr ${dloadaddr} + 0x200000 && tftp ${dloadaddr} Image-r8a779md-geist.dtb && tftp ${kloadaddr} Image && booti ${kloadaddr} - ${dloadaddr}" +CONFIG_DEFAULT_FDT_FILE="r8a779md-geist.dtb" +# CONFIG_SPL_SHARES_INIT_SP_ADDR is not set +CONFIG_SYS_EEPROM_PAGE_WRITE_DELAY_MS=10 +CONFIG_CMD_DFU=y +CONFIG_CMD_MMC=y +CONFIG_CMD_PCI=y +CONFIG_CMD_USB=y +CONFIG_CMD_USB_MASS_STORAGE=y +CONFIG_DM_USB_GADGET=y +CONFIG_MULTI_DTB_FIT_LZO=y +CONFIG_MULTI_DTB_FIT_USER_DEFINED_AREA=y +CONFIG_OF_DTB_PROPS_REMOVE=y +CONFIG_OF_REMOVE_PROPS="dmas dma-names interrupt-parent interrupts interrupts-extended interrupt-names interrupt-map interrupt-map-mask iommus" +CONFIG_ENV_IS_IN_MMC=y +CONFIG_ENV_RELOC_GD_ENV_ADDR=y +CONFIG_ENV_MMC_EMMC_HW_PARTITION=2 +CONFIG_DFU_TFTP=y +CONFIG_DFU_RAM=y +CONFIG_DFU_SF=y +CONFIG_SYS_I2C_RCAR_IIC=y +CONFIG_MISC=y +CONFIG_I2C_EEPROM=y +CONFIG_SYS_I2C_EEPROM_ADDR=0x70 +CONFIG_MMC_IO_VOLTAGE=y +CONFIG_MMC_UHS_SUPPORT=y +CONFIG_MMC_HS400_SUPPORT=y +CONFIG_RENESAS_SDHI=y +CONFIG_DM_MTD=y +CONFIG_SPI_FLASH_SPANSION=y +CONFIG_PHY_MICREL=y +CONFIG_PHY_MICREL_KSZ90X1=y +CONFIG_DM_ETH_PHY=y +CONFIG_RENESAS_RAVB=y +CONFIG_NVME_PCI=y +CONFIG_PCI_REGION_MULTI_ENTRY=y +CONFIG_PCI_RCAR_GEN3=y +CONFIG_SYSINFO=y +CONFIG_TEE=y +CONFIG_OPTEE=y +CONFIG_USB=y +CONFIG_USB_EHCI_HCD=y +CONFIG_USB_EHCI_GENERIC=y +CONFIG_USB_GADGET=y +CONFIG_USB_GADGET_MANUFACTURER="Renesas" +CONFIG_USB_GADGET_VENDOR_NUM=0x045b +CONFIG_USB_GADGET_PRODUCT_NUM=0x023c +CONFIG_USB_GADGET_DOWNLOAD=y +CONFIG_USB_RENESAS_USBHS=y +CONFIG_USB_STORAGE=y diff --git a/include/configs/geist.h b/include/configs/geist.h new file mode 100644 index 00000000000..3f7e2e913ed --- /dev/null +++ b/include/configs/geist.h @@ -0,0 +1,18 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * This file is Geist board configuration. + * + * Copyright (C) 2025-2026 Renesas Electronics Corporation + */ + +#ifndef __GEIST_H +#define __GEIST_H + +#include "rcar-gen3-common.h" + +/* Environment in eMMC, at the end of 2nd "boot sector" */ + +#define CFG_SYS_FLASH_BANKS_LIST { 0x08000000 } +#define CFG_SYS_WRITE_SWAPPED_DATA + +#endif /* __GEIST_H */ From 38eeda675b299d35b3655a3fb3609df0537021d9 Mon Sep 17 00:00:00 2001 From: Tony Dinh Date: Tue, 2 Jun 2026 12:24:42 -0700 Subject: [PATCH 17/48] usb: xhci-mvebu: Enable Armada 375 in XHCI driver Add armada-375-xhci to the compatible list in XHCI MVEBU driver. Tested with WD MyCloud Gen2 NAS. Signed-off-by: Tony Dinh Reviewed-by: Marek Vasut --- drivers/usb/host/xhci-mvebu.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/usb/host/xhci-mvebu.c b/drivers/usb/host/xhci-mvebu.c index 12dc61aee9d..c294a56b3c9 100644 --- a/drivers/usb/host/xhci-mvebu.c +++ b/drivers/usb/host/xhci-mvebu.c @@ -82,6 +82,7 @@ static int xhci_usb_of_to_plat(struct udevice *dev) static const struct udevice_id xhci_usb_ids[] = { { .compatible = "marvell,armada3700-xhci" }, + { .compatible = "marvell,armada-375-xhci" }, { .compatible = "marvell,armada-380-xhci" }, { .compatible = "marvell,armada-8k-xhci" }, { } From b353d523a86775663ca2eebcd4741f3f3a9b1fe4 Mon Sep 17 00:00:00 2001 From: Francesco Valla Date: Sun, 31 May 2026 23:15:09 +0200 Subject: [PATCH 18/48] tests: fs_helper: check path validity during cleanup If the filesystem creation attempted by the FsHelper class fails, the invocation of the cleanup function will cause a TypeError exception, because the path of the filesystem itself, fed to os.remove(), will be None. This will lead to a test failure even in case a skip is instead wanted. Such an exception will lead to a backtrace like this: test/py/tests/test_fs/conftest.py:269: in fs_obj_basic fsh.mk_fs() test/py/tests/fs_helper.py:70: in mk_fs self.fs_img = mk_fs(self.config, self.fs_type, self.size_mb << 20, test/py/tests/fs_helper.py:246: in mk_fs check_call(f'mkfs.{fs_lnxtype} {mkfs_opt} {fs_img}', shell=True, /usr/lib64/python3.14/subprocess.py:420: in check_call raise CalledProcessError(retcode, cmd) E subprocess.CalledProcessError: Command '<...>' returned non-zero exit status 1. During handling of the above exception, another exception occurred: test/py/tests/test_fs/conftest.py:272: in fs_obj_basic pytest.skip('Setup failed for filesystem: ' + fs_type + '. {}'.format(err)) E Skipped: Setup failed for filesystem: ext4. Command '<...>' returned non-zero exit status 1. During handling of the above exception, another exception occurred: test/py/tests/test_fs/conftest.py:277: in fs_obj_basic fsh.cleanup() test/py/tests/fs_helper.py:91: in cleanup os.remove(self.fs_img) E TypeError: remove: path should be string, bytes or os.PathLike, not NoneType Fix this by checking if the variable containing the filesystem path is valid before attempting to call os.remove() on it. Fixes: 3691b1e4ce074 ("test: Convert fs_helper to use a class") Signed-off-by: Francesco Valla --- test/py/tests/fs_helper.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/py/tests/fs_helper.py b/test/py/tests/fs_helper.py index ee779474ce6..e3824b2c1fd 100644 --- a/test/py/tests/fs_helper.py +++ b/test/py/tests/fs_helper.py @@ -87,7 +87,7 @@ class FsHelper: """Remove created image""" if self.tmpdir: self.tmpdir.cleanup() - if self._do_cleanup: + if self._do_cleanup and self.fs_img: os.remove(self.fs_img) def __enter__(self): From 81d60060831afa50a43a6dcaf8e34932e6b8ccc2 Mon Sep 17 00:00:00 2001 From: Giovanni Santini Date: Mon, 18 May 2026 22:46:05 +0200 Subject: [PATCH 19/48] Makefile: fix extra dash in KBUILD_CFLAGS Remove an extra leading dash from the KBUILD_CFLAGS assignment under the CONFIG_CC_OPTIMIZE_FOR_DEBUG conditional block. The extra dash breaks the build when CONFIG_CC_OPTIMIZE_FOR_DEBUG is enabled. Fixes: 56ae3c2a44fc ("Makefile: repair CONFIG_CC_OPTIMIZE_FOR_DEBUG support") Signed-off-by: Giovanni Santini Reviewed-by: Simon Glass --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index f07faada3d5..e276755c489 100644 --- a/Makefile +++ b/Makefile @@ -920,7 +920,7 @@ endif ifdef CONFIG_CC_OPTIMIZE_FOR_SIZE KBUILD_CFLAGS += -Os else ifdef CONFIG_CC_OPTIMIZE_FOR_DEBUG --KBUILD_CFLAGS += -Og +KBUILD_CFLAGS += -Og # Avoid false positives -Wmaybe-uninitialized # https://gcc.gnu.org/bugzilla/show_bug.cgi?id=78394 KBUILD_CFLAGS += -Wno-maybe-uninitialized From 5188b96cdb7884cdcad2a068450e66516edf74f9 Mon Sep 17 00:00:00 2001 From: Denis Mukhin Date: Tue, 26 May 2026 14:00:02 -0700 Subject: [PATCH 20/48] .gitignore: exclude logo generated file Correct the rule in .gitignore to skip u_boot_logo.bmp.S artifact which is generated for any board with CONFIG_VIDEO_LOGO enabled. Also, correct the stale u_boot_logo name in CLEAN_FILES in top-level Makefile. Signed-off-by: Denis Mukhin Reviewed-by: Simon Glass --- .gitignore | 2 +- Makefile | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.gitignore b/.gitignore index e5d22dbe8e9..d57d3be0291 100644 --- a/.gitignore +++ b/.gitignore @@ -80,7 +80,7 @@ fit-dtb.blob* /*imx8mimage* /*imx8mcst* /*rcar4-sa0* -/drivers/video/u_boot_logo.S +/drivers/video/u_boot_logo.bmp.S /test/fdt_overlay/test-fdt-overlay-stacked.dtbo.S /test/fdt_overlay/test-fdt-overlay.dtbo.S capsule_esl_file diff --git a/Makefile b/Makefile index e276755c489..4e18eb4cfba 100644 --- a/Makefile +++ b/Makefile @@ -2544,7 +2544,7 @@ CLEAN_FILES += $(MODVERDIR) \ $(filter-out include, $(shell ls -1 $d 2>/dev/null)))) CLEAN_FILES += include/autoconf.mk* include/bmp_logo.h include/bmp_logo_data.h \ - include/config.h include/generated/env.* drivers/video/u_boot_logo.S \ + include/config.h include/generated/env.* drivers/video/u_boot_logo.bmp.S \ tools/version.h u-boot* MLO* SPL System.map fit-dtb.blob* \ u-boot-ivt.img.log u-boot-dtb.imx.log SPL.log u-boot.imx.log \ lpc32xx-* bl31.c bl31.elf bl31_*.bin image.map tispl.bin* \ From 919af6e49b1c013e8ed138f16ad2196f66900547 Mon Sep 17 00:00:00 2001 From: Francois Berder Date: Sat, 9 May 2026 22:01:42 +0200 Subject: [PATCH 21/48] net: ti: icssg: Fix portname buffer overflow portname consists of dev->parent->name ("icssg0-eth", "icssg1-eth", or "ethernet") and dev->name is the port node name ("port@0" or "port@1"). Every board DTS in the repository produces a string that overflows the buffer: "icssg1-eth-port@0" 17 chars + NUL = 18 bytes (AM642 EVM, IoT2050) "ethernet-port@0" 15 chars + NUL = 16 bytes (SR-SOM, phyboard) This commits increases portname to 64 bytes and replaces sprintf by snprintf so that any future DT node name cannot overflow it regardless of length. Signed-off-by: Francois Berder Reviewed-by: Jerome Forissier --- drivers/net/ti/icssg_prueth.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/drivers/net/ti/icssg_prueth.c b/drivers/net/ti/icssg_prueth.c index 12a162b9d68..4796d0d67cd 100644 --- a/drivers/net/ti/icssg_prueth.c +++ b/drivers/net/ti/icssg_prueth.c @@ -496,14 +496,15 @@ static int prueth_port_probe(struct udevice *dev) { struct prueth_priv *priv = dev_get_priv(dev); struct prueth *prueth; - char portname[15]; + char portname[64]; int ret; priv->dev = dev; prueth = dev_get_priv(dev->parent); priv->prueth = prueth; - sprintf(portname, "%s-%s", dev->parent->name, dev->name); + snprintf(portname, sizeof(portname), "%s-%s", dev->parent->name, dev->name); + portname[sizeof(portname) - 1] = '\0'; device_set_name(dev, portname); From a38bf2121a398538730cd42a0cf3db8f80119c62 Mon Sep 17 00:00:00 2001 From: Francois Berder Date: Mon, 11 May 2026 15:37:58 +0200 Subject: [PATCH 22/48] net: sntp: Check packet length in sntp_handler Currently, the sntp_handler uses data in the UDP packet regardless of the actual packet size. A OOB read can occur if the packet is too small. Fix it by checking the packet length before extracting seconds from a SNTP packet. Signed-off-by: Francois Berder Reviewed-by: Jerome Forissier --- net/sntp.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/net/sntp.c b/net/sntp.c index 77cee0046bd..4b3dc675bab 100644 --- a/net/sntp.c +++ b/net/sntp.c @@ -64,6 +64,9 @@ static void sntp_handler(uchar *pkt, unsigned dest, struct in_addr sip, if (dest != sntp_our_port) return; + if (len < SNTP_PACKET_LEN) + return; + /* * As the RTC's used in U-Boot support second resolution only * we simply ignore the sub-second field. From 4ba29d709419a567832276f80592d28f42e965b2 Mon Sep 17 00:00:00 2001 From: Francois Berder Date: Mon, 11 May 2026 21:55:31 +0200 Subject: [PATCH 23/48] net: dhcpv6: Prevent buffer overflow during BOOTFILE_URL parsing The net_boot_file_name is a 1024 byte buffer. However, based on DHCPv6 RFC, bootfile-url length is specified by option_len, a 16-bit unsigned integer (valid range: 0-65535). Hence, one needs to make sure that option_len is less than the size of net_boot_file_name array before copying bootfile-url to net_boot_file_name. Signed-off-by: Francois Berder Reviewed-by: Jerome Forissier --- net/dhcpv6.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/net/dhcpv6.c b/net/dhcpv6.c index 5bf935cb6a3..51f44979f8e 100644 --- a/net/dhcpv6.c +++ b/net/dhcpv6.c @@ -377,6 +377,11 @@ static void dhcp6_parse_options(uchar *rx_pkt, unsigned int len) break; case DHCP6_OPTION_OPT_BOOTFILE_URL: debug("DHCP6_OPTION_OPT_BOOTFILE_URL FOUND\n"); + if (option_len >= sizeof(net_boot_file_name)) { + debug("Option length for BOOTFILE_URL is greater or equal than %zu. Skipping\n", + sizeof(net_boot_file_name)); + break; + } copy_filename(net_boot_file_name, option_ptr, option_len + 1); debug("net_boot_file_name: %s\n", net_boot_file_name); From 2b612de8952d448ab6345c5af6e28fecea1a2f1e Mon Sep 17 00:00:00 2001 From: Francois Berder Date: Fri, 15 May 2026 18:53:32 +0200 Subject: [PATCH 24/48] net: dhcpv6: Prevent out-of-bounds reads while parsing options dhcp6_parse_options() verifies that an option's declared data fits within the packet, but does not check that option_len is large enough for the fixed-size read each case performs. A malicious DHCP server can send an ADVERTISE with a zero-length IA_NA, STATUS_CODE, SOL_MAX_RT, or BOOTFILE_PARAM option, causing the parser to read 2-4 bytes past the option's declared data. Check option_len value before each dereference of option_ptr. Signed-off-by: Francois Berder --- net/dhcpv6.c | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/net/dhcpv6.c b/net/dhcpv6.c index 51f44979f8e..640f089a2e1 100644 --- a/net/dhcpv6.c +++ b/net/dhcpv6.c @@ -339,6 +339,11 @@ static void dhcp6_parse_options(uchar *rx_pkt, unsigned int len) break; case DHCP6_OPTION_IA_TA: case DHCP6_OPTION_IA_NA: + if (option_len < sizeof(u32)) { + debug("Invalid IA_NA/IA_TA option length\n"); + break; + } + /* check the IA_ID */ if (*((u32 *)option_ptr) != htonl(sm_params.ia_id)) { debug("IA_ID mismatch 0x%08x 0x%08x\n", @@ -347,6 +352,10 @@ static void dhcp6_parse_options(uchar *rx_pkt, unsigned int len) } if (ntohs(option_hdr->option_id) == DHCP6_OPTION_IA_NA) { + if (option_len < 3 * sizeof(u32)) { + debug("Invalid IA_NA option length\n"); + break; + } /* skip past IA_ID/T1/T2 */ option_ptr += 3 * sizeof(u32); } else if (ntohs(option_hdr->option_id) == DHCP6_OPTION_IA_TA) { @@ -358,12 +367,20 @@ static void dhcp6_parse_options(uchar *rx_pkt, unsigned int len) break; case DHCP6_OPTION_STATUS_CODE: debug("DHCP6_OPTION_STATUS_CODE FOUND\n"); + if (option_len < sizeof(u16)) { + debug("Invalid status code option length\n"); + break; + } sm_params.rx_status.status_code = ntohs(*((u16 *)option_ptr)); debug("DHCP6 top-level status code %d\n", sm_params.rx_status.status_code); debug("DHCP6 status message: %.*s\n", len, option_ptr + 2); break; case DHCP6_OPTION_SOL_MAX_RT: debug("DHCP6_OPTION_SOL_MAX_RT FOUND\n"); + if (option_len != sizeof(u32)) { + debug("Invalid SOL_MAX_RT option length\n"); + break; + } sol_max_rt_sec = ntohl(*((u32 *)option_ptr)); /* A DHCP client MUST ignore any SOL_MAX_RT option values that are less @@ -394,6 +411,12 @@ static void dhcp6_parse_options(uchar *rx_pkt, unsigned int len) case DHCP6_OPTION_OPT_BOOTFILE_PARAM: if (IS_ENABLED(CONFIG_DHCP6_PXE_DHCP_OPTION)) { debug("DHCP6_OPTION_OPT_BOOTFILE_PARAM FOUND\n"); + + if (option_len < sizeof(u16)) { + debug("Invalid BOOTFILE_PARAM option length\n"); + break; + } + /* if CONFIG_DHCP6_PXE_DHCP_OPTION is set the PXE config file path * is contained in the first OPT_BOOTFILE_PARAM argument */ @@ -419,6 +442,10 @@ static void dhcp6_parse_options(uchar *rx_pkt, unsigned int len) break; case DHCP6_OPTION_PREFERENCE: debug("DHCP6_OPTION_PREFERENCE FOUND\n"); + if (option_len != 1) { + debug("Invalid preference option length\n"); + break; + } sm_params.rx_status.preference = *option_ptr; break; default: From f447887238822af40582483112cab524926e9258 Mon Sep 17 00:00:00 2001 From: Francois Berder Date: Fri, 15 May 2026 18:56:51 +0200 Subject: [PATCH 25/48] net: bootp: Prevent out-of-bounds read in dhcp_message_type dhcp_message_type() scans DHCP options looking for a 0xff end-of-options marker with no check that the scan pointer stays within the received packet. A server can send a crafted OFFER with no 0xff terminator and large option length fields, advancing the pointer past bp_vend[312] into adjacent heap memory. This is the same class of bug as CVE-2024-42040, which fixed the related bootp_process_vendor() call site. Fix it by adding an end parameter to dhcp_message_type() and checking that popt is lower than end. Signed-off-by: Francois Berder Reviewed-by: Jerome Forissier --- net/bootp.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/net/bootp.c b/net/bootp.c index 8976936b184..f0dc329d6e4 100644 --- a/net/bootp.c +++ b/net/bootp.c @@ -997,13 +997,13 @@ static void dhcp_packet_process_options(struct bootp_hdr *bp) } } -static int dhcp_message_type(unsigned char *popt) +static int dhcp_message_type(unsigned char *popt, unsigned char *end) { if (net_read_u32((u32 *)popt) != htonl(BOOTP_VENDOR_MAGIC)) return -1; popt += 4; - while (*popt != 0xff) { + while (popt < end && *popt != 0xff) { if (*popt == 53) /* DHCP Message Type */ return *(popt + 2); if (*popt == 0) { @@ -1120,7 +1120,7 @@ static void dhcp_handler(uchar *pkt, unsigned dest, struct in_addr sip, strlen(CONFIG_SYS_BOOTFILE_PREFIX)) == 0) { #endif /* CONFIG_SYS_BOOTFILE_PREFIX */ if (CONFIG_IS_ENABLED(UNIT_TEST) && - dhcp_message_type((u8 *)bp->bp_vend) == -1) { + dhcp_message_type((u8 *)bp->bp_vend, (u8 *)pkt + len) == -1) { debug("got BOOTP response; transitioning to BOUND\n"); goto dhcp_got_bootp; } @@ -1149,7 +1149,7 @@ static void dhcp_handler(uchar *pkt, unsigned dest, struct in_addr sip, case REQUESTING: debug("DHCP State: REQUESTING\n"); - if (dhcp_message_type((u8 *)bp->bp_vend) == DHCP_ACK) { + if (dhcp_message_type((u8 *)bp->bp_vend, (u8 *)pkt + len) == DHCP_ACK) { dhcp_got_bootp: dhcp_packet_process_options(bp); /* Store net params from reply */ From fac46e5aa7c448444764044467e0cceb9d12f3f0 Mon Sep 17 00:00:00 2001 From: Francois Berder Date: Fri, 15 May 2026 22:35:03 +0200 Subject: [PATCH 26/48] boot: pxe_utils: Fix potential initrd_filesize buffer overflow ulong is 64 bits on 64-bit platforms. Hence, simple_xtoa can produce up to 16 hex characters + NULL byte. The initrd_filesize buffer is only 10 bytes which can cause a buffer overflow on every PXE boot that loads an initrd on an address greater than 4GB. Increase buffer size to 17 bytes to hold the maximum hex representation of a 64-bit address. Signed-off-by: Francois Berder Reviewed-by: Jerome Forissier --- boot/pxe_utils.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/boot/pxe_utils.c b/boot/pxe_utils.c index 419ab1f1b0e..8c1310dabeb 100644 --- a/boot/pxe_utils.c +++ b/boot/pxe_utils.c @@ -546,7 +546,7 @@ static int label_boot(struct pxe_context *ctx, struct pxe_label *label) char *zboot_argv[] = { "zboot", NULL, "0", NULL, NULL }; char *kernel_addr = NULL; char *initrd_addr_str = NULL; - char initrd_filesize[10]; + char initrd_filesize[17]; char initrd_str[28]; char mac_str[29] = ""; char ip_str[68] = ""; From 389363d287585d8135a554c4419a4f580346b9f8 Mon Sep 17 00:00:00 2001 From: Denis Mukhin Date: Thu, 28 May 2026 20:44:36 -0700 Subject: [PATCH 27/48] drivers: nvme: Log I/O timeouts Current code silently swallows any timed-out commands scheduled to NVMe. Log those to be able to debug any potential problems with the NVMe hardware/firmware. Signed-off-by: Denis Mukhin Reviewed-by: Neil Armstrong Reviewed-by: Simon Glass Link: https://patch.msgid.link/20260529034441.2075305-2-dmukhin@ford.com Signed-off-by: Neil Armstrong --- drivers/nvme/nvme.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/nvme/nvme.c b/drivers/nvme/nvme.c index 980ca919632..147a104149e 100644 --- a/drivers/nvme/nvme.c +++ b/drivers/nvme/nvme.c @@ -199,8 +199,10 @@ static int nvme_submit_sync_cmd(struct nvme_queue *nvmeq, if ((status & 0x01) == phase) break; if (timeout_us > 0 && (timer_get_us() - start_time) - >= timeout_us) + >= timeout_us) { + pr_warn("nvme: cmd %#x timed out\n", cmd->common.command_id); return -ETIMEDOUT; + } } ops = (struct nvme_ops *)nvmeq->dev->udev->driver->ops; From b20ce94bb9d06c0bffe6cf0b2795fb021f7c0052 Mon Sep 17 00:00:00 2001 From: Torsten Duwe Date: Mon, 1 Jun 2026 12:39:20 +0200 Subject: [PATCH 28/48] ARM: bcm283x: Add bcm2712 PCIe memory window Add a mapping region for the PCIe bus address spaces to the BCM2712 memory controller setup. Generously merging the PCIe address spaces works sufficiently well for a boot loader. Signed-off-by: Torsten Duwe Co-authored-by: Oleksii Moisieiev Tested-by: Pedro Falcato Reviewed-by: Peter Robinson --- arch/arm/mach-bcm283x/init.c | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/arch/arm/mach-bcm283x/init.c b/arch/arm/mach-bcm283x/init.c index 7a1de22e0ae..7a2faaa4de6 100644 --- a/arch/arm/mach-bcm283x/init.c +++ b/arch/arm/mach-bcm283x/init.c @@ -18,7 +18,7 @@ #ifdef CONFIG_ARM64 #include -#define MEM_MAP_MAX_ENTRIES (4) +#define MEM_MAP_MAX_ENTRIES (5) static struct mm_region bcm283x_mem_map[MEM_MAP_MAX_ENTRIES] = { { @@ -83,6 +83,14 @@ static struct mm_region bcm2712_mem_map[MEM_MAP_MAX_ENTRIES] = { .attrs = PTE_BLOCK_MEMTYPE(MT_DEVICE_NGNRNE) | PTE_BLOCK_NON_SHARE | PTE_BLOCK_PXN | PTE_BLOCK_UXN + }, { + /* Whole PCIe section */ + .virt = 0x1800000000UL, + .phys = 0x1800000000UL, + .size = 0x0800000000UL, + .attrs = PTE_BLOCK_MEMTYPE(MT_DEVICE_NGNRNE) | + PTE_BLOCK_NON_SHARE | + PTE_BLOCK_PXN | PTE_BLOCK_UXN }, { /* SoC bus */ .virt = 0x107c000000UL, From b24c620e5e129277d50cceac2d758e8c5bf53293 Mon Sep 17 00:00:00 2001 From: Andrea della Porta Date: Mon, 1 Jun 2026 12:39:23 +0200 Subject: [PATCH 29/48] pci: brcmstb: Fix PCIe bus numbers The linux kernel assigns a new domain for every Root Complex where bus numbering starts from 0 for each domain. U-Boot does not have domains and uses a flattened bus numbering scheme instead. This means that any device or bridge on the second enumerated RC will receive a bus number equal to the last assigned one +1. This bus number contributes to the address written into the index register, which will select the configuration space to be read. Compensate for this contribution by subtracting the base bus number. Signed-off-by: Andrea della Porta Signed-off-by: Torsten Duwe Tested-by: Pedro Falcato Reviewed-by: Peter Robinson --- drivers/pci/pcie_brcmstb.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/pci/pcie_brcmstb.c b/drivers/pci/pcie_brcmstb.c index f089c48f028..47c0802df23 100644 --- a/drivers/pci/pcie_brcmstb.c +++ b/drivers/pci/pcie_brcmstb.c @@ -125,7 +125,7 @@ static int brcm_pcie_config_address(const struct udevice *dev, pci_dev_t bdf, uint offset, void **paddress) { struct brcm_pcie *pcie = dev_get_priv(dev); - unsigned int pci_bus = PCI_BUS(bdf); + unsigned int pci_bus = PCI_BUS(bdf) - dev_seq(dev); unsigned int pci_dev = PCI_DEV(bdf); unsigned int pci_func = PCI_FUNC(bdf); int idx; From d0b2a1cb3f33b63c316ad30aa9fda8ff02a6b01b Mon Sep 17 00:00:00 2001 From: Torsten Duwe Date: Mon, 1 Jun 2026 12:39:25 +0200 Subject: [PATCH 30/48] pci: brcmstb: Support different variants using a cfg struct The Linux kernel driver already had support for multiple hardware variants when the bcm2712 was added (see e.g. linux commit 10dbedad3c818 which is the last in a longer set of changes). This patch brings in this required infrastructure and adds a differentiation between 2711 and 2712 register layouts on top. Signed-off-by: Torsten Duwe Co-authored-by: Oleksii Moisieiev Tested-by: Pedro Falcato Reviewed-by: Neil Armstrong --- .../mach-bcm283x/include/mach/acpi/bcm2711.h | 5 + drivers/pci/pcie_brcmstb.c | 104 ++++++++++++++++-- 2 files changed, 99 insertions(+), 10 deletions(-) diff --git a/arch/arm/mach-bcm283x/include/mach/acpi/bcm2711.h b/arch/arm/mach-bcm283x/include/mach/acpi/bcm2711.h index a86875b1833..5171c593c72 100644 --- a/arch/arm/mach-bcm283x/include/mach/acpi/bcm2711.h +++ b/arch/arm/mach-bcm283x/include/mach/acpi/bcm2711.h @@ -70,6 +70,7 @@ #define PCIE_MISC_RC_BAR2_CONFIG_HI 0x4038 #define PCIE_MISC_RC_BAR3_CONFIG_LO 0x403c #define RC_BAR3_CONFIG_LO_SIZE_MASK 0x1f +#define PCIE_MISC_PCIE_CTRL 0x4064 #define PCIE_MISC_PCIE_STATUS 0x4068 #define STATUS_PCIE_PORT_MASK 0x80 #define STATUS_PCIE_PORT_SHIFT 7 @@ -108,6 +109,10 @@ #define PCIE_RGR1_SW_INIT_1 0x9210 #define PCIE_EXT_CFG_INDEX 0x9000 +#define RGR1_SW_INIT_1_PERST_MASK 0x1 +#define RGR1_SW_INIT_1_PERSTB_MASK 0x4 +#define RGR1_SW_INIT_1_INIT_MASK 0x2 + /* A small window pointing at the ECAM of the device selected by CFG_INDEX */ #define PCIE_EXT_CFG_DATA 0x8000 diff --git a/drivers/pci/pcie_brcmstb.c b/drivers/pci/pcie_brcmstb.c index 47c0802df23..5cb39dfd136 100644 --- a/drivers/pci/pcie_brcmstb.c +++ b/drivers/pci/pcie_brcmstb.c @@ -49,6 +49,24 @@ #define SSC_STATUS_PLL_LOCK_MASK 0x800 #define SSC_STATUS_PLL_LOCK_SHIFT 11 +enum { + RGR1_SW_INIT_1, + PCIE_HARD_DEBUG, +}; + +enum brcm_pcie_type { + BCM2711, + BCM2712 +}; + +struct brcm_pcie; + +struct brcm_pcie_cfg_data { + const int *offsets; + const enum brcm_pcie_type type; + void (*perst_set)(struct brcm_pcie *pcie, u32 val); +}; + /** * struct brcm_pcie - the PCIe controller state * @base: Base address of memory mapped IO registers of the controller @@ -61,6 +79,7 @@ struct brcm_pcie { int gen; bool ssc; + const struct brcm_pcie_cfg_data *pcie_cfg; }; /** @@ -104,6 +123,36 @@ static bool brcm_pcie_rc_mode(struct brcm_pcie *pcie) return (val & STATUS_PCIE_PORT_MASK) >> STATUS_PCIE_PORT_SHIFT; } +static void brcm_pcie_perst_set_generic(struct brcm_pcie *pcie, u32 val) +{ + if (val) + setbits_le32(pcie->base + pcie->pcie_cfg->offsets[RGR1_SW_INIT_1], + RGR1_SW_INIT_1_PERST_MASK); + else + clrbits_le32(pcie->base + pcie->pcie_cfg->offsets[RGR1_SW_INIT_1], + RGR1_SW_INIT_1_PERST_MASK); +} + +static void brcm_pcie_perst_set_2712(struct brcm_pcie *pcie, u32 val) +{ + u32 tmp; + + /* Perst bit has moved and assert value is 0 */ + tmp = readl(pcie->base + PCIE_MISC_PCIE_CTRL); + u32p_replace_bits(&tmp, !val, RGR1_SW_INIT_1_PERSTB_MASK); + writel(tmp, pcie->base + PCIE_MISC_PCIE_CTRL); +} + +static void brcm_pcie_bridge_sw_init_set(struct brcm_pcie *pcie, u32 val) +{ + if (val) + setbits_le32(pcie->base + pcie->pcie_cfg->offsets[RGR1_SW_INIT_1], + RGR1_SW_INIT_1_INIT_MASK); + else + clrbits_le32(pcie->base + pcie->pcie_cfg->offsets[RGR1_SW_INIT_1], + RGR1_SW_INIT_1_INIT_MASK); +} + /** * brcm_pcie_link_up() - Check whether the PCIe link is up * @pcie: Pointer to the PCIe controller state @@ -365,8 +414,9 @@ static int brcm_pcie_probe(struct udevice *dev) * e.g. BCM7278, the fundamental reset should not be asserted here. * This will need to be changed when support for other SoCs is added. */ - setbits_le32(base + PCIE_RGR1_SW_INIT_1, - PCIE_RGR1_SW_INIT_1_INIT_MASK | PCIE_RGR1_SW_INIT_1_PERST_MASK); + brcm_pcie_bridge_sw_init_set(pcie, 1); + if (pcie->pcie_cfg->type != BCM2712) + pcie->pcie_cfg->perst_set(pcie, 1); /* * The delay is a safety precaution to preclude the reset signal * from looking like a glitch. @@ -374,9 +424,9 @@ static int brcm_pcie_probe(struct udevice *dev) udelay(100); /* Take the bridge out of reset */ - clrbits_le32(base + PCIE_RGR1_SW_INIT_1, PCIE_RGR1_SW_INIT_1_INIT_MASK); + brcm_pcie_bridge_sw_init_set(pcie, 0); - clrbits_le32(base + PCIE_MISC_HARD_PCIE_HARD_DEBUG, + clrbits_le32(base + pcie->pcie_cfg->offsets[PCIE_HARD_DEBUG], PCIE_HARD_DEBUG_SERDES_IDDQ_MASK); /* Wait for SerDes to be stable */ @@ -426,8 +476,7 @@ static int brcm_pcie_probe(struct udevice *dev) brcm_pcie_set_gen(pcie, pcie->gen); /* Unassert the fundamental reset */ - clrbits_le32(pcie->base + PCIE_RGR1_SW_INIT_1, - PCIE_RGR1_SW_INIT_1_PERST_MASK); + pcie->pcie_cfg->perst_set(pcie, 0); /* * Wait for 100ms after PERST# deassertion; see PCIe CEM specification @@ -514,14 +563,25 @@ static int brcm_pcie_remove(struct udevice *dev) void __iomem *base = pcie->base; /* Assert fundamental reset */ - setbits_le32(base + PCIE_RGR1_SW_INIT_1, PCIE_RGR1_SW_INIT_1_PERST_MASK); + setbits_le32(base + pcie->pcie_cfg->offsets[RGR1_SW_INIT_1], + PCIE_RGR1_SW_INIT_1_PERST_MASK); /* Turn off SerDes */ - setbits_le32(base + PCIE_MISC_HARD_PCIE_HARD_DEBUG, + setbits_le32(base + pcie->pcie_cfg->offsets[PCIE_HARD_DEBUG], PCIE_HARD_DEBUG_SERDES_IDDQ_MASK); /* Shutdown bridge */ - setbits_le32(base + PCIE_RGR1_SW_INIT_1, PCIE_RGR1_SW_INIT_1_INIT_MASK); + brcm_pcie_bridge_sw_init_set(pcie, 1); + + /* + * For the controllers that are utilizing reset for bridge Sw init, + * such as BCM2712, reset should be deasserted after assertion. + * Leaving it in asserted state may lead to unexpected hangs in + * the Linux Kernel driver because it do not perform reset initialization + * and start accessing device memory. + */ + if (pcie->pcie_cfg->type == BCM2712) + brcm_pcie_bridge_sw_init_set(pcie, 0); return 0; } @@ -546,6 +606,7 @@ static int brcm_pcie_of_to_plat(struct udevice *dev) else pcie->gen = max_link_speed; + pcie->pcie_cfg = (const struct brcm_pcie_cfg_data *)dev_get_driver_data(dev); return 0; } @@ -554,8 +615,31 @@ static const struct dm_pci_ops brcm_pcie_ops = { .write_config = brcm_pcie_write_config, }; +static const int pcie_offsets[] = { + [RGR1_SW_INIT_1] = 0x9210, + [PCIE_HARD_DEBUG] = 0x4204, +}; + +static const struct brcm_pcie_cfg_data bcm2711_cfg = { + .offsets = pcie_offsets, + .type = BCM2711, + .perst_set = brcm_pcie_perst_set_generic, +}; + +static const int pcie_offsets_bcm2712[] = { + [RGR1_SW_INIT_1] = 0x0, + [PCIE_HARD_DEBUG] = 0x4304, +}; + +static const struct brcm_pcie_cfg_data bcm2712_cfg = { + .offsets = pcie_offsets_bcm2712, + .type = BCM2712, + .perst_set = brcm_pcie_perst_set_2712, +}; + static const struct udevice_id brcm_pcie_ids[] = { - { .compatible = "brcm,bcm2711-pcie" }, + { .compatible = "brcm,bcm2711-pcie", .data = (ulong)&bcm2711_cfg }, + { .compatible = "brcm,bcm2712-pcie", .data = (ulong)&bcm2712_cfg }, { } }; From 64ae1351b5203581a512ad8510e45870fdef4409 Mon Sep 17 00:00:00 2001 From: Torsten Duwe Date: Mon, 1 Jun 2026 12:39:27 +0200 Subject: [PATCH 31/48] reset: Add RPi5 brcmstb reset facilities A driver for Broadcom reset controllers ported from linux/drivers/reset/reset-brcmstb.c to U-Boot. Signed-off-by: Torsten Duwe Co-authored-by: Oleksii Moisieiev Tested-by: Pedro Falcato --- configs/rpi_arm64_defconfig | 1 + drivers/reset/Kconfig | 8 +++ drivers/reset/Makefile | 1 + drivers/reset/reset-brcmstb.c | 97 +++++++++++++++++++++++++++++++++++ 4 files changed, 107 insertions(+) create mode 100644 drivers/reset/reset-brcmstb.c diff --git a/configs/rpi_arm64_defconfig b/configs/rpi_arm64_defconfig index 69e8e72c5d7..153d7ed301e 100644 --- a/configs/rpi_arm64_defconfig +++ b/configs/rpi_arm64_defconfig @@ -44,6 +44,7 @@ CONFIG_BCMGENET=y CONFIG_PCI_BRCMSTB=y CONFIG_PINCTRL=y # CONFIG_PINCTRL_GENERIC is not set +CONFIG_RESET_BRCMSTB=y CONFIG_DM_RNG=y CONFIG_RNG_IPROC200=y # CONFIG_REQUIRE_SERIAL_CONSOLE is not set diff --git a/drivers/reset/Kconfig b/drivers/reset/Kconfig index ebf484d9df4..7f1b2a304e3 100644 --- a/drivers/reset/Kconfig +++ b/drivers/reset/Kconfig @@ -64,6 +64,14 @@ config RESET_BCM6345 help Support reset controller on BCM6345. +config RESET_BRCMSTB + depends on ARCH_BCM283X + bool "Generic Reset controller driver for Broadcom" + help + This enables reset controller for Broadcom devices. + If you wish to use reset resources managed by the Broadcom + Reset Controller, say Y here. Otherwise, say N. + config RESET_UNIPHIER bool "Reset controller driver for UniPhier SoCs" depends on ARCH_UNIPHIER diff --git a/drivers/reset/Makefile b/drivers/reset/Makefile index 088545c6473..ad5fe6b6184 100644 --- a/drivers/reset/Makefile +++ b/drivers/reset/Makefile @@ -13,6 +13,7 @@ obj-$(CONFIG_RESET_AIROHA) += reset-airoha.o obj-$(CONFIG_RESET_TI_SCI) += reset-ti-sci.o obj-$(CONFIG_RESET_HSDK) += reset-hsdk.o obj-$(CONFIG_RESET_BCM6345) += reset-bcm6345.o +obj-$(CONFIG_RESET_BRCMSTB) += reset-brcmstb.o obj-$(CONFIG_RESET_UNIPHIER) += reset-uniphier.o obj-$(CONFIG_RESET_AST2500) += reset-ast2500.o obj-$(CONFIG_RESET_AST2600) += reset-ast2600.o diff --git a/drivers/reset/reset-brcmstb.c b/drivers/reset/reset-brcmstb.c new file mode 100644 index 00000000000..7861f7c9baf --- /dev/null +++ b/drivers/reset/reset-brcmstb.c @@ -0,0 +1,97 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Broadcom STB generic reset controller + * + * Copyright (C) 2024 EPAM Systems + * + * Moved from linux kernel: + * Author: Florian Fainelli + * Copyright (C) 2018 Broadcom + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +struct brcmstb_reset { + void __iomem *base; +}; + +#define SW_INIT_SET 0x00 +#define SW_INIT_CLEAR 0x04 +#define SW_INIT_STATUS 0x08 + +#define SW_INIT_BIT(id) BIT((id) & 0x1f) +#define SW_INIT_BANK(id) ((id) >> 5) + +#define usleep_range(a, b) udelay((b)) + +/* A full bank contains extra registers that we are not utilizing but still + * qualify as a single bank. + */ +#define SW_INIT_BANK_SIZE 0x18 + +static int brcmstb_reset_assert(struct reset_ctl *rst) +{ + unsigned int off = SW_INIT_BANK(rst->id) * SW_INIT_BANK_SIZE; + struct brcmstb_reset *priv = dev_get_priv(rst->dev); + + writel_relaxed(SW_INIT_BIT(rst->id), priv->base + off + SW_INIT_SET); + return 0; +} + +static int brcmstb_reset_deassert(struct reset_ctl *rst) +{ + unsigned int off = SW_INIT_BANK(rst->id) * SW_INIT_BANK_SIZE; + struct brcmstb_reset *priv = dev_get_priv(rst->dev); + + writel_relaxed(SW_INIT_BIT(rst->id), priv->base + off + SW_INIT_CLEAR); + /* Maximum reset delay after de-asserting a line and seeing block + * operation is typically 14us for the worst case, build some slack + * here. + */ + usleep_range(100, 200); + return 0; +} + +static int brcmstb_reset_status(struct reset_ctl *rst) +{ + unsigned int off = SW_INIT_BANK(rst->id) * SW_INIT_BANK_SIZE; + struct brcmstb_reset *priv = dev_get_priv(rst->dev); + + return readl_relaxed(priv->base + off + SW_INIT_STATUS) & + SW_INIT_BIT(rst->id); +} + +struct reset_ops brcmstb_reset_reset_ops = { + .rst_assert = brcmstb_reset_assert, + .rst_deassert = brcmstb_reset_deassert, + .rst_status = brcmstb_reset_status}; + +static int brcmstb_reset_probe(struct udevice *dev) +{ + struct brcmstb_reset *priv = dev_get_priv(dev); + + priv->base = dev_remap_addr(dev); + if (!priv->base) + return -EINVAL; + + return 0; +} + +static const struct udevice_id brcmstb_reset_ids[] = { + {.compatible = "brcm,brcmstb-reset"}, {/* sentinel */}}; + +U_BOOT_DRIVER(brcmstb_reset) = { + .name = "brcmstb-reset", + .id = UCLASS_RESET, + .of_match = brcmstb_reset_ids, + .ops = &brcmstb_reset_reset_ops, + .probe = brcmstb_reset_probe, + .priv_auto = sizeof(struct brcmstb_reset), +}; From af4f915fd6d2ec9cc024a4d528cebc9c44d15036 Mon Sep 17 00:00:00 2001 From: Torsten Duwe Date: Mon, 1 Jun 2026 12:39:29 +0200 Subject: [PATCH 32/48] reset: Add RPi5 rescal reset facilities A driver for Broadcom rescal reset controllers ported from linux/drivers/reset/reset-brcmstb-rescal.c to U-Boot. Signed-off-by: Torsten Duwe Co-authored-by: Oleksii Moisieiev Tested-by: Pedro Falcato --- configs/rpi_arm64_defconfig | 1 + drivers/reset/Kconfig | 8 +++ drivers/reset/Makefile | 1 + drivers/reset/reset-brcmstb-rescal.c | 103 +++++++++++++++++++++++++++ 4 files changed, 113 insertions(+) create mode 100644 drivers/reset/reset-brcmstb-rescal.c diff --git a/configs/rpi_arm64_defconfig b/configs/rpi_arm64_defconfig index 153d7ed301e..38af5029403 100644 --- a/configs/rpi_arm64_defconfig +++ b/configs/rpi_arm64_defconfig @@ -45,6 +45,7 @@ CONFIG_PCI_BRCMSTB=y CONFIG_PINCTRL=y # CONFIG_PINCTRL_GENERIC is not set CONFIG_RESET_BRCMSTB=y +CONFIG_RESET_BRCMSTB_RESCAL=y CONFIG_DM_RNG=y CONFIG_RNG_IPROC200=y # CONFIG_REQUIRE_SERIAL_CONSOLE is not set diff --git a/drivers/reset/Kconfig b/drivers/reset/Kconfig index 7f1b2a304e3..485f907b041 100644 --- a/drivers/reset/Kconfig +++ b/drivers/reset/Kconfig @@ -72,6 +72,14 @@ config RESET_BRCMSTB If you wish to use reset resources managed by the Broadcom Reset Controller, say Y here. Otherwise, say N. +config RESET_BRCMSTB_RESCAL + depends on ARCH_BCM283X + bool "Generic Rescal Reset controller driver for Broadcom" + help + Support rescal reset controller on Broadcom. + If you wish to use reset resources managed by the Broadcom + Reset Controller, say Y here. Otherwise, say N. + config RESET_UNIPHIER bool "Reset controller driver for UniPhier SoCs" depends on ARCH_UNIPHIER diff --git a/drivers/reset/Makefile b/drivers/reset/Makefile index ad5fe6b6184..c369bdb3d6c 100644 --- a/drivers/reset/Makefile +++ b/drivers/reset/Makefile @@ -14,6 +14,7 @@ obj-$(CONFIG_RESET_TI_SCI) += reset-ti-sci.o obj-$(CONFIG_RESET_HSDK) += reset-hsdk.o obj-$(CONFIG_RESET_BCM6345) += reset-bcm6345.o obj-$(CONFIG_RESET_BRCMSTB) += reset-brcmstb.o +obj-$(CONFIG_RESET_BRCMSTB_RESCAL) += reset-brcmstb-rescal.o obj-$(CONFIG_RESET_UNIPHIER) += reset-uniphier.o obj-$(CONFIG_RESET_AST2500) += reset-ast2500.o obj-$(CONFIG_RESET_AST2600) += reset-ast2600.o diff --git a/drivers/reset/reset-brcmstb-rescal.c b/drivers/reset/reset-brcmstb-rescal.c new file mode 100644 index 00000000000..fc8fcfa8b3f --- /dev/null +++ b/drivers/reset/reset-brcmstb-rescal.c @@ -0,0 +1,103 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Broadcom STB generic reset controller + * + * Copyright (C) 2024 EPAM Systems + * Moved from linux kernel: + * Copyright (C) 2018-2020 Broadcom + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define BRCM_RESCAL_START 0x0 +#define BRCM_RESCAL_START_BIT BIT(0) +#define BRCM_RESCAL_CTRL 0x4 +#define BRCM_RESCAL_STATUS 0x8 +#define BRCM_RESCAL_STATUS_BIT BIT(0) + +struct brcm_rescal_reset { + void __iomem *base; +}; + +/* Also doubles a deassert */ +static int brcm_rescal_reset_set(struct reset_ctl *rst) +{ + struct brcm_rescal_reset *data = dev_get_priv(rst->dev); + void __iomem *base = data->base; + u32 reg; + int ret; + + reg = readl(base + BRCM_RESCAL_START); + writel(reg | BRCM_RESCAL_START_BIT, base + BRCM_RESCAL_START); + reg = readl(base + BRCM_RESCAL_START); + if (!(reg & BRCM_RESCAL_START_BIT)) { + dev_err(rst->dev, "failed to start SATA/PCIe rescal\n"); + return -EIO; + } + + ret = readl_poll_timeout(base + BRCM_RESCAL_STATUS, reg, + (reg & BRCM_RESCAL_STATUS_BIT), 100); + if (ret) { + dev_err(rst->dev, "time out on SATA/PCIe rescal\n"); + return ret; + } + + reg = readl(base + BRCM_RESCAL_START); + writel(reg & ~BRCM_RESCAL_START_BIT, base + BRCM_RESCAL_START); + + dev_dbg(rst->dev, "SATA/PCIe rescal success\n"); + return 0; +} + +/* A dummy function - deassert/reset does all the work */ +static int brcm_rescal_reset_assert(struct reset_ctl *rst) +{ + return 0; +} + +static int brcm_rescal_reset_xlate(struct reset_ctl *reset_ctl, + struct ofnode_phandle_args *args) +{ + /* This is needed if #reset-cells == 0. */ + return 0; +} + +static const struct reset_ops brcm_rescal_reset_ops = { + .rst_deassert = brcm_rescal_reset_set, + .rst_assert = brcm_rescal_reset_assert, + .of_xlate = brcm_rescal_reset_xlate, +}; + +static int brcm_rescal_reset_probe(struct udevice *dev) +{ + struct brcm_rescal_reset *data = dev_get_priv(dev); + + data->base = dev_remap_addr(dev); + if (!data->base) + return -EINVAL; + + return 0; +} + +static const struct udevice_id brcm_rescal_reset_of_match[] = { + {.compatible = "brcm,bcm7216-pcie-sata-rescal"}, + {}, +}; + +U_BOOT_DRIVER(brcmstb_reset_rescal) = { + .name = "brcmstb-reset-rescal", + .id = UCLASS_RESET, + .of_match = brcm_rescal_reset_of_match, + .ops = &brcm_rescal_reset_ops, + .probe = brcm_rescal_reset_probe, + .priv_auto = sizeof(struct brcm_rescal_reset), +}; From b6f853f1cc5ce3f7bc2da2a6df421c300858ea8a Mon Sep 17 00:00:00 2001 From: Torsten Duwe Date: Mon, 1 Jun 2026 12:39:31 +0200 Subject: [PATCH 33/48] pci: brcmstb: Get and use bridge and rescal reset properties Check whether the device tree has nodes for the two reset controls and use them if so. Signed-off-by: Torsten Duwe Co-authored-by: Oleksii Moisieiev Tested-by: Pedro Falcato Reviewed-by: Neil Armstrong --- drivers/pci/pcie_brcmstb.c | 71 +++++++++++++++++++++++++++++++++++--- 1 file changed, 66 insertions(+), 5 deletions(-) diff --git a/drivers/pci/pcie_brcmstb.c b/drivers/pci/pcie_brcmstb.c index 5cb39dfd136..012b501078a 100644 --- a/drivers/pci/pcie_brcmstb.c +++ b/drivers/pci/pcie_brcmstb.c @@ -21,6 +21,7 @@ #include #include #include +#include /* PCIe parameters */ #define BRCM_NUM_PCIE_OUT_WINS 4 @@ -79,6 +80,8 @@ struct brcm_pcie { int gen; bool ssc; + struct reset_ctl rescal; + struct reset_ctl bridge_reset; const struct brcm_pcie_cfg_data *pcie_cfg; }; @@ -143,14 +146,58 @@ static void brcm_pcie_perst_set_2712(struct brcm_pcie *pcie, u32 val) writel(tmp, pcie->base + PCIE_MISC_PCIE_CTRL); } -static void brcm_pcie_bridge_sw_init_set(struct brcm_pcie *pcie, u32 val) +static int brcm_pcie_get_resets_dt(struct udevice *dev) { + struct brcm_pcie *pcie = dev_get_priv(dev); + int ret; + + ret = reset_get_by_name(dev, "rescal", &pcie->rescal); + if (ret) { + printf("Unable to get rescal reset\n"); + return ret; + } + + ret = reset_get_by_name(dev, "bridge", &pcie->bridge_reset); + if (ret) + printf("Unable to get bridge reset\n"); + + return ret; +} + +static int brcm_pcie_do_reset(struct udevice *dev) +{ + struct brcm_pcie *pcie = dev_get_priv(dev); + int ret; + + ret = reset_deassert(&pcie->rescal); + if (ret) + printf("failed to deassert 'rescal'\n"); + return ret; +} + +static int brcm_pcie_bridge_sw_init_set(struct brcm_pcie *pcie, u32 val) +{ + int ret = 0; + + if (reset_valid(&pcie->bridge_reset)) + { + if (val) + ret = reset_assert(&pcie->bridge_reset); + else + ret = reset_deassert(&pcie->bridge_reset); + if (ret) + log_err("failed to %sassert bridge reset, err=%d\n", + val ? "" : "de", ret); + return ret; + } + if (val) setbits_le32(pcie->base + pcie->pcie_cfg->offsets[RGR1_SW_INIT_1], RGR1_SW_INIT_1_INIT_MASK); else clrbits_le32(pcie->base + pcie->pcie_cfg->offsets[RGR1_SW_INIT_1], RGR1_SW_INIT_1_INIT_MASK); + return 0; } /** @@ -405,16 +452,25 @@ static int brcm_pcie_probe(struct udevice *dev) int num_out_wins = 0; u64 rc_bar2_offset, rc_bar2_size; unsigned int scb_size_val; - int i, ret; + int i, ret = 0; u16 nlw, cls, lnksta; u32 tmp; + /* + * Ensure rescal reset for BCM2712 is really disabled. + */ + if (pcie->pcie_cfg->type == BCM2712) + ret = brcm_pcie_do_reset(dev); + if (ret) + return ret; /* * Reset the bridge, assert the fundamental reset. Note for some SoCs, * e.g. BCM7278, the fundamental reset should not be asserted here. * This will need to be changed when support for other SoCs is added. */ - brcm_pcie_bridge_sw_init_set(pcie, 1); + ret = brcm_pcie_bridge_sw_init_set(pcie, 1); + if (ret) + return ret; if (pcie->pcie_cfg->type != BCM2712) pcie->pcie_cfg->perst_set(pcie, 1); /* @@ -424,8 +480,9 @@ static int brcm_pcie_probe(struct udevice *dev) udelay(100); /* Take the bridge out of reset */ - brcm_pcie_bridge_sw_init_set(pcie, 0); - + ret = brcm_pcie_bridge_sw_init_set(pcie, 0); + if (ret) + return ret; clrbits_le32(base + pcie->pcie_cfg->offsets[PCIE_HARD_DEBUG], PCIE_HARD_DEBUG_SERDES_IDDQ_MASK); @@ -607,6 +664,10 @@ static int brcm_pcie_of_to_plat(struct udevice *dev) pcie->gen = max_link_speed; pcie->pcie_cfg = (const struct brcm_pcie_cfg_data *)dev_get_driver_data(dev); + + if (pcie->pcie_cfg->type == BCM2712) + return brcm_pcie_get_resets_dt(dev); + return 0; } From df883ec51b5b602b68a517bc513eaba3b115d890 Mon Sep 17 00:00:00 2001 From: Torsten Duwe Date: Mon, 1 Jun 2026 12:39:34 +0200 Subject: [PATCH 34/48] pci: brcmstb: Fix iBAR size calculation Fix inbound window size calculation, like Linux commit 25a98c7270156. Signed-off-by: Torsten Duwe Tested-by: Pedro Falcato Reviewed-by: Neil Armstrong --- drivers/pci/pcie_brcmstb.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/pci/pcie_brcmstb.c b/drivers/pci/pcie_brcmstb.c index 012b501078a..164d8e2b7fe 100644 --- a/drivers/pci/pcie_brcmstb.c +++ b/drivers/pci/pcie_brcmstb.c @@ -101,8 +101,8 @@ static int brcm_pcie_encode_ibar_size(u64 size) if (log2_in >= 12 && log2_in <= 15) /* Covers 4KB to 32KB (inclusive) */ return (log2_in - 12) + 0x1c; - else if (log2_in >= 16 && log2_in <= 37) - /* Covers 64KB to 32GB, (inclusive) */ + else if (log2_in >= 16 && log2_in <= 36) + /* Covers 64KB to 64GB, (inclusive) */ return log2_in - 15; /* Something is awry so disable */ From 585d6cfd9b6b886ddfde9b66c9399eadb5086936 Mon Sep 17 00:00:00 2001 From: Torsten Duwe Date: Mon, 1 Jun 2026 12:39:36 +0200 Subject: [PATCH 35/48] pci: brcmstb: rework iBAR handling Rework the setup of inbound PCIe windows: use the convenience functions from Linux kernel commit ae6476c6de187 to calculate the BAR offsets and factor out the setup code into a separate function. The Linux kernel first allocates and populates an array of inbound_win[] and sets the BARs from it later, while U-Boot does it all on the fly, in one go, so the code is not 1:1 comparable. Signed-off-by: Torsten Duwe Tested-by: Pedro Falcato Reviewed-by: Neil Armstrong --- drivers/pci/pcie_brcmstb.c | 150 ++++++++++++++++++++++++++++++++----- 1 file changed, 131 insertions(+), 19 deletions(-) diff --git a/drivers/pci/pcie_brcmstb.c b/drivers/pci/pcie_brcmstb.c index 164d8e2b7fe..624376fe235 100644 --- a/drivers/pci/pcie_brcmstb.c +++ b/drivers/pci/pcie_brcmstb.c @@ -50,6 +50,29 @@ #define SSC_STATUS_PLL_LOCK_MASK 0x800 #define SSC_STATUS_PLL_LOCK_SHIFT 11 +#define PCIE_RC_PL_PHY_CTL_15 0x184c +#define PCIE_RC_PL_PHY_CTL_15_DIS_PLL_PD_MASK 0x400000 +#define PCIE_RC_PL_PHY_CTL_15_PM_CLK_PERIOD_MASK 0xff + +#define PCIE_MISC_UBUS_CTRL 0x40a4 +#define PCIE_MISC_UBUS_CTRL_UBUS_PCIE_REPLY_ERR_DIS_MASK BIT(13) +#define PCIE_MISC_UBUS_CTRL_UBUS_PCIE_REPLY_DECERR_DIS_MASK BIT(19) +#define PCIE_MISC_AXI_READ_ERROR_DATA 0x4170 +#define PCIE_MISC_UBUS_TIMEOUT 0x40A8 +#define PCIE_MISC_RC_CONFIG_RETRY_TIMEOUT 0x405c +#define PCIE_MISC_RC_BAR4_CONFIG_LO 0x40d4 +#define PCIE_MISC_RC_BAR4_CONFIG_HI 0x40d8 +#define PCIE_MISC_UBUS_BAR_CONFIG_REMAP_HI_MASK 0xff +#define PCIE_MISC_UBUS_BAR4_CONFIG_REMAP_HI 0x4110 +#define PCIE_MISC_UBUS_BAR_CONFIG_REMAP_ENABLE 0x1 +#define PCIE_MISC_UBUS_BAR_CONFIG_REMAP_LO_MASK 0xfffff000 +#define PCIE_MISC_UBUS_BAR4_CONFIG_REMAP_LO 0x410c + +#define PCIE_MISC_UBUS_BAR1_CONFIG_REMAP 0x40ac +#define PCIE_MISC_UBUS_BAR2_CONFIG_REMAP 0x40b4 +#define PCIE_MISC_UBUS_BAR2_CONFIG_REMAP_ACCESS_ENABLE_MASK BIT(0) +#define MISC_CTRL_PCIE_RCB_MPS_MODE_MASK 0x400 + enum { RGR1_SW_INIT_1, PCIE_HARD_DEBUG, @@ -441,17 +464,105 @@ static void brcm_pcie_set_outbound_win(struct brcm_pcie *pcie, writel(tmp, base + PCIE_MEM_WIN0_LIMIT_HI(win)); } +static u32 brcm_bar_reg_offset(int bar) +{ + if (bar <= 3) + return PCIE_MISC_RC_BAR1_CONFIG_LO + 8 * (bar - 1); + else + return PCIE_MISC_RC_BAR4_CONFIG_LO + 8 * (bar - 4); +} + +static u32 brcm_ubus_reg_offset(int bar) +{ + if (bar <= 3) + return PCIE_MISC_UBUS_BAR1_CONFIG_REMAP + 8 * (bar - 1); + else + return PCIE_MISC_UBUS_BAR4_CONFIG_REMAP_LO + 8 * (bar - 4); +} + +/* + * Round size up to the next power of two, as required by + * brcm_pcie_encode_ibar_size(). If size is already a power of two + * fls64(size - 1) still gives the correct result because the hardware + * encodes the exponent, not the raw value. + */ +static u64 brcm_ibar_round_size(u64 size) +{ + return 1ULL << fls64(size - 1); +} + +static void brcm_pcie_set_inbound_windows(struct udevice *dev) +{ + struct brcm_pcie *pcie = dev_get_priv(dev); + void __iomem *base = pcie->base; + bool is_2712 = (pcie->pcie_cfg->type == BCM2712); + int i, ibar_no, ret; + u32 tmp; + + ibar_no = 0; + /* pre-2712 chips leave the first entry empty */ + if (pcie->pcie_cfg->type != BCM2712) + ibar_no++; + + /* program inbound windows from OF property "dma-regions" */ + for (i = 0; i < 7; i++, ibar_no++) { + u64 bar_cpu, bar_size, bar_pci; + struct pci_region region; + int ubus_bar_offset, rc_bar_offset; + + ret = pci_get_dma_regions(dev, ®ion, i); + if (ret) /* no region #i? Then we're done. */ + break; + ubus_bar_offset = brcm_ubus_reg_offset(ibar_no + 1); + rc_bar_offset = brcm_bar_reg_offset(ibar_no + 1); + + bar_pci = region.bus_start; + bar_cpu = region.phys_start; + bar_size = region.size; + + if (is_2712) { + /* BCM2712: BAR holds raw PCI address; UBUS remap + * registers supply the CPU-side translation. */ + tmp = lower_32_bits(bar_pci); + u32p_replace_bits(&tmp, brcm_pcie_encode_ibar_size(bar_size), + RC_BAR2_CONFIG_LO_SIZE_MASK); + writel(tmp, base + rc_bar_offset); + writel(upper_32_bits(bar_pci), base + rc_bar_offset + 4); + + tmp = lower_32_bits(bar_cpu) & + PCIE_MISC_UBUS_BAR_CONFIG_REMAP_LO_MASK; + tmp |= PCIE_MISC_UBUS_BAR_CONFIG_REMAP_ENABLE; + writel(tmp, base + ubus_bar_offset); + + tmp = upper_32_bits(bar_cpu) & + PCIE_MISC_UBUS_BAR_CONFIG_REMAP_HI_MASK; + writel(tmp, base + ubus_bar_offset + 4); + } else { + /* Pre-BCM2712 (e.g. BCM2711 / RPi4): the BAR config + * register holds the offset (bus_start - phys_start), + * not the raw PCI address. The size must be rounded + * up to the next power of two before encoding. */ + u64 bar_offset = bar_pci - bar_cpu; + u64 bar_size_po2 = brcm_ibar_round_size(bar_size); + + tmp = lower_32_bits(bar_offset); + u32p_replace_bits(&tmp, brcm_pcie_encode_ibar_size(bar_size_po2), + RC_BAR2_CONFIG_LO_SIZE_MASK); + writel(tmp, base + rc_bar_offset); + writel(upper_32_bits(bar_offset), base + rc_bar_offset + 4); + /* UBUS remap registers are not used on pre-2712 hardware. */ + } + } +} + static int brcm_pcie_probe(struct udevice *dev) { struct udevice *ctlr = pci_get_controller(dev); struct pci_controller *hose = dev_get_uclass_priv(ctlr); struct brcm_pcie *pcie = dev_get_priv(dev); void __iomem *base = pcie->base; - struct pci_region region; bool ssc_good = false; int num_out_wins = 0; - u64 rc_bar2_offset, rc_bar2_size; - unsigned int scb_size_val; int i, ret = 0; u16 nlw, cls, lnksta; u32 tmp; @@ -496,23 +607,22 @@ static int brcm_pcie_probe(struct udevice *dev) MISC_CTRL_CFG_READ_UR_MODE_MASK | MISC_CTRL_MAX_BURST_SIZE_128); - pci_get_dma_regions(dev, ®ion, 0); - rc_bar2_offset = region.bus_start - region.phys_start; - rc_bar2_size = 1ULL << fls64(region.size - 1); - - tmp = lower_32_bits(rc_bar2_offset); - u32p_replace_bits(&tmp, brcm_pcie_encode_ibar_size(rc_bar2_size), - RC_BAR2_CONFIG_LO_SIZE_MASK); - writel(tmp, base + PCIE_MISC_RC_BAR2_CONFIG_LO); - writel(upper_32_bits(rc_bar2_offset), - base + PCIE_MISC_RC_BAR2_CONFIG_HI); - - scb_size_val = rc_bar2_size ? - ilog2(rc_bar2_size) - 15 : 0xf; /* 0xf is 1GB */ - tmp = readl(base + PCIE_MISC_MISC_CTRL); - u32p_replace_bits(&tmp, scb_size_val, - MISC_CTRL_SCB0_SIZE_MASK); + if (pcie->pcie_cfg->type == BCM2712) { + /* BCM2712: fixed 32GB SCB0 window */ + u32p_replace_bits(&tmp, 20, MISC_CTRL_SCB0_SIZE_MASK); + } else { + /* Pre-BCM2712: size SCB0 to match the actual DMA region. + * rc_bar2_size must be a power of two; ilog2(size) - 15 + * gives the hardware encoding (e.g. 1GB -> 15). */ + struct pci_region region; + u64 rc_bar2_size; + + pci_get_dma_regions(dev, ®ion, 0); + rc_bar2_size = brcm_ibar_round_size(region.size); + u32p_replace_bits(&tmp, rc_bar2_size ? ilog2(rc_bar2_size) - 15 : 0xf, + MISC_CTRL_SCB0_SIZE_MASK); + } writel(tmp, base + PCIE_MISC_MISC_CTRL); /* Disable the PCIe->GISB memory window (RC_BAR1) */ @@ -529,6 +639,8 @@ static int brcm_pcie_probe(struct udevice *dev) /* Clear any interrupts we find on boot */ writel(0xffffffff, base + PCIE_MSI_INTR2_CLR); + brcm_pcie_set_inbound_windows(dev); + if (pcie->gen) brcm_pcie_set_gen(pcie, pcie->gen); From de9ea19cf77817c6de2b74d26cfc18d648f88e03 Mon Sep 17 00:00:00 2001 From: Torsten Duwe Date: Mon, 1 Jun 2026 12:39:40 +0200 Subject: [PATCH 36/48] pci: brcmstb: Adapt to AXI bridge Fix-ups for the BCM root complex when it is located behind an AXI bridge and clocked with 54MHz. Some are from kernel commit 377bced88c326, some where picked by Oleksii off a now-stale older branch. All reworked for the simpler setup code in U-Boot. Signed-off-by: Torsten Duwe Co-authored-by: Oleksii Moisieiev Tested-by: Pedro Falcato Reviewed-by: Neil Armstrong --- .../mach-bcm283x/include/mach/acpi/bcm2711.h | 1 + drivers/pci/pcie_brcmstb.c | 64 ++++++++++++++++++- 2 files changed, 64 insertions(+), 1 deletion(-) diff --git a/arch/arm/mach-bcm283x/include/mach/acpi/bcm2711.h b/arch/arm/mach-bcm283x/include/mach/acpi/bcm2711.h index 5171c593c72..c72b47e1b10 100644 --- a/arch/arm/mach-bcm283x/include/mach/acpi/bcm2711.h +++ b/arch/arm/mach-bcm283x/include/mach/acpi/bcm2711.h @@ -54,6 +54,7 @@ #define MISC_CTRL_CFG_READ_UR_MODE_MASK 0x2000 #define MISC_CTRL_MAX_BURST_SIZE_MASK 0x300000 #define MISC_CTRL_MAX_BURST_SIZE_128 0x0 +#define MISC_CTRL_MAX_BURST_SIZE_128_2712 0x100000 #define MISC_CTRL_SCB0_SIZE_MASK 0xf8000000 #define PCIE_MISC_CPU_2_PCIE_MEM_WIN0_LO 0x400c diff --git a/drivers/pci/pcie_brcmstb.c b/drivers/pci/pcie_brcmstb.c index 624376fe235..1b03b0a7b05 100644 --- a/drivers/pci/pcie_brcmstb.c +++ b/drivers/pci/pcie_brcmstb.c @@ -555,6 +555,30 @@ static void brcm_pcie_set_inbound_windows(struct udevice *dev) } } +static void brcm_pcie_munge_pll(struct brcm_pcie *pcie) +{ + u32 tmp; + int ret, i; + u8 regs[] = { 0x16, 0x17, 0x18, 0x19, 0x1b, 0x1c, 0x1e }; + u16 data[] = { 0x50b9, 0xbda1, 0x0094, 0x97b4, 0x5030, 0x5030, 0x0007 }; + + ret = brcm_pcie_mdio_write(pcie->base, MDIO_PORT0, SET_ADDR_OFFSET, + 0x1600); + for (i = 0; i < ARRAY_SIZE(regs); i++) { + brcm_pcie_mdio_read(pcie->base, MDIO_PORT0, regs[i], &tmp); + debug("PCIE MDIO pre_refclk 0x%02x = 0x%04x\n", + regs[i], tmp); + } + for (i = 0; i < ARRAY_SIZE(regs); i++) { + brcm_pcie_mdio_write(pcie->base, MDIO_PORT0, regs[i], data[i]); + brcm_pcie_mdio_read(pcie->base, MDIO_PORT0, regs[i], &tmp); + debug("PCIE MDIO post_refclk 0x%02x = 0x%04x\n", + regs[i], tmp); + } + + udelay(200); +} + static int brcm_pcie_probe(struct udevice *dev) { struct udevice *ctlr = pci_get_controller(dev); @@ -600,12 +624,27 @@ static int brcm_pcie_probe(struct udevice *dev) /* Wait for SerDes to be stable */ udelay(100); + if (pcie->pcie_cfg->type == BCM2712) { + /* Allow a 54MHz (xosc) refclk source */ + brcm_pcie_munge_pll(pcie); + /* Fix for L1SS errata */ + tmp = readl(base + PCIE_RC_PL_PHY_CTL_15); + tmp &= ~PCIE_RC_PL_PHY_CTL_15_PM_CLK_PERIOD_MASK; + /* PM clock period is 18.52ns (round down) */ + tmp |= 0x12; + writel(tmp, base + PCIE_RC_PL_PHY_CTL_15); + } + + tmp = (pcie->pcie_cfg->type == BCM2712) ? + MISC_CTRL_MAX_BURST_SIZE_128_2712 : + MISC_CTRL_MAX_BURST_SIZE_128; /* Set SCB_MAX_BURST_SIZE, CFG_READ_UR_MODE, SCB_ACCESS_EN */ clrsetbits_le32(base + PCIE_MISC_MISC_CTRL, MISC_CTRL_MAX_BURST_SIZE_MASK, MISC_CTRL_SCB_ACCESS_EN_MASK | MISC_CTRL_CFG_READ_UR_MODE_MASK | - MISC_CTRL_MAX_BURST_SIZE_128); + MISC_CTRL_PCIE_RCB_MPS_MODE_MASK | + tmp); tmp = readl(base + PCIE_MISC_MISC_CTRL); if (pcie->pcie_cfg->type == BCM2712) { @@ -625,6 +664,29 @@ static int brcm_pcie_probe(struct udevice *dev) } writel(tmp, base + PCIE_MISC_MISC_CTRL); + if (pcie->pcie_cfg->type == BCM2712) { + /* Suppress AXI error responses and return 1s for read failures */ + tmp = readl(base + PCIE_MISC_UBUS_CTRL); + u32p_replace_bits(&tmp, 1, PCIE_MISC_UBUS_CTRL_UBUS_PCIE_REPLY_ERR_DIS_MASK); + u32p_replace_bits(&tmp, 1, PCIE_MISC_UBUS_CTRL_UBUS_PCIE_REPLY_DECERR_DIS_MASK); + writel(tmp, base + PCIE_MISC_UBUS_CTRL); + writel(0xffffffff, base + PCIE_MISC_AXI_READ_ERROR_DATA); + + /* + * Adjust timeouts. The UBUS timeout also affects CRS + * completion retries, as the request will get terminated if + * either timeout expires, so both have to be a large value + * (in clocks of 750MHz). + * Set UBUS timeout to 250ms, then set RC config retry timeout + * to be ~240ms. + * + * Setting CRSVis=1 will stop the core from blocking on a CRS + * response, but does require the device to be well-behaved... + */ + writel(0xB2D0000, base + PCIE_MISC_UBUS_TIMEOUT); + writel(0xABA0000, base + PCIE_MISC_RC_CONFIG_RETRY_TIMEOUT); + } + /* Disable the PCIe->GISB memory window (RC_BAR1) */ clrbits_le32(base + PCIE_MISC_RC_BAR1_CONFIG_LO, RC_BAR1_CONFIG_LO_SIZE_MASK); From af4aad1f0a0beba82d2015d79b450b59bf34d2bc Mon Sep 17 00:00:00 2001 From: Marek Vasut Date: Wed, 3 Jun 2026 16:17:55 +0200 Subject: [PATCH 37/48] lmb: Optionally limit available memory to 4 GiB on limited systems Some architectures can not DMA above 4 GiB boundary, limit available memory to memory below 4 GiB boundary. Signed-off-by: Marek Vasut Reviewed-by: Ilias Apalodimas Tested-by: Ilias Apalodimas #rpi4 8GiB --- lib/Kconfig | 8 ++++++++ lib/lmb.c | 20 +++++++++++++++++++- 2 files changed, 27 insertions(+), 1 deletion(-) diff --git a/lib/Kconfig b/lib/Kconfig index 77ebc79e1db..29911068a69 100644 --- a/lib/Kconfig +++ b/lib/Kconfig @@ -1295,6 +1295,14 @@ config SPL_LMB_ARCH_MEM_MAP memory map. Enable this config in such scenarios which allow architectures and boards to define their own memory map. +config LMB_LIMIT_DMA_BELOW_4G + bool + depends on LMB + default y if ARCH_BCM283X + help + Some architectures can not DMA above 4 GiB boundary, + limit available memory to memory below 4 GiB boundary. + config PHANDLE_CHECK_SEQ bool "Enable phandle check while getting sequence number" help diff --git a/lib/lmb.c b/lib/lmb.c index 8f12c6ad8e5..a2aeb526e29 100644 --- a/lib/lmb.c +++ b/lib/lmb.c @@ -611,6 +611,7 @@ static __maybe_unused void lmb_reserve_common_spl(void) static void lmb_add_memory(void) { int i; + phys_addr_t bank_end; phys_size_t size; u64 ram_top = gd->ram_top; struct bd_info *bd = gd->bd; @@ -625,8 +626,25 @@ static void lmb_add_memory(void) for (i = 0; i < CONFIG_NR_DRAM_BANKS; i++) { size = bd->bi_dram[i].size; - if (size) + if (size) { lmb_add(bd->bi_dram[i].start, size); + if (!IS_ENABLED(CONFIG_LMB_LIMIT_DMA_BELOW_4G)) + continue; + + bank_end = bd->bi_dram[i].start + size; + + /* + * Reserve memory above ram_top as + * no-overwrite so that it cannot be + * allocated + */ + if (bd->bi_dram[i].start >= ram_top) + lmb_reserve(bd->bi_dram[i].start, size, + LMB_NOOVERWRITE); + else if (bank_end > ram_top) + lmb_reserve(ram_top, bank_end - ram_top, + LMB_NOOVERWRITE); + } } } From 31c2bb0cd1832f1030c42fbf588e7c4911e619dc Mon Sep 17 00:00:00 2001 From: Sam Day Date: Thu, 28 May 2026 05:21:06 +0000 Subject: [PATCH 38/48] arch: arm: force 4K page alignment in linker Since 5c71f8110, the u-boot.elf produced by dragonboard410c_defconfig no longer fits in the 1MiB aboot partition it is intended for. To be precise, this issue occurs on toolchains that have a linker with a COMMONPAGESIZE > 4K. Since u-boot is hardcoded for 4K granules, we ensure that the linker doesn't try to align to anything larger than that, otherwise we're just filling our ELFs with a bunch of useless zeros. Suggested-by: Stephan Gerhold Signed-off-by: Sam Day Tested-by: Peter Robinson --- arch/arm/config.mk | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/arch/arm/config.mk b/arch/arm/config.mk index a7eff84a267..bce9a31e966 100644 --- a/arch/arm/config.mk +++ b/arch/arm/config.mk @@ -112,6 +112,14 @@ endif # needed for relocation LDFLAGS_u-boot += -pie +ifeq ($(CONFIG_ARM64),y) +# U-Boot uses fixed 4K granules, so we force the linker to match. +# Otherwise, we're subject to toolchain preferences, (e.g Fedora's +# aarch64-linux-none toolchain selects 64K granules) and we end up wasting +# a lot of space in ELFs with MMU_PGPROT enabled. +LDFLAGS_u-boot += -z common-page-size=0x1000 -z max-page-size=0x1000 +endif + # # FIXME: binutils versions < 2.22 have a bug in the assembler where # branches to weak symbols can be incorrectly optimized in thumb mode From 37c6f531dafb370e7fe378f547fb8bd7a79e3869 Mon Sep 17 00:00:00 2001 From: Emanuele Ghidoli Date: Wed, 20 May 2026 15:51:34 +0200 Subject: [PATCH 39/48] board: toradex: verdin-imx95: fix ram size check calculated addresses The ram_alias_checks addresses are 32 bit values. When summed as 64 bit values the calculation is done correctly, otherwise, if they are summed as 32 bit values, the sum wraps around. Fix by adding uintptr_t recast to the base address. Fixes: 60d8255d8dc0 ("board: toradex: add Toradex Verdin iMX95") Signed-off-by: Emanuele Ghidoli Acked-by: Francesco Dolcini --- board/toradex/verdin-imx95/verdin-imx95.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/board/toradex/verdin-imx95/verdin-imx95.c b/board/toradex/verdin-imx95/verdin-imx95.c index 60c1dbb5e29..7c0804c1d1c 100644 --- a/board/toradex/verdin-imx95/verdin-imx95.c +++ b/board/toradex/verdin-imx95/verdin-imx95.c @@ -50,10 +50,10 @@ int board_late_init(void) } static const struct ram_alias_check ram_alias_checks[] = { - { (void *)(PHYS_SDRAM + SZ_8G), (void *)(PHYS_SDRAM), SZ_16G }, - { (void *)(PHYS_SDRAM + SZ_4G), (void *)(PHYS_SDRAM), SZ_8G }, - { (void *)(PHYS_SDRAM + SZ_2G), (void *)(PHYS_SDRAM), SZ_4G }, - { (void *)(PHYS_SDRAM + SZ_1G), (void *)(PHYS_SDRAM), SZ_2G }, + { (void *)((uintptr_t)PHYS_SDRAM + SZ_8G), (void *)(PHYS_SDRAM), SZ_16G }, + { (void *)((uintptr_t)PHYS_SDRAM + SZ_4G), (void *)(PHYS_SDRAM), SZ_8G }, + { (void *)((uintptr_t)PHYS_SDRAM + SZ_2G), (void *)(PHYS_SDRAM), SZ_4G }, + { (void *)((uintptr_t)PHYS_SDRAM + SZ_1G), (void *)(PHYS_SDRAM), SZ_2G }, { NULL } }; From 8377214282d00989722e1ff0ea83e6234f99564d Mon Sep 17 00:00:00 2001 From: Frieder Schrempf Date: Thu, 4 Jun 2026 17:18:41 -0300 Subject: [PATCH 40/48] imx: kontron-sl-mx6ul: Enable CONFIG_DM_MDIO to fix boot abort The following failure occurs right before switching to the kernel: data abort pc : [<9ff60162>] lr : [<9ff79d13>] reloc pc : [<8781c162>] lr : [<87835d13>] sp : 9bf30f78 ip : 9bf4b140 fp : 007963a0 r10: fffffdfb r9 : 9bf3bed0 r8 : 00004600 r7 : 00000000 r6 : 9ffe5a0c r5 : 00004600 r4 : 9bf4acf0 r3 : f5f5f5f5 r2 : f5f5f5f5 r1 : 9ffe0c5c r0 : 9bf7c130 Flags: NzCv IRQs off FIQs off Mode SVC_32 (T) Code: 9ffe b158 e9d0 2300 (6053) 601a Resetting CPU ... This is due to the fact that the board uses a shared MDIO bus for both ethernet controllers, but FEC_MXC_SHARE_MDIO is not enabled. This results in a double free in fecmxc_remove(). To fix this enable CONFIG_DM_MDIO so the shared MDIO is correctly detected from the devicetree. Fixes: 048fdda977ab ("imx: kontron-sl-mx6ul: Enable second ethernet interface") Signed-off-by: Frieder Schrempf --- configs/kontron-sl-mx6ul_defconfig | 1 + 1 file changed, 1 insertion(+) diff --git a/configs/kontron-sl-mx6ul_defconfig b/configs/kontron-sl-mx6ul_defconfig index f800c3e4039..b1f5b13e404 100644 --- a/configs/kontron-sl-mx6ul_defconfig +++ b/configs/kontron-sl-mx6ul_defconfig @@ -92,6 +92,7 @@ CONFIG_DM_SPI_FLASH=y CONFIG_SPI_FLASH_MACRONIX=y CONFIG_SPI_FLASH_WINBOND=y CONFIG_SPI_FLASH_MTD=y +CONFIG_DM_MDIO=y CONFIG_DM_ETH_PHY=y CONFIG_FEC_MXC=y CONFIG_MII=y From cdb9e79056dcc94440202845a75a31e4e40cc3a2 Mon Sep 17 00:00:00 2001 From: Ye Li Date: Fri, 22 May 2026 21:51:42 +0800 Subject: [PATCH 41/48] cpu: imx8_cpu: Fix CPU segment information print Should not use CONFIG_IMX_TMU to determine the print of CPU market segment information. Only iMX8 platforms don't have segment fuse. And there is no extended commercial part on iMX9 (91/93/94/95), fix it to extended industrial. Signed-off-by: Ye Li --- drivers/cpu/imx8_cpu.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/drivers/cpu/imx8_cpu.c b/drivers/cpu/imx8_cpu.c index 785c299eca5..3473712a423 100644 --- a/drivers/cpu/imx8_cpu.c +++ b/drivers/cpu/imx8_cpu.c @@ -222,7 +222,7 @@ static int cpu_imx_get_desc(const struct udevice *dev, char *buf, int size) ret = snprintf(buf, size, "NXP i.MX%s Rev%s %s at %u MHz", plat->type, plat->rev, plat->name, plat->freq_mhz); - if (IS_ENABLED(CONFIG_IMX_TMU)) { + if (!IS_ENABLED(CONFIG_IMX8)) { /* imx8 does not have segment fuse */ switch (get_cpu_temp_grade(&minc, &maxc)) { case TEMP_AUTOMOTIVE: grade = "Automotive temperature grade"; @@ -231,7 +231,10 @@ static int cpu_imx_get_desc(const struct udevice *dev, char *buf, int size) grade = "Industrial temperature grade"; break; case TEMP_EXTCOMMERCIAL: - grade = "Extended Consumer temperature grade"; + if (IS_ENABLED(CONFIG_ARCH_IMX9)) + grade = "Extended Industrial temperature grade"; + else + grade = "Extended Consumer temperature grade"; break; default: grade = "Consumer temperature grade"; From 822a98588d16e5542b4e4d9d23c19a8ee7e93040 Mon Sep 17 00:00:00 2001 From: Marek Vasut Date: Sat, 30 May 2026 19:08:24 +0200 Subject: [PATCH 42/48] binman: imx8mimage: Handle nxp,boot-from = "fspi" Boot from FSPI requires additional 448 Byte long header, with U-Boot SPL starting at offset 0x1000. Currently, both i.MX8MM and i.MX8MN attempt to generate this header using fspi_conf_block with filename pointing at CONFIG_FSPI_CONF_FILE file. This does not work, for two reasons. First, the CONFIG_FSPI_CONF_FILE is generated by mkimage -T imx8mimage and may not be available yet when the fspi_conf_block is evaluated. That leads to a race condition where highly parallel builds fail to find the CONFIG_FSPI_CONF_FILE, which is usually called fspi_header.bin, on first build attempt. Second, binman gets confused and patches incorrect offset of DDR PHY firmware blobs into U-Boot SPL, the offset is incremented by exactly 0x1000 which is the size of fspi_conf_block. Fix both problems at once, make imx8mimage handle the generated FSPI header and prepend it in front of the imx8mimage processed data. This way, the race condition is solved, because the data generated by the imx8mimage are surely combined only after mkimage -T imx8mimage ran. The binman offset calculation is also solved, because there is no fspi_conf_block node in the DT anymore. Signed-off-by: Marek Vasut --- tools/binman/etype/nxp_imx8mimage.py | 14 +++++++++++++- tools/binman/ftest.py | 14 ++++++++++++++ tools/binman/test/vendor/nxp_imx8m_fspi.dts | 18 ++++++++++++++++++ .../binman/test/vendor/nxp_imx8m_fspi_fail.dts | 18 ++++++++++++++++++ .../binman/test/vendor/nxp_imx8m_fspi_pass.dts | 18 ++++++++++++++++++ 5 files changed, 81 insertions(+), 1 deletion(-) create mode 100644 tools/binman/test/vendor/nxp_imx8m_fspi.dts create mode 100644 tools/binman/test/vendor/nxp_imx8m_fspi_fail.dts create mode 100644 tools/binman/test/vendor/nxp_imx8m_fspi_pass.dts diff --git a/tools/binman/etype/nxp_imx8mimage.py b/tools/binman/etype/nxp_imx8mimage.py index 8ad177b3b65..25c43438a87 100644 --- a/tools/binman/etype/nxp_imx8mimage.py +++ b/tools/binman/etype/nxp_imx8mimage.py @@ -7,6 +7,8 @@ # configuration file and input data. # +import os + from collections import OrderedDict from binman.entry import Entry @@ -23,6 +25,8 @@ class Entry_nxp_imx8mimage(Entry_mkimage): - nxp,boot-from - device to boot from (e.g. 'sd') - nxp,loader-address - loader address (SPL text base) - nxp,rom-version - BootROM version ('2' for i.MX8M Nano and Plus) + - nxp,fspi-header-filename - FSPI header file name (CONFIG_FSPI_CONF_FILE). + Used only if 'nxp,boot-from == "fspi"' . """ def __init__(self, section, etype, node): @@ -33,6 +37,7 @@ class Entry_nxp_imx8mimage(Entry_mkimage): def ReadNode(self): super().ReadNode() self.boot_from = fdt_util.GetString(self._node, 'nxp,boot-from') + self.fspi_header = fdt_util.GetString(self._node, 'nxp,fspi-header-filename', 'fspi_header.bin') self.loader_address = fdt_util.GetInt(self._node, 'nxp,loader-address') self.rom_version = fdt_util.GetInt(self._node, 'nxp,rom-version') self.ReadEntries() @@ -52,7 +57,14 @@ class Entry_nxp_imx8mimage(Entry_mkimage): args = ['-d', input_fname, '-n', cfg_fname, '-T', 'imx8mimage', output_fname] if self.mkimage.run_cmd(*args) is not None: - return tools.read_file(output_fname) + outdata = tools.read_file(output_fname) + if self.boot_from == 'fspi': + spidata = tools.read_file(os.path.join(tools.get_output_dir(), self.fspi_header)) + if len(spidata) != 448: + raise ValueError("FSPI header is not 448 Bytes long") + spidata += tools.get_bytes(0, 0x1000 - len(spidata)) + outdata = spidata + outdata + return outdata else: # Bintool is missing; just use the input data as the output self.record_missing_bintool(self.mkimage) diff --git a/tools/binman/ftest.py b/tools/binman/ftest.py index 9a3811c1732..bf98b268ac1 100644 --- a/tools/binman/ftest.py +++ b/tools/binman/ftest.py @@ -8099,6 +8099,20 @@ fdt fdtmap Extract the devicetree blob from the fdtmap result = cst.fetch(bintool.FETCH_BUILD) self.assertEqual(('cst', None), result) + def testNxpImx8MFSPI(self): + """Test that binman can produce an iMX8m FSPI image""" + testdir = tempfile.mkdtemp(prefix='binman.') + + tools.write_file(os.path.join(testdir, 'fspi_header.bin'), tools.get_bytes(0, 448)) + with terminal.capture(): + self._DoTestFile('vendor/nxp_imx8m_fspi.dts', output_dir=testdir) + self._DoTestFile('vendor/nxp_imx8m_fspi_pass.dts', output_dir=testdir) + + tools.write_file(os.path.join(testdir, 'fspi_header_fail.bin'), tools.get_bytes(0, 4097)) + with terminal.capture(): + with self.assertRaises(ValueError) as e: + self._DoTestFile('vendor/nxp_imx8m_fspi_fail.dts', output_dir=testdir) + def testNxpHeaderDdrfw(self): """Test that binman can add a header to DDR PHY firmware images""" data = self._DoReadFile('vendor/nxp_ddrfw_imx95.dts') diff --git a/tools/binman/test/vendor/nxp_imx8m_fspi.dts b/tools/binman/test/vendor/nxp_imx8m_fspi.dts new file mode 100644 index 00000000000..ae6cc5981e6 --- /dev/null +++ b/tools/binman/test/vendor/nxp_imx8m_fspi.dts @@ -0,0 +1,18 @@ +// SPDX-License-Identifier: GPL-2.0+ + +/dts-v1/; + +/ { + #address-cells = <1>; + #size-cells = <1>; + + binman { + nxp-imx8mimage { + args; /* TODO: Needed by mkimage etype superclass */ + nxp,boot-from = "fspi"; + nxp,fspi-header-filename = "fspi_header.bin"; + nxp,rom-version = <1>; + nxp,loader-address = <0x10>; + }; + }; +}; diff --git a/tools/binman/test/vendor/nxp_imx8m_fspi_fail.dts b/tools/binman/test/vendor/nxp_imx8m_fspi_fail.dts new file mode 100644 index 00000000000..5a0d758e5a3 --- /dev/null +++ b/tools/binman/test/vendor/nxp_imx8m_fspi_fail.dts @@ -0,0 +1,18 @@ +// SPDX-License-Identifier: GPL-2.0+ + +/dts-v1/; + +/ { + #address-cells = <1>; + #size-cells = <1>; + + binman { + nxp-imx8mimage { + args; /* TODO: Needed by mkimage etype superclass */ + nxp,boot-from = "fspi"; + nxp,fspi-header-filename = "fspi_header_fail.bin"; + nxp,rom-version = <2>; + nxp,loader-address = <0x10>; + }; + }; +}; diff --git a/tools/binman/test/vendor/nxp_imx8m_fspi_pass.dts b/tools/binman/test/vendor/nxp_imx8m_fspi_pass.dts new file mode 100644 index 00000000000..448d93d277a --- /dev/null +++ b/tools/binman/test/vendor/nxp_imx8m_fspi_pass.dts @@ -0,0 +1,18 @@ +// SPDX-License-Identifier: GPL-2.0+ + +/dts-v1/; + +/ { + #address-cells = <1>; + #size-cells = <1>; + + binman { + nxp-imx8mimage { + args; /* TODO: Needed by mkimage etype superclass */ + nxp,boot-from = "fspi"; + /* Default nxp,fspi-header-filename = "fspi_header.bin"; */ + nxp,rom-version = <2>; + nxp,loader-address = <0x10>; + }; + }; +}; From c3680dcf9a7e0f90bfb0b91d6f640a09557b2320 Mon Sep 17 00:00:00 2001 From: Marek Vasut Date: Sat, 30 May 2026 19:08:25 +0200 Subject: [PATCH 43/48] arm64: dts: imx8mm: Generate FSPI header using binman imx8mimage The binman imx8mimage now correctly handles generated fspi_header.bin in its imx8mimage etype. Make use of this, remove fspi_conf_block in favor of generated fspi_header.bin, and configure imx8mimage accordingly. Signed-off-by: Marek Vasut --- arch/arm/dts/imx8mm-u-boot.dtsi | 13 +++++-------- 1 file changed, 5 insertions(+), 8 deletions(-) diff --git a/arch/arm/dts/imx8mm-u-boot.dtsi b/arch/arm/dts/imx8mm-u-boot.dtsi index d891e8062fe..ab135fc8a47 100644 --- a/arch/arm/dts/imx8mm-u-boot.dtsi +++ b/arch/arm/dts/imx8mm-u-boot.dtsi @@ -50,14 +50,6 @@ section { pad-byte = <0x00>; -#ifdef CONFIG_FSPI_CONF_HEADER - fspi_conf_block { - filename = CONFIG_FSPI_CONF_FILE; - type = "blob-ext"; - size = <0x1000>; - }; -#endif - #ifdef CONFIG_IMX_HAB nxp-imx8mcst@0 { filename = "u-boot-spl-mkimage.signed.bin"; @@ -68,7 +60,12 @@ binman_imx_spl: nxp-imx8mimage { filename = "u-boot-spl-mkimage.bin"; +#ifdef CONFIG_FSPI_CONF_HEADER + nxp,boot-from = "fspi"; + nxp,fspi-header-filename = CONFIG_FSPI_CONF_FILE; +#else nxp,boot-from = "sd"; +#endif nxp,rom-version = <1>; nxp,loader-address = ; args; /* Needed by mkimage etype superclass */ From b9fc16e72ddb1cfa3f01b484613343d77b97b1c0 Mon Sep 17 00:00:00 2001 From: Marek Vasut Date: Sat, 30 May 2026 19:08:26 +0200 Subject: [PATCH 44/48] arm64: dts: imx8mn: Generate FSPI header using binman imx8mimage The binman imx8mimage now correctly handles generated fspi_header.bin in its imx8mimage etype. Make use of this, remove fspi_conf_block in favor of generated fspi_header.bin, and configure imx8mimage accordingly. Signed-off-by: Marek Vasut --- arch/arm/dts/imx8mn-u-boot.dtsi | 13 +++++-------- 1 file changed, 5 insertions(+), 8 deletions(-) diff --git a/arch/arm/dts/imx8mn-u-boot.dtsi b/arch/arm/dts/imx8mn-u-boot.dtsi index 29eecd6d70d..8993605af3c 100644 --- a/arch/arm/dts/imx8mn-u-boot.dtsi +++ b/arch/arm/dts/imx8mn-u-boot.dtsi @@ -104,14 +104,6 @@ section { pad-byte = <0x00>; -#ifdef CONFIG_FSPI_CONF_HEADER - fspi_conf_block { - filename = CONFIG_FSPI_CONF_FILE; - type = "blob-ext"; - offset = <0x400>; - }; -#endif - #ifdef CONFIG_IMX_HAB nxp-imx8mcst@0 { filename = "u-boot-spl-mkimage.signed.bin"; @@ -122,7 +114,12 @@ binman_imx_spl: nxp-imx8mimage { filename = "u-boot-spl-mkimage.bin"; +#ifdef CONFIG_FSPI_CONF_HEADER + nxp,boot-from = "fspi"; + nxp,fspi-header-filename = CONFIG_FSPI_CONF_FILE; +#else nxp,boot-from = "sd"; +#endif nxp,rom-version = <2>; nxp,loader-address = ; args; /* Needed by mkimage etype superclass */ From 0fba623e4fd421bbea6e44156ea15a135d08576d Mon Sep 17 00:00:00 2001 From: Marek Vasut Date: Thu, 4 Jun 2026 00:32:12 +0200 Subject: [PATCH 45/48] tools: imx8image: Fix FSPI alignment to 4 kiB The SPI NOR minimum subsector size is 4 kiB, update the alignment. THis is particularly important in case of embedded DUMMY_DDR, which must be at at least 4 kiB aligned offset. Fixes: a2b96ece5be1 ("tools: add i.MX8/8X image support") Signed-off-by: Marek Vasut Reviewed-by: Peng Fan --- tools/imx8image.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/imx8image.c b/tools/imx8image.c index 84f46bcaf37..bb1b8667971 100644 --- a/tools/imx8image.c +++ b/tools/imx8image.c @@ -80,7 +80,7 @@ static table_entry_t imx8image_core_entries[] = { static table_entry_t imx8image_sector_size[] = { {0x400, "sd", "sd/emmc",}, {0x400, "emmc_fastboot", "emmc fastboot",}, - {0x400, "fspi", "flexspi", }, + {0x1000, "fspi", "flexspi", }, {0x1000, "nand_4k", "nand 4K", }, {0x2000, "nand_8k", "nand 8K", }, {0x4000, "nand_16k", "nand 16K", }, From 3dd149ba17cd34724bc535d6de290de6e74e177f Mon Sep 17 00:00:00 2001 From: Marek Vasut Date: Thu, 4 Jun 2026 19:33:15 +0200 Subject: [PATCH 46/48] lmb: Rename LMB_LIMIT_DMA_BELOW_4G to LMB_LIMIT_DMA_BELOW_RAM_TOP Rename LMB_LIMIT_DMA_BELOW_4G to LMB_LIMIT_DMA_BELOW_RAM_TOP to make the Kconfig option more descriptive. No functional change. Suggested-by: Ilias Apalodimas Signed-off-by: Marek Vasut Reviewed-by: Ilias Apalodimas --- lib/Kconfig | 7 ++++--- lib/lmb.c | 2 +- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/lib/Kconfig b/lib/Kconfig index 29911068a69..cf13ac1bdad 100644 --- a/lib/Kconfig +++ b/lib/Kconfig @@ -1295,13 +1295,14 @@ config SPL_LMB_ARCH_MEM_MAP memory map. Enable this config in such scenarios which allow architectures and boards to define their own memory map. -config LMB_LIMIT_DMA_BELOW_4G +config LMB_LIMIT_DMA_BELOW_RAM_TOP bool depends on LMB default y if ARCH_BCM283X help - Some architectures can not DMA above 4 GiB boundary, - limit available memory to memory below 4 GiB boundary. + Some architectures can not DMA above ram_top boundary, + which is after 4 GiB or 32-bit boundary too. Limit the + available memory to memory below ram_top boundary. config PHANDLE_CHECK_SEQ bool "Enable phandle check while getting sequence number" diff --git a/lib/lmb.c b/lib/lmb.c index a2aeb526e29..275d105c5aa 100644 --- a/lib/lmb.c +++ b/lib/lmb.c @@ -628,7 +628,7 @@ static void lmb_add_memory(void) if (size) { lmb_add(bd->bi_dram[i].start, size); - if (!IS_ENABLED(CONFIG_LMB_LIMIT_DMA_BELOW_4G)) + if (!IS_ENABLED(CONFIG_LMB_LIMIT_DMA_BELOW_RAM_TOP)) continue; bank_end = bd->bi_dram[i].start + size; From 6d7171bcfe2994a5fc42dd900bbaea732db1aeac Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Frank=20B=C3=B6wingloh?= Date: Fri, 5 Jun 2026 09:33:31 +0200 Subject: [PATCH 47/48] smbios: Fix wrong sysinfo ID for Type 3 enclosure asset tag MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit smbios_write_type3() uses SYSID_SM_BASEBOARD_ASSET_TAG (Type 2) instead of SYSID_SM_ENCLOSURE_ASSET_TAG (Type 3) for the enclosure asset tag. This causes the enclosure's asset tag to be read from the baseboard sysinfo field rather than the enclosure-specific one. Fixes: bcf456dd ("smbios: add detailed smbios information") Signed-off-by: Frank Böwingloh Cc: Raymond Mao Cc: Tom Rini Cc: Ilias Apalodimas Reviewed-by: Raymond Mao --- lib/smbios.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/smbios.c b/lib/smbios.c index 906d2753517..afde6401ae5 100644 --- a/lib/smbios.c +++ b/lib/smbios.c @@ -679,7 +679,7 @@ static int smbios_write_type3(ulong *current, int *handle, t->serial_number = smbios_add_prop_si(ctx, "serial", SYSID_SM_ENCLOSURE_SERIAL, NULL); t->asset_tag_number = smbios_add_prop_si(ctx, "asset-tag", - SYSID_SM_BASEBOARD_ASSET_TAG, + SYSID_SM_ENCLOSURE_ASSET_TAG, NULL); t->oem_defined = smbios_get_val_si(ctx, "oem-defined", SYSID_SM_ENCLOSURE_OEM, 0); From 1296a428c67cf103eca482d4a63349661c1b799f Mon Sep 17 00:00:00 2001 From: Tom Rini Date: Mon, 8 Jun 2026 13:43:04 -0600 Subject: [PATCH 48/48] Prepare v2026.07-rc4 Signed-off-by: Tom Rini --- Makefile | 2 +- doc/develop/release_cycle.rst | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Makefile b/Makefile index 4e18eb4cfba..4e5c1dd6a1c 100644 --- a/Makefile +++ b/Makefile @@ -3,7 +3,7 @@ VERSION = 2026 PATCHLEVEL = 07 SUBLEVEL = -EXTRAVERSION = -rc3 +EXTRAVERSION = -rc4 NAME = # *DOCUMENTATION* diff --git a/doc/develop/release_cycle.rst b/doc/develop/release_cycle.rst index b53eac45504..1e3e179d77f 100644 --- a/doc/develop/release_cycle.rst +++ b/doc/develop/release_cycle.rst @@ -77,7 +77,7 @@ For the next scheduled release, release candidates were made on: * U-Boot |next_ver|-rc3 was released on Mon 25 May 2026. -.. * U-Boot |next_ver|-rc4 was released on Mon 08 June 2026. +* U-Boot |next_ver|-rc4 was released on Mon 08 June 2026. .. * U-Boot |next_ver|-rc5 was released on Mon 22 June 2026.