summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--board/freescale/mx6q_sabreauto/mx6q_sabreauto.c21
-rw-r--r--drivers/mmc/imx_esdhc.c56
-rw-r--r--include/asm-arm/arch-mx6/mx6_pins.h4
-rw-r--r--include/configs/mx6q_sabreauto.h2
-rw-r--r--include/fsl_esdhc.h16
5 files changed, 75 insertions, 24 deletions
diff --git a/board/freescale/mx6q_sabreauto/mx6q_sabreauto.c b/board/freescale/mx6q_sabreauto/mx6q_sabreauto.c
index 135dff0..3190997 100644
--- a/board/freescale/mx6q_sabreauto/mx6q_sabreauto.c
+++ b/board/freescale/mx6q_sabreauto/mx6q_sabreauto.c
@@ -200,10 +200,10 @@ int board_eth_init(bd_t *bis)
#ifdef CONFIG_CMD_MMC
struct fsl_esdhc_cfg usdhc_cfg[4] = {
- {USDHC1_BASE_ADDR, 1, 1},
- {USDHC2_BASE_ADDR, 1, 1},
- {USDHC3_BASE_ADDR, 1, 1},
- {USDHC4_BASE_ADDR, 1, 1},
+ {USDHC1_BASE_ADDR, 1, 1, 1},
+ {USDHC2_BASE_ADDR, 1, 1, 1},
+ {USDHC3_BASE_ADDR, 1, 1, 1},
+ {USDHC4_BASE_ADDR, 1, 1, 1},
};
#ifdef CONFIG_DYNAMIC_MMC_DEVNO
@@ -301,6 +301,19 @@ int board_mmc_init(bd_t *bis)
return -1;
}
+/* For DDR mode operation, provide target delay parameter for each SD port.
+ * Use cfg->esdhc_base to distinguish the SD port #. The delay for each port
+ * is dependent on trace lengths for that particular port. If the following
+ * CONFIG is not defined, then the default target delay value will be used.
+ */
+#ifdef CONFIG_GET_DDR_TARGET_DELAY
+u32 get_ddr_delay(struct fsl_esdhc *cfg)
+{
+ /* No delay required on SABRE Auto board SD ports */
+ return 0;
+}
+#endif
+
#endif
int board_init(void)
diff --git a/drivers/mmc/imx_esdhc.c b/drivers/mmc/imx_esdhc.c
index a5345cb..d086949 100644
--- a/drivers/mmc/imx_esdhc.c
+++ b/drivers/mmc/imx_esdhc.c
@@ -325,6 +325,11 @@ void set_sysctl(struct mmc *mmc, uint clock)
pre_div >>= 1;
div -= 1;
+ /* for USDHC, pre_div requires another shift in DDR mode */
+ if (cfg->is_usdhc && (mmc->bus_width == EMMC_MODE_4BIT_DDR ||
+ mmc->bus_width == EMMC_MODE_8BIT_DDR))
+ pre_div >>= 1;
+
clk = (pre_div << 8) | (div << 4);
#ifndef CONFIG_IMX_ESDHC_V1
@@ -353,6 +358,16 @@ static void esdhc_dll_setup(struct mmc *mmc)
struct fsl_esdhc_cfg *cfg = (struct fsl_esdhc_cfg *)mmc->priv;
struct fsl_esdhc *regs = (struct fsl_esdhc *)cfg->esdhc_base;
uint dll_control;
+ u32 target_delay = ESDHC_DLL_TARGET_DEFAULT_VAL;
+
+/* For DDR mode operation, provide target delay parameter for each SD port.
+ * Use cfg->esdhc_base to distinguish the SD port #. The delay for each port
+ * is dependent on trace lengths for that particular port. If the following
+ * CONFIG is not defined, then the default target delay value will be used.
+ */
+#ifdef CONFIG_GET_DDR_TARGET_DELAY
+ target_delay = get_ddr_delay(cfg);
+#endif
/* For i.MX50 TO1, need to force slave override mode */
if (get_board_rev() == (0x50000 | CHIP_REV_1_0) ||
@@ -367,6 +382,11 @@ static void esdhc_dll_setup(struct mmc *mmc)
writel(dll_control, &regs->dllctrl);
} else {
+
+ /* on USDHC, enable DLL only for clock > 25 MHz */
+ if (cfg->is_usdhc && mmc->clock <= 25000000)
+ return;
+
/* Disable auto clock gating for PERCLK, HCLK, and IPGCLK */
writel(readl(&regs->sysctl) | 0x7, &regs->sysctl);
/* Stop SDCLK while delay line is calibrated */
@@ -375,16 +395,29 @@ static void esdhc_dll_setup(struct mmc *mmc)
/* Reset DLL */
writel(readl(&regs->dllctrl) | 0x2, &regs->dllctrl);
+ dll_control = 0;
+
/* Enable DLL */
- writel(readl(&regs->dllctrl) | 0x1, &regs->dllctrl);
+ if (cfg->is_usdhc)
+ dll_control |= 0x01000001;
+ else
+ dll_control |= 0x00000001;
- dll_control = readl(&regs->dllctrl);
+ writel(dll_control, &regs->dllctrl);
/* Set target delay */
- dll_control &= ~ESDHC_DLLCTRL_TARGET_MASK;
- dll_control |= (ESDHC_DLL_TARGET_DEFAULT_VAL <<
- ESDHC_DLLCTRL_TARGET_SHIFT);
- writel(dll_control, &regs->dllctrl);
+ if (cfg->is_usdhc) {
+ dll_control &= ~USDHC_DLLCTRL_TARGET_MASK;
+ dll_control |= (((target_delay & USDHC_DLL_LOW_MASK) <<
+ USDHC_DLLCTRL_TARGET_LOW_SHIFT) |
+ ((target_delay >> USDHC_DLL_HIGH_SHIFT) <<
+ USDHC_DLLCTRL_TARGET_HIGH_SHIFT));
+ writel(dll_control, &regs->dllctrl);
+ } else {
+ dll_control &= ~ESDHC_DLLCTRL_TARGET_MASK;
+ dll_control |= (target_delay << ESDHC_DLLCTRL_TARGET_SHIFT);
+ writel(dll_control, &regs->dllctrl);
+ }
/* Wait for slave lock */
while ((readl(&regs->dllstatus) & ESDHC_DLLSTS_SLV_LOCK_MASK) !=
@@ -478,7 +511,7 @@ int fsl_esdhc_initialize(bd_t *bis, struct fsl_esdhc_cfg *cfg)
{
struct fsl_esdhc *regs;
struct mmc *mmc;
- u32 ver, caps;
+ u32 caps;
if (!cfg)
return -1;
@@ -497,9 +530,7 @@ int fsl_esdhc_initialize(bd_t *bis, struct fsl_esdhc_cfg *cfg)
enable_usdhc();
#endif
- ver = (readl(&regs->hostver) & ESDHC_HOSTVER_VVN_MASK)
- >> ESDHC_HOSTVER_VVN_SHIFT;
- if (SDHC_IS_USDHC(ver))
+ if (cfg->is_usdhc)
sprintf(mmc->name, "FSL_USDHC");
caps = readl(&regs->hostcapblt);
@@ -517,7 +548,7 @@ int fsl_esdhc_initialize(bd_t *bis, struct fsl_esdhc_cfg *cfg)
* it is to be used in SDR mode only. Use eSDHC for DDR mode.
*/
#ifndef CONFIG_MX50_ENABLE_USDHC_SDR
- if (ver >= ESDHC_HOSTVER_DDR_SUPPORT)
+ if (cfg->is_usdhc)
mmc->host_caps |= EMMC_MODE_4BIT_DDR;
#ifdef CONFIG_EMMC_DDR_PORT_DETECT
@@ -525,9 +556,6 @@ int fsl_esdhc_initialize(bd_t *bis, struct fsl_esdhc_cfg *cfg)
mmc->host_caps |= EMMC_MODE_4BIT_DDR;
#endif
- if (SDHC_IS_USDHC(ver))
- mmc->host_caps |= EMMC_MODE_4BIT_DDR;
-
#endif /* #ifndef CONFIG_MX50_ENABLE_USDHC_SDR */
mmc->f_min = 400000;
diff --git a/include/asm-arm/arch-mx6/mx6_pins.h b/include/asm-arm/arch-mx6/mx6_pins.h
index 2cc7114..f64473a 100644
--- a/include/asm-arm/arch-mx6/mx6_pins.h
+++ b/include/asm-arm/arch-mx6/mx6_pins.h
@@ -48,8 +48,8 @@ typedef enum iomux_config {
PAD_CTL_DSE_40ohm | PAD_CTL_SRE_FAST | PAD_CTL_HYS)
#define MX6Q_USDHC_PAD_CTRL (PAD_CTL_PKE | PAD_CTL_PUE | \
- PAD_CTL_PUS_100K_UP | PAD_CTL_SPEED_MED | \
- PAD_CTL_DSE_40ohm | PAD_CTL_SRE_FAST | PAD_CTL_HYS)
+ PAD_CTL_PUS_47K_UP | PAD_CTL_SPEED_LOW | \
+ PAD_CTL_DSE_80ohm | PAD_CTL_SRE_FAST | PAD_CTL_HYS)
#define MX6Q_ENET_PAD_CTRL (PAD_CTL_PKE | PAD_CTL_PUE | \
PAD_CTL_PUS_100K_UP | PAD_CTL_SPEED_MED | \
diff --git a/include/configs/mx6q_sabreauto.h b/include/configs/mx6q_sabreauto.h
index 34d53bc..32247c0 100644
--- a/include/configs/mx6q_sabreauto.h
+++ b/include/configs/mx6q_sabreauto.h
@@ -183,6 +183,8 @@
#define CONFIG_BOOT_PARTITION_ACCESS
/* SD3 and SD4 are 8 bit */
#define CONFIG_MMC_8BIT_PORTS 0xC
+ /* Setup target delay in DDR mode for each SD port */
+ #define CONFIG_GET_DDR_TARGET_DELAY
#endif
/*
diff --git a/include/fsl_esdhc.h b/include/fsl_esdhc.h
index 08e62a5..fe62c01 100644
--- a/include/fsl_esdhc.h
+++ b/include/fsl_esdhc.h
@@ -151,10 +151,8 @@
#define ESDHC_HOSTVER_VVN_MASK 0x0000ff00
#define ESDHC_HOSTVER_VVN_SHIFT 8
-#define ESDHC_HOSTVER_DDR_SUPPORT 0x13
-#define USDHC_HOSTVER_VVN 0x0
-
-#define SDHC_IS_USDHC(x) (x == USDHC_HOSTVER_VVN)
+#define ESDHC_HOSTVER_SVN_MASK 0x000000ff
+#define ESDHC_HOSTVER_SVN_SHIFT 0
#define ESDHC_DLLCTRL_SLV_OVERRIDE_VAL 12
#define ESDHC_DLLCTRL_SLV_OVERRIDE_VAL_MASK 0x0000FC00
@@ -165,10 +163,20 @@
#define ESDHC_DLL_TARGET_DEFAULT_VAL 4
#define ESDHC_DLLSTS_SLV_LOCK_MASK 0x00000001
+#define USDHC_DLLCTRL_SLV_OVERRIDE_VAL_MASK 0x0000FE00
+#define USDHC_DLLCTRL_SLV_OVERRIDE_VAL_SHIFT 9
+#define USDHC_DLLCTRL_SLV_OVERRIDE 0x100
+#define USDHC_DLLCTRL_TARGET_MASK 0x00070078
+#define USDHC_DLLCTRL_TARGET_LOW_SHIFT 3
+#define USDHC_DLLCTRL_TARGET_HIGH_SHIFT 16
+#define USDHC_DLL_LOW_MASK 0xF
+#define USDHC_DLL_HIGH_SHIFT 4
+
struct fsl_esdhc_cfg {
u32 esdhc_base;
u32 no_snoop;
u32 clk_enable;
+ u32 is_usdhc;
};
#if defined(CONFIG_FSL_ESDHC) || defined(CONFIG_IMX_MMC)