Commit a27c75e5 authored by Linus Torvalds's avatar Linus Torvalds

Merge tag 'mmc-v5.14-rc4' of git://git.kernel.org/pub/scm/linux/kernel/git/ulfh/mmc

Pull MMC host fixes from Ulf Hansson:

 - dw_mmc: Fix hang on data CRC error

 - mmci: Fix voltage switch procedure for the stm32 variant

 - sdhci-iproc: Fix some clock issues for BCM2711

 - sdhci-msm: Fixup software timeout value

* tag 'mmc-v5.14-rc4' of git://git.kernel.org/pub/scm/linux/kernel/git/ulfh/mmc:
  mmc: sdhci-iproc: Set SDHCI_QUIRK_CAP_CLOCK_BASE_BROKEN on BCM2711
  mmc: sdhci-iproc: Cap min clock frequency on BCM2711
  mmc: sdhci-msm: Update the software timeout value for sdhc
  mmc: mmci: stm32: Check when the voltage switch procedure should be done
  mmc: dw_mmc: Fix hang on data CRC error
parents 43a6473e 419dd626
......@@ -2018,8 +2018,8 @@ static void dw_mci_tasklet_func(struct tasklet_struct *t)
continue;
}
dw_mci_stop_dma(host);
send_stop_abort(host, data);
dw_mci_stop_dma(host);
state = STATE_SENDING_STOP;
break;
}
......@@ -2043,10 +2043,10 @@ static void dw_mci_tasklet_func(struct tasklet_struct *t)
*/
if (test_and_clear_bit(EVENT_DATA_ERROR,
&host->pending_events)) {
dw_mci_stop_dma(host);
if (!(host->data_status & (SDMMC_INT_DRTO |
SDMMC_INT_EBE)))
send_stop_abort(host, data);
dw_mci_stop_dma(host);
state = STATE_DATA_ERROR;
break;
}
......@@ -2079,10 +2079,10 @@ static void dw_mci_tasklet_func(struct tasklet_struct *t)
*/
if (test_and_clear_bit(EVENT_DATA_ERROR,
&host->pending_events)) {
dw_mci_stop_dma(host);
if (!(host->data_status & (SDMMC_INT_DRTO |
SDMMC_INT_EBE)))
send_stop_abort(host, data);
dw_mci_stop_dma(host);
state = STATE_DATA_ERROR;
break;
}
......
......@@ -479,8 +479,9 @@ static int sdmmc_post_sig_volt_switch(struct mmci_host *host,
u32 status;
int ret = 0;
if (ios->signal_voltage == MMC_SIGNAL_VOLTAGE_180) {
spin_lock_irqsave(&host->lock, flags);
if (ios->signal_voltage == MMC_SIGNAL_VOLTAGE_180 &&
host->pwr_reg & MCI_STM32_VSWITCHEN) {
mmci_write_pwrreg(host, host->pwr_reg | MCI_STM32_VSWITCH);
spin_unlock_irqrestore(&host->lock, flags);
......@@ -492,9 +493,11 @@ static int sdmmc_post_sig_volt_switch(struct mmci_host *host,
writel_relaxed(MCI_STM32_VSWENDC | MCI_STM32_CKSTOPC,
host->base + MMCICLEAR);
spin_lock_irqsave(&host->lock, flags);
mmci_write_pwrreg(host, host->pwr_reg &
~(MCI_STM32_VSWITCHEN | MCI_STM32_VSWITCH));
}
spin_unlock_irqrestore(&host->lock, flags);
return ret;
}
......
......@@ -173,6 +173,23 @@ static unsigned int sdhci_iproc_get_max_clock(struct sdhci_host *host)
return pltfm_host->clock;
}
/*
* There is a known bug on BCM2711's SDHCI core integration where the
* controller will hang when the difference between the core clock and the bus
* clock is too great. Specifically this can be reproduced under the following
* conditions:
*
* - No SD card plugged in, polling thread is running, probing cards at
* 100 kHz.
* - BCM2711's core clock configured at 500MHz or more
*
* So we set 200kHz as the minimum clock frequency available for that SoC.
*/
static unsigned int sdhci_iproc_bcm2711_get_min_clock(struct sdhci_host *host)
{
return 200000;
}
static const struct sdhci_ops sdhci_iproc_ops = {
.set_clock = sdhci_set_clock,
.get_max_clock = sdhci_iproc_get_max_clock,
......@@ -271,13 +288,15 @@ static const struct sdhci_ops sdhci_iproc_bcm2711_ops = {
.set_clock = sdhci_set_clock,
.set_power = sdhci_set_power_and_bus_voltage,
.get_max_clock = sdhci_iproc_get_max_clock,
.get_min_clock = sdhci_iproc_bcm2711_get_min_clock,
.set_bus_width = sdhci_set_bus_width,
.reset = sdhci_reset,
.set_uhs_signaling = sdhci_set_uhs_signaling,
};
static const struct sdhci_pltfm_data sdhci_bcm2711_pltfm_data = {
.quirks = SDHCI_QUIRK_MULTIBLOCK_READ_ACMD12,
.quirks = SDHCI_QUIRK_MULTIBLOCK_READ_ACMD12 |
SDHCI_QUIRK_CAP_CLOCK_BASE_BROKEN,
.ops = &sdhci_iproc_bcm2711_ops,
};
......
......@@ -2089,6 +2089,23 @@ static void sdhci_msm_cqe_disable(struct mmc_host *mmc, bool recovery)
sdhci_cqe_disable(mmc, recovery);
}
static void sdhci_msm_set_timeout(struct sdhci_host *host, struct mmc_command *cmd)
{
u32 count, start = 15;
__sdhci_set_timeout(host, cmd);
count = sdhci_readb(host, SDHCI_TIMEOUT_CONTROL);
/*
* Update software timeout value if its value is less than hardware data
* timeout value. Qcom SoC hardware data timeout value was calculated
* using 4 * MCLK * 2^(count + 13). where MCLK = 1 / host->clock.
*/
if (cmd && cmd->data && host->clock > 400000 &&
host->clock <= 50000000 &&
((1 << (count + start)) > (10 * host->clock)))
host->data_timeout = 22LL * NSEC_PER_SEC;
}
static const struct cqhci_host_ops sdhci_msm_cqhci_ops = {
.enable = sdhci_msm_cqe_enable,
.disable = sdhci_msm_cqe_disable,
......@@ -2438,6 +2455,7 @@ static const struct sdhci_ops sdhci_msm_ops = {
.irq = sdhci_msm_cqe_irq,
.dump_vendor_regs = sdhci_msm_dump_vendor_regs,
.set_power = sdhci_set_power_noreg,
.set_timeout = sdhci_msm_set_timeout,
};
static const struct sdhci_pltfm_data sdhci_msm_pdata = {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment