From 276432faf710efefa6eaef553650b2dda62f8f07 Mon Sep 17 00:00:00 2001 From: Subrata Banik Date: Tue, 12 Aug 2025 22:02:41 +0530 Subject: [PATCH] soc/qualcomm/common: Add MMU configuration for fragmented DRAM regions Stating with Qualcomm X1P42100 SoC generation, the DRAM memory map is not expected to be contiguous (unlike previous generations) therefore, the memory map could be something like this. 1. Assume hardware design has 4GB of DRAM then the memory map would look like: - DDR_SPACE (2 GB) : 0x80000000 - 0x100000000 - DDR_SPACE_1 (2 GB) : 0x880000000 - 0x900000000 2. Assume hardware design has 16GB of DRAM then the memory map would look like: - DDR_SPACE (2 GB) : 0x80000000 - 0x100000000 - DDR_SPACE_1 (14 GB) : 0x880000000 - 0x400000000 3. Assume hardware design has 64GB of DRAM then the memory map would look like: - DDR_SPACE (2 GB) : 0x80000000 - 0x100000000 - DDR_SPACE_1 (30 GB) : 0x880000000 - 0x1000000000 - DDR_SPACE_2 (32 GB) : 0x8800000000 - 0x9000000000 This commit introduces logic to handle systems with fragmented DRAM configurations. Previously, the Memory Management Unit (MMU) was configured assuming a single, contiguous block of DRAM. This change extends the MMU setup to properly configure multiple, non-contiguous DRAM regions. The changes include: - Declaring dram_space_1 and dram_space_2 as optional regions, allowing the dynamic allocation for these DRAM ranges based on DRAM capacity of the platform. - Introduce `qc_get_soc_dram_space_config` function that takes care of DRAM based resource splitting as per `_dram`, `_dram_space_1` and `_dram_space_2` region limit. - Modifying qc_mmu_dram_config_post_dram_init() to check for these optional regions and configure them individually. This ensures all available DRAM is correctly mapped and accessible to the system. This approach improves flexibility and allows coreboot to support a wider range of Qualcomm platforms with different memory layouts. TEST=Able to boot google/quenbi to OS. Change-Id: If3788f4c77535f9a5e47ad2034ab9a8e0fe85b51 Signed-off-by: Subrata Banik Reviewed-on: https://review.coreboot.org/c/coreboot/+/88752 Reviewed-by: Kapil Porwal Tested-by: build bot (Jenkins) --- .../qualcomm/common/include/soc/mmu_common.h | 1 + .../common/include/soc/symbols_common.h | 8 +++ src/soc/qualcomm/common/mmu.c | 56 ++++++++++++++++++- 3 files changed, 62 insertions(+), 3 deletions(-) diff --git a/src/soc/qualcomm/common/include/soc/mmu_common.h b/src/soc/qualcomm/common/include/soc/mmu_common.h index 99a74116e0..1954c5db53 100644 --- a/src/soc/qualcomm/common/include/soc/mmu_common.h +++ b/src/soc/qualcomm/common/include/soc/mmu_common.h @@ -12,6 +12,7 @@ static struct region * const ddr_region = (struct region *)_ddr_information; +struct region *qc_get_soc_dram_space_config(size_t ddr_size, int *count); void soc_mmu_dram_config_post_dram_init(void); void qc_mmu_dram_config_post_dram_init(size_t ddr_size); bool soc_modem_carve_out(void **start, void **end); diff --git a/src/soc/qualcomm/common/include/soc/symbols_common.h b/src/soc/qualcomm/common/include/soc/symbols_common.h index 9d39db255e..caa1e7d174 100644 --- a/src/soc/qualcomm/common/include/soc/symbols_common.h +++ b/src/soc/qualcomm/common/include/soc/symbols_common.h @@ -32,4 +32,12 @@ DECLARE_REGION(dram_modem) DECLARE_REGION(dram_tz) DECLARE_REGION(dram_tz_rem) +/* + * DDR_SPACE (2 GB) aka `_dram`: 0x80000000 - 0x100000000 + * DDR_SPACE_1 (30 GB) aka `_dram_space_1`: 0x880000000 - 0x1000000000 + * DDR_SPACE_2 (480 GB) aka `dram_space_2`: 0x8800000000 - 0x10000000000 + */ +DECLARE_OPTIONAL_REGION(dram_space_1) +DECLARE_OPTIONAL_REGION(dram_space_2) + #endif // _SOC_QUALCOMM_SYMBOLS_COMMON_H_ diff --git a/src/soc/qualcomm/common/mmu.c b/src/soc/qualcomm/common/mmu.c index f87cebb47b..ff8d5dc98e 100644 --- a/src/soc/qualcomm/common/mmu.c +++ b/src/soc/qualcomm/common/mmu.c @@ -1,22 +1,72 @@ /* SPDX-License-Identifier: GPL-2.0-only */ #include +#include #include #include #include +/* DRAM region: DDR_SPACE, DDR_SPACE_1 and DDR_SPACE_2 */ +#define MAX_DRAM_SPACE_INDEX 3 + __weak bool soc_modem_carve_out(void **start, void **end) { return false; } +struct region *qc_get_soc_dram_space_config(size_t ddr_size, int *count) +{ + static struct region config[MAX_DRAM_SPACE_INDEX]; + static int populated_count = 0; + int i; + + if (!populated_count) { + void *region_start[MAX_DRAM_SPACE_INDEX] = { + _dram, + _dram_space_1, + _dram_space_2 + }; + size_t size[MAX_DRAM_SPACE_INDEX] = { + REGION_SIZE(dram), + REGION_SIZE(dram_space_1), + REGION_SIZE(dram_space_2) + }; + + /* Handle the case where DDR space is contiguous */ + if (!_edram) + size[0] = ddr_size; + + for (i = 0; i < MAX_DRAM_SPACE_INDEX && ddr_size > 0; i++) { + config[i].offset = (size_t)region_start[i]; + size_t to_map = MIN(ddr_size, size[i]); + config[i].size = to_map; + ddr_size -= to_map; + } + + populated_count = i; + + if (ddr_size) + printk(BIOS_CRIT, "Too much DRAM for available windows (%zu bytes left over)!\n", + ddr_size); + } + + *count = populated_count; + + return config; +} + void qc_mmu_dram_config_post_dram_init(size_t ddr_size) { void *start = NULL; void *end = NULL; - if (!soc_modem_carve_out(&start, &end)) { - mmu_config_range((void *)_dram, ddr_size, CACHED_RAM); - } else { + if (soc_modem_carve_out(&start, &end)) { + if (_dram_space_1) + die("Using carve out together with DRAM windows not supported"); mmu_config_range((void *)_dram, start - (void *)_dram, CACHED_RAM); mmu_config_range(end, (void *)_dram + ddr_size - end, CACHED_RAM); + } else { + int count; + struct region *config = qc_get_soc_dram_space_config(ddr_size, &count); + for (int i = 0; i < count; i++) + mmu_config_range((void *)config[i].offset, config[i].size, CACHED_RAM); } mmu_config_range((void *)_aop_code_ram, REGION_SIZE(aop_code_ram),