diff options
| -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 dfb2eeeb4..46ae9cb52 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);  	} |