From 67bfb7dfd753cf082355f75ef541d355c22b3641 Mon Sep 17 00:00:00 2001 From: Aswin Murugan Date: Wed, 29 Apr 2026 18:55:52 +0530 Subject: [PATCH 1/2] mach-snapdragon: Add memory node fixup handlers Add device tree DDR configuration fixup handler infrastructure to support runtime dts modifications. DDR info fixup (qcom_fixup_ddrinfo.c) - Adds DDR configuration information like DDR size. Signed-off-by: Aswin Murugan --- arch/arm/mach-snapdragon/Makefile | 1 + arch/arm/mach-snapdragon/qcom_fixup_ddrinfo.c | 161 ++++++++++++++++++ .../arm/mach-snapdragon/qcom_fixup_handlers.h | 46 +++++ 3 files changed, 208 insertions(+) create mode 100644 arch/arm/mach-snapdragon/qcom_fixup_ddrinfo.c create mode 100644 arch/arm/mach-snapdragon/qcom_fixup_handlers.h diff --git a/arch/arm/mach-snapdragon/Makefile b/arch/arm/mach-snapdragon/Makefile index 343e825c6fdd..d1ebe75c4f4f 100644 --- a/arch/arm/mach-snapdragon/Makefile +++ b/arch/arm/mach-snapdragon/Makefile @@ -4,4 +4,5 @@ obj-y += board.o obj-$(CONFIG_EFI_HAVE_CAPSULE_SUPPORT) += capsule_update.o +obj-$(CONFIG_OF_LIVE) += qcom_fixup_ddrinfo.o obj-$(CONFIG_OF_LIVE) += of_fixup.o diff --git a/arch/arm/mach-snapdragon/qcom_fixup_ddrinfo.c b/arch/arm/mach-snapdragon/qcom_fixup_ddrinfo.c new file mode 100644 index 000000000000..59a0e3c5d82a --- /dev/null +++ b/arch/arm/mach-snapdragon/qcom_fixup_ddrinfo.c @@ -0,0 +1,161 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * DDRInfo Fixup + * + * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. + * + */ + +#include +#include +#include +#include +#include "qcom_fixup_handlers.h" +#include "qcom-priv.h" + +/* With the new SMEM architecture, SMEM IDs need to be defined in individual + * driver files + */ +#define SMEM_ID_DDRINFO 0x25B // 603 + +struct ddr_details_entry { + u8 manufacturer_id; + u8 device_type; +}; + +/** + * get_ddr_details() - Retrieves the DDR details entry from the SMEM. + * @ddr_detail: The DDR details entry to retrieve. + * + * This function retrieves the DDR details entry from the SMEM and prints it + * out. + * + * Return: 0 on success, -1 on failure + */ +static int get_ddr_details(struct ddr_details_entry *ddr_detail) +{ + void *ddr_table_ptr; + struct udevice *dev; + size_t size; + + if (uclass_get_device(UCLASS_SMEM, 0, &dev) != 0) + return log_msg_ret("Error: uclass_get_device\n", -1); + ddr_table_ptr = smem_get(dev, 0, SMEM_ID_DDRINFO, &size); + + if (!ddr_table_ptr) + return log_msg_ret("Error: invalid DDR Entry\n", -1); + memcpy((void *)ddr_detail, ddr_table_ptr, sizeof(struct ddr_details_entry)); + + return 0; +} + +/** + * set_mem_reg_node() - Sets the ram partition info to memory node + * @fdt_ptr: Pointer to the device tree + * @path_offset: Offset to the memory node + * @start_addr: Start address of the mem partition + * @mem_size: Size of the mem partition + * + * This function is responsible for setting the reg property of memory node + * in the device tree + * + * Return: 0 on success, -1 on failure + */ +static int set_mem_reg_node(struct fdt_header *fdt_ptr, u32 path_offset, + u64 start_addr, u64 mem_size) +{ + int ret; + + log_debug("Mem info start addr: %llx ,size %llx\n", start_addr, mem_size); + ret = fixup_dt_node(fdt_ptr, path_offset, "reg", + (void *)(&start_addr), APPEND_PROP_U64); + if (ret) + return log_msg_ret("Failed to append start_addr details in Reg prop\n", -1); + + ret = fixup_dt_node(fdt_ptr, path_offset, "reg", + (void *)(&mem_size), APPEND_PROP_U64); + if (ret) + return log_msg_ret("Failed to append mem_size details in Reg prop\n", -1); + + return 0; +} + +/** + * set_ram_part_info() - Gets the ram partition info from smem and sets + * it to memory node + * @fdt_ptr: Pointer to the device tree + * @path_offset: Offset to the memory node + * + * This function is responsible for obtaining ram partition information info + * from smem and sets it to the device tree + * tree. + * + * Return: 0 on success, -1 on failure + */ +static int set_ram_part_info(struct fdt_header *fdt_ptr, u32 path_offset) +{ + int ret = 0, res, part; + struct usable_ram_partition_table *rpt; + struct ram_partition_entry *rpe; + + rpt = qcom_get_ram_partitions(); + if (!rpt) + return -1; + rpe = &rpt->ram_part_entry[0]; + + for (part = 0; part < rpt->num_partitions; part++, rpe++) + if (rpe->partition_category == RAM_PARTITION_SDRAM && + rpe->partition_type == RAM_PARTITION_SYS_MEMORY) { + res = set_mem_reg_node(fdt_ptr, path_offset, + rpe->start_address, + rpe->available_length); + if (res) { + log_err("Failed to set Mem info start addr: %llx ,size %llx\n", + rpe->start_address, rpe->available_length); + ret = -1; + } + } + + return ret; +} + +/** + * ddrinfo_fixup_handler() - DDRInfo Fixup handler function + * @fdt_ptr: Pointer to the device tree + * + * This function is responsible for updating the DDR information in the device + * tree. + */ +void ddrinfo_fixup_handler(struct fdt_header *fdt_ptr) +{ + u32 path_offset, ret; + u64 prop_value; + struct ddr_details_entry ddr_details; + + ret = get_ddr_details(&ddr_details); + if (ret) { + log_err("Error getting DDR details\n"); + return; + } + + path_offset = fdt_path_offset(fdt_ptr, "/memory"); + if (path_offset < 0) { + log_err("Error getting memory offset: %d\n", path_offset); + return; + } + + prop_value = (u64)ddr_details.device_type; + ret = fixup_dt_node(fdt_ptr, path_offset, "ddr_device_type", + (void *)(&prop_value), APPEND_PROP_U64); + if (ret) + log_err("Failed to append DDR device type data : %d\n", ret); + + ret = fdt_delprop(fdt_ptr, path_offset, "reg"); + if (!ret) { + ret = set_ram_part_info(fdt_ptr, path_offset); + if (ret) + log_err("set_ram_part_info failed"); + } +} + +/* End of File */ diff --git a/arch/arm/mach-snapdragon/qcom_fixup_handlers.h b/arch/arm/mach-snapdragon/qcom_fixup_handlers.h new file mode 100644 index 000000000000..60c5cf6f0996 --- /dev/null +++ b/arch/arm/mach-snapdragon/qcom_fixup_handlers.h @@ -0,0 +1,46 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ +/* + * SUBSET Parts Fixup: A tool for fixing up subset parts in a system + * + * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. + * + */ + +#include + +enum fdt_fixup_type { + APPEND_PROP_U32 = 0, + APPEND_PROP_U64 = 1, + SET_PROP_U32 = 2, + SET_PROP_U64 = 3, + SET_PROP_STRING = 4, + ADD_SUBNODE = 5, +}; + +/** + * ddrinfo_fixup_handler() - DDRInfo Fixup handler function + * @fdt_ptr: Pointer to the device tree + * + * This function is responsible for updating the DDR information in + * the device tree. + * + * Return: None + */ +void ddrinfo_fixup_handler(struct fdt_header *fdt_ptr); + +/** + * fixup_dt_node() - Exports a property to the firmware DT node. + * @fdt_ptr: The firmware DT node to update. + * @node_offset: The offset in the DT node where the property should be set. + * @property_name: The name of the property to set. + * @property_value: The value of the property to set. + * @type: Fixup type + * This function sets a property in the firmware DT node with the given name and + * value. + * + * Return: 0 on success, negative on failure. + */ +int fixup_dt_node(void *fdt_ptr, int node_offset, + const char *property_name, + void *property_value, + enum fdt_fixup_type type); From 8f76c2f09068769f5c1a7b7ed311246ee00b4b41 Mon Sep 17 00:00:00 2001 From: Aswin Murugan Date: Tue, 13 Jan 2026 17:24:04 +0530 Subject: [PATCH 2/2] arm: snapdragon: Integrate OF_LIVE fixup handlers in ft_board_setup() Integrate the device tree fixup handlers into ft_board_setup() to enable runtime device tree modifications for Qualcomm Snapdragon platforms. This patch adds: 1. ft_board_setup() implementation - Calls all registered fixup handlers - Provides central point for device tree modifications - Executes before passing DT to kernel 2. fixup_dt_node() utility function - Generic device tree node manipulation helper - Supports multiple operation types: * APPEND_PROP_U32/U64: Append 32/64-bit properties * SET_PROP_U32/U64/STRING: Set property values * ADD_SUBNODE: Add new device tree nodes - Automatically adjusts FDT size as needed Signed-off-by: Aswin Murugan --- arch/arm/mach-snapdragon/of_fixup.c | 82 +++++++++++++++++++++++++++++ 1 file changed, 82 insertions(+) diff --git a/arch/arm/mach-snapdragon/of_fixup.c b/arch/arm/mach-snapdragon/of_fixup.c index 374e6262db43..c1a0a92834b4 100644 --- a/arch/arm/mach-snapdragon/of_fixup.c +++ b/arch/arm/mach-snapdragon/of_fixup.c @@ -30,6 +30,7 @@ #include #include #include +#include "qcom_fixup_handlers.h" /** * find_ssphy_node() - Find the super-speed PHY node referenced by DWC3 @@ -283,5 +284,86 @@ EVENT_SPY_FULL(EVT_OF_LIVE_BUILT, qcom_of_fixup_nodes); int ft_board_setup(void __maybe_unused *blob, struct bd_info __maybe_unused *bd) { + struct fdt_header *fdt = blob; + + ddrinfo_fixup_handler(fdt); + return 0; } + +int fixup_dt_node(void *fdt_ptr, int node_offset, + const char *property_name, + void *property_value, + enum fdt_fixup_type type) +{ + int ret; + + if ((!fdt_ptr || node_offset < 0) || + (!property_value && type != ADD_SUBNODE)) + return -1; + + switch (type) { + case APPEND_PROP_U32: + fdt_set_totalsize(fdt_ptr, + (fdt_totalsize(fdt_ptr) + + sizeof(struct fdt_property) + + strlen(property_name) + 3 + + sizeof(u32))); + ret = fdt_appendprop_u32(fdt_ptr, node_offset, + property_name, + *(u32 *)property_value); + break; + case APPEND_PROP_U64: + fdt_set_totalsize(fdt_ptr, + (fdt_totalsize(fdt_ptr) + + sizeof(struct fdt_property) + + strlen(property_name) + 3 + + sizeof(u64))); + ret = fdt_appendprop_u64(fdt_ptr, node_offset, + property_name, + *(u64 *)property_value); + break; + case SET_PROP_U32: + fdt_set_totalsize(fdt_ptr, + (fdt_totalsize(fdt_ptr) + + sizeof(struct fdt_property) + + strlen(property_name) + 3 + + sizeof(u32))); + ret = fdt_setprop_u32(fdt_ptr, node_offset, + property_name, + *(u32 *)property_value); + break; + case SET_PROP_U64: + fdt_set_totalsize(fdt_ptr, + (fdt_totalsize(fdt_ptr) + + sizeof(struct fdt_property) + + strlen(property_name) + 3 + + sizeof(u64))); + ret = fdt_setprop_u64(fdt_ptr, node_offset, + property_name, + *(u64 *)property_value); + break; + case SET_PROP_STRING: + fdt_set_totalsize(fdt_ptr, + (fdt_totalsize(fdt_ptr) + + sizeof(struct fdt_property) + + strlen(property_name) + 3 + + strlen((char *)property_value))); + ret = fdt_setprop_string(fdt_ptr, node_offset, + property_name, + (char *)property_value); + break; + case ADD_SUBNODE: + fdt_set_totalsize(fdt_ptr, + (fdt_totalsize(fdt_ptr) + + sizeof(struct fdt_property) + + strlen(property_name) + 3)); + ret = fdt_add_subnode(fdt_ptr, node_offset, + property_name); + break; + default: + ret = -1; + } + + return ret; +}