Skip to content
Snippets Groups Projects
Commit 56b34bc6 authored by Przemyslaw Marczak's avatar Przemyslaw Marczak Committed by Pantelis Antoniou
Browse files

mmc: sdhci: Avoid commands errors by simple timeout adaptation.


Old command timeout value was too small and it caused I/O errors which
led to uncompleted read/write/erase operations and filesystem errors.
Timeout adaptation fixes this issue.

Changes in sdhci_send_command() function:
- change timeout variable to static
- increase default command timeout to 100 ms
- add definition of max command timeout value,
  which can be redefined in each board config file
- wait for card ready state for max defined time
  if it doesn't exceed defined maximum or return COMM_ERR

Once successfully increased timeout value will be used in next function
call. This fix was tested on Goni, Trats, Trats2 boards by testing UMS
on MMC storage.

Changes v2:
- move global variable cmd_timeout into function sdhci_send_command()
- change condition "==" to ">=" when comparing time with timeout
- print information about timeout increasing and card busy timeout

Signed-off-by: default avatarPrzemyslaw Marczak <p.marczak@samsung.com>
Cc: Pantelis Antoniou <panto@antoniou-consulting.com>
parent b44fe83a
No related branches found
No related tags found
No related merge requests found
...@@ -109,6 +109,19 @@ static int sdhci_transfer_data(struct sdhci_host *host, struct mmc_data *data, ...@@ -109,6 +109,19 @@ static int sdhci_transfer_data(struct sdhci_host *host, struct mmc_data *data,
return 0; 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, int sdhci_send_command(struct mmc *mmc, struct mmc_cmd *cmd,
struct mmc_data *data) struct mmc_data *data)
{ {
...@@ -117,11 +130,12 @@ int sdhci_send_command(struct mmc *mmc, struct mmc_cmd *cmd, ...@@ -117,11 +130,12 @@ int sdhci_send_command(struct mmc *mmc, struct mmc_cmd *cmd,
int ret = 0; int ret = 0;
int trans_bytes = 0, is_aligned = 1; int trans_bytes = 0, is_aligned = 1;
u32 mask, flags, mode; u32 mask, flags, mode;
unsigned int timeout, start_addr = 0; unsigned int time = 0, start_addr = 0;
unsigned int retry = 10000; unsigned int retry = 10000;
int mmc_dev = mmc->block_dev.dev;
/* Wait max 10 ms */ /* Timeout unit - ms */
timeout = 10; static unsigned int cmd_timeout = CONFIG_SDHCI_CMD_DEFAULT_TIMEOUT;
sdhci_writel(host, SDHCI_INT_ALL_MASK, SDHCI_INT_STATUS); sdhci_writel(host, SDHCI_INT_ALL_MASK, SDHCI_INT_STATUS);
mask = SDHCI_CMD_INHIBIT | SDHCI_DATA_INHIBIT; mask = SDHCI_CMD_INHIBIT | SDHCI_DATA_INHIBIT;
...@@ -132,11 +146,18 @@ int sdhci_send_command(struct mmc *mmc, struct mmc_cmd *cmd, ...@@ -132,11 +146,18 @@ int sdhci_send_command(struct mmc *mmc, struct mmc_cmd *cmd,
mask &= ~SDHCI_DATA_INHIBIT; mask &= ~SDHCI_DATA_INHIBIT;
while (sdhci_readl(host, SDHCI_PRESENT_STATE) & mask) { while (sdhci_readl(host, SDHCI_PRESENT_STATE) & mask) {
if (timeout == 0) { if (time >= cmd_timeout) {
printf("Controller never released inhibit bit(s).\n"); printf("MMC: %d busy ", mmc_dev);
return COMM_ERR; 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); udelay(1000);
} }
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment