remoteproc: qcom: Add shutdown-ack irq

Add shutdown-ack irq handling required for sysmon shutdown for
Q6V5 MSS on SDM845/MSM8996 and for WCSS Q6V5 on QCS404 SoC.

Signed-off-by: Sibi Sankar <sibis@codeaurora.org>
[bjorn: Revert back to qcom_add_sysmon_subdev returning a sysmon object]
Signed-off-by: Bjorn Andersson <bjorn.andersson@linaro.org>
This commit is contained in:
Sibi Sankar 2019-01-08 15:53:43 +05:30 committed by Bjorn Andersson
parent 05f9f57500
commit 027045a6e2
5 changed files with 53 additions and 2 deletions

View File

@ -439,6 +439,10 @@ static int adsp_probe(struct platform_device *pdev)
adsp->sysmon = qcom_add_sysmon_subdev(rproc, adsp->sysmon = qcom_add_sysmon_subdev(rproc,
desc->sysmon_name, desc->sysmon_name,
desc->ssctl_id); desc->ssctl_id);
if (IS_ERR(adsp->sysmon)) {
ret = PTR_ERR(adsp->sysmon);
goto disable_pm;
}
ret = rproc_add(rproc); ret = rproc_add(rproc);
if (ret) if (ret)

View File

@ -1341,6 +1341,10 @@ static int q6v5_probe(struct platform_device *pdev)
qcom_add_smd_subdev(rproc, &qproc->smd_subdev); qcom_add_smd_subdev(rproc, &qproc->smd_subdev);
qcom_add_ssr_subdev(rproc, &qproc->ssr_subdev, "mpss"); qcom_add_ssr_subdev(rproc, &qproc->ssr_subdev, "mpss");
qproc->sysmon = qcom_add_sysmon_subdev(rproc, "modem", 0x12); qproc->sysmon = qcom_add_sysmon_subdev(rproc, "modem", 0x12);
if (IS_ERR(qproc->sysmon)) {
ret = PTR_ERR(qproc->sysmon);
goto free_rproc;
}
ret = rproc_add(rproc); ret = rproc_add(rproc);
if (ret) if (ret)

View File

@ -304,6 +304,10 @@ static int adsp_probe(struct platform_device *pdev)
adsp->sysmon = qcom_add_sysmon_subdev(rproc, adsp->sysmon = qcom_add_sysmon_subdev(rproc,
desc->sysmon_name, desc->sysmon_name,
desc->ssctl_id); desc->ssctl_id);
if (IS_ERR(adsp->sysmon)) {
ret = PTR_ERR(adsp->sysmon);
goto free_rproc;
}
ret = rproc_add(rproc); ret = rproc_add(rproc);
if (ret) if (ret)

View File

@ -6,7 +6,9 @@
#include <linux/module.h> #include <linux/module.h>
#include <linux/notifier.h> #include <linux/notifier.h>
#include <linux/slab.h> #include <linux/slab.h>
#include <linux/interrupt.h>
#include <linux/io.h> #include <linux/io.h>
#include <linux/of_irq.h>
#include <linux/of_platform.h> #include <linux/of_platform.h>
#include <linux/platform_device.h> #include <linux/platform_device.h>
#include <linux/remoteproc/qcom_rproc.h> #include <linux/remoteproc/qcom_rproc.h>
@ -24,6 +26,7 @@ struct qcom_sysmon {
const char *name; const char *name;
int shutdown_irq;
int ssctl_version; int ssctl_version;
int ssctl_instance; int ssctl_instance;
@ -33,6 +36,7 @@ struct qcom_sysmon {
struct rpmsg_endpoint *ept; struct rpmsg_endpoint *ept;
struct completion comp; struct completion comp;
struct completion shutdown_comp;
struct mutex lock; struct mutex lock;
bool ssr_ack; bool ssr_ack;
@ -431,6 +435,15 @@ static int sysmon_notify(struct notifier_block *nb, unsigned long event,
return NOTIFY_DONE; return NOTIFY_DONE;
} }
static irqreturn_t sysmon_shutdown_interrupt(int irq, void *data)
{
struct qcom_sysmon *sysmon = data;
complete(&sysmon->shutdown_comp);
return IRQ_HANDLED;
}
/** /**
* qcom_add_sysmon_subdev() - create a sysmon subdev for the given remoteproc * qcom_add_sysmon_subdev() - create a sysmon subdev for the given remoteproc
* @rproc: rproc context to associate the subdev with * @rproc: rproc context to associate the subdev with
@ -448,7 +461,7 @@ struct qcom_sysmon *qcom_add_sysmon_subdev(struct rproc *rproc,
sysmon = kzalloc(sizeof(*sysmon), GFP_KERNEL); sysmon = kzalloc(sizeof(*sysmon), GFP_KERNEL);
if (!sysmon) if (!sysmon)
return NULL; return ERR_PTR(-ENOMEM);
sysmon->dev = rproc->dev.parent; sysmon->dev = rproc->dev.parent;
sysmon->rproc = rproc; sysmon->rproc = rproc;
@ -457,13 +470,35 @@ struct qcom_sysmon *qcom_add_sysmon_subdev(struct rproc *rproc,
sysmon->ssctl_instance = ssctl_instance; sysmon->ssctl_instance = ssctl_instance;
init_completion(&sysmon->comp); init_completion(&sysmon->comp);
init_completion(&sysmon->shutdown_comp);
mutex_init(&sysmon->lock); mutex_init(&sysmon->lock);
sysmon->shutdown_irq = of_irq_get_byname(sysmon->dev->of_node,
"shutdown-ack");
if (sysmon->shutdown_irq < 0) {
if (sysmon->shutdown_irq != -ENODATA) {
dev_err(sysmon->dev,
"failed to retrieve shutdown-ack IRQ\n");
return ERR_PTR(sysmon->shutdown_irq);
}
} else {
ret = devm_request_threaded_irq(sysmon->dev,
sysmon->shutdown_irq,
NULL, sysmon_shutdown_interrupt,
IRQF_TRIGGER_RISING | IRQF_ONESHOT,
"q6v5 shutdown-ack", sysmon);
if (ret) {
dev_err(sysmon->dev,
"failed to acquire shutdown-ack IRQ\n");
return ERR_PTR(ret);
}
}
ret = qmi_handle_init(&sysmon->qmi, SSCTL_MAX_MSG_LEN, &ssctl_ops, NULL); ret = qmi_handle_init(&sysmon->qmi, SSCTL_MAX_MSG_LEN, &ssctl_ops, NULL);
if (ret < 0) { if (ret < 0) {
dev_err(sysmon->dev, "failed to initialize qmi handle\n"); dev_err(sysmon->dev, "failed to initialize qmi handle\n");
kfree(sysmon); kfree(sysmon);
return NULL; return ERR_PTR(ret);
} }
qmi_add_lookup(&sysmon->qmi, 43, 0, 0); qmi_add_lookup(&sysmon->qmi, 43, 0, 0);

View File

@ -553,6 +553,10 @@ static int wcnss_probe(struct platform_device *pdev)
qcom_add_smd_subdev(rproc, &wcnss->smd_subdev); qcom_add_smd_subdev(rproc, &wcnss->smd_subdev);
wcnss->sysmon = qcom_add_sysmon_subdev(rproc, "wcnss", WCNSS_SSCTL_ID); wcnss->sysmon = qcom_add_sysmon_subdev(rproc, "wcnss", WCNSS_SSCTL_ID);
if (IS_ERR(wcnss->sysmon)) {
ret = PTR_ERR(wcnss->sysmon);
goto free_rproc;
}
ret = rproc_add(rproc); ret = rproc_add(rproc);
if (ret) if (ret)