aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Documentation/devicetree/bindings/mmc/fsl-imx-esdhc.txt5
-rw-r--r--drivers/mmc/host/sdhci-esdhc-imx.c18
-rw-r--r--include/linux/platform_data/mmc-esdhc-imx.h1
3 files changed, 24 insertions, 0 deletions
diff --git a/Documentation/devicetree/bindings/mmc/fsl-imx-esdhc.txt b/Documentation/devicetree/bindings/mmc/fsl-imx-esdhc.txt
index 1dd622546d06..9046ba06c47a 100644
--- a/Documentation/devicetree/bindings/mmc/fsl-imx-esdhc.txt
+++ b/Documentation/devicetree/bindings/mmc/fsl-imx-esdhc.txt
@@ -12,6 +12,11 @@ Required properties:
Optional properties:
- fsl,cd-controller : Indicate to use controller internal card detection
- fsl,wp-controller : Indicate to use controller internal write protection
+- fsl,delay-line : Specify the number of delay cells for override mode.
+ This is used to set the clock delay for DLL(Delay Line) on override mode
+ to select a proper data sampling window in case the clock quality is not good
+ due to signal path is too long on the board. Please refer to eSDHC/uSDHC
+ chapter, DLL (Delay Line) section in RM for details.
Examples:
diff --git a/drivers/mmc/host/sdhci-esdhc-imx.c b/drivers/mmc/host/sdhci-esdhc-imx.c
index 915fa68e5122..260a81fde18d 100644
--- a/drivers/mmc/host/sdhci-esdhc-imx.c
+++ b/drivers/mmc/host/sdhci-esdhc-imx.c
@@ -46,6 +46,11 @@
/* Bits 3 and 6 are not SDHCI standard definitions */
#define ESDHC_MIX_CTRL_SDHCI_MASK 0xb7
+/* dll control register */
+#define ESDHC_DLL_CTRL 0x60
+#define ESDHC_DLL_OVERRIDE_VAL_SHIFT 9
+#define ESDHC_DLL_OVERRIDE_EN_SHIFT 8
+
/* tune control register */
#define ESDHC_TUNE_CTRL_STATUS 0x68
#define ESDHC_TUNE_CTRL_STEP 1
@@ -817,6 +822,7 @@ static int esdhc_set_uhs_signaling(struct sdhci_host *host, unsigned int uhs)
{
struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
struct pltfm_imx_data *imx_data = pltfm_host->priv;
+ struct esdhc_platform_data *boarddata = &imx_data->boarddata;
switch (uhs) {
case MMC_TIMING_UHS_SDR12:
@@ -837,6 +843,15 @@ static int esdhc_set_uhs_signaling(struct sdhci_host *host, unsigned int uhs)
ESDHC_MIX_CTRL_DDREN,
host->ioaddr + ESDHC_MIX_CTRL);
imx_data->is_ddr = 1;
+ if (boarddata->delay_line) {
+ u32 v;
+ v = boarddata->delay_line <<
+ ESDHC_DLL_OVERRIDE_VAL_SHIFT |
+ (1 << ESDHC_DLL_OVERRIDE_EN_SHIFT);
+ if (is_imx53_esdhc(imx_data))
+ v <<= 1;
+ writel(v, host->ioaddr + ESDHC_DLL_CTRL);
+ }
break;
}
@@ -901,6 +916,9 @@ sdhci_esdhc_imx_probe_dt(struct platform_device *pdev,
else
boarddata->support_vsel = true;
+ if (of_property_read_u32(np, "fsl,delay-line", &boarddata->delay_line))
+ boarddata->delay_line = 0;
+
return 0;
}
#else
diff --git a/include/linux/platform_data/mmc-esdhc-imx.h b/include/linux/platform_data/mmc-esdhc-imx.h
index a0f5a8f9b3bc..75f70f6ac137 100644
--- a/include/linux/platform_data/mmc-esdhc-imx.h
+++ b/include/linux/platform_data/mmc-esdhc-imx.h
@@ -45,5 +45,6 @@ struct esdhc_platform_data {
int max_bus_width;
unsigned int f_max;
bool support_vsel;
+ unsigned int delay_line;
};
#endif /* __ASM_ARCH_IMX_ESDHC_H */