This patch is added the use_hold_reg bit in CMD register.

In upper version than 2.40a, bit[29] of CMD register is used the use_hold_reg.
Some SoC is affected by this bit.
(This bit means whether use hold register when send data and cmd.
 And related with cclk_in_drv phase)

Signed-off-by: Jaehoon Chung <jh80.ch...@samsung.com>
Signed-off-by: Kyungmin Park <kyungmin.p...@samsung.com>
---
 drivers/mmc/host/dw_mmc.c  |   36 ++++++++++++++++++++++++++++++++++++
 drivers/mmc/host/dw_mmc.h  |    1 +
 include/linux/mmc/dw_mmc.h |    3 +++
 3 files changed, 40 insertions(+), 0 deletions(-)

diff --git a/drivers/mmc/host/dw_mmc.c b/drivers/mmc/host/dw_mmc.c
index feafa2d..426171f 100644
--- a/drivers/mmc/host/dw_mmc.c
+++ b/drivers/mmc/host/dw_mmc.c
@@ -265,11 +265,45 @@ static u32 dw_mci_prepare_command(struct mmc_host *mmc, 
struct mmc_command *cmd)
 static void dw_mci_start_command(struct dw_mci *host,
                                 struct mmc_command *cmd, u32 cmd_flags)
 {
+       struct dw_mci_slot *slot = host->cur_slot;
+       struct mmc_ios *ios = &slot->mmc->ios;
+
        host->cmd = cmd;
        dev_vdbg(&host->dev,
                 "start command: ARGR=0x%08x CMDR=0x%08x\n",
                 cmd->arg, cmd_flags);
 
+       if (host->quirks & DW_MCI_QUIRK_USE_CLKSEL_REG) {
+               /*
+                * If use HOLD register and SDR12/SDSR25,
+                * CMD and DATA sent to card through HOLD register by default.
+                * But if mode is SDR50/DDR50/SDR104,
+                * only use the hold register when cclk_in_drv value is upper 
than 0.
+                */
+               switch (ios->timing) {
+               case MMC_TIMING_UHS_SDR50:
+               case MMC_TIMING_UHS_DDR50:
+                       if (host->pdata->get_clk_drv)
+                               if ((host->pdata->get_clk_drv(host) &&
+                                               host->use_hold_reg)) {
+                                       cmd_flags |= SDMMC_CMD_USE_HOLD_REG;
+                                       break;
+                               }
+
+                       cmd_flags &= ~SDMMC_CMD_USE_HOLD_REG;
+                       break;
+               case MMC_TIMING_UHS_SDR104:
+               case MMC_TIMING_UHS_SDR12:
+               case MMC_TIMING_UHS_SDR25:
+                       if (host->use_hold_reg) {
+                               cmd_flags |= SDMMC_CMD_USE_HOLD_REG;
+                               break;
+                       }
+               default:
+                       cmd_flags &= ~SDMMC_CMD_USE_HOLD_REG;
+               }
+       }
+
        mci_writel(host, CMDARG, cmd->arg);
        wmb();
 
@@ -2018,6 +2052,8 @@ int dw_mci_probe(struct dw_mci *host)
                host->data_shift = 2;
        }
 
+       host->use_hold_reg = (mci_readl(host, HCON) >> 22) & 0x1;
+
        /* Reset all blocks */
        if (!mci_wait_reset(&host->dev, host))
                return -ENODEV;
diff --git a/drivers/mmc/host/dw_mmc.h b/drivers/mmc/host/dw_mmc.h
index b6a1a78..cc905ee 100644
--- a/drivers/mmc/host/dw_mmc.h
+++ b/drivers/mmc/host/dw_mmc.h
@@ -111,6 +111,7 @@
 #define SDMMC_INT_ERROR                        0xbfc2
 /* Command register defines */
 #define SDMMC_CMD_START                        BIT(31)
+#define SDMMC_CMD_USE_HOLD_REG         BIT(29)
 #define SDMMC_CMD_CCS_EXP              BIT(23)
 #define SDMMC_CMD_CEATA_RD             BIT(22)
 #define SDMMC_CMD_UPD_CLK              BIT(21)
diff --git a/include/linux/mmc/dw_mmc.h b/include/linux/mmc/dw_mmc.h
index f20979c..803a80d 100644
--- a/include/linux/mmc/dw_mmc.h
+++ b/include/linux/mmc/dw_mmc.h
@@ -156,6 +156,7 @@ struct dw_mci {
        u32                     fifoth_val;
        u16                     verid;
        u16                     data_offset;
+       bool                    use_hold_reg;
        struct device           dev;
        struct dw_mci_board     *pdata;
        struct dw_mci_slot      *slot[MAX_MCI_SLOTS];
@@ -201,6 +202,8 @@ struct dw_mci_dma_ops {
 #define DW_MCI_QUIRK_HIGHSPEED                 BIT(2)
 /* Unreliable card detection */
 #define DW_MCI_QUIRK_BROKEN_CARD_DETECTION     BIT(3)
+/* To use the CLKSEL register for phase-shift */
+#define DW_MCI_QUIRK_USE_CLKSEL_REG            BIT(4)
 
 
 struct dma_pdata;
-- 
1.7.4.1
--
To unsubscribe from this list: send the line "unsubscribe linux-mmc" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to