summaryrefslogtreecommitdiffstats
path: root/drivers/slimbus/core.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/core.c
parentafbdcc7c384b0d446da08b1e0901dc176b41b9e0 (diff)
downloadlinux-4b14e62ad3c9e6e6774517f4077e197c0537fb07.tar.bz2
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/core.c')
-rw-r--r--drivers/slimbus/core.c16
1 files changed, 16 insertions, 0 deletions
diff --git a/drivers/slimbus/core.c b/drivers/slimbus/core.c
index 1accb20ed5cd..4988a8f4d905 100644
--- a/drivers/slimbus/core.c
+++ b/drivers/slimbus/core.c
@@ -9,6 +9,7 @@
#include <linux/init.h>
#include <linux/idr.h>
#include <linux/of.h>
+#include <linux/pm_runtime.h>
#include <linux/slimbus.h>
#include "slimbus.h"
@@ -218,6 +219,8 @@ int slim_register_controller(struct slim_controller *ctrl)
ida_init(&ctrl->laddr_ida);
idr_init(&ctrl->tid_idr);
mutex_init(&ctrl->lock);
+ mutex_init(&ctrl->sched.m_reconf);
+ init_completion(&ctrl->sched.pause_comp);
dev_dbg(ctrl->dev, "Bus [%s] registered:dev:%p\n",
ctrl->name, ctrl->dev);
@@ -249,6 +252,8 @@ int slim_unregister_controller(struct slim_controller *ctrl)
{
/* Remove all clients */
device_for_each_child(ctrl->dev, NULL, slim_ctrl_remove_device);
+ /* Enter Clock Pause */
+ slim_ctrl_clk_pause(ctrl, false, 0);
ida_simple_remove(&ctrl_ida, ctrl->id);
return 0;
@@ -416,6 +421,14 @@ int slim_device_report_present(struct slim_controller *ctrl,
struct slim_device *sbdev;
int ret;
+ ret = pm_runtime_get_sync(ctrl->dev);
+
+ if (ctrl->sched.clk_state != SLIM_CLK_ACTIVE) {
+ dev_err(ctrl->dev, "slim ctrl not active,state:%d, ret:%d\n",
+ ctrl->sched.clk_state, ret);
+ goto slimbus_not_active;
+ }
+
sbdev = slim_get_device(ctrl, e_addr);
if (IS_ERR(sbdev))
return -ENODEV;
@@ -427,6 +440,9 @@ int slim_device_report_present(struct slim_controller *ctrl,
ret = slim_device_alloc_laddr(sbdev, true);
+slimbus_not_active:
+ pm_runtime_mark_last_busy(ctrl->dev);
+ pm_runtime_put_autosuspend(ctrl->dev);
return ret;
}
EXPORT_SYMBOL_GPL(slim_device_report_present);