diff options
Diffstat (limited to 'drivers/mmc/sdhci.c')
-rw-r--r-- | drivers/mmc/sdhci.c | 35 |
1 files changed, 28 insertions, 7 deletions
diff --git a/drivers/mmc/sdhci.c b/drivers/mmc/sdhci.c index dfb2eeeb4d..46ae9cb52d 100644 --- a/drivers/mmc/sdhci.c +++ b/drivers/mmc/sdhci.c @@ -109,6 +109,19 @@ static int sdhci_transfer_data(struct sdhci_host *host, struct mmc_data *data, return 0; } +/* + * No command will be sent by driver if card is busy, so driver must wait + * for card ready state. + * Every time when card is busy after timeout then (last) timeout value will be + * increased twice but only if it doesn't exceed global defined maximum. + * Each function call will use last timeout value. Max timeout can be redefined + * in board config file. + */ +#ifndef CONFIG_SDHCI_CMD_MAX_TIMEOUT +#define CONFIG_SDHCI_CMD_MAX_TIMEOUT 3200 +#endif +#define CONFIG_SDHCI_CMD_DEFAULT_TIMEOUT 100 + int sdhci_send_command(struct mmc *mmc, struct mmc_cmd *cmd, struct mmc_data *data) { @@ -117,11 +130,12 @@ int sdhci_send_command(struct mmc *mmc, struct mmc_cmd *cmd, int ret = 0; int trans_bytes = 0, is_aligned = 1; u32 mask, flags, mode; - unsigned int timeout, start_addr = 0; + unsigned int time = 0, start_addr = 0; unsigned int retry = 10000; + int mmc_dev = mmc->block_dev.dev; - /* Wait max 10 ms */ - timeout = 10; + /* Timeout unit - ms */ + static unsigned int cmd_timeout = CONFIG_SDHCI_CMD_DEFAULT_TIMEOUT; sdhci_writel(host, SDHCI_INT_ALL_MASK, SDHCI_INT_STATUS); mask = SDHCI_CMD_INHIBIT | SDHCI_DATA_INHIBIT; @@ -132,11 +146,18 @@ int sdhci_send_command(struct mmc *mmc, struct mmc_cmd *cmd, mask &= ~SDHCI_DATA_INHIBIT; while (sdhci_readl(host, SDHCI_PRESENT_STATE) & mask) { - if (timeout == 0) { - printf("Controller never released inhibit bit(s).\n"); - return COMM_ERR; + if (time >= cmd_timeout) { + printf("MMC: %d busy ", mmc_dev); + if (2 * cmd_timeout <= CONFIG_SDHCI_CMD_MAX_TIMEOUT) { + cmd_timeout += cmd_timeout; + printf("timeout increasing to: %u ms.\n", + cmd_timeout); + } else { + puts("timeout.\n"); + return COMM_ERR; + } } - timeout--; + time++; udelay(1000); } |