* [PATCH RESEND v5 0/5] Add FIT multi-DTB selection for Qualcomm
@ 2026-10-12 17:07 Aswin Murugan
2026-10-12 17:07 ` [PATCH RESEND v5 1/5] misc: qcom: Add HW-Info aggregator driver Aswin Murugan
` (5 more replies)
0 siblings, 6 replies; 11+ messages in thread
From: Aswin Murugan @ 2026-10-12 17:07 UTC (permalink / raw)
To: trini, ilias.apalodimas, aswin.murugan, casey.connolly,
quic_varada, neil.armstrong, sumit.garg, u-boot,
balaji.selvanathan, Michael.Srba, nathbappai, jbx6244,
quentin.schulz, anshuld, marcello.bauer, tan.siewert, u-boot-qcom
This series adds dynamic device tree selection from FIT images for
Qualcomm Snapdragon platforms, enabling U-Boot to select the
appropriate DTB based on hardware parameters detected at boot.
Qualcomm FIT-based DTB format is documented in [1].
The FIT image contains only DTBs, while the kernel is provided
separately as part of a UKI image.
The implementation consists of:
1. Hardware detection infrastructure: Introduces the qcom,hwinfo
driver and qcom_hwdetect helper to collect hardware identification
data from SMEM, IMEM and TCSR into a single qcom_hw_params
structure for consumers such as FIT multi-DTB selection.
2. FIT multi-DTB selection: Implements DTB selection based on the
aggregated hardware information. The code parses metadata DTBs,
matches FIT configurations against detected hardware attributes,
applies overlays, and loads the selected DTB for EFI boot.
[1] https://github.com/qualcomm-linux/qcom-dtb-metadata/blob/main/
Documentation.md
---
Changes in v4:
1. Drop the SMEM cache infrastructure.
2. misc: qcom: add qcom,hwinfo driver to provide a common interface
for reading IMEM boot cookie and TCSR SOC version information.
3. arm: snapdragon: add qcom_hwdetect helper to aggregate hardware
information from SMEM, IMEM and TCSR into a single
struct qcom_hw_params.
4. Refactor FIT multi-DTB selection to consume qcom_hw_params instead
of accessing SMEM, IMEM and TCSR data directly.
5. Separate hardware discovery from FIT parsing and DTB matching
logic, reducing complexity and improving code organization.
6. Load FIT images directly from a raw GPT partition and remove the
FAT filesystem image based loading approach.
7. Drop IH_TYPE_FATFS, mkimage FAT image generation support and
related documentation updates.
8. arm: dts: enable qcom,hwinfo on qcs9100-ride-r3, qcs615-ride and
qcs6490-rb3gen2 by adding the required qcom,hwinfo DT nodes and
board-specific offsets.
Link to v3:
https://lore.kernel.org/u-boot/20260417120951.3454249-1-aswin.murugan@oss.qualcomm.com/
Changes in v3:
1. Runtime IMEM address lookup via DT: Removed CONFIG_QCOM_IMEM_SIZE Kconfig option.
Added qcom_imem_table[] mapping SoC compatible strings to IMEM addresses.
2. Split SoC version sources: SoC hardware version now read from TCSR register via
qcom_read_tcsr_soc_version(). The soc_info->plat_ver from SMEM is stored separately
as board_version. Added socver and boardrev metadata node matching for finer-grained DTB selection.
3. qcom_load_fit_image() returns int: Changed return type from efi_status_t to int,
returning standard Linux error codes for consistency with the rest of the driver.
4. Code cleanup: strtok() replaced with strsep(); memcpy + manual null-termination replaced with strlcpy();
DDR thresholds use SZ_* macros; compatible matching and FDT loading extracted into dedicated helpers.
5. image: add IH_TYPE_FATFS image type: Added new fatfs image type to represent a raw FAT
filesystem partition image, registered in the image type lookup table.
6. mkimage: add fatfs image type for FAT partition images: Added fatimage.c handler that
uses mkfs.vfat and mcopy to create FAT images from a directory.
New --fat-extra-space, --fat-type, --fat-volume-id, --fat-mkfs-opts long options added
to mkimage.
7. doc: document mkimage fatfs type and Qualcomm multi-DTB: Updated 'doc/mkimage.1' for the new
fatfs type and options. Added 'doc/board/qualcomm/multi_dtb.rst' covering FIT ITS configuration,
QCOM metadata format, socver/boardrev guidelines, and image creation steps.
Link to v2:
https://lore.kernel.org/u-boot/20260129184817.224101-1-aswin.murugan@oss.qualcomm.com/
Changes in v2:
1. In v1, a combined DTB format was used for multi-DTB support. Based on
feedback, v2 implements FIT-based DTB selection instead.
Link to v1: https://lore.kernel.org/all/20260106122134.2047864-1-aswin.murugan@oss.qualcomm.com/
Aswin Murugan via U-Boot (5):
misc: qcom: Add HW-Info aggregator driver
mach-snapdragon: Add hardware detection helper
mach-snapdragon: Add FIT multi-DTB selection support
configs: qcom_defconfig: Enable QCOM_FIT_MULTIDTB
arm: dts: Enable qcom, hwinfo on qcs9100-ride-r3, qcs615-ride and
qcs6490-rb3gen2
arch/arm/dts/qcs615-ride-u-boot.dtsi | 10 +
arch/arm/dts/qcs6490-rb3gen2-u-boot.dtsi | 10 +
arch/arm/dts/qcs9100-ride-r3-u-boot.dtsi | 10 +
arch/arm/mach-snapdragon/Kconfig | 17 +
arch/arm/mach-snapdragon/Makefile | 2 +
arch/arm/mach-snapdragon/board.c | 7 +
arch/arm/mach-snapdragon/qcom_fit_multidtb.c | 1033 ++++++++++++++++++
arch/arm/mach-snapdragon/qcom_fit_multidtb.h | 61 ++
arch/arm/mach-snapdragon/qcom_hwdetect.c | 167 +++
arch/arm/mach-snapdragon/qcom_hwdetect.h | 52 +
configs/qcom_defconfig | 2 +
drivers/misc/Kconfig | 9 +
drivers/misc/Makefile | 1 +
drivers/misc/qcom_hwinfo.c | 160 +++
include/qcom_hwinfo.h | 109 ++
15 files changed, 1650 insertions(+)
create mode 100644 arch/arm/mach-snapdragon/qcom_fit_multidtb.c
create mode 100644 arch/arm/mach-snapdragon/qcom_fit_multidtb.h
create mode 100644 arch/arm/mach-snapdragon/qcom_hwdetect.c
create mode 100644 arch/arm/mach-snapdragon/qcom_hwdetect.h
create mode 100644 drivers/misc/qcom_hwinfo.c
create mode 100644 include/qcom_hwinfo.h
--
2.34.1
^ permalink raw reply [flat|nested] 11+ messages in thread
* [PATCH RESEND v5 1/5] misc: qcom: Add HW-Info aggregator driver
2026-10-12 17:07 [PATCH RESEND v5 0/5] Add FIT multi-DTB selection for Qualcomm Aswin Murugan
@ 2026-10-12 17:07 ` Aswin Murugan
2026-10-12 17:07 ` [PATCH RESEND v5 2/5] mach-snapdragon: Add hardware detection helper Aswin Murugan
` (4 subsequent siblings)
5 siblings, 0 replies; 11+ messages in thread
From: Aswin Murugan @ 2026-10-12 17:07 UTC (permalink / raw)
To: trini, ilias.apalodimas, aswin.murugan, casey.connolly,
quic_varada, neil.armstrong, sumit.garg, u-boot,
balaji.selvanathan, Michael.Srba, nathbappai, jbx6244,
quentin.schulz, anshuld, marcello.bauer, tan.siewert, u-boot-qcom
From: Aswin Murugan via U-Boot <u-boot@lists.u-boot-project.org>
Add a generic driver that binds to a U-Boot-only "qcom,hwinfo" DT
node holding phandles to the existing IMEM/TCSR syscon nodes plus
per-SoC offsets. This provides a common interface for reading the
IMEM boot cookie (used to detect boot storage type) and the TCSR
SOC_HW_VERSION register.
Signed-off-by: Aswin Murugan <aswin.murugan@oss.qualcomm.com>
---
drivers/misc/Kconfig | 9 +++
drivers/misc/Makefile | 1 +
drivers/misc/qcom_hwinfo.c | 160 +++++++++++++++++++++++++++++++++++++
include/qcom_hwinfo.h | 109 +++++++++++++++++++++++++
4 files changed, 279 insertions(+)
create mode 100644 drivers/misc/qcom_hwinfo.c
create mode 100644 include/qcom_hwinfo.h
diff --git a/drivers/misc/Kconfig b/drivers/misc/Kconfig
index 5f22bcb330e..95eba94609b 100644
--- a/drivers/misc/Kconfig
+++ b/drivers/misc/Kconfig
@@ -102,6 +102,15 @@ config QCOM_GENI
for providing a common interface for various peripherals like UART, I2C, SPI,
etc.
+config QCOM_HWINFO
+ bool "Qualcomm HW-Info aggregator driver"
+ depends on MISC
+ select SYSCON
+ select REGMAP
+ help
+ Reads the IMEM boot cookie and TCSR HW version via a common
+ "qcom,hwinfo" DT node.
+
config ROCKCHIP_EFUSE
bool "Rockchip e-fuse support"
depends on MISC
diff --git a/drivers/misc/Makefile b/drivers/misc/Makefile
index 9ddbe9cd114..1d484f97bfb 100644
--- a/drivers/misc/Makefile
+++ b/drivers/misc/Makefile
@@ -67,6 +67,7 @@ obj-$(CONFIG_QFW_SMBIOS) += qfw_smbios.o
obj-$(CONFIG_SANDBOX) += qfw_sandbox.o
endif
obj-$(CONFIG_QCOM_GENI) += qcom_geni.o
+obj-$(CONFIG_$(PHASE_)QCOM_HWINFO) += qcom_hwinfo.o
obj-$(CONFIG_$(PHASE_)ROCKCHIP_EFUSE) += rockchip-efuse.o
obj-$(CONFIG_$(PHASE_)ROCKCHIP_OTP) += rockchip-otp.o
obj-$(CONFIG_$(PHASE_)ROCKCHIP_IODOMAIN) += rockchip-io-domain.o
diff --git a/drivers/misc/qcom_hwinfo.c b/drivers/misc/qcom_hwinfo.c
new file mode 100644
index 00000000000..822968234d5
--- /dev/null
+++ b/drivers/misc/qcom_hwinfo.c
@@ -0,0 +1,160 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Qualcomm HW-Info aggregator driver
+ *
+ * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries.
+ *
+ * Binds to a U-Boot-only DT node (compatible = "qcom,hwinfo") holding
+ * phandles to the existing IMEM/TCSR syscon nodes plus per-SoC offsets.
+ *
+ * Example DT node (arch/arm/dts/<board>-u-boot.dtsi):
+ *
+ * qcom_hwinfo: qcom-hwinfo {
+ * compatible = "qcom,hwinfo";
+ * imem = <&sram>;
+ * imem-boot-cookie-offset = <0x0>;
+ * tcsr = <&tcsr>;
+ * tcsr-hw-version-offset = <0x8000>;
+ * };
+ */
+
+#include <dm.h>
+#include <log.h>
+#include <regmap.h>
+#include <syscon.h>
+#include <dm/device_compat.h>
+#include <linux/err.h>
+#include <qcom_hwinfo.h>
+
+struct qcom_hwinfo_priv {
+ struct regmap *imem_regmap;
+ u32 imem_cookie_off;
+ struct regmap *tcsr_regmap;
+ u32 tcsr_hwver_off;
+};
+
+int qcom_hwinfo_get_imem_cookie(struct udevice *dev,
+ const struct qcom_hwinfo_imem_cookie **cookie)
+{
+ struct qcom_hwinfo_priv *priv = dev_get_priv(dev);
+ const struct qcom_hwinfo_imem_cookie *c;
+ void *base;
+
+ if (!priv->imem_regmap)
+ return -ENODEV;
+
+ /* IMEM is plain mapped SRAM; safe to dereference directly. */
+ base = regmap_get_range(priv->imem_regmap, 0);
+ if (!base) {
+ dev_err(dev, "Failed to get IMEM regmap range\n");
+ return -ENODEV;
+ }
+
+ c = (const struct qcom_hwinfo_imem_cookie *)((u8 *)base + priv->imem_cookie_off);
+
+ if (c->shared_imem_magic != QCOM_HWINFO_IMEM_MAGIC_NUM ||
+ c->shared_imem_version < QCOM_HWINFO_IMEM_VERSION_NUM) {
+ dev_warn(dev, "Invalid IMEM cookie magic=0x%x version=%u\n",
+ c->shared_imem_magic, c->shared_imem_version);
+ return -EINVAL;
+ }
+
+ *cookie = c;
+
+ return 0;
+}
+
+int qcom_hwinfo_get_storage_type(struct udevice *dev, u32 *storage_type)
+{
+ const struct qcom_hwinfo_imem_cookie *cookie;
+ int ret;
+
+ ret = qcom_hwinfo_get_imem_cookie(dev, &cookie);
+ if (ret) {
+ dev_warn(dev, "Failed to get IMEM cookie: %d, defaulting to UFS\n", ret);
+ *storage_type = QCOM_HWINFO_STORAGE_UFS;
+ return 0;
+ }
+
+ switch (cookie->boot_device_type) {
+ case QCOM_HWINFO_UFS_FLASH:
+ *storage_type = QCOM_HWINFO_STORAGE_UFS;
+ break;
+ case QCOM_HWINFO_MMC_FLASH:
+ case QCOM_HWINFO_SDC_FLASH:
+ *storage_type = QCOM_HWINFO_STORAGE_EMMC;
+ break;
+ case QCOM_HWINFO_NAND_FLASH:
+ *storage_type = QCOM_HWINFO_STORAGE_NAND;
+ break;
+ default:
+ dev_warn(dev, "Unknown boot device type: %u, defaulting to UFS\n",
+ cookie->boot_device_type);
+ *storage_type = QCOM_HWINFO_STORAGE_UFS;
+ break;
+ }
+
+ return 0;
+}
+
+int qcom_hwinfo_get_tcsr_hw_version(struct udevice *dev, u32 *hw_version)
+{
+ struct qcom_hwinfo_priv *priv = dev_get_priv(dev);
+ int ret;
+
+ if (!priv->tcsr_regmap)
+ return -ENODEV;
+
+ ret = regmap_read(priv->tcsr_regmap, priv->tcsr_hwver_off, hw_version);
+ if (ret) {
+ dev_err(dev, "Failed to read TCSR HW version: %d\n", ret);
+ return ret;
+ }
+
+ return 0;
+}
+
+static int qcom_hwinfo_of_to_plat(struct udevice *dev)
+{
+ struct qcom_hwinfo_priv *priv = dev_get_priv(dev);
+
+ priv->imem_regmap = syscon_regmap_lookup_by_phandle(dev, "imem");
+ if (IS_ERR(priv->imem_regmap)) {
+ dev_warn(dev, "Unable to find 'imem' regmap (%ld)\n",
+ PTR_ERR(priv->imem_regmap));
+ priv->imem_regmap = NULL;
+ } else {
+ priv->imem_cookie_off =
+ dev_read_u32_default(dev, "imem-boot-cookie-offset", 0);
+ }
+
+ priv->tcsr_regmap = syscon_regmap_lookup_by_phandle(dev, "tcsr");
+ if (IS_ERR(priv->tcsr_regmap)) {
+ dev_warn(dev, "Unable to find 'tcsr' regmap (%ld)\n",
+ PTR_ERR(priv->tcsr_regmap));
+ priv->tcsr_regmap = NULL;
+ } else {
+ priv->tcsr_hwver_off =
+ dev_read_u32_default(dev, "tcsr-hw-version-offset", 0);
+ }
+
+ if (!priv->imem_regmap && !priv->tcsr_regmap) {
+ dev_err(dev, "Neither 'imem' nor 'tcsr' regmap found\n");
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static const struct udevice_id qcom_hwinfo_ids[] = {
+ { .compatible = "qcom,hwinfo" },
+ { }
+};
+
+U_BOOT_DRIVER(qcom_hwinfo) = {
+ .name = "qcom_hwinfo",
+ .id = UCLASS_MISC,
+ .of_match = qcom_hwinfo_ids,
+ .of_to_plat = qcom_hwinfo_of_to_plat,
+ .priv_auto = sizeof(struct qcom_hwinfo_priv),
+};
diff --git a/include/qcom_hwinfo.h b/include/qcom_hwinfo.h
new file mode 100644
index 00000000000..994a7d0bb20
--- /dev/null
+++ b/include/qcom_hwinfo.h
@@ -0,0 +1,109 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+/*
+ * Qualcomm HW-Info aggregator driver
+ *
+ * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries.
+ *
+ * Reads boot-time hardware info (IMEM boot cookie, TCSR HW version) via
+ * syscon regions, using offsets from the "qcom,hwinfo" DT node.
+ */
+
+#ifndef __QCOM_HWINFO_H__
+#define __QCOM_HWINFO_H__
+
+#include <linux/types.h>
+
+struct udevice;
+
+/*
+ * Storage type values. Match enum mem_card_type in
+ * arch/arm/mach-snapdragon/qcom_fit_multidtb.h.
+ */
+enum qcom_hwinfo_storage_type {
+ QCOM_HWINFO_STORAGE_EMMC = 0,
+ QCOM_HWINFO_STORAGE_UFS = 1,
+ QCOM_HWINFO_STORAGE_NAND = 2,
+ QCOM_HWINFO_STORAGE_SDCARD = 3,
+ QCOM_HWINFO_STORAGE_UNKNOWN,
+};
+
+/* Boot shared IMEM cookie constants */
+#define QCOM_HWINFO_IMEM_MAGIC_NUM 0xc1f8db40
+#define QCOM_HWINFO_IMEM_VERSION_NUM 0x3
+
+/* Boot device types from shared IMEM */
+enum qcom_hwinfo_boot_media_type {
+ QCOM_HWINFO_NO_FLASH = 0,
+ QCOM_HWINFO_NOR_FLASH = 1,
+ QCOM_HWINFO_NAND_FLASH = 2,
+ QCOM_HWINFO_ONENAND_FLASH = 3,
+ QCOM_HWINFO_SDC_FLASH = 4,
+ QCOM_HWINFO_MMC_FLASH = 5,
+ QCOM_HWINFO_SPI_FLASH = 6,
+ QCOM_HWINFO_PCIE_FLASHLESS = 7,
+ QCOM_HWINFO_UFS_FLASH = 8,
+ QCOM_HWINFO_RESERVED_0_FLASH = 9,
+ QCOM_HWINFO_RESERVED_1_FLASH = 10,
+ QCOM_HWINFO_USB_FLASHLESS = 11,
+};
+
+/*
+ * Boot shared IMEM cookie layout, populated by the bootloader.
+ * Do NOT mark __packed - breaks natural alignment expected by firmware.
+ */
+struct qcom_hwinfo_imem_cookie {
+ u32 shared_imem_magic;
+ u32 shared_imem_version;
+ u64 etb_buf_addr;
+ u64 l2_cache_dump_buff_addr;
+ u32 a64_pointer_padding;
+ u32 uefi_ram_dump_magic;
+ u32 ddr_training_cookie;
+ u32 abnormal_reset_occurred;
+ u32 reset_status_register;
+ u32 rpm_sync_cookie;
+ u32 debug_config;
+ u64 boot_log_addr;
+ u32 boot_log_size;
+ u32 boot_fail_count;
+ u32 sbl1_error_type;
+ u32 uefi_image_magic;
+ u32 boot_device_type;
+ u64 boot_devtree_addr;
+ u64 boot_devtree_size;
+};
+
+/**
+ * qcom_hwinfo_get_imem_cookie() - Get a read-only pointer to the IMEM cookie
+ * @dev: qcom_hwinfo device
+ * @cookie: Returns a const pointer into the live IMEM region
+ *
+ * Validates magic/version before returning. On failure, @cookie is unset.
+ *
+ * Return: 0 on success, -ENODEV if imem regmap unavailable, -EINVAL on
+ * magic/version mismatch
+ */
+int qcom_hwinfo_get_imem_cookie(struct udevice *dev,
+ const struct qcom_hwinfo_imem_cookie **cookie);
+
+/**
+ * qcom_hwinfo_get_storage_type() - Detect boot storage type from IMEM cookie
+ * @dev: qcom_hwinfo device
+ * @storage_type: Returns detected storage type
+ *
+ * Wraps qcom_hwinfo_get_imem_cookie(); defaults to UFS on failure.
+ *
+ * Return: 0 always
+ */
+int qcom_hwinfo_get_storage_type(struct udevice *dev, u32 *storage_type);
+
+/**
+ * qcom_hwinfo_get_tcsr_hw_version() - Read the TCSR SOC_HW_VERSION register
+ * @dev: qcom_hwinfo device
+ * @hw_version: Returns the raw register value
+ *
+ * Return: 0 on success, negative error code on failure
+ */
+int qcom_hwinfo_get_tcsr_hw_version(struct udevice *dev, u32 *hw_version);
+
+#endif /* __QCOM_HWINFO_H__ */
--
2.34.1
^ permalink raw reply related [flat|nested] 11+ messages in thread
* [PATCH RESEND v5 2/5] mach-snapdragon: Add hardware detection helper
2026-10-12 17:07 [PATCH RESEND v5 0/5] Add FIT multi-DTB selection for Qualcomm Aswin Murugan
2026-10-12 17:07 ` [PATCH RESEND v5 1/5] misc: qcom: Add HW-Info aggregator driver Aswin Murugan
@ 2026-10-12 17:07 ` Aswin Murugan
2026-10-12 17:07 ` [PATCH RESEND v5 3/5] mach-snapdragon: Add FIT multi-DTB selection support Aswin Murugan
` (3 subsequent siblings)
5 siblings, 0 replies; 11+ messages in thread
From: Aswin Murugan @ 2026-10-12 17:07 UTC (permalink / raw)
To: trini, ilias.apalodimas, aswin.murugan, casey.connolly,
quic_varada, neil.armstrong, sumit.garg, u-boot,
balaji.selvanathan, Michael.Srba, nathbappai, jbx6244,
quentin.schulz, anshuld, marcello.bauer, tan.siewert, u-boot-qcom
From: Aswin Murugan via U-Boot <u-boot@lists.u-boot-project.org>
Add qcom_hwdetect, a helper that aggregates hardware parameters
(chip ID, chip version, board version, platform, subtype, OEM
variant, foundry ID, DDR size type, storage type) from SMEM, TCSR,
and IMEM into a single struct qcom_hw_params. This is intended for
consumption by FIT multi-DTB selection and other subsystems that
need a unified view of hardware identification data.
Depends on the qcom,hwinfo driver for IMEM/TCSR register access.
Signed-off-by: Aswin Murugan <aswin.murugan@oss.qualcomm.com>
---
arch/arm/mach-snapdragon/Kconfig | 8 ++
arch/arm/mach-snapdragon/Makefile | 1 +
arch/arm/mach-snapdragon/qcom_hwdetect.c | 167 +++++++++++++++++++++++
arch/arm/mach-snapdragon/qcom_hwdetect.h | 52 +++++++
4 files changed, 228 insertions(+)
create mode 100644 arch/arm/mach-snapdragon/qcom_hwdetect.c
create mode 100644 arch/arm/mach-snapdragon/qcom_hwdetect.h
diff --git a/arch/arm/mach-snapdragon/Kconfig b/arch/arm/mach-snapdragon/Kconfig
index ddded0029ef..5911e76dc1e 100644
--- a/arch/arm/mach-snapdragon/Kconfig
+++ b/arch/arm/mach-snapdragon/Kconfig
@@ -59,6 +59,14 @@ config QCOM_GENERATE_MBN
New platforms can be added to tools/qcom/mkmbn/mkmbn.py if they aren't already
supported.
+config QCOM_HWDETECT
+ bool "Qualcomm Hardware Detection"
+ depends on QCOM_SMEM
+ select QCOM_HWINFO
+ help
+ Hardware parameter detection from SMEM and TCSR for
+ DTB selection and other platform subsystems.
+
choice
prompt "Qualcomm boot0.h workaround"
optional
diff --git a/arch/arm/mach-snapdragon/Makefile b/arch/arm/mach-snapdragon/Makefile
index 2360b7c658e..6132847d7f4 100644
--- a/arch/arm/mach-snapdragon/Makefile
+++ b/arch/arm/mach-snapdragon/Makefile
@@ -10,6 +10,7 @@ obj-y += board_spl.o
else
obj-y += board.o
obj-$(CONFIG_EFI_HAVE_CAPSULE_SUPPORT) += capsule_update.o
+obj-$(CONFIG_QCOM_HWDETECT) += qcom_hwdetect.o
endif
obj-$(CONFIG_OF_LIVE) += of_fixup.o
diff --git a/arch/arm/mach-snapdragon/qcom_hwdetect.c b/arch/arm/mach-snapdragon/qcom_hwdetect.c
new file mode 100644
index 00000000000..a3a3a26556d
--- /dev/null
+++ b/arch/arm/mach-snapdragon/qcom_hwdetect.c
@@ -0,0 +1,167 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Qualcomm Hardware Detection
+ *
+ * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries.
+ *
+ * Detects hardware parameters from SMEM, TCSR registers, and IMEM
+ * for use by DTB selection and other subsystems.
+ */
+
+#include <dm.h>
+#include <log.h>
+#include <qcom_hwinfo.h>
+#include <asm/global_data.h>
+#include <dm/uclass.h>
+#include <linux/errno.h>
+#include <linux/sizes.h>
+#include <soc/qcom/smem.h>
+#include <soc/qcom/socinfo.h>
+
+#include "qcom_hwdetect.h"
+
+DECLARE_GLOBAL_DATA_PTR;
+
+/* TCSR SOC HW Version register field masks */
+#define TCSR_MAJOR_VERSION_MASK 0x0000ff00
+#define TCSR_MAJOR_VERSION_SHIFT 8
+#define TCSR_MINOR_VERSION_MASK 0x000000ff
+#define TCSR_MINOR_VERSION_SHIFT 0
+
+/* DDR type enum */
+enum ddr_type {
+ DDRTYPE_256MB = 1,
+ DDRTYPE_512MB,
+ DDRTYPE_1024MB,
+ DDRTYPE_2048MB,
+ DDRTYPE_3072MB,
+ DDRTYPE_4096MB,
+ DDRTYPE_128MB,
+};
+
+/**
+ * qcom_get_hwinfo_dev() - Look up the qcom,hwinfo device
+ * @devp: Returns the qcom_hwinfo udevice
+ *
+ * Return: 0 on success, negative error code on failure
+ */
+static int qcom_get_hwinfo_dev(struct udevice **devp)
+{
+ int ret;
+
+ ret = uclass_get_device_by_driver(UCLASS_MISC, DM_DRIVER_GET(qcom_hwinfo),
+ devp);
+ if (ret)
+ log_warning("qcom,hwinfo device not found/probed: %d\n", ret);
+
+ return ret;
+}
+
+/**
+ * qcom_get_ddr_size_type() - Get DDR size type from gd->ram_size
+ * @ddr_type: Pointer to store DDR type
+ *
+ * Uses gd->ram_size which is calculated by dram.c from SMEM/FDT
+ * during early boot. Avoids redundant SMEM re-parsing.
+ *
+ * Return: 0 on success
+ */
+static int qcom_get_ddr_size_type(u32 *ddr_type)
+{
+ u64 total_ddr_size = gd->ram_size;
+
+ log_debug("Total DDR Size: 0x%llx (%llu MB)\n",
+ total_ddr_size, total_ddr_size / SZ_1M);
+
+ *ddr_type = 0;
+ if (total_ddr_size <= SZ_128M)
+ *ddr_type = DDRTYPE_128MB;
+ else if (total_ddr_size <= SZ_256M)
+ *ddr_type = DDRTYPE_256MB;
+ else if (total_ddr_size <= SZ_512M)
+ *ddr_type = DDRTYPE_512MB;
+ else if (total_ddr_size <= SZ_1G)
+ *ddr_type = DDRTYPE_1024MB;
+ else if (total_ddr_size <= SZ_2G)
+ *ddr_type = DDRTYPE_2048MB;
+ else if (total_ddr_size <= (SZ_2G + SZ_1G))
+ *ddr_type = DDRTYPE_3072MB;
+ else if (total_ddr_size <= SZ_4G)
+ *ddr_type = DDRTYPE_4096MB;
+
+ log_debug("DDR Type: %u\n", *ddr_type);
+
+ return 0;
+}
+
+int qcom_hwdetect_get_params(struct qcom_hw_params *params)
+{
+ struct udevice *hwinfo;
+ struct socinfo *soc_info;
+ size_t size;
+ int ret;
+ u32 raw_version, reg_val, major, minor;
+
+ if (!params)
+ return -EINVAL;
+
+ memset(params, 0, sizeof(*params));
+
+ ret = qcom_get_hwinfo_dev(&hwinfo);
+ if (ret) {
+ log_err("qcom,hwinfo device not available\n");
+ return ret;
+ }
+
+ soc_info = qcom_smem_get(QCOM_SMEM_HOST_ANY, SMEM_HW_SW_BUILD_ID, &size);
+ if (IS_ERR_OR_NULL(soc_info)) {
+ log_err("Failed to get SOC info from SMEM\n");
+ return -ENODEV;
+ }
+
+ params->chip_id = le32_to_cpu(soc_info->id) & 0xffff;
+
+ raw_version = le32_to_cpu(soc_info->plat_ver);
+ params->board_version = (SOCINFO_MAJOR(raw_version) << 4) | SOCINFO_MINOR(raw_version);
+
+ ret = qcom_hwinfo_get_tcsr_hw_version(hwinfo, ®_val);
+ if (ret) {
+ log_err("Failed to read TCSR HW version via qcom,hwinfo: %d\n", ret);
+ return ret;
+ }
+ major = (reg_val & TCSR_MAJOR_VERSION_MASK) >> TCSR_MAJOR_VERSION_SHIFT;
+ minor = (reg_val & TCSR_MINOR_VERSION_MASK) >> TCSR_MINOR_VERSION_SHIFT;
+ params->chip_version = (major << 4) | minor;
+
+ params->platform = le32_to_cpu(soc_info->hw_plat);
+ params->subtype = le32_to_cpu(soc_info->hw_plat_subtype);
+
+ if (le32_to_cpu(soc_info->fmt) >= 17)
+ params->oem_variant_id = le32_to_cpu(soc_info->oem_variant);
+
+ if (le32_to_cpu(soc_info->fmt) >= 9)
+ params->foundry_id = le32_to_cpu(soc_info->foundry_id);
+
+ ret = qcom_get_ddr_size_type(¶ms->ddr_size_type);
+ if (ret)
+ log_warning("Failed to get DDR size, defaulting to 0\n");
+
+ ret = qcom_hwinfo_get_storage_type(hwinfo, ¶ms->storage_type);
+ if (ret) {
+ log_warning("Failed to detect storage type via qcom,hwinfo, defaulting to UFS\n");
+ params->storage_type = QCOM_HWINFO_STORAGE_UFS;
+ }
+
+ log_debug("Hardware Parameters:\n");
+ log_debug(" Chip ID: 0x%x\n", params->chip_id);
+ log_debug(" Chip Version: 0x%x\n", params->chip_version);
+ log_debug(" Board Version: 0x%x\n", params->board_version);
+ log_debug(" Platform: 0x%x\n", params->platform);
+ log_debug(" Subtype: 0x%x\n", params->subtype);
+ log_debug(" OEM Variant ID: 0x%x\n", params->oem_variant_id);
+ log_debug(" DDR Size Type: %u\n", params->ddr_size_type);
+ log_debug(" Storage Type: %u\n", params->storage_type);
+ log_debug(" Foundry ID: 0x%x\n", params->foundry_id);
+
+ return 0;
+}
diff --git a/arch/arm/mach-snapdragon/qcom_hwdetect.h b/arch/arm/mach-snapdragon/qcom_hwdetect.h
new file mode 100644
index 00000000000..cb75f565756
--- /dev/null
+++ b/arch/arm/mach-snapdragon/qcom_hwdetect.h
@@ -0,0 +1,52 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+/*
+ * Qualcomm Hardware Detection
+ *
+ * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries.
+ */
+
+#ifndef __QCOM_HWDETECT_H__
+#define __QCOM_HWDETECT_H__
+
+#include <linux/types.h>
+
+/**
+ * struct qcom_hw_params - Hardware parameters
+ * @chip_id: SoC chip ID
+ * @chip_version: SoC version from TCSR
+ * @platform: Hardware platform ID
+ * @board_version: Board version
+ * @subtype: Hardware platform subtype
+ * @oem_variant_id: OEM variant ID
+ * @foundry_id: Foundry ID
+ * @softsku_id: Software SKU ID
+ * @ddr_size_type: DDR size type (0-7)
+ * @storage_type: Storage type (UFS/EMMC/NAND)
+ *
+ * Contains all hardware parameters detected from SMEM, TCSR, and IMEM.
+ */
+struct qcom_hw_params {
+ u32 chip_id;
+ u32 chip_version;
+ u32 platform;
+ u32 board_version;
+ u32 subtype;
+ u32 oem_variant_id;
+ u32 foundry_id;
+ u32 softsku_id;
+ u32 ddr_size_type;
+ u32 storage_type;
+};
+
+/**
+ * qcom_hwdetect_get_params() - Get hardware parameters
+ * @params: Pointer to store hardware parameters
+ *
+ * Detects all hardware parameters from SMEM, TCSR, and IMEM.
+ * Returns a complete structure ready for use by any subsystem.
+ *
+ * Return: 0 on success, negative error code on failure
+ */
+int qcom_hwdetect_get_params(struct qcom_hw_params *params);
+
+#endif /* __QCOM_HWDETECT_H__ */
--
2.34.1
^ permalink raw reply related [flat|nested] 11+ messages in thread
* [PATCH RESEND v5 3/5] mach-snapdragon: Add FIT multi-DTB selection support
2026-10-12 17:07 [PATCH RESEND v5 0/5] Add FIT multi-DTB selection for Qualcomm Aswin Murugan
2026-10-12 17:07 ` [PATCH RESEND v5 1/5] misc: qcom: Add HW-Info aggregator driver Aswin Murugan
2026-10-12 17:07 ` [PATCH RESEND v5 2/5] mach-snapdragon: Add hardware detection helper Aswin Murugan
@ 2026-10-12 17:07 ` Aswin Murugan
2026-10-12 17:07 ` [PATCH RESEND v5 4/5] configs: qcom_defconfig: Enable QCOM_FIT_MULTIDTB Aswin Murugan
` (2 subsequent siblings)
5 siblings, 0 replies; 11+ messages in thread
From: Aswin Murugan @ 2026-10-12 17:07 UTC (permalink / raw)
To: trini, ilias.apalodimas, aswin.murugan, casey.connolly,
quic_varada, neil.armstrong, sumit.garg, u-boot,
balaji.selvanathan, Michael.Srba, nathbappai, jbx6244,
quentin.schulz, anshuld, marcello.bauer, tan.siewert, u-boot-qcom
From: Aswin Murugan via U-Boot <u-boot@lists.u-boot-project.org>
Add support for automatically selecting the correct DTB from a FIT
image based on hardware parameters detected at runtime via SMEM,
TCSR, and IMEM.
The FIT image (qclinux_fit.img) is loaded from the "dtb_a" raw GPT
partition. A metadata DTB embedded as the first FIT image is parsed
to build a "bucket list" of matching identifiers based on detected
hardware (OEM, SoC, SoC version, board, board revision, peripheral
subtype, storage type, DDR size, soft SKU). FIT configurations are
then scored against this bucket list via their "compatible" string,
and the best-matching configuration's DTB (plus any listed overlays)
is loaded, overlaid, and installed via the "fdt_addr" environment
variable for the EFI boot flow to consume.
This is gated behind CONFIG_QCOM_FIT_MULTIDTB and is a no-op unless
both the config is enabled and hardware detection succeeds, so it is
safe to enable without affecting boards that don't need it.
Signed-off-by: Aswin Murugan <aswin.murugan@oss.qualcomm.com>
---
arch/arm/mach-snapdragon/Kconfig | 9 +
arch/arm/mach-snapdragon/Makefile | 1 +
arch/arm/mach-snapdragon/board.c | 7 +
arch/arm/mach-snapdragon/qcom_fit_multidtb.c | 1033 ++++++++++++++++++
arch/arm/mach-snapdragon/qcom_fit_multidtb.h | 61 ++
5 files changed, 1111 insertions(+)
create mode 100644 arch/arm/mach-snapdragon/qcom_fit_multidtb.c
create mode 100644 arch/arm/mach-snapdragon/qcom_fit_multidtb.h
diff --git a/arch/arm/mach-snapdragon/Kconfig b/arch/arm/mach-snapdragon/Kconfig
index 5911e76dc1e..98b6655385e 100644
--- a/arch/arm/mach-snapdragon/Kconfig
+++ b/arch/arm/mach-snapdragon/Kconfig
@@ -49,6 +49,15 @@ config SYS_CONFIG_NAME
Based on this option include/configs/<CONFIG_SYS_CONFIG_NAME>.h header
will be used for board configuration.
+config QCOM_FIT_MULTIDTB
+ bool "Enable FIT multi-DTB selection for Qualcomm platforms"
+ depends on FIT
+ select QCOM_HWDETECT
+ help
+ Enable FIT multi-DTB selection for Qualcomm platforms.
+ This allows U-Boot to select the appropriate device tree
+ from a FIT image.
+
config QCOM_GENERATE_MBN
bool "Generate an MBN-compatible ELF binary"
help
diff --git a/arch/arm/mach-snapdragon/Makefile b/arch/arm/mach-snapdragon/Makefile
index 6132847d7f4..74ccdd9bd53 100644
--- a/arch/arm/mach-snapdragon/Makefile
+++ b/arch/arm/mach-snapdragon/Makefile
@@ -10,6 +10,7 @@ obj-y += board_spl.o
else
obj-y += board.o
obj-$(CONFIG_EFI_HAVE_CAPSULE_SUPPORT) += capsule_update.o
+obj-$(CONFIG_QCOM_FIT_MULTIDTB) += qcom_fit_multidtb.o
obj-$(CONFIG_QCOM_HWDETECT) += qcom_hwdetect.o
endif
diff --git a/arch/arm/mach-snapdragon/board.c b/arch/arm/mach-snapdragon/board.c
index 87adb100edd..9bfb7183241 100644
--- a/arch/arm/mach-snapdragon/board.c
+++ b/arch/arm/mach-snapdragon/board.c
@@ -26,6 +26,7 @@
#include <time.h>
#include "qcom-priv.h"
+#include "qcom_fit_multidtb.h"
enum qcom_boot_source qcom_boot_source __section(".data") = 0;
enum qcom_memmap_source qcom_memmap_source __section(".data") = 0;
@@ -452,5 +453,11 @@ int board_late_init(void)
/* Configure the dfu_string for capsule updates */
qcom_configure_capsule_updates();
+ /* Try FIT multi-DTB selection if enabled */
+ if (IS_ENABLED(CONFIG_QCOM_FIT_MULTIDTB)) {
+ if (qcom_fit_multidtb_setup())
+ log_debug("FIT multi-DTB selection not available or failed\n");
+ }
+
return 0;
}
diff --git a/arch/arm/mach-snapdragon/qcom_fit_multidtb.c b/arch/arm/mach-snapdragon/qcom_fit_multidtb.c
new file mode 100644
index 00000000000..45423910d34
--- /dev/null
+++ b/arch/arm/mach-snapdragon/qcom_fit_multidtb.c
@@ -0,0 +1,1033 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Qualcomm FIT Multi-DTB Selection
+ *
+ * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries.
+ *
+ * Automatic DTB selection from FIT images based on hardware detection via SMEM.
+ * Loads qclinux_fit.img from dtb partition, detects hardware parameters,
+ * and selects the best matching DTB configuration.
+ */
+
+#include <blk.h>
+#include <dm.h>
+#include <env.h>
+#include <image.h>
+#include <lmb.h>
+#include <log.h>
+#include <malloc.h>
+#include <part.h>
+#include <linux/errno.h>
+#include <linux/kernel.h>
+#include <linux/libfdt.h>
+#include <linux/list.h>
+#include <linux/sizes.h>
+#include <linux/string.h>
+
+#include "qcom_fit_multidtb.h"
+#include "qcom_hwdetect.h"
+
+/* GPT partition name containing the FIT image */
+#define QCOM_FIT_PARTNAME "dtb_a"
+
+#define lmb_alloc(size, addr) \
+ lmb_alloc_mem(LMB_MEM_ALLOC_ANY, SZ_2M, addr, size, LMB_NONE)
+
+/* Maximum values to match (SOC needs 2) */
+#define MAX_MATCH_VALUES 2
+
+/* Metadata DTB node names */
+#define META_NODE_OEM "oem"
+#define META_NODE_SOC "soc"
+#define META_NODE_SOCVER "socver"
+#define META_NODE_BOARD "board"
+#define META_NODE_BOARDREV "boardrev"
+#define META_NODE_SOC_SKU "soc-sku"
+#define META_NODE_BOARD_SUBTYPE_PERIPHERAL "board-subtype-peripheral-subtype"
+#define META_NODE_BOARD_SUBTYPE_STORAGE "board-subtype-storage-type"
+#define META_NODE_BOARD_SUBTYPE_DDR_SIZE "board-subtype-memory-size"
+#define META_NODE_SOFTSKU "softsku"
+
+/* Property names */
+#define PROP_OEM_ID "oem-id"
+#define PROP_MSM_ID "msm-id"
+#define PROP_SOCVER_ID "socver-id"
+#define PROP_BOARD_ID "board-id"
+#define PROP_BOARDREV_ID "boardrev-id"
+#define PROP_BOARD_SUBTYPE "board-subtype"
+#define PROP_SOFTSKU_ID "softsku-id"
+#define PROP_COMPATIBLE "compatible"
+#define PROP_FDT "fdt"
+#define PROP_DATA "data"
+
+/**
+ * struct overlay_entry - Gathered overlay FDT image info
+ * @name: Overlay image name in the FIT
+ * @data: Pointer to overlay FDT data within the FIT
+ * @size: Size of the overlay FDT data
+ */
+struct overlay_entry {
+ const char *name;
+ const void *data;
+ size_t size;
+};
+
+/**
+ * add_to_bucket() - Add a node name to the bucket list
+ * @name: Node name to add
+ * @name_len: Length of the name
+ * @bucket_head: Head of the bucket list
+ *
+ * Return: 0 on success, negative error code on failure
+ */
+static int add_to_bucket(const char *name, int name_len, struct list_head *bucket_head)
+{
+ struct bucket_node *node;
+
+ node = malloc(sizeof(*node));
+ if (!node)
+ return -ENOMEM;
+
+ node->name = malloc(name_len + 1);
+ if (!node->name) {
+ free(node);
+ return -ENOMEM;
+ }
+
+ strlcpy(node->name, name, name_len + 1);
+
+ list_add_tail(&node->list, bucket_head);
+
+ return 0;
+}
+
+/**
+ * search_in_bucket() - Check if a name exists in the bucket list
+ * @name: Name to search for
+ * @bucket_head: Head of the bucket list
+ *
+ * Return: true if found, false otherwise
+ */
+static bool search_in_bucket(const char *name, struct list_head *bucket_head)
+{
+ struct bucket_node *node;
+
+ list_for_each_entry(node, bucket_head, list) {
+ if (!strcmp(node->name, name))
+ return true;
+ }
+
+ return false;
+}
+
+/**
+ * free_bucket_list() - Free all nodes in the bucket list
+ * @bucket_head: Head of the bucket list
+ */
+static void free_bucket_list(struct list_head *bucket_head)
+{
+ struct bucket_node *node, *tmp;
+
+ list_for_each_entry_safe(node, tmp, bucket_head, list) {
+ list_del(&node->list);
+ free(node->name);
+ free(node);
+ }
+}
+
+/**
+ * log_match_values() - Log matched hardware parameter values
+ * @log_type: Type label for logging (e.g., "SOC", "Board")
+ * @subnode_name: Name of the matched node
+ * @num_match_values: Number of values to log
+ * @match_values: Array of matched values
+ */
+static void log_match_values(const char *log_type, const char *subnode_name,
+ int num_match_values, const u32 *match_values)
+{
+ int i;
+
+ log_info("Matched %s: %s (", log_type, subnode_name);
+
+ for (i = 0; i < num_match_values; i++) {
+ if (i > 0)
+ log_info(", ");
+ log_info("val%d=0x%x", i + 1, match_values[i]);
+ }
+
+ log_info(")\n");
+}
+
+/**
+ * process_node() - Generic metadata node processor
+ * @type: Type of node to process
+ * @metadata: Metadata DTB pointer
+ * @root_offset: Root node offset
+ * @params: Hardware parameters
+ * @bucket_head: Bucket list head
+ *
+ * Processes different types of nodes in the metadata DTB. Handles matching
+ * hardware parameters against DTB properties, with support for bit masking/shifting
+ * and fallback values.
+ *
+ * Return: 0 on success, -ENOENT if no match, other negative on error
+ */
+static int process_node(enum node_process_type type,
+ void *metadata,
+ int root_offset,
+ struct qcom_hw_params *params,
+ struct list_head *bucket_head)
+{
+ const char *node_name, *prop_name, *log_type;
+ const char *fallback;
+ const char *subnode_name;
+ int node_offset, subnode, len, name_len;
+ int num_match_values, i;
+ u32 match_values[MAX_MATCH_VALUES];
+ u32 masks[MAX_MATCH_VALUES];
+ int shifts[MAX_MATCH_VALUES];
+ bool all_match;
+
+ fallback = NULL;
+ num_match_values = 1;
+ memset(shifts, 0, sizeof(shifts));
+ memset(masks, 0xff, sizeof(masks));
+
+ switch (type) {
+ case NODE_TYPE_OEM:
+ node_name = META_NODE_OEM;
+ prop_name = PROP_OEM_ID;
+ match_values[0] = params->oem_variant_id;
+ log_type = "OEM";
+ fallback = "qcom";
+ break;
+ case NODE_TYPE_SOC:
+ node_name = META_NODE_SOC;
+ prop_name = PROP_MSM_ID;
+ match_values[0] = params->chip_id;
+ masks[0] = 0xffff;
+ num_match_values = 1;
+ log_type = "SOC";
+ break;
+ case NODE_TYPE_SOCVER:
+ node_name = META_NODE_SOCVER;
+ prop_name = PROP_SOCVER_ID;
+ match_values[0] = params->chip_version;
+ num_match_values = 1;
+ log_type = "SOCVER";
+ break;
+ case NODE_TYPE_BOARD:
+ node_name = META_NODE_BOARD;
+ prop_name = PROP_BOARD_ID;
+ match_values[0] = params->platform;
+ log_type = "Board";
+ break;
+ case NODE_TYPE_BOARDREV:
+ node_name = META_NODE_BOARDREV;
+ prop_name = PROP_BOARDREV_ID;
+ match_values[0] = params->board_version;
+ num_match_values = 1;
+ log_type = "BoardRev";
+ break;
+ case NODE_TYPE_PERIPHERAL:
+ node_name = META_NODE_BOARD_SUBTYPE_PERIPHERAL;
+ prop_name = PROP_BOARD_SUBTYPE;
+ match_values[0] = params->subtype;
+ log_type = "Peripheral Subtype";
+ break;
+ case NODE_TYPE_STORAGE:
+ node_name = META_NODE_BOARD_SUBTYPE_STORAGE;
+ prop_name = PROP_BOARD_SUBTYPE;
+ match_values[0] = params->storage_type;
+ masks[0] = 0xc000;
+ shifts[0] = 14;
+ log_type = "Storage";
+ break;
+ case NODE_TYPE_DDR_SIZE:
+ node_name = META_NODE_BOARD_SUBTYPE_DDR_SIZE;
+ prop_name = PROP_BOARD_SUBTYPE;
+ match_values[0] = params->ddr_size_type;
+ masks[0] = 0x1f00;
+ shifts[0] = 8;
+ log_type = "DDR Size";
+ break;
+ case NODE_TYPE_SOFTSKU:
+ node_name = META_NODE_SOFTSKU;
+ prop_name = PROP_SOFTSKU_ID;
+ match_values[0] = params->softsku_id;
+ log_type = "SoftSKU";
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ node_offset = fdt_subnode_offset(metadata, root_offset, node_name);
+ if (node_offset < 0) {
+ log_debug("%s node not found\n", log_type);
+ return node_offset;
+ }
+
+ fdt_for_each_subnode(subnode, metadata, node_offset) {
+ const u32 *prop = fdt_getprop(metadata, subnode, prop_name, &len);
+
+ if (!prop || len < (int)(num_match_values * sizeof(u32)))
+ continue;
+
+ all_match = true;
+ for (i = 0; i < num_match_values; i++) {
+ u32 dtb_value = fdt32_to_cpu(prop[i]);
+
+ dtb_value = (dtb_value & masks[i]) >> shifts[i];
+
+ if (dtb_value != match_values[i]) {
+ all_match = false;
+ break;
+ }
+ }
+
+ if (!all_match)
+ continue;
+
+ subnode_name = fdt_get_name(metadata, subnode, &name_len);
+ if (subnode_name) {
+ log_match_values(log_type, subnode_name, num_match_values,
+ match_values);
+ return add_to_bucket(subnode_name, name_len, bucket_head);
+ }
+ }
+
+ if (fallback) {
+ log_info("No %s match, using fallback '%s'\n", log_type, fallback);
+ return add_to_bucket(fallback, strlen(fallback), bucket_head);
+ }
+
+ log_debug("No %s match\n", log_type);
+
+ return -ENOENT;
+}
+
+/**
+ * qcom_add_dtbo_tokens() - Split a comma-separated token string into the bucket list
+ * @str: Comma-separated overlay token string
+ * @bucket_head: Bucket list head
+ *
+ * Splits @str on commas, trims surrounding whitespace from each token, skips
+ * empty tokens, and adds each remaining token to the bucket list.
+ *
+ * Return: 0 on success, negative error code on failure
+ */
+static int qcom_add_dtbo_tokens(const char *str, struct list_head *bucket_head)
+{
+ char *str_copy;
+ char *str_ptr;
+ char *token;
+ int ret = 0;
+
+ str_copy = strdup(str);
+ if (!str_copy)
+ return -ENOMEM;
+
+ str_ptr = str_copy;
+ while ((token = strsep(&str_ptr, ","))) {
+ while (*token == ' ' || *token == '\t')
+ token++;
+
+ if (!*token)
+ continue;
+
+ log_info("Adding vendor DTBO token: %s\n", token);
+ ret = add_to_bucket(token, strlen(token), bucket_head);
+ if (ret) {
+ log_err("Failed to add token '%s': %d\n", token, ret);
+ break;
+ }
+ }
+
+ free(str_copy);
+ return ret;
+}
+
+/**
+ * qcom_parse_vendor_dtbo() - Parse vendor_dtbo environment variable
+ * @bucket_head: Bucket list to add overlay tokens to
+ *
+ * Reads the "vendor_dtbo" environment variable and parses its comma-separated
+ * overlay identifiers, adding them to the bucket list for FIT configuration
+ * matching. This influences which FIT configuration is selected.
+ *
+ * Return: 0 on success, negative error code on failure or if unset
+ */
+static int qcom_parse_vendor_dtbo(struct list_head *bucket_head)
+{
+ const char *vendor_dtbo;
+
+ vendor_dtbo = env_get("vendor_dtbo");
+ if (!vendor_dtbo || !*vendor_dtbo)
+ return -ENOENT;
+
+ log_info("vendor_dtbo: %s\n", vendor_dtbo);
+
+ return qcom_add_dtbo_tokens(vendor_dtbo, bucket_head);
+}
+
+/**
+ * qcom_build_bucket_list() - Build bucket list from metadata DTB
+ * @metadata: Metadata DTB pointer
+ * @params: Hardware parameters
+ * @bucket_head: Bucket list head
+ *
+ * This function parses the metadata DTB and builds a list of matching
+ * node names based on the detected hardware parameters.
+ *
+ * Return: 0 on success, negative error code on failure
+ */
+static int qcom_build_bucket_list(void *metadata,
+ struct qcom_hw_params *params,
+ struct list_head *bucket_head)
+{
+ int root_offset;
+ int ret;
+ struct bucket_node *node;
+
+ log_debug("Building bucket list from hardware parameters\n");
+
+ root_offset = fdt_path_offset(metadata, "/");
+ if (root_offset < 0) {
+ log_err("Failed to find root node in metadata DTB\n");
+ return root_offset;
+ }
+
+ ret = process_node(NODE_TYPE_OEM, metadata, root_offset,
+ params, bucket_head);
+ if (ret < 0 && ret != -ENOENT)
+ return ret;
+
+ ret = process_node(NODE_TYPE_SOC, metadata, root_offset,
+ params, bucket_head);
+ if (ret < 0 && ret != -ENOENT)
+ return ret;
+
+ ret = process_node(NODE_TYPE_SOCVER, metadata, root_offset,
+ params, bucket_head);
+ if (ret < 0 && ret != -ENOENT)
+ return ret;
+
+ ret = process_node(NODE_TYPE_BOARD, metadata, root_offset,
+ params, bucket_head);
+ if (ret < 0 && ret != -ENOENT)
+ return ret;
+
+ ret = process_node(NODE_TYPE_BOARDREV, metadata, root_offset,
+ params, bucket_head);
+ if (ret < 0 && ret != -ENOENT)
+ return ret;
+
+ process_node(NODE_TYPE_PERIPHERAL, metadata, root_offset,
+ params, bucket_head);
+
+ process_node(NODE_TYPE_STORAGE, metadata, root_offset,
+ params, bucket_head);
+
+ process_node(NODE_TYPE_DDR_SIZE, metadata, root_offset,
+ params, bucket_head);
+
+ process_node(NODE_TYPE_SOFTSKU, metadata, root_offset,
+ params, bucket_head);
+
+ ret = qcom_parse_vendor_dtbo(bucket_head);
+ if (ret)
+ log_debug("vendor_dtbo not applied: %d\n", ret);
+
+ log_debug("Bucket list: ");
+ list_for_each_entry(node, bucket_head, list)
+ log_debug("%s ", node->name);
+ log_debug("\n");
+
+ return 0;
+}
+
+/**
+ * qcom_fit_calc_size() - Compute the true total size of a FIT image
+ * @fit: Pointer to a buffer containing at least the FIT's FDT structure
+ * @buf_size: Size of the buffer pointed to by @fit
+ *
+ * External-data FITs store image payloads after the FDT structure via
+ * "data-offset"/"data-size" properties, so fdt_totalsize() alone misses
+ * them. Walk /images to find the true end of the file.
+ *
+ * Return: total FIT size in bytes, or 0 on error
+ */
+static size_t qcom_fit_calc_size(const void *fit, size_t buf_size)
+{
+ int images_node, node;
+ size_t aligned_size, max_end, end;
+ int offset, size;
+
+ if (buf_size < sizeof(struct fdt_header) || fdt_check_header(fit)) {
+ log_err("Invalid FDT header while probing FIT size\n");
+ return 0;
+ }
+
+ aligned_size = (fdt_totalsize(fit) + 3) & ~3;
+ max_end = 0;
+
+ images_node = fdt_path_offset(fit, FIT_IMAGES_PATH);
+ if (images_node < 0)
+ return aligned_size;
+
+ fdt_for_each_subnode(node, fit, images_node) {
+ if (fit_image_get_data_offset(fit, node, &offset))
+ continue;
+ if (fit_image_get_data_size(fit, node, &size))
+ continue;
+ if (offset < 0 || size < 0)
+ continue;
+
+ end = (size_t)offset + (size_t)size;
+ if (end > max_end)
+ max_end = end;
+ }
+
+ return max_end ? aligned_size + max_end : aligned_size;
+}
+
+/**
+ * qcom_load_raw_partition() - Load FIT image from a raw partition by name
+ * @partname: GPT partition name to search for
+ * @fitp: Pointer to store FIT image address
+ * @fit_sizep: Pointer to store FIT image size
+ *
+ * Probes the FDT structure first to size the real FIT, instead of
+ * malloc()'ing the whole (possibly oversized) partition. The caller is
+ * responsible for validating the content (fdt_check_header, fit_check_format).
+ *
+ * Return: 0 on success, negative error code on failure
+ */
+static int qcom_load_raw_partition(const char *partname, void **fitp,
+ size_t *fit_sizep)
+{
+ struct udevice *blk_dev;
+ struct blk_desc *desc = NULL;
+ struct disk_partition part_info;
+ void *probe_buf;
+ void *part_buf;
+ size_t probe_size, probe_blocks, fit_size;
+ lbaint_t fit_blocks;
+
+ blk_foreach_probe(BLKF_BOTH, blk_dev) {
+ desc = dev_get_uclass_plat(blk_dev);
+ if (!desc)
+ continue;
+ if (part_get_info_by_name(desc, partname, &part_info) >= 0)
+ break;
+ desc = NULL;
+ }
+
+ if (!desc) {
+ log_err("Partition '%s' not found on any block device\n", partname);
+ return -ENOENT;
+ }
+
+ probe_blocks = min_t(size_t, DIV_ROUND_UP(SZ_8K, part_info.blksz),
+ part_info.size);
+ probe_size = probe_blocks * part_info.blksz;
+
+ probe_buf = malloc(probe_size);
+ if (!probe_buf)
+ return -ENOMEM;
+
+ if (blk_dread(desc, part_info.start, probe_blocks, probe_buf) != probe_blocks) {
+ log_err("Failed to probe-read partition '%s'\n", partname);
+ free(probe_buf);
+ return -EIO;
+ }
+
+ fit_size = qcom_fit_calc_size(probe_buf, probe_size);
+ free(probe_buf);
+
+ if (!fit_size) {
+ log_err("Failed to determine FIT size for partition '%s'\n", partname);
+ return -EINVAL;
+ }
+
+ if (fit_size > (size_t)(part_info.size * part_info.blksz))
+ fit_size = (size_t)(part_info.size * part_info.blksz);
+
+ fit_blocks = DIV_ROUND_UP(fit_size, part_info.blksz);
+ fit_size = (size_t)fit_blocks * part_info.blksz;
+
+ part_buf = malloc(fit_size);
+ if (!part_buf)
+ return -ENOMEM;
+
+ if (blk_dread(desc, part_info.start, fit_blocks, part_buf) != fit_blocks) {
+ log_err("Failed to read partition '%s'\n", partname);
+ free(part_buf);
+ return -EIO;
+ }
+
+ *fitp = part_buf;
+ *fit_sizep = fit_size;
+
+ log_info("Loaded raw partition '%s': %zu bytes\n", partname, fit_size);
+ return 0;
+}
+
+/**
+ * qcom_extract_metadata_dtb() - Extract metadata DTB from FIT image
+ * @fit: FIT image pointer
+ * @metadata: Pointer to store metadata DTB address
+ * @metadata_size: Pointer to store metadata DTB size
+ *
+ * The metadata DTB is the first image in the FIT (fdt-0).
+ *
+ * Return: 0 on success, negative error code on failure
+ */
+static int qcom_extract_metadata_dtb(void *fit, void **metadata,
+ size_t *metadata_size)
+{
+ int images_node, first_image;
+ const void *data;
+ size_t size;
+ int ret;
+
+ images_node = fdt_path_offset(fit, FIT_IMAGES_PATH);
+ if (images_node < 0) {
+ log_err("Cannot find /images node in FIT\n");
+ return images_node;
+ }
+
+ first_image = fdt_first_subnode(fit, images_node);
+ if (first_image < 0) {
+ log_err("Cannot find first image in FIT\n");
+ return first_image;
+ }
+
+ ret = fit_image_get_data(fit, first_image, &data, &size);
+ if (ret) {
+ log_err("Failed to get metadata DTB data\n");
+ return ret;
+ }
+
+ *metadata = malloc(size);
+ if (!*metadata) {
+ log_err("Failed to allocate memory for metadata DTB\n");
+ return -ENOMEM;
+ }
+
+ memcpy(*metadata, data, size);
+ *metadata_size = size;
+
+ log_info("Extracted metadata DTB: %zu bytes\n", size);
+
+ return 0;
+}
+
+/**
+ * qcom_count_compatible_matches() - Count matching tokens in compatible string
+ * @compatible: Compatible string from FIT configuration
+ * @compat_len: Length of compatible string
+ * @bucket_head: Bucket list head
+ *
+ * Parses the compatible string and counts how many tokens match entries
+ * in the bucket list. The compatible string format is typically:
+ * "vendor,device-variant-subtype" where tokens are separated by commas and dashes.
+ *
+ * Return: Number of matching tokens
+ */
+static int qcom_count_compatible_matches(const char *compatible, int compat_len,
+ struct list_head *bucket_head,
+ bool *full_match)
+{
+ char *compat_copy;
+ char *str_ptr;
+ char *token;
+ int match_count = 0;
+
+ *full_match = true;
+
+ compat_copy = malloc(compat_len + 1);
+ if (!compat_copy) {
+ *full_match = false;
+ return 0;
+ }
+
+ memcpy(compat_copy, compatible, compat_len);
+ compat_copy[compat_len] = '\0';
+
+ str_ptr = compat_copy;
+
+ strsep(&str_ptr, ",");
+
+ token = strsep(&str_ptr, "-");
+ while (token) {
+ match_count++;
+ if (!search_in_bucket(token, bucket_head)) {
+ *full_match = false;
+ break;
+ }
+ token = strsep(&str_ptr, "-");
+ }
+
+ free(compat_copy);
+ return match_count;
+}
+
+/**
+ * qcom_find_matching_config() - Find matching FIT configuration
+ * @fit: FIT image pointer
+ * @bucket_head: Bucket list head
+ * @config_node: Pointer to store matching configuration node offset
+ *
+ * This function iterates through all FIT configurations and finds the one
+ * with the most matching tokens in its compatible string against the bucket list.
+ *
+ * Return: 0 on success, negative error code on failure
+ */
+static int qcom_find_matching_config(void *fit, struct list_head *bucket_head,
+ int *config_node)
+{
+ int configs_node, cfg;
+ const char *compatible;
+ int compat_len;
+ const char *cfg_name;
+ int name_len;
+ int best_match_count = 0;
+ int best_config = -1;
+ int match_count;
+ bool full_match;
+
+ configs_node = fdt_path_offset(fit, FIT_CONFS_PATH);
+ if (configs_node < 0) {
+ log_err("Cannot find /configurations node in FIT\n");
+ return configs_node;
+ }
+
+ fdt_for_each_subnode(cfg, fit, configs_node) {
+ cfg_name = fdt_get_name(fit, cfg, &name_len);
+ compatible = fdt_getprop(fit, cfg, PROP_COMPATIBLE, &compat_len);
+
+ if (!compatible || compat_len <= 0) {
+ log_debug("Config %s has no compatible property\n", cfg_name);
+ continue;
+ }
+
+ log_debug("Checking config: %s, compatible: %s\n",
+ cfg_name, compatible);
+
+ match_count = qcom_count_compatible_matches(compatible, compat_len,
+ bucket_head, &full_match);
+
+ log_debug("Config %s: %d tokens, full_match=%d\n", cfg_name,
+ match_count, full_match);
+
+ if (!full_match)
+ continue;
+
+ if (match_count > best_match_count) {
+ best_match_count = match_count;
+ best_config = cfg;
+ }
+ }
+
+ if (best_config < 0) {
+ log_err("No matching configuration found\n");
+ return -ENOENT;
+ }
+
+ cfg_name = fdt_get_name(fit, best_config, &name_len);
+ compatible = fdt_getprop(fit, best_config, PROP_COMPATIBLE, &compat_len);
+ log_info("Selected configuration: %s (compatible: %s, matches: %d)\n",
+ cfg_name, compatible, best_match_count);
+
+ *config_node = best_config;
+ return 0;
+}
+
+/**
+ * qcom_get_fdt_image_data() - Get FDT image data from FIT
+ * @fit: FIT image pointer
+ * @images_node: Images node offset
+ * @fdt_name: FDT image name to load
+ * @fdt_datap: Pointer to store FDT data address
+ * @fdt_sizep: Pointer to store FDT data size
+ *
+ * Helper function to load an FDT image from the FIT by name.
+ *
+ * Return: 0 on success, negative error code on failure
+ */
+static int qcom_get_fdt_image_data(void *fit, int images_node,
+ const char *fdt_name,
+ const void **fdt_datap, size_t *fdt_sizep)
+{
+ int fdt_node;
+ int ret;
+
+ fdt_node = fdt_subnode_offset(fit, images_node, fdt_name);
+ if (fdt_node < 0) {
+ log_err("Cannot find FDT node: %s\n", fdt_name);
+ return fdt_node;
+ }
+
+ ret = fit_image_get_data(fit, fdt_node, fdt_datap, fdt_sizep);
+ if (ret) {
+ log_err("Failed to get FDT data for %s\n", fdt_name);
+ return ret;
+ }
+
+ return 0;
+}
+
+/**
+ * qcom_load_dtb_with_overlays() - Load DTB and apply overlays
+ * @fit: FIT image pointer
+ * @config_node: Configuration node offset
+ * @final_dtb: Pointer to store final DTB address
+ * @final_dtb_size: Pointer to store final DTB size
+ *
+ * This function loads the base DTB and applies all DTBOs specified in the
+ * configuration's "fdt" property.
+ *
+ * Return: 0 on success, negative error code on failure
+ */
+static int qcom_load_dtb_with_overlays(void *fit, int config_node,
+ void **final_dtb,
+ size_t *final_dtb_size)
+{
+ int images_node;
+ const char *fdt_name;
+ int fdt_name_len;
+ const void *fdt_data;
+ size_t fdt_size;
+ void *base_dtb = NULL;
+ size_t base_dtb_size = 0;
+ phys_addr_t dtb_addr;
+ int i, ret;
+ int fixups_offset;
+ struct overlay_entry *overlays = NULL;
+ int overlay_count = 0;
+ size_t overlays_size = 0;
+
+ images_node = fdt_path_offset(fit, FIT_IMAGES_PATH);
+ if (images_node < 0)
+ return images_node;
+
+ fdt_name = fdt_stringlist_get(fit, config_node, PROP_FDT, 0, &fdt_name_len);
+ if (!fdt_name) {
+ log_err("No fdt property in configuration\n");
+ return -EINVAL;
+ }
+
+ log_info("DTB: %s\n", fdt_name);
+
+ ret = qcom_get_fdt_image_data(fit, images_node, fdt_name,
+ &fdt_data, &fdt_size);
+ if (ret)
+ return ret;
+
+ /* Gather overlay entries once: name, data pointer, and size */
+ for (i = 1; ; i++) {
+ const char *ov_name;
+ const void *ov_data;
+ size_t ov_size;
+ int ov_name_len;
+ struct overlay_entry *tmp;
+
+ ov_name = fdt_stringlist_get(fit, config_node, PROP_FDT, i, &ov_name_len);
+ if (!ov_name)
+ break;
+
+ if (qcom_get_fdt_image_data(fit, images_node, ov_name, &ov_data, &ov_size))
+ continue;
+
+ tmp = realloc(overlays, (overlay_count + 1) * sizeof(*overlays));
+ if (!tmp) {
+ ret = -ENOMEM;
+ goto free_overlays;
+ }
+ overlays = tmp;
+ overlays[overlay_count].name = ov_name;
+ overlays[overlay_count].data = ov_data;
+ overlays[overlay_count].size = ov_size;
+ overlay_count++;
+ overlays_size += ov_size;
+ }
+
+ /* Allocate base DTB with extra space for overlays using LMB */
+ base_dtb_size = fdt_size + overlays_size + (2 * 1024);
+ ret = lmb_alloc(base_dtb_size, &dtb_addr);
+ if (ret) {
+ log_err("Failed to allocate LMB memory for base DTB: %zu bytes\n", base_dtb_size);
+ ret = -ENOMEM;
+ goto free_overlays;
+ }
+ base_dtb = (void *)dtb_addr;
+
+ memcpy(base_dtb, fdt_data, fdt_size);
+ ret = fdt_open_into(base_dtb, base_dtb, base_dtb_size);
+ if (ret) {
+ log_err("Failed to open DTB: %d\n", ret);
+ goto free_overlays;
+ }
+
+ /* Apply overlays using the already-gathered entries */
+ for (i = 0; i < overlay_count; i++) {
+ log_info("Applying overlay: %s (%zu bytes)\n",
+ overlays[i].name, overlays[i].size);
+
+ fixups_offset = fdt_path_offset(overlays[i].data, "/__fixups__");
+ if (fixups_offset == -FDT_ERR_NOTFOUND) {
+ log_warning("%s is not a valid overlay (no __fixups__)\n",
+ overlays[i].name);
+ continue;
+ }
+
+ ret = fdt_overlay_apply_verbose(base_dtb, (void *)overlays[i].data);
+ if (ret)
+ log_err("Failed to apply overlay %s: %d\n", overlays[i].name, ret);
+ }
+
+ ret = fdt_pack(base_dtb);
+ if (ret) {
+ log_err("Failed to pack DTB: %d\n", ret);
+ goto free_overlays;
+ }
+
+ *final_dtb = base_dtb;
+ *final_dtb_size = fdt_totalsize(base_dtb);
+
+ log_info("Final DTB size: %zu bytes\n", *final_dtb_size);
+
+ ret = 0;
+
+free_overlays:
+ free(overlays);
+ return ret;
+}
+
+/**
+ * qcom_fit_multidtb_setup() - Main entry point for FIT multi-DTB selection
+ *
+ * This is the main function that orchestrates the entire DTB selection process:
+ * 1. Load qclinux_fit.img from EFI partition
+ * 2. Extract metadata DTB
+ * 3. Detect hardware parameters from SMEM
+ * 4. Build bucket list from metadata
+ * 5. Find matching FIT configuration
+ * 6. Load DTB and apply overlays
+ * 7. Install FDT for EFI
+ *
+ * Return: 0 on success, negative error code on failure
+ */
+int qcom_fit_multidtb_setup(void)
+{
+ void *fit = NULL;
+ size_t fit_size = 0;
+ void *metadata = NULL;
+ size_t metadata_size = 0;
+ struct qcom_hw_params hw_params;
+ LIST_HEAD(bucket_list);
+ int config_node;
+ void *final_dtb = NULL;
+ size_t final_dtb_size = 0;
+ int ret;
+
+ log_debug("=== FIT Multi-DTB Selection ===\n");
+
+ log_debug("Loading FIT image\n");
+ ret = qcom_load_raw_partition(QCOM_FIT_PARTNAME, &fit, &fit_size);
+ if (ret) {
+ log_err("Failed to load FIT image\n");
+ goto cleanup_fit;
+ }
+
+ ret = fdt_check_header(fit);
+ if (ret) {
+ log_err("Invalid FIT header\n");
+ ret = -EINVAL;
+ goto cleanup_fit;
+ }
+
+ ret = fit_check_format(fit, IMAGE_SIZE_INVAL);
+ if (ret) {
+ log_err("Invalid FIT format\n");
+ ret = -EINVAL;
+ goto cleanup_fit;
+ }
+
+ log_debug("Extracting metadata DTB\n");
+ ret = qcom_extract_metadata_dtb(fit, &metadata, &metadata_size);
+ if (ret) {
+ log_err("Failed to extract metadata DTB\n");
+ goto cleanup_metadata;
+ }
+
+ log_debug("Detecting hardware parameters\n");
+ ret = qcom_hwdetect_get_params(&hw_params);
+ if (ret) {
+ log_err("Failed to detect hardware parameters\n");
+ goto cleanup_metadata;
+ }
+
+ log_debug("Building bucket list\n");
+ ret = qcom_build_bucket_list(metadata, &hw_params, &bucket_list);
+ if (ret) {
+ log_err("Failed to build bucket list\n");
+ goto cleanup_bucket;
+ }
+
+ log_debug("Finding matching configuration\n");
+ ret = qcom_find_matching_config(fit, &bucket_list, &config_node);
+ if (ret) {
+ log_err("Failed to find matching configuration\n");
+ goto cleanup_bucket;
+ }
+
+ log_debug("Loading DTB and applying overlays\n");
+ ret = qcom_load_dtb_with_overlays(fit, config_node, &final_dtb,
+ &final_dtb_size);
+ if (ret) {
+ log_err("Failed to load DTB with overlays\n");
+ goto cleanup_dtb;
+ }
+
+ log_debug("Setting fdt_addr to selected DTB address\n");
+
+ ret = fdt_check_header(final_dtb);
+ if (ret) {
+ log_err("Invalid final DTB header: %d\n", ret);
+ ret = -EINVAL;
+ goto cleanup_dtb;
+ }
+
+ /* Update fdt_addr environment variable to point to our DTB */
+ env_set_hex("fdt_addr", (ulong)final_dtb);
+ log_info("Updated fdt_addr=0x%lx, DTB size=%zu bytes\n", (ulong)final_dtb, final_dtb_size);
+ log_info("EFI boot flow will use DTB directly from this address\n");
+
+ /* Don't free final_dtb - LMB manages memory and EFI boot flow will use it */
+ final_dtb = NULL;
+
+ log_debug("=== FIT Multi-DTB Selection Complete ===\n");
+
+ ret = 0;
+ goto cleanup_success;
+
+cleanup_dtb:
+ if (ret && final_dtb)
+ final_dtb = NULL;
+
+cleanup_success:
+cleanup_bucket:
+ free_bucket_list(&bucket_list);
+
+cleanup_metadata:
+ if (metadata)
+ free(metadata);
+
+cleanup_fit:
+ if (fit)
+ free(fit);
+
+ return ret;
+}
diff --git a/arch/arm/mach-snapdragon/qcom_fit_multidtb.h b/arch/arm/mach-snapdragon/qcom_fit_multidtb.h
new file mode 100644
index 00000000000..00b6d935a4a
--- /dev/null
+++ b/arch/arm/mach-snapdragon/qcom_fit_multidtb.h
@@ -0,0 +1,61 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+/*
+ * Qualcomm FIT Multi-DTB Selection
+ *
+ * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries.
+ *
+ * This implements automatic DTB selection from FIT images based on hardware
+ * detection via SMEM.
+ */
+
+#ifndef __QCOM_FIT_MULTIDTB_H__
+#define __QCOM_FIT_MULTIDTB_H__
+
+#include <linux/types.h>
+#include <linux/list.h>
+
+/**
+ * struct bucket_node - Node in the bucket list
+ * @list: List head for linking nodes
+ * @name: Node name string (e.g., "qcom", "sa8775p-v2", "ride", "ufs", "8gb")
+ *
+ * The bucket list contains all matching node names from the metadata DTB.
+ * These are used to match against FIT configuration compatible strings.
+ */
+struct bucket_node {
+ struct list_head list;
+ char *name;
+};
+
+/* Node processing types for metadata DTB parsing */
+enum node_process_type {
+ NODE_TYPE_OEM,
+ NODE_TYPE_SOC,
+ NODE_TYPE_SOCVER,
+ NODE_TYPE_BOARD,
+ NODE_TYPE_BOARDREV,
+ NODE_TYPE_PERIPHERAL,
+ NODE_TYPE_STORAGE,
+ NODE_TYPE_DDR_SIZE,
+ NODE_TYPE_SOFTSKU,
+};
+
+/* Function prototypes */
+
+/**
+ * qcom_fit_multidtb_setup() - Main entry point for FIT multi-DTB selection
+ *
+ * This function:
+ * 1. Loads qclinux_fit.img from EFI partition
+ * 2. Extracts metadata DTB
+ * 3. Detects hardware parameters from SMEM
+ * 4. Builds bucket list from metadata
+ * 5. Finds matching FIT configuration
+ * 6. Loads DTB and applies overlays
+ * 7. Sets FDT for EFI
+ *
+ * Return: 0 on success, negative error code on failure
+ */
+int qcom_fit_multidtb_setup(void);
+
+#endif /* __QCOM_FIT_MULTIDTB_H__ */
--
2.34.1
^ permalink raw reply related [flat|nested] 11+ messages in thread
* [PATCH RESEND v5 4/5] configs: qcom_defconfig: Enable QCOM_FIT_MULTIDTB
2026-10-12 17:07 [PATCH RESEND v5 0/5] Add FIT multi-DTB selection for Qualcomm Aswin Murugan
` (2 preceding siblings ...)
2026-10-12 17:07 ` [PATCH RESEND v5 3/5] mach-snapdragon: Add FIT multi-DTB selection support Aswin Murugan
@ 2026-10-12 17:07 ` Aswin Murugan
2026-10-12 17:07 ` [PATCH RESEND v5 5/5] arm: dts: Enable qcom, hwinfo on qcs9100-ride-r3, qcs615-ride and qcs6490-rb3gen2 Aswin Murugan
2026-10-12 17:50 ` [PATCH RESEND v5 0/5] Add FIT multi-DTB selection for Qualcomm Tom Rini
5 siblings, 0 replies; 11+ messages in thread
From: Aswin Murugan @ 2026-10-12 17:07 UTC (permalink / raw)
To: trini, ilias.apalodimas, aswin.murugan, casey.connolly,
quic_varada, neil.armstrong, sumit.garg, u-boot,
balaji.selvanathan, Michael.Srba, nathbappai, jbx6244,
quentin.schulz, anshuld, marcello.bauer, tan.siewert, u-boot-qcom
Cc: Simon Glass
From: Aswin Murugan via U-Boot <u-boot@lists.u-boot-project.org>
Enable FIT multi-DTB selection and its OF_LIBFDT_OVERLAY dependency
by default.
Reviewed-by: Simon Glass <sjg@chromium.org>
Signed-off-by: Aswin Murugan <aswin.murugan@oss.qualcomm.com>
---
configs/qcom_defconfig | 2 ++
1 file changed, 2 insertions(+)
diff --git a/configs/qcom_defconfig b/configs/qcom_defconfig
index 7d4a2b589aa..a152ac6708f 100644
--- a/configs/qcom_defconfig
+++ b/configs/qcom_defconfig
@@ -13,6 +13,7 @@ CONFIG_EFI_CAPSULE_FIRMWARE_RAW=y
CONFIG_BUTTON_CMD=y
CONFIG_FIT=y
CONFIG_FIT_VERBOSE=y
+CONFIG_QCOM_FIT_MULTIDTB=y
CONFIG_BOOTSTD_FULL=y
# CONFIG_BOOTMETH_VBE is not set
CONFIG_BOOTDELAY=1
@@ -48,6 +49,7 @@ CONFIG_CMD_EFIDEBUG=y
CONFIG_CMD_RNG=y
CONFIG_CMD_REGULATOR=y
CONFIG_CMD_LOG=y
+CONFIG_OF_LIBFDT_OVERLAY=y
CONFIG_OF_UPSTREAM_BUILD_VENDOR=y
CONFIG_ENV_USE_DEFAULT_ENV_TEXT_FILE=y
CONFIG_ENV_DEFAULT_ENV_TEXT_FILE="board/qualcomm/default.env"
--
2.34.1
^ permalink raw reply related [flat|nested] 11+ messages in thread
* [PATCH RESEND v5 5/5] arm: dts: Enable qcom, hwinfo on qcs9100-ride-r3, qcs615-ride and qcs6490-rb3gen2
2026-10-12 17:07 [PATCH RESEND v5 0/5] Add FIT multi-DTB selection for Qualcomm Aswin Murugan
` (3 preceding siblings ...)
2026-10-12 17:07 ` [PATCH RESEND v5 4/5] configs: qcom_defconfig: Enable QCOM_FIT_MULTIDTB Aswin Murugan
@ 2026-10-12 17:07 ` Aswin Murugan
2026-10-12 17:50 ` [PATCH RESEND v5 0/5] Add FIT multi-DTB selection for Qualcomm Tom Rini
5 siblings, 0 replies; 11+ messages in thread
From: Aswin Murugan @ 2026-10-12 17:07 UTC (permalink / raw)
To: trini, ilias.apalodimas, aswin.murugan, casey.connolly,
quic_varada, neil.armstrong, sumit.garg, u-boot,
balaji.selvanathan, Michael.Srba, nathbappai, jbx6244,
quentin.schulz, anshuld, marcello.bauer, tan.siewert, u-boot-qcom
From: Aswin Murugan via U-Boot <u-boot@lists.u-boot-project.org>
Add the "qcom,hwinfo" DT node with the appropriate IMEM boot-cookie
and TCSR HW-version offsets for each board, enabling FIT multi-DTB
selection (CONFIG_QCOM_FIT_MULTIDTB) to detect hardware parameters
at boot time.
Signed-off-by: Aswin Murugan <aswin.murugan@oss.qualcomm.com>
---
arch/arm/dts/qcs615-ride-u-boot.dtsi | 10 ++++++++++
arch/arm/dts/qcs6490-rb3gen2-u-boot.dtsi | 10 ++++++++++
arch/arm/dts/qcs9100-ride-r3-u-boot.dtsi | 10 ++++++++++
3 files changed, 30 insertions(+)
diff --git a/arch/arm/dts/qcs615-ride-u-boot.dtsi b/arch/arm/dts/qcs615-ride-u-boot.dtsi
index 68fffc70fcb..8400b786f4d 100644
--- a/arch/arm/dts/qcs615-ride-u-boot.dtsi
+++ b/arch/arm/dts/qcs615-ride-u-boot.dtsi
@@ -11,4 +11,14 @@
<0x0 0xc0000000 0x0 0xc0000000>,
<0x1 0x80000000 0x1 0x00000000>;
};
+
+ qcom_hwinfo: qcom-hwinfo {
+ compatible = "qcom,hwinfo";
+
+ imem = <&{/soc@0/sram@14680000}>;
+ imem-boot-cookie-offset = <0x2a000>;
+
+ tcsr = <&tcsr>;
+ tcsr-hw-version-offset = <0x8000>;
+ };
};
diff --git a/arch/arm/dts/qcs6490-rb3gen2-u-boot.dtsi b/arch/arm/dts/qcs6490-rb3gen2-u-boot.dtsi
index c3ec4a317f7..ffcc2b3d47f 100644
--- a/arch/arm/dts/qcs6490-rb3gen2-u-boot.dtsi
+++ b/arch/arm/dts/qcs6490-rb3gen2-u-boot.dtsi
@@ -15,6 +15,16 @@
<0 0xC3400000 0 0x3CC00000>,
<1 0x00000000 1 0x00000000>;
};
+
+ qcom_hwinfo: qcom-hwinfo {
+ compatible = "qcom,hwinfo";
+
+ imem = <&{/soc@0/sram@146a5000}>;
+ imem-boot-cookie-offset = <0x5000>;
+
+ tcsr = <&tcsr_2>;
+ tcsr-hw-version-offset = <0x8000>;
+ };
};
// RAM Entry 0 : Base 0x0080000000 Size 0x003A800000
diff --git a/arch/arm/dts/qcs9100-ride-r3-u-boot.dtsi b/arch/arm/dts/qcs9100-ride-r3-u-boot.dtsi
index 5905dfad18f..ab10ec37056 100644
--- a/arch/arm/dts/qcs9100-ride-r3-u-boot.dtsi
+++ b/arch/arm/dts/qcs9100-ride-r3-u-boot.dtsi
@@ -17,4 +17,14 @@
<0x0 0xd3500000 0x0 0x07c00000>,
<0x0 0xdb300000 0x0 0x24d00000>;
};
+
+ qcom_hwinfo: qcom-hwinfo {
+ compatible = "qcom,hwinfo";
+
+ imem = <&sram>;
+ imem-boot-cookie-offset = <0x0>;
+
+ tcsr = <&tcsr>;
+ tcsr-hw-version-offset = <0x8000>;
+ };
};
--
2.34.1
^ permalink raw reply related [flat|nested] 11+ messages in thread
* Re: [PATCH RESEND v5 0/5] Add FIT multi-DTB selection for Qualcomm
2026-10-12 17:07 [PATCH RESEND v5 0/5] Add FIT multi-DTB selection for Qualcomm Aswin Murugan
` (4 preceding siblings ...)
2026-10-12 17:07 ` [PATCH RESEND v5 5/5] arm: dts: Enable qcom, hwinfo on qcs9100-ride-r3, qcs615-ride and qcs6490-rb3gen2 Aswin Murugan
@ 2026-10-12 17:50 ` Tom Rini
2026-10-13 7:20 ` Aswin Murugan
5 siblings, 1 reply; 11+ messages in thread
From: Tom Rini @ 2026-10-12 17:50 UTC (permalink / raw)
To: Aswin Murugan
Cc: ilias.apalodimas, casey.connolly, quic_varada, neil.armstrong,
sumit.garg, u-boot, balaji.selvanathan, Michael.Srba, nathbappai,
jbx6244, quentin.schulz, anshuld, marcello.bauer, tan.siewert,
u-boot-qcom
[-- Attachment #1: Type: text/plain, Size: 2502 bytes --]
On Mon, Oct 12, 2026 at 10:37:49PM +0530, Aswin Murugan wrote:
> This series adds dynamic device tree selection from FIT images for
> Qualcomm Snapdragon platforms, enabling U-Boot to select the
> appropriate DTB based on hardware parameters detected at boot.
>
> Qualcomm FIT-based DTB format is documented in [1].
>
> The FIT image contains only DTBs, while the kernel is provided
> separately as part of a UKI image.
>
> The implementation consists of:
>
> 1. Hardware detection infrastructure: Introduces the qcom,hwinfo
> driver and qcom_hwdetect helper to collect hardware identification
> data from SMEM, IMEM and TCSR into a single qcom_hw_params
> structure for consumers such as FIT multi-DTB selection.
>
> 2. FIT multi-DTB selection: Implements DTB selection based on the
> aggregated hardware information. The code parses metadata DTBs,
> matches FIT configurations against detected hardware attributes,
> applies overlays, and loads the selected DTB for EFI boot.
>
> [1] https://github.com/qualcomm-linux/qcom-dtb-metadata/blob/main/
> Documentation.md
>
> ---
>
> Changes in v4:
... which was sent as v5, and this is a re-send of?
> 1. Drop the SMEM cache infrastructure.
>
> 2. misc: qcom: add qcom,hwinfo driver to provide a common interface
> for reading IMEM boot cookie and TCSR SOC version information.
>
> 3. arm: snapdragon: add qcom_hwdetect helper to aggregate hardware
> information from SMEM, IMEM and TCSR into a single
> struct qcom_hw_params.
>
> 4. Refactor FIT multi-DTB selection to consume qcom_hw_params instead
> of accessing SMEM, IMEM and TCSR data directly.
>
> 5. Separate hardware discovery from FIT parsing and DTB matching
> logic, reducing complexity and improving code organization.
>
> 6. Load FIT images directly from a raw GPT partition and remove the
> FAT filesystem image based loading approach.
>
> 7. Drop IH_TYPE_FATFS, mkimage FAT image generation support and
> related documentation updates.
>
> 8. arm: dts: enable qcom,hwinfo on qcs9100-ride-r3, qcs615-ride and
> qcs6490-rb3gen2 by adding the required qcom,hwinfo DT nodes and
> board-specific offsets.
>
> Link to v3:
> https://lore.kernel.org/u-boot/20260417120951.3454249-1-aswin.murugan@oss.qualcomm.com/
The FAT comments in v3 were addressed. I'm not really sure the discussion about if
this approach makes sense as really was addressed however?
--
Tom
[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 228 bytes --]
^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: [PATCH RESEND v5 0/5] Add FIT multi-DTB selection for Qualcomm
2026-10-12 17:50 ` [PATCH RESEND v5 0/5] Add FIT multi-DTB selection for Qualcomm Tom Rini
@ 2026-10-13 7:20 ` Aswin Murugan
2026-10-13 15:03 ` Tom Rini
0 siblings, 1 reply; 11+ messages in thread
From: Aswin Murugan @ 2026-10-13 7:20 UTC (permalink / raw)
To: Tom Rini
Cc: ilias.apalodimas, casey.connolly, quic_varada, neil.armstrong,
sumit.garg, u-boot, balaji.selvanathan, Michael.Srba, nathbappai,
jbx6244, quentin.schulz, anshuld, marcello.bauer, tan.siewert,
u-boot-qcom
On 10/12/2026 11:20 PM, Tom Rini wrote:
Hi Tom,
> On Mon, Oct 12, 2026 at 10:37:49PM +0530, Aswin Murugan wrote:
>> This series adds dynamic device tree selection from FIT images for
>> Qualcomm Snapdragon platforms, enabling U-Boot to select the
>> appropriate DTB based on hardware parameters detected at boot.
>>
>> Qualcomm FIT-based DTB format is documented in [1].
>>
>> The FIT image contains only DTBs, while the kernel is provided
>> separately as part of a UKI image.
>>
>> The implementation consists of:
>>
>> 1. Hardware detection infrastructure: Introduces the qcom,hwinfo
>> driver and qcom_hwdetect helper to collect hardware identification
>> data from SMEM, IMEM and TCSR into a single qcom_hw_params
>> structure for consumers such as FIT multi-DTB selection.
>>
>> 2. FIT multi-DTB selection: Implements DTB selection based on the
>> aggregated hardware information. The code parses metadata DTBs,
>> matches FIT configurations against detected hardware attributes,
>> applies overlays, and loads the selected DTB for EFI boot.
>>
>> [1] https://github.com/qualcomm-linux/qcom-dtb-metadata/blob/main/
>> Documentation.md
>>
>> ---
>>
>> Changes in v4:
> ... which was sent as v5, and this is a re-send of?
Yes, this is a resend of v4, which was sent as v5
>> 1. Drop the SMEM cache infrastructure.
>>
>> 2. misc: qcom: add qcom,hwinfo driver to provide a common interface
>> for reading IMEM boot cookie and TCSR SOC version information.
>>
>> 3. arm: snapdragon: add qcom_hwdetect helper to aggregate hardware
>> information from SMEM, IMEM and TCSR into a single
>> struct qcom_hw_params.
>>
>> 4. Refactor FIT multi-DTB selection to consume qcom_hw_params instead
>> of accessing SMEM, IMEM and TCSR data directly.
>>
>> 5. Separate hardware discovery from FIT parsing and DTB matching
>> logic, reducing complexity and improving code organization.
>>
>> 6. Load FIT images directly from a raw GPT partition and remove the
>> FAT filesystem image based loading approach.
>>
>> 7. Drop IH_TYPE_FATFS, mkimage FAT image generation support and
>> related documentation updates.
>>
>> 8. arm: dts: enable qcom,hwinfo on qcs9100-ride-r3, qcs615-ride and
>> qcs6490-rb3gen2 by adding the required qcom,hwinfo DT nodes and
>> board-specific offsets.
>>
>> Link to v3:
>> https://lore.kernel.org/u-boot/20260417120951.3454249-1-aswin.murugan@oss.qualcomm.com/
> The FAT comments in v3 were addressed. I'm not really sure the discussion about if
> this approach makes sense as really was addressed however?
Yes, the FAT-related comments from v3 were addressed in this
revision by dropping the FAT filesystem image-based loading
approach and loading FIT image directly from a raw GPT
partition.
Regarding the broader design, the reasoning for using a
DTB-only FIT was discussed in the v3 thread [1]. The intention
is to support firmware-side DT selection while keeping DTB
management independent of kernel packaging, matching existing
Qualcomm deployment models. This is intended to coexist with,
rather than replace, approaches such as UKI DT bundling.
[1]: https://lore.kernel.org/u-boot/afSXa7q7hJC_ZW07@sumit-xelite/
Thanks,
Aswin
^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: [PATCH RESEND v5 0/5] Add FIT multi-DTB selection for Qualcomm
2026-10-13 7:20 ` Aswin Murugan
@ 2026-10-13 15:03 ` Tom Rini
2026-10-16 12:15 ` Sumit Garg
0 siblings, 1 reply; 11+ messages in thread
From: Tom Rini @ 2026-10-13 15:03 UTC (permalink / raw)
To: Aswin Murugan
Cc: ilias.apalodimas, casey.connolly, quic_varada, neil.armstrong,
sumit.garg, u-boot, balaji.selvanathan, Michael.Srba, nathbappai,
jbx6244, quentin.schulz, anshuld, marcello.bauer, tan.siewert,
u-boot-qcom
[-- Attachment #1: Type: text/plain, Size: 3856 bytes --]
On Tue, Oct 13, 2026 at 12:50:42PM +0530, Aswin Murugan wrote:
>
> On 10/12/2026 11:20 PM, Tom Rini wrote:
> Hi Tom,
> > On Mon, Oct 12, 2026 at 10:37:49PM +0530, Aswin Murugan wrote:
> > > This series adds dynamic device tree selection from FIT images for
> > > Qualcomm Snapdragon platforms, enabling U-Boot to select the
> > > appropriate DTB based on hardware parameters detected at boot.
> > >
> > > Qualcomm FIT-based DTB format is documented in [1].
> > >
> > > The FIT image contains only DTBs, while the kernel is provided
> > > separately as part of a UKI image.
> > >
> > > The implementation consists of:
> > >
> > > 1. Hardware detection infrastructure: Introduces the qcom,hwinfo
> > > driver and qcom_hwdetect helper to collect hardware identification
> > > data from SMEM, IMEM and TCSR into a single qcom_hw_params
> > > structure for consumers such as FIT multi-DTB selection.
> > >
> > > 2. FIT multi-DTB selection: Implements DTB selection based on the
> > > aggregated hardware information. The code parses metadata DTBs,
> > > matches FIT configurations against detected hardware attributes,
> > > applies overlays, and loads the selected DTB for EFI boot.
> > >
> > > [1] https://github.com/qualcomm-linux/qcom-dtb-metadata/blob/main/
> > > Documentation.md
> > >
> > > ---
> > >
> > > Changes in v4:
> > ... which was sent as v5, and this is a re-send of?
> Yes, this is a resend of v4, which was sent as v5
> > > 1. Drop the SMEM cache infrastructure.
> > >
> > > 2. misc: qcom: add qcom,hwinfo driver to provide a common interface
> > > for reading IMEM boot cookie and TCSR SOC version information.
> > >
> > > 3. arm: snapdragon: add qcom_hwdetect helper to aggregate hardware
> > > information from SMEM, IMEM and TCSR into a single
> > > struct qcom_hw_params.
> > >
> > > 4. Refactor FIT multi-DTB selection to consume qcom_hw_params instead
> > > of accessing SMEM, IMEM and TCSR data directly.
> > >
> > > 5. Separate hardware discovery from FIT parsing and DTB matching
> > > logic, reducing complexity and improving code organization.
> > >
> > > 6. Load FIT images directly from a raw GPT partition and remove the
> > > FAT filesystem image based loading approach.
> > >
> > > 7. Drop IH_TYPE_FATFS, mkimage FAT image generation support and
> > > related documentation updates.
> > >
> > > 8. arm: dts: enable qcom,hwinfo on qcs9100-ride-r3, qcs615-ride and
> > > qcs6490-rb3gen2 by adding the required qcom,hwinfo DT nodes and
> > > board-specific offsets.
> > >
> > > Link to v3:
> > > https://lore.kernel.org/u-boot/20260417120951.3454249-1-aswin.murugan@oss.qualcomm.com/
> > The FAT comments in v3 were addressed. I'm not really sure the discussion about if
> > this approach makes sense as really was addressed however?
>
> Yes, the FAT-related comments from v3 were addressed in this
> revision by dropping the FAT filesystem image-based loading
> approach and loading FIT image directly from a raw GPT
> partition.
Right, thanks.
> Regarding the broader design, the reasoning for using a
> DTB-only FIT was discussed in the v3 thread [1]. The intention
> is to support firmware-side DT selection while keeping DTB
> management independent of kernel packaging, matching existing
> Qualcomm deployment models. This is intended to coexist with,
> rather than replace, approaches such as UKI DT bundling.
>
> [1]: https://lore.kernel.org/u-boot/afSXa7q7hJC_ZW07@sumit-xelite/
Yes, and I'd appreciate some of the people that were discussing things
in that thread chiming in and saying they're happy enough, as it wasn't
clear to me in re-reading the thread yesterday that the discussion ended
with agreement and instead just stopped.
--
Tom
[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 228 bytes --]
^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: [PATCH RESEND v5 0/5] Add FIT multi-DTB selection for Qualcomm
2026-10-13 15:03 ` Tom Rini
@ 2026-10-16 12:15 ` Sumit Garg
2026-10-16 16:27 ` Tom Rini
0 siblings, 1 reply; 11+ messages in thread
From: Sumit Garg @ 2026-10-16 12:15 UTC (permalink / raw)
To: Tom Rini
Cc: Aswin Murugan, ilias.apalodimas, casey.connolly, quic_varada,
neil.armstrong, sumit.garg, u-boot, balaji.selvanathan,
Michael.Srba, nathbappai, jbx6244, quentin.schulz, anshuld,
marcello.bauer, tan.siewert, u-boot-qcom
Hi Tom,
On Tue, 13 Oct 2026 at 09:03:07 -0600, Tom Rini wrote:
>On Tue, Oct 13, 2026 at 12:50:42PM +0530, Aswin Murugan wrote:
>>
>> On 10/12/2026 11:20 PM, Tom Rini wrote:
>> Hi Tom,
>> > On Mon, Oct 12, 2026 at 10:37:49PM +0530, Aswin Murugan wrote:
>> > > This series adds dynamic device tree selection from FIT images for
>> > > Qualcomm Snapdragon platforms, enabling U-Boot to select the
>> > > appropriate DTB based on hardware parameters detected at boot.
>> > >
>> > > Qualcomm FIT-based DTB format is documented in [1].
>> > >
>> > > The FIT image contains only DTBs, while the kernel is provided
>> > > separately as part of a UKI image.
>> > >
>> > > The implementation consists of:
>> > >
>> > > 1. Hardware detection infrastructure: Introduces the qcom,hwinfo
>> > > driver and qcom_hwdetect helper to collect hardware identification
>> > > data from SMEM, IMEM and TCSR into a single qcom_hw_params
>> > > structure for consumers such as FIT multi-DTB selection.
>> > >
>> > > 2. FIT multi-DTB selection: Implements DTB selection based on the
>> > > aggregated hardware information. The code parses metadata DTBs,
>> > > matches FIT configurations against detected hardware attributes,
>> > > applies overlays, and loads the selected DTB for EFI boot.
>> > >
>> > > [1] https://github.com/qualcomm-linux/qcom-dtb-metadata/blob/main/
>> > > Documentation.md
>> > >
>> > > ---
>> > >
>> > > Changes in v4:
>> > ... which was sent as v5, and this is a re-send of?
>> Yes, this is a resend of v4, which was sent as v5
>> > > 1. Drop the SMEM cache infrastructure.
>> > >
>> > > 2. misc: qcom: add qcom,hwinfo driver to provide a common interface
>> > > for reading IMEM boot cookie and TCSR SOC version information.
>> > >
>> > > 3. arm: snapdragon: add qcom_hwdetect helper to aggregate hardware
>> > > information from SMEM, IMEM and TCSR into a single
>> > > struct qcom_hw_params.
>> > >
>> > > 4. Refactor FIT multi-DTB selection to consume qcom_hw_params instead
>> > > of accessing SMEM, IMEM and TCSR data directly.
>> > >
>> > > 5. Separate hardware discovery from FIT parsing and DTB matching
>> > > logic, reducing complexity and improving code organization.
>> > >
>> > > 6. Load FIT images directly from a raw GPT partition and remove the
>> > > FAT filesystem image based loading approach.
>> > >
>> > > 7. Drop IH_TYPE_FATFS, mkimage FAT image generation support and
>> > > related documentation updates.
>> > >
>> > > 8. arm: dts: enable qcom,hwinfo on qcs9100-ride-r3, qcs615-ride and
>> > > qcs6490-rb3gen2 by adding the required qcom,hwinfo DT nodes and
>> > > board-specific offsets.
>> > >
>> > > Link to v3:
>> > > https://lore.kernel.org/u-boot/20260417120951.3454249-1-aswin.murugan@oss.qualcomm.com/
>> > The FAT comments in v3 were addressed. I'm not really sure the discussion about if
>> > this approach makes sense as really was addressed however?
>>
>> Yes, the FAT-related comments from v3 were addressed in this
>> revision by dropping the FAT filesystem image-based loading
>> approach and loading FIT image directly from a raw GPT
>> partition.
>
>Right, thanks.
>
>> Regarding the broader design, the reasoning for using a
>> DTB-only FIT was discussed in the v3 thread [1]. The intention
>> is to support firmware-side DT selection while keeping DTB
>> management independent of kernel packaging, matching existing
>> Qualcomm deployment models. This is intended to coexist with,
>> rather than replace, approaches such as UKI DT bundling.
>>
>> [1]: https://lore.kernel.org/u-boot/afSXa7q7hJC_ZW07@sumit-xelite/
>
>Yes, and I'd appreciate some of the people that were discussing things
>in that thread chiming in and saying they're happy enough, as it wasn't
>clear to me in re-reading the thread yesterday that the discussion ended
>with agreement and instead just stopped.
>
As of now the Qualcomm subsystem maintenence is in really inactive state
as you can see from the list of patchsets even carrying review tags are
missing custodian attention here [1]. If you remember it from our earlier
private thread with Casey and Neil many months ago, the maintainence
situation hasn't improved at all.
Even as a reviewer for the Qcom subsystem, I have tried earlier with all
the reviews but patches were still floating on the list, which just
demotivated me from doing further reviews.
I would really like to get this maintainence situation fixed. Would it
be fine with you to accept me as a Qcom subsystem custodian with more
people from Qualcomm contributing as reviewers?
In the meantime why we decide on that, can you help with picking patches
which have been reviewed directly for the Qualcomm subsystem?
[1] https://patchwork.ozlabs.org/project/uboot/list/?delegate=151538¶m=4&page=1
-Sumit
^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: [PATCH RESEND v5 0/5] Add FIT multi-DTB selection for Qualcomm
2026-10-16 12:15 ` Sumit Garg
@ 2026-10-16 16:27 ` Tom Rini
0 siblings, 0 replies; 11+ messages in thread
From: Tom Rini @ 2026-10-16 16:27 UTC (permalink / raw)
To: Sumit Garg
Cc: Aswin Murugan, ilias.apalodimas, casey.connolly, quic_varada,
neil.armstrong, u-boot, balaji.selvanathan, Michael.Srba,
nathbappai, jbx6244, quentin.schulz, anshuld, marcello.bauer,
tan.siewert, u-boot-qcom
[-- Attachment #1: Type: text/plain, Size: 5568 bytes --]
On Fri, Oct 16, 2026 at 05:45:56PM +0530, Sumit Garg wrote:
> Hi Tom,
>
> On Tue, 13 Oct 2026 at 09:03:07 -0600, Tom Rini wrote:
> > On Tue, Oct 13, 2026 at 12:50:42PM +0530, Aswin Murugan wrote:
> > >
> > > On 10/12/2026 11:20 PM, Tom Rini wrote:
> > > Hi Tom,
> > > > On Mon, Oct 12, 2026 at 10:37:49PM +0530, Aswin Murugan wrote:
> > > > > This series adds dynamic device tree selection from FIT images for
> > > > > Qualcomm Snapdragon platforms, enabling U-Boot to select the
> > > > > appropriate DTB based on hardware parameters detected at boot.
> > > > >
> > > > > Qualcomm FIT-based DTB format is documented in [1].
> > > > >
> > > > > The FIT image contains only DTBs, while the kernel is provided
> > > > > separately as part of a UKI image.
> > > > >
> > > > > The implementation consists of:
> > > > >
> > > > > 1. Hardware detection infrastructure: Introduces the qcom,hwinfo
> > > > > driver and qcom_hwdetect helper to collect hardware identification
> > > > > data from SMEM, IMEM and TCSR into a single qcom_hw_params
> > > > > structure for consumers such as FIT multi-DTB selection.
> > > > >
> > > > > 2. FIT multi-DTB selection: Implements DTB selection based on the
> > > > > aggregated hardware information. The code parses metadata DTBs,
> > > > > matches FIT configurations against detected hardware attributes,
> > > > > applies overlays, and loads the selected DTB for EFI boot.
> > > > >
> > > > > [1] https://github.com/qualcomm-linux/qcom-dtb-metadata/blob/main/
> > > > > Documentation.md
> > > > >
> > > > > ---
> > > > >
> > > > > Changes in v4:
> > > > ... which was sent as v5, and this is a re-send of?
> > > Yes, this is a resend of v4, which was sent as v5
> > > > > 1. Drop the SMEM cache infrastructure.
> > > > >
> > > > > 2. misc: qcom: add qcom,hwinfo driver to provide a common interface
> > > > > for reading IMEM boot cookie and TCSR SOC version information.
> > > > >
> > > > > 3. arm: snapdragon: add qcom_hwdetect helper to aggregate hardware
> > > > > information from SMEM, IMEM and TCSR into a single
> > > > > struct qcom_hw_params.
> > > > >
> > > > > 4. Refactor FIT multi-DTB selection to consume qcom_hw_params instead
> > > > > of accessing SMEM, IMEM and TCSR data directly.
> > > > >
> > > > > 5. Separate hardware discovery from FIT parsing and DTB matching
> > > > > logic, reducing complexity and improving code organization.
> > > > >
> > > > > 6. Load FIT images directly from a raw GPT partition and remove the
> > > > > FAT filesystem image based loading approach.
> > > > >
> > > > > 7. Drop IH_TYPE_FATFS, mkimage FAT image generation support and
> > > > > related documentation updates.
> > > > >
> > > > > 8. arm: dts: enable qcom,hwinfo on qcs9100-ride-r3, qcs615-ride and
> > > > > qcs6490-rb3gen2 by adding the required qcom,hwinfo DT nodes and
> > > > > board-specific offsets.
> > > > >
> > > > > Link to v3:
> > > > > https://lore.kernel.org/u-boot/20260417120951.3454249-1-aswin.murugan@oss.qualcomm.com/
> > > > The FAT comments in v3 were addressed. I'm not really sure the discussion about if
> > > > this approach makes sense as really was addressed however?
> > >
> > > Yes, the FAT-related comments from v3 were addressed in this
> > > revision by dropping the FAT filesystem image-based loading
> > > approach and loading FIT image directly from a raw GPT
> > > partition.
> >
> > Right, thanks.
> >
> > > Regarding the broader design, the reasoning for using a
> > > DTB-only FIT was discussed in the v3 thread [1]. The intention
> > > is to support firmware-side DT selection while keeping DTB
> > > management independent of kernel packaging, matching existing
> > > Qualcomm deployment models. This is intended to coexist with,
> > > rather than replace, approaches such as UKI DT bundling.
> > >
> > > [1]: https://lore.kernel.org/u-boot/afSXa7q7hJC_ZW07@sumit-xelite/
> >
> > Yes, and I'd appreciate some of the people that were discussing things
> > in that thread chiming in and saying they're happy enough, as it wasn't
> > clear to me in re-reading the thread yesterday that the discussion ended
> > with agreement and instead just stopped.
> >
>
> As of now the Qualcomm subsystem maintenence is in really inactive state
> as you can see from the list of patchsets even carrying review tags are
> missing custodian attention here [1]. If you remember it from our earlier
> private thread with Casey and Neil many months ago, the maintainence
> situation hasn't improved at all.
>
> Even as a reviewer for the Qcom subsystem, I have tried earlier with all
> the reviews but patches were still floating on the list, which just
> demotivated me from doing further reviews.
>
> I would really like to get this maintainence situation fixed. Would it
> be fine with you to accept me as a Qcom subsystem custodian with more
> people from Qualcomm contributing as reviewers?
>
> In the meantime why we decide on that, can you help with picking patches
> which have been reviewed directly for the Qualcomm subsystem?
>
> [1] https://patchwork.ozlabs.org/project/uboot/list/?delegate=151538¶m=4&page=1
I don't have a problem with (and a number of our SoCs do this now) have
co-custodians, so I've reached out to Casey.
Since you brought it up in this thread, you were in the original v3 with
questions / concerns about the approach that I wasn't sure if were
resolved.
--
Tom
[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 228 bytes --]
^ permalink raw reply [flat|nested] 11+ messages in thread
end of thread, other threads:[~2026-10-16 16:27 UTC | newest]
Thread overview: 11+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-10-12 17:07 [PATCH RESEND v5 0/5] Add FIT multi-DTB selection for Qualcomm Aswin Murugan
2026-10-12 17:07 ` [PATCH RESEND v5 1/5] misc: qcom: Add HW-Info aggregator driver Aswin Murugan
2026-10-12 17:07 ` [PATCH RESEND v5 2/5] mach-snapdragon: Add hardware detection helper Aswin Murugan
2026-10-12 17:07 ` [PATCH RESEND v5 3/5] mach-snapdragon: Add FIT multi-DTB selection support Aswin Murugan
2026-10-12 17:07 ` [PATCH RESEND v5 4/5] configs: qcom_defconfig: Enable QCOM_FIT_MULTIDTB Aswin Murugan
2026-10-12 17:07 ` [PATCH RESEND v5 5/5] arm: dts: Enable qcom, hwinfo on qcs9100-ride-r3, qcs615-ride and qcs6490-rb3gen2 Aswin Murugan
2026-10-12 17:50 ` [PATCH RESEND v5 0/5] Add FIT multi-DTB selection for Qualcomm Tom Rini
2026-10-13 7:20 ` Aswin Murugan
2026-10-13 15:03 ` Tom Rini
2026-10-16 12:15 ` Sumit Garg
2026-10-16 16:27 ` Tom Rini
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.