drivers: remoteproc: Modify callbacks for Rproc during Deepsleep

Handle deviations in Deepsleep requirements by introducing new
callbacks that would be invoked during deepsleep suspend.

Change-Id: I988a72fa3b175de4338b4e5fa2a90191a438aa4b
Signed-off-by: Shreyas K K <quic_shrekk@quicinc.com>
This commit is contained in:
Shreyas K K
2023-12-01 02:23:14 +05:30
committed by Jai Kumar Gautam
parent af8a87a771
commit 1221637cb7
5 changed files with 108 additions and 0 deletions

View File

@@ -93,6 +93,7 @@ void qcom_remove_sysmon_subdev(struct qcom_sysmon *sysmon);
bool qcom_sysmon_shutdown_acked(struct qcom_sysmon *sysmon);
uint32_t qcom_sysmon_get_txn_id(struct qcom_sysmon *sysmon);
int qcom_sysmon_get_reason(struct qcom_sysmon *sysmon, char *buf, size_t len);
void qcom_sysmon_set_ops_stop(struct qcom_sysmon *sysmon, bool suspend);
#else
static inline struct qcom_sysmon *qcom_add_sysmon_subdev(struct rproc *rproc,
const char *name,
@@ -120,6 +121,9 @@ static inline int qcom_sysmon_get_reason(struct qcom_sysmon *sysmon,
{
return -ENODEV;
}
static inline void qcom_sysmon_set_ops_stop(struct qcom_sysmon *sysmon,
bool suspend) { }
#endif
#endif

View File

@@ -32,6 +32,7 @@
#include <soc/qcom/secure_buffer.h>
#include <trace/events/rproc_qcom.h>
#include <soc/qcom/qcom_ramdump.h>
#include <linux/remoteproc/qcom_rproc.h>
#include "qcom_common.h"
#include "qcom_pil_info.h"
@@ -635,6 +636,54 @@ static int adsp_stop(struct rproc *rproc)
return ret;
}
static int adsp_shutdown(struct rproc *rproc)
{
struct qcom_adsp *adsp = (struct qcom_adsp *)rproc->priv;
int handover;
int ret;
trace_rproc_qcom_event(dev_name(adsp->dev), "adsp_shutdown", "enter");
scm_pas_enable_bw();
if (adsp->retry_shutdown)
ret = qcom_scm_pas_shutdown_retry(adsp->pas_id);
else
ret = qcom_scm_pas_shutdown(adsp->pas_id);
if (ret)
panic("Panicking, remoteproc %s failed to shutdown.\n", rproc->name);
if (adsp->dtb_pas_id) {
ret = qcom_scm_pas_shutdown(adsp->dtb_pas_id);
if (ret)
panic("Panicking, remoteproc %s dtb failed to shutdown.\n", rproc->name);
}
scm_pas_disable_bw();
adsp_pds_disable(adsp, adsp->active_pds, adsp->active_pd_count);
if (adsp->qmp)
qcom_rproc_toggle_load_state(adsp->qmp, adsp->qmp_name, false);
handover = qcom_q6v5_unprepare(&adsp->q6v5);
if (handover)
qcom_pas_handover(&adsp->q6v5);
trace_rproc_qcom_event(dev_name(adsp->dev), "adsp_shutdown", "exit");
return ret;
}
void adsp_set_ops_stop(struct rproc *rproc, bool suspend)
{
struct qcom_adsp *adsp;
adsp = (struct qcom_adsp *)rproc->priv;
qcom_sysmon_set_ops_stop(adsp->sysmon, suspend);
if (suspend)
rproc->ops->stop = adsp_shutdown;
else
rproc->ops->stop = adsp_stop;
}
EXPORT_SYMBOL_GPL(adsp_set_ops_stop);
static int adsp_attach(struct rproc *rproc)
{
struct qcom_adsp *adsp = (struct qcom_adsp *)rproc->priv;

View File

@@ -775,6 +775,51 @@ static void sysmon_stop(struct rproc_subdev *subdev, bool crashed)
del_timer_sync(&sysmon->timeout_data.timer);
}
static void sysmon_shutdown(struct rproc_subdev *subdev, bool crashed)
{
unsigned long timeout;
struct qcom_sysmon *sysmon = container_of(subdev, struct qcom_sysmon, subdev);
trace_rproc_qcom_event(dev_name(sysmon->rproc->dev.parent), SYSMON_SUBDEV_NAME,
crashed ? "crash stop" : "stop");
sysmon->shutdown_acked = false;
mutex_lock(&sysmon->state_lock);
sysmon->state = QCOM_SSR_BEFORE_SHUTDOWN;
sysmon->transaction_id++;
dev_info(sysmon->dev, "Incrementing tid for %s to %d\n", sysmon->name,
sysmon->transaction_id);
blocking_notifier_call_chain(&sysmon_notifiers, 0, (void *)sysmon);
mutex_unlock(&sysmon->state_lock);
/* Don't request graceful shutdown if we've crashed */
if (crashed)
return;
sysmon->timeout_data.timer.function = sysmon_shutdown_notif_timeout_handler;
timeout = jiffies + msecs_to_jiffies(SYSMON_NOTIF_TIMEOUT);
mod_timer(&sysmon->timeout_data.timer, timeout);
if (sysmon->ssctl_instance) {
if (!wait_for_completion_timeout(&sysmon->ssctl_comp, HZ / 2))
dev_err(sysmon->dev, "timeout waiting for ssctl service\n");
}
del_timer_sync(&sysmon->timeout_data.timer);
}
void qcom_sysmon_set_ops_stop(struct qcom_sysmon *sysmon, bool suspend)
{
if (suspend)
sysmon->subdev.stop = sysmon_shutdown;
else
sysmon->subdev.stop = sysmon_stop;
}
EXPORT_SYMBOL_GPL(qcom_sysmon_set_ops_stop);
static void sysmon_unprepare(struct rproc_subdev *subdev)
{
struct qcom_sysmon *sysmon = container_of(subdev, struct qcom_sysmon,

View File

@@ -124,6 +124,7 @@ static int subsys_suspend(struct subsystem_data *ss_data, struct rproc *rproc, u
case SUBSYS_DEEPSLEEP:
case SUBSYS_HIBERNATE:
ss_data->ignore_ssr = true;
adsp_set_ops_stop(rproc, true);
rproc_shutdown(rproc);
ss_data->ignore_ssr = false;
break;
@@ -144,6 +145,7 @@ static int subsys_resume(struct subsystem_data *ss_data, struct rproc *rproc, u3
case SUBSYS_DEEPSLEEP:
case SUBSYS_HIBERNATE:
ss_data->ignore_ssr = true;
adsp_set_ops_stop(rproc, false);
ret = rproc_boot(rproc);
ss_data->ignore_ssr = false;
break;

View File

@@ -61,6 +61,14 @@ static inline int qcom_rproc_set_dtb_firmware(struct rproc *rproc, const char *d
{
return -EINVAL;
}
#endif
#if IS_ENABLED(CONFIG_QCOM_Q6V5_PAS)
void adsp_set_ops_stop(struct rproc *rproc, bool suspend);
#else
static inline void adsp_set_ops_stop(struct rproc *rproc, bool suspend) { }
#endif
#endif