From 4b14e62ad3c9e6e6774517f4077e197c0537fb07 Mon Sep 17 00:00:00 2001 From: Sagar Dharia Date: Mon, 11 Dec 2017 23:43:01 +0000 Subject: 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 Signed-off-by: Srinivas Kandagatla Reviwed-by: Mark Brown Signed-off-by: Greg Kroah-Hartman --- drivers/slimbus/messaging.c | 35 ++++++++++++++++++++++++++++++++++- 1 file changed, 34 insertions(+), 1 deletion(-) (limited to 'drivers/slimbus/messaging.c') 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 +#include #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); -- cgit