summaryrefslogtreecommitdiff
path: root/drivers/mmc
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/mmc')
-rw-r--r--drivers/mmc/Kconfig9
-rw-r--r--drivers/mmc/Makefile1
-rw-r--r--drivers/mmc/dw_mmc.c2
-rw-r--r--drivers/mmc/exynos_dw_mmc.c2
-rw-r--r--drivers/mmc/mmc.c43
-rw-r--r--drivers/mmc/rockchip_dw_mmc.c98
6 files changed, 149 insertions, 6 deletions
diff --git a/drivers/mmc/Kconfig b/drivers/mmc/Kconfig
index 3e835f7..6277f92 100644
--- a/drivers/mmc/Kconfig
+++ b/drivers/mmc/Kconfig
@@ -10,6 +10,15 @@ config DM_MMC
appear as block devices in U-Boot and can support filesystems such
as EXT4 and FAT.
+config ROCKCHIP_DWMMC
+ bool "Rockchip SD/MMC controller support"
+ depends on DM_MMC && OF_CONTROL
+ 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 SH_SDHI
bool "SuperH/Renesas ARM SoCs on-chip SDHI host controller support"
depends on RMOBILE
diff --git a/drivers/mmc/Makefile b/drivers/mmc/Makefile
index cae207c..99d0295 100644
--- a/drivers/mmc/Makefile
+++ b/drivers/mmc/Makefile
@@ -29,6 +29,7 @@ obj-$(CONFIG_MXS_MMC) += mxsmmc.o
obj-$(CONFIG_OMAP_HSMMC) += omap_hsmmc.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
obj-$(CONFIG_S5P_SDHCI) += s5p_sdhci.o
diff --git a/drivers/mmc/dw_mmc.c b/drivers/mmc/dw_mmc.c
index 77b87e0..1117fed 100644
--- a/drivers/mmc/dw_mmc.c
+++ b/drivers/mmc/dw_mmc.c
@@ -266,7 +266,7 @@ static int dwmci_setup_bus(struct dwmci_host *host, u32 freq)
* host->bus_hz should be set by user.
*/
if (host->get_mmc_clk)
- sclk = host->get_mmc_clk(host);
+ sclk = host->get_mmc_clk(host, freq);
else if (host->bus_hz)
sclk = host->bus_hz;
else {
diff --git a/drivers/mmc/exynos_dw_mmc.c b/drivers/mmc/exynos_dw_mmc.c
index cde2ba7..863bbb3 100644
--- a/drivers/mmc/exynos_dw_mmc.c
+++ b/drivers/mmc/exynos_dw_mmc.c
@@ -39,7 +39,7 @@ static void exynos_dwmci_clksel(struct dwmci_host *host)
dwmci_writel(host, DWMCI_CLKSEL, priv->sdr_timing);
}
-unsigned int exynos_dwmci_get_clk(struct dwmci_host *host)
+unsigned int exynos_dwmci_get_clk(struct dwmci_host *host, uint freq)
{
unsigned long sclk;
int8_t clk_div;
diff --git a/drivers/mmc/mmc.c b/drivers/mmc/mmc.c
index f12546a..371c1ec 100644
--- a/drivers/mmc/mmc.c
+++ b/drivers/mmc/mmc.c
@@ -10,6 +10,8 @@
#include <config.h>
#include <common.h>
#include <command.h>
+#include <dm.h>
+#include <dm/device-internal.h>
#include <errno.h>
#include <mmc.h>
#include <part.h>
@@ -1759,10 +1761,44 @@ static void do_preinit(void)
}
}
+#if defined(CONFIG_DM_MMC) && defined(CONFIG_SPL_BUILD)
+static int mmc_probe(bd_t *bis)
+{
+ return 0;
+}
+#elif defined(CONFIG_DM_MMC)
+static int mmc_probe(bd_t *bis)
+{
+ int ret;
+ struct uclass *uc;
+ struct udevice *m;
+
+ ret = uclass_get(UCLASS_MMC, &uc);
+ if (ret)
+ return ret;
+
+ uclass_foreach_dev(m, uc) {
+ ret = device_probe(m);
+ if (ret)
+ printf("%s - probe failed: %d\n", m->name, ret);
+ }
+
+ return 0;
+}
+#else
+static int mmc_probe(bd_t *bis)
+{
+ if (board_mmc_init(bis) < 0)
+ cpu_mmc_init(bis);
+
+ return 0;
+}
+#endif
int mmc_initialize(bd_t *bis)
{
static int initialized = 0;
+ int ret;
if (initialized) /* Avoid initializing mmc multiple times */
return 0;
initialized = 1;
@@ -1770,10 +1806,9 @@ int mmc_initialize(bd_t *bis)
INIT_LIST_HEAD (&mmc_devices);
cur_dev_num = 0;
-#ifndef CONFIG_DM_MMC
- if (board_mmc_init(bis) < 0)
- cpu_mmc_init(bis);
-#endif
+ ret = mmc_probe(bis);
+ if (ret)
+ return ret;
#ifndef CONFIG_SPL_BUILD
print_mmc_devices(',');
diff --git a/drivers/mmc/rockchip_dw_mmc.c b/drivers/mmc/rockchip_dw_mmc.c
new file mode 100644
index 0000000..f11c8e0
--- /dev/null
+++ b/drivers/mmc/rockchip_dw_mmc.c
@@ -0,0 +1,98 @@
+/*
+ * Copyright (c) 2013 Google, Inc
+ *
+ * SPDX-License-Identifier: GPL-2.0+
+ */
+
+#include <common.h>
+#include <clk.h>
+#include <dm.h>
+#include <dwmmc.h>
+#include <errno.h>
+#include <syscon.h>
+#include <asm/arch/clock.h>
+#include <asm/arch/periph.h>
+#include <linux/err.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+struct rockchip_dwmmc_priv {
+ struct udevice *clk;
+ struct rk3288_grf *grf;
+ struct dwmci_host host;
+};
+
+static uint rockchip_dwmmc_get_mmc_clk(struct dwmci_host *host, uint freq)
+{
+ struct udevice *dev = host->priv;
+ struct rockchip_dwmmc_priv *priv = dev_get_priv(dev);
+ int ret;
+
+ ret = clk_set_periph_rate(priv->clk, PERIPH_ID_SDMMC0 + host->dev_index,
+ freq);
+ if (ret < 0) {
+ debug("%s: err=%d\n", __func__, ret);
+ return ret;
+ }
+
+ return freq;
+}
+
+static int rockchip_dwmmc_ofdata_to_platdata(struct udevice *dev)
+{
+ struct rockchip_dwmmc_priv *priv = dev_get_priv(dev);
+ struct dwmci_host *host = &priv->host;
+
+ host->name = dev->name;
+ host->ioaddr = (void *)dev_get_addr(dev);
+ host->buswidth = fdtdec_get_int(gd->fdt_blob, dev->of_offset,
+ "bus-width", 4);
+ host->get_mmc_clk = rockchip_dwmmc_get_mmc_clk;
+ host->priv = dev;
+
+ /* TODO(sjg@chromium.org): Remove the need for this hack */
+ host->dev_index = (ulong)host->ioaddr == 0xff0f0000 ? 0 : 1;
+
+ return 0;
+}
+
+static int rockchip_dwmmc_probe(struct udevice *dev)
+{
+ struct mmc_uclass_priv *upriv = dev_get_uclass_priv(dev);
+ struct rockchip_dwmmc_priv *priv = dev_get_priv(dev);
+ struct dwmci_host *host = &priv->host;
+ u32 minmax[2];
+ int ret;
+
+ priv->grf = syscon_get_first_range(ROCKCHIP_SYSCON_GRF);
+ if (IS_ERR(priv->grf))
+ return PTR_ERR(priv->grf);
+ ret = uclass_get_device(UCLASS_CLK, CLK_GENERAL, &priv->clk);
+ if (ret)
+ return ret;
+
+ ret = fdtdec_get_int_array(gd->fdt_blob, dev->of_offset,
+ "clock-freq-min-max", minmax, 2);
+ if (!ret)
+ ret = add_dwmci(host, minmax[1], minmax[0]);
+ if (ret)
+ return ret;
+
+ upriv->mmc = host->mmc;
+
+ return 0;
+}
+
+static const struct udevice_id rockchip_dwmmc_ids[] = {
+ { .compatible = "rockchip,rk3288-dw-mshc" },
+ { }
+};
+
+U_BOOT_DRIVER(rockchip_dwmmc_drv) = {
+ .name = "rockchip_dwmmc",
+ .id = UCLASS_MMC,
+ .of_match = rockchip_dwmmc_ids,
+ .ofdata_to_platdata = rockchip_dwmmc_ofdata_to_platdata,
+ .probe = rockchip_dwmmc_probe,
+ .priv_auto_alloc_size = sizeof(struct rockchip_dwmmc_priv),
+};