imx9: scmi: Get DDR size through SM SCMI API

System Manager(SM) has implemented the MISC protocol to retrieve DDR
information. Using this API, U-Boot can obtain the DDR size dynamically
instead of relying on static configuration macros.

This change addresses the DDR ECC enabled case, where 1/8 of the total
DDR size is reserved for ECC data. The scmi_misc_ddrinfo() returns the
DDR size with EEC overhead already deducted.

Implementation details:
- Query the DDR size via scmi_misc_ddrinfo()
- Replace direct REG_DDR_CS[0,1]_BNDS register reads with SCMI call
- Switch from PHYS_SDRAM[x]_SIZE macros to runtime detection
- For backward compatibility with older SM firmware, fall back to
  static PHYS_SDRAM[x]_SIZE configuration if the SCMI call fails

Signed-off-by: Ye Li <ye.li@nxp.com>
Signed-off-by: Alice Guo <alice.guo@nxp.com>
Reviewed-by: Peng Fan <peng.fan@nxp.com>
This commit is contained in:
Ye Li
2026-03-02 13:20:02 +08:00
committed by Fabio Estevam
parent a27980786c
commit e1cc7117b6
3 changed files with 99 additions and 14 deletions

View File

@@ -254,6 +254,43 @@ struct scmi_rom_passover_get_out {
u32 passover[(sizeof(rom_passover_t) + 8) / 4];
};
/**
* struct scmi_ddr_info_out - Get DDR memory region info
* @status: Error code
* @attributes: Region attributes:
* Bit[31] ECC enable.
* Set to 1 if ECC enabled.
* Set to 0 if ECC disabled or not configured.
* Bits[30:18] Reserved, must be zero.
* Bits[17:16] Number of DDR memory regions.
* Bits[15:11] Reserved, must be zero.
* Bits[10:8] Width.
* Bus width is 16 << this field.
* So 0=16, 1=32, 2=64, etc.
* Bits[7:5] Reserved, must be zero.
* Bits[4:0] DDR type.
* Set to 0 if LPDDR5.
* Set to 1 if LPDDR5X.
* Set to 2 if LPDDR4.
* Set to 3 if LPDDR4X
* @mts: DDR speed in megatransfers per second
* @startlow: The lower 32 bits of the physical start address of the region
* @starthigh: The upper 32 bits of the physical start address of the region
* @endlow: The lower 32 bits of the physical end address of the region. This
* excludes any DDR used to store ECC data
* @endhigh: The upper 32 bits of the physical end address of the region. This
* excludes any DDR used to store ECC data
*/
struct scmi_ddr_info_out {
s32 status;
u32 attributes;
u32 mts;
u32 startlow;
u32 starthigh;
u32 endlow;
u32 endhigh;
};
#endif
/* For i.MX ULP */

View File

@@ -58,6 +58,34 @@ uint32_t scmi_get_rom_data(rom_passover_t *rom_data)
return 0;
}
int scmi_misc_ddrinfo(u32 ddrc_id, struct scmi_ddr_info_out *out)
{
u32 in = ddrc_id;
struct scmi_msg msg = {
.protocol_id = SCMI_PROTOCOL_ID_IMX_MISC,
.message_id = SCMI_MISC_DDR_INFO_GET,
.in_msg = (u8 *)&in,
.in_msg_sz = sizeof(in),
.out_msg = (u8 *)out,
.out_msg_sz = sizeof(*out),
};
int ret;
struct udevice *dev;
ret = uclass_get_device_by_name(UCLASS_CLK, "protocol@14", &dev);
if (ret)
return ret;
ret = devm_scmi_process_msg(dev, &msg);
if (ret != 0 || out->status != 0) {
printf("Failed to get ddr cfg, scmi_err = %d\n",
out->status);
return -EINVAL;
}
return 0;
}
#if IS_ENABLED(CONFIG_ENV_IS_IN_MMC)
__weak int board_mmc_get_env_dev(int devno)
{
@@ -335,25 +363,44 @@ void enable_caches(void)
__weak int board_phys_sdram_size(phys_size_t *size)
{
struct scmi_ddr_info_out ddr_info = {0};
int ret;
u32 ddrc_id = 0, ddrc_num = 1;
phys_size_t start, end;
phys_size_t val;
if (!size)
return -EINVAL;
val = readl(REG_DDR_CS0_BNDS);
start = (val >> 16) << 24;
end = (val & 0xFFFF);
end = end ? end + 1 : 0;
end = end << 24;
*size = end - start;
*size = 0;
do {
ret = scmi_misc_ddrinfo(ddrc_id++, &ddr_info);
if (ret) {
/* if get DDR info failed, fall to default config */
*size = PHYS_SDRAM_SIZE;
#ifdef PHYS_SDRAM_2_SIZE
*size += PHYS_SDRAM_2_SIZE;
#endif
return 0;
} else {
ddrc_num = ((ddr_info.attributes >> 16) & 0x3);
start = ddr_info.starthigh;
start <<= 32;
start += ddr_info.startlow;
val = readl(REG_DDR_CS1_BNDS);
start = (val >> 16) << 24;
end = (val & 0xFFFF);
end = end ? end + 1 : 0;
end = end << 24;
*size += end - start;
end = ddr_info.endhigh;
end <<= 32;
end += ddr_info.endlow;
*size += end + 1 - start;
debug("ddr info attr 0x%x, start 0x%x 0x%x, end 0x%x 0x%x, mts %u\n",
ddr_info.attributes, ddr_info.starthigh, ddr_info.startlow,
ddr_info.endhigh, ddr_info.endlow, ddr_info.mts);
}
} while (ddrc_id < ddrc_num);
/* SM reports total DDR size, need remove secure memory */
*size -= PHYS_SDRAM - 0x80000000;
return 0;
}

View File

@@ -54,7 +54,8 @@ enum scmi_discovery_id {
};
enum scmi_imx_misc_message_id {
SCMI_MISC_ROM_PASSOVER_GET = 0x7
SCMI_MISC_ROM_PASSOVER_GET = 0x7,
SCMI_MISC_DDR_INFO_GET = 0x22,
};
/*