summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSagar Dharia <sdharia@codeaurora.org>2015-12-22 16:10:56 -0700
committerGerrit - the friendly Code Review server <code-review@localhost>2016-07-27 13:41:39 -0700
commit2a488ee4705936f3b8dba952e3aac3ebf73d6b93 (patch)
tree37260b52c8cb1793a2a3f25e08a65e9457eaf8eb
parent97442af04a66583690a7882cd1058b1efd3746ab (diff)
slim: msm: Handle slimbus HW noise during early boot-up
Capability exchange may timeout during boot due to noise on slimbus lines. Introduce retry mechanism to recover from this state. If the HW noise happens just after capability exchange is successful, make sure slimbus satellite HW powered on again by checking HW status during message transfer. Change-Id: I6ebf0ec78201551152bf6ac0d4372f36734a4708 Signed-off-by: Sagar Dharia <sdharia@codeaurora.org>
-rw-r--r--drivers/slimbus/slim-msm-ngd.c69
-rw-r--r--drivers/slimbus/slim-msm.h2
2 files changed, 61 insertions, 10 deletions
diff --git a/drivers/slimbus/slim-msm-ngd.c b/drivers/slimbus/slim-msm-ngd.c
index 98fce5e5c06a..2e6672326a77 100644
--- a/drivers/slimbus/slim-msm-ngd.c
+++ b/drivers/slimbus/slim-msm-ngd.c
@@ -299,6 +299,26 @@ static void slim_reinit_tx_msgq(struct msm_slim_ctrl *dev)
}
}
+static int ngd_check_hw_status(struct msm_slim_ctrl *dev)
+{
+ void __iomem *ngd = dev->base + NGD_BASE(dev->ctrl.nr, dev->ver);
+ u32 laddr = readl_relaxed(ngd + NGD_STATUS);
+ int ret = 0;
+
+ /* Lost logical addr due to noise */
+ if (!(laddr & NGD_LADDR)) {
+ SLIM_WARN(dev, "NGD lost LADDR: status:0x%x\n", laddr);
+ ret = ngd_slim_power_up(dev, false);
+
+ if (ret) {
+ SLIM_WARN(dev, "slim resume ret:%d, state:%d\n",
+ ret, dev->state);
+ ret = -EREMOTEIO;
+ }
+ }
+ return ret;
+}
+
static int ngd_xfer_msg(struct slim_controller *ctrl, struct slim_msg_txn *txn)
{
DECLARE_COMPLETION_ONSTACK(done);
@@ -351,7 +371,6 @@ static int ngd_xfer_msg(struct slim_controller *ctrl, struct slim_msg_txn *txn)
/* If txn is tried when controller is down, wait for ADSP to boot */
if (!report_sat) {
-
if (dev->state == MSM_CTRL_DOWN) {
u8 mc = (u8)txn->mc;
int timeout;
@@ -418,6 +437,12 @@ static int ngd_xfer_msg(struct slim_controller *ctrl, struct slim_msg_txn *txn)
msm_slim_put_ctrl(dev);
return -EREMOTEIO;
}
+ ret = ngd_check_hw_status(dev);
+ if (ret) {
+ mutex_unlock(&dev->tx_lock);
+ msm_slim_put_ctrl(dev);
+ return ret;
+ }
}
if (txn->mt == SLIM_MSG_MT_CORE &&
@@ -737,6 +762,14 @@ static int ngd_bulk_wr(struct slim_controller *ctrl, u8 la, u8 mt, u8 mc,
}
mutex_lock(&dev->tx_lock);
}
+
+ ret = ngd_check_hw_status(dev);
+ if (ret) {
+ mutex_unlock(&dev->tx_lock);
+ msm_slim_put_ctrl(dev);
+ return ret;
+ }
+
if (dev->use_tx_msgqs != MSM_MSGQ_ENABLED) {
SLIM_WARN(dev, "bulk wr not supported");
ret = -EPROTONOSUPPORT;
@@ -1080,6 +1113,7 @@ static void ngd_slim_setup(struct msm_slim_ctrl *dev)
} else {
if (dev->use_rx_msgqs == MSM_MSGQ_DISABLED)
goto setup_tx_msg_path;
+
if ((dev->use_rx_msgqs == MSM_MSGQ_ENABLED) &&
(cfg & NGD_CFG_RX_MSGQ_EN))
goto setup_tx_msg_path;
@@ -1185,7 +1219,7 @@ static void ngd_slim_rx(struct msm_slim_ctrl *dev, u8 *buf)
static int ngd_slim_power_up(struct msm_slim_ctrl *dev, bool mdm_restart)
{
void __iomem *ngd;
- int timeout, ret = 0;
+ int timeout, retries = 0, ret = 0;
enum msm_ctrl_state cur_state = dev->state;
u32 laddr;
u32 rx_msgq;
@@ -1203,16 +1237,24 @@ static int ngd_slim_power_up(struct msm_slim_ctrl *dev, bool mdm_restart)
}
}
+hw_init_retry:
/* No need to vote if contorller is not in low power mode */
if (!mdm_restart &&
(cur_state == MSM_CTRL_DOWN || cur_state == MSM_CTRL_ASLEEP)) {
ret = msm_slim_qmi_power_request(dev, true);
if (ret) {
- SLIM_ERR(dev, "SLIM QMI power request failed:%d\n",
- ret);
+ SLIM_WARN(dev, "SLIM power req failed:%d, retry:%d\n",
+ ret, retries);
+ msm_slim_qmi_power_request(dev, false);
+ if (retries < INIT_MX_RETRIES) {
+ retries++;
+ goto hw_init_retry;
+ }
return ret;
}
}
+ retries = 0;
+
if (!dev->ver) {
dev->ver = readl_relaxed(dev->base);
/* Version info in 16 MSbits */
@@ -1276,6 +1318,7 @@ static int ngd_slim_power_up(struct msm_slim_ctrl *dev, bool mdm_restart)
dev->state = MSM_CTRL_DOWN;
}
+capability_retry:
/*
* ADSP power collapse case (OR SSR), where HW was reset
* BAM programming will happen when capability message is received
@@ -1296,7 +1339,16 @@ static int ngd_slim_power_up(struct msm_slim_ctrl *dev, bool mdm_restart)
timeout = wait_for_completion_timeout(&dev->reconf, HZ);
if (!timeout) {
- SLIM_WARN(dev, "capability exchange timed-out\n");
+ u32 cfg = readl_relaxed(dev->base +
+ NGD_BASE(dev->ctrl.nr, dev->ver));
+ laddr = readl_relaxed(ngd + NGD_STATUS);
+ SLIM_WARN(dev,
+ "slim capability time-out:%d, stat:0x%x,cfg:0x%x\n",
+ retries, laddr, cfg);
+ if (retries < INIT_MX_RETRIES) {
+ retries++;
+ goto capability_retry;
+ }
return -ETIMEDOUT;
}
/* mutliple transactions waiting on slimbus to power up? */
@@ -1388,12 +1440,11 @@ capability_retry:
SLIM_INFO(dev,
"SLIM SAT: capability exchange successful\n");
- if (prev_state >= MSM_CTRL_ASLEEP)
- complete(&dev->reconf);
- else
+ if (prev_state < MSM_CTRL_ASLEEP)
SLIM_WARN(dev,
- "SLIM: unexpected capability, state:%d\n",
+ "capability due to noise, state:%d\n",
prev_state);
+ complete(&dev->reconf);
/* ADSP SSR, send device_up notifications */
if (prev_state == MSM_CTRL_DOWN)
complete(&dev->qmi.slave_notify);
diff --git a/drivers/slimbus/slim-msm.h b/drivers/slimbus/slim-msm.h
index 7859d1e79e39..fc0a8d23f573 100644
--- a/drivers/slimbus/slim-msm.h
+++ b/drivers/slimbus/slim-msm.h
@@ -67,7 +67,7 @@
#define SLIM_MSG_ASM_FIRST_WORD(l, mt, mc, dt, ad) \
((l) | ((mt) << 5) | ((mc) << 8) | ((dt) << 15) | ((ad) << 16))
-#define INIT_MX_RETRIES 10
+#define INIT_MX_RETRIES 3
#define DEF_RETRY_MS 10
#define MSM_CONCUR_MSG 8
#define SAT_CONCUR_MSG 8