All of lore.kernel.org
 help / color / mirror / Atom feed
From: Sibi Sankar <sibis@codeaurora.org>
To: bjorn.andersson@linaro.org, robh+dt@kernel.org,
	andy.gross@linaro.org, david.brown@linaro.org
Cc: linux-arm-msm@vger.kernel.org, linux-soc@vger.kernel.org,
	devicetree@vger.kernel.org, linux-kernel@vger.kernel.org,
	tsoni@codeaurora.org, clew@codeaurora.org,
	akdwived@codeaurora.org, ohad@wizery.com, mark.rutland@arm.com,
	linux-remoteproc@vger.kernel.org, dianders@chromium.org,
	Sibi Sankar <sibis@codeaurora.org>
Subject: [PATCH v2 2/4] remoteproc: qcom: q6v5: Add shutdown-ack irq
Date: Mon, 24 Dec 2018 14:18:22 +0530	[thread overview]
Message-ID: <20181224084824.25193-2-sibis@codeaurora.org> (raw)
In-Reply-To: <20181224084824.25193-1-sibis@codeaurora.org>

Add shutdown-ack irq handling for Q6V5. This patch includes enabling
shutdown-ack irq on those Q6V5 instances with "has_shutdown_irq"
flag set and exposing Q6V5 state information to the sysmon instance
which is required to ascertain graceful shutdown completion.

Signed-off-by: Sibi Sankar <sibis@codeaurora.org>
---

 v2:
   Move shutdown-irq get to Q6V5 from sysmon to handle
   -EPROBE_DEFER cases
   Correct the shutdown-irq wait time to 10 * HZ

 drivers/remoteproc/qcom_common.h    |  7 ++--
 drivers/remoteproc/qcom_q6v5.c      | 53 +++++++++++++++++++++++++++++
 drivers/remoteproc/qcom_q6v5.h      |  5 +++
 drivers/remoteproc/qcom_q6v5_adsp.c |  3 +-
 drivers/remoteproc/qcom_q6v5_mss.c  |  3 +-
 drivers/remoteproc/qcom_q6v5_pas.c  |  3 +-
 drivers/remoteproc/qcom_sysmon.c    |  6 +++-
 drivers/remoteproc/qcom_wcnss.c     |  3 +-
 8 files changed, 76 insertions(+), 7 deletions(-)

diff --git a/drivers/remoteproc/qcom_common.h b/drivers/remoteproc/qcom_common.h
index 58de71e4781c..d938b09ad02c 100644
--- a/drivers/remoteproc/qcom_common.h
+++ b/drivers/remoteproc/qcom_common.h
@@ -7,6 +7,7 @@
 #include <linux/soc/qcom/qmi.h>
 
 struct qcom_sysmon;
+struct qcom_q6v5;
 
 struct qcom_rproc_glink {
 	struct rproc_subdev subdev;
@@ -45,12 +46,14 @@ void qcom_remove_ssr_subdev(struct rproc *rproc, struct qcom_rproc_ssr *ssr);
 #if IS_ENABLED(CONFIG_QCOM_SYSMON)
 struct qcom_sysmon *qcom_add_sysmon_subdev(struct rproc *rproc,
 					   const char *name,
-					   int ssctl_instance);
+					   int ssctl_instance,
+					   struct qcom_q6v5 *q6v5);
 void qcom_remove_sysmon_subdev(struct qcom_sysmon *sysmon);
 #else
 static inline struct qcom_sysmon *qcom_add_sysmon_subdev(struct rproc *rproc,
 							 const char *name,
-							 int ssctl_instance)
+							 int ssctl_instance,
+							 struct qcom_q6v5 *q6v5)
 {
 	return NULL;
 }
diff --git a/drivers/remoteproc/qcom_q6v5.c b/drivers/remoteproc/qcom_q6v5.c
index 0d33e3079f0d..a4c2ecae6a0f 100644
--- a/drivers/remoteproc/qcom_q6v5.c
+++ b/drivers/remoteproc/qcom_q6v5.c
@@ -25,6 +25,7 @@ int qcom_q6v5_prepare(struct qcom_q6v5 *q6v5)
 {
 	reinit_completion(&q6v5->start_done);
 	reinit_completion(&q6v5->stop_done);
+	reinit_completion(&q6v5->shutdown_done);
 
 	q6v5->running = true;
 	q6v5->handover_issued = false;
@@ -141,6 +142,35 @@ static irqreturn_t q6v5_stop_interrupt(int irq, void *data)
 	return IRQ_HANDLED;
 }
 
+static irqreturn_t q6v5_shutdown_interrupt(int irq, void *data)
+{
+	struct qcom_q6v5 *q6v5 = data;
+
+	complete(&q6v5->shutdown_done);
+
+	return IRQ_HANDLED;
+}
+
+/**
+ * qcom_q6v5_wait_for_shutdown() - wait for remote processor shutdown signal
+ * @q6v5:	reference to qcom_q6v5 context
+ * @timeout:	timeout to wait for the event, in jiffies
+ *
+ * Return: 0 on success, -ETIMEDOUT on timeout
+ */
+int qcom_q6v5_wait_for_shutdown(struct qcom_q6v5 *q6v5, int timeout)
+{
+	int ret;
+
+	if (!q6v5->has_shutdown_irq)
+		return 0;
+
+	ret = wait_for_completion_timeout(&q6v5->shutdown_done, timeout);
+
+	return !ret ? -ETIMEDOUT : 0;
+}
+EXPORT_SYMBOL_GPL(qcom_q6v5_wait_for_shutdown);
+
 /**
  * qcom_q6v5_request_stop() - request the remote processor to stop
  * @q6v5:	reference to qcom_q6v5 context
@@ -185,6 +215,7 @@ int qcom_q6v5_init(struct qcom_q6v5 *q6v5, struct platform_device *pdev,
 
 	init_completion(&q6v5->start_done);
 	init_completion(&q6v5->stop_done);
+	init_completion(&q6v5->shutdown_done);
 
 	q6v5->wdog_irq = platform_get_irq_byname(pdev, "wdog");
 	if (q6v5->wdog_irq < 0) {
@@ -277,6 +308,28 @@ int qcom_q6v5_init(struct qcom_q6v5 *q6v5, struct platform_device *pdev,
 		return ret;
 	}
 
+	if (q6v5->has_shutdown_irq) {
+		q6v5->shutdown_irq = platform_get_irq_byname(pdev,
+							     "shutdown-ack");
+		if (q6v5->shutdown_irq < 0) {
+			if (q6v5->shutdown_irq != -EPROBE_DEFER)
+				dev_err(&pdev->dev,
+					"failed to get shutdown-ack IRQ: %d\n",
+					q6v5->shutdown_irq);
+			return q6v5->shutdown_irq;
+		}
+
+		ret = devm_request_threaded_irq(&pdev->dev, q6v5->shutdown_irq,
+						NULL, q6v5_shutdown_interrupt,
+						IRQF_TRIGGER_RISING |
+						IRQF_ONESHOT,
+						"q6v5 shutdown", q6v5);
+		if (ret) {
+			dev_err(&pdev->dev, "failed to acquire shutdown IRQ\n");
+			return ret;
+		}
+	}
+
 	q6v5->state = qcom_smem_state_get(&pdev->dev, "stop", &q6v5->stop_bit);
 	if (IS_ERR(q6v5->state)) {
 		dev_err(&pdev->dev, "failed to acquire stop state\n");
diff --git a/drivers/remoteproc/qcom_q6v5.h b/drivers/remoteproc/qcom_q6v5.h
index 7ac92c1e0f49..5cbaf2564c3a 100644
--- a/drivers/remoteproc/qcom_q6v5.h
+++ b/drivers/remoteproc/qcom_q6v5.h
@@ -21,11 +21,15 @@ struct qcom_q6v5 {
 	int ready_irq;
 	int handover_irq;
 	int stop_irq;
+	int shutdown_irq;
+
+	u8 has_shutdown_irq;
 
 	bool handover_issued;
 
 	struct completion start_done;
 	struct completion stop_done;
+	struct completion shutdown_done;
 
 	int crash_reason;
 
@@ -42,5 +46,6 @@ int qcom_q6v5_prepare(struct qcom_q6v5 *q6v5);
 int qcom_q6v5_unprepare(struct qcom_q6v5 *q6v5);
 int qcom_q6v5_request_stop(struct qcom_q6v5 *q6v5);
 int qcom_q6v5_wait_for_start(struct qcom_q6v5 *q6v5, int timeout);
+int qcom_q6v5_wait_for_shutdown(struct qcom_q6v5 *q6v5, int timeout);
 
 #endif
diff --git a/drivers/remoteproc/qcom_q6v5_adsp.c b/drivers/remoteproc/qcom_q6v5_adsp.c
index 79374d1de311..5fc42d38a1cd 100644
--- a/drivers/remoteproc/qcom_q6v5_adsp.c
+++ b/drivers/remoteproc/qcom_q6v5_adsp.c
@@ -438,7 +438,8 @@ static int adsp_probe(struct platform_device *pdev)
 	qcom_add_ssr_subdev(rproc, &adsp->ssr_subdev, desc->ssr_name);
 	adsp->sysmon = qcom_add_sysmon_subdev(rproc,
 					      desc->sysmon_name,
-					      desc->ssctl_id);
+					      desc->ssctl_id,
+					      &adsp->q6v5);
 
 	ret = rproc_add(rproc);
 	if (ret)
diff --git a/drivers/remoteproc/qcom_q6v5_mss.c b/drivers/remoteproc/qcom_q6v5_mss.c
index 01be7314e176..3bc2dec85928 100644
--- a/drivers/remoteproc/qcom_q6v5_mss.c
+++ b/drivers/remoteproc/qcom_q6v5_mss.c
@@ -1340,7 +1340,8 @@ static int q6v5_probe(struct platform_device *pdev)
 	qcom_add_glink_subdev(rproc, &qproc->glink_subdev);
 	qcom_add_smd_subdev(rproc, &qproc->smd_subdev);
 	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,
+					       &qproc->q6v5);
 
 	ret = rproc_add(rproc);
 	if (ret)
diff --git a/drivers/remoteproc/qcom_q6v5_pas.c b/drivers/remoteproc/qcom_q6v5_pas.c
index b1e63fcd5fdf..920a39ea6609 100644
--- a/drivers/remoteproc/qcom_q6v5_pas.c
+++ b/drivers/remoteproc/qcom_q6v5_pas.c
@@ -303,7 +303,8 @@ static int adsp_probe(struct platform_device *pdev)
 	qcom_add_ssr_subdev(rproc, &adsp->ssr_subdev, desc->ssr_name);
 	adsp->sysmon = qcom_add_sysmon_subdev(rproc,
 					      desc->sysmon_name,
-					      desc->ssctl_id);
+					      desc->ssctl_id,
+					      &adsp->q6v5);
 
 	ret = rproc_add(rproc);
 	if (ret)
diff --git a/drivers/remoteproc/qcom_sysmon.c b/drivers/remoteproc/qcom_sysmon.c
index e976a602b015..c0d6ee8de995 100644
--- a/drivers/remoteproc/qcom_sysmon.c
+++ b/drivers/remoteproc/qcom_sysmon.c
@@ -14,12 +14,14 @@
 #include <linux/rpmsg.h>
 
 #include "qcom_common.h"
+#include "qcom_q6v5.h"
 
 static BLOCKING_NOTIFIER_HEAD(sysmon_notifiers);
 
 struct qcom_sysmon {
 	struct rproc_subdev subdev;
 	struct rproc *rproc;
+	struct qcom_q6v5 *q6v5;
 
 	struct list_head node;
 
@@ -442,7 +444,8 @@ static int sysmon_notify(struct notifier_block *nb, unsigned long event,
  */
 struct qcom_sysmon *qcom_add_sysmon_subdev(struct rproc *rproc,
 					   const char *name,
-					   int ssctl_instance)
+					   int ssctl_instance,
+					   struct qcom_q6v5 *q6v5)
 {
 	struct qcom_sysmon *sysmon;
 	int ret;
@@ -456,6 +459,7 @@ struct qcom_sysmon *qcom_add_sysmon_subdev(struct rproc *rproc,
 
 	sysmon->name = name;
 	sysmon->ssctl_instance = ssctl_instance;
+	sysmon->q6v5 = q6v5;
 
 	init_completion(&sysmon->comp);
 	mutex_init(&sysmon->lock);
diff --git a/drivers/remoteproc/qcom_wcnss.c b/drivers/remoteproc/qcom_wcnss.c
index b0e07e9f42d5..af13cade35da 100644
--- a/drivers/remoteproc/qcom_wcnss.c
+++ b/drivers/remoteproc/qcom_wcnss.c
@@ -552,7 +552,8 @@ static int wcnss_probe(struct platform_device *pdev)
 	}
 
 	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,
+					       NULL);
 
 	ret = rproc_add(rproc);
 	if (ret)
-- 
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
a Linux Foundation Collaborative Project

  reply	other threads:[~2018-12-24  8:48 UTC|newest]

Thread overview: 9+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2018-12-24  8:48 [PATCH v2 1/4] dt-bindings: remoteproc: qcom: Introduce shutdown-ack irq for Q6V5 Sibi Sankar
2018-12-24  8:48 ` Sibi Sankar [this message]
2018-12-24  8:48 ` [PATCH v2 3/4] remoteproc: qcom: Wait for shutdown-ack/ind on sysmon shutdown Sibi Sankar
2019-01-03 23:33   ` Bjorn Andersson
2019-01-08 10:14     ` Sibi Sankar
2018-12-24  8:48 ` [PATCH v2 4/4] remoteproc: qcom: Enable shutdown-ack irq on Q6V5 Sibi Sankar
2018-12-27 21:55 ` [PATCH v2 1/4] dt-bindings: remoteproc: qcom: Introduce shutdown-ack irq for Q6V5 Rob Herring
2018-12-27 21:55   ` Rob Herring
2018-12-27 21:55   ` Rob Herring

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20181224084824.25193-2-sibis@codeaurora.org \
    --to=sibis@codeaurora.org \
    --cc=akdwived@codeaurora.org \
    --cc=andy.gross@linaro.org \
    --cc=bjorn.andersson@linaro.org \
    --cc=clew@codeaurora.org \
    --cc=david.brown@linaro.org \
    --cc=devicetree@vger.kernel.org \
    --cc=dianders@chromium.org \
    --cc=linux-arm-msm@vger.kernel.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=linux-remoteproc@vger.kernel.org \
    --cc=linux-soc@vger.kernel.org \
    --cc=mark.rutland@arm.com \
    --cc=ohad@wizery.com \
    --cc=robh+dt@kernel.org \
    --cc=tsoni@codeaurora.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.