Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

mmc: sdhci-esdhc-imx: add delay line setting support

The DLL(Delay Line) is newly added to assist in sampling read data.
The DLL provides the ability to programmatically select a quantized
delay (in fractions of the clock period) regardless of on-chip variations
such as process, voltage and temperature (PVT).

This patch adds a user interface to set slave delay line via device tree.
It's usually used in high speed mode like mmc DDR mode when the signal
quality is not good caused by board design, e.g. the signal path is too
long. User can manually set delay line to find a suitable data sampling
window for card to work properly.

Signed-off-by: Dong Aisheng <b29396@freescale.com>
Acked-by: Shawn Guo <shawn.guo@linaro.org>
Signed-off-by: Chris Ball <cjb@laptop.org>

authored by

Dong Aisheng and committed by
Chris Ball
602519b2 de5bdbff

+24
+5
Documentation/devicetree/bindings/mmc/fsl-imx-esdhc.txt
··· 12 12 Optional properties: 13 13 - fsl,cd-controller : Indicate to use controller internal card detection 14 14 - fsl,wp-controller : Indicate to use controller internal write protection 15 + - fsl,delay-line : Specify the number of delay cells for override mode. 16 + This is used to set the clock delay for DLL(Delay Line) on override mode 17 + to select a proper data sampling window in case the clock quality is not good 18 + due to signal path is too long on the board. Please refer to eSDHC/uSDHC 19 + chapter, DLL (Delay Line) section in RM for details. 15 20 16 21 Examples: 17 22
+18
drivers/mmc/host/sdhci-esdhc-imx.c
··· 46 46 /* Bits 3 and 6 are not SDHCI standard definitions */ 47 47 #define ESDHC_MIX_CTRL_SDHCI_MASK 0xb7 48 48 49 + /* dll control register */ 50 + #define ESDHC_DLL_CTRL 0x60 51 + #define ESDHC_DLL_OVERRIDE_VAL_SHIFT 9 52 + #define ESDHC_DLL_OVERRIDE_EN_SHIFT 8 53 + 49 54 /* tune control register */ 50 55 #define ESDHC_TUNE_CTRL_STATUS 0x68 51 56 #define ESDHC_TUNE_CTRL_STEP 1 ··· 822 817 { 823 818 struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host); 824 819 struct pltfm_imx_data *imx_data = pltfm_host->priv; 820 + struct esdhc_platform_data *boarddata = &imx_data->boarddata; 825 821 826 822 switch (uhs) { 827 823 case MMC_TIMING_UHS_SDR12: ··· 843 837 ESDHC_MIX_CTRL_DDREN, 844 838 host->ioaddr + ESDHC_MIX_CTRL); 845 839 imx_data->is_ddr = 1; 840 + if (boarddata->delay_line) { 841 + u32 v; 842 + v = boarddata->delay_line << 843 + ESDHC_DLL_OVERRIDE_VAL_SHIFT | 844 + (1 << ESDHC_DLL_OVERRIDE_EN_SHIFT); 845 + if (is_imx53_esdhc(imx_data)) 846 + v <<= 1; 847 + writel(v, host->ioaddr + ESDHC_DLL_CTRL); 848 + } 846 849 break; 847 850 } 848 851 ··· 915 900 boarddata->support_vsel = false; 916 901 else 917 902 boarddata->support_vsel = true; 903 + 904 + if (of_property_read_u32(np, "fsl,delay-line", &boarddata->delay_line)) 905 + boarddata->delay_line = 0; 918 906 919 907 return 0; 920 908 }
+1
include/linux/platform_data/mmc-esdhc-imx.h
··· 45 45 int max_bus_width; 46 46 unsigned int f_max; 47 47 bool support_vsel; 48 + unsigned int delay_line; 48 49 }; 49 50 #endif /* __ASM_ARCH_IMX_ESDHC_H */