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)
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