The existing approach does not account for interleaving in the DDRs when
setting up regions. There is support for MSMC to calculate the regions
for each DDR, so modify k3_ddrss_probe to set the regions accordingly
for multi-DDR systems.

Signed-off-by: Neha Malcom Francis <n-fran...@ti.com>
---
 drivers/ram/k3-ddrss/k3-ddrss.c | 43 +++++++++++++++++++++++++++++++--
 1 file changed, 41 insertions(+), 2 deletions(-)

diff --git a/drivers/ram/k3-ddrss/k3-ddrss.c b/drivers/ram/k3-ddrss/k3-ddrss.c
index 205dce51799..8429dddeb58 100644
--- a/drivers/ram/k3-ddrss/k3-ddrss.c
+++ b/drivers/ram/k3-ddrss/k3-ddrss.c
@@ -808,8 +808,10 @@ static int k3_ddrss_probe(struct udevice *dev)
        u64 end;
        int ret;
        struct k3_ddrss_desc *ddrss = dev_get_priv(dev);
+       __maybe_unused u32 inst, ddr_ram_size, ecc_res;
        __maybe_unused struct k3_ddrss_data *ddrss_data = (struct k3_ddrss_data 
*)dev_get_driver_data(dev);
        __maybe_unused struct k3_ddrss_ecc_region *range = &ddrss->ecc_range;
+       __maybe_unused struct k3_msmc *msmc_parent = NULL;
 
        debug("%s(dev=%p)\n", __func__, dev);
 
@@ -863,14 +865,51 @@ static int k3_ddrss_probe(struct udevice *dev)
                        ddrss->ecc_range.range = range->range;
                }
 
+#if !CONFIG_IS_ENABLED(K3_MULTI_DDR)
                end = ddrss->ecc_range.start + ddrss->ecc_range.range;
+               inst = ddrss->instance;
+               ddr_ram_size = ddrss->ddr_ram_size;
+               ecc_res = ddrss->ecc_reserved_space;
 
-               if (end > (ddrss->ddr_ram_size - ddrss->ecc_reserved_space))
-                       ddrss->ecc_regions[0].range = ddrss->ddr_ram_size - 
ddrss->ecc_reserved_space;
+               if (end > (ddr_ram_size - ecc_res))
+                       ddrss->ecc_regions[0].range = ddr_ram_size - ecc_res;
                else
                        ddrss->ecc_regions[0].range = ddrss->ecc_range.range;
 
                ddrss->ecc_regions[0].start = ddrss->ecc_range.start - 
ddrss->ddr_bank_base[0];
+#else
+
+               /* In case multi-DDR, we rely on MSMC's calculation of regions 
for each DDR */
+               msmc_parent = kzalloc(sizeof(msmc_parent), GFP_KERNEL);
+               if (!msmc_parent) {
+                       debug("%s: failed to allocate msmc_parent\n", __func__);
+                       return -ENOMEM;
+               }
+               msmc_parent = dev_get_priv(dev->parent);
+               if (!msmc_parent) {
+                       printf("%s: could not get MSMC parent to set up inline 
ECC regions\n",
+                              __func__);
+                       kfree(msmc_parent);
+                       return -EINVAL;
+               }
+
+               if (msmc_parent->R0[0].start < 0) {
+                       /* Configure entire DDR space by default */
+                       ddrss->ecc_regions[0].start = ddrss->ddr_bank_base[0];
+                       ddrss->ecc_regions[0].range = ddr_ram_size - ecc_res;
+               } else {
+                       end = msmc_parent->R0[inst].start + 
msmc_parent->R0[inst].range;
+
+                       if (end > (ddr_ram_size - ecc_res))
+                               ddrss->ecc_regions[0].range = ddr_ram_size - 
ecc_res;
+                       else
+                               ddrss->ecc_regions[0].range = 
msmc_parent->R0[inst].range;
+
+                       ddrss->ecc_regions[0].start =  
msmc_parent->R0[inst].start;
+               }
+
+               kfree(msmc_parent);
+#endif
 
                k3_ddrss_lpddr4_ecc_init(ddrss);
        }
-- 
2.34.1

Reply via email to