From: Peng Fan <[email protected]>

Current driver always programs the reset vector as 0. This works when
the Cortex‑M7 on i.MX95 executes from TCM, since the reset vector is
naturally located at address 0. However, when the firmware is loaded into
DDR, the reset vector must be set to the actual reset address instead of 0.

For the Cortex‑M33 Sync core on i.MX94, the CODE TCM base is also not 0,
so the correct reset vector must be passed to the SM API; otherwise the
M33 Sync core cannot boot successfully.

rproc_elf_get_boot_addr() returns the ELF entry point, which is not the
hardware reset vector address. To derive the proper reset vector, this
patch introduces imx_rproc_get_boot_addr(), which masks the ELF entry
point using the SoC‑specific 'reset_vector_mask'. The resulting reset
vector address is then passed to the appropriate SM CPU/LMM reset vector
API calls.

Signed-off-by: Peng Fan <[email protected]>
---
 drivers/remoteproc/imx_rproc.c | 17 ++++++++++++++---
 1 file changed, 14 insertions(+), 3 deletions(-)

diff --git a/drivers/remoteproc/imx_rproc.c b/drivers/remoteproc/imx_rproc.c
index 
0dd80e688b0ea3df4c66e5726884dc86c8a5a881..9b07103857b13018bdf62431cbfeffa3e3c1a15c
 100644
--- a/drivers/remoteproc/imx_rproc.c
+++ b/drivers/remoteproc/imx_rproc.c
@@ -124,6 +124,7 @@ struct imx_rproc {
        u32                             rsrc_id;        /* resource id */
        u32                             entry;          /* cpu start address */
        u32                             core_index;
+       u32                             reset_vector_mask;
        struct dev_pm_domain_list       *pd_list;
        const struct imx_rproc_plat_ops *ops;
        /*
@@ -345,7 +346,7 @@ static int imx_rproc_sm_cpu_start(struct rproc *rproc)
        const struct imx_rproc_dcfg *dcfg = priv->dcfg;
        int ret;
 
-       ret = scmi_imx_cpu_reset_vector_set(dcfg->cpuid, 0, true, false, false);
+       ret = scmi_imx_cpu_reset_vector_set(dcfg->cpuid, rproc->bootaddr, true, 
false, false);
        if (ret) {
                dev_err(priv->dev, "Failed to set reset vector cpuid(%u): 
%d\n", dcfg->cpuid, ret);
                return ret;
@@ -365,7 +366,7 @@ static int imx_rproc_sm_lmm_start(struct rproc *rproc)
         * If the remoteproc core can't start the M7, it will already be
         * handled in imx_rproc_sm_lmm_prepare().
         */
-       ret = scmi_imx_lmm_reset_vector_set(dcfg->lmid, dcfg->cpuid, 0, 0);
+       ret = scmi_imx_lmm_reset_vector_set(dcfg->lmid, dcfg->cpuid, 0, 
rproc->bootaddr);
        if (ret) {
                dev_err(dev, "Failed to set reset vector lmid(%u), cpuid(%u): 
%d\n",
                        dcfg->lmid, dcfg->cpuid, ret);
@@ -739,6 +740,13 @@ imx_rproc_elf_find_loaded_rsc_table(struct rproc *rproc, 
const struct firmware *
        return rproc_elf_find_loaded_rsc_table(rproc, fw);
 }
 
+static u64 imx_rproc_get_boot_addr(struct rproc *rproc, const struct firmware 
*fw)
+{
+       struct imx_rproc *priv = rproc->priv;
+
+       return rproc_elf_get_boot_addr(rproc, fw) & priv->reset_vector_mask;
+}
+
 static const struct rproc_ops imx_rproc_ops = {
        .prepare        = imx_rproc_prepare,
        .attach         = imx_rproc_attach,
@@ -752,7 +760,7 @@ static const struct rproc_ops imx_rproc_ops = {
        .find_loaded_rsc_table = imx_rproc_elf_find_loaded_rsc_table,
        .get_loaded_rsc_table = imx_rproc_get_loaded_rsc_table,
        .sanity_check   = rproc_elf_sanity_check,
-       .get_boot_addr  = rproc_elf_get_boot_addr,
+       .get_boot_addr  = imx_rproc_get_boot_addr,
 };
 
 static int imx_rproc_addr_init(struct imx_rproc *priv,
@@ -1244,6 +1252,9 @@ static int imx_rproc_probe(struct platform_device *pdev)
        priv->rproc = rproc;
        priv->dcfg = dcfg;
        priv->dev = dev;
+       priv->reset_vector_mask = GENMASK(31, 0);
+
+       of_property_read_u32(np, "fsl,reset-vector-mask", 
&priv->reset_vector_mask);
 
        if (dcfg->ops)
                priv->ops = dcfg->ops;

-- 
2.37.1


Reply via email to