Diffstat (limited to 'patches/remoteproc/0011-remoteproc-qcom_q6v5_pas-Attach-running-remoteproc-i.patch')
| -rw-r--r-- | patches/remoteproc/0011-remoteproc-qcom_q6v5_pas-Attach-running-remoteproc-i.patch | 106 |
1 files changed, 106 insertions, 0 deletions
diff --git a/patches/remoteproc/0011-remoteproc-qcom_q6v5_pas-Attach-running-remoteproc-i.patch b/patches/remoteproc/0011-remoteproc-qcom_q6v5_pas-Attach-running-remoteproc-i.patch new file mode 100644 index 0000000..66ecc0f --- /dev/null +++ b/patches/remoteproc/0011-remoteproc-qcom_q6v5_pas-Attach-running-remoteproc-i.patch @@ -0,0 +1,106 @@ +A remoteproc might be already running during boot, e.g. because it was +already started by the boot firmware. This is the case for example on X1E, +where the boot firmware starts a "lite" ADSP firmware that supports +charging and USB-CC detection, but is missing audio functionality. This +firmware uses the same interfaces as the full firmware and can be reused in +case the device-specific firmware is missing (e.g. in generic distro +installers). + +The running remoteproc is currently not modelled at all - it is just killed +through qcom_pas_shutdown() without even using the SMP2P stop signal +beforehand. If the firmware is present the "lite" firmware is now stopped more +gracefully with the SMP2P stop signal. + +diff --git a/drivers/remoteproc/qcom_q6v5_pas.c b/drivers/remoteproc/qcom_q6v5_pas.c +index 672af7336..3cf24f202 100644 +--- a/drivers/remoteproc/qcom_q6v5_pas.c ++++ b/drivers/remoteproc/qcom_q6v5_pas.c +@@ -236,10 +237,13 @@ + /* Store firmware handle to be used in qcom_pas_start() */ + pas->firmware = fw; + +- if (pas->lite_pas_id) +- qcom_scm_pas_shutdown(pas->lite_pas_id); +- if (pas->lite_dtb_pas_id) +- qcom_scm_pas_shutdown(pas->lite_dtb_pas_id); ++ /* ++ * We don't support loading the "lite" firmware, so we don't need to ++ * keep trying to shut it down. If it was running, it should have ++ * already been stopped by adsp_stop(). ++ */ ++ pas->lite_pas_id = 0; ++ pas->lite_dtb_pas_id = 0; + + if (pas->dtb_pas_id) { + ret = request_firmware(&pas->dtb_firmware, pas->dtb_firmware_name, pas->dev); +@@ -401,6 +405,28 @@ + qcom_pas_pds_disable(pas, pas->proxy_pds, pas->proxy_pd_count); + } + ++static int qcom_q6v5_pas_shutdown(int pas_id, int lite_pas_id) ++{ ++ int ret, lite_ret = -ENODEV; ++ ++ /* ++ * We don't know if the boot firmware started the "full" or "lite" ++ * firmware, so we don't know if we need to shutdown the lite_pas_id or ++ * the normal pas_id. Unfortunately, the return codes of the SCM calls ++ * are also not helpful to figure that out. Since shutting down a ++ * stopped remoteproc is a no-op, we just shutdown both and if one of ++ * the calls succeeds, we assume it's okay. ++ */ ++ if (lite_pas_id) ++ lite_ret = qcom_scm_pas_shutdown(lite_pas_id); ++ ++ ret = qcom_scm_pas_shutdown(pas_id); ++ if (ret && lite_ret) ++ return ret; ++ ++ return 0; ++} ++ + static int qcom_pas_stop(struct rproc *rproc) + { + struct qcom_pas *pas = rproc->priv; +@@ -411,7 +437,7 @@ + if (ret == -ETIMEDOUT) + dev_err(pas->dev, "timed out on wait\n"); + +- ret = qcom_scm_pas_shutdown(pas->pas_id); ++ ret = qcom_q6v5_pas_shutdown(pas->pas_id, pas->lite_pas_id); + if (ret && pas->decrypt_shutdown) + ret = qcom_pas_shutdown_poll_decrypt(pas); + +@@ -419,7 +445,7 @@ + dev_err(pas->dev, "failed to shutdown: %d\n", ret); + + if (pas->dtb_pas_id) { +- ret = qcom_scm_pas_shutdown(pas->dtb_pas_id); ++ ret = qcom_q6v5_pas_shutdown(pas->dtb_pas_id, pas->lite_dtb_pas_id); + if (ret) + dev_err(pas->dev, "failed to shutdown dtb: %d\n", ret); + +@@ -428,9 +454,11 @@ + + qcom_pas_unmap_carveout(rproc, pas->mem_phys, pas->mem_size); + +- handover = qcom_q6v5_unprepare(&pas->q6v5); +- if (handover) +- qcom_pas_handover(&pas->q6v5); ++ if (rproc->state != RPROC_DETACHED) { ++ handover = qcom_q6v5_unprepare(&pas->q6v5); ++ if (handover) ++ qcom_pas_handover(&pas->q6v5); ++ } + + if (pas->smem_host_id) + ret = qcom_smem_bust_hwspin_lock_by_host(pas->smem_host_id); +@@ -859,7 +890,7 @@ + + rproc->has_iommu = of_property_present(pdev->dev.of_node, "iommus"); + if (desc->auto_boot) +- rproc->auto_boot = RPROC_AUTO_BOOT_ATTACH_OR_START; ++ rproc->auto_boot = RPROC_AUTO_BOOT_RESTART_IF_FW_AVAILABLE; + else + rproc->auto_boot = RPROC_AUTO_BOOT_DISABLED; + rproc_coredump_set_elf_info(rproc, ELFCLASS32, EM_NONE); |