diff options
Diffstat (limited to 'drivers/mmc/host/sdhci.c')
-rw-r--r-- | drivers/mmc/host/sdhci.c | 155 |
1 files changed, 104 insertions, 51 deletions
diff --git a/drivers/mmc/host/sdhci.c b/drivers/mmc/host/sdhci.c index 37b2a9ae52e..ada1a3ea3a8 100644 --- a/drivers/mmc/host/sdhci.c +++ b/drivers/mmc/host/sdhci.c @@ -707,19 +707,28 @@ static void sdhci_set_transfer_irqs(struct sdhci_host *host) sdhci_writel(host, host->ier, SDHCI_SIGNAL_ENABLE); } -static void sdhci_prepare_data(struct sdhci_host *host, struct mmc_command *cmd) +static void sdhci_set_timeout(struct sdhci_host *host, struct mmc_command *cmd) { u8 count; + + if (host->ops->set_timeout) { + host->ops->set_timeout(host, cmd); + } else { + count = sdhci_calc_timeout(host, cmd); + sdhci_writeb(host, count, SDHCI_TIMEOUT_CONTROL); + } +} + +static void sdhci_prepare_data(struct sdhci_host *host, struct mmc_command *cmd) +{ u8 ctrl; struct mmc_data *data = cmd->data; int ret; WARN_ON(host->data); - if (data || (cmd->flags & MMC_RSP_BUSY)) { - count = sdhci_calc_timeout(host, cmd); - sdhci_writeb(host, count, SDHCI_TIMEOUT_CONTROL); - } + if (data || (cmd->flags & MMC_RSP_BUSY)) + sdhci_set_timeout(host, cmd); if (!data) return; @@ -1007,6 +1016,7 @@ void sdhci_send_command(struct sdhci_host *host, struct mmc_command *cmd) mod_timer(&host->timer, timeout); host->cmd = cmd; + host->busy_handle = 0; sdhci_prepare_data(host, cmd); @@ -1194,7 +1204,6 @@ void sdhci_set_clock(struct sdhci_host *host, unsigned int clock) clock_set: if (real_div) host->mmc->actual_clock = (host->max_clk * clk_mul) / real_div; - clk |= (div & SDHCI_DIV_MASK) << SDHCI_DIVIDER_SHIFT; clk |= ((div & SDHCI_DIV_HI_MASK) >> SDHCI_DIV_MASK_LEN) << SDHCI_DIVIDER_HI_SHIFT; @@ -1357,11 +1366,12 @@ static void sdhci_request(struct mmc_host *mmc, struct mmc_request *mrq) present_state = sdhci_readl(host, SDHCI_PRESENT_STATE); /* * Check if the re-tuning timer has already expired and there - * is no on-going data transfer. If so, we need to execute - * tuning procedure before sending command. + * is no on-going data transfer and DAT0 is not busy. If so, + * we need to execute tuning procedure before sending command. */ if ((host->flags & SDHCI_NEEDS_RETUNING) && - !(present_state & (SDHCI_DOING_WRITE | SDHCI_DOING_READ))) { + !(present_state & (SDHCI_DOING_WRITE | SDHCI_DOING_READ)) && + (present_state & SDHCI_DATA_0_LVL_MASK)) { if (mmc->card) { /* eMMC uses cmd21 but sd and sdio use cmd19 */ tuning_opcode = @@ -1471,6 +1481,18 @@ static void sdhci_do_set_ios(struct sdhci_host *host, struct mmc_ios *ios) if (!ios->clock || ios->clock != host->clock) { host->ops->set_clock(host, ios->clock); host->clock = ios->clock; + + if (host->quirks & SDHCI_QUIRK_DATA_TIMEOUT_USES_SDCLK && + host->clock) { + host->timeout_clk = host->mmc->actual_clock ? + host->mmc->actual_clock / 1000 : + host->clock / 1000; + host->mmc->max_busy_timeout = + host->ops->get_max_timeout_count ? + host->ops->get_max_timeout_count(host) : + 1 << 27; + host->mmc->max_busy_timeout /= host->timeout_clk; + } } sdhci_set_power(host, ios->power_mode, ios->vdd); @@ -1733,8 +1755,8 @@ static int sdhci_do_start_signal_voltage_switch(struct sdhci_host *host, ret = regulator_set_voltage(mmc->supply.vqmmc, 2700000, 3600000); if (ret) { - pr_warning("%s: Switching to 3.3V signalling voltage " - " failed\n", mmc_hostname(mmc)); + pr_warn("%s: Switching to 3.3V signalling voltage failed\n", + mmc_hostname(mmc)); return -EIO; } } @@ -1746,8 +1768,8 @@ static int sdhci_do_start_signal_voltage_switch(struct sdhci_host *host, if (!(ctrl & SDHCI_CTRL_VDD_180)) return 0; - pr_warning("%s: 3.3V regulator output did not became stable\n", - mmc_hostname(mmc)); + pr_warn("%s: 3.3V regulator output did not became stable\n", + mmc_hostname(mmc)); return -EAGAIN; case MMC_SIGNAL_VOLTAGE_180: @@ -1755,8 +1777,8 @@ static int sdhci_do_start_signal_voltage_switch(struct sdhci_host *host, ret = regulator_set_voltage(mmc->supply.vqmmc, 1700000, 1950000); if (ret) { - pr_warning("%s: Switching to 1.8V signalling voltage " - " failed\n", mmc_hostname(mmc)); + pr_warn("%s: Switching to 1.8V signalling voltage failed\n", + mmc_hostname(mmc)); return -EIO; } } @@ -1773,8 +1795,8 @@ static int sdhci_do_start_signal_voltage_switch(struct sdhci_host *host, if (ctrl & SDHCI_CTRL_VDD_180) return 0; - pr_warning("%s: 1.8V regulator output did not became stable\n", - mmc_hostname(mmc)); + pr_warn("%s: 1.8V regulator output did not became stable\n", + mmc_hostname(mmc)); return -EAGAIN; case MMC_SIGNAL_VOLTAGE_120: @@ -1782,8 +1804,8 @@ static int sdhci_do_start_signal_voltage_switch(struct sdhci_host *host, ret = regulator_set_voltage(mmc->supply.vqmmc, 1100000, 1300000); if (ret) { - pr_warning("%s: Switching to 1.2V signalling voltage " - " failed\n", mmc_hostname(mmc)); + pr_warn("%s: Switching to 1.2V signalling voltage failed\n", + mmc_hostname(mmc)); return -EIO; } } @@ -2203,7 +2225,7 @@ static void sdhci_tuning_timer(unsigned long data) * * \*****************************************************************************/ -static void sdhci_cmd_irq(struct sdhci_host *host, u32 intmask) +static void sdhci_cmd_irq(struct sdhci_host *host, u32 intmask, u32 *mask) { BUG_ON(intmask == 0); @@ -2241,11 +2263,18 @@ static void sdhci_cmd_irq(struct sdhci_host *host, u32 intmask) if (host->cmd->data) DBG("Cannot wait for busy signal when also " "doing a data transfer"); - else if (!(host->quirks & SDHCI_QUIRK_NO_BUSY_IRQ)) + else if (!(host->quirks & SDHCI_QUIRK_NO_BUSY_IRQ) + && !host->busy_handle) { + /* Mark that command complete before busy is ended */ + host->busy_handle = 1; return; + } /* The controller does not support the end-of-busy IRQ, * fall through and take the SDHCI_INT_RESPONSE */ + } else if ((host->quirks2 & SDHCI_QUIRK2_STOP_WITH_TC) && + host->cmd->opcode == MMC_STOP_TRANSMISSION && !host->data) { + *mask &= ~SDHCI_INT_DATA_END; } if (intmask & SDHCI_INT_RESPONSE) @@ -2304,8 +2333,21 @@ static void sdhci_data_irq(struct sdhci_host *host, u32 intmask) * above in sdhci_cmd_irq(). */ if (host->cmd && (host->cmd->flags & MMC_RSP_BUSY)) { + if (intmask & SDHCI_INT_DATA_TIMEOUT) { + host->cmd->error = -ETIMEDOUT; + tasklet_schedule(&host->finish_tasklet); + return; + } if (intmask & SDHCI_INT_DATA_END) { - sdhci_finish_command(host); + /* + * Some cards handle busy-end interrupt + * before the command completed, so make + * sure we do things in the proper order. + */ + if (host->busy_handle) + sdhci_finish_command(host); + else + host->busy_handle = 1; return; } } @@ -2442,7 +2484,8 @@ static irqreturn_t sdhci_irq(int irq, void *dev_id) } if (intmask & SDHCI_INT_CMD_MASK) - sdhci_cmd_irq(host, intmask & SDHCI_INT_CMD_MASK); + sdhci_cmd_irq(host, intmask & SDHCI_INT_CMD_MASK, + &intmask); if (intmask & SDHCI_INT_DATA_MASK) sdhci_data_irq(host, intmask & SDHCI_INT_DATA_MASK); @@ -2534,7 +2577,7 @@ void sdhci_enable_irq_wakeups(struct sdhci_host *host) } EXPORT_SYMBOL_GPL(sdhci_enable_irq_wakeups); -void sdhci_disable_irq_wakeups(struct sdhci_host *host) +static void sdhci_disable_irq_wakeups(struct sdhci_host *host) { u8 val; u8 mask = SDHCI_WAKE_ON_INSERT | SDHCI_WAKE_ON_REMOVE @@ -2544,7 +2587,6 @@ void sdhci_disable_irq_wakeups(struct sdhci_host *host) val &= ~mask; sdhci_writeb(host, val, SDHCI_WAKE_UP_CONTROL); } -EXPORT_SYMBOL_GPL(sdhci_disable_irq_wakeups); int sdhci_suspend_host(struct sdhci_host *host) { @@ -2749,6 +2791,7 @@ int sdhci_add_host(struct sdhci_host *host) u32 caps[2] = {0, 0}; u32 max_current_caps; unsigned int ocr_avail; + unsigned int override_timeout_clk; int ret; WARN_ON(host == NULL); @@ -2762,6 +2805,8 @@ int sdhci_add_host(struct sdhci_host *host) if (debug_quirks2) host->quirks2 = debug_quirks2; + override_timeout_clk = host->timeout_clk; + sdhci_do_reset(host, SDHCI_RESET_ALL); host->version = sdhci_readw(host, SDHCI_HOST_VERSION); @@ -2807,8 +2852,7 @@ int sdhci_add_host(struct sdhci_host *host) if (host->flags & (SDHCI_USE_SDMA | SDHCI_USE_ADMA)) { if (host->ops->enable_dma) { if (host->ops->enable_dma(host)) { - pr_warning("%s: No suitable DMA " - "available. Falling back to PIO.\n", + pr_warn("%s: No suitable DMA available - falling back to PIO\n", mmc_hostname(mmc)); host->flags &= ~(SDHCI_USE_SDMA | SDHCI_USE_ADMA); @@ -2830,15 +2874,14 @@ int sdhci_add_host(struct sdhci_host *host) dma_free_coherent(mmc_dev(mmc), ADMA_SIZE, host->adma_desc, host->adma_addr); kfree(host->align_buffer); - pr_warning("%s: Unable to allocate ADMA " - "buffers. Falling back to standard DMA.\n", + pr_warn("%s: Unable to allocate ADMA buffers - falling back to standard DMA\n", mmc_hostname(mmc)); host->flags &= ~SDHCI_USE_ADMA; host->adma_desc = NULL; host->align_buffer = NULL; } else if (host->adma_addr & 3) { - pr_warning("%s: unable to allocate aligned ADMA descriptor\n", - mmc_hostname(mmc)); + pr_warn("%s: unable to allocate aligned ADMA descriptor\n", + mmc_hostname(mmc)); host->flags &= ~SDHCI_USE_ADMA; dma_free_coherent(mmc_dev(mmc), ADMA_SIZE, host->adma_desc, host->adma_addr); @@ -2908,25 +2951,30 @@ int sdhci_add_host(struct sdhci_host *host) } else mmc->f_min = host->max_clk / SDHCI_MAX_DIV_SPEC_200; - host->timeout_clk = - (caps[0] & SDHCI_TIMEOUT_CLK_MASK) >> SDHCI_TIMEOUT_CLK_SHIFT; - if (host->timeout_clk == 0) { - if (host->ops->get_timeout_clock) { - host->timeout_clk = host->ops->get_timeout_clock(host); - } else if (!(host->quirks & - SDHCI_QUIRK_DATA_TIMEOUT_USES_SDCLK)) { - pr_err("%s: Hardware doesn't specify timeout clock " - "frequency.\n", mmc_hostname(mmc)); - return -ENODEV; + if (!(host->quirks & SDHCI_QUIRK_DATA_TIMEOUT_USES_SDCLK)) { + host->timeout_clk = (caps[0] & SDHCI_TIMEOUT_CLK_MASK) >> + SDHCI_TIMEOUT_CLK_SHIFT; + if (host->timeout_clk == 0) { + if (host->ops->get_timeout_clock) { + host->timeout_clk = + host->ops->get_timeout_clock(host); + } else { + pr_err("%s: Hardware doesn't specify timeout clock frequency.\n", + mmc_hostname(mmc)); + return -ENODEV; + } } - } - if (caps[0] & SDHCI_TIMEOUT_CLK_UNIT) - host->timeout_clk *= 1000; - if (host->quirks & SDHCI_QUIRK_DATA_TIMEOUT_USES_SDCLK) - host->timeout_clk = mmc->f_max / 1000; + if (caps[0] & SDHCI_TIMEOUT_CLK_UNIT) + host->timeout_clk *= 1000; - mmc->max_busy_timeout = (1 << 27) / host->timeout_clk; + mmc->max_busy_timeout = host->ops->get_max_timeout_count ? + host->ops->get_max_timeout_count(host) : 1 << 27; + mmc->max_busy_timeout /= host->timeout_clk; + } + + if (override_timeout_clk) + host->timeout_clk = override_timeout_clk; mmc->caps |= MMC_CAP_SDIO_IRQ | MMC_CAP_ERASE | MMC_CAP_CMD23; mmc->caps2 |= MMC_CAP2_SDIO_IRQ_NOTHREAD; @@ -2998,8 +3046,13 @@ int sdhci_add_host(struct sdhci_host *host) /* SD3.0: SDR104 is supported so (for eMMC) the caps2 * field can be promoted to support HS200. */ - if (!(host->quirks2 & SDHCI_QUIRK2_BROKEN_HS200)) + if (!(host->quirks2 & SDHCI_QUIRK2_BROKEN_HS200)) { mmc->caps2 |= MMC_CAP2_HS200; + if (IS_ERR(mmc->supply.vqmmc) || + !regulator_is_supported_voltage + (mmc->supply.vqmmc, 1100000, 1300000)) + mmc->caps2 &= ~MMC_CAP2_HS200_1_2V_SDR; + } } else if (caps[1] & SDHCI_SUPPORT_SDR50) mmc->caps |= MMC_CAP_UHS_SDR50; @@ -3049,7 +3102,7 @@ int sdhci_add_host(struct sdhci_host *host) */ max_current_caps = sdhci_readl(host, SDHCI_MAX_CURRENT); if (!max_current_caps && !IS_ERR(mmc->supply.vmmc)) { - u32 curr = regulator_get_current_limit(mmc->supply.vmmc); + int curr = regulator_get_current_limit(mmc->supply.vmmc); if (curr > 0) { /* convert to SDHCI_MAX_CURRENT format */ @@ -3158,8 +3211,8 @@ int sdhci_add_host(struct sdhci_host *host) mmc->max_blk_size = (caps[0] & SDHCI_MAX_BLOCK_MASK) >> SDHCI_MAX_BLOCK_SHIFT; if (mmc->max_blk_size >= 3) { - pr_warning("%s: Invalid maximum block size, " - "assuming 512 bytes\n", mmc_hostname(mmc)); + pr_warn("%s: Invalid maximum block size, assuming 512 bytes\n", + mmc_hostname(mmc)); mmc->max_blk_size = 0; } } |