On Fri, Mar 27, 2026 at 10:42:03AM +0800, Peng Fan (OSS) wrote: > From: Peng Fan <[email protected]> > > Cortex-M[7,33] processors use a fixed reset vector table format: > > 0x00 Initial SP value > 0x04 Reset vector > 0x08 NMI > 0x0C ... > ... > IRQ[n] > > In ELF images, the corresponding layout is: > > reset_vectors: --> hardware reset address > .word __stack_end__ > .word Reset_Handler > .word NMI_Handler > .word HardFault_Handler > ... > .word UART_IRQHandler > .word SPI_IRQHandler > ... > > Reset_Handler: --> ELF entry point address > ... > > The hardware fetches the first two words from reset_vectors and populates > SP with __stack_end__ and PC with Reset_Handler. Execution proceeds from > Reset_Handler. > > However, the ELF entry point does not always match the hardware reset > address. For example, on i.MX94 CM33S: > > ELF entry point: 0x0ffc211d > hardware reset base: 0x0ffc0000 (default reset value, sw programmable) >
But why? Why can't the ELF image be set to the right reset base? > To derive the correct hardware reset address, the unused lower bits must > be masked off. The boot code should apply a SoC-specific mask before > programming the reset address registers, e.g.: > > reset_address = entry & reset_vector_mask > > Current driver always programs the reset vector as 0. But i.MX94 CM33S's > default reset base is 0x0ffc0000, 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 SM CPU/LMM reset vector API calls. > > Signed-off-by: Peng Fan <[email protected]> > --- > drivers/remoteproc/imx_rproc.c | 17 ++++++++++++++--- > drivers/remoteproc/imx_rproc.h | 2 ++ > 2 files changed, 16 insertions(+), 3 deletions(-) > > diff --git a/drivers/remoteproc/imx_rproc.c b/drivers/remoteproc/imx_rproc.c > index > 0dd80e688b0ea3df4c66e5726884dc86c8a5a881..d8ead42640881bd523d605fa7002935ef6e98077 > 100644 > --- a/drivers/remoteproc/imx_rproc.c > +++ b/drivers/remoteproc/imx_rproc.c > @@ -345,7 +345,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 +365,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 +739,17 @@ 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; > + u32 reset_vector_mask = GENMASK_U32(31, 0); > + > + if (priv->dcfg->reset_vector_mask) > + reset_vector_mask = priv->dcfg->reset_vector_mask; > + > + return rproc_elf_get_boot_addr(rproc, fw) & reset_vector_mask; > +} > + > static const struct rproc_ops imx_rproc_ops = { > .prepare = imx_rproc_prepare, > .attach = imx_rproc_attach, > @@ -752,7 +763,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, > diff --git a/drivers/remoteproc/imx_rproc.h b/drivers/remoteproc/imx_rproc.h > index > d37e6f90548cec727b4aeb874680b42af85bdbb4..0d7d48352a1091ad24e8e083172ce6da6d26ae10 > 100644 > --- a/drivers/remoteproc/imx_rproc.h > +++ b/drivers/remoteproc/imx_rproc.h > @@ -41,6 +41,8 @@ struct imx_rproc_dcfg { > /* For System Manager(SM) based SoCs */ > u32 cpuid; /* ID of the remote core */ > u32 lmid; /* ID of the Logcial Machine */ > + /* reset_vector = elf_entry_addr & reset_vector_mask */ > + u32 reset_vector_mask; > }; > > #endif /* _IMX_RPROC_H */ > > -- > 2.37.1 >

