diff options
author | Anish Trivedi <anish@freescale.com> | 2011-05-05 13:16:17 -0500 |
---|---|---|
committer | Anish Trivedi <anish@freescale.com> | 2011-05-10 11:38:23 -0500 |
commit | c53f846a0b72a22f65f07b9eb6638168cc7004a9 (patch) | |
tree | 771deedcdd90af9bb725b474ddc10219f86cf061 /drivers/mmc | |
parent | 6fc284a6a40dff807f1598e1c3ebda6cfb28cc8f (diff) | |
download | u-boot-imx-c53f846a0b72a22f65f07b9eb6638168cc7004a9.zip u-boot-imx-c53f846a0b72a22f65f07b9eb6638168cc7004a9.tar.gz u-boot-imx-c53f846a0b72a22f65f07b9eb6638168cc7004a9.tar.bz2 |
ENGR00142995 MX50: Enable uSDHC instead of eSDHC for SDR mode
On SD3 on MX50, there is an option to choose eSDHC or uSDHC controller.
By default eSDHC is selected. However, eSDHC shows some borderline timing
in SDR mode at 50 MHz, whereas uSDHC shows borderline timing in DDR mode
at 50 MHz. Therefore, add a compile time option to uboot for MX50 to
select uSDHC in SDR mode or eSDHC in DDR mode on SD3 port.
By default the compile time option, CONFIG_MX50_ENABLE_USDHC_SDR,
is commented out in the include/configs/mx50_<board>.h file to
select eSDHC with DDR mode enabled. Uncomment the define to select
uSDHC with only SDR mode enabled.
Also increased max frequency supported by ESDHC to 52 MHz instead
of 50 MHz.
Signed-off-by: Anish Trivedi <anish@freescale.com>
Diffstat (limited to 'drivers/mmc')
-rw-r--r-- | drivers/mmc/imx_esdhc.c | 36 |
1 files changed, 30 insertions, 6 deletions
diff --git a/drivers/mmc/imx_esdhc.c b/drivers/mmc/imx_esdhc.c index ced336a..f31176f 100644 --- a/drivers/mmc/imx_esdhc.c +++ b/drivers/mmc/imx_esdhc.c @@ -66,12 +66,15 @@ struct fsl_esdhc { uint autoc12err; uint hostcapblt; uint wml; - char reserved1[8]; + uint mixctrl; + char reserved1[4]; uint fevt; char reserved2[12]; uint dllctrl; uint dllstatus; - char reserved3[148]; + char reserved3[88]; + uint vendorspec; + char reserved4[56]; uint hostver; }; @@ -206,17 +209,24 @@ esdhc_send_cmd(struct mmc *mmc, struct mmc_cmd *cmd, struct mmc_data *data) /* Send the command */ writel(cmd->cmdarg, ®s->cmdarg); + /* for uSDHC, write to mixer control register */ + writel(xfertyp, ®s->mixctrl); writel(xfertyp, ®s->xfertyp); /* Mask all irqs */ writel(0, ®s->irqsigen); /* Wait for the command to complete */ - while (!(readl(®s->irqstat) & IRQSTAT_CC)); + while (!(readl(®s->irqstat) & (IRQSTAT_CC | IRQSTAT_CTOE))) + ; irqstat = readl(®s->irqstat); writel(irqstat, ®s->irqstat); + /* Reset CMD portion on error */ + if (irqstat & (CMD_ERR | IRQSTAT_CTOE)) + writel(readl(®s->sysctl) | SYSCTL_RSTC, ®s->sysctl); + if (irqstat & CMD_ERR) return COMM_ERR; @@ -281,9 +291,12 @@ esdhc_send_cmd(struct mmc *mmc, struct mmc_cmd *cmd, struct mmc_data *data) while (!(readl(®s->irqstat) & IRQSTAT_TC)) ; } - if (readl(®s->irqstat) & 0xFFFF0000) + /* Reset CMD and DATA portions of the controller on error */ + if (readl(®s->irqstat) & 0xFFFF0000) { + writel(readl(®s->sysctl) | SYSCTL_RSTC | SYSCTL_RSTD, + ®s->sysctl); return COMM_ERR; - + } writel(-1, ®s->irqstat); return 0; @@ -479,6 +492,11 @@ int fsl_esdhc_initialize(bd_t *bis, struct fsl_esdhc_cfg *cfg) mmc->set_ios = esdhc_set_ios; mmc->init = esdhc_init; +/* Enable uSDHC if the config is defined (only for i.MX50 in SDR mode) */ +#ifdef CONFIG_MX50_ENABLE_USDHC_SDR + enable_usdhc(); +#endif + caps = readl(®s->hostcapblt); if (caps & ESDHC_HOSTCAPBLT_VS30) mmc->voltages |= MMC_VDD_29_30 | MMC_VDD_30_31; @@ -490,6 +508,10 @@ int fsl_esdhc_initialize(bd_t *bis, struct fsl_esdhc_cfg *cfg) if (caps & ESDHC_HOSTCAPBLT_HSS) mmc->host_caps |= MMC_MODE_HS_52MHz | MMC_MODE_HS; +/* Do not advertise DDR capability for uSDHC on MX50 since + * it is to be used in SDR mode only. Use eSDHC for DDR mode. + */ +#ifndef CONFIG_MX50_ENABLE_USDHC_SDR if (((readl(®s->hostver) & ESDHC_HOSTVER_VVN_MASK) >> ESDHC_HOSTVER_VVN_SHIFT) >= ESDHC_HOSTVER_DDR_SUPPORT) mmc->host_caps |= EMMC_MODE_4BIT_DDR; @@ -499,8 +521,10 @@ int fsl_esdhc_initialize(bd_t *bis, struct fsl_esdhc_cfg *cfg) mmc->host_caps |= EMMC_MODE_4BIT_DDR; #endif +#endif /* #ifndef CONFIG_MX50_ENABLE_USDHC_SDR */ + mmc->f_min = 400000; - mmc->f_max = MIN(mxc_get_clock(MXC_ESDHC_CLK), 50000000); + mmc->f_max = MIN(mxc_get_clock(MXC_ESDHC_CLK), 52000000); mmc_register(mmc); |