Hi Mathieu,

> Subject: [PATCH v2 2/3] remoteproc: imx_rproc: Pass bootaddr to SM
> CPU/LMM reset vector

I had an follow-up patch to update reset-vector-mask for i.MX95-CM7
to make it could boot from non-TCM area, not included in this pachset
to avoid unnecessary churn for i.MX94 support, but I realize that
that patch should be squashed into this patch 2/3 to avoid breaking
i.MX95 M7 TCM booting.
Although in my test, cm7 luckily boots up without crash[1], but in theory,
below change should be included in patch 2/3. I will include below change
in v3 after we clear the reset-vector-mask question.

Daniel, please see whether this is ok for you, since you reviewed this
patch.

diff --git a/drivers/remoteproc/imx_rproc.c b/drivers/remoteproc/imx_rproc.c
index 525a92e03e8ab..930dd9eca6fb5 100644
--- a/drivers/remoteproc/imx_rproc.c
+++ b/drivers/remoteproc/imx_rproc.c
@@ -1541,6 +1541,7 @@ static const struct imx_rproc_dcfg imx_rproc_cfg_imx95_m7 
= {
        /* Must align with System Manager Firmware */
        .cpuid          = 1, /* Use 1 as cpu id for M7 core */
        .lmid           = 1, /* Use 1 as Logical Machine ID where M7 resides */
+       .reset_vector_mask = GENMASK_U32(31, 16),
 };
 
 static const struct of_device_id imx_rproc_of_match[] = {


[1]
[  135.738523] remoteproc remoteproc0: powering up imx-rproc
[  135.748464] remoteproc remoteproc0: Booting fw image 
imx95-19x19-evk_m7_TCM_rpmsg_lite_str_echo_rtos.elf, size 98996
[  135.759229] imx-rproc imx95-cm7: lmm(1) powered on by Linux
[  135.764900] ============== entry 0x91d
[  135.772597] xxxxxxxxxxxx bootaddr 0x91d
[  135.775818] rproc-virtio rproc-virtio.2.auto: assigned reserved memory node 
vdevbuffer@88020000
[  135.780278] /soc/bus@42000000/i2c@426d0000/tcpc@50/connector: Fixed 
dependency cycle(s) with /soc/usb@4c010010/usb@4c100000
[  135.795970] /soc/usb@4c010010/usb@4c100000: Fixed dependency cycle(s) with 
/soc/bus@42000000/i2c@426d0000/tcpc@50/connector
[  135.807727] virtio_rpmsg_bus virtio0: rpmsg host is online
[  135.811546] virtio_rpmsg_bus virtio0: creating channel rpmsg-i2c-channel 
addr 0x1


Thanks,
Peng.

> 
> 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..d8ead42640881bd5
> 23d605fa7002935ef6e98077 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..0d7d48352a1091ad
> 24e8e083172ce6da6d26ae10 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

Reply via email to