int mmc_send_status(struct mmc *mmc, int timeout)
{
struct mmc_cmd cmd;
- int err, retries = 5;
+ int err;
+ int retries = 0;
+ const int max_tries = 5000;
cmd.cmdidx = MMC_CMD_SEND_STATUS;
cmd.resp_type = MMC_RSP_R1;
if (!mmc_host_is_spi(mmc))
cmd.cmdarg = mmc->rca << 16;
- while (1) {
+ do {
err = mmc_send_cmd(mmc, &cmd, NULL);
if (!err) {
if ((cmd.response[0] & MMC_STATUS_RDY_FOR_DATA) &&
#endif
return -ECOMM;
}
- } else if (--retries < 0)
- return err;
+ }
+ if (err == -EBUSY) {
+ if (retries == 0)
+ printf("(e)MMC is busy; please wait... ");
+ if (retries++ > max_tries)
+ break;
+ udelay(10000);
+ continue;
+ }
if (timeout-- <= 0)
break;
udelay(1000);
- }
-
+ } while (err);
+ if (retries)
+ printf("\n");
mmc_trace_state(mmc, &cmd);
- if (timeout <= 0) {
+ if (err) {
#if !defined(CONFIG_SPL_BUILD) || defined(CONFIG_SPL_LIBCOMMON_SUPPORT)
- printf("Timeout waiting card ready\n");
+ printf("Timeout waiting for card ready\n");
#endif
- return -ETIMEDOUT;
+ return err;
}
return 0;
/* Some cards seem to need this */
mmc_go_idle(mmc);
- /* Asking to the card its capabilities */
+ /* Asking the card for its capabilities */
for (i = 0; i < 2; i++) {
err = mmc_send_op_cond_iter(mmc, i != 0);
if (err)
static int mmc_complete_op_cond(struct mmc *mmc)
{
struct mmc_cmd cmd;
- int timeout = 1000;
+ int timeout = 10 * CONFIG_SYS_HZ;
uint start;
int err;
ret = mmc_send_status(mmc, timeout);
return ret;
-
}
static int mmc_change_freq(struct mmc *mmc)
cmd.cmdarg = mmc->rca << 16;
err = mmc_send_cmd(mmc, &cmd, NULL);
+ if (err)
+ return err;
/* Waiting for the ready status */
- mmc_send_status(mmc, timeout);
-
+ err = mmc_send_status(mmc, timeout);
if (err)
return err;
mmc->part_config = MMCPART_NOAVAILABLE;
if (!IS_SD(mmc) && (mmc->version >= MMC_VERSION_4)) {
/* check ext_csd version and capacity */
+
err = mmc_send_ext_csd(mmc, ext_csd);
if (err)
return err;
{
#endif
struct sdhci_host *host = mmc->priv;
- unsigned int stat = 0;
+ unsigned int stat;
int ret = 0;
int trans_bytes = 0, is_aligned = 1;
u32 mask, flags, mode;
unsigned start = get_timer(0);
/* Timeout unit - ms */
- static unsigned int cmd_timeout = SDHCI_CMD_DEFAULT_TIMEOUT;
+ unsigned int cmd_timeout;
+
+ cmd_timeout = cmd->cmdidx == MMC_CMD_SEND_STATUS ? 10 : 200;
sdhci_writel(host, SDHCI_INT_ALL_MASK, SDHCI_INT_STATUS);
mask = SDHCI_CMD_INHIBIT | SDHCI_DATA_INHIBIT;
if (cmd->cmdidx == MMC_CMD_STOP_TRANSMISSION)
mask &= ~SDHCI_DATA_INHIBIT;
- while (sdhci_readl(host, SDHCI_PRESENT_STATE) & mask) {
- if (time >= cmd_timeout) {
- printf("%s: MMC: %d busy ", __func__, mmc_dev);
- if (2 * cmd_timeout <= SDHCI_CMD_MAX_TIMEOUT) {
- cmd_timeout += cmd_timeout;
- printf("timeout increasing to: %u ms.\n",
- cmd_timeout);
- } else {
- puts("timeout.\n");
+ while ((stat = sdhci_readl(host, SDHCI_PRESENT_STATE) & mask)) {
+ if (time++ >= cmd_timeout) {
+ debug("%s: MMC: %d busy\n", __func__, mmc_dev);
+ if (stat & (SDHCI_CMD_INHIBIT | SDHCI_DATA_INHIBIT))
+ return -EBUSY;
+ else
return -ECOMM;
- }
}
- time++;
udelay(1000);
}
if (data->flags != MMC_DATA_READ)
memcpy(aligned_buffer, data->src, trans_bytes);
#endif
-
sdhci_writel(host, start_addr, SDHCI_DMA_ADDRESS);
mode |= SDHCI_TRNS_DMA;
#endif
if ((stat & (SDHCI_INT_ERROR | mask)) == mask) {
sdhci_cmd_done(host, cmd);
sdhci_writel(host, mask, SDHCI_INT_STATUS);
- } else
+ } else {
ret = -1;
+ }
if (!ret && data)
ret = sdhci_transfer_data(host, data, start_addr);
static int sdhci_set_clock(struct mmc *mmc, unsigned int clock)
{
struct sdhci_host *host = mmc->priv;
- unsigned int div, clk = 0, timeout, reg;
+ unsigned int div, timeout, reg;
+ uint16_t clk = 0;
/* Wait max 20 ms */
timeout = 200;
while (sdhci_readl(host, SDHCI_PRESENT_STATE) &
(SDHCI_CMD_INHIBIT | SDHCI_DATA_INHIBIT)) {
if (timeout == 0) {
- printf("%s: Timeout to wait cmd & data inhibit\n",
+ printf("%s: Timeout waiting for cmd & data inhibit\n",
__func__);
return -1;
}