From: Sagar Dharia <sdharia@codeaurora.org>
To: gregkh@linuxfoundation.org, bp@suse.de, poeschel@lemonage.de,
sdharia@codeaurora.org, treding@nvidia.com, broonie@kernel.org,
gong.chen@linux.intel.com, andreas.noever@gmail.com,
alan@linux.intel.com, mathieu.poirier@linaro.org,
daniel@ffwll.ch, oded.gabbay@amd.com, jkosina@suse.cz,
sharon.dvir1@mail.huji.ac.il, joe@perches.com,
davem@davemloft.net, james.hogan@imgtec.com,
michael.opdenacker@free-electrons.com,
daniel.thompson@linaro.org, linux-kernel@vger.kernel.org
Cc: nkaje@codeaurora.org, kheitke@audience.com,
mlocke@codeaurora.org, agross@codeaurora.org,
linux-arm-msm@vger.kernel.org
Subject: [PATCH V2 5/6] slimbus: Add support for 'clock-pause' feature
Date: Tue, 16 Jun 2015 19:46:03 -0600 [thread overview]
Message-ID: <1434505564-14333-6-git-send-email-sdharia@codeaurora.org> (raw)
In-Reply-To: <1434505564-14333-1-git-send-email-sdharia@codeaurora.org>
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>
---
drivers/slimbus/slimbus.c | 109 ++++++++++++++++++++++++++++++++++++++++++++++
include/linux/slimbus.h | 65 +++++++++++++++++++++++++++
2 files changed, 174 insertions(+)
diff --git a/drivers/slimbus/slimbus.c b/drivers/slimbus/slimbus.c
index d74dfec..3cfa414 100644
--- a/drivers/slimbus/slimbus.c
+++ b/drivers/slimbus/slimbus.c
@@ -436,7 +436,9 @@ static int slim_register_controller(struct slim_controller *ctrl)
ctrl->min_cg = SLIM_MIN_CLK_GEAR;
if (!ctrl->max_cg)
ctrl->max_cg = SLIM_MAX_CLK_GEAR;
+ init_completion(&ctrl->sched.pause_comp);
mutex_init(&ctrl->m_ctrl);
+ mutex_init(&ctrl->sched.m_reconf);
ret = device_register(&ctrl->dev);
if (ret)
goto out_list;
@@ -1059,6 +1061,113 @@ int slim_request_clear_inf_element(struct slim_device *sb,
}
EXPORT_SYMBOL(slim_request_clear_inf_element);
+/**
+ * slim_ctrl_clk_pause: Called by slimbus controller to enter/exit 'clock pause'
+ * Slimbus specification needs this sequence to turn-off clocks for the bus.
+ * The sequence involves sending 3 broadcast messages (reconfiguration
+ * sequence) to inform all devices on the bus.
+ * To exit clock-pause, controller typically wakes up active framer device.
+ * @ctrl: controller requesting bus to be paused or woken up
+ * @wakeup: Wakeup this controller from clock pause.
+ * @restart: Restart time value per spec used for clock pause. This value
+ * isn't used when controller is to be woken up.
+ * This API executes clock pause reconfiguration sequence if wakeup is false.
+ * If wakeup is true, controller's wakeup is called.
+ * For entering clock-pause, -EBUSY is returned if a message txn in pending.
+ */
+int slim_ctrl_clk_pause(struct slim_controller *ctrl, bool wakeup, u8 restart)
+{
+ int i, ret = 0;
+ unsigned long flags;
+ struct slim_sched *sched = &ctrl->sched;
+ struct slim_val_inf msg = {0, 0, NULL, NULL, NULL, NULL};
+
+ DEFINE_SLIM_BCAST_TXN(txn, SLIM_MSG_MC_BEGIN_RECONFIGURATION,
+ 3, SLIM_LA_MANAGER, &msg);
+
+ if (wakeup == false && restart > SLIM_CLK_UNSPECIFIED)
+ return -EINVAL;
+ mutex_lock(&sched->m_reconf);
+ if (wakeup) {
+ if (sched->clk_state == SLIM_CLK_ACTIVE) {
+ mutex_unlock(&sched->m_reconf);
+ return 0;
+ }
+ /**
+ * Fine-tune calculation based on clock gear,
+ * message-bandwidth after bandwidth management
+ */
+ ret = wait_for_completion_timeout(&sched->pause_comp,
+ msecs_to_jiffies(100));
+ if (!ret) {
+ mutex_unlock(&sched->m_reconf);
+ pr_err("Previous clock pause did not finish");
+ return -ETIMEDOUT;
+ }
+ ret = 0;
+ /**
+ * Slimbus framework will call controller wakeup
+ * Controller should make sure that it sets active framer
+ * out of clock pause
+ */
+ if (sched->clk_state == SLIM_CLK_PAUSED && ctrl->wakeup)
+ ret = ctrl->wakeup(ctrl);
+ if (!ret)
+ sched->clk_state = SLIM_CLK_ACTIVE;
+ mutex_unlock(&sched->m_reconf);
+ return ret;
+ }
+
+ /* already paused */
+ if (ctrl->sched.clk_state == SLIM_CLK_PAUSED) {
+ mutex_unlock(&sched->m_reconf);
+ return 0;
+ }
+
+ spin_lock_irqsave(&ctrl->txn_lock, flags);
+ for (i = 0; i < ctrl->last_tid; i++) {
+ /* Pending response for a message */
+ if (ctrl->txnt[i]) {
+ spin_unlock_irqrestore(&ctrl->txn_lock, flags);
+ mutex_unlock(&sched->m_reconf);
+ return -EBUSY;
+ }
+ }
+ spin_unlock_irqrestore(&ctrl->txn_lock, flags);
+
+ sched->clk_state = SLIM_CLK_ENTERING_PAUSE;
+
+ /* clock pause sequence */
+ ret = slim_processtxn(ctrl, &txn);
+ if (ret)
+ goto clk_pause_ret;
+
+ txn.mc = SLIM_MSG_MC_NEXT_PAUSE_CLOCK;
+ txn.rl = 4;
+ msg.num_bytes = 1;
+ msg.wbuf = &restart;
+ ret = slim_processtxn(ctrl, &txn);
+ if (ret)
+ goto clk_pause_ret;
+
+ txn.mc = SLIM_MSG_MC_RECONFIGURE_NOW;
+ txn.rl = 3;
+ msg.num_bytes = 1;
+ msg.wbuf = NULL;
+ ret = slim_processtxn(ctrl, &txn);
+
+clk_pause_ret:
+ if (ret) {
+ sched->clk_state = SLIM_CLK_ACTIVE;
+ } else {
+ sched->clk_state = SLIM_CLK_PAUSED;
+ complete(&sched->pause_comp);
+ }
+ mutex_unlock(&sched->m_reconf);
+ return ret;
+}
+EXPORT_SYMBOL(slim_ctrl_clk_pause);
+
MODULE_LICENSE("GPL v2");
MODULE_VERSION("0.1");
MODULE_DESCRIPTION("Slimbus module");
diff --git a/include/linux/slimbus.h b/include/linux/slimbus.h
index 924cdd3..f1099c5 100644
--- a/include/linux/slimbus.h
+++ b/include/linux/slimbus.h
@@ -114,11 +114,21 @@ struct slim_addrt {
#define SLIM_MSG_MC_REPLY_VALUE 0x64
#define SLIM_MSG_MC_CHANGE_VALUE 0x68
+/* Clock pause Reconfiguration messages */
+#define SLIM_MSG_MC_BEGIN_RECONFIGURATION 0x40
+#define SLIM_MSG_MC_NEXT_PAUSE_CLOCK 0x4A
+#define SLIM_MSG_MC_RECONFIGURE_NOW 0x5F
+
/* Destination type Values */
#define SLIM_MSG_DEST_LOGICALADDR 0
#define SLIM_MSG_DEST_ENUMADDR 1
#define SLIM_MSG_DEST_BROADCAST 3
+/* Clock pause values per slimbus spec */
+#define SLIM_CLK_FAST 0
+#define SLIM_CLK_CONST_PHASE 1
+#define SLIM_CLK_UNSPECIFIED 2
+
/**
* struct slim_val_inf: Slimbus value or information element
* @start_offset: Specifies starting offset in information/value element map
@@ -163,6 +173,39 @@ struct slim_msg_txn {
};
/**
+ * enum slim_clk_state: Slimbus controller's clock state used internally for
+ * maintaining current clock state.
+ * @SLIM_CLK_ACTIVE: Slimbus clock is active
+ * @SLIM_CLK_ENTERING_PAUSE: Slimbus clock pause sequence is being sent on the
+ * bus. If this succeeds, state changes to SLIM_CLK_PAUSED. If the
+ * transition fails, state changes back to SLIM_CLK_ACTIVE
+ * @SLIM_CLK_PAUSED: Slimbus controller clock has paused.
+ */
+enum slim_clk_state {
+ SLIM_CLK_ACTIVE,
+ SLIM_CLK_ENTERING_PAUSE,
+ SLIM_CLK_PAUSED,
+};
+
+/**
+ * struct slim_sched: Framework uses this structure internally for scheduling.
+ * @clk_state: Controller's clock state from enum slim_clk_state
+ * @pause_comp: Signals completion of clock pause sequence. This is useful when
+ * client tries to call slimbus transaction when controller is entering
+ * clock pause.
+ * @m_reconf: This mutex is held until current reconfiguration (data channel
+ * scheduling, message bandwidth reservation) is done. Message APIs can
+ * use the bus concurrently when this mutex is held since elemental access
+ * messages can be sent on the bus when reconfiguration is in progress.
+ */
+struct slim_sched {
+ int clkgear;
+ enum slim_clk_state clk_state;
+ struct completion pause_comp;
+ struct mutex m_reconf;
+};
+
+/**
* struct slim_controller: Controls every instance of SLIMbus
* (similar to 'master' on SPI)
* 'Manager device' is responsible for device management, bandwidth
@@ -200,6 +243,7 @@ struct slim_msg_txn {
* @txnt: Table of transactions having transaction ID
* @txn_lock: Lock to protect table of transactions
* @last_tid: size of the table txnt (can't grow beyond 256 since TID is 8-bits)
+ * @sched: scheduler structure used by the controller
* @dev_released: completion used to signal when sysfs has released this
* controller so that it can be deleted during shutdown
* @xfer_msg: Transfer a message on this controller (this can be a broadcast
@@ -211,6 +255,9 @@ struct slim_msg_txn {
* @get_laddr: It is possible that controller needs to set fixed logical
* address table and get_laddr can be used in that case so that controller
* can do this assignment.
+ * @wakeup: This function pointer implements controller-specific procedure
+ * to wake it up from clock-pause. Framework will call this to bring
+ * the controller out of clock pause.
*/
struct slim_controller {
struct device dev;
@@ -229,6 +276,7 @@ struct slim_controller {
struct slim_val_inf *txnt[SLIM_MAX_TXNS];
u8 last_tid;
spinlock_t txn_lock;
+ struct slim_sched sched;
struct completion dev_released;
int (*xfer_msg)(struct slim_controller *ctrl,
struct slim_msg_txn *txn);
@@ -236,6 +284,7 @@ struct slim_controller {
struct slim_eaddr *ea, u8 laddr);
int (*get_laddr)(struct slim_controller *ctrl,
struct slim_eaddr *ea, u8 *laddr);
+ int (*wakeup)(struct slim_controller *ctrl);
};
#define to_slim_controller(d) container_of(d, struct slim_controller, dev)
@@ -521,4 +570,20 @@ static inline bool slim_tid_txn(u8 mt, u8 mc)
}
/* end of message apis */
+/**
+ * slim_ctrl_clk_pause: Called by slimbus controller to enter/exit 'clock pause'
+ * Slimbus specification needs this sequence to turn-off clocks for the bus.
+ * The sequence involves sending 3 broadcast messages (reconfiguration
+ * sequence) to inform all devices on the bus.
+ * To exit clock-pause, controller typically wakes up active framer device.
+ * @ctrl: controller requesting bus to be paused or woken up
+ * @wakeup: Wakeup this controller from clock pause.
+ * @restart: Restart time value per spec used for clock pause. This value
+ * isn't used when controller is to be woken up.
+ * This API executes clock pause reconfiguration sequence if wakeup is false.
+ * If wakeup is true, controller's wakeup is called.
+ * For entering clock-pause, -EBUSY is returned if a message txn in pending.
+ */
+int slim_ctrl_clk_pause(struct slim_controller *ctrl, bool wakeup, u8 restart);
+
#endif /* _LINUX_SLIMBUS_H */
--
1.8.2.1
next prev parent reply other threads:[~2015-06-17 1:46 UTC|newest]
Thread overview: 16+ messages / expand[flat|nested] mbox.gz Atom feed top
2015-06-17 1:45 [PATCH V2 0/6] Introduce framework for SLIMbus device drivers Sagar Dharia
2015-06-17 1:45 ` [PATCH V2 1/6] SLIMbus: Device management on SLIMbus Sagar Dharia
2015-06-17 3:38 ` Joe Perches
2015-06-17 13:16 ` Mark Brown
2015-06-17 17:36 ` Sagar Dharia
2015-06-18 21:39 ` Srinivas Kandagatla
2015-06-19 8:22 ` Daniel Thompson
2015-06-17 1:46 ` [PATCH V2 2/6] of/slimbus: OF helper for SLIMbus Sagar Dharia
2015-06-17 13:09 ` Mark Brown
2015-06-17 17:01 ` Sagar Dharia
2015-06-17 1:46 ` [PATCH V2 3/6] slimbus: Add messaging APIs to slimbus framework Sagar Dharia
2015-06-17 1:46 ` [PATCH V2 4/6] slim: qcom: Add Qualcomm Slimbus controller driver Sagar Dharia
2015-06-17 13:53 ` Mark Brown
2015-06-28 19:13 ` Sagar Dharia
2015-06-17 1:46 ` Sagar Dharia [this message]
2015-06-17 1:46 ` [PATCH V2 6/6] slim: qcom: Add runtime-pm support using clock-pause feature Sagar Dharia
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=1434505564-14333-6-git-send-email-sdharia@codeaurora.org \
--to=sdharia@codeaurora.org \
--cc=agross@codeaurora.org \
--cc=alan@linux.intel.com \
--cc=andreas.noever@gmail.com \
--cc=bp@suse.de \
--cc=broonie@kernel.org \
--cc=daniel.thompson@linaro.org \
--cc=daniel@ffwll.ch \
--cc=davem@davemloft.net \
--cc=gong.chen@linux.intel.com \
--cc=gregkh@linuxfoundation.org \
--cc=james.hogan@imgtec.com \
--cc=jkosina@suse.cz \
--cc=joe@perches.com \
--cc=kheitke@audience.com \
--cc=linux-arm-msm@vger.kernel.org \
--cc=linux-kernel@vger.kernel.org \
--cc=mathieu.poirier@linaro.org \
--cc=michael.opdenacker@free-electrons.com \
--cc=mlocke@codeaurora.org \
--cc=nkaje@codeaurora.org \
--cc=oded.gabbay@amd.com \
--cc=poeschel@lemonage.de \
--cc=sharon.dvir1@mail.huji.ac.il \
--cc=treding@nvidia.com \
/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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).