aboutsummaryrefslogtreecommitdiffci
path: root/patches/remoteproc/0011-remoteproc-qcom_q6v5_pas-Attach-running-remoteproc-i.patch
diff refs
from: back
to: back
| flip
diff options
context:
space:
mode:
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.patch106
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);