aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/slimbus/messaging.c
diff options
context:
space:
mode:
authorSagar Dharia <sdharia@codeaurora.org>2017-12-11 23:43:01 +0000
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2017-12-19 11:01:03 +0100
commit4b14e62ad3c9e6e6774517f4077e197c0537fb07 (patch)
treec944a1253b54bee25c13fe0841bfdd4dd3bb641c /drivers/slimbus/messaging.c
parentslimbus: Add messaging APIs to slimbus framework (diff)
downloadlinux-dev-4b14e62ad3c9e6e6774517f4077e197c0537fb07.tar.xz
linux-dev-4b14e62ad3c9e6e6774517f4077e197c0537fb07.zip
slimbus: Add support for 'clock-pause' feature
Per SLIMbus specification, a reconfiguration sequence known as 'clock pause' needs to be broadcast over the bus while entering low- power mode. Clock-pause is initiated by the controller driver. To exit clock-pause, controller typically wakes up the framer device. Since wakeup precedure is controller-specific, framework calls it via controller's function pointer to invoke it. Signed-off-by: Sagar Dharia <sdharia@codeaurora.org> Signed-off-by: Srinivas Kandagatla <srinivas.kandagatla@linaro.org> Reviwed-by: Mark Brown <broonie@kernel.org> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Diffstat (limited to 'drivers/slimbus/messaging.c')
-rw-r--r--drivers/slimbus/messaging.c35
1 files changed, 34 insertions, 1 deletions
diff --git a/drivers/slimbus/messaging.c b/drivers/slimbus/messaging.c
index 031e67648d7c..755462a4c75e 100644
--- a/drivers/slimbus/messaging.c
+++ b/drivers/slimbus/messaging.c
@@ -4,6 +4,7 @@
*/
#include <linux/slab.h>
+#include <linux/pm_runtime.h>
#include "slimbus.h"
/**
@@ -46,6 +47,10 @@ void slim_msg_response(struct slim_controller *ctrl, u8 *reply, u8 tid, u8 len)
memcpy(msg->rbuf, reply, len);
if (txn->comp)
complete(txn->comp);
+
+ /* Remove runtime-pm vote now that response was received for TID txn */
+ pm_runtime_mark_last_busy(ctrl->dev);
+ pm_runtime_put_autosuspend(ctrl->dev);
}
EXPORT_SYMBOL_GPL(slim_msg_response);
@@ -65,10 +70,29 @@ EXPORT_SYMBOL_GPL(slim_msg_response);
int slim_do_transfer(struct slim_controller *ctrl, struct slim_msg_txn *txn)
{
DECLARE_COMPLETION_ONSTACK(done);
- bool need_tid;
+ bool need_tid = false, clk_pause_msg = false;
unsigned long flags;
int ret, tid, timeout;
+ /*
+ * do not vote for runtime-PM if the transactions are part of clock
+ * pause sequence
+ */
+ if (ctrl->sched.clk_state == SLIM_CLK_ENTERING_PAUSE &&
+ (txn->mt == SLIM_MSG_MT_CORE &&
+ txn->mc >= SLIM_MSG_MC_BEGIN_RECONFIGURATION &&
+ txn->mc <= SLIM_MSG_MC_RECONFIGURE_NOW))
+ clk_pause_msg = true;
+
+ if (!clk_pause_msg) {
+ ret = pm_runtime_get_sync(ctrl->dev);
+ if (ctrl->sched.clk_state != SLIM_CLK_ACTIVE) {
+ dev_err(ctrl->dev, "ctrl wrong state:%d, ret:%d\n",
+ ctrl->sched.clk_state, ret);
+ goto slim_xfer_err;
+ }
+ }
+
need_tid = slim_tid_txn(txn->mt, txn->mc);
if (need_tid) {
@@ -107,6 +131,15 @@ int slim_do_transfer(struct slim_controller *ctrl, struct slim_msg_txn *txn)
dev_err(ctrl->dev, "Tx:MT:0x%x, MC:0x%x, LA:0x%x failed:%d\n",
txn->mt, txn->mc, txn->la, ret);
+slim_xfer_err:
+ if (!clk_pause_msg && (!need_tid || ret == -ETIMEDOUT)) {
+ /*
+ * remove runtime-pm vote if this was TX only, or
+ * if there was error during this transaction
+ */
+ pm_runtime_mark_last_busy(ctrl->dev);
+ pm_runtime_mark_last_busy(ctrl->dev);
+ }
return ret;
}
EXPORT_SYMBOL_GPL(slim_do_transfer);