summaryrefslogtreecommitdiff
path: root/drivers/mmc
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/mmc')
-rw-r--r--drivers/mmc/Kconfig107
-rw-r--r--drivers/mmc/Makefile27
-rw-r--r--drivers/mmc/arm_pl180_mmci.c4
-rw-r--r--drivers/mmc/bfin_sdh.c4
-rw-r--r--drivers/mmc/davinci_mmc.c4
-rw-r--r--drivers/mmc/dw_mmc.c5
-rw-r--r--drivers/mmc/fsl_esdhc.c3
-rw-r--r--drivers/mmc/ftsdc010_mci.c4
-rw-r--r--drivers/mmc/gen_atmel_mci.c4
-rw-r--r--drivers/mmc/mmc_spi.c3
-rw-r--r--drivers/mmc/mvebu_mmc.c4
-rw-r--r--drivers/mmc/mxcmmc.c4
-rw-r--r--drivers/mmc/mxsmmc.c4
-rw-r--r--drivers/mmc/omap_hsmmc.c6
-rw-r--r--drivers/mmc/pic32_sdhci.c17
-rw-r--r--drivers/mmc/pxa_mmc_gen.c8
-rw-r--r--drivers/mmc/rockchip_sdhci.c19
-rw-r--r--drivers/mmc/s3c_sdi.c6
-rw-r--r--drivers/mmc/s5p_sdhci.c15
-rw-r--r--drivers/mmc/sdhci-cadence.c125
-rw-r--r--drivers/mmc/sdhci.c59
-rw-r--r--drivers/mmc/sh_mmcif.c4
-rw-r--r--drivers/mmc/sh_sdhi.c6
-rw-r--r--drivers/mmc/sunxi_mmc.c6
-rw-r--r--drivers/mmc/tegra_mmc.c4
25 files changed, 363 insertions, 89 deletions
diff --git a/drivers/mmc/Kconfig b/drivers/mmc/Kconfig
index c3462ab..9ed8da3 100644
--- a/drivers/mmc/Kconfig
+++ b/drivers/mmc/Kconfig
@@ -68,15 +68,86 @@ config ATMEL_SDHCI
It is compliant with the SD Host Controller Standard V3.0
specification.
-config ROCKCHIP_DWMMC
+config MMC_DAVINCI
+ bool "TI DAVINCI Multimedia Card Interface support"
+ depends on ARCH_DAVINCI
+ default y
+ help
+ This selects the TI DAVINCI Multimedia card Interface.
+ If you have an DAVINCI board with a Multimedia Card slot,
+ say Y here. If unsure, say N.
+
+config MMC_DW
+ bool "Synopsys DesignWare Memory Card Interface"
+ help
+ This selects support for the Synopsys DesignWare Mobile Storage IP
+ block, this provides host support for SD and MMC interfaces, in both
+ PIO, internal DMA mode and external DMA mode.
+
+config MMC_DW_EXYNOS
+ bool "Exynos specific extensions for Synopsys DW Memory Card Interface"
+ depends on ARCH_EXYNOS
+ depends on MMC_DW
+ default y
+ help
+ This selects support for Samsung Exynos SoC specific extensions to the
+ Synopsys DesignWare Memory Card Interface driver. Select this option
+ for platforms based on Exynos4 and Exynos5 SoC's.
+
+config MMC_DW_K3
+ bool "K3 specific extensions for Synopsys DW Memory Card Interface"
+ depends on MMC_DW
+ help
+ This selects support for Hisilicon K3 SoC specific extensions to the
+ Synopsys DesignWare Memory Card Interface driver. Select this option
+ for platforms based on Hisilicon K3 SoC's.
+
+config MMC_DW_ROCKCHIP
bool "Rockchip SD/MMC controller support"
depends on DM_MMC && OF_CONTROL
+ depends on MMC_DW
help
This enables support for the Rockchip SD/MMM controller, which is
based on Designware IP. The device is compatible with at least
SD 3.0, SDIO 3.0 and MMC 4.5 and supports common eMMC chips as well
as removeable SD and micro-SD cards.
+config MMC_DW_SOCFPGA
+ bool "SOCFPGA specific extensions for Synopsys DW Memory Card Interface"
+ depends on ARCH_SOCFPGA
+ depends on MMC_DW
+ default y
+ help
+ This selects support for Altera SOCFPGA specific extensions to the
+ Synopsys DesignWare Memory Card Interface driver. Select this option
+ for platforms based on Altera SOCFPGA.
+
+config MMC_MXC
+ bool "Freescale i.MX21/27/31 or MPC512x Multimedia Card support"
+ help
+ This selects the Freescale i.MX21, i.MX27, i.MX31 or MPC512x
+ Multimedia Card Interface. If you have an i.MX or MPC512x platform
+ with a Multimedia Card slot, say Y here.
+
+ If unsure, say N.
+
+config MMC_MXS
+ bool "Freescale MXS Multimedia Card Interface support"
+ help
+ This selects the Freescale SSP MMC controller found on MXS based
+ platforms like mx23/28.
+
+ If unsure, say N.
+
+config MMC_OMAP_HS
+ bool "TI OMAP High Speed Multimedia Card Interface support"
+ help
+ This selects the TI OMAP High Speed Multimedia card Interface.
+ If you have an omap2plus board with a Multimedia Card slot,
+ say Y here.
+
+ If unsure, say N.
+
config SH_SDHI
bool "SuperH/Renesas ARM SoCs on-chip SDHI host controller support"
depends on RMOBILE
@@ -107,8 +178,8 @@ config ROCKCHIP_SDHCI
config MMC_UNIPHIER
bool "UniPhier SD/MMC Host Controller support"
depends on ARCH_UNIPHIER
- depends on BLK
- select DM_MMC_OPS
+ depends on BLK && DM_MMC_OPS
+ depends on OF_CONTROL
help
This selects support for the SD/MMC Host Controller on UniPhier SoCs.
@@ -159,6 +230,18 @@ config MMC_SDHCI_BCM2835
If unsure, say N.
+config MMC_SDHCI_CADENCE
+ bool "SDHCI support for the Cadence SD/SDIO/eMMC controller"
+ depends on BLK && DM_MMC_OPS
+ depends on MMC_SDHCI
+ depends on OF_CONTROL
+ help
+ This selects the Cadence SD/SDIO/eMMC driver.
+
+ If you have a controller with this interface, say Y here.
+
+ If unsure, say N.
+
config MMC_SDHCI_KONA
bool "SDHCI support on Broadcom KONA platform"
depends on MMC_SDHCI
@@ -204,6 +287,24 @@ config MMC_SDHCI_SPEAR
If unsure, say N.
+config MMC_SDHCI_TEGRA
+ bool "SDHCI platform support for the Tegra SD/MMC Controller"
+ depends on TEGRA
+ default y
+ help
+ This selects the Tegra SD/MMC controller. If you have a Tegra
+ platform with SD or MMC devices, say Y here.
+
+ If unsure, say N.
+
+config MMC_SUNXI
+ bool "Allwinner sunxi SD/MMC Host Controller support"
+ depends on ARCH_SUNXI && !UART0_PORT_F
+ default y
+ help
+ This selects support for the SD/MMC Host Controller on
+ Allwinner sunxi SoCs.
+
endif
endmenu
diff --git a/drivers/mmc/Makefile b/drivers/mmc/Makefile
index 2b136ea..4dca09c 100644
--- a/drivers/mmc/Makefile
+++ b/drivers/mmc/Makefile
@@ -16,10 +16,13 @@ endif
obj-$(CONFIG_ARM_PL180_MMCI) += arm_pl180_mmci.o
obj-$(CONFIG_ATMEL_SDHCI) += atmel_sdhci.o
obj-$(CONFIG_BFIN_SDH) += bfin_sdh.o
-obj-$(CONFIG_DAVINCI_MMC) += davinci_mmc.o
-obj-$(CONFIG_DWMMC) += dw_mmc.o
-obj-$(CONFIG_EXYNOS_DWMMC) += exynos_dw_mmc.o
-obj-$(CONFIG_HIKEY_DWMMC) += hi6220_dw_mmc.o
+obj-$(CONFIG_MMC_DAVINCI) += davinci_mmc.o
+
+obj-$(CONFIG_MMC_DW) += dw_mmc.o
+obj-$(CONFIG_MMC_DW_EXYNOS) += exynos_dw_mmc.o
+obj-$(CONFIG_MMC_DW_K3) += hi6220_dw_mmc.o
+obj-$(CONFIG_MMC_DW_ROCKCHIP) += rockchip_dw_mmc.o
+obj-$(CONFIG_MMC_DW_SOCFPGA) += socfpga_dw_mmc.o
obj-$(CONFIG_FSL_ESDHC) += fsl_esdhc.o
obj-$(CONFIG_FTSDC010) += ftsdc010_mci.o
obj-$(CONFIG_FTSDC021) += ftsdc021_sdhci.o
@@ -29,14 +32,12 @@ obj-$(CONFIG_GENERIC_MMC) += mmc_boot.o
endif
obj-$(CONFIG_GENERIC_ATMEL_MCI) += gen_atmel_mci.o
obj-$(CONFIG_MMC_SPI) += mmc_spi.o
-obj-$(CONFIG_MMC_SUNXI) += sunxi_mmc.o
obj-$(CONFIG_MVEBU_MMC) += mvebu_mmc.o
-obj-$(CONFIG_MXC_MMC) += mxcmmc.o
-obj-$(CONFIG_MXS_MMC) += mxsmmc.o
-obj-$(CONFIG_OMAP_HSMMC) += omap_hsmmc.o
+obj-$(CONFIG_MMC_OMAP_HS) += omap_hsmmc.o
+obj-$(CONFIG_MMC_MXC) += mxcmmc.o
+obj-$(CONFIG_MMC_MXS) += mxsmmc.o
obj-$(CONFIG_X86) += pci_mmc.o
obj-$(CONFIG_PXA_MMC_GENERIC) += pxa_mmc_gen.o
-obj-$(CONFIG_ROCKCHIP_DWMMC) += rockchip_dw_mmc.o
obj-$(CONFIG_SUPPORT_EMMC_RPMB) += rpmb.o
obj-$(CONFIG_S3C_SDI) += s3c_sdi.o
ifdef CONFIG_BLK
@@ -46,9 +47,6 @@ endif
endif
obj-$(CONFIG_SH_MMCIF) += sh_mmcif.o
obj-$(CONFIG_SH_SDHI) += sh_sdhi.o
-obj-$(CONFIG_SOCFPGA_DWMMC) += socfpga_dw_mmc.o
-obj-$(CONFIG_TEGRA_MMC) += tegra_mmc.o
-obj-$(CONFIG_MMC_UNIPHIER) += uniphier-sd.o
obj-$(CONFIG_ZYNQ_SDHCI) += zynq_sdhci.o
obj-$(CONFIG_ROCKCHIP_SDHCI) += rockchip_sdhci.o
@@ -64,7 +62,12 @@ obj-$(CONFIG_MSM_SDHCI) += msm_sdhci.o
# SDHCI
obj-$(CONFIG_MMC_SDHCI) += sdhci.o
obj-$(CONFIG_MMC_SDHCI_BCM2835) += bcm2835_sdhci.o
+obj-$(CONFIG_MMC_SDHCI_CADENCE) += sdhci-cadence.o
obj-$(CONFIG_MMC_SDHCI_KONA) += kona_sdhci.o
obj-$(CONFIG_MMC_SDHCI_MV) += mv_sdhci.o
obj-$(CONFIG_MMC_SDHCI_S5P) += s5p_sdhci.o
obj-$(CONFIG_MMC_SDHCI_SPEAR) += spear_sdhci.o
+obj-$(CONFIG_MMC_SDHCI_TEGRA) += tegra_mmc.o
+
+obj-$(CONFIG_MMC_SUNXI) += sunxi_mmc.o
+obj-$(CONFIG_MMC_UNIPHIER) += uniphier-sd.o
diff --git a/drivers/mmc/arm_pl180_mmci.c b/drivers/mmc/arm_pl180_mmci.c
index e64ac3c..ddf8383 100644
--- a/drivers/mmc/arm_pl180_mmci.c
+++ b/drivers/mmc/arm_pl180_mmci.c
@@ -275,7 +275,7 @@ static int mmc_host_reset(struct mmc *dev)
return 0;
}
-static void host_set_ios(struct mmc *dev)
+static int host_set_ios(struct mmc *dev)
{
struct pl180_mmc_host *host = dev->priv;
u32 sdi_clkcr;
@@ -333,6 +333,8 @@ static void host_set_ios(struct mmc *dev)
writel(sdi_clkcr, &host->base->clock);
udelay(CLK_CHANGE_DELAY);
+
+ return 0;
}
static const struct mmc_ops arm_pl180_mmci_ops = {
diff --git a/drivers/mmc/bfin_sdh.c b/drivers/mmc/bfin_sdh.c
index 993a00c..1627dca 100644
--- a/drivers/mmc/bfin_sdh.c
+++ b/drivers/mmc/bfin_sdh.c
@@ -234,7 +234,7 @@ static void sdh_set_clk(unsigned long clk)
bfin_write_SDH_CLK_CTL(clk_ctl & ~CLK_E);
}
-static void bfin_sdh_set_ios(struct mmc *mmc)
+static int bfin_sdh_set_ios(struct mmc *mmc)
{
u16 cfg = 0;
u16 clk_ctl = 0;
@@ -250,6 +250,8 @@ static void bfin_sdh_set_ios(struct mmc *mmc)
}
bfin_write_SDH_CLK_CTL(clk_ctl);
sdh_set_clk(mmc->clock);
+
+ return 0;
}
static int bfin_sdh_init(struct mmc *mmc)
diff --git a/drivers/mmc/davinci_mmc.c b/drivers/mmc/davinci_mmc.c
index b495c75..9edb668 100644
--- a/drivers/mmc/davinci_mmc.c
+++ b/drivers/mmc/davinci_mmc.c
@@ -348,7 +348,7 @@ static int dmmc_init(struct mmc *mmc)
}
/* Set buswidth or clock as indicated by the GENERIC_MMC framework */
-static void dmmc_set_ios(struct mmc *mmc)
+static int dmmc_set_ios(struct mmc *mmc)
{
struct davinci_mmc *host = mmc->priv;
struct davinci_mmc_regs *regs = host->reg_base;
@@ -362,6 +362,8 @@ static void dmmc_set_ios(struct mmc *mmc)
/* Set clock speed */
if (mmc->clock)
dmmc_set_clock(mmc, mmc->clock);
+
+ return 0;
}
static const struct mmc_ops dmmc_ops = {
diff --git a/drivers/mmc/dw_mmc.c b/drivers/mmc/dw_mmc.c
index d6ac46c..700f764 100644
--- a/drivers/mmc/dw_mmc.c
+++ b/drivers/mmc/dw_mmc.c
@@ -388,7 +388,7 @@ static int dwmci_set_ios(struct udevice *dev)
{
struct mmc *mmc = mmc_get_mmc_dev(dev);
#else
-static void dwmci_set_ios(struct mmc *mmc)
+static int dwmci_set_ios(struct mmc *mmc)
{
#endif
struct dwmci_host *host = (struct dwmci_host *)mmc->priv;
@@ -421,9 +421,8 @@ static void dwmci_set_ios(struct mmc *mmc)
if (host->clksel)
host->clksel(host);
-#ifdef CONFIG_DM_MMC_OPS
+
return 0;
-#endif
}
static int dwmci_init(struct mmc *mmc)
diff --git a/drivers/mmc/fsl_esdhc.c b/drivers/mmc/fsl_esdhc.c
index 9796d39..7defeb4 100644
--- a/drivers/mmc/fsl_esdhc.c
+++ b/drivers/mmc/fsl_esdhc.c
@@ -592,7 +592,7 @@ static void esdhc_clock_control(struct mmc *mmc, bool enable)
}
#endif
-static void esdhc_set_ios(struct mmc *mmc)
+static int esdhc_set_ios(struct mmc *mmc)
{
struct fsl_esdhc_priv *priv = mmc->priv;
struct fsl_esdhc *regs = priv->esdhc_regs;
@@ -614,6 +614,7 @@ static void esdhc_set_ios(struct mmc *mmc)
else if (mmc->bus_width == 8)
esdhc_setbits32(&regs->proctl, PROCTL_DTW_8);
+ return 0;
}
static int esdhc_init(struct mmc *mmc)
diff --git a/drivers/mmc/ftsdc010_mci.c b/drivers/mmc/ftsdc010_mci.c
index e88c632..652a718 100644
--- a/drivers/mmc/ftsdc010_mci.c
+++ b/drivers/mmc/ftsdc010_mci.c
@@ -251,7 +251,7 @@ static int ftsdc010_request(struct mmc *mmc, struct mmc_cmd *cmd,
return ret;
}
-static void ftsdc010_set_ios(struct mmc *mmc)
+static int ftsdc010_set_ios(struct mmc *mmc)
{
struct ftsdc010_chip *chip = mmc->priv;
struct ftsdc010_mmc __iomem *regs = chip->regs;
@@ -270,6 +270,8 @@ static void ftsdc010_set_ios(struct mmc *mmc)
setbits_le32(&regs->bwr, FTSDC010_BWR_MODE_1BIT);
break;
}
+
+ return 0;
}
static int ftsdc010_init(struct mmc *mmc)
diff --git a/drivers/mmc/gen_atmel_mci.c b/drivers/mmc/gen_atmel_mci.c
index cca0b04..7dc4a5d 100644
--- a/drivers/mmc/gen_atmel_mci.c
+++ b/drivers/mmc/gen_atmel_mci.c
@@ -336,7 +336,7 @@ mci_send_cmd(struct mmc *mmc, struct mmc_cmd *cmd, struct mmc_data *data)
}
/* Entered into mmc structure during driver init */
-static void mci_set_ios(struct mmc *mmc)
+static int mci_set_ios(struct mmc *mmc)
{
struct atmel_mci_priv *priv = mmc->priv;
atmel_mci_t *mci = priv->mci;
@@ -370,6 +370,8 @@ static void mci_set_ios(struct mmc *mmc)
writel(busw << 7 | MMCI_BF(SCDSEL, MCI_BUS), &mci->sdcr);
}
+
+ return 0;
}
/* Entered into mmc structure during driver init */
diff --git a/drivers/mmc/mmc_spi.c b/drivers/mmc/mmc_spi.c
index 2510117..a9d95fb 100644
--- a/drivers/mmc/mmc_spi.c
+++ b/drivers/mmc/mmc_spi.c
@@ -236,13 +236,14 @@ done:
return ret;
}
-static void mmc_spi_set_ios(struct mmc *mmc)
+static int mmc_spi_set_ios(struct mmc *mmc)
{
struct spi_slave *spi = mmc->priv;
debug("%s: clock %u\n", __func__, mmc->clock);
if (mmc->clock)
spi_set_speed(spi, mmc->clock);
+ return 0;
}
static int mmc_spi_init_p(struct mmc *mmc)
diff --git a/drivers/mmc/mvebu_mmc.c b/drivers/mmc/mvebu_mmc.c
index a2792ac..3c7fb21 100644
--- a/drivers/mmc/mvebu_mmc.c
+++ b/drivers/mmc/mvebu_mmc.c
@@ -316,12 +316,14 @@ static void mvebu_mmc_set_bus(unsigned int bus)
mvebu_mmc_write(SDIO_HOST_CTRL, ctrl_reg);
}
-static void mvebu_mmc_set_ios(struct mmc *mmc)
+static int mvebu_mmc_set_ios(struct mmc *mmc)
{
debug("%s: bus[%d] clock[%d]\n", DRIVER_NAME,
mmc->bus_width, mmc->clock);
mvebu_mmc_set_bus(mmc->bus_width);
mvebu_mmc_set_clk(mmc->clock);
+
+ return 0;
}
/*
diff --git a/drivers/mmc/mxcmmc.c b/drivers/mmc/mxcmmc.c
index 5a385a3..dcf17c5 100644
--- a/drivers/mmc/mxcmmc.c
+++ b/drivers/mmc/mxcmmc.c
@@ -448,7 +448,7 @@ static void mxcmci_set_clk_rate(struct mxcmci_host *host, unsigned int clk_ios)
writel((prescaler << 4) | divider, &host->base->clk_rate);
}
-static void mxcmci_set_ios(struct mmc *mmc)
+static int mxcmci_set_ios(struct mmc *mmc)
{
struct mxcmci_host *host = mmc->priv;
if (mmc->bus_width == 4)
@@ -464,6 +464,8 @@ static void mxcmci_set_ios(struct mmc *mmc)
}
host->clock = mmc->clock;
+
+ return 0;
}
static int mxcmci_init(struct mmc *mmc)
diff --git a/drivers/mmc/mxsmmc.c b/drivers/mmc/mxsmmc.c
index 0896028..fe1fe70 100644
--- a/drivers/mmc/mxsmmc.c
+++ b/drivers/mmc/mxsmmc.c
@@ -304,7 +304,7 @@ mxsmmc_send_cmd(struct mmc *mmc, struct mmc_cmd *cmd, struct mmc_data *data)
return 0;
}
-static void mxsmmc_set_ios(struct mmc *mmc)
+static int mxsmmc_set_ios(struct mmc *mmc)
{
struct mxsmmc_priv *priv = mmc->priv;
struct mxs_ssp_regs *ssp_regs = priv->regs;
@@ -331,6 +331,8 @@ static void mxsmmc_set_ios(struct mmc *mmc)
debug("MMC%d: Set %d bits bus width\n",
mmc->block_dev.devnum, mmc->bus_width);
+
+ return 0;
}
static int mxsmmc_init(struct mmc *mmc)
diff --git a/drivers/mmc/omap_hsmmc.c b/drivers/mmc/omap_hsmmc.c
index 0a1ee40..b326846 100644
--- a/drivers/mmc/omap_hsmmc.c
+++ b/drivers/mmc/omap_hsmmc.c
@@ -511,7 +511,7 @@ static int mmc_write_data(struct hsmmc *mmc_base, const char *buf,
return 0;
}
-static void omap_hsmmc_set_ios(struct mmc *mmc)
+static int omap_hsmmc_set_ios(struct mmc *mmc)
{
struct hsmmc *mmc_base;
unsigned int dsor = 0;
@@ -559,10 +559,12 @@ static void omap_hsmmc_set_ios(struct mmc *mmc)
while ((readl(&mmc_base->sysctl) & ICS_MASK) == ICS_NOTREADY) {
if (get_timer(0) - start > MAX_RETRY_MS) {
printf("%s: timedout waiting for ics!\n", __func__);
- return;
+ return -ETIMEDOUT;
}
}
writel(readl(&mmc_base->sysctl) | CEN_ENABLE, &mmc_base->sysctl);
+
+ return 0;
}
#ifdef OMAP_HSMMC_USE_GPIO
diff --git a/drivers/mmc/pic32_sdhci.c b/drivers/mmc/pic32_sdhci.c
index 2abf943..c06364c 100644
--- a/drivers/mmc/pic32_sdhci.c
+++ b/drivers/mmc/pic32_sdhci.c
@@ -15,6 +15,20 @@
DECLARE_GLOBAL_DATA_PTR;
+static int pic32_sdhci_get_cd(struct sdhci_host *host)
+{
+ /* PIC32 SDHCI CD errata:
+ * - set CD_TEST and clear CD_TEST_INS bit
+ */
+ sdhci_writeb(host, SDHCI_CTRL_CD_TEST, SDHCI_HOST_CONTROL);
+
+ return 0;
+}
+
+static const struct sdhci_ops pic32_sdhci_ops = {
+ .get_cd = pic32_sdhci_get_cd,
+};
+
static int pic32_sdhci_probe(struct udevice *dev)
{
struct sdhci_host *host = dev_get_priv(dev);
@@ -30,9 +44,10 @@ static int pic32_sdhci_probe(struct udevice *dev)
host->ioaddr = ioremap(addr, size);
host->name = dev->name;
- host->quirks = SDHCI_QUIRK_NO_HISPD_BIT | SDHCI_QUIRK_NO_CD;
+ host->quirks = SDHCI_QUIRK_NO_HISPD_BIT;
host->bus_width = fdtdec_get_int(gd->fdt_blob, dev->of_offset,
"bus-width", 4);
+ host->ops = &pic32_sdhci_ops;
ret = fdtdec_get_int_array(gd->fdt_blob, dev->of_offset,
"clock-freq-min-max", f_min_max, 2);
diff --git a/drivers/mmc/pxa_mmc_gen.c b/drivers/mmc/pxa_mmc_gen.c
index a5462e2..f627553 100644
--- a/drivers/mmc/pxa_mmc_gen.c
+++ b/drivers/mmc/pxa_mmc_gen.c
@@ -313,7 +313,7 @@ static int pxa_mmc_request(struct mmc *mmc, struct mmc_cmd *cmd,
return 0;
}
-static void pxa_mmc_set_ios(struct mmc *mmc)
+static int pxa_mmc_set_ios(struct mmc *mmc)
{
struct pxa_mmc_priv *priv = mmc->priv;
struct pxa_mmc_regs *regs = priv->regs;
@@ -322,13 +322,13 @@ static void pxa_mmc_set_ios(struct mmc *mmc)
if (!mmc->clock) {
pxa_mmc_stop_clock(mmc);
- return;
+ return 0;
}
/* PXA3xx can do 26MHz with special settings. */
if (mmc->clock == 26000000) {
writel(0x7, &regs->clkrt);
- return;
+ return 0;
}
/* Set clock to the card the usual way. */
@@ -342,6 +342,8 @@ static void pxa_mmc_set_ios(struct mmc *mmc)
}
writel(pxa_mmc_clock, &regs->clkrt);
+
+ return 0;
}
static int pxa_mmc_init(struct mmc *mmc)
diff --git a/drivers/mmc/rockchip_sdhci.c b/drivers/mmc/rockchip_sdhci.c
index c56e1a3..e33e35e 100644
--- a/drivers/mmc/rockchip_sdhci.c
+++ b/drivers/mmc/rockchip_sdhci.c
@@ -12,7 +12,9 @@
#include <libfdt.h>
#include <malloc.h>
#include <sdhci.h>
+#include <clk.h>
+DECLARE_GLOBAL_DATA_PTR;
/* 400KHz is max freq for card ID etc. Use that as min */
#define EMMC_MIN_FREQ 400000
@@ -32,11 +34,24 @@ static int arasan_sdhci_probe(struct udevice *dev)
struct rockchip_sdhc_plat *plat = dev_get_platdata(dev);
struct rockchip_sdhc *prv = dev_get_priv(dev);
struct sdhci_host *host = &prv->host;
- int ret;
+ int max_frequency, ret;
+ struct clk clk;
+
+
+ max_frequency = fdtdec_get_int(gd->fdt_blob, dev->of_offset,
+ "max-frequency", 0);
+ ret = clk_get_by_index(dev, 0, &clk);
+ if (!ret) {
+ ret = clk_set_rate(&clk, max_frequency);
+ if (IS_ERR_VALUE(ret))
+ printf("%s clk set rate fail!\n", __func__);
+ } else {
+ printf("%s fail to get clk\n", __func__);
+ }
host->quirks = SDHCI_QUIRK_WAIT_SEND_CMD;
- ret = sdhci_setup_cfg(&plat->cfg, host, CONFIG_ROCKCHIP_SDHCI_MAX_FREQ,
+ ret = sdhci_setup_cfg(&plat->cfg, host, max_frequency,
EMMC_MIN_FREQ);
host->mmc = &plat->mmc;
diff --git a/drivers/mmc/s3c_sdi.c b/drivers/mmc/s3c_sdi.c
index 1b8358a..faf7b83 100644
--- a/drivers/mmc/s3c_sdi.c
+++ b/drivers/mmc/s3c_sdi.c
@@ -207,7 +207,7 @@ error:
return ret;
}
-static void s3cmmc_set_ios(struct mmc *mmc)
+static int s3cmmc_set_ios(struct mmc *mmc)
{
struct s3c24x0_sdi *sdi_regs = s3c24x0_get_base_sdi();
uint32_t divider = 0;
@@ -215,7 +215,7 @@ static void s3cmmc_set_ios(struct mmc *mmc)
wide_bus = (mmc->bus_width == 4);
if (!mmc->clock)
- return;
+ return 0;
divider = DIV_ROUND_UP(get_PCLK(), mmc->clock);
if (divider)
@@ -223,6 +223,8 @@ static void s3cmmc_set_ios(struct mmc *mmc)
writel(divider, &sdi_regs->sdipre);
mdelay(125);
+
+ return 0;
}
static int s3cmmc_init(struct mmc *mmc)
diff --git a/drivers/mmc/s5p_sdhci.c b/drivers/mmc/s5p_sdhci.c
index ac737e0..1f1d2ed 100644
--- a/drivers/mmc/s5p_sdhci.c
+++ b/drivers/mmc/s5p_sdhci.c
@@ -73,6 +73,17 @@ static void s5p_sdhci_set_control_reg(struct sdhci_host *host)
sdhci_writel(host, ctrl, SDHCI_CONTROL2);
}
+static void s5p_set_clock(struct sdhci_host *host, u32 div)
+{
+ /* ToDo : Use the Clock Framework */
+ set_mmc_clk(host->index, div);
+}
+
+static const struct sdhci_ops s5p_sdhci_ops = {
+ .set_clock = &s5p_set_clock,
+ .set_control_reg = &s5p_sdhci_set_control_reg,
+};
+
static int s5p_sdhci_core_init(struct sdhci_host *host)
{
host->name = S5P_NAME;
@@ -81,9 +92,7 @@ static int s5p_sdhci_core_init(struct sdhci_host *host)
SDHCI_QUIRK_32BIT_DMA_ADDR |
SDHCI_QUIRK_WAIT_SEND_CMD | SDHCI_QUIRK_USE_WIDE8;
host->voltages = MMC_VDD_32_33 | MMC_VDD_33_34 | MMC_VDD_165_195;
-
- host->set_control_reg = &s5p_sdhci_set_control_reg;
- host->set_clock = set_mmc_clk;
+ host->ops = &s5p_sdhci_ops;
if (host->bus_width == 8)
host->host_caps |= MMC_MODE_8BIT;
diff --git a/drivers/mmc/sdhci-cadence.c b/drivers/mmc/sdhci-cadence.c
new file mode 100644
index 0000000..2253bbc
--- /dev/null
+++ b/drivers/mmc/sdhci-cadence.c
@@ -0,0 +1,125 @@
+/*
+ * Copyright (C) 2016 Socionext Inc.
+ * Author: Masahiro Yamada <yamada.masahiro@socionext.com>
+ *
+ * SPDX-License-Identifier: GPL-2.0+
+ */
+
+#include <common.h>
+#include <linux/io.h>
+#include <linux/sizes.h>
+#include <dm/device.h>
+#include <mmc.h>
+#include <sdhci.h>
+
+/* HRS - Host Register Set (specific to Cadence) */
+#define SDHCI_CDNS_HRS04 0x10 /* PHY access port */
+#define SDHCI_CDNS_HRS04_ACK BIT(26)
+#define SDHCI_CDNS_HRS04_RD BIT(25)
+#define SDHCI_CDNS_HRS04_WR BIT(24)
+#define SDHCI_CDNS_HRS04_RDATA_SHIFT 12
+#define SDHCI_CDNS_HRS04_WDATA_SHIFT 8
+#define SDHCI_CDNS_HRS04_ADDR_SHIFT 0
+
+/* SRS - Slot Register Set (SDHCI-compatible) */
+#define SDHCI_CDNS_SRS_BASE 0x200
+
+/* PHY */
+#define SDHCI_CDNS_PHY_DLY_SD_HS 0x00
+#define SDHCI_CDNS_PHY_DLY_SD_DEFAULT 0x01
+#define SDHCI_CDNS_PHY_DLY_UHS_SDR12 0x02
+#define SDHCI_CDNS_PHY_DLY_UHS_SDR25 0x03
+#define SDHCI_CDNS_PHY_DLY_UHS_SDR50 0x04
+#define SDHCI_CDNS_PHY_DLY_UHS_DDR50 0x05
+#define SDHCI_CDNS_PHY_DLY_EMMC_LEGACY 0x06
+#define SDHCI_CDNS_PHY_DLY_EMMC_SDR 0x07
+#define SDHCI_CDNS_PHY_DLY_EMMC_DDR 0x08
+
+struct sdhci_cdns_plat {
+ struct mmc_config cfg;
+ struct mmc mmc;
+ void __iomem *hrs_addr;
+};
+
+static void sdhci_cdns_write_phy_reg(struct sdhci_cdns_plat *plat,
+ u8 addr, u8 data)
+{
+ void __iomem *reg = plat->hrs_addr + SDHCI_CDNS_HRS04;
+ u32 tmp;
+
+ tmp = (data << SDHCI_CDNS_HRS04_WDATA_SHIFT) |
+ (addr << SDHCI_CDNS_HRS04_ADDR_SHIFT);
+ writel(tmp, reg);
+
+ tmp |= SDHCI_CDNS_HRS04_WR;
+ writel(tmp, reg);
+
+ tmp &= ~SDHCI_CDNS_HRS04_WR;
+ writel(tmp, reg);
+}
+
+static void sdhci_cdns_phy_init(struct sdhci_cdns_plat *plat)
+{
+ sdhci_cdns_write_phy_reg(plat, SDHCI_CDNS_PHY_DLY_SD_HS, 4);
+ sdhci_cdns_write_phy_reg(plat, SDHCI_CDNS_PHY_DLY_SD_DEFAULT, 4);
+ sdhci_cdns_write_phy_reg(plat, SDHCI_CDNS_PHY_DLY_EMMC_LEGACY, 9);
+ sdhci_cdns_write_phy_reg(plat, SDHCI_CDNS_PHY_DLY_EMMC_SDR, 2);
+ sdhci_cdns_write_phy_reg(plat, SDHCI_CDNS_PHY_DLY_EMMC_DDR, 3);
+}
+
+static int sdhci_cdns_bind(struct udevice *dev)
+{
+ struct sdhci_cdns_plat *plat = dev_get_platdata(dev);
+
+ return sdhci_bind(dev, &plat->mmc, &plat->cfg);
+}
+
+static int sdhci_cdns_probe(struct udevice *dev)
+{
+ struct mmc_uclass_priv *upriv = dev_get_uclass_priv(dev);
+ struct sdhci_cdns_plat *plat = dev_get_platdata(dev);
+ struct sdhci_host *host = dev_get_priv(dev);
+ fdt_addr_t base;
+ int ret;
+
+ base = dev_get_addr(dev);
+ if (base == FDT_ADDR_T_NONE)
+ return -EINVAL;
+
+ plat->hrs_addr = devm_ioremap(dev, base, SZ_1K);
+ if (!plat->hrs_addr)
+ return -ENOMEM;
+
+ host->name = dev->name;
+ host->ioaddr = plat->hrs_addr + SDHCI_CDNS_SRS_BASE;
+ host->quirks |= SDHCI_QUIRK_WAIT_SEND_CMD;
+
+ sdhci_cdns_phy_init(plat);
+
+ ret = sdhci_setup_cfg(&plat->cfg, host, 0, 0);
+ if (ret)
+ return ret;
+
+ upriv->mmc = &plat->mmc;
+ host->mmc = &plat->mmc;
+ host->mmc->priv = host;
+
+ return sdhci_probe(dev);
+}
+
+static const struct udevice_id sdhci_cdns_match[] = {
+ { .compatible = "socionext,uniphier-sd4hc" },
+ { .compatible = "cdns,sd4hc" },
+ { /* sentinel */ }
+};
+
+U_BOOT_DRIVER(sdhci_cdns) = {
+ .name = "sdhci-cdns",
+ .id = UCLASS_MMC,
+ .of_match = sdhci_cdns_match,
+ .bind = sdhci_cdns_bind,
+ .probe = sdhci_cdns_probe,
+ .priv_auto_alloc_size = sizeof(struct sdhci_host),
+ .platdata_auto_alloc_size = sizeof(struct sdhci_cdns_plat),
+ .ops = &sdhci_ops,
+};
diff --git a/drivers/mmc/sdhci.c b/drivers/mmc/sdhci.c
index cbf5f56..5b404ff 100644
--- a/drivers/mmc/sdhci.c
+++ b/drivers/mmc/sdhci.c
@@ -359,8 +359,8 @@ static int sdhci_set_clock(struct mmc *mmc, unsigned int clock)
div >>= 1;
}
- if (host->set_clock)
- host->set_clock(host->index, div);
+ if (host->ops && host->ops->set_clock)
+ host->ops->set_clock(host, div);
clk |= (div & SDHCI_DIV_MASK) << SDHCI_DIVIDER_SHIFT;
clk |= ((div & SDHCI_DIV_HI_MASK) >> SDHCI_DIV_MASK_LEN)
@@ -411,9 +411,6 @@ static void sdhci_set_power(struct sdhci_host *host, unsigned short power)
return;
}
- if (host->quirks & SDHCI_QUIRK_NO_SIMULT_VDD_AND_POWER)
- sdhci_writeb(host, pwr, SDHCI_POWER_CONTROL);
-
pwr |= SDHCI_POWER_ON;
sdhci_writeb(host, pwr, SDHCI_POWER_CONTROL);
@@ -424,14 +421,14 @@ static int sdhci_set_ios(struct udevice *dev)
{
struct mmc *mmc = mmc_get_mmc_dev(dev);
#else
-static void sdhci_set_ios(struct mmc *mmc)
+static int sdhci_set_ios(struct mmc *mmc)
{
#endif
u32 ctrl;
struct sdhci_host *host = mmc->priv;
- if (host->set_control_reg)
- host->set_control_reg(host);
+ if (host->ops && host->ops->set_control_reg)
+ host->ops->set_control_reg(host);
if (mmc->clock != host->clock)
sdhci_set_clock(mmc, mmc->clock);
@@ -462,9 +459,8 @@ static void sdhci_set_ios(struct mmc *mmc)
ctrl &= ~SDHCI_CTRL_HISPD;
sdhci_writeb(host, ctrl, SDHCI_HOST_CONTROL);
-#ifdef CONFIG_DM_MMC_OPS
+
return 0;
-#endif
}
static int sdhci_init(struct mmc *mmc)
@@ -484,25 +480,8 @@ static int sdhci_init(struct mmc *mmc)
sdhci_set_power(host, fls(mmc->cfg->voltages) - 1);
- if (host->quirks & SDHCI_QUIRK_NO_CD) {
-#if defined(CONFIG_PIC32_SDHCI)
- /* PIC32 SDHCI CD errata:
- * - set CD_TEST and clear CD_TEST_INS bit
- */
- sdhci_writeb(host, SDHCI_CTRL_CD_TEST, SDHCI_HOST_CONTROL);
-#else
- unsigned int status;
-
- sdhci_writeb(host, SDHCI_CTRL_CD_TEST_INS | SDHCI_CTRL_CD_TEST,
- SDHCI_HOST_CONTROL);
-
- status = sdhci_readl(host, SDHCI_PRESENT_STATE);
- while ((!(status & SDHCI_CARD_PRESENT)) ||
- (!(status & SDHCI_CARD_STATE_STABLE)) ||
- (!(status & SDHCI_CARD_DETECT_PIN_LEVEL)))
- status = sdhci_readl(host, SDHCI_PRESENT_STATE);
-#endif
- }
+ if (host->ops && host->ops->get_cd)
+ host->ops->get_cd(host);
/* Enable only interrupts served by the SD controller */
sdhci_writel(host, SDHCI_INT_DATA_MASK | SDHCI_INT_CMD_MASK,
@@ -593,27 +572,23 @@ int sdhci_setup_cfg(struct mmc_config *cfg, struct sdhci_host *host,
cfg->voltages |= host->voltages;
cfg->host_caps = MMC_MODE_HS | MMC_MODE_HS_52MHz | MMC_MODE_4BIT;
+
+ /* Since Host Controller Version3.0 */
if (SDHCI_GET_VERSION(host) >= SDHCI_SPEC_300) {
- if (caps & SDHCI_CAN_DO_8BIT)
- cfg->host_caps |= MMC_MODE_8BIT;
+ if (!(caps & SDHCI_CAN_DO_8BIT))
+ cfg->host_caps &= ~MMC_MODE_8BIT;
+
+ /* Find out whether clock multiplier is supported */
+ caps_1 = sdhci_readl(host, SDHCI_CAPABILITIES_1);
+ host->clk_mul = (caps_1 & SDHCI_CLOCK_MUL_MASK) >>
+ SDHCI_CLOCK_MUL_SHIFT;
}
if (host->host_caps)
cfg->host_caps |= host->host_caps;
-
cfg->b_max = CONFIG_SYS_MMC_MAX_BLK_COUNT;
- /*
- * In case of Host Controller v3.00, find out whether clock
- * multiplier is supported.
- */
- if (SDHCI_GET_VERSION(host) >= SDHCI_SPEC_300) {
- caps_1 = sdhci_readl(host, SDHCI_CAPABILITIES_1);
- host->clk_mul = (caps_1 & SDHCI_CLOCK_MUL_MASK) >>
- SDHCI_CLOCK_MUL_SHIFT;
- }
-
return 0;
}
diff --git a/drivers/mmc/sh_mmcif.c b/drivers/mmc/sh_mmcif.c
index 69ded9e..1ff59f0 100644
--- a/drivers/mmc/sh_mmcif.c
+++ b/drivers/mmc/sh_mmcif.c
@@ -539,7 +539,7 @@ static int sh_mmcif_request(struct mmc *mmc, struct mmc_cmd *cmd,
return ret;
}
-static void sh_mmcif_set_ios(struct mmc *mmc)
+static int sh_mmcif_set_ios(struct mmc *mmc)
{
struct sh_mmcif_host *host = mmc->priv;
@@ -554,6 +554,8 @@ static void sh_mmcif_set_ios(struct mmc *mmc)
host->bus_width = MMC_BUS_WIDTH_1;
debug("clock = %d, buswidth = %d\n", mmc->clock, mmc->bus_width);
+
+ return 0;
}
static int sh_mmcif_init(struct mmc *mmc)
diff --git a/drivers/mmc/sh_sdhi.c b/drivers/mmc/sh_sdhi.c
index 78e2ef6..25224e2 100644
--- a/drivers/mmc/sh_sdhi.c
+++ b/drivers/mmc/sh_sdhi.c
@@ -608,14 +608,14 @@ static int sh_sdhi_send_cmd(struct mmc *mmc, struct mmc_cmd *cmd,
return ret;
}
-static void sh_sdhi_set_ios(struct mmc *mmc)
+static int sh_sdhi_set_ios(struct mmc *mmc)
{
int ret;
struct sh_sdhi_host *host = mmc_priv(mmc);
ret = sh_sdhi_clock_control(host, mmc->clock);
if (ret)
- return;
+ return -EINVAL;
if (mmc->bus_width == 4)
sh_sdhi_writew(host, SDHI_OPTION, ~OPT_BUS_WIDTH_1 &
@@ -625,6 +625,8 @@ static void sh_sdhi_set_ios(struct mmc *mmc)
sh_sdhi_readw(host, SDHI_OPTION));
debug("clock = %d, buswidth = %d\n", mmc->clock, mmc->bus_width);
+
+ return 0;
}
static int sh_sdhi_initialize(struct mmc *mmc)
diff --git a/drivers/mmc/sunxi_mmc.c b/drivers/mmc/sunxi_mmc.c
index b8716c9..fd3fc2a 100644
--- a/drivers/mmc/sunxi_mmc.c
+++ b/drivers/mmc/sunxi_mmc.c
@@ -227,7 +227,7 @@ static int mmc_config_clock(struct mmc *mmc)
return 0;
}
-static void sunxi_mmc_set_ios(struct mmc *mmc)
+static int sunxi_mmc_set_ios(struct mmc *mmc)
{
struct sunxi_mmc_host *mmchost = mmc->priv;
@@ -237,7 +237,7 @@ static void sunxi_mmc_set_ios(struct mmc *mmc)
/* Change clock first */
if (mmc->clock && mmc_config_clock(mmc) != 0) {
mmchost->fatal_err = 1;
- return;
+ return -EINVAL;
}
/* Change bus width */
@@ -247,6 +247,8 @@ static void sunxi_mmc_set_ios(struct mmc *mmc)
writel(0x1, &mmchost->reg->width);
else
writel(0x0, &mmchost->reg->width);
+
+ return 0;
}
static int sunxi_mmc_core_init(struct mmc *mmc)
diff --git a/drivers/mmc/tegra_mmc.c b/drivers/mmc/tegra_mmc.c
index 97b1154..0211dc7 100644
--- a/drivers/mmc/tegra_mmc.c
+++ b/drivers/mmc/tegra_mmc.c
@@ -408,7 +408,7 @@ out:
priv->clock = clock;
}
-static void tegra_mmc_set_ios(struct mmc *mmc)
+static int tegra_mmc_set_ios(struct mmc *mmc)
{
struct tegra_mmc_priv *priv = mmc->priv;
unsigned char ctrl;
@@ -438,6 +438,8 @@ static void tegra_mmc_set_ios(struct mmc *mmc)
writeb(ctrl, &priv->reg->hostctl);
debug("mmc_set_ios: hostctl = %08X\n", ctrl);
+
+ return 0;
}
static void tegra_mmc_pad_init(struct tegra_mmc_priv *priv)