mmc: msm_sdcc: Add new soft reset mechanism for SDCCv4
Newer versions of SDCCv4 controller has added a soft
reset mechanism to reset the controller state machine
or reset the entire controller to default power on state.
MCI_POWER[SW_RST] - The impact of this reset bit will be
similar to the impact of the reset by doing clk_reset() on
host controller clock (HCLK). With this all SW registers
and all internal logic is reset.
MCI_POWER[SW_RST_CONFIG] - Resets the controller state machines
without resetting configuration registers (MCI_POWER, MCI_CLK,
MCI_INT_MASKn).
Change-Id: I7fd13e736b23dff16c20bd9f865ca97e7daaf304
Signed-off-by: Sujit Reddy Thumma <sthumma@codeaurora.org>
diff --git a/drivers/mmc/host/msm_sdcc.h b/drivers/mmc/host/msm_sdcc.h
index dc32d1c..baeabd2 100644
--- a/drivers/mmc/host/msm_sdcc.h
+++ b/drivers/mmc/host/msm_sdcc.h
@@ -38,6 +38,8 @@
#define MCI_PWR_UP 0x02
#define MCI_PWR_ON 0x03
#define MCI_OD (1 << 6)
+#define MCI_SW_RST (1 << 7)
+#define MCI_SW_RST_CFG (1 << 8)
#define MMCICLOCK 0x004
#define MCI_CLK_ENABLE (1 << 8)
@@ -363,14 +365,12 @@
u32 pwr;
struct mmc_platform_data *plat;
- u32 sdcc_version;
+ unsigned int hw_caps;
unsigned int oldstat;
struct msmsdcc_dma_data dma;
struct msmsdcc_sps_data sps;
- bool is_dma_mode;
- bool is_sps_mode;
struct msmsdcc_pio_data pio;
#ifdef CONFIG_HAS_EARLYSUSPEND
@@ -415,6 +415,47 @@
struct device_attribute polling;
};
+#define MSMSDCC_VERSION_MASK 0xFFFF
+#define MSMSDCC_DMA_SUP (1 << 0)
+#define MSMSDCC_SPS_BAM_SUP (1 << 1)
+#define MSMSDCC_SOFT_RESET (1 << 2)
+#define MSMSDCC_AUTO_PROG_DONE (1 << 3)
+#define MSMSDCC_REG_WR_ACTIVE (1 << 4)
+#define MSMSDCC_SW_RST (1 << 5)
+#define MSMSDCC_SW_RST_CFG (1 << 6)
+
+#define set_hw_caps(h, val) ((h)->hw_caps |= val)
+#define is_sps_mode(h) ((h)->hw_caps & MSMSDCC_SPS_BAM_SUP)
+#define is_dma_mode(h) ((h)->hw_caps & MSMSDCC_DMA_SUP)
+#define is_soft_reset(h) ((h)->hw_caps & MSMSDCC_SOFT_RESET)
+#define is_auto_prog_done(h) ((h)->hw_caps & MSMSDCC_AUTO_PROG_DONE)
+#define is_wait_for_reg_write(h) ((h)->hw_caps & MSMSDCC_REG_WR_ACTIVE)
+#define is_sw_hard_reset(h) ((h)->hw_caps & MSMSDCC_SW_RST)
+#define is_sw_reset_save_config(h) ((h)->hw_caps & MSMSDCC_SW_RST_CFG)
+
+/* Set controller capabilities based on version */
+static inline void set_default_hw_caps(struct msmsdcc_host *host)
+{
+ u32 version;
+ /*
+ * Lookup the Controller Version, to identify the supported features
+ * Version number read as 0 would indicate SDCC3 or earlier versions.
+ */
+ version = readl_relaxed(host->base + MCI_VERSION);
+ pr_info("%s: SDCC Version: 0x%.8x\n", mmc_hostname(host->mmc), version);
+
+ if (!version)
+ return;
+
+ version &= MSMSDCC_VERSION_MASK;
+ if (version) /* SDCC v4 and greater */
+ host->hw_caps |= MSMSDCC_AUTO_PROG_DONE |
+ MSMSDCC_SOFT_RESET | MSMSDCC_REG_WR_ACTIVE;
+
+ if (version >= 0x2D) /* SDCC v4 2.1.0 and greater */
+ host->hw_caps |= MSMSDCC_SW_RST | MSMSDCC_SW_RST_CFG;
+}
+
int msmsdcc_set_pwrsave(struct mmc_host *mmc, int pwrsave);
int msmsdcc_sdio_al_lpm(struct mmc_host *mmc, bool enable);