aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSrinivas Kandagatla <srinivas.kandagatla@linaro.org>2016-04-07 16:41:46 +0100
committerSrinivas Kandagatla <srinivas.kandagatla@linaro.org>2016-04-07 20:37:13 +0100
commit0b186dd99e8c42b7c721997c7ac910f89f8d0615 (patch)
treefa51024bd2463277050962a90e079fa157597ebb
parent43e5a9f4428d6eac9177979dd8b942d8bba4d752 (diff)
WIP: mmc: mmci: add qcom specific program end support
This patch adds support to programend interrupt which is very specific to QCOM integration. This interrupt is use as busy signal when a command forces the card to enter into programming state like CMD6 writing to ext_csd registers. This also fixes the __mmc_switch timeout issue reproted with latest versions of the eMMC used on DB600c board. This is just a WIP patch, will be cleaned up soon. Signed-off-by: Srinivas Kandagatla <srinivas.kandagatla@linaro.org>
-rw-r--r--drivers/mmc/host/mmci.c17
-rw-r--r--drivers/mmc/host/mmci.h11
2 files changed, 25 insertions, 3 deletions
diff --git a/drivers/mmc/host/mmci.c b/drivers/mmc/host/mmci.c
index 2e6c96845c9a6..05aa2b01d09d9 100644
--- a/drivers/mmc/host/mmci.c
+++ b/drivers/mmc/host/mmci.c
@@ -814,7 +814,7 @@ static void mmci_start_data(struct mmci_host *host, struct mmc_data *data)
datactrl = MCI_DPSM_ENABLE | blksz_bits << 4;
if (data->flags & MMC_DATA_READ)
- datactrl |= MCI_DPSM_DIRECTION;
+ datactrl |= MCI_DPSM_DIRECTION | MCI_QCOM_RX_DATA_PEND;
if (host->mmc->card && mmc_card_sdio(host->mmc->card)) {
u32 clk;
@@ -896,6 +896,11 @@ mmci_start_command(struct mmci_host *host, struct mmc_command *cmd, u32 c)
if (/*interrupt*/0)
c |= MCI_CPSM_INTERRUPT;
+ if ((cmd->flags & MMC_RSP_R1B) == MMC_RSP_R1B) {
+ c |= MCI_QCOM_CSPM_PROGENA;
+ host->prog_enable = true;
+ }
+
if (mmc_cmd_type(cmd) == MMC_CMD_ADTC)
c |= host->variant->data_cmd_enable;
@@ -990,9 +995,17 @@ mmci_cmd_irq(struct mmci_host *host, struct mmc_command *cmd,
busy_resp = host->variant->busy_detect && (cmd->flags & MMC_RSP_BUSY);
if (!((status|host->busy_status) & (MCI_CMDCRCFAIL|MCI_CMDTIMEOUT|
- MCI_CMDSENT|MCI_CMDRESPEND)))
+ MCI_CMDSENT|MCI_CMDRESPEND | MCI_QCOM_PROGDONE)))
return;
+ if (host->prog_enable) {
+ if(status & MCI_QCOM_PROGDONE) {
+ host->prog_enable = false;
+ } else {
+ return;
+ }
+ }
+
/* Check if we need to wait for busy completion. */
if (host->busy_status && (status & MCI_ST_CARDBUSY))
return;
diff --git a/drivers/mmc/host/mmci.h b/drivers/mmc/host/mmci.h
index a1f5e4f49e2a3..0c8644ae52373 100644
--- a/drivers/mmc/host/mmci.h
+++ b/drivers/mmc/host/mmci.h
@@ -64,6 +64,7 @@
#define MCI_ST_CE_ATACMD (1 << 14)
/* Modified on Qualcomm Integrations */
+#define MCI_QCOM_CSPM_PROGENA BIT(11)
#define MCI_QCOM_CSPM_DATCMD BIT(12)
#define MCI_QCOM_CSPM_MCIABORT BIT(13)
#define MCI_QCOM_CSPM_CCSENABLE BIT(14)
@@ -95,6 +96,9 @@
#define MCI_ST_DPSM_BUSYMODE (1 << 14)
#define MCI_ST_DPSM_DDRMODE (1 << 15)
+#define MCI_QCOM_DATA_PEND (1 << 17)
+#define MCI_QCOM_RX_DATA_PEND (1 << 20)
+
#define MMCIDATACNT 0x030
#define MMCISTATUS 0x034
#define MCI_CMDCRCFAIL (1 << 0)
@@ -124,6 +128,9 @@
#define MCI_ST_CEATAEND (1 << 23)
#define MCI_ST_CARDBUSY (1 << 24)
+/* Extended status bits for the QCOM variants */
+#define MCI_QCOM_PROGDONE (1 << 23)
+
#define MMCICLEAR 0x038
#define MCI_CMDCRCFAILCLR (1 << 0)
#define MCI_DATACRCFAILCLR (1 << 1)
@@ -169,6 +176,7 @@
#define MCI_ST_CEATAENDMASK (1 << 23)
#define MCI_ST_BUSYEND (1 << 24)
+#define MCI_QCOM_PROGDONEMASK (1 << 23)
#define MMCIMASK1 0x040
#define MMCIFIFOCNT 0x048
#define MMCIFIFO 0x080 /* to 0x0bc */
@@ -176,7 +184,7 @@
#define MCI_IRQENABLE \
(MCI_CMDCRCFAILMASK|MCI_DATACRCFAILMASK|MCI_CMDTIMEOUTMASK| \
MCI_DATATIMEOUTMASK|MCI_TXUNDERRUNMASK|MCI_RXOVERRUNMASK| \
- MCI_CMDRESPENDMASK|MCI_CMDSENTMASK|MCI_STARTBITERRMASK)
+ MCI_CMDRESPENDMASK| MCI_QCOM_PROGDONEMASK |MCI_CMDSENTMASK|MCI_STARTBITERRMASK)
/* These interrupts are directed to IRQ1 when two IRQ lines are available */
#define MCI_IRQ1MASK \
@@ -204,6 +212,7 @@ struct mmci_host {
struct mmc_host *mmc;
struct clk *clk;
bool singleirq;
+ bool prog_enable;
spinlock_t lock;