On Fri, Jul 31, 2015 at 11:55 AM, Yangbo Lu yangbo...@freescale.com wrote:
Add eMMC DDR mode support for Freescale SDHC adapter card.
The u-boot should provide device tree properties 'adapter-type'
and 'periperal-frequency' for this feature, if not, the card
would not use DDR mode.
Signed-off-by: Yangbo Lu yangbo...@freescale.com
---
drivers/mmc/host/sdhci-esdhc.h| 24 +++
drivers/mmc/host/sdhci-of-esdhc.c | 132
--
2 files changed, 152 insertions(+), 4 deletions(-)
diff --git a/drivers/mmc/host/sdhci-esdhc.h b/drivers/mmc/host/sdhci-esdhc.h
index 163ac99..015ec01 100644
--- a/drivers/mmc/host/sdhci-esdhc.h
+++ b/drivers/mmc/host/sdhci-esdhc.h
@@ -28,10 +28,32 @@
#define ESDHC_CLOCK_MASK 0xfff0
#define ESDHC_PREDIV_SHIFT 8
#define ESDHC_DIVIDER_SHIFT4
+#define ESDHC_CLOCK_CRDEN 0x0008
#define ESDHC_CLOCK_PEREN 0x0004
#define ESDHC_CLOCK_HCKEN 0x0002
#define ESDHC_CLOCK_IPGEN 0x0001
+#define ESDHCI_PRESENT_STATE 0x24
+#define ESDHC_CLK_STABLE 0x0008
+
+#define ESDHC_CAPABILITIES_1 0x114
+#define ESDHC_MODE_MASK0x0007
+#define ESDHC_MODE_DDR50_SEL 0xfffc
+#define ESDHC_MODE_DDR50 0x0004
+
+#define ESDHC_CLOCK_CONTROL0x144
+#define ESDHC_CLKLPBK_EXTPIN 0x8000
+#define ESDHC_CMDCLK_SHIFTED 0x8000
+
+/* SDHC Adapter Card Type */
+#define ESDHC_ADAPTER_TYPE_EMMC45 0x1/* eMMC Card Rev4.5 */
+#define ESDHC_ADAPTER_TYPE_SDMMC_LEGACY 0x2/* SD/MMC Legacy Card */
+#define ESDHC_ADAPTER_TYPE_EMMC44 0x3/* eMMC Card Rev4.4 */
+#define ESDHC_ADAPTER_TYPE_RSV 0x4/* Reserved */
+#define ESDHC_ADAPTER_TYPE_MMC 0x5/* MMC Card */
+#define ESDHC_ADAPTER_TYPE_SD 0x6/* SD Card Rev2.0 Rev3.0 */
+#define ESDHC_NO_ADAPTER0x7/* No Card is Present*/
+
Hi Yangbo,
You could put those of_esdhc specific defines in of_esdhc driver since
sdhci-esdhc.h
is shared by both sdhci-imx-esdhc and sdhci-of-esdhc driver.
Or it may be time to remove such dependency that each driver uses its
own head file
separately since there's already a lot difference between them and no
reason to share
the headfile anymore.
The later one might be a more reasonable way to me.
Regards
Dong Aisheng
/* pltfm-specific */
#define ESDHC_HOST_CONTROL_LE 0x20
@@ -45,6 +67,8 @@
/* OF-specific */
#define ESDHC_DMA_SYSCTL 0x40c
#define ESDHC_DMA_SNOOP0x0040
+#define ESDHC_FLUSH_ASYNC_FIFO 0x0004
+#define ESDHC_USE_PERIPHERAL_CLK0x0008
#define ESDHC_HOST_CONTROL_RES 0x01
diff --git a/drivers/mmc/host/sdhci-of-esdhc.c
b/drivers/mmc/host/sdhci-of-esdhc.c
index f1021d8..6d7e3f9 100644
--- a/drivers/mmc/host/sdhci-of-esdhc.c
+++ b/drivers/mmc/host/sdhci-of-esdhc.c
@@ -24,11 +24,30 @@
#define VENDOR_V_220x12
#define VENDOR_V_230x13
+
+static u32 adapter_type;
+static bool peripheral_clk_available;
+
static u32 esdhc_readl(struct sdhci_host *host, int reg)
{
u32 ret;
- ret = sdhci_32bs_readl(host, reg);
+ if (reg == SDHCI_CAPABILITIES_1) {
+ ret = sdhci_32bs_readl(host, ESDHC_CAPABILITIES_1);
+ switch (adapter_type) {
+ case ESDHC_ADAPTER_TYPE_EMMC44:
+ if (ret ESDHC_MODE_DDR50) {
+ ret = ESDHC_MODE_DDR50_SEL;
+ /* enable 1/8V DDR capable */
+ host-mmc-caps |= MMC_CAP_1_8V_DDR;
+ } else
+ ret = ~ESDHC_MODE_MASK;
+ break;
+ default:
+ ret = ~ESDHC_MODE_MASK;
+ }
+ } else
+ ret = sdhci_32bs_readl(host, reg);
/*
* The bit of ADMA flag in eSDHC is not compatible with standard
* SDHC register, so set fake flag SDHCI_CAN_DO_ADMA2 when ADMA is
@@ -159,8 +178,11 @@ static void esdhc_writeb(struct sdhci_host *host, u8
val, int reg)
}
/* Prevent SDHCI core from writing reserved bits (e.g. HISPD). */
- if (reg == SDHCI_HOST_CONTROL)
+ if (reg == SDHCI_HOST_CONTROL) {
val = ~ESDHC_HOST_CONTROL_RES;
+ val = ~SDHCI_CTRL_HISPD;
+ val |= (sdhci_32bs_readl(host, reg) SDHCI_CTRL_HISPD);
+ }
sdhci_clrsetbits(host, 0xff, val, reg);
}
@@ -307,6 +329,84 @@ static void esdhc_reset(struct sdhci_host *host, u8 mask)
sdhci_writel(host, host-ier, SDHCI_SIGNAL_ENABLE);
}
+static void esdhc_clock_control(struct sdhci_host *host, bool enable)
+{
+ u32 value;
+ u32 time_out;
+
+ value = sdhci_readl(host, ESDHC_SYSTEM_CONTROL);
+
+ if (enable)
+ value |= ESDHC_CLOCK_CRDEN;
+ else
+