summaryrefslogtreecommitdiff
path: root/drivers/mmc/host
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/mmc/host')
-rw-r--r--drivers/mmc/host/Kconfig2
-rw-r--r--drivers/mmc/host/dw_mmc-exynos.c14
-rw-r--r--drivers/mmc/host/dw_mmc-rockchip.c64
-rw-r--r--drivers/mmc/host/dw_mmc.c49
-rw-r--r--drivers/mmc/host/mmc_spi.c11
-rw-r--r--drivers/mmc/host/moxart-mmc.c6
-rw-r--r--drivers/mmc/host/mtk-sd.c18
-rw-r--r--drivers/mmc/host/mxs-mmc.c2
-rw-r--r--drivers/mmc/host/rtsx_pci_sdmmc.c36
-rw-r--r--drivers/mmc/host/sdhci-esdhc-imx.c3
-rw-r--r--drivers/mmc/host/sdhci-of-esdhc.c4
-rw-r--r--drivers/mmc/host/sdhci-pxav3.c22
-rw-r--r--drivers/mmc/host/sdhci.c72
-rw-r--r--drivers/mmc/host/sdhci.h5
-rw-r--r--drivers/mmc/host/usdhi6rol0.c5
-rw-r--r--drivers/mmc/host/via-sdmmc.c6
-rw-r--r--drivers/mmc/host/vub300.c20
17 files changed, 260 insertions, 79 deletions
diff --git a/drivers/mmc/host/Kconfig b/drivers/mmc/host/Kconfig
index 01959bd2d523..bf6102bb2e03 100644
--- a/drivers/mmc/host/Kconfig
+++ b/drivers/mmc/host/Kconfig
@@ -377,7 +377,7 @@ config MMC_OMAP_HS
config MMC_WBSD
tristate "Winbond W83L51xD SD/MMC Card Interface support"
- depends on ISA_DMA_API
+ depends on ISA_DMA_API && !M68K
help
This selects the Winbond(R) W83L51xD Secure digital and
Multimedia card Interface.
diff --git a/drivers/mmc/host/dw_mmc-exynos.c b/drivers/mmc/host/dw_mmc-exynos.c
index 3a7e835a0033..4ebd9c8e5a47 100644
--- a/drivers/mmc/host/dw_mmc-exynos.c
+++ b/drivers/mmc/host/dw_mmc-exynos.c
@@ -442,6 +442,18 @@ static s8 dw_mci_exynos_get_best_clksmpl(u8 candiates)
}
}
+ /*
+ * If there is no cadiates value, then it needs to return -EIO.
+ * If there are candiates values and don't find bset clk sample value,
+ * then use a first candiates clock sample value.
+ */
+ for (i = 0; i < iter; i++) {
+ __c = ror8(candiates, i);
+ if ((__c & 0x1) == 0x1) {
+ loc = i;
+ goto out;
+ }
+ }
out:
return loc;
}
@@ -472,6 +484,8 @@ static int dw_mci_exynos_execute_tuning(struct dw_mci_slot *slot, u32 opcode)
priv->tuned_sample = found;
} else {
ret = -EIO;
+ dev_warn(&mmc->class_dev,
+ "There is no candiates value about clksmpl!\n");
}
return ret;
diff --git a/drivers/mmc/host/dw_mmc-rockchip.c b/drivers/mmc/host/dw_mmc-rockchip.c
index 9becebeeccd1..b2c482da5dd7 100644
--- a/drivers/mmc/host/dw_mmc-rockchip.c
+++ b/drivers/mmc/host/dw_mmc-rockchip.c
@@ -78,6 +78,70 @@ static void dw_mci_rk3288_set_ios(struct dw_mci *host, struct mmc_ios *ios)
/* Make sure we use phases which we can enumerate with */
if (!IS_ERR(priv->sample_clk))
clk_set_phase(priv->sample_clk, priv->default_sample_phase);
+
+ /*
+ * Set the drive phase offset based on speed mode to achieve hold times.
+ *
+ * NOTE: this is _not_ a value that is dynamically tuned and is also
+ * _not_ a value that will vary from board to board. It is a value
+ * that could vary between different SoC models if they had massively
+ * different output clock delays inside their dw_mmc IP block (delay_o),
+ * but since it's OK to overshoot a little we don't need to do complex
+ * calculations and can pick values that will just work for everyone.
+ *
+ * When picking values we'll stick with picking 0/90/180/270 since
+ * those can be made very accurately on all known Rockchip SoCs.
+ *
+ * Note that these values match values from the DesignWare Databook
+ * tables for the most part except for SDR12 and "ID mode". For those
+ * two modes the databook calculations assume a clock in of 50MHz. As
+ * seen above, we always use a clock in rate that is exactly the
+ * card's input clock (times RK3288_CLKGEN_DIV, but that gets divided
+ * back out before the controller sees it).
+ *
+ * From measurement of a single device, it appears that delay_o is
+ * about .5 ns. Since we try to leave a bit of margin, it's expected
+ * that numbers here will be fine even with much larger delay_o
+ * (the 1.4 ns assumed by the DesignWare Databook would result in the
+ * same results, for instance).
+ */
+ if (!IS_ERR(priv->drv_clk)) {
+ int phase;
+
+ /*
+ * In almost all cases a 90 degree phase offset will provide
+ * sufficient hold times across all valid input clock rates
+ * assuming delay_o is not absurd for a given SoC. We'll use
+ * that as a default.
+ */
+ phase = 90;
+
+ switch (ios->timing) {
+ case MMC_TIMING_MMC_DDR52:
+ /*
+ * Since clock in rate with MMC_DDR52 is doubled when
+ * bus width is 8 we need to double the phase offset
+ * to get the same timings.
+ */
+ if (ios->bus_width == MMC_BUS_WIDTH_8)
+ phase = 180;
+ break;
+ case MMC_TIMING_UHS_SDR104:
+ case MMC_TIMING_MMC_HS200:
+ /*
+ * In the case of 150 MHz clock (typical max for
+ * Rockchip SoCs), 90 degree offset will add a delay
+ * of 1.67 ns. That will meet min hold time of .8 ns
+ * as long as clock output delay is < .87 ns. On
+ * SoCs measured this seems to be OK, but it doesn't
+ * hurt to give margin here, so we use 180.
+ */
+ phase = 180;
+ break;
+ }
+
+ clk_set_phase(priv->drv_clk, phase);
+ }
}
#define NUM_PHASES 360
diff --git a/drivers/mmc/host/dw_mmc.c b/drivers/mmc/host/dw_mmc.c
index 581f5d0271f4..4b5cca022642 100644
--- a/drivers/mmc/host/dw_mmc.c
+++ b/drivers/mmc/host/dw_mmc.c
@@ -380,7 +380,7 @@ static void dw_mci_start_command(struct dw_mci *host,
static inline void send_stop_abort(struct dw_mci *host, struct mmc_data *data)
{
- struct mmc_command *stop = data->stop ? data->stop : &host->stop_abort;
+ struct mmc_command *stop = &host->stop_abort;
dw_mci_start_command(host, stop, host->stop_cmdr);
}
@@ -701,6 +701,7 @@ static int dw_mci_edmac_start_dma(struct dw_mci *host,
int ret = 0;
/* Set external dma config: burst size, burst width */
+ memset(&cfg, 0, sizeof(cfg));
cfg.dst_addr = host->phy_regs + fifo_offset;
cfg.src_addr = cfg.dst_addr;
cfg.dst_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES;
@@ -1202,10 +1203,7 @@ static void __dw_mci_start_request(struct dw_mci *host,
spin_unlock_irqrestore(&host->irq_lock, irqflags);
}
- if (mrq->stop)
- host->stop_cmdr = dw_mci_prepare_command(slot->mmc, mrq->stop);
- else
- host->stop_cmdr = dw_mci_prep_stop_abort(host, cmd);
+ host->stop_cmdr = dw_mci_prep_stop_abort(host, cmd);
}
static void dw_mci_start_request(struct dw_mci *host,
@@ -1744,8 +1742,35 @@ static void dw_mci_tasklet_func(unsigned long priv)
}
if (cmd->data && err) {
- dw_mci_stop_dma(host);
+ /*
+ * During UHS tuning sequence, sending the stop
+ * command after the response CRC error would
+ * throw the system into a confused state
+ * causing all future tuning phases to report
+ * failure.
+ *
+ * In such case controller will move into a data
+ * transfer state after a response error or
+ * response CRC error. Let's let that finish
+ * before trying to send a stop, so we'll go to
+ * STATE_SENDING_DATA.
+ *
+ * Although letting the data transfer take place
+ * will waste a bit of time (we already know
+ * the command was bad), it can't cause any
+ * errors since it's possible it would have
+ * taken place anyway if this tasklet got
+ * delayed. Allowing the transfer to take place
+ * avoids races and keeps things simple.
+ */
+ if (err != -ETIMEDOUT &&
+ host->dir_status == DW_MCI_RECV_STATUS) {
+ state = STATE_SENDING_DATA;
+ continue;
+ }
+
send_stop_abort(host, data);
+ dw_mci_stop_dma(host);
state = STATE_SENDING_STOP;
break;
}
@@ -1769,11 +1794,10 @@ static void dw_mci_tasklet_func(unsigned long priv)
*/
if (test_and_clear_bit(EVENT_DATA_ERROR,
&host->pending_events)) {
- dw_mci_stop_dma(host);
- if (data->stop ||
- !(host->data_status & (SDMMC_INT_DRTO |
+ 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;
}
@@ -1807,11 +1831,10 @@ static void dw_mci_tasklet_func(unsigned long priv)
*/
if (test_and_clear_bit(EVENT_DATA_ERROR,
&host->pending_events)) {
- dw_mci_stop_dma(host);
- if (data->stop ||
- !(host->data_status & (SDMMC_INT_DRTO |
+ 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;
}
@@ -1886,7 +1909,7 @@ static void dw_mci_tasklet_func(unsigned long priv)
host->cmd = NULL;
host->data = NULL;
- if (mrq->stop)
+ if (!mrq->sbc && mrq->stop)
dw_mci_command_complete(host, mrq->stop);
else
host->cmd_status = 0;
diff --git a/drivers/mmc/host/mmc_spi.c b/drivers/mmc/host/mmc_spi.c
index 40a369c7005a..b52489a67097 100644
--- a/drivers/mmc/host/mmc_spi.c
+++ b/drivers/mmc/host/mmc_spi.c
@@ -1153,17 +1153,22 @@ static void mmc_spi_initsequence(struct mmc_spi_host *host)
* SPI protocol. Another is that when chipselect is released while
* the card returns BUSY status, the clock must issue several cycles
* with chipselect high before the card will stop driving its output.
+ *
+ * SPI_CS_HIGH means "asserted" here. In some cases like when using
+ * GPIOs for chip select, SPI_CS_HIGH is set but this will be logically
+ * inverted by gpiolib, so if we want to ascertain to drive it high
+ * we should toggle the default with an XOR as we do here.
*/
- host->spi->mode |= SPI_CS_HIGH;
+ host->spi->mode ^= SPI_CS_HIGH;
if (spi_setup(host->spi) != 0) {
/* Just warn; most cards work without it. */
dev_warn(&host->spi->dev,
"can't change chip-select polarity\n");
- host->spi->mode &= ~SPI_CS_HIGH;
+ host->spi->mode ^= SPI_CS_HIGH;
} else {
mmc_spi_readbytes(host, 18);
- host->spi->mode &= ~SPI_CS_HIGH;
+ host->spi->mode ^= SPI_CS_HIGH;
if (spi_setup(host->spi) != 0) {
/* Wot, we can't get the same setup we had before? */
dev_err(&host->spi->dev,
diff --git a/drivers/mmc/host/moxart-mmc.c b/drivers/mmc/host/moxart-mmc.c
index 79905ce895ad..41a5493cb68d 100644
--- a/drivers/mmc/host/moxart-mmc.c
+++ b/drivers/mmc/host/moxart-mmc.c
@@ -257,7 +257,7 @@ static void moxart_dma_complete(void *param)
static void moxart_transfer_dma(struct mmc_data *data, struct moxart_host *host)
{
u32 len, dir_data, dir_slave;
- unsigned long dma_time;
+ long dma_time;
struct dma_async_tx_descriptor *desc = NULL;
struct dma_chan *dma_chan;
@@ -397,7 +397,8 @@ static void moxart_prepare_data(struct moxart_host *host)
static void moxart_request(struct mmc_host *mmc, struct mmc_request *mrq)
{
struct moxart_host *host = mmc_priv(mmc);
- unsigned long pio_time, flags;
+ long pio_time;
+ unsigned long flags;
u32 status;
spin_lock_irqsave(&host->lock, flags);
@@ -632,6 +633,7 @@ static int moxart_probe(struct platform_device *pdev)
host->dma_chan_tx, host->dma_chan_rx);
host->have_dma = true;
+ memset(&cfg, 0, sizeof(cfg));
cfg.src_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES;
cfg.dst_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES;
diff --git a/drivers/mmc/host/mtk-sd.c b/drivers/mmc/host/mtk-sd.c
index 5ef25463494f..1770c8df9d1b 100644
--- a/drivers/mmc/host/mtk-sd.c
+++ b/drivers/mmc/host/mtk-sd.c
@@ -720,13 +720,13 @@ static void msdc_track_cmd_data(struct msdc_host *host,
static void msdc_request_done(struct msdc_host *host, struct mmc_request *mrq)
{
unsigned long flags;
- bool ret;
- ret = cancel_delayed_work(&host->req_timeout);
- if (!ret) {
- /* delay work already running */
- return;
- }
+ /*
+ * No need check the return value of cancel_delayed_work, as only ONE
+ * path will go here!
+ */
+ cancel_delayed_work(&host->req_timeout);
+
spin_lock_irqsave(&host->lock, flags);
host->mrq = NULL;
spin_unlock_irqrestore(&host->lock, flags);
@@ -747,7 +747,7 @@ static bool msdc_cmd_done(struct msdc_host *host, int events,
bool done = false;
bool sbc_error;
unsigned long flags;
- u32 *rsp = cmd->resp;
+ u32 *rsp;
if (mrq->sbc && cmd == mrq->cmd &&
(events & (MSDC_INT_ACMDRDY | MSDC_INT_ACMDCRCERR
@@ -768,6 +768,7 @@ static bool msdc_cmd_done(struct msdc_host *host, int events,
if (done)
return true;
+ rsp = cmd->resp;
sdr_clr_bits(host->base + MSDC_INTEN, cmd_ints_mask);
@@ -942,7 +943,7 @@ static void msdc_data_xfer_next(struct msdc_host *host,
static bool msdc_data_xfer_done(struct msdc_host *host, u32 events,
struct mmc_request *mrq, struct mmc_data *data)
{
- struct mmc_command *stop = data->stop;
+ struct mmc_command *stop;
unsigned long flags;
bool done;
unsigned int check_data = events &
@@ -958,6 +959,7 @@ static bool msdc_data_xfer_done(struct msdc_host *host, u32 events,
if (done)
return true;
+ stop = data->stop;
if (check_data || (stop && stop->error)) {
dev_dbg(host->dev, "DMA status: 0x%8X\n",
diff --git a/drivers/mmc/host/mxs-mmc.c b/drivers/mmc/host/mxs-mmc.c
index c8b8ac66ff7e..687fd68fbbcd 100644
--- a/drivers/mmc/host/mxs-mmc.c
+++ b/drivers/mmc/host/mxs-mmc.c
@@ -651,7 +651,7 @@ static int mxs_mmc_probe(struct platform_device *pdev)
ret = mmc_of_parse(mmc);
if (ret)
- goto out_clk_disable;
+ goto out_free_dma;
mmc->ocr_avail = MMC_VDD_32_33 | MMC_VDD_33_34;
diff --git a/drivers/mmc/host/rtsx_pci_sdmmc.c b/drivers/mmc/host/rtsx_pci_sdmmc.c
index 93137483ecde..10ec88833889 100644
--- a/drivers/mmc/host/rtsx_pci_sdmmc.c
+++ b/drivers/mmc/host/rtsx_pci_sdmmc.c
@@ -553,9 +553,22 @@ static int sd_write_long_data(struct realtek_pci_sdmmc *host,
return 0;
}
+static inline void sd_enable_initial_mode(struct realtek_pci_sdmmc *host)
+{
+ rtsx_pci_write_register(host->pcr, SD_CFG1,
+ SD_CLK_DIVIDE_MASK, SD_CLK_DIVIDE_128);
+}
+
+static inline void sd_disable_initial_mode(struct realtek_pci_sdmmc *host)
+{
+ rtsx_pci_write_register(host->pcr, SD_CFG1,
+ SD_CLK_DIVIDE_MASK, SD_CLK_DIVIDE_0);
+}
+
static int sd_rw_multi(struct realtek_pci_sdmmc *host, struct mmc_request *mrq)
{
struct mmc_data *data = mrq->data;
+ int err;
if (host->sg_count < 0) {
data->error = host->sg_count;
@@ -564,22 +577,19 @@ static int sd_rw_multi(struct realtek_pci_sdmmc *host, struct mmc_request *mrq)
return data->error;
}
- if (data->flags & MMC_DATA_READ)
- return sd_read_long_data(host, mrq);
+ if (data->flags & MMC_DATA_READ) {
+ if (host->initial_mode)
+ sd_disable_initial_mode(host);
- return sd_write_long_data(host, mrq);
-}
+ err = sd_read_long_data(host, mrq);
-static inline void sd_enable_initial_mode(struct realtek_pci_sdmmc *host)
-{
- rtsx_pci_write_register(host->pcr, SD_CFG1,
- SD_CLK_DIVIDE_MASK, SD_CLK_DIVIDE_128);
-}
+ if (host->initial_mode)
+ sd_enable_initial_mode(host);
-static inline void sd_disable_initial_mode(struct realtek_pci_sdmmc *host)
-{
- rtsx_pci_write_register(host->pcr, SD_CFG1,
- SD_CLK_DIVIDE_MASK, SD_CLK_DIVIDE_0);
+ return err;
+ }
+
+ return sd_write_long_data(host, mrq);
}
static void sd_normal_rw(struct realtek_pci_sdmmc *host,
diff --git a/drivers/mmc/host/sdhci-esdhc-imx.c b/drivers/mmc/host/sdhci-esdhc-imx.c
index 8d838779fd1b..b95d911ef497 100644
--- a/drivers/mmc/host/sdhci-esdhc-imx.c
+++ b/drivers/mmc/host/sdhci-esdhc-imx.c
@@ -1240,9 +1240,10 @@ static int sdhci_esdhc_imx_remove(struct platform_device *pdev)
struct sdhci_host *host = platform_get_drvdata(pdev);
struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
struct pltfm_imx_data *imx_data = pltfm_host->priv;
- int dead = (readl(host->ioaddr + SDHCI_INT_STATUS) == 0xffffffff);
+ int dead;
pm_runtime_get_sync(&pdev->dev);
+ dead = (readl(host->ioaddr + SDHCI_INT_STATUS) == 0xffffffff);
pm_runtime_disable(&pdev->dev);
pm_runtime_put_noidle(&pdev->dev);
diff --git a/drivers/mmc/host/sdhci-of-esdhc.c b/drivers/mmc/host/sdhci-of-esdhc.c
index 356b294c93c9..e78e7a874856 100644
--- a/drivers/mmc/host/sdhci-of-esdhc.c
+++ b/drivers/mmc/host/sdhci-of-esdhc.c
@@ -625,8 +625,8 @@ static int sdhci_esdhc_probe(struct platform_device *pdev)
host->quirks &= ~SDHCI_QUIRK_NO_BUSY_IRQ;
if (of_find_compatible_node(NULL, NULL, "fsl,p2020-esdhc")) {
- host->quirks2 |= SDHCI_QUIRK_RESET_AFTER_REQUEST;
- host->quirks2 |= SDHCI_QUIRK_BROKEN_TIMEOUT_VAL;
+ host->quirks |= SDHCI_QUIRK_RESET_AFTER_REQUEST;
+ host->quirks |= SDHCI_QUIRK_BROKEN_TIMEOUT_VAL;
}
if (of_device_is_compatible(np, "fsl,p5040-esdhc") ||
diff --git a/drivers/mmc/host/sdhci-pxav3.c b/drivers/mmc/host/sdhci-pxav3.c
index f5edf9d3a18a..0535827b02ee 100644
--- a/drivers/mmc/host/sdhci-pxav3.c
+++ b/drivers/mmc/host/sdhci-pxav3.c
@@ -307,8 +307,30 @@ static void pxav3_set_uhs_signaling(struct sdhci_host *host, unsigned int uhs)
__func__, uhs, ctrl_2);
}
+static void pxav3_set_power(struct sdhci_host *host, unsigned char mode,
+ unsigned short vdd)
+{
+ struct mmc_host *mmc = host->mmc;
+ u8 pwr = host->pwr;
+
+ sdhci_set_power(host, mode, vdd);
+
+ if (host->pwr == pwr)
+ return;
+
+ if (host->pwr == 0)
+ vdd = 0;
+
+ if (!IS_ERR(mmc->supply.vmmc)) {
+ spin_unlock_irq(&host->lock);
+ mmc_regulator_set_ocr(mmc, mmc->supply.vmmc, vdd);
+ spin_lock_irq(&host->lock);
+ }
+}
+
static const struct sdhci_ops pxav3_sdhci_ops = {
.set_clock = sdhci_set_clock,
+ .set_power = pxav3_set_power,
.platform_send_init_74_clocks = pxav3_gen_init_74_clocks,
.get_max_clock = sdhci_pltfm_clk_get_max_clock,
.set_bus_width = sdhci_set_bus_width,
diff --git a/drivers/mmc/host/sdhci.c b/drivers/mmc/host/sdhci.c
index 82bfc9df04e8..f88d4e9ab801 100644
--- a/drivers/mmc/host/sdhci.c
+++ b/drivers/mmc/host/sdhci.c
@@ -1298,6 +1298,10 @@ static u16 sdhci_get_preset_value(struct sdhci_host *host)
u16 preset = 0;
switch (host->timing) {
+ case MMC_TIMING_MMC_HS:
+ case MMC_TIMING_SD_HS:
+ preset = sdhci_readw(host, SDHCI_PRESET_FOR_HIGH_SPEED);
+ break;
case MMC_TIMING_UHS_SDR12:
preset = sdhci_readw(host, SDHCI_PRESET_FOR_SDR12);
break;
@@ -1453,24 +1457,25 @@ clock_set:
}
EXPORT_SYMBOL_GPL(sdhci_set_clock);
-static void sdhci_set_power(struct sdhci_host *host, unsigned char mode,
- unsigned short vdd)
+static void sdhci_set_power_reg(struct sdhci_host *host, unsigned char mode,
+ unsigned short vdd)
{
struct mmc_host *mmc = host->mmc;
- u8 pwr = 0;
- if (!IS_ERR(mmc->supply.vmmc)) {
- spin_unlock_irq(&host->lock);
- mmc_regulator_set_ocr(mmc, mmc->supply.vmmc, vdd);
- spin_lock_irq(&host->lock);
+ spin_unlock_irq(&host->lock);
+ mmc_regulator_set_ocr(mmc, mmc->supply.vmmc, vdd);
+ spin_lock_irq(&host->lock);
- if (mode != MMC_POWER_OFF)
- sdhci_writeb(host, SDHCI_POWER_ON, SDHCI_POWER_CONTROL);
- else
- sdhci_writeb(host, 0, SDHCI_POWER_CONTROL);
+ if (mode != MMC_POWER_OFF)
+ sdhci_writeb(host, SDHCI_POWER_ON, SDHCI_POWER_CONTROL);
+ else
+ sdhci_writeb(host, 0, SDHCI_POWER_CONTROL);
+}
- return;
- }
+void sdhci_set_power(struct sdhci_host *host, unsigned char mode,
+ unsigned short vdd)
+{
+ u8 pwr = 0;
if (mode != MMC_POWER_OFF) {
switch (1 << vdd) {
@@ -1483,6 +1488,12 @@ static void sdhci_set_power(struct sdhci_host *host, unsigned char mode,
break;
case MMC_VDD_32_33:
case MMC_VDD_33_34:
+ /*
+ * 3.4 ~ 3.6V are valid only for those platforms where it's
+ * known that the voltage range is supported by hardware.
+ */
+ case MMC_VDD_34_35:
+ case MMC_VDD_35_36:
pwr = SDHCI_POWER_330;
break;
default:
@@ -1503,7 +1514,6 @@ static void sdhci_set_power(struct sdhci_host *host, unsigned char mode,
host->ops->check_power_status(host, REQ_BUS_OFF);
if (host->quirks2 & SDHCI_QUIRK2_CARD_ON_NEEDS_BUS_ON)
sdhci_runtime_pm_bus_off(host);
- vdd = 0;
} else {
/*
* Spec says that we should clear the power reg before setting
@@ -1542,6 +1552,20 @@ static void sdhci_set_power(struct sdhci_host *host, unsigned char mode,
mdelay(10);
}
}
+EXPORT_SYMBOL_GPL(sdhci_set_power);
+
+static void __sdhci_set_power(struct sdhci_host *host, unsigned char mode,
+ unsigned short vdd)
+{
+ struct mmc_host *mmc = host->mmc;
+
+ if (host->ops->set_power)
+ host->ops->set_power(host, mode, vdd);
+ else if (!IS_ERR(mmc->supply.vmmc))
+ sdhci_set_power_reg(host, mode, vdd);
+ else
+ sdhci_set_power(host, mode, vdd);
+}
/*****************************************************************************\
* *
@@ -1845,9 +1869,7 @@ void sdhci_set_uhs_signaling(struct sdhci_host *host, unsigned timing)
ctrl_2 |= SDHCI_CTRL_UHS_SDR104;
else if (timing == MMC_TIMING_UHS_SDR12)
ctrl_2 |= SDHCI_CTRL_UHS_SDR12;
- else if (timing == MMC_TIMING_SD_HS ||
- timing == MMC_TIMING_MMC_HS ||
- timing == MMC_TIMING_UHS_SDR25)
+ else if (timing == MMC_TIMING_UHS_SDR25)
ctrl_2 |= SDHCI_CTRL_UHS_SDR25;
else if (timing == MMC_TIMING_UHS_SDR50)
ctrl_2 |= SDHCI_CTRL_UHS_SDR50;
@@ -1936,7 +1958,7 @@ static void sdhci_do_set_ios(struct sdhci_host *host, struct mmc_ios *ios)
pr_err("%s: enabling controller clock: failed: %d\n",
mmc_hostname(host->mmc), ret);
} else {
- sdhci_set_power(host, ios->power_mode, ios->vdd);
+ __sdhci_set_power(host, ios->power_mode, ios->vdd);
}
}
}
@@ -1954,7 +1976,7 @@ static void sdhci_do_set_ios(struct sdhci_host *host, struct mmc_ios *ios)
if (!host->ops->enable_controller_clock && (ios->power_mode &
(MMC_POWER_UP |
MMC_POWER_ON)))
- sdhci_set_power(host, ios->power_mode, ios->vdd);
+ __sdhci_set_power(host, ios->power_mode, ios->vdd);
spin_lock_irqsave(&host->lock, flags);
@@ -2536,7 +2558,7 @@ static int sdhci_execute_tuning(struct mmc_host *mmc, u32 opcode)
spin_lock_irqsave(&host->lock, flags);
if (!host->tuning_done) {
- pr_info(DRIVER_NAME ": Timeout waiting for "
+ pr_debug(DRIVER_NAME ": Timeout waiting for "
"Buffer Read Ready interrupt during tuning "
"procedure, falling back to fixed sampling "
"clock\n");
@@ -4080,11 +4102,13 @@ int sdhci_add_host(struct sdhci_host *host)
if (host->ops->get_min_clock)
mmc->f_min = host->ops->get_min_clock(host);
else if (host->version >= SDHCI_SPEC_300) {
- if (host->clk_mul) {
- mmc->f_min = (host->max_clk * host->clk_mul) / 1024;
+ if (host->clk_mul)
max_clk = host->max_clk * host->clk_mul;
- } else
- mmc->f_min = host->max_clk / SDHCI_MAX_DIV_SPEC_300;
+ /*
+ * Divided Clock Mode minimum clock rate is always less than
+ * Programmable Clock Mode minimum clock rate.
+ */
+ mmc->f_min = host->max_clk / SDHCI_MAX_DIV_SPEC_300;
} else
mmc->f_min = host->max_clk / SDHCI_MAX_DIV_SPEC_200;
diff --git a/drivers/mmc/host/sdhci.h b/drivers/mmc/host/sdhci.h
index 86b7066a81c2..e53f0c6ed375 100644
--- a/drivers/mmc/host/sdhci.h
+++ b/drivers/mmc/host/sdhci.h
@@ -244,6 +244,7 @@
/* 60-FB reserved */
+#define SDHCI_PRESET_FOR_HIGH_SPEED 0x64
#define SDHCI_PRESET_FOR_SDR12 0x66
#define SDHCI_PRESET_FOR_SDR25 0x68
#define SDHCI_PRESET_FOR_SDR50 0x6A
@@ -642,6 +643,8 @@ struct sdhci_ops {
#endif
void (*set_clock)(struct sdhci_host *host, unsigned int clock);
+ void (*set_power)(struct sdhci_host *host, unsigned char mode,
+ unsigned short vdd);
int (*enable_dma)(struct sdhci_host *host);
unsigned int (*get_max_clock)(struct sdhci_host *host);
@@ -806,6 +809,8 @@ static inline bool sdhci_sdio_irq_enabled(struct sdhci_host *host)
}
void sdhci_set_clock(struct sdhci_host *host, unsigned int clock);
+void sdhci_set_power(struct sdhci_host *host, unsigned char mode,
+ unsigned short vdd);
void sdhci_set_bus_width(struct sdhci_host *host, int width);
void sdhci_reset(struct sdhci_host *host, u8 mask);
void sdhci_set_uhs_signaling(struct sdhci_host *host, unsigned timing);
diff --git a/drivers/mmc/host/usdhi6rol0.c b/drivers/mmc/host/usdhi6rol0.c
index b47122d3e8d8..49798a68299e 100644
--- a/drivers/mmc/host/usdhi6rol0.c
+++ b/drivers/mmc/host/usdhi6rol0.c
@@ -1751,6 +1751,7 @@ static int usdhi6_probe(struct platform_device *pdev)
version = usdhi6_read(host, USDHI6_VERSION);
if ((version & 0xfff) != 0xa0d) {
+ ret = -EPERM;
dev_err(dev, "Version not recognized %x\n", version);
goto e_clk_off;
}
@@ -1808,10 +1809,12 @@ static int usdhi6_probe(struct platform_device *pdev)
ret = mmc_add_host(mmc);
if (ret < 0)
- goto e_clk_off;
+ goto e_release_dma;
return 0;
+e_release_dma:
+ usdhi6_dma_release(host);
e_clk_off:
clk_disable_unprepare(host->clk);
e_free_mmc:
diff --git a/drivers/mmc/host/via-sdmmc.c b/drivers/mmc/host/via-sdmmc.c
index 63fac78b3d46..a3472127bea3 100644
--- a/drivers/mmc/host/via-sdmmc.c
+++ b/drivers/mmc/host/via-sdmmc.c
@@ -859,6 +859,9 @@ static void via_sdc_data_isr(struct via_crdr_mmc_host *host, u16 intmask)
{
BUG_ON(intmask == 0);
+ if (!host->data)
+ return;
+
if (intmask & VIA_CRDR_SDSTS_DT)
host->data->error = -ETIMEDOUT;
else if (intmask & (VIA_CRDR_SDSTS_RC | VIA_CRDR_SDSTS_WC))
@@ -1269,11 +1272,14 @@ static void via_init_sdc_pm(struct via_crdr_mmc_host *host)
static int via_sd_suspend(struct pci_dev *pcidev, pm_message_t state)
{
struct via_crdr_mmc_host *host;
+ unsigned long flags;
host = pci_get_drvdata(pcidev);
+ spin_lock_irqsave(&host->lock, flags);
via_save_pcictrlreg(host);
via_save_sdcreg(host);
+ spin_unlock_irqrestore(&host->lock, flags);
pci_save_state(pcidev);
pci_enable_wake(pcidev, pci_choose_state(pcidev, state), 0);
diff --git a/drivers/mmc/host/vub300.c b/drivers/mmc/host/vub300.c
index 1e819f98b94f..69987b9066f6 100644
--- a/drivers/mmc/host/vub300.c
+++ b/drivers/mmc/host/vub300.c
@@ -579,7 +579,7 @@ static void check_vub300_port_status(struct vub300_mmc_host *vub300)
GET_SYSTEM_PORT_STATUS,
USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
0x0000, 0x0000, &vub300->system_port_status,
- sizeof(vub300->system_port_status), HZ);
+ sizeof(vub300->system_port_status), 1000);
if (sizeof(vub300->system_port_status) == retval)
new_system_port_status(vub300);
}
@@ -1245,7 +1245,7 @@ static void __download_offload_pseudocode(struct vub300_mmc_host *vub300,
SET_INTERRUPT_PSEUDOCODE,
USB_DIR_OUT | USB_TYPE_VENDOR |
USB_RECIP_DEVICE, 0x0000, 0x0000,
- xfer_buffer, xfer_length, HZ);
+ xfer_buffer, xfer_length, 1000);
kfree(xfer_buffer);
if (retval < 0) {
strncpy(vub300->vub_name,
@@ -1292,7 +1292,7 @@ static void __download_offload_pseudocode(struct vub300_mmc_host *vub300,
SET_TRANSFER_PSEUDOCODE,
USB_DIR_OUT | USB_TYPE_VENDOR |
USB_RECIP_DEVICE, 0x0000, 0x0000,
- xfer_buffer, xfer_length, HZ);
+ xfer_buffer, xfer_length, 1000);
kfree(xfer_buffer);
if (retval < 0) {
strncpy(vub300->vub_name,
@@ -1998,7 +1998,7 @@ static void __set_clock_speed(struct vub300_mmc_host *vub300, u8 buf[8],
usb_control_msg(vub300->udev, usb_sndctrlpipe(vub300->udev, 0),
SET_CLOCK_SPEED,
USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
- 0x00, 0x00, buf, buf_array_size, HZ);
+ 0x00, 0x00, buf, buf_array_size, 1000);
if (retval != 8) {
dev_err(&vub300->udev->dev, "SET_CLOCK_SPEED"
" %dkHz failed with retval=%d\n", kHzClock, retval);
@@ -2020,14 +2020,14 @@ static void vub300_mmc_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
usb_control_msg(vub300->udev, usb_sndctrlpipe(vub300->udev, 0),
SET_SD_POWER,
USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
- 0x0000, 0x0000, NULL, 0, HZ);
+ 0x0000, 0x0000, NULL, 0, 1000);
/* must wait for the VUB300 u-proc to boot up */
msleep(600);
} else if ((ios->power_mode == MMC_POWER_UP) && !vub300->card_powered) {
usb_control_msg(vub300->udev, usb_sndctrlpipe(vub300->udev, 0),
SET_SD_POWER,
USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
- 0x0001, 0x0000, NULL, 0, HZ);
+ 0x0001, 0x0000, NULL, 0, 1000);
msleep(600);
vub300->card_powered = 1;
} else if (ios->power_mode == MMC_POWER_ON) {
@@ -2290,14 +2290,14 @@ static int vub300_probe(struct usb_interface *interface,
GET_HC_INF0,
USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
0x0000, 0x0000, &vub300->hc_info,
- sizeof(vub300->hc_info), HZ);
+ sizeof(vub300->hc_info), 1000);
if (retval < 0)
goto error5;
retval =
- usb_control_msg(vub300->udev, usb_rcvctrlpipe(vub300->udev, 0),
+ usb_control_msg(vub300->udev, usb_sndctrlpipe(vub300->udev, 0),
SET_ROM_WAIT_STATES,
USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
- firmware_rom_wait_states, 0x0000, NULL, 0, HZ);
+ firmware_rom_wait_states, 0x0000, NULL, 0, 1000);
if (retval < 0)
goto error5;
dev_info(&vub300->udev->dev,
@@ -2312,7 +2312,7 @@ static int vub300_probe(struct usb_interface *interface,
GET_SYSTEM_PORT_STATUS,
USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
0x0000, 0x0000, &vub300->system_port_status,
- sizeof(vub300->system_port_status), HZ);
+ sizeof(vub300->system_port_status), 1000);
if (retval < 0) {
goto error4;
} else if (sizeof(vub300->system_port_status) == retval) {