Merge "drivers: qcom: rpmh: Disallow wake votes in solver mode." into msm-4.9
diff --git a/drivers/soc/qcom/rpmh.c b/drivers/soc/qcom/rpmh.c
index e30c159..b9070bd 100644
--- a/drivers/soc/qcom/rpmh.c
+++ b/drivers/soc/qcom/rpmh.c
@@ -12,6 +12,7 @@
*/
#include <linux/atomic.h>
+#include <linux/delay.h>
#include <linux/interrupt.h>
#include <linux/kernel.h>
#include <linux/list.h>
@@ -70,6 +71,7 @@ struct rpmh_mbox {
struct rpmh_msg *msg_pool;
DECLARE_BITMAP(fast_req, RPMH_MAX_FAST_RES);
bool dirty;
+ bool in_solver_mode;
};
struct rpmh_client {
@@ -458,10 +460,21 @@ int rpmh_write_passthru(struct rpmh_client *rc, enum rpmh_state state,
int count = 0;
int ret, i, j, k;
bool complete_set;
+ unsigned long flags;
+ struct rpmh_mbox *rpm;
if (rpmh_standalone)
return 0;
+ /* Do not allow setting wake votes when in solver mode */
+ rpm = rc->rpmh;
+ spin_lock_irqsave(&rpm->lock, flags);
+ if (rpm->in_solver_mode && state == RPMH_WAKE_ONLY_STATE) {
+ spin_unlock_irqrestore(&rpm->lock, flags);
+ return -EIO;
+ }
+ spin_unlock_irqrestore(&rpm->lock, flags);
+
while (n[count++])
;
count--;
@@ -526,6 +539,43 @@ int rpmh_write_passthru(struct rpmh_client *rc, enum rpmh_state state,
EXPORT_SYMBOL(rpmh_write_passthru);
/**
+ * rpmh_mode_solver_set: Indicate that the RSC controller hardware has
+ * been configured to be in solver mode
+ *
+ * @rc: The RPMH handle
+ * @enable: Boolean value indicating if the controller is in solver mode.
+ *
+ * When solver mode is enabled, passthru API will not be able to send wake
+ * votes, just awake and active votes.
+ */
+int rpmh_mode_solver_set(struct rpmh_client *rc, bool enable)
+{
+ struct rpmh_mbox *rpm;
+ unsigned long flags;
+
+ if (IS_ERR_OR_NULL(rc))
+ return -EINVAL;
+
+ if (rpmh_standalone)
+ return 0;
+
+ rpm = rc->rpmh;
+ do {
+ spin_lock_irqsave(&rpm->lock, flags);
+ if (mbox_controller_is_idle(rc->chan)) {
+ rpm->in_solver_mode = enable;
+ spin_unlock_irqrestore(&rpm->lock, flags);
+ break;
+ }
+ spin_unlock_irqrestore(&rpm->lock, flags);
+ udelay(10);
+ } while (1);
+
+ return 0;
+}
+EXPORT_SYMBOL(rpmh_mode_solver_set);
+
+/**
* rpmh_write_control: Write async control commands to the controller
*
* @rc: The RPMh handle got from rpmh_get_dev_channel
diff --git a/include/soc/qcom/rpmh.h b/include/soc/qcom/rpmh.h
index 34434fd..75e6ccd 100644
--- a/include/soc/qcom/rpmh.h
+++ b/include/soc/qcom/rpmh.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2016, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2016-2017, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -34,6 +34,8 @@ int rpmh_write_async(struct rpmh_client *rc, enum rpmh_state state,
int rpmh_write_passthru(struct rpmh_client *rc, enum rpmh_state state,
struct tcs_cmd *cmd, int *n);
+int rpmh_mode_solver_set(struct rpmh_client *rc, bool enable);
+
int rpmh_write_control(struct rpmh_client *rc, struct tcs_cmd *cmd, int n);
int rpmh_invalidate(struct rpmh_client *rc);
@@ -70,6 +72,9 @@ static inline int rpmh_write_passthru(struct rpmh_client *rc,
enum rpmh_state state, struct tcs_cmd *cmd, int *n)
{ return -ENODEV; }
+static inline int rpmh_mode_solver_set(struct rpmh_client *rc, bool enable)
+{ return -ENODEV; }
+
static inline int rpmh_write_control(struct rpmh_client *rc,
struct tcs_cmd *cmd, int n)
{ return -ENODEV; }