summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAsutosh Das <asutoshd@codeaurora.org>2015-05-29 15:39:37 +0530
committerSubhash Jadavani <subhashj@codeaurora.org>2016-05-31 15:27:08 -0700
commitf052410b0bd6f04effc8d2c9c9323dda55d9c7da (patch)
treecdea594d02008ec07e287c7d7e484c8ee3b33535
parented1bdbadff70bc32ae279b9fa967094c2d784b56 (diff)
mmc: cmdq: trigger get queue status after dcmd
CMDQ spec defines periodic SEND_STATUS mechanism to poll on READY tasks in the device. When DAT lines are in IDLE the counter counts from its reset value to '0' and then triggers SEND_STATUS command. When CMD13 is completed and also the syncing of the device status to HCLK domain is done there is a 1 cycle pulse to reload the counter with timer reset value so that the counting can start over. In rare cases, when the 'done' pulse for reloading the counter happens in parallel to a BUSY state of direct command - the IDLE counter is not reloaded and can't trigger another CMD13. If this scenario happens when there are pending tasks which are not 'READY' yet - it can lead to a deadlock, since there is no other mechainsm to send CMD13, and CQE will never get READY on the pending tasks. Hence, trigger a send status command after DCMD is completed as a work-around to the above issue. Change-Id: I4e8530e72c8bf581ffaeed7d35d8b8c61d282ffa Signed-off-by: Asutosh Das <asutoshd@codeaurora.org>
-rw-r--r--drivers/mmc/host/cmdq_hci.c5
-rw-r--r--drivers/mmc/host/cmdq_hci.h3
2 files changed, 8 insertions, 0 deletions
diff --git a/drivers/mmc/host/cmdq_hci.c b/drivers/mmc/host/cmdq_hci.c
index 77aa31522e1e..9710abab69e2 100644
--- a/drivers/mmc/host/cmdq_hci.c
+++ b/drivers/mmc/host/cmdq_hci.c
@@ -185,6 +185,8 @@ static void cmdq_dumpregs(struct cmdq_host *cq_host)
pr_err(DRV_NAME ": Resp idx 0x%08x | Resp arg: 0x%08x\n",
cmdq_readl(cq_host, CQCRI),
cmdq_readl(cq_host, CQCRA));
+ pr_err(DRV_NAME": Vendor cfg 0x%08x\n",
+ cmdq_readl(cq_host, CQ_VENDOR_CFG));
pr_err(DRV_NAME ": ===========================================\n");
cmdq_dump_debug_ram(cq_host);
@@ -639,6 +641,9 @@ static void cmdq_finish_data(struct mmc_host *mmc, unsigned int tag)
if (tag == cq_host->dcmd_slot)
mrq->cmd->resp[0] = cmdq_readl(cq_host, CQCRDCT);
+ if (mrq->cmdq_req->cmdq_req_flags & DCMD)
+ cmdq_writel(cq_host, cmdq_readl(cq_host, CQ_VENDOR_CFG) |
+ CMDQ_SEND_STATUS_TRIGGER, CQCTL);
mrq->done(mrq);
}
diff --git a/drivers/mmc/host/cmdq_hci.h b/drivers/mmc/host/cmdq_hci.h
index cbae969f9f60..610715f1875c 100644
--- a/drivers/mmc/host/cmdq_hci.h
+++ b/drivers/mmc/host/cmdq_hci.h
@@ -146,6 +146,9 @@
#define DAT_ADDR_LO(x) ((x & 0xFFFFFFFF) << 32)
#define DAT_ADDR_HI(x) ((x & 0xFFFFFFFF) << 0)
+#define CQ_VENDOR_CFG 0x100
+#define CMDQ_SEND_STATUS_TRIGGER (1 << 31)
+
struct cmdq_host {
const struct cmdq_host_ops *ops;
void __iomem *mmio;