IPQ8074, IPQ6018, and IPQ9574 support an m3 firmware image in addtion to the q6 firmware. The firmware releases from qcom provide both q6 and m3 firmware for these SoCs. Support loading the m3 firmware image.
Signed-off-by: Alexandru Gagniuc <[email protected]> --- drivers/remoteproc/qcom_q6v5_wcss.c | 44 +++++++++++++++++++++++++---- 1 file changed, 39 insertions(+), 5 deletions(-) diff --git a/drivers/remoteproc/qcom_q6v5_wcss.c b/drivers/remoteproc/qcom_q6v5_wcss.c index b62e97c92d058..265010c5c82cb 100644 --- a/drivers/remoteproc/qcom_q6v5_wcss.c +++ b/drivers/remoteproc/qcom_q6v5_wcss.c @@ -101,7 +101,8 @@ enum { }; struct wcss_data { - const char *firmware_name; + const char *q6_firmware_name; + const char *m3_firmware_name; unsigned int crash_reason_smem; u32 version; bool aon_reset_required; @@ -161,6 +162,7 @@ struct q6v5_wcss { unsigned int crash_reason_smem; u32 version; bool requires_force_stop; + const char *m3_firmware_name; struct qcom_rproc_glink glink_subdev; struct qcom_rproc_pdm pdm_subdev; @@ -922,11 +924,40 @@ static void *q6v5_wcss_da_to_va(struct rproc *rproc, u64 da, size_t len, bool *i return wcss->mem_region + offset; } +static int q6v5_wcss_load_aux(struct q6v5_wcss *wcss, const char *fw_name) +{ + const struct firmware *extra_fw; + int ret; + + dev_info(wcss->dev, "loading additional firmware image %s\n", fw_name); + + ret = request_firmware(&extra_fw, fw_name, wcss->dev); + if (ret) + return 0; + + ret = qcom_mdt_load_no_init(wcss->dev, extra_fw, fw_name, + wcss->mem_region, wcss->mem_phys, + wcss->mem_size, &wcss->mem_reloc); + + release_firmware(extra_fw); + + if (ret) + dev_err(wcss->dev, "can't load %s\n", fw_name); + + return ret; +} + static int q6v5_wcss_load(struct rproc *rproc, const struct firmware *fw) { struct q6v5_wcss *wcss = rproc->priv; int ret; + if (wcss->m3_firmware_name) { + ret = q6v5_wcss_load_aux(wcss, wcss->m3_firmware_name); + if (ret) + return ret; + } + ret = qcom_mdt_load_no_init(wcss->dev, fw, rproc->firmware, wcss->mem_region, wcss->mem_phys, wcss->mem_size, &wcss->mem_reloc); @@ -1187,7 +1218,7 @@ static int q6v5_wcss_probe(struct platform_device *pdev) return -EINVAL; rproc = devm_rproc_alloc(&pdev->dev, pdev->name, desc->ops, - desc->firmware_name, sizeof(*wcss)); + desc->q6_firmware_name, sizeof(*wcss)); if (!rproc) { dev_err(&pdev->dev, "failed to allocate rproc\n"); return -ENOMEM; @@ -1198,6 +1229,7 @@ static int q6v5_wcss_probe(struct platform_device *pdev) wcss->version = desc->version; wcss->requires_force_stop = desc->requires_force_stop; + wcss->m3_firmware_name = desc->m3_firmware_name; ret = q6v5_wcss_init_mmio(wcss, pdev); if (ret) @@ -1275,7 +1307,8 @@ static void q6v5_wcss_remove(struct platform_device *pdev) } static const struct wcss_data wcss_ipq8074_res_init = { - .firmware_name = "IPQ8074/q6_fw.mdt", + .q6_firmware_name = "IPQ8074/q6_fw.mdt", + .m3_firmware_name = "IPQ8074/m3_fw.mdt", .crash_reason_smem = WCSS_CRASH_REASON, .aon_reset_required = true, .wcss_q6_reset_required = true, @@ -1284,7 +1317,8 @@ static const struct wcss_data wcss_ipq8074_res_init = { }; static const struct wcss_data wcss_ipq9574_res_init = { - .firmware_name = "IPQ9574/q6_fw.mdt", + .q6_firmware_name = "IPQ9574/q6_fw.mdt", + .m3_firmware_name = "IPQ9574/m3_fw.mdt", .version = WCSS_IPQ9574, .crash_reason_smem = WCSS_CRASH_REASON, .aon_reset_required = true, @@ -1295,7 +1329,7 @@ static const struct wcss_data wcss_ipq9574_res_init = { static const struct wcss_data wcss_qcs404_res_init = { .crash_reason_smem = WCSS_CRASH_REASON, - .firmware_name = "wcnss.mdt", + .q6_firmware_name = "wcnss.mdt", .version = WCSS_QCS404, .aon_reset_required = false, .wcss_q6_reset_required = false, -- 2.45.1

