summaryrefslogtreecommitdiffstats
path: root/drivers/mmc/host
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/mmc/host')
-rw-r--r--drivers/mmc/host/Kconfig10
-rw-r--r--drivers/mmc/host/Makefile2
-rw-r--r--drivers/mmc/host/atmel-mci.c34
-rw-r--r--drivers/mmc/host/dw_mmc-exynos.c9
-rw-r--r--drivers/mmc/host/dw_mmc-pci.c4
-rw-r--r--drivers/mmc/host/dw_mmc-pltfm.c1
-rw-r--r--drivers/mmc/host/dw_mmc.c23
-rw-r--r--drivers/mmc/host/jz4740_mmc.c7
-rw-r--r--drivers/mmc/host/mmc_spi.c49
-rw-r--r--drivers/mmc/host/mvsdio.c3
-rw-r--r--drivers/mmc/host/mxs-mmc.c22
-rw-r--r--drivers/mmc/host/of_mmc_spi.c46
-rw-r--r--drivers/mmc/host/omap_hsmmc.c3
-rw-r--r--drivers/mmc/host/pxamci.c2
-rw-r--r--drivers/mmc/host/rtsx_pci_sdmmc.c70
-rw-r--r--drivers/mmc/host/sdhci-bcm-kona.c18
-rw-r--r--drivers/mmc/host/sdhci-bcm2835.c2
-rw-r--r--drivers/mmc/host/sdhci-esdhc-imx.c2
-rw-r--r--drivers/mmc/host/sdhci-of-esdhc.c1
-rw-r--r--drivers/mmc/host/sdhci-pxav3.c3
-rw-r--r--drivers/mmc/host/sdhci-s3c.c8
-rw-r--r--drivers/mmc/host/sdhci-sirf.c2
-rw-r--r--drivers/mmc/host/sdhci.c11
-rw-r--r--drivers/mmc/host/sh_mmcif.c63
-rw-r--r--drivers/mmc/host/sh_mobile_sdhi.c23
-rw-r--r--drivers/mmc/host/tmio_mmc_dma.c4
-rw-r--r--drivers/mmc/host/tmio_mmc_pio.c24
-rw-r--r--drivers/mmc/host/vub300.c2
28 files changed, 248 insertions, 200 deletions
diff --git a/drivers/mmc/host/Kconfig b/drivers/mmc/host/Kconfig
index 8a4c066787d..b7fd5ab80a4 100644
--- a/drivers/mmc/host/Kconfig
+++ b/drivers/mmc/host/Kconfig
@@ -284,11 +284,11 @@ config MMC_OMAP
config MMC_OMAP_HS
tristate "TI OMAP High Speed Multimedia Card Interface support"
- depends on SOC_OMAP2430 || ARCH_OMAP3 || ARCH_OMAP4
+ depends on ARCH_OMAP2PLUS || COMPILE_TEST
help
This selects the TI OMAP High Speed Multimedia card Interface.
- If you have an OMAP2430 or OMAP3 board or OMAP4 board with a
- Multimedia Card slot, say Y or M here.
+ If you have an omap2plus board with a Multimedia Card slot,
+ say Y or M here.
If unsure, say N.
@@ -530,7 +530,7 @@ config SDH_BFIN_MISSING_CMD_PULLUP_WORKAROUND
config MMC_DW
tristate "Synopsys DesignWare Memory Card Interface"
- depends on ARM
+ depends on ARC || ARM
help
This selects support for the Synopsys DesignWare Mobile Storage IP
block, this provides host support for SD and MMC interfaces, in both
@@ -569,7 +569,7 @@ config MMC_DW_EXYNOS
config MMC_DW_SOCFPGA
tristate "SOCFPGA specific extensions for Synopsys DW Memory Card Interface"
- depends on MMC_DW
+ depends on MMC_DW && MFD_SYSCON
select MMC_DW_PLTFM
help
This selects support for Altera SoCFPGA specific extensions to the
diff --git a/drivers/mmc/host/Makefile b/drivers/mmc/host/Makefile
index d422e2167e1..c41d0c36450 100644
--- a/drivers/mmc/host/Makefile
+++ b/drivers/mmc/host/Makefile
@@ -52,8 +52,6 @@ obj-$(CONFIG_MMC_WMT) += wmt-sdmmc.o
obj-$(CONFIG_MMC_REALTEK_PCI) += rtsx_pci_sdmmc.o
-obj-$(CONFIG_MMC_REALTEK_PCI) += rtsx_pci_sdmmc.o
-
obj-$(CONFIG_MMC_SDHCI_PLTFM) += sdhci-pltfm.o
obj-$(CONFIG_MMC_SDHCI_CNS3XXX) += sdhci-cns3xxx.o
obj-$(CONFIG_MMC_SDHCI_ESDHC_IMX) += sdhci-esdhc-imx.o
diff --git a/drivers/mmc/host/atmel-mci.c b/drivers/mmc/host/atmel-mci.c
index bdb84da7495..69e438ee043 100644
--- a/drivers/mmc/host/atmel-mci.c
+++ b/drivers/mmc/host/atmel-mci.c
@@ -378,6 +378,8 @@ static int atmci_regs_show(struct seq_file *s, void *v)
{
struct atmel_mci *host = s->private;
u32 *buf;
+ int ret = 0;
+
buf = kmalloc(ATMCI_REGS_SIZE, GFP_KERNEL);
if (!buf)
@@ -388,12 +390,16 @@ static int atmci_regs_show(struct seq_file *s, void *v)
* not disabling interrupts, so IMR and SR may not be
* consistent.
*/
+ ret = clk_prepare_enable(host->mck);
+ if (ret)
+ goto out;
+
spin_lock_bh(&host->lock);
- clk_enable(host->mck);
memcpy_fromio(buf, host->regs, ATMCI_REGS_SIZE);
- clk_disable(host->mck);
spin_unlock_bh(&host->lock);
+ clk_disable_unprepare(host->mck);
+
seq_printf(s, "MR:\t0x%08x%s%s ",
buf[ATMCI_MR / 4],
buf[ATMCI_MR / 4] & ATMCI_MR_RDPROOF ? " RDPROOF" : "",
@@ -442,9 +448,10 @@ static int atmci_regs_show(struct seq_file *s, void *v)
val & ATMCI_CFG_LSYNC ? " LSYNC" : "");
}
+out:
kfree(buf);
- return 0;
+ return ret;
}
static int atmci_regs_open(struct inode *inode, struct file *file)
@@ -1262,6 +1269,7 @@ static void atmci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
struct atmel_mci_slot *slot = mmc_priv(mmc);
struct atmel_mci *host = slot->host;
unsigned int i;
+ bool unprepare_clk;
slot->sdc_reg &= ~ATMCI_SDCBUS_MASK;
switch (ios->bus_width) {
@@ -1277,9 +1285,13 @@ static void atmci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
unsigned int clock_min = ~0U;
u32 clkdiv;
+ clk_prepare(host->mck);
+ unprepare_clk = true;
+
spin_lock_bh(&host->lock);
if (!host->mode_reg) {
clk_enable(host->mck);
+ unprepare_clk = false;
atmci_writel(host, ATMCI_CR, ATMCI_CR_SWRST);
atmci_writel(host, ATMCI_CR, ATMCI_CR_MCIEN);
if (host->caps.has_cfg_reg)
@@ -1347,6 +1359,8 @@ static void atmci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
} else {
bool any_slot_active = false;
+ unprepare_clk = false;
+
spin_lock_bh(&host->lock);
slot->clock = 0;
for (i = 0; i < ATMCI_MAX_NR_SLOTS; i++) {
@@ -1360,12 +1374,16 @@ static void atmci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
if (host->mode_reg) {
atmci_readl(host, ATMCI_MR);
clk_disable(host->mck);
+ unprepare_clk = true;
}
host->mode_reg = 0;
}
spin_unlock_bh(&host->lock);
}
+ if (unprepare_clk)
+ clk_unprepare(host->mck);
+
switch (ios->power_mode) {
case MMC_POWER_UP:
set_bit(ATMCI_CARD_NEED_INIT, &slot->flags);
@@ -2376,10 +2394,12 @@ static int __init atmci_probe(struct platform_device *pdev)
if (!host->regs)
goto err_ioremap;
- clk_enable(host->mck);
+ ret = clk_prepare_enable(host->mck);
+ if (ret)
+ goto err_request_irq;
atmci_writel(host, ATMCI_CR, ATMCI_CR_SWRST);
host->bus_hz = clk_get_rate(host->mck);
- clk_disable(host->mck);
+ clk_disable_unprepare(host->mck);
host->mapbase = regs->start;
@@ -2482,11 +2502,11 @@ static int __exit atmci_remove(struct platform_device *pdev)
atmci_cleanup_slot(host->slot[i], i);
}
- clk_enable(host->mck);
+ clk_prepare_enable(host->mck);
atmci_writel(host, ATMCI_IDR, ~0UL);
atmci_writel(host, ATMCI_CR, ATMCI_CR_MCIDIS);
atmci_readl(host, ATMCI_SR);
- clk_disable(host->mck);
+ clk_disable_unprepare(host->mck);
if (host->dma.chan)
dma_release_channel(host->dma.chan);
diff --git a/drivers/mmc/host/dw_mmc-exynos.c b/drivers/mmc/host/dw_mmc-exynos.c
index 866edef2e82..6a1fa2110a0 100644
--- a/drivers/mmc/host/dw_mmc-exynos.c
+++ b/drivers/mmc/host/dw_mmc-exynos.c
@@ -39,6 +39,7 @@ enum dw_mci_exynos_type {
DW_MCI_TYPE_EXYNOS4210,
DW_MCI_TYPE_EXYNOS4412,
DW_MCI_TYPE_EXYNOS5250,
+ DW_MCI_TYPE_EXYNOS5420,
};
/* Exynos implementation specific driver private data */
@@ -62,6 +63,9 @@ static struct dw_mci_exynos_compatible {
}, {
.compatible = "samsung,exynos5250-dw-mshc",
.ctrl_type = DW_MCI_TYPE_EXYNOS5250,
+ }, {
+ .compatible = "samsung,exynos5420-dw-mshc",
+ .ctrl_type = DW_MCI_TYPE_EXYNOS5420,
},
};
@@ -90,7 +94,8 @@ static int dw_mci_exynos_setup_clock(struct dw_mci *host)
{
struct dw_mci_exynos_priv_data *priv = host->priv;
- if (priv->ctrl_type == DW_MCI_TYPE_EXYNOS5250)
+ if (priv->ctrl_type == DW_MCI_TYPE_EXYNOS5250 ||
+ priv->ctrl_type == DW_MCI_TYPE_EXYNOS5420)
host->bus_hz /= (priv->ciu_div + 1);
else if (priv->ctrl_type == DW_MCI_TYPE_EXYNOS4412)
host->bus_hz /= EXYNOS4412_FIXED_CIU_CLK_DIV;
@@ -173,6 +178,8 @@ static const struct of_device_id dw_mci_exynos_match[] = {
.data = &exynos_drv_data, },
{ .compatible = "samsung,exynos5250-dw-mshc",
.data = &exynos_drv_data, },
+ { .compatible = "samsung,exynos5420-dw-mshc",
+ .data = &exynos_drv_data, },
{},
};
MODULE_DEVICE_TABLE(of, dw_mci_exynos_match);
diff --git a/drivers/mmc/host/dw_mmc-pci.c b/drivers/mmc/host/dw_mmc-pci.c
index b456b0c3523..f70546a3a7c 100644
--- a/drivers/mmc/host/dw_mmc-pci.c
+++ b/drivers/mmc/host/dw_mmc-pci.c
@@ -59,7 +59,9 @@ static int dw_mci_pci_probe(struct pci_dev *pdev,
if (ret)
return ret;
- host->regs = pcim_iomap_table(pdev)[0];
+ host->regs = pcim_iomap_table(pdev)[PCI_BAR_NO];
+
+ pci_set_master(pdev);
ret = dw_mci_probe(host);
if (ret)
diff --git a/drivers/mmc/host/dw_mmc-pltfm.c b/drivers/mmc/host/dw_mmc-pltfm.c
index ee525565aa7..20897529ea5 100644
--- a/drivers/mmc/host/dw_mmc-pltfm.c
+++ b/drivers/mmc/host/dw_mmc-pltfm.c
@@ -23,6 +23,7 @@
#include <linux/of.h>
#include "dw_mmc.h"
+#include "dw_mmc-pltfm.h"
static void dw_mci_rockchip_prepare_command(struct dw_mci *host, u32 *cmdr)
{
diff --git a/drivers/mmc/host/dw_mmc.c b/drivers/mmc/host/dw_mmc.c
index ee5f1676f14..018f365e5ae 100644
--- a/drivers/mmc/host/dw_mmc.c
+++ b/drivers/mmc/host/dw_mmc.c
@@ -1601,18 +1601,17 @@ static irqreturn_t dw_mci_interrupt(int irq, void *dev_id)
pending = mci_readl(host, MINTSTS); /* read-only mask reg */
- if (pending) {
-
- /*
- * DTO fix - version 2.10a and below, and only if internal DMA
- * is configured.
- */
- if (host->quirks & DW_MCI_QUIRK_IDMAC_DTO) {
- if (!pending &&
- ((mci_readl(host, STATUS) >> 17) & 0x1fff))
- pending |= SDMMC_INT_DATA_OVER;
- }
+ /*
+ * DTO fix - version 2.10a and below, and only if internal DMA
+ * is configured.
+ */
+ if (host->quirks & DW_MCI_QUIRK_IDMAC_DTO) {
+ if (!pending &&
+ ((mci_readl(host, STATUS) >> 17) & 0x1fff))
+ pending |= SDMMC_INT_DATA_OVER;
+ }
+ if (pending) {
if (pending & DW_MCI_CMD_ERROR_FLAGS) {
mci_writel(host, RINTSTS, DW_MCI_CMD_ERROR_FLAGS);
host->cmd_status = pending;
@@ -2231,7 +2230,7 @@ int dw_mci_probe(struct dw_mci *host)
}
}
- host->vmmc = devm_regulator_get(host->dev, "vmmc");
+ host->vmmc = devm_regulator_get_optional(host->dev, "vmmc");
if (IS_ERR(host->vmmc)) {
ret = PTR_ERR(host->vmmc);
if (ret == -EPROBE_DEFER)
diff --git a/drivers/mmc/host/jz4740_mmc.c b/drivers/mmc/host/jz4740_mmc.c
index 0308c9f1cf5..66516339e3a 100644
--- a/drivers/mmc/host/jz4740_mmc.c
+++ b/drivers/mmc/host/jz4740_mmc.c
@@ -713,7 +713,7 @@ static int jz4740_mmc_request_gpios(struct mmc_host *mmc,
mmc->caps2 |= MMC_CAP2_RO_ACTIVE_HIGH;
if (gpio_is_valid(pdata->gpio_card_detect)) {
- ret = mmc_gpio_request_cd(mmc, pdata->gpio_card_detect);
+ ret = mmc_gpio_request_cd(mmc, pdata->gpio_card_detect, 0);
if (ret)
return ret;
}
@@ -783,9 +783,8 @@ static int jz4740_mmc_probe(struct platform_device* pdev)
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
host->base = devm_ioremap_resource(&pdev->dev, res);
- if (!host->base) {
- ret = -EBUSY;
- dev_err(&pdev->dev, "Failed to ioremap base memory\n");
+ if (IS_ERR(host->base)) {
+ ret = PTR_ERR(host->base);
goto err_free_host;
}
diff --git a/drivers/mmc/host/mmc_spi.c b/drivers/mmc/host/mmc_spi.c
index 74145d1d51f..0a87e569134 100644
--- a/drivers/mmc/host/mmc_spi.c
+++ b/drivers/mmc/host/mmc_spi.c
@@ -36,6 +36,7 @@
#include <linux/mmc/host.h>
#include <linux/mmc/mmc.h> /* for R1_SPI_* bit values */
+#include <linux/mmc/slot-gpio.h>
#include <linux/spi/spi.h>
#include <linux/spi/mmc_spi.h>
@@ -1272,33 +1273,11 @@ static void mmc_spi_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
}
}
-static int mmc_spi_get_ro(struct mmc_host *mmc)
-{
- struct mmc_spi_host *host = mmc_priv(mmc);
-
- if (host->pdata && host->pdata->get_ro)
- return !!host->pdata->get_ro(mmc->parent);
- /*
- * Board doesn't support read only detection; let the mmc core
- * decide what to do.
- */
- return -ENOSYS;
-}
-
-static int mmc_spi_get_cd(struct mmc_host *mmc)
-{
- struct mmc_spi_host *host = mmc_priv(mmc);
-
- if (host->pdata && host->pdata->get_cd)
- return !!host->pdata->get_cd(mmc->parent);
- return -ENOSYS;
-}
-
static const struct mmc_host_ops mmc_spi_ops = {
.request = mmc_spi_request,
.set_ios = mmc_spi_set_ios,
- .get_ro = mmc_spi_get_ro,
- .get_cd = mmc_spi_get_cd,
+ .get_ro = mmc_gpio_get_ro,
+ .get_cd = mmc_gpio_get_cd,
};
@@ -1324,6 +1303,7 @@ static int mmc_spi_probe(struct spi_device *spi)
struct mmc_host *mmc;
struct mmc_spi_host *host;
int status;
+ bool has_ro = false;
/* We rely on full duplex transfers, mostly to reduce
* per-transfer overheads (by making fewer transfers).
@@ -1448,18 +1428,33 @@ static int mmc_spi_probe(struct spi_device *spi)
}
/* pass platform capabilities, if any */
- if (host->pdata)
+ if (host->pdata) {
mmc->caps |= host->pdata->caps;
+ mmc->caps2 |= host->pdata->caps2;
+ }
status = mmc_add_host(mmc);
if (status != 0)
goto fail_add_host;
+ if (host->pdata && host->pdata->flags & MMC_SPI_USE_CD_GPIO) {
+ status = mmc_gpio_request_cd(mmc, host->pdata->cd_gpio,
+ host->pdata->cd_debounce);
+ if (status != 0)
+ goto fail_add_host;
+ }
+
+ if (host->pdata && host->pdata->flags & MMC_SPI_USE_RO_GPIO) {
+ has_ro = true;
+ status = mmc_gpio_request_ro(mmc, host->pdata->ro_gpio);
+ if (status != 0)
+ goto fail_add_host;
+ }
+
dev_info(&spi->dev, "SD/MMC host %s%s%s%s%s\n",
dev_name(&mmc->class_dev),
host->dma_dev ? "" : ", no DMA",
- (host->pdata && host->pdata->get_ro)
- ? "" : ", no WP",
+ has_ro ? "" : ", no WP",
(host->pdata && host->pdata->setpower)
? "" : ", no poweroff",
(mmc->caps & MMC_CAP_NEEDS_POLL)
diff --git a/drivers/mmc/host/mvsdio.c b/drivers/mmc/host/mvsdio.c
index 4ddd83f9865..06c5b0b28eb 100644
--- a/drivers/mmc/host/mvsdio.c
+++ b/drivers/mmc/host/mvsdio.c
@@ -757,7 +757,8 @@ static int __init mvsd_probe(struct platform_device *pdev)
if (mvsd_data->gpio_card_detect &&
gpio_is_valid(mvsd_data->gpio_card_detect)) {
ret = mmc_gpio_request_cd(mmc,
- mvsd_data->gpio_card_detect);
+ mvsd_data->gpio_card_detect,
+ 0);
if (ret)
goto out;
} else {
diff --git a/drivers/mmc/host/mxs-mmc.c b/drivers/mmc/host/mxs-mmc.c
index f38d75f46f7..e1fa3ef735e 100644
--- a/drivers/mmc/host/mxs-mmc.c
+++ b/drivers/mmc/host/mxs-mmc.c
@@ -102,12 +102,15 @@ static int mxs_mmc_get_cd(struct mmc_host *mmc)
BM_SSP_STATUS_CARD_DETECT) ^ host->cd_inverted;
}
-static void mxs_mmc_reset(struct mxs_mmc_host *host)
+static int mxs_mmc_reset(struct mxs_mmc_host *host)
{
struct mxs_ssp *ssp = &host->ssp;
u32 ctrl0, ctrl1;
+ int ret;
- stmp_reset_block(ssp->base);
+ ret = stmp_reset_block(ssp->base);
+ if (ret)
+ return ret;
ctrl0 = BM_SSP_CTRL0_IGNORE_CRC;
ctrl1 = BF_SSP(0x3, CTRL1_SSP_MODE) |
@@ -132,6 +135,7 @@ static void mxs_mmc_reset(struct mxs_mmc_host *host)
writel(ctrl0, ssp->base + HW_SSP_CTRL0);
writel(ctrl1, ssp->base + HW_SSP_CTRL1(ssp));
+ return 0;
}
static void mxs_mmc_start_cmd(struct mxs_mmc_host *host,
@@ -618,21 +622,25 @@ static int mxs_mmc_probe(struct platform_device *pdev)
}
}
- ssp->clk = clk_get(&pdev->dev, NULL);
+ ssp->clk = devm_clk_get(&pdev->dev, NULL);
if (IS_ERR(ssp->clk)) {
ret = PTR_ERR(ssp->clk);
goto out_mmc_free;
}
clk_prepare_enable(ssp->clk);
- mxs_mmc_reset(host);
+ ret = mxs_mmc_reset(host);
+ if (ret) {
+ dev_err(&pdev->dev, "Failed to reset mmc: %d\n", ret);
+ goto out_clk_disable;
+ }
ssp->dmach = dma_request_slave_channel(&pdev->dev, "rx-tx");
if (!ssp->dmach) {
dev_err(mmc_dev(host->mmc),
"%s: failed to request dma\n", __func__);
ret = -ENODEV;
- goto out_clk_put;
+ goto out_clk_disable;
}
/* set mmc core parameters */
@@ -685,9 +693,8 @@ static int mxs_mmc_probe(struct platform_device *pdev)
out_free_dma:
if (ssp->dmach)
dma_release_channel(ssp->dmach);
-out_clk_put:
+out_clk_disable:
clk_disable_unprepare(ssp->clk);
- clk_put(ssp->clk);
out_mmc_free:
mmc_free_host(mmc);
return ret;
@@ -705,7 +712,6 @@ static int mxs_mmc_remove(struct platform_device *pdev)
dma_release_channel(ssp->dmach);
clk_disable_unprepare(ssp->clk);
- clk_put(ssp->clk);
mmc_free_host(mmc);
diff --git a/drivers/mmc/host/of_mmc_spi.c b/drivers/mmc/host/of_mmc_spi.c
index d720b5e05b9..6e218fb1a66 100644
--- a/drivers/mmc/host/of_mmc_spi.c
+++ b/drivers/mmc/host/of_mmc_spi.c
@@ -50,25 +50,6 @@ static struct of_mmc_spi *to_of_mmc_spi(struct device *dev)
return container_of(dev->platform_data, struct of_mmc_spi, pdata);
}
-static int of_mmc_spi_read_gpio(struct device *dev, int gpio_num)
-{
- struct of_mmc_spi *oms = to_of_mmc_spi(dev);
- bool active_low = oms->alow_gpios[gpio_num];
- bool value = gpio_get_value(oms->gpios[gpio_num]);
-
- return active_low ^ value;
-}
-
-static int of_mmc_spi_get_cd(struct device *dev)
-{
- return of_mmc_spi_read_gpio(dev, CD_GPIO);
-}
-
-static int of_mmc_spi_get_ro(struct device *dev)
-{
- return of_mmc_spi_read_gpio(dev, WP_GPIO);
-}
-
static int of_mmc_spi_init(struct device *dev,
irqreturn_t (*irqhandler)(int, void *), void *mmc)
{
@@ -130,20 +111,22 @@ struct mmc_spi_platform_data *mmc_spi_get_pdata(struct spi_device *spi)
if (!gpio_is_valid(oms->gpios[i]))
continue;
- ret = gpio_request(oms->gpios[i], dev_name(dev));
- if (ret < 0) {
- oms->gpios[i] = -EINVAL;
- continue;
- }
-
if (gpio_flags & OF_GPIO_ACTIVE_LOW)
oms->alow_gpios[i] = true;
}
- if (gpio_is_valid(oms->gpios[CD_GPIO]))
- oms->pdata.get_cd = of_mmc_spi_get_cd;
- if (gpio_is_valid(oms->gpios[WP_GPIO]))
- oms->pdata.get_ro = of_mmc_spi_get_ro;
+ if (gpio_is_valid(oms->gpios[CD_GPIO])) {
+ oms->pdata.cd_gpio = oms->gpios[CD_GPIO];
+ oms->pdata.flags |= MMC_SPI_USE_CD_GPIO;
+ if (!oms->alow_gpios[CD_GPIO])
+ oms->pdata.caps2 |= MMC_CAP2_CD_ACTIVE_HIGH;
+ }
+ if (gpio_is_valid(oms->gpios[WP_GPIO])) {
+ oms->pdata.ro_gpio = oms->gpios[WP_GPIO];
+ oms->pdata.flags |= MMC_SPI_USE_RO_GPIO;
+ if (!oms->alow_gpios[WP_GPIO])
+ oms->pdata.caps2 |= MMC_CAP2_RO_ACTIVE_HIGH;
+ }
oms->detect_irq = irq_of_parse_and_map(np, 0);
if (oms->detect_irq != 0) {
@@ -166,15 +149,10 @@ void mmc_spi_put_pdata(struct spi_device *spi)
struct device *dev = &spi->dev;
struct device_node *np = dev->of_node;
struct of_mmc_spi *oms = to_of_mmc_spi(dev);
- int i;
if (!dev->platform_data || !np)
return;
- for (i = 0; i < ARRAY_SIZE(oms->gpios); i++) {
- if (gpio_is_valid(oms->gpios[i]))
- gpio_free(oms->gpios[i]);
- }
kfree(oms);
dev->platform_data = NULL;
}
diff --git a/drivers/mmc/host/omap_hsmmc.c b/drivers/mmc/host/omap_hsmmc.c
index 1865321465c..6ac63df645c 100644
--- a/drivers/mmc/host/omap_hsmmc.c
+++ b/drivers/mmc/host/omap_hsmmc.c
@@ -21,6 +21,7 @@
#include <linux/debugfs.h>
#include <linux/dmaengine.h>
#include <linux/seq_file.h>
+#include <linux/sizes.h>
#include <linux/interrupt.h>
#include <linux/delay.h>
#include <linux/dma-mapping.h>
@@ -1041,6 +1042,7 @@ static void omap_hsmmc_do_irq(struct omap_hsmmc_host *host, int status)
}
}
+ OMAP_HSMMC_WRITE(host->base, STAT, status);
if (end_cmd || ((status & CC_EN) && host->cmd))
omap_hsmmc_cmd_done(host, host->cmd);
if ((end_trans || (status & TC_EN)) && host->mrq)
@@ -1060,7 +1062,6 @@ static irqreturn_t omap_hsmmc_irq(int irq, void *dev_id)
omap_hsmmc_do_irq(host, status);
/* Flush posted write */
- OMAP_HSMMC_WRITE(host->base, STAT, status);
status = OMAP_HSMMC_READ(host->base, STAT);
}
diff --git a/drivers/mmc/host/pxamci.c b/drivers/mmc/host/pxamci.c
index 2c5a91bb8ec..1956a3df7cf 100644
--- a/drivers/mmc/host/pxamci.c
+++ b/drivers/mmc/host/pxamci.c
@@ -83,7 +83,7 @@ struct pxamci_host {
static inline void pxamci_init_ocr(struct pxamci_host *host)
{
#ifdef CONFIG_REGULATOR
- host->vcc = regulator_get(mmc_dev(host->mmc), "vmmc");
+ host->vcc = regulator_get_optional(mmc_dev(host->mmc), "vmmc");
if (IS_ERR(host->vcc))
host->vcc = NULL;
diff --git a/drivers/mmc/host/rtsx_pci_sdmmc.c b/drivers/mmc/host/rtsx_pci_sdmmc.c
index 82a35b91cdb..375a880e0c5 100644
--- a/drivers/mmc/host/rtsx_pci_sdmmc.c
+++ b/drivers/mmc/host/rtsx_pci_sdmmc.c
@@ -1,6 +1,6 @@
/* Realtek PCI-Express SD/MMC Card Interface driver
*
- * Copyright(c) 2009 Realtek Semiconductor Corp. All rights reserved.
+ * Copyright(c) 2009-2013 Realtek Semiconductor Corp. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
@@ -17,7 +17,6 @@
*
* Author:
* Wei WANG <wei_wang@realsil.com.cn>
- * No. 450, Shenhu Road, Suzhou Industry Park, Suzhou, China
*/
#include <linux/module.h>
@@ -56,7 +55,6 @@ struct realtek_pci_sdmmc {
bool double_clk;
bool eject;
bool initial_mode;
- bool ddr_mode;
int power_state;
#define SDMMC_POWER_ON 1
#define SDMMC_POWER_OFF 0
@@ -228,6 +226,7 @@ static void sd_send_cmd_get_rsp(struct realtek_pci_sdmmc *host,
int stat_idx = 0;
u8 rsp_type;
int rsp_len = 5;
+ bool clock_toggled = false;
dev_dbg(sdmmc_dev(host), "%s: SD/MMC CMD %d, arg = 0x%08x\n",
__func__, cmd_idx, arg);
@@ -271,6 +270,8 @@ static void sd_send_cmd_get_rsp(struct realtek_pci_sdmmc *host,
0xFF, SD_CLK_TOGGLE_EN);
if (err < 0)
goto out;
+
+ clock_toggled = true;
}
rtsx_pci_init_cmd(pcr);
@@ -351,6 +352,10 @@ static void sd_send_cmd_get_rsp(struct realtek_pci_sdmmc *host,
out:
cmd->error = err;
+
+ if (err && clock_toggled)
+ rtsx_pci_write_register(pcr, SD_BUS_STAT,
+ SD_CLK_TOGGLE_EN | SD_CLK_FORCE_STOP, 0);
}
static int sd_rw_multi(struct realtek_pci_sdmmc *host, struct mmc_request *mrq)
@@ -475,18 +480,24 @@ static void sd_normal_rw(struct realtek_pci_sdmmc *host,
kfree(buf);
}
-static int sd_change_phase(struct realtek_pci_sdmmc *host, u8 sample_point)
+static int sd_change_phase(struct realtek_pci_sdmmc *host,
+ u8 sample_point, bool rx)
{
struct rtsx_pcr *pcr = host->pcr;
int err;
- dev_dbg(sdmmc_dev(host), "%s: sample_point = %d\n",
- __func__, sample_point);
+ dev_dbg(sdmmc_dev(host), "%s(%s): sample_point = %d\n",
+ __func__, rx ? "RX" : "TX", sample_point);
rtsx_pci_init_cmd(pcr);
rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, CLK_CTL, CHANGE_CLK, CHANGE_CLK);
- rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, SD_VPRX_CTL, 0x1F, sample_point);
+ if (rx)
+ rtsx_pci_add_cmd(pcr, WRITE_REG_CMD,
+ SD_VPRX_CTL, 0x1F, sample_point);
+ else
+ rtsx_pci_add_cmd(pcr, WRITE_REG_CMD,
+ SD_VPTX_CTL, 0x1F, sample_point);
rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, SD_VPCLK0_CTL, PHASE_NOT_RESET, 0);
rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, SD_VPCLK0_CTL,
PHASE_NOT_RESET, PHASE_NOT_RESET);
@@ -602,7 +613,7 @@ static int sd_tuning_rx_cmd(struct realtek_pci_sdmmc *host,
int err;
u8 cmd[5] = {0};
- err = sd_change_phase(host, sample_point);
+ err = sd_change_phase(host, sample_point, true);
if (err < 0)
return err;
@@ -664,7 +675,7 @@ static int sd_tuning_rx(struct realtek_pci_sdmmc *host, u8 opcode)
if (final_phase == 0xFF)
return -EINVAL;
- err = sd_change_phase(host, final_phase);
+ err = sd_change_phase(host, final_phase, true);
if (err < 0)
return err;
} else {
@@ -833,14 +844,11 @@ static int sd_set_power_mode(struct realtek_pci_sdmmc *host,
return err;
}
-static int sd_set_timing(struct realtek_pci_sdmmc *host,
- unsigned char timing, bool *ddr_mode)
+static int sd_set_timing(struct realtek_pci_sdmmc *host, unsigned char timing)
{
struct rtsx_pcr *pcr = host->pcr;
int err = 0;
- *ddr_mode = false;
-
rtsx_pci_init_cmd(pcr);
switch (timing) {
@@ -857,8 +865,6 @@ static int sd_set_timing(struct realtek_pci_sdmmc *host,
break;
case MMC_TIMING_UHS_DDR50:
- *ddr_mode = true;
-
rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, SD_CFG1,
0x0C | SD_ASYNC_FIFO_NOT_RST,
SD_DDR_MODE | SD_ASYNC_FIFO_NOT_RST);
@@ -926,7 +932,7 @@ static void sdmmc_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
sd_set_bus_width(host, ios->bus_width);
sd_set_power_mode(host, ios->power_mode);
- sd_set_timing(host, ios->timing, &host->ddr_mode);
+ sd_set_timing(host, ios->timing);
host->vpclk = false;
host->double_clk = true;
@@ -1121,11 +1127,11 @@ static int sdmmc_switch_voltage(struct mmc_host *mmc, struct mmc_ios *ios)
goto out;
}
+out:
/* Stop toggle SD clock in idle */
err = rtsx_pci_write_register(pcr, SD_BUS_STAT,
SD_CLK_TOGGLE_EN | SD_CLK_FORCE_STOP, 0);
-out:
mutex_unlock(&pcr->pcr_mutex);
return err;
@@ -1148,9 +1154,35 @@ static int sdmmc_execute_tuning(struct mmc_host *mmc, u32 opcode)
rtsx_pci_start_run(pcr);
- if (!host->ddr_mode)
- err = sd_tuning_rx(host, MMC_SEND_TUNING_BLOCK);
+ /* Set initial TX phase */
+ switch (mmc->ios.timing) {
+ case MMC_TIMING_UHS_SDR104:
+ err = sd_change_phase(host, SDR104_TX_PHASE(pcr), false);
+ break;
+
+ case MMC_TIMING_UHS_SDR50:
+ err = sd_change_phase(host, SDR50_TX_PHASE(pcr), false);
+ break;
+
+ case MMC_TIMING_UHS_DDR50:
+ err = sd_change_phase(host, DDR50_TX_PHASE(pcr), false);
+ break;
+
+ default:
+ err = 0;
+ }
+ if (err)
+ goto out;
+
+ /* Tuning RX phase */
+ if ((mmc->ios.timing == MMC_TIMING_UHS_SDR104) ||
+ (mmc->ios.timing == MMC_TIMING_UHS_SDR50))
+ err = sd_tuning_rx(host, opcode);
+ else if (mmc->ios.timing == MMC_TIMING_UHS_DDR50)
+ err = sd_change_phase(host, DDR50_RX_PHASE(pcr), true);
+
+out:
mutex_unlock(&pcr->pcr_mutex);
return err;
diff --git a/drivers/mmc/host/sdhci-bcm-kona.c b/drivers/mmc/host/sdhci-bcm-kona.c
index 87175f9817c..85472d3fd37 100644
--- a/drivers/mmc/host/sdhci-bcm-kona.c
+++ b/drivers/mmc/host/sdhci-bcm-kona.c
@@ -24,7 +24,6 @@
#include <linux/of.h>
#include <linux/of_device.h>
#include <linux/of_gpio.h>
-#include <linux/version.h>
#include <linux/mmc/slot-gpio.h>
#include "sdhci-pltfm.h"
@@ -162,7 +161,7 @@ static int sdhci_bcm_kona_sd_card_emulate(struct sdhci_host *host, int insert)
/*
* SD card interrupt event callback
*/
-void sdhci_bcm_kona_card_event(struct sdhci_host *host)
+static void sdhci_bcm_kona_card_event(struct sdhci_host *host)
{
if (mmc_gpio_get_cd(host->mmc) > 0) {
dev_dbg(mmc_dev(host->mmc),
@@ -221,13 +220,14 @@ static struct sdhci_pltfm_data sdhci_pltfm_data_kona = {
SDHCI_QUIRK_CAP_CLOCK_BASE_BROKEN,
};
-static const struct of_device_id sdhci_bcm_kona_of_match[] __initdata = {
- { .compatible = "bcm,kona-sdhci"},
+static struct __initconst of_device_id sdhci_bcm_kona_of_match[] = {
+ { .compatible = "brcm,kona-sdhci"},
+ { .compatible = "bcm,kona-sdhci"}, /* deprecated name */
{}
};
MODULE_DEVICE_TABLE(of, sdhci_bcm_kona_of_match);
-static int __init sdhci_bcm_kona_probe(struct platform_device *pdev)
+static int sdhci_bcm_kona_probe(struct platform_device *pdev)
{
struct sdhci_bcm_kona_dev *kona_dev = NULL;
struct sdhci_pltfm_host *pltfm_priv;
@@ -263,7 +263,7 @@ static int __init sdhci_bcm_kona_probe(struct platform_device *pdev)
(mmc_gpio_get_cd(host->mmc) != -ENOSYS) ? 'Y' : 'N',
(mmc_gpio_get_ro(host->mmc) != -ENOSYS) ? 'Y' : 'N');
- if (host->mmc->caps | MMC_CAP_NONREMOVABLE)
+ if (host->mmc->caps & MMC_CAP_NONREMOVABLE)
host->quirks |= SDHCI_QUIRK_BROKEN_CARD_DETECTION;
dev_dbg(dev, "is_8bit=%c\n",
@@ -282,7 +282,7 @@ static int __init sdhci_bcm_kona_probe(struct platform_device *pdev)
}
/* if device is eMMC, emulate card insert right here */
- if (host->mmc->caps | MMC_CAP_NONREMOVABLE) {
+ if (host->mmc->caps & MMC_CAP_NONREMOVABLE) {
ret = sdhci_bcm_kona_sd_card_emulate(host, 1);
if (ret) {
dev_err(dev,
@@ -336,10 +336,10 @@ static struct platform_driver sdhci_bcm_kona_driver = {
.name = "sdhci-kona",
.owner = THIS_MODULE,
.pm = SDHCI_PLTFM_PMOPS,
- .of_match_table = of_match_ptr(sdhci_bcm_kona_of_match),
+ .of_match_table = sdhci_bcm_kona_of_match,
},
.probe = sdhci_bcm_kona_probe,
- .remove = __exit_p(sdhci_bcm_kona_remove),
+ .remove = sdhci_bcm_kona_remove,
};
module_platform_driver(sdhci_bcm_kona_driver);
diff --git a/drivers/mmc/host/sdhci-bcm2835.c b/drivers/mmc/host/sdhci-bcm2835.c
index 0584a1c788b..36fa2df0466 100644
--- a/drivers/mmc/host/sdhci-bcm2835.c
+++ b/drivers/mmc/host/sdhci-bcm2835.c
@@ -119,7 +119,7 @@ static u8 bcm2835_sdhci_readb(struct sdhci_host *host, int reg)
return byte;
}
-unsigned int bcm2835_sdhci_get_min_clock(struct sdhci_host *host)
+static unsigned int bcm2835_sdhci_get_min_clock(struct sdhci_host *host)
{
return MIN_FREQ;
}
diff --git a/drivers/mmc/host/sdhci-esdhc-imx.c b/drivers/mmc/host/sdhci-esdhc-imx.c
index 1dd5ba85875..abc8cf01e6e 100644
--- a/drivers/mmc/host/sdhci-esdhc-imx.c
+++ b/drivers/mmc/host/sdhci-esdhc-imx.c
@@ -616,7 +616,7 @@ static int sdhci_esdhc_imx_probe(struct platform_device *pdev)
/* card_detect */
switch (boarddata->cd_type) {
case ESDHC_CD_GPIO:
- err = mmc_gpio_request_cd(host->mmc, boarddata->cd_gpio);
+ err = mmc_gpio_request_cd(host->mmc, boarddata->cd_gpio, 0);
if (err) {
dev_err(mmc_dev(host->mmc),
"failed to request card-detect gpio!\n");
diff --git a/drivers/mmc/host/sdhci-of-esdhc.c b/drivers/mmc/host/sdhci-of-esdhc.c
index 15039e2d1c1..e328252ebf2 100644
--- a/drivers/mmc/host/sdhci-of-esdhc.c
+++ b/drivers/mmc/host/sdhci-of-esdhc.c
@@ -316,6 +316,7 @@ static int sdhci_esdhc_probe(struct platform_device *pdev)
/* call to generic mmc_of_parse to support additional capabilities */
mmc_of_parse(host->mmc);
+ mmc_of_parse_voltage(np, &host->ocr_mask);
ret = sdhci_add_host(host);
if (ret)
diff --git a/drivers/mmc/host/sdhci-pxav3.c b/drivers/mmc/host/sdhci-pxav3.c
index bf99359a3a9..793dacd3b84 100644
--- a/drivers/mmc/host/sdhci-pxav3.c
+++ b/drivers/mmc/host/sdhci-pxav3.c
@@ -278,7 +278,8 @@ static int sdhci_pxav3_probe(struct platform_device *pdev)
host->mmc->pm_caps |= pdata->pm_caps;
if (gpio_is_valid(pdata->ext_cd_gpio)) {
- ret = mmc_gpio_request_cd(host->mmc, pdata->ext_cd_gpio);
+ ret = mmc_gpio_request_cd(host->mmc, pdata->ext_cd_gpio,
+ 0);
if (ret) {
dev_err(mmc_dev(host->mmc),
"failed to allocate card detect gpio\n");
diff --git a/drivers/mmc/host/sdhci-s3c.c b/drivers/mmc/host/sdhci-s3c.c
index 926aaf6acc6..6debda95215 100644
--- a/drivers/mmc/host/sdhci-s3c.c
+++ b/drivers/mmc/host/sdhci-s3c.c
@@ -296,9 +296,12 @@ static void sdhci_cmu_set_clock(struct sdhci_host *host, unsigned int clock)
unsigned long timeout;
u16 clk = 0;
- /* don't bother if the clock is going off */
- if (clock == 0)
+ /* If the clock is going off, set to 0 at clock control register */
+ if (clock == 0) {
+ sdhci_writew(host, 0, SDHCI_CLOCK_CONTROL);
+ host->clock = clock;
return;
+ }
sdhci_s3c_set_clock(host, clock);
@@ -608,6 +611,7 @@ static int sdhci_s3c_probe(struct platform_device *pdev)
host->hw_name = "samsung-hsmmc";
host->ops = &sdhci_s3c_ops;
host->quirks = 0;
+ host->quirks2 = 0;
host->irq = irq;
/* Setup quirks for the controller */
diff --git a/drivers/mmc/host/sdhci-sirf.c b/drivers/mmc/host/sdhci-sirf.c
index 62a4a835acc..696122c1b46 100644
--- a/drivers/mmc/host/sdhci-sirf.c
+++ b/drivers/mmc/host/sdhci-sirf.c
@@ -84,7 +84,7 @@ static int sdhci_sirf_probe(struct platform_device *pdev)
* gets setup in sdhci_add_host() and we oops.
*/
if (gpio_is_valid(priv->gpio_cd)) {
- ret = mmc_gpio_request_cd(host->mmc, priv->gpio_cd);
+ ret = mmc_gpio_request_cd(host->mmc, priv->gpio_cd, 0);
if (ret) {
dev_err(&pdev->dev, "card detect irq request failed: %d\n",
ret);
diff --git a/drivers/mmc/host/sdhci.c b/drivers/mmc/host/sdhci.c
index a78bd4f3aec..7a7fb4f0d5a 100644
--- a/drivers/mmc/host/sdhci.c
+++ b/drivers/mmc/host/sdhci.c
@@ -2966,7 +2966,7 @@ int sdhci_add_host(struct sdhci_host *host)
mmc->caps |= MMC_CAP_NEEDS_POLL;
/* If vqmmc regulator and no 1.8V signalling, then there's no UHS */
- host->vqmmc = regulator_get(mmc_dev(mmc), "vqmmc");
+ host->vqmmc = regulator_get_optional(mmc_dev(mmc), "vqmmc");
if (IS_ERR_OR_NULL(host->vqmmc)) {
if (PTR_ERR(host->vqmmc) < 0) {
pr_info("%s: no vqmmc regulator found\n",
@@ -3042,7 +3042,7 @@ int sdhci_add_host(struct sdhci_host *host)
ocr_avail = 0;
- host->vmmc = regulator_get(mmc_dev(mmc), "vmmc");
+ host->vmmc = regulator_get_optional(mmc_dev(mmc), "vmmc");
if (IS_ERR_OR_NULL(host->vmmc)) {
if (PTR_ERR(host->vmmc) < 0) {
pr_info("%s: no vmmc regulator found\n",
@@ -3119,6 +3119,9 @@ int sdhci_add_host(struct sdhci_host *host)
SDHCI_MAX_CURRENT_MULTIPLIER;
}
+ if (host->ocr_mask)
+ ocr_avail = host->ocr_mask;
+
mmc->ocr_avail = ocr_avail;
mmc->ocr_avail_sdio = ocr_avail;
if (host->ocr_avail_sdio)
@@ -3213,6 +3216,8 @@ int sdhci_add_host(struct sdhci_host *host)
host->tuning_timer.function = sdhci_tuning_timer;
}
+ sdhci_init(host, 0);
+
ret = request_irq(host->irq, sdhci_irq, IRQF_SHARED,
mmc_hostname(mmc), host);
if (ret) {
@@ -3221,8 +3226,6 @@ int sdhci_add_host(struct sdhci_host *host)
goto untasklet;
}
- sdhci_init(host, 0);
-
#ifdef CONFIG_MMC_DEBUG
sdhci_dumpregs(host);
#endif
diff --git a/drivers/mmc/host/sh_mmcif.c b/drivers/mmc/host/sh_mmcif.c
index 6706b5e3b97..36629a024aa 100644
--- a/drivers/mmc/host/sh_mmcif.c
+++ b/drivers/mmc/host/sh_mmcif.c
@@ -61,6 +61,7 @@
#include <linux/platform_device.h>
#include <linux/pm_qos.h>
#include <linux/pm_runtime.h>
+#include <linux/sh_dma.h>
#include <linux/spinlock.h>
#include <linux/module.h>
@@ -133,6 +134,8 @@
INT_BUFWEN | INT_CMD12DRE | INT_BUFRE | \
INT_DTRANE | INT_CMD12RBE | INT_CMD12CRE)
+#define INT_CCS (INT_CCSTO | INT_CCSRCV | INT_CCSDE)
+
/* CE_INT_MASK */
#define MASK_ALL 0x00000000
#define MASK_MCCSDE (1 << 29)
@@ -161,7 +164,7 @@
#define MASK_START_CMD (MASK_MCMDVIO | MASK_MBUFVIO | MASK_MWDATERR | \
MASK_MRDATERR | MASK_MRIDXERR | MASK_MRSPERR | \
- MASK_MCCSTO | MASK_MCRCSTO | MASK_MWDATTO | \
+ MASK_MCRCSTO | MASK_MWDATTO | \
MASK_MRDATTO | MASK_MRBSYTO | MASK_MRSPTO)
#define MASK_CLEAN (INT_ERR_STS | MASK_MRBSYE | MASK_MCRSPE | \
@@ -243,6 +246,8 @@ struct sh_mmcif_host {
int sg_blkidx;
bool power;
bool card_present;
+ bool ccs_enable; /* Command Completion Signal support */
+ bool clk_ctrl2_enable;
struct mutex thread_lock;
/* DMA support */
@@ -386,25 +391,29 @@ static void sh_mmcif_request_dma(struct sh_mmcif_host *host,
host->dma_active = false;
- if (!pdata)
- return;
-
- if (pdata->slave_id_tx <= 0 || pdata->slave_id_rx <= 0)
+ if (pdata) {
+ if (pdata->slave_id_tx <= 0 || pdata->slave_id_rx <= 0)
+ return;
+ } else if (!host->pd->dev.of_node) {
return;
+ }
/* We can only either use DMA for both Tx and Rx or not use it at all */
dma_cap_zero(mask);
dma_cap_set(DMA_SLAVE, mask);
- host->chan_tx = dma_request_channel(mask, shdma_chan_filter,
- (void *)pdata->slave_id_tx);
+ host->chan_tx = dma_request_slave_channel_compat(mask, shdma_chan_filter,
+ pdata ? (void *)pdata->slave_id_tx : NULL,
+ &host->pd->dev, "tx");
dev_dbg(&host->pd->dev, "%s: TX: got channel %p\n", __func__,
host->chan_tx);
if (!host->chan_tx)
return;
- cfg.slave_id = pdata->slave_id_tx;
+ /* In the OF case the driver will get the slave ID from the DT */
+ if (pdata)
+ cfg.slave_id = pdata->slave_id_tx;
cfg.direction = DMA_MEM_TO_DEV;
cfg.dst_addr = res->start + MMCIF_CE_DATA;
cfg.src_addr = 0;
@@ -412,15 +421,17 @@ static void sh_mmcif_request_dma(struct sh_mmcif_host *host,
if (ret < 0)
goto ecfgtx;
- host->chan_rx = dma_request_channel(mask, shdma_chan_filter,
- (void *)pdata->slave_id_rx);
+ host->chan_rx = dma_request_slave_channel_compat(mask, shdma_chan_filter,
+ pdata ? (void *)pdata->slave_id_rx : NULL,
+ &host->pd->dev, "rx");
dev_dbg(&host->pd->dev, "%s: RX: got channel %p\n", __func__,
host->chan_rx);
if (!host->chan_rx)
goto erqrx;
- cfg.slave_id = pdata->slave_id_rx;
+ if (pdata)
+ cfg.slave_id = pdata->slave_id_rx;
cfg.direction = DMA_DEV_TO_MEM;
cfg.dst_addr = 0;
cfg.src_addr = res->start + MMCIF_CE_DATA;
@@ -485,8 +496,12 @@ static void sh_mmcif_sync_reset(struct sh_mmcif_host *host)
sh_mmcif_writel(host->addr, MMCIF_CE_VERSION, SOFT_RST_ON);
sh_mmcif_writel(host->addr, MMCIF_CE_VERSION, SOFT_RST_OFF);
+ if (host->ccs_enable)
+ tmp |= SCCSTO_29;
+ if (host->clk_ctrl2_enable)
+ sh_mmcif_writel(host->addr, MMCIF_CE_CLK_CTRL2, 0x0F0F0000);
sh_mmcif_bitset(host, MMCIF_CE_CLK_CTRL, tmp |
- SRSPTO_256 | SRBSYTO_29 | SRWDTO_29 | SCCSTO_29);
+ SRSPTO_256 | SRBSYTO_29 | SRWDTO_29);
/* byte swap on */
sh_mmcif_bitset(host, MMCIF_CE_BUF_ACC, BUF_ACC_ATYP);
}
@@ -866,6 +881,9 @@ static void sh_mmcif_start_cmd(struct sh_mmcif_host *host,
break;
}
+ if (host->ccs_enable)
+ mask |= MASK_MCCSTO;
+
if (mrq->data) {
sh_mmcif_writel(host->addr, MMCIF_CE_BLOCK_SET, 0);
sh_mmcif_writel(host->addr, MMCIF_CE_BLOCK_SET,
@@ -873,7 +891,10 @@ static void sh_mmcif_start_cmd(struct sh_mmcif_host *host,
}
opc = sh_mmcif_set_cmd(host, mrq);
- sh_mmcif_writel(host->addr, MMCIF_CE_INT, 0xD80430C0);
+ if (host->ccs_enable)
+ sh_mmcif_writel(host->addr, MMCIF_CE_INT, 0xD80430C0);
+ else
+ sh_mmcif_writel(host->addr, MMCIF_CE_INT, 0xD80430C0 | INT_CCS);
sh_mmcif_writel(host->addr, MMCIF_CE_INT_MASK, mask);
/* set arg */
sh_mmcif_writel(host->addr, MMCIF_CE_ARG, cmd->arg);
@@ -956,11 +977,8 @@ static int sh_mmcif_clk_update(struct sh_mmcif_host *host)
static void sh_mmcif_set_power(struct sh_mmcif_host *host, struct mmc_ios *ios)
{
- struct sh_mmcif_plat_data *pd = host->pd->dev.platform_data;
struct mmc_host *mmc = host->mmc;
- if (pd && pd->set_pwr)
- pd->set_pwr(host->pd, ios->power_mode != MMC_POWER_OFF);
if (!IS_ERR(mmc->supply.vmmc))
/* Errors ignored... */
mmc_regulator_set_ocr(mmc, mmc->supply.vmmc,
@@ -1241,11 +1259,14 @@ static irqreturn_t sh_mmcif_irqt(int irq, void *dev_id)
static irqreturn_t sh_mmcif_intr(int irq, void *dev_id)
{
struct sh_mmcif_host *host = dev_id;
- u32 state;
+ u32 state, mask;
state = sh_mmcif_readl(host->addr, MMCIF_CE_INT);
- sh_mmcif_writel(host->addr, MMCIF_CE_INT,
- ~(state & sh_mmcif_readl(host->addr, MMCIF_CE_INT_MASK)));
+ mask = sh_mmcif_readl(host->addr, MMCIF_CE_INT_MASK);
+ if (host->ccs_enable)
+ sh_mmcif_writel(host->addr, MMCIF_CE_INT, ~(state & mask));
+ else
+ sh_mmcif_writel(host->addr, MMCIF_CE_INT, INT_CCS | ~(state & mask));
sh_mmcif_bitclr(host, MMCIF_CE_INT_MASK, state & MASK_CLEAN);
if (state & ~MASK_CLEAN)
@@ -1379,6 +1400,8 @@ static int sh_mmcif_probe(struct platform_device *pdev)
host->mmc = mmc;
host->addr = reg;
host->timeout = msecs_to_jiffies(1000);
+ host->ccs_enable = !pd || !pd->ccs_unsupported;
+ host->clk_ctrl2_enable = pd && pd->clk_ctrl2_present;
host->pd = pdev;
@@ -1436,7 +1459,7 @@ static int sh_mmcif_probe(struct platform_device *pdev)
}
if (pd && pd->use_cd_gpio) {
- ret = mmc_gpio_request_cd(mmc, pd->cd_gpio);
+ ret = mmc_gpio_request_cd(mmc, pd->cd_gpio, 0);
if (ret < 0)
goto erqcd;
}
diff --git a/drivers/mmc/host/sh_mobile_sdhi.c b/drivers/mmc/host/sh_mobile_sdhi.c
index ebea749297c..87ed3fb5149 100644
--- a/drivers/mmc/host/sh_mobile_sdhi.c
+++ b/drivers/mmc/host/sh_mobile_sdhi.c
@@ -70,20 +70,6 @@ static void sh_mobile_sdhi_clk_disable(struct platform_device *pdev)
clk_disable(priv->clk);
}
-static void sh_mobile_sdhi_set_pwr(struct platform_device *pdev, int state)
-{
- struct sh_mobile_sdhi_info *p = pdev->dev.platform_data;
-
- p->set_pwr(pdev, state);
-}
-
-static int sh_mobile_sdhi_get_cd(struct platform_device *pdev)
-{
- struct sh_mobile_sdhi_info *p = pdev->dev.platform_data;
-
- return p->get_cd(pdev);
-}
-
static int sh_mobile_sdhi_wait_idle(struct tmio_mmc_host *host)
{
int timeout = 1000;
@@ -129,7 +115,12 @@ static const struct sh_mobile_sdhi_ops sdhi_ops = {
static const struct of_device_id sh_mobile_sdhi_of_match[] = {
{ .compatible = "renesas,shmobile-sdhi" },
{ .compatible = "renesas,sh7372-sdhi" },
+ { .compatible = "renesas,sh73a0-sdhi", .data = &sh_mobile_sdhi_of_cfg[0], },
+ { .compatible = "renesas,r8a73a4-sdhi", .data = &sh_mobile_sdhi_of_cfg[0], },
{ .compatible = "renesas,r8a7740-sdhi", .data = &sh_mobile_sdhi_of_cfg[0], },
+ { .compatible = "renesas,r8a7778-sdhi", .data = &sh_mobile_sdhi_of_cfg[0], },
+ { .compatible = "renesas,r8a7779-sdhi", .data = &sh_mobile_sdhi_of_cfg[0], },
+ { .compatible = "renesas,r8a7790-sdhi", .data = &sh_mobile_sdhi_of_cfg[0], },
{},
};
MODULE_DEVICE_TABLE(of, sh_mobile_sdhi_of_match);
@@ -180,10 +171,6 @@ static int sh_mobile_sdhi_probe(struct platform_device *pdev)
mmc_data->capabilities |= p->tmio_caps;
mmc_data->capabilities2 |= p->tmio_caps2;
mmc_data->cd_gpio = p->cd_gpio;
- if (p->set_pwr)
- mmc_data->set_pwr = sh_mobile_sdhi_set_pwr;
- if (p->get_cd)
- mmc_data->get_cd = sh_mobile_sdhi_get_cd;
if (p->dma_slave_tx > 0 && p->dma_slave_rx > 0) {
/*
diff --git a/drivers/mmc/host/tmio_mmc_dma.c b/drivers/mmc/host/tmio_mmc_dma.c
index 47bdb8fa341..65edb4a6245 100644
--- a/drivers/mmc/host/tmio_mmc_dma.c
+++ b/drivers/mmc/host/tmio_mmc_dma.c
@@ -104,6 +104,7 @@ static void tmio_mmc_start_dma_rx(struct tmio_mmc_host *host)
pio:
if (!desc) {
/* DMA failed, fall back to PIO */
+ tmio_mmc_enable_dma(host, false);
if (ret >= 0)
ret = -EIO;
host->chan_rx = NULL;
@@ -116,7 +117,6 @@ pio:
}
dev_warn(&host->pdev->dev,
"DMA failed: %d, falling back to PIO\n", ret);
- tmio_mmc_enable_dma(host, false);
}
dev_dbg(&host->pdev->dev, "%s(): desc %p, cookie %d, sg[%d]\n", __func__,
@@ -185,6 +185,7 @@ static void tmio_mmc_start_dma_tx(struct tmio_mmc_host *host)
pio:
if (!desc) {
/* DMA failed, fall back to PIO */
+ tmio_mmc_enable_dma(host, false);
if (ret >= 0)
ret = -EIO;
host->chan_tx = NULL;
@@ -197,7 +198,6 @@ pio:
}
dev_warn(&host->pdev->dev,
"DMA failed: %d, falling back to PIO\n", ret);
- tmio_mmc_enable_dma(host, false);
}
dev_dbg(&host->pdev->dev, "%s(): desc %p, cookie %d\n", __func__,
diff --git a/drivers/mmc/host/tmio_mmc_pio.c b/drivers/mmc/host/tmio_mmc_pio.c
index b72edb72f7d..b3802256f95 100644
--- a/drivers/mmc/host/tmio_mmc_pio.c
+++ b/drivers/mmc/host/tmio_mmc_pio.c
@@ -795,9 +795,13 @@ static void tmio_mmc_power_on(struct tmio_mmc_host *host, unsigned short vdd)
* omap_hsmmc.c driver does.
*/
if (!IS_ERR(mmc->supply.vqmmc) && !ret) {
- regulator_enable(mmc->supply.vqmmc);
+ ret = regulator_enable(mmc->supply.vqmmc);
udelay(200);
}
+
+ if (ret < 0)
+ dev_dbg(&host->pdev->dev, "Regulators failed to power up: %d\n",
+ ret);
}
static void tmio_mmc_power_off(struct tmio_mmc_host *host)
@@ -932,25 +936,11 @@ static int tmio_mmc_get_ro(struct mmc_host *mmc)
(sd_ctrl_read32(host, CTL_STATUS) & TMIO_STAT_WRPROTECT));
}
-static int tmio_mmc_get_cd(struct mmc_host *mmc)
-{
- struct tmio_mmc_host *host = mmc_priv(mmc);
- struct tmio_mmc_data *pdata = host->pdata;
- int ret = mmc_gpio_get_cd(mmc);
- if (ret >= 0)
- return ret;
-
- if (!pdata->get_cd)
- return -ENOSYS;
- else
- return pdata->get_cd(host->pdev);
-}
-
static const struct mmc_host_ops tmio_mmc_ops = {
.request = tmio_mmc_request,
.set_ios = tmio_mmc_set_ios,
.get_ro = tmio_mmc_get_ro,
- .get_cd = tmio_mmc_get_cd,
+ .get_cd = mmc_gpio_get_cd,
.enable_sdio_irq = tmio_mmc_enable_sdio_irq,
};
@@ -1106,7 +1096,7 @@ int tmio_mmc_host_probe(struct tmio_mmc_host **host,
dev_pm_qos_expose_latency_limit(&pdev->dev, 100);
if (pdata->flags & TMIO_MMC_USE_GPIO_CD) {
- ret = mmc_gpio_request_cd(mmc, pdata->cd_gpio);
+ ret = mmc_gpio_request_cd(mmc, pdata->cd_gpio, 0);
if (ret < 0) {
tmio_mmc_host_remove(_host);
return ret;
diff --git a/drivers/mmc/host/vub300.c b/drivers/mmc/host/vub300.c
index cb9f361c03a..e9028ad05ff 100644
--- a/drivers/mmc/host/vub300.c
+++ b/drivers/mmc/host/vub300.c
@@ -2079,7 +2079,7 @@ static void vub300_enable_sdio_irq(struct mmc_host *mmc, int enable)
kref_put(&vub300->kref, vub300_delete);
}
-void vub300_init_card(struct mmc_host *mmc, struct mmc_card *card)
+static void vub300_init_card(struct mmc_host *mmc, struct mmc_card *card)
{ /* NOT irq */
struct vub300_mmc_host *vub300 = mmc_priv(mmc);
dev_info(&vub300->udev->dev, "NO host QUIRKS for this card\n");