|
@@ -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);
|
|
|
}
|
|
|
|