aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSrinivas Kandagatla <srinivas.kandagatla@linaro.org>2020-09-18 15:22:47 +0100
committerSrinivas Kandagatla <srinivas.kandagatla@linaro.org>2020-09-24 09:22:02 +0100
commit25161f8b2e86238cc783d8c3c4949d74d9876a98 (patch)
treeda8bf1d3ff14b60fc80071ea4faf47a1383deb2f
parent55eaf2eedbaeff93a7a9adbdfe1b89bf43e09899 (diff)
downloadkernel-tracking-qcomlt-audio.tar.gz
WIP: slimbus: ngd: add ssr supporttracking-qcomlt-audio
This patch adds ssr callback support and before shutdown event it will make sure the pending dma is finished and will update slave status to absent. Signed-off-by: Srinivas Kandagatla <srinivas.kandagatla@linaro.org>
-rw-r--r--drivers/slimbus/qcom-ngd-ctrl.c66
1 files changed, 65 insertions, 1 deletions
diff --git a/drivers/slimbus/qcom-ngd-ctrl.c b/drivers/slimbus/qcom-ngd-ctrl.c
index ba31920c1015..687ca21d5233 100644
--- a/drivers/slimbus/qcom-ngd-ctrl.c
+++ b/drivers/slimbus/qcom-ngd-ctrl.c
@@ -13,6 +13,9 @@
#include <linux/slimbus.h>
#include <linux/delay.h>
#include <linux/pm_runtime.h>
+#include <linux/mutex.h>
+#include <linux/notifier.h>
+#include <linux/remoteproc/qcom_rproc.h>
#include <linux/of.h>
#include <linux/io.h>
#include <linux/soc/qcom/qmi.h>
@@ -157,6 +160,9 @@ struct qcom_slim_ngd_ctrl {
struct work_struct m_work;
struct workqueue_struct *mwq;
spinlock_t tx_buf_lock;
+ struct mutex tx_lock;
+ struct notifier_block nb;
+ void *notifier;
enum qcom_slim_ngd_state state;
dma_addr_t rx_phys_base;
dma_addr_t tx_phys_base;
@@ -868,14 +874,18 @@ static int qcom_slim_ngd_xfer_msg(struct slim_controller *sctrl,
if (txn->msg && txn->msg->wbuf)
memcpy(puc, txn->msg->wbuf, txn->msg->num_bytes);
+ mutex_lock(&ctrl->tx_lock);
ret = qcom_slim_ngd_tx_msg_post(ctrl, pbuf, txn->rl);
- if (ret)
+ if (ret) {
+ mutex_unlock(&ctrl->tx_lock);
return ret;
+ }
timeout = wait_for_completion_timeout(&tx_sent, HZ);
if (!timeout) {
dev_err(sctrl->dev, "TX timed out:MC:0x%x,mt:0x%x", txn->mc,
txn->mt);
+ mutex_unlock(&ctrl->tx_lock);
return -ETIMEDOUT;
}
@@ -884,10 +894,12 @@ static int qcom_slim_ngd_xfer_msg(struct slim_controller *sctrl,
if (!timeout) {
dev_err(sctrl->dev, "TX timed out:MC:0x%x,mt:0x%x",
txn->mc, txn->mt);
+ mutex_unlock(&ctrl->tx_lock);
return -ETIMEDOUT;
}
}
+ mutex_unlock(&ctrl->tx_lock);
return 0;
}
@@ -1200,6 +1212,45 @@ capability_retry:
}
}
+static int qcom_slim_ngd_update_device_status(struct device *dev, void *null)
+{
+ slim_report_absent(to_slim_device(dev));
+
+ return 0;
+}
+
+static int qcom_slim_ngd_ssr_notify(struct notifier_block *nb,
+ unsigned long action,
+ void *data)
+{
+ struct qcom_slim_ngd_ctrl *ctrl = container_of(nb,
+ struct qcom_slim_ngd_ctrl, nb);
+ struct device *dev = ctrl->dev;
+
+ switch (action) {
+ case QCOM_SSR_BEFORE_SHUTDOWN:
+ /* Make sure the last dma xfer is finished */
+ mutex_lock(&ctrl->tx_lock);
+ device_for_each_child(ctrl->ctrl.dev, NULL,
+ qcom_slim_ngd_update_device_status);
+ ctrl->state = QCOM_SLIM_NGD_CTRL_DOWN;
+ qcom_slim_ngd_exit_dma(ctrl);
+ mutex_unlock(&ctrl->tx_lock);
+ break;
+
+ case QCOM_SSR_BEFORE_POWERUP:
+ case QCOM_SSR_AFTER_POWERUP:
+ case QCOM_SSR_AFTER_SHUTDOWN:
+ break;
+
+ default:
+ dev_err(dev, "received unrecognized event %lu\n", action);
+ break;
+ }
+
+ return NOTIFY_OK;
+}
+
static int qcom_slim_ngd_runtime_resume(struct device *dev)
{
struct qcom_slim_ngd_ctrl *ctrl = dev_get_drvdata(dev);
@@ -1420,6 +1471,7 @@ static int qcom_slim_ngd_ctrl_probe(struct platform_device *pdev)
{
struct device *dev = &pdev->dev;
struct qcom_slim_ngd_ctrl *ctrl;
+ const char *subsys_name;
struct resource *res;
int ret;
@@ -1447,6 +1499,17 @@ static int qcom_slim_ngd_ctrl_probe(struct platform_device *pdev)
return ret;
}
+ ret = of_property_read_string(dev->of_node, "qcom,subsys-name",
+ &subsys_name);
+ if (ret)
+ subsys_name = "lpass";
+
+ ctrl->nb.notifier_call = qcom_slim_ngd_ssr_notify;
+
+ ctrl->notifier = qcom_register_ssr_notifier(subsys_name, &ctrl->nb);
+ if (IS_ERR(ctrl->notifier))
+ return PTR_ERR(ctrl->notifier);
+
ctrl->dev = dev;
ctrl->framer.rootfreq = SLIM_ROOT_FREQ >> 3;
ctrl->framer.superfreq =
@@ -1460,6 +1523,7 @@ static int qcom_slim_ngd_ctrl_probe(struct platform_device *pdev)
ctrl->ctrl.wakeup = NULL;
ctrl->state = QCOM_SLIM_NGD_CTRL_DOWN;
+ mutex_init(&ctrl->tx_lock);
spin_lock_init(&ctrl->tx_buf_lock);
init_completion(&ctrl->reconf);
init_completion(&ctrl->qmi.qmi_comp);