diff options
Diffstat (limited to 'drivers/mmc/host/atmel-mci.c')
| -rw-r--r-- | drivers/mmc/host/atmel-mci.c | 34 |
1 files changed, 23 insertions, 11 deletions
diff --git a/drivers/mmc/host/atmel-mci.c b/drivers/mmc/host/atmel-mci.c index 2cbb4516d35..bb585d94090 100644 --- a/drivers/mmc/host/atmel-mci.c +++ b/drivers/mmc/host/atmel-mci.c @@ -37,6 +37,7 @@ #include <linux/atmel-mci.h> #include <linux/atmel_pdc.h> +#include <asm/cacheflush.h> #include <asm/io.h> #include <asm/unaligned.h> @@ -820,16 +821,9 @@ static void atmci_pdc_complete(struct atmel_mci *host) atmci_pdc_cleanup(host); - /* - * If the card was removed, data will be NULL. No point trying - * to send the stop command or waiting for NBUSY in this case. - */ - if (host->data) { - dev_dbg(&host->pdev->dev, - "(%s) set pending xfer complete\n", __func__); - atmci_set_pending(host, EVENT_XFER_COMPLETE); - tasklet_schedule(&host->tasklet); - } + dev_dbg(&host->pdev->dev, "(%s) set pending xfer complete\n", __func__); + atmci_set_pending(host, EVENT_XFER_COMPLETE); + tasklet_schedule(&host->tasklet); } static void atmci_dma_cleanup(struct atmel_mci *host) @@ -1192,11 +1186,22 @@ static void atmci_start_request(struct atmel_mci *host, iflags |= ATMCI_CMDRDY; cmd = mrq->cmd; cmdflags = atmci_prepare_command(slot->mmc, cmd); - atmci_send_command(host, cmd, cmdflags); + + /* + * DMA transfer should be started before sending the command to avoid + * unexpected errors especially for read operations in SDIO mode. + * Unfortunately, in PDC mode, command has to be sent before starting + * the transfer. + */ + if (host->submit_data != &atmci_submit_data_dma) + atmci_send_command(host, cmd, cmdflags); if (data) host->submit_data(host, data); + if (host->submit_data == &atmci_submit_data_dma) + atmci_send_command(host, cmd, cmdflags); + if (mrq->stop) { host->stop_cmdr = atmci_prepare_command(slot->mmc, mrq->stop); host->stop_cmdr |= ATMCI_CMDR_STOP_XFER; @@ -1391,8 +1396,14 @@ static void atmci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios) clk_unprepare(host->mck); switch (ios->power_mode) { + case MMC_POWER_OFF: + if (!IS_ERR(mmc->supply.vmmc)) + mmc_regulator_set_ocr(mmc, mmc->supply.vmmc, 0); + break; case MMC_POWER_UP: set_bit(ATMCI_CARD_NEED_INIT, &slot->flags); + if (!IS_ERR(mmc->supply.vmmc)) + mmc_regulator_set_ocr(mmc, mmc->supply.vmmc, ios->vdd); break; default: /* @@ -2204,6 +2215,7 @@ static int __init atmci_init_slot(struct atmel_mci *host, } host->slot[id] = slot; + mmc_regulator_get_supply(mmc); mmc_add_host(mmc); if (gpio_is_valid(slot->detect_pin)) { |
