@@ -35,6 +35,25 @@
#define EXYNOS4210_FIXED_CIU_CLK_DIV 2
#define EXYNOS4412_FIXED_CIU_CLK_DIV 4
+/* Block number in eMMC */
+#define DWMCI_BLOCK_NUM 0xFFFFFFFF
+
+#define SDMMC_EMMCP_BASE 0x1000
+#define SDMMC_MPSECURITY (SDMMC_EMMCP_BASE + 0x0010)
+#define SDMMC_MPSBEGIN0 (SDMMC_EMMCP_BASE + 0x0200)
+#define SDMMC_MPSEND0 (SDMMC_EMMCP_BASE + 0x0204)
+#define SDMMC_MPSCTRL0 (SDMMC_EMMCP_BASE + 0x020C)
+
+/* SMU control bits */
+#define DWMCI_MPSCTRL_SECURE_READ_BIT BIT(7)
+#define DWMCI_MPSCTRL_SECURE_WRITE_BIT BIT(6)
+#define DWMCI_MPSCTRL_NON_SECURE_READ_BIT BIT(5)
+#define DWMCI_MPSCTRL_NON_SECURE_WRITE_BIT BIT(4)
+#define DWMCI_MPSCTRL_USE_FUSE_KEY BIT(3)
+#define DWMCI_MPSCTRL_ECB_MODE BIT(2)
+#define DWMCI_MPSCTRL_ENCRYPTION BIT(1)
+#define DWMCI_MPSCTRL_VALID BIT(0)
+
/* Variations in Exynos specific dw-mshc controller */
enum dw_mci_exynos_type {
DW_MCI_TYPE_EXYNOS4210,
@@ -74,6 +93,17 @@ static int dw_mci_exynos_priv_init(struct dw_mci *host)
{
struct dw_mci_exynos_priv_data *priv = host->priv;
+ if (priv->ctrl_type == DW_MCI_TYPE_EXYNOS5420 &&
+ host->pdata->quirks & DW_MCI_QUIRK_BYPASS_SMU) {
+ mci_writel(host, MPSBEGIN0, 0);
+ mci_writel(host, MPSEND0, DWMCI_BLOCK_NUM);
+ mci_writel(host, MPSCTRL0,
+ DWMCI_MPSCTRL_SECURE_WRITE_BIT |
+ DWMCI_MPSCTRL_NON_SECURE_READ_BIT |
+ DWMCI_MPSCTRL_VALID |
+ DWMCI_MPSCTRL_NON_SECURE_WRITE_BIT);
+ }
+
return 0;
}
@@ -106,7 +136,18 @@ static int dw_mci_exynos_suspend(struct device *dev)
static int dw_mci_exynos_resume(struct device *dev)
{
struct dw_mci *host = dev_get_drvdata(dev);
+ struct dw_mci_exynos_priv_data *priv = host->priv;
+ if (priv->ctrl_type == DW_MCI_TYPE_EXYNOS5420 &&
+ host->pdata->quirks & DW_MCI_QUIRK_BYPASS_SMU) {
+ mci_writel(host, MPSBEGIN0, 0);
+ mci_writel(host, MPSEND0, DWMCI_BLOCK_NUM);
+ mci_writel(host, MPSCTRL0,
+ DWMCI_MPSCTRL_SECURE_WRITE_BIT |
+ DWMCI_MPSCTRL_NON_SECURE_READ_BIT |
+ DWMCI_MPSCTRL_VALID |
+ DWMCI_MPSCTRL_NON_SECURE_WRITE_BIT);
+ }
return dw_mci_resume(host);
}
@@ -2107,6 +2107,9 @@ static struct dw_mci_of_quirks {
}, {
.quirk = "broken-cd",
.id = DW_MCI_QUIRK_BROKEN_CARD_DETECTION,
+ }, {
+ .quirk = "bypass-smu",
+ .id = DW_MCI_QUIRK_BYPASS_SMU,
},
};
@@ -209,6 +209,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)
+/*Bypass the Security management unit*/
+#define DW_MCI_QUIRK_BYPASS_SMU BIT(4)
/* Slot level quirks */
/* This slot has no write protect */
Exynos5420 Mobile Storage Host controller has Security Management Unit (SMU) for channel 0 and channel 1 (mainly for eMMC).This patch adds a quirk to bypass SMU as it is not being used yet. This patch is on top of the below patch by Doug Anderson. mmc: dw_mmc: Add exynos resume_noirq callback to clear WAKEUP_INT Signed-off-by: Yuvaraj Kumar C D <yuvaraj.cd@samsung.com> --- drivers/mmc/host/dw_mmc-exynos.c | 41 ++++++++++++++++++++++++++++++++++++++ drivers/mmc/host/dw_mmc.c | 3 +++ include/linux/mmc/dw_mmc.h | 2 ++ 3 files changed, 46 insertions(+)