From: Iuliana Prodan <iuliana.prodan@xxxxxxx> Some DSP firmware requires a FW_READY signal before proceeding, while others do not. Introduce imx_dsp_rproc_wait_fw_ready() to check the resource table and determine if waiting is needed. Use the WAIT_FW_READY flag (bit 1) to distinguish cases where waiting is required, as bit 0 is reserved for VIRTIO_RPMSG_F_NS in OpenAMP and mentioned in rpmsg documentation (not used in Linux, so far). This flag is set by the remote processor in the dfeatures member of struct fw_rsc_vdev, indicating supported virtio device features. Update imx_dsp_rproc_start() to handle this condition accordingly. Signed-off-by: Iuliana Prodan <iuliana.prodan@xxxxxxx> --- drivers/remoteproc/imx_dsp_rproc.c | 84 +++++++++++++++++++++++++++--- 1 file changed, 77 insertions(+), 7 deletions(-) diff --git a/drivers/remoteproc/imx_dsp_rproc.c b/drivers/remoteproc/imx_dsp_rproc.c index b9bb15970966..8eefaee28061 100644 --- a/drivers/remoteproc/imx_dsp_rproc.c +++ b/drivers/remoteproc/imx_dsp_rproc.c @@ -1,5 +1,5 @@ // SPDX-License-Identifier: GPL-2.0-only -/* Copyright 2021 NXP */ +/* Copyright 2021, 2025 NXP */ #include <dt-bindings/firmware/imx/rsrc.h> #include <linux/arm-smccc.h> @@ -38,6 +38,15 @@ MODULE_PARM_DESC(no_mailboxes, #define REMOTE_IS_READY BIT(0) #define REMOTE_READY_WAIT_MAX_RETRIES 500 +/* + * This flag is set by the remote processor in the dfeatures member of + * struct fw_rsc_vdev, indicating supported virtio device features + * + * Use bit 1 since bit 0 is used for VIRTIO_RPMSG_F_NS + * in OpenAMP and mentioned in kernel's rpmsg documentation + */ +#define WAIT_FW_READY BIT(1) + /* att flags */ /* DSP own area */ #define ATT_OWN BIT(31) @@ -300,13 +309,74 @@ static int imx_dsp_rproc_ready(struct rproc *rproc) return -ETIMEDOUT; } +/* + * Determines whether we should wait for a FW_READY reply + * from the remote processor. + * + * This function inspects the resource table associated with the remote + * processor to check if the firmware has indicated that waiting + * for a FW_READY signal is necessary. + * By default, wait for FW_READY unless an RSC_VDEV explicitly + * indicates otherwise. + * + * Return: + * - true: If we should wait for FW READY + * - false: If FW_READY wait is not required + */ +static bool imx_dsp_rproc_wait_fw_ready(struct rproc *rproc) +{ + struct device *dev = &rproc->dev; + struct fw_rsc_hdr *hdr; + struct fw_rsc_vdev *rsc; + int i, offset, avail; + + /* + * If there is no resource table, wait for FW_READY + * unless no_mailboxes module param is used + */ + if (!rproc->table_ptr) + return true; + + /* Iterate over each resource entry in the resource table */ + for (i = 0; i < rproc->table_ptr->num; i++) { + offset = rproc->table_ptr->offset[i]; + hdr = (void *)rproc->table_ptr + offset; + avail = rproc->table_sz - offset - sizeof(*hdr); + + /* Ensure the resource table is not truncated */ + if (avail < 0) { + dev_err(dev, "Resource table is truncated\n"); + return true; + } + + /* Check if the resource type is a virtio device */ + if (hdr->type == RSC_VDEV) { + rsc = (struct fw_rsc_vdev *)((void *)hdr + sizeof(*hdr)); + + /* vdev does not require waiting for FW_READY */ + return !!(rsc->dfeatures & WAIT_FW_READY); + } + } + + /* + * By default, wait for the FW_READY + * unless a vdev entry disables it + */ + return true; +} + /* * Start function for rproc_ops * - * There is a handshake for start procedure: when DSP starts, it - * will send a doorbell message to this driver, then the - * REMOTE_IS_READY flags is set, then driver will kick - * a message to DSP. + * The start procedure involves a handshake: when the DSP starts, it + * sends a doorbell message to this driver, which sets the + * REMOTE_IS_READY flag. The driver then sends a message to the DSP. + * + * Before proceeding, the driver checks if it needs to wait for a + * firmware ready reply using imx_dsp_rproc_wait_fw_ready(). + * If waiting is required, it calls imx_dsp_rproc_ready() to complete + * the initialization. + * If waiting is not required, the start function returns. */ static int imx_dsp_rproc_start(struct rproc *rproc) { @@ -335,8 +405,8 @@ static int imx_dsp_rproc_start(struct rproc *rproc) if (ret) dev_err(dev, "Failed to enable remote core!\n"); - else - ret = imx_dsp_rproc_ready(rproc); + else if (imx_dsp_rproc_wait_fw_ready(rproc)) + return imx_dsp_rproc_ready(rproc); return ret; } -- 2.25.1