aboutsummaryrefslogtreecommitdiff
path: root/drivers
diff options
context:
space:
mode:
authorWenyou Yang2015-09-22 14:59:25 +0800
committerAndreas Bießmann2015-11-03 14:21:30 +0100
commit79667b7b769405ec510baf2afed566eae58ec713 (patch)
treee28a44fc5b06321e1007254de3eee7f0fa6ee7ab /drivers
parentce39680f7e560236213487ac6bf1baa66b6f74e3 (diff)
mmc: sdhci: Fix the SD clock stop sequence
According to the SDHC specification, stopping the SD Clock is by setting the SD Clock Enable bit in the Clock Control register at 0, instead of setting all bits at 0. Before stopping the SD clock, we need to make sure all SD transactions to complete, so add checking the CMD and DAT bits in the Presen State register, before stopping the SD clock. Signed-off-by: Wenyou Yang <wenyou.yang@atmel.com>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/mmc/sdhci.c20
1 files changed, 18 insertions, 2 deletions
diff --git a/drivers/mmc/sdhci.c b/drivers/mmc/sdhci.c
index d89e3028417..02d71b93440 100644
--- a/drivers/mmc/sdhci.c
+++ b/drivers/mmc/sdhci.c
@@ -286,9 +286,25 @@ static int sdhci_send_command(struct mmc *mmc, struct mmc_cmd *cmd,
static int sdhci_set_clock(struct mmc *mmc, unsigned int clock)
{
struct sdhci_host *host = mmc->priv;
- unsigned int div, clk, timeout;
+ unsigned int div, clk, timeout, reg;
- sdhci_writew(host, 0, SDHCI_CLOCK_CONTROL);
+ /* 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",
+ __func__);
+ return -1;
+ }
+
+ timeout--;
+ udelay(100);
+ }
+
+ reg = sdhci_readw(host, SDHCI_CLOCK_CONTROL);
+ reg &= ~SDHCI_CLOCK_CARD_EN;
+ sdhci_writew(host, reg, SDHCI_CLOCK_CONTROL);
if (clock == 0)
return 0;