
Hi, Bryan,
On 23/10/24 20:09, Bryan Brattlof wrote:
On October 21, 2024 thus sayeth Santhosh Kumar K:
As R5 is a 32 bit processor, the RAM banks' base and size calculation is restricted to 32 bits, which results in wrong values if bank's base is greater than 32 bits or bank's size is greater than or equal to 4GB.
So, add k3_ddrss_ddr_bank_base_size_calc() to get the base address and size of RAM's banks from the device tree memory node, and store in a 64 bit device private data which can be used for ECC reserved memory calculation, Setting ECC range and Fixing up bank size in device tree when ECC is enabled.
Signed-off-by: Santhosh Kumar K s-k6@ti.com
drivers/ram/k3-ddrss/k3-ddrss.c | 72 ++++++++++++++++++++++++++------- 1 file changed, 57 insertions(+), 15 deletions(-)
diff --git a/drivers/ram/k3-ddrss/k3-ddrss.c b/drivers/ram/k3-ddrss/k3-ddrss.c index f2ab8cf2b49b..bd6783ebc2cd 100644 --- a/drivers/ram/k3-ddrss/k3-ddrss.c +++ b/drivers/ram/k3-ddrss/k3-ddrss.c @@ -147,6 +147,9 @@ struct k3_ddrss_desc { struct k3_ddrss_ecc_region ecc_regions[K3_DDRSS_MAX_ECC_REGIONS]; u64 ecc_reserved_space; bool ti_ecc_enabled;
- unsigned long long ddr_bank_base[CONFIG_NR_DRAM_BANKS];
- unsigned long long ddr_bank_size[CONFIG_NR_DRAM_BANKS];
- unsigned long long ddr_ram_size;
Should we use the u64 typedef here?
Yes, I'll replace.
};
struct reginitdata { @@ -668,11 +671,54 @@ static void k3_ddrss_lpddr4_preload_full_mem(struct k3_ddrss_desc *ddrss, printf("ECC: priming DDR completed in %lu msec\n", get_timer(done)); }
+static void k3_ddrss_ddr_bank_base_size_calc(struct k3_ddrss_desc *ddrss) +{
- int bank, na, ns, len, parent;
- const fdt32_t *ptr, *end;
- for (bank = 0; bank < CONFIG_NR_DRAM_BANKS; bank++) {
ddrss->ddr_bank_base[bank] = 0;
ddrss->ddr_bank_size[bank] = 0;
- }
- ofnode mem = ofnode_null();
- do {
mem = ofnode_by_prop_value(mem, "device_type", "memory", 7);
- } while (!ofnode_is_enabled(mem));
- const void *fdt = ofnode_to_fdt(mem);
- int node = ofnode_to_offset(mem);
- const char *property = "reg";
- parent = fdt_parent_offset(fdt, node);
- na = fdt_address_cells(fdt, parent);
- ns = fdt_size_cells(fdt, parent);
- ptr = fdt_getprop(fdt, node, property, &len);
- end = ptr + len / sizeof(*ptr);
- for (bank = 0; bank < CONFIG_NR_DRAM_BANKS; bank++) {
if (ptr + na + ns <= end) {
if (CONFIG_IS_ENABLED(OF_TRANSLATE))
ddrss->ddr_bank_base[bank] = fdt_translate_address(fdt, node, ptr);
else
ddrss->ddr_bank_base[bank] = fdtdec_get_number(ptr, na);
ddrss->ddr_bank_size[bank] = fdtdec_get_number(&ptr[na], ns);
}
ptr += na + ns;
- }
- for (bank = 0; bank < CONFIG_NR_DRAM_BANKS; bank++)
ddrss->ddr_ram_size += ddrss->ddr_bank_size[bank];
+}
- static void k3_ddrss_lpddr4_ecc_calc_reserved_mem(struct k3_ddrss_desc *ddrss) { fdtdec_setup_mem_size_base_lowest();
- ddrss->ecc_reserved_space = gd->ram_size;
ddrss->ecc_reserved_space = ddrss->ddr_ram_size; do_div(ddrss->ecc_reserved_space, 9);
/* Round to clean number */
@@ -696,7 +742,7 @@ static void k3_ddrss_lpddr4_ecc_init(struct k3_ddrss_desc *ddrss) /* Preload the full memory with 0's using the BIST engine of * the LPDDR4 controller. */
- k3_ddrss_lpddr4_preload_full_mem(ddrss, gd->ram_size, 0);
k3_ddrss_lpddr4_preload_full_mem(ddrss, ddrss->ddr_ram_size, 0);
/* Clear Error Count Register */ writel(0x1, base + DDRSS_ECC_1B_ERR_CNT_REG);
@@ -741,6 +787,8 @@ static int k3_ddrss_probe(struct udevice *dev)
k3_lpddr4_start(ddrss);
- k3_ddrss_ddr_bank_base_size_calc(ddrss);
- if (ddrss->ti_ecc_enabled) { if (!ddrss->ddrss_ss_cfg) { printf("%s: ss_cfg is required if ecc is enabled but not provided.",
@@ -761,30 +809,24 @@ static int k3_ddrss_probe(struct udevice *dev)
int k3_ddrss_ddr_fdt_fixup(struct udevice *dev, void *blob, struct bd_info *bd) {
- struct k3_ddrss_desc *ddrss = dev_get_priv(dev);
- u64 start[CONFIG_NR_DRAM_BANKS];
- u64 size[CONFIG_NR_DRAM_BANKS]; int bank;
struct k3_ddrss_desc *ddrss = dev_get_priv(dev);
if (ddrss->ecc_reserved_space == 0) return 0;
for (bank = CONFIG_NR_DRAM_BANKS - 1; bank >= 0; bank--) {
if (ddrss->ecc_reserved_space > bd->bi_dram[bank].size) {
ddrss->ecc_reserved_space -= bd->bi_dram[bank].size;
bd->bi_dram[bank].size = 0;
if (ddrss->ecc_reserved_space > ddrss->ddr_bank_size[bank]) {
ddrss->ecc_reserved_space -= ddrss->ddr_bank_size[bank];
} else {ddrss->ddr_bank_size[bank] = 0;
bd->bi_dram[bank].size -= ddrss->ecc_reserved_space;
} }ddrss->ddr_bank_size[bank] -= ddrss->ecc_reserved_space; break;
- for (bank = 0; bank < CONFIG_NR_DRAM_BANKS; bank++) {
start[bank] = bd->bi_dram[bank].start;
size[bank] = bd->bi_dram[bank].size;
- }
- return fdt_fixup_memory_banks(blob, start, size, CONFIG_NR_DRAM_BANKS);
- return fdt_fixup_memory_banks(blob, ddrss->ddr_bank_base,
}ddrss->ddr_bank_size, CONFIG_NR_DRAM_BANKS);
Have we looked into passing this information via the global data pointer rather than fixing up the device tree on each boot phase?
https://patchwork.ozlabs.org/project/uboot/patch/20180926215520.87168-23-sjg@chromium.org/
I don't see a clear path to pass GD from SPL to SPL but there is a TPL to SPL which I think we should be able to copy.
At R5, the phys_addr_t is 32 bits - so, can't store more than 4GB in global data pointer.
Even in the above series you shared, handoff_save_dram() saves the RAM and banks' size from global data only.
Hence, the fix-up is necessary to pass information from R5 SPL to A53 SPL.
Regards, Santhosh.
~Bryan