mirror of
https://source.denx.de/u-boot/u-boot.git
synced 2026-06-02 09:46:37 +03:00
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:
@@ -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 */
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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,
|
||||
};
|
||||
|
||||
/*
|
||||
|
||||
Reference in New Issue
Block a user