X-Git-Url: https://git.sur5r.net/?a=blobdiff_plain;f=drivers%2Fmmc%2Fomap_hsmmc.c;h=ef12ecd5e369517e75e24a295f88348ee96d2c97;hb=df3fc52608daa1e10332f59cd2f226ba400d1c98;hp=c7f76209f33cbe8a6ca23d490bf31958c121ec4c;hpb=0c0892be0d93a5a892b93739c5eb3bf692fed4ff;p=u-boot diff --git a/drivers/mmc/omap_hsmmc.c b/drivers/mmc/omap_hsmmc.c index c7f76209f3..ef12ecd5e3 100644 --- a/drivers/mmc/omap_hsmmc.c +++ b/drivers/mmc/omap_hsmmc.c @@ -30,6 +30,10 @@ #include #include #include +#include + +/* If we fail after 1 second wait, something is really bad */ +#define MAX_RETRY_MS 1000 static int mmc_read_data(hsmmc_t *mmc_base, char *buf, unsigned int size); static int mmc_write_data(hsmmc_t *mmc_base, const char *buf, unsigned int siz); @@ -70,18 +74,29 @@ unsigned char mmc_board_init(hsmmc_t *mmc_base) void mmc_init_stream(hsmmc_t *mmc_base) { + ulong start; writel(readl(&mmc_base->con) | INIT_INITSTREAM, &mmc_base->con); writel(MMC_CMD0, &mmc_base->cmd); - while (!(readl(&mmc_base->stat) & CC_MASK)) - ; + start = get_timer(0); + while (!(readl(&mmc_base->stat) & CC_MASK)) { + if (get_timer(0) - start > MAX_RETRY_MS) { + printf("%s: timedout waiting for cc!\n", __func__); + return; + } + } writel(CC_MASK, &mmc_base->stat) ; writel(MMC_CMD0, &mmc_base->cmd) ; - while (!(readl(&mmc_base->stat) & CC_MASK)) - ; + start = get_timer(0); + while (!(readl(&mmc_base->stat) & CC_MASK)) { + if (get_timer(0) - start > MAX_RETRY_MS) { + printf("%s: timedout waiting for cc2!\n", __func__); + return; + } + } writel(readl(&mmc_base->con) & ~INIT_INITSTREAM, &mmc_base->con); } @@ -91,16 +106,28 @@ static int mmc_init_setup(struct mmc *mmc) hsmmc_t *mmc_base = (hsmmc_t *)mmc->priv; unsigned int reg_val; unsigned int dsor; + ulong start; mmc_board_init(mmc_base); writel(readl(&mmc_base->sysconfig) | MMC_SOFTRESET, &mmc_base->sysconfig); - while ((readl(&mmc_base->sysstatus) & RESETDONE) == 0) - ; + start = get_timer(0); + while ((readl(&mmc_base->sysstatus) & RESETDONE) == 0) { + if (get_timer(0) - start > MAX_RETRY_MS) { + printf("%s: timedout waiting for cc2!\n", __func__); + return TIMEOUT; + } + } writel(readl(&mmc_base->sysctl) | SOFTRESETALL, &mmc_base->sysctl); - while ((readl(&mmc_base->sysctl) & SOFTRESETALL) != 0x0) - ; + start = get_timer(0); + while ((readl(&mmc_base->sysctl) & SOFTRESETALL) != 0x0) { + if (get_timer(0) - start > MAX_RETRY_MS) { + printf("%s: timedout waiting for softresetall!\n", + __func__); + return TIMEOUT; + } + } writel(DTW_1_BITMODE | SDBP_PWROFF | SDVS_3V0, &mmc_base->hctl); writel(readl(&mmc_base->capa) | VS30_3V0SUP | VS18_1V8SUP, &mmc_base->capa); @@ -116,8 +143,13 @@ static int mmc_init_setup(struct mmc *mmc) (ICE_STOP | DTO_15THDTO | CEN_DISABLE)); mmc_reg_out(&mmc_base->sysctl, ICE_MASK | CLKD_MASK, (dsor << CLKD_OFFSET) | ICE_OSCILLATE); - while ((readl(&mmc_base->sysctl) & ICS_MASK) == ICS_NOTREADY) - ; + start = get_timer(0); + while ((readl(&mmc_base->sysctl) & ICS_MASK) == ICS_NOTREADY) { + if (get_timer(0) - start > MAX_RETRY_MS) { + printf("%s: timedout waiting for ics!\n", __func__); + return TIMEOUT; + } + } writel(readl(&mmc_base->sysctl) | CEN_ENABLE, &mmc_base->sysctl); writel(readl(&mmc_base->hctl) | SDBP_PWRON, &mmc_base->hctl); @@ -137,14 +169,23 @@ static int mmc_send_cmd(struct mmc *mmc, struct mmc_cmd *cmd, { hsmmc_t *mmc_base = (hsmmc_t *)mmc->priv; unsigned int flags, mmc_stat; - unsigned int retry = 0x100000; - + ulong start; - while ((readl(&mmc_base->pstate) & DATI_MASK) == DATI_CMDDIS) - ; + start = get_timer(0); + while ((readl(&mmc_base->pstate) & DATI_MASK) == DATI_CMDDIS) { + if (get_timer(0) - start > MAX_RETRY_MS) { + printf("%s: timedout waiting for cmddis!\n", __func__); + return TIMEOUT; + } + } writel(0xFFFFFFFF, &mmc_base->stat); - while (readl(&mmc_base->stat)) - ; + start = get_timer(0); + while (readl(&mmc_base->stat)) { + if (get_timer(0) - start > MAX_RETRY_MS) { + printf("%s: timedout waiting for stat!\n", __func__); + return TIMEOUT; + } + } /* * CMDREG * CMDIDX[13:8] : Command index @@ -200,15 +241,14 @@ static int mmc_send_cmd(struct mmc *mmc, struct mmc_cmd *cmd, writel(cmd->cmdarg, &mmc_base->arg); writel((cmd->cmdidx << 24) | flags, &mmc_base->cmd); + start = get_timer(0); do { mmc_stat = readl(&mmc_base->stat); - retry--; - } while ((mmc_stat == 0) && (retry > 0)); - - if (retry == 0) { - printf("%s : timeout: No status update\n", __func__); - return TIMEOUT; - } + if (get_timer(0) - start > MAX_RETRY_MS) { + printf("%s : timeout: No status update\n", __func__); + return TIMEOUT; + } + } while (!mmc_stat); if ((mmc_stat & IE_CTO) != 0) return TIMEOUT; @@ -253,8 +293,14 @@ static int mmc_read_data(hsmmc_t *mmc_base, char *buf, unsigned int size) count /= 4; while (size) { + ulong start = get_timer(0); do { mmc_stat = readl(&mmc_base->stat); + if (get_timer(0) - start > MAX_RETRY_MS) { + printf("%s: timedout waiting for status!\n", + __func__); + return TIMEOUT; + } } while (mmc_stat == 0); if ((mmc_stat & ERRI_MASK) != 0) @@ -298,8 +344,14 @@ static int mmc_write_data(hsmmc_t *mmc_base, const char *buf, unsigned int size) count /= 4; while (size) { + ulong start = get_timer(0); do { mmc_stat = readl(&mmc_base->stat); + if (get_timer(0) - start > MAX_RETRY_MS) { + printf("%s: timedout waiting for status!\n", + __func__); + return TIMEOUT; + } } while (mmc_stat == 0); if ((mmc_stat & ERRI_MASK) != 0) @@ -334,6 +386,7 @@ static void mmc_set_ios(struct mmc *mmc) { hsmmc_t *mmc_base = (hsmmc_t *)mmc->priv; unsigned int dsor = 0; + ulong start; /* configue bus width */ switch (mmc->bus_width) { @@ -372,8 +425,13 @@ static void mmc_set_ios(struct mmc *mmc) mmc_reg_out(&mmc_base->sysctl, ICE_MASK | CLKD_MASK, (dsor << CLKD_OFFSET) | ICE_OSCILLATE); - while ((readl(&mmc_base->sysctl) & ICS_MASK) == ICS_NOTREADY) - ; + start = get_timer(0); + while ((readl(&mmc_base->sysctl) & ICS_MASK) == ICS_NOTREADY) { + if (get_timer(0) - start > MAX_RETRY_MS) { + printf("%s: timedout waiting for ics!\n", __func__); + return; + } + } writel(readl(&mmc_base->sysctl) | CEN_ENABLE, &mmc_base->sysctl); } @@ -408,6 +466,16 @@ int omap_mmc_init(int dev_index) mmc->f_min = 400000; mmc->f_max = 52000000; + mmc->b_max = 0; + +#if defined(CONFIG_OMAP34XX) + /* + * Silicon revs 2.1 and older do not support multiblock transfers. + */ + if ((get_cpu_family() == CPU_OMAP34XX) && (get_cpu_rev() <= CPU_3XX_ES21)) + mmc->b_max = 1; +#endif + mmc_register(mmc); return 0;