Hi Aswin, On Thu, 29 Jan 2026 at 11:48, Aswin Murugan <[email protected]> wrote: > > Add cached access functions for commonly used SMEM data to reduce > redundant SMEM lookups across the boot process.
What is SMEM? Could you add some mention of this in doc/board/qualcomm/ ? > > This patch introduces three generic caching functions: > - qcom_get_smem_device(): Cached SMEM device access > - qcom_get_socinfo(): Cached socinfo structure access > - qcom_get_ram_partitions(): Cached RAM partition table access > > The implementation includes new header files for data structures: > - include/soc/qcom/socinfo.h: Added socinfo header from Linux [1] > Provides socinfo structure definitions for SoC identification > and hardware parameters > - arch/arm/mach-snapdragon/rampart.h: Provides RAM partition table > structures for memory layout information > > The caching mechanism initializes SMEM data on first access and > returns cached pointers on subsequent calls, avoiding expensive > SMEM lookups during boot. This infrastructure is designed to be > reusable by other Qualcomm-specific features that require hardware > information from SMEM. > > The functions provide a clean API for accessing: > - SoC information (chip ID, version, platform details) > - RAM partition layout for memory size calculations > - Hardware parameters needed for device-specific configurations > > [1] > https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/include/linux/soc/qcom/socinfo.h?id=7dcc1dfaa3d1cd3aafed2beb7086ed34fdb22303 > > Signed-off-by: Aswin Murugan <[email protected]> > --- > arch/arm/mach-snapdragon/board.c | 92 +++++++++++ > arch/arm/mach-snapdragon/qcom-priv.h | 10 ++ > arch/arm/mach-snapdragon/rampart.h | 236 +++++++++++++++++++++++++++ > include/soc/qcom/socinfo.h | 114 +++++++++++++ > 4 files changed, 452 insertions(+) > create mode 100644 arch/arm/mach-snapdragon/rampart.h > create mode 100644 include/soc/qcom/socinfo.h > > diff --git a/arch/arm/mach-snapdragon/board.c > b/arch/arm/mach-snapdragon/board.c > index 5fb3240acc5..cbe2aaeba6e 100644 > --- a/arch/arm/mach-snapdragon/board.c > +++ b/arch/arm/mach-snapdragon/board.c > @@ -30,6 +30,7 @@ > #include <malloc.h> > #include <fdt_support.h> > #include <usb.h> > +#include <smem.h> > #include <sort.h> > #include <time.h> header order https://docs.u-boot.org/en/latest/develop/codingstyle.html#include-files > > @@ -39,6 +40,13 @@ DECLARE_GLOBAL_DATA_PTR; > > enum qcom_boot_source qcom_boot_source __section(".data") = 0; > > +/* SMEM cache structure */ > +static struct { > + struct udevice *smem_dev; > + struct socinfo *soc_info; > + struct usable_ram_partition_table *ram_partition_table; how about 'ram_part' as the name, since it is shorter? Please comment the struct too. > +} smem_cache; > + > static struct mm_region rbx_mem_map[CONFIG_NR_DRAM_BANKS + 2] = { { 0 } }; This should already be zero. Can you move this to device-private data? Then it can be allocated/freed by driver model. Perhaps you could just have smem_dev as a variable with the other two fields (from the above struct) kept in driver-private data? > > struct mm_region *mem_map = rbx_mem_map; > @@ -749,3 +757,87 @@ void enable_caches(void) > } > dcache_enable(); > } > + > +/** > + * qcom_get_smem_device() - Get cached SMEM device > + * > + * This function provides cached access to the SMEM device. > + * On first call, it initializes the SMEM device. > + * Subsequent calls return the cached pointer. > + * > + * Return: Pointer to SMEM device on success, NULL on failure > + */ > +struct udevice *qcom_get_smem_device(void) > +{ > + if (smem_cache.smem_dev) > + return smem_cache.smem_dev; > + > + if (uclass_get_device(UCLASS_SMEM, 0, &smem_cache.smem_dev)) { If there is only ever one, then uclass_first_device_err() > + log_err("Failed to get SMEM device\n"); > + return NULL; > + } > + > + return smem_cache.smem_dev; > +} > + > +/** > + * qcom_get_socinfo() - Get cached socinfo from SMEM > + * > + * This function provides cached access to the socinfo structure from SMEM. > + * On first call, it initializes the SMEM device and retrieves the socinfo. > + * Subsequent calls return the cached pointer. > + * > + * Return: Pointer to socinfo structure on success, NULL on failure > + */ > +struct socinfo *qcom_get_socinfo(void) > +{ > + size_t size; > + struct udevice *dev; > + > + if (smem_cache.soc_info) > + return smem_cache.soc_info; > + > + dev = qcom_get_smem_device(); > + if (!dev) > + return NULL; > + > + smem_cache.soc_info = smem_get(dev, 0, SMEM_HW_SW_BUILD_ID, &size); > + if (!smem_cache.soc_info) { > + log_err("Failed to get socinfo from SMEM\n"); > + return NULL; > + } > + > + return smem_cache.soc_info; > +} > + > +/** > + * qcom_get_ram_partitions() - Get cached RAM partition table from SMEM > + * > + * This function provides cached access to the RAM partition table from SMEM. > + * On first call, it retrieves the partition table from SMEM. > + * Subsequent calls return the cached pointer. > + * > + * Return: Pointer to RAM partition table on success, NULL on failure > + */ > +struct usable_ram_partition_table *qcom_get_ram_partitions(void) > +{ > + size_t size; > + struct udevice *dev; > + > + if (smem_cache.ram_partition_table) > + return smem_cache.ram_partition_table; > + > + dev = qcom_get_smem_device(); > + if (!dev) > + return NULL; > + > + smem_cache.ram_partition_table = smem_get(dev, 0, > + > SMEM_USABLE_RAM_PARTITION_TABLE, > + &size); > + if (!smem_cache.ram_partition_table) { > + log_err("Failed to get RAM partition table from SMEM\n"); > + return NULL; > + } > + > + return smem_cache.ram_partition_table; > +} > diff --git a/arch/arm/mach-snapdragon/qcom-priv.h > b/arch/arm/mach-snapdragon/qcom-priv.h > index b8bf574e8bb..ca1363514ae 100644 > --- a/arch/arm/mach-snapdragon/qcom-priv.h > +++ b/arch/arm/mach-snapdragon/qcom-priv.h > @@ -3,6 +3,9 @@ > #ifndef __QCOM_PRIV_H__ > #define __QCOM_PRIV_H__ > > +#include <soc/qcom/socinfo.h> > +#include "rampart.h" > + > /** > * enum qcom_boot_source - Track where we got loaded from. > * Used for capsule update logic. > @@ -17,6 +20,13 @@ enum qcom_boot_source { > > extern enum qcom_boot_source qcom_boot_source; > > +/* > + * SMEM Cache API - Provides cached access to SMEM data structures > + */ > +struct udevice *qcom_get_smem_device(void); > +struct socinfo *qcom_get_socinfo(void); > +struct usable_ram_partition_table *qcom_get_ram_partitions(void); comments > + > #if IS_ENABLED(CONFIG_EFI_HAVE_CAPSULE_SUPPORT) > void qcom_configure_capsule_updates(void); > #else > diff --git a/arch/arm/mach-snapdragon/rampart.h > b/arch/arm/mach-snapdragon/rampart.h > new file mode 100644 > index 00000000000..cfddaca0d5f > --- /dev/null > +++ b/arch/arm/mach-snapdragon/rampart.h > @@ -0,0 +1,236 @@ > +// SPDX-License-Identifier: GPL-2.0 > +/* > + * RAM partition table definitions > + * > + * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. > + * > + */ > + > +#define SMEM_USABLE_RAM_PARTITION_TABLE 402 > + > +#define RAM_PARTITION_H_MAJOR 03 > +#define RAM_PARTITION_H_MINOR 00 > + > +typedef u8 uint8; > +typedef u32 uint32; > +typedef u64 uint64; We already have these definitions - see asm-generic/int-ll64.h > + > +/** > + * Total length of zero filled name string. This is not a C > + * string, as it can occupy the total number of bytes, and if > + * it does, it does not require a zero terminator. It cannot > + * be manipulated with standard string handling library functions. > + */ > +#define RAM_PART_NAME_LENGTH 16 > + > +/** > + * Number of RAM partition entries which are usable by APPS. > + */ > +#define RAM_NUM_PART_ENTRIES 32 > + > +/** > + * @name: Magic numbers > + * Used in identifying valid RAM partition table. > + */ > +#define RAM_PART_MAGIC1 0x9DA5E0A8 > +#define RAM_PART_MAGIC2 0xAF9EC4E2 lower-case hex (please fix throughout0 > + > +/** > + * Must increment this version number whenever RAM structure of > + * RAM partition table changes. > + */ > +#define RAM_PARTITION_VERSION 0x3 > + > +/** > + * Value which indicates the partition can grow to fill the > + * rest of RAM. Must only be used on the last partition. > + */ > +#define RAM_PARTITION_GROW 0xFFFFFFFF > + > +/** > + * RAM partition API return types. > + */ > +enum ram_partition_return_type { > + RAM_PART_SUCCESS = 0, /* Successful return from API */ > + RAM_PART_NULL_PTR_ERR, /* Partition table/entry null > pointer */ > + RAM_PART_OUT_OF_BOUND_PTR_ERR, /* Partition table pointer is not > in SMEM */ > + RAM_PART_TABLE_EMPTY_ERR, /* Trying to delete entry from > empty table */ > + RAM_PART_TABLE_FULL_ERR, /* Trying to add entry to full > table */ > + RAM_PART_CATEGORY_NOT_EXIST_ERR, /* Partition doesn't belong to any > memory category */ > + RAM_PART_OTHER_ERR, /* Unknown error */ > + RAM_PART_RETURN_MAX_SIZE = 0x7FFFFFFF > +}; > + > +/** > + * RAM partition attributes. > + */ > +enum ram_partition_attribute_t { > + RAM_PARTITION_DEFAULT_ATTRB = ~0, /* No specific attribute > definition */ > + RAM_PARTITION_READ_ONLY = 0, /* Read-only RAM partition */ > + RAM_PARTITION_READWRITE, /* Read/write RAM partition */ > + RAM_PARTITION_ATTRIBUTE_MAX_SIZE = 0x7FFFFFFF > +}; > + > +/** > + * RAM partition categories. > + */ > +enum ram_partition_category_t { > + RAM_PARTITION_DEFAULT_CATEGORY = ~0, /* No specific category > definition */ > + RAM_PARTITION_IRAM = 4, /* IRAM RAM partition */ > + RAM_PARTITION_IMEM = 5, /* IMEM RAM partition */ > + RAM_PARTITION_SDRAM = 14, /* SDRAM type without > specific bus information**/ > + RAM_PARTITION_CATEGORY_MAX_SIZE = 0x7FFFFFFF > +}; > + > +/** > + * RAM Partition domains. > + * @note: For shared RAM partition, domain value would be 0b11:\n > + * RAM_PARTITION_APPS_DOMAIN | RAM_PARTITION_MODEM_DOMAIN. > + */ > +enum ram_partition_domain_t { > + RAM_PARTITION_DEFAULT_DOMAIN = 0, /* 0b00: No specific domain > definition */ > + RAM_PARTITION_APPS_DOMAIN = 1, /* 0b01: APPS RAM partition */ > + RAM_PARTITION_MODEM_DOMAIN = 2, /* 0b10: MODEM RAM partition */ > + RAM_PARTITION_DOMAIN_MAX_SIZE = 0x7FFFFFFF > +}; > + > +/** > + * RAM Partition types. > + * @note: The RAM_PARTITION_SYS_MEMORY type represents DDR rams that are > attached > + * to the current system. > + */ > +enum ram_partition_type_t { > + RAM_PARTITION_SYS_MEMORY = 1, /* system memory */ > + RAM_PARTITION_BOOT_REGION_MEMORY1, /* boot loader memory 1 */ > + RAM_PARTITION_BOOT_REGION_MEMORY2, /* boot loader memory 2, > reserved */ > + RAM_PARTITION_APPSBL_MEMORY, /* apps boot loader memory */ > + RAM_PARTITION_APPS_MEMORY, /* apps usage memory */ > + RAM_PARTITION_TOOLS_FV_MEMORY, /* tools usage memory */ > + RAM_PARTITION_QUANTUM_FV_MEMORY, /* quantum usage memory */ > + RAM_PARTITION_QUEST_FV_MEMORY, /* quest usage memory */ > + RAM_PARTITION_TYPE_MAX_SIZE = 0x7FFFFFFF > +}; > + > +/** > + * @brief: Holds information for an entry in the RAM partition table. > + */ > +struct ram_partition_entry { > + char name[RAM_PART_NAME_LENGTH]; /* Partition name, unused for now */ > + uint64 start_address; /* Partition start address in RAM */ > + uint64 length; /* Partition length in RAM in Bytes > */ > + uint32 partition_attribute; /* Partition attribute */ > + uint32 partition_category; /* Partition category */ > + uint32 partition_domain; /* Partition domain */ > + uint32 partition_type; /* Partition type */ > + uint32 num_partitions; /* Number of partitions on device */ > + uint32 hw_info; /* hw information such as type and > frequency */ > + uint8 highest_bank_bit; /* Highest bit corresponding to a > bank */ > + uint8 reserve0; /* Reserved for future use */ > + uint8 reserve1; /* Reserved for future use */ > + uint8 reserve2; /* Reserved for future use */ > + uint32 min_pasr_size; /* Minimum PASR size in MB */ > + uint64 available_length; /* Available Partition length in > RAM in Bytes */ > +}; > + > +/** > + * @brief: Defines the RAM partition table structure > + * @note: No matter how you change the structure, do not change the > placement of the > + * first four elements so that future compatibility will always be guaranteed > + * at least for the identifiers. > + * > + * @note: The other portion of the structure may be changed as necessary to > accommodate > + * new features. Be sure to increment version number if you change it. > + */ > +struct usable_ram_partition_table { > + uint32 magic1; /* Magic number to identify valid RAM > partition table */ > + uint32 magic2; /* Magic number to identify valid RAM > partition table */ > + uint32 version; /* Version number to track structure > definition changes */ > + uint32 reserved1; /* Reserved for future use */ > + > + uint32 num_partitions; /* Number of RAM partition table entries */ > + > + uint32 reserved2; /* Added for 8 bytes alignment of header */ > + > + /* RAM partition table entries */ > + struct ram_partition_entry ram_part_entry[RAM_NUM_PART_ENTRIES]; > +}; > + > +/** > + * Version 1 structure 32 Bit > + * @brief: Holds information for an entry in the RAM partition table. > + */ > +struct ram_partition_entry_v1 { > + char name[RAM_PART_NAME_LENGTH]; /* Partition name, unused for now */ > + uint64 start_address; /* Partition start address in RAM */ > + uint64 length; /* Partition length in RAM in Bytes > */ > + uint32 partition_attribute; /* Partition attribute */ > + uint32 partition_category; /* Partition category */ > + uint32 partition_domain; /* Partition domain */ > + uint32 partition_type; /* Partition type */ > + uint32 num_partitions; /* Number of partitions on device */ > + uint32 hw_info; /* hw information such as type and > frequency */ > + uint32 reserved4; /* Reserved for future use */ > + uint32 reserved5; /* Reserved for future use */ > +}; > + > +/** > + * @brief: Defines the RAM partition table structure > + * @note: No matter how you change the structure, do not change the > placement of the > + * first four elements so that future compatibility will always be guaranteed > + * at least for the identifiers. > + * > + * @note: The other portion of the structure may be changed as necessary to > accommodate > + * new features. Be sure to increment version number if you change it. > + */ > +struct usable_ram_partition_table_v1 { > + uint32 magic1; /* Magic number to identify valid RAM > partition table */ > + uint32 magic2; /* Magic number to identify valid RAM > partition table */ > + uint32 version; /* Version number to track structure > definition changes */ > + uint32 reserved1; /* Reserved for future use */ > + > + uint32 num_partitions; /* Number of RAM partition table entries */ > + > + uint32 reserved2; /* Added for 8 bytes alignment of header */ > + > + /* RAM partition table entries */ > + struct ram_partition_entry_v1 ram_part_entry_v1[RAM_NUM_PART_ENTRIES]; > +}; > + > +/** > + * Version 0 structure 32 Bit > + * @brief: Holds information for an entry in the RAM partition table. > + */ > +struct ram_partition_entry_v0 { > + char name[RAM_PART_NAME_LENGTH]; /* Partition name, unused for now */ > + uint32 start_address; /* Partition start address in RAM */ > + uint32 length; /* Partition length in RAM in Bytes > */ > + uint32 partition_attribute; /* Partition attribute */ > + uint32 partition_category; /* Partition category */ > + uint32 partition_domain; /* Partition domain */ > + uint32 partition_type; /* Partition type */ > + uint32 num_partitions; /* Number of partitions on device */ > + uint32 reserved3; /* Reserved for future use */ > + uint32 reserved4; /* Reserved for future use */ > + uint32 reserved5; /* Reserved for future use */ > +}; > + > +/** > + * @brief: Defines the RAM partition table structure > + * @note: No matter how you change the structure, do not change the > placement of the > + * first four elements so that future compatibility will always be guaranteed > + * at least for the identifiers. > + * > + * @note: The other portion of the structure may be changed as necessary to > accommodate > + * new features. Be sure to increment version number if you change it. > + */ Is this actually kerneldoc? We don't normally use @brief etc. > +struct usable_ram_partition_table_v0 { > + uint32 magic1; /* Magic number to identify valid RAM > partition table */ > + uint32 magic2; /* Magic number to identify valid RAM > partition table */ > + uint32 version; /* Version number to track structure > definition changes */ > + uint32 reserved1; /* Reserved for future use */ > + > + uint32 num_partitions; /* Number of RAM partition table entries */ > + > + /* RAM partition table entries */ > + struct ram_partition_entry_v0 ram_part_entry_v0[RAM_NUM_PART_ENTRIES]; very long identifiers! > +}; > diff --git a/include/soc/qcom/socinfo.h b/include/soc/qcom/socinfo.h > new file mode 100644 > index 00000000000..1bb6e200e1f > --- /dev/null > +++ b/include/soc/qcom/socinfo.h > @@ -0,0 +1,114 @@ > +/* SPDX-License-Identifier: GPL-2.0 */ > +/* > + * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. > + */ > + > +#ifndef __QCOM_SOCINFO_H__ > +#define __QCOM_SOCINFO_H__ > + > +#include <linux/types.h> > + > +/* > + * SMEM item id, used to acquire handles to respective > + * SMEM region. > + */ > +#define SMEM_HW_SW_BUILD_ID 137 > + > +#define SMEM_SOCINFO_BUILD_ID_LENGTH 32 > +#define SMEM_SOCINFO_CHIP_ID_LENGTH 32 > + > +/* > + * SoC version type with major number in the upper 16 bits and minor > + * number in the lower 16 bits. > + */ > +#define SOCINFO_MAJOR(ver) (((ver) >> 16) & 0xffff) > +#define SOCINFO_MINOR(ver) ((ver) & 0xffff) > +#define SOCINFO_VERSION(maj, min) ((((maj) & 0xffff) << 16) | ((min) & > 0xffff)) > + > +/* Socinfo SMEM item structure */ > +struct socinfo { > + __le32 fmt; > + __le32 id; > + __le32 ver; > + char build_id[SMEM_SOCINFO_BUILD_ID_LENGTH]; > + /* Version 2 */ > + __le32 raw_id; > + __le32 raw_ver; > + /* Version 3 */ > + __le32 hw_plat; > + /* Version 4 */ > + __le32 plat_ver; > + /* Version 5 */ > + __le32 accessory_chip; > + /* Version 6 */ > + __le32 hw_plat_subtype; > + /* Version 7 */ > + __le32 pmic_model; > + __le32 pmic_die_rev; > + /* Version 8 */ > + __le32 pmic_model_1; > + __le32 pmic_die_rev_1; > + __le32 pmic_model_2; > + __le32 pmic_die_rev_2; > + /* Version 9 */ > + __le32 foundry_id; > + /* Version 10 */ > + __le32 serial_num; > + /* Version 11 */ > + __le32 num_pmics; > + __le32 pmic_array_offset; > + /* Version 12 */ > + __le32 chip_family; > + __le32 raw_device_family; > + __le32 raw_device_num; > + /* Version 13 */ > + __le32 nproduct_id; > + char chip_id[SMEM_SOCINFO_CHIP_ID_LENGTH]; > + /* Version 14 */ > + __le32 num_clusters; > + __le32 ncluster_array_offset; > + __le32 num_subset_parts; > + __le32 nsubset_parts_array_offset; > + /* Version 15 */ > + __le32 nmodem_supported; > + /* Version 16 */ > + __le32 feature_code; > + __le32 pcode; > + __le32 npartnamemap_offset; > + __le32 nnum_partname_mapping; > + /* Version 17 */ > + __le32 oem_variant; > + /* Version 18 */ > + __le32 num_kvps; > + __le32 kvps_offset; > + /* Version 19 */ > + __le32 num_func_clusters; > + __le32 boot_cluster; > + __le32 boot_core; > +}; > + > +/* Internal feature codes */ > +enum qcom_socinfo_feature_code { > + /* External feature codes */ > + SOCINFO_FC_UNKNOWN = 0x0, > + SOCINFO_FC_AA, > + SOCINFO_FC_AB, > + SOCINFO_FC_AC, > + SOCINFO_FC_AD, > + SOCINFO_FC_AE, > + SOCINFO_FC_AF, > + SOCINFO_FC_AG, > + SOCINFO_FC_AH, > +}; Do these values have any meaning, or are they documented somewhere? > + > +/* Internal feature codes */ > +/* Valid values: 0 <= n <= 0xf */ > +#define SOCINFO_FC_Yn(n) (0xf1 + (n)) > +#define SOCINFO_FC_INT_MAX SOCINFO_FC_Yn(0xf) > + > +/* Product codes */ > +#define SOCINFO_PC_UNKNOWN 0 > +#define SOCINFO_PCn(n) ((n) + 1) > +#define SOCINFO_PC_RESERVE (BIT(31) - 1) > + > +#endif > -- > 2.34.1 > Regards, Simon

