summaryrefslogtreecommitdiff
path: root/drivers/mmc
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/mmc')
-rw-r--r--drivers/mmc/Kconfig6
-rw-r--r--drivers/mmc/meson_gx_mmc.c3
-rw-r--r--drivers/mmc/mmc.c2
-rw-r--r--drivers/mmc/renesas-sdhi.c23
-rw-r--r--drivers/mmc/sh_mmcif.c165
-rw-r--r--drivers/mmc/tmio-common.c22
-rw-r--r--drivers/mmc/uniphier-sd.c29
7 files changed, 214 insertions, 36 deletions
diff --git a/drivers/mmc/Kconfig b/drivers/mmc/Kconfig
index 6935da2177d..4fa8dd83bb7 100644
--- a/drivers/mmc/Kconfig
+++ b/drivers/mmc/Kconfig
@@ -266,6 +266,12 @@ config SH_SDHI
help
Support for the on-chip SDHI host controller on SuperH/Renesas ARM SoCs platform
+config SH_MMCIF
+ bool "SuperH/Renesas ARM SoCs on-chip MMCIF host controller support"
+ depends on ARCH_RMOBILE || SH
+ help
+ Support for the on-chip MMCIF host controller on SuperH/Renesas ARM SoCs platform
+
config MMC_UNIPHIER
bool "UniPhier SD/MMC Host Controller support"
depends on ARCH_UNIPHIER
diff --git a/drivers/mmc/meson_gx_mmc.c b/drivers/mmc/meson_gx_mmc.c
index a2cd5d3a446..454593eec43 100644
--- a/drivers/mmc/meson_gx_mmc.c
+++ b/drivers/mmc/meson_gx_mmc.c
@@ -35,6 +35,9 @@ static void meson_mmc_config_clock(struct mmc *mmc)
uint32_t meson_mmc_clk = 0;
unsigned int clk, clk_src, clk_div;
+ if (!mmc->clock)
+ return;
+
/* 1GHz / CLK_MAX_DIV = 15,9 MHz */
if (mmc->clock > 16000000) {
clk = SD_EMMC_CLKSRC_DIV2;
diff --git a/drivers/mmc/mmc.c b/drivers/mmc/mmc.c
index c9308933003..f72b80c7048 100644
--- a/drivers/mmc/mmc.c
+++ b/drivers/mmc/mmc.c
@@ -1334,7 +1334,7 @@ static int sd_set_card_speed(struct mmc *mmc, enum bus_mode mode)
return 0;
}
-int sd_select_bus_width(struct mmc *mmc, int w)
+static int sd_select_bus_width(struct mmc *mmc, int w)
{
int err;
struct mmc_cmd cmd;
diff --git a/drivers/mmc/renesas-sdhi.c b/drivers/mmc/renesas-sdhi.c
index 56a43ca7d3f..8e49b2f73cc 100644
--- a/drivers/mmc/renesas-sdhi.c
+++ b/drivers/mmc/renesas-sdhi.c
@@ -330,8 +330,10 @@ static const struct udevice_id renesas_sdhi_match[] = {
static int renesas_sdhi_probe(struct udevice *dev)
{
+ struct tmio_sd_priv *priv = dev_get_priv(dev);
u32 quirks = dev_get_driver_data(dev);
struct fdt_resource reg_res;
+ struct clk clk;
DECLARE_GLOBAL_DATA_PTR;
int ret;
@@ -348,6 +350,27 @@ static int renesas_sdhi_probe(struct udevice *dev)
quirks |= TMIO_SD_CAP_16BIT;
}
+ ret = clk_get_by_index(dev, 0, &clk);
+ if (ret < 0) {
+ dev_err(dev, "failed to get host clock\n");
+ return ret;
+ }
+
+ /* set to max rate */
+ priv->mclk = clk_set_rate(&clk, ULONG_MAX);
+ if (IS_ERR_VALUE(priv->mclk)) {
+ dev_err(dev, "failed to set rate for host clock\n");
+ clk_free(&clk);
+ return priv->mclk;
+ }
+
+ ret = clk_enable(&clk);
+ clk_free(&clk);
+ if (ret) {
+ dev_err(dev, "failed to enable host clock\n");
+ return ret;
+ }
+
ret = tmio_sd_probe(dev, quirks);
#if CONFIG_IS_ENABLED(MMC_HS200_SUPPORT)
if (!ret)
diff --git a/drivers/mmc/sh_mmcif.c b/drivers/mmc/sh_mmcif.c
index 1ff59f06d57..26fe125cea7 100644
--- a/drivers/mmc/sh_mmcif.c
+++ b/drivers/mmc/sh_mmcif.c
@@ -11,9 +11,13 @@
#include <watchdog.h>
#include <command.h>
#include <mmc.h>
+#include <clk.h>
+#include <dm.h>
#include <malloc.h>
#include <linux/errno.h>
-#include <asm/io.h>
+#include <linux/compat.h>
+#include <linux/io.h>
+#include <linux/sizes.h>
#include "sh_mmcif.h"
#define DRIVER_NAME "sh_mmcif"
@@ -510,10 +514,9 @@ static int sh_mmcif_start_cmd(struct sh_mmcif_host *host,
return ret;
}
-static int sh_mmcif_request(struct mmc *mmc, struct mmc_cmd *cmd,
- struct mmc_data *data)
+static int sh_mmcif_send_cmd_common(struct sh_mmcif_host *host,
+ struct mmc_cmd *cmd, struct mmc_data *data)
{
- struct sh_mmcif_host *host = mmc->priv;
int ret;
WATCHDOG_RESET();
@@ -539,10 +542,8 @@ static int sh_mmcif_request(struct mmc *mmc, struct mmc_cmd *cmd,
return ret;
}
-static int sh_mmcif_set_ios(struct mmc *mmc)
+static int sh_mmcif_set_ios_common(struct sh_mmcif_host *host, struct mmc *mmc)
{
- struct sh_mmcif_host *host = mmc->priv;
-
if (mmc->clock)
sh_mmcif_clock_control(host, mmc->clock);
@@ -558,19 +559,45 @@ static int sh_mmcif_set_ios(struct mmc *mmc)
return 0;
}
-static int sh_mmcif_init(struct mmc *mmc)
+static int sh_mmcif_initialize_common(struct sh_mmcif_host *host)
{
- struct sh_mmcif_host *host = mmc->priv;
-
sh_mmcif_sync_reset(host);
sh_mmcif_write(MASK_ALL, &host->regs->ce_int_mask);
return 0;
}
+#ifndef CONFIG_DM_MMC
+static void *mmc_priv(struct mmc *mmc)
+{
+ return (void *)mmc->priv;
+}
+
+static int sh_mmcif_send_cmd(struct mmc *mmc, struct mmc_cmd *cmd,
+ struct mmc_data *data)
+{
+ struct sh_mmcif_host *host = mmc_priv(mmc);
+
+ return sh_mmcif_send_cmd_common(host, cmd, data);
+}
+
+static int sh_mmcif_set_ios(struct mmc *mmc)
+{
+ struct sh_mmcif_host *host = mmc_priv(mmc);
+
+ return sh_mmcif_set_ios_common(host, mmc);
+}
+
+static int sh_mmcif_initialize(struct mmc *mmc)
+{
+ struct sh_mmcif_host *host = mmc_priv(mmc);
+
+ return sh_mmcif_initialize_common(host);
+}
+
static const struct mmc_ops sh_mmcif_ops = {
- .send_cmd = sh_mmcif_request,
- .set_ios = sh_mmcif_set_ios,
- .init = sh_mmcif_init,
+ .send_cmd = sh_mmcif_send_cmd,
+ .set_ios = sh_mmcif_set_ios,
+ .init = sh_mmcif_initialize,
};
static struct mmc_config sh_mmcif_cfg = {
@@ -606,3 +633,115 @@ int mmcif_mmc_init(void)
return 0;
}
+
+#else
+struct sh_mmcif_plat {
+ struct mmc_config cfg;
+ struct mmc mmc;
+};
+
+int sh_mmcif_dm_send_cmd(struct udevice *dev, struct mmc_cmd *cmd,
+ struct mmc_data *data)
+{
+ struct sh_mmcif_host *host = dev_get_priv(dev);
+
+ return sh_mmcif_send_cmd_common(host, cmd, data);
+}
+
+int sh_mmcif_dm_set_ios(struct udevice *dev)
+{
+ struct sh_mmcif_host *host = dev_get_priv(dev);
+ struct mmc *mmc = mmc_get_mmc_dev(dev);
+
+ return sh_mmcif_set_ios_common(host, mmc);
+}
+
+static const struct dm_mmc_ops sh_mmcif_dm_ops = {
+ .send_cmd = sh_mmcif_dm_send_cmd,
+ .set_ios = sh_mmcif_dm_set_ios,
+};
+
+static int sh_mmcif_dm_bind(struct udevice *dev)
+{
+ struct sh_mmcif_plat *plat = dev_get_platdata(dev);
+
+ return mmc_bind(dev, &plat->mmc, &plat->cfg);
+}
+
+static int sh_mmcif_dm_probe(struct udevice *dev)
+{
+ struct sh_mmcif_plat *plat = dev_get_platdata(dev);
+ struct sh_mmcif_host *host = dev_get_priv(dev);
+ struct mmc_uclass_priv *upriv = dev_get_uclass_priv(dev);
+ struct clk sh_mmcif_clk;
+ fdt_addr_t base;
+ int ret;
+
+ base = devfdt_get_addr(dev);
+ if (base == FDT_ADDR_T_NONE)
+ return -EINVAL;
+
+ host->regs = (struct sh_mmcif_regs *)devm_ioremap(dev, base, SZ_2K);
+ if (!host->regs)
+ return -ENOMEM;
+
+ ret = clk_get_by_index(dev, 0, &sh_mmcif_clk);
+ if (ret) {
+ debug("failed to get clock, ret=%d\n", ret);
+ return ret;
+ }
+
+ ret = clk_enable(&sh_mmcif_clk);
+ if (ret) {
+ debug("failed to enable clock, ret=%d\n", ret);
+ return ret;
+ }
+
+ host->clk = clk_get_rate(&sh_mmcif_clk);
+
+ plat->cfg.name = dev->name;
+ plat->cfg.host_caps = MMC_MODE_HS_52MHz | MMC_MODE_HS;
+
+ switch (fdtdec_get_int(gd->fdt_blob, dev_of_offset(dev), "bus-width",
+ 1)) {
+ case 8:
+ plat->cfg.host_caps |= MMC_MODE_8BIT;
+ break;
+ case 4:
+ plat->cfg.host_caps |= MMC_MODE_4BIT;
+ break;
+ case 1:
+ break;
+ default:
+ dev_err(dev, "Invalid \"bus-width\" value\n");
+ return -EINVAL;
+ }
+
+ sh_mmcif_initialize_common(host);
+
+ plat->cfg.voltages = MMC_VDD_165_195 | MMC_VDD_32_33 | MMC_VDD_33_34;
+ plat->cfg.f_min = MMC_CLK_DIV_MIN(host->clk);
+ plat->cfg.f_max = MMC_CLK_DIV_MAX(host->clk);
+ plat->cfg.b_max = CONFIG_SYS_MMC_MAX_BLK_COUNT;
+
+ upriv->mmc = &plat->mmc;
+
+ return 0;
+}
+
+static const struct udevice_id sh_mmcif_sd_match[] = {
+ { .compatible = "renesas,sh-mmcif" },
+ { /* sentinel */ }
+};
+
+U_BOOT_DRIVER(sh_mmcif_mmc) = {
+ .name = "sh-mmcif",
+ .id = UCLASS_MMC,
+ .of_match = sh_mmcif_sd_match,
+ .bind = sh_mmcif_dm_bind,
+ .probe = sh_mmcif_dm_probe,
+ .priv_auto_alloc_size = sizeof(struct sh_mmcif_host),
+ .platdata_auto_alloc_size = sizeof(struct sh_mmcif_plat),
+ .ops = &sh_mmcif_dm_ops,
+};
+#endif
diff --git a/drivers/mmc/tmio-common.c b/drivers/mmc/tmio-common.c
index 5f1c9c0bd4d..4ea66121427 100644
--- a/drivers/mmc/tmio-common.c
+++ b/drivers/mmc/tmio-common.c
@@ -713,7 +713,6 @@ int tmio_sd_probe(struct udevice *dev, u32 quirks)
struct tmio_sd_priv *priv = dev_get_priv(dev);
struct mmc_uclass_priv *upriv = dev_get_uclass_priv(dev);
fdt_addr_t base;
- struct clk clk;
int ret;
base = devfdt_get_addr(dev);
@@ -728,27 +727,6 @@ int tmio_sd_probe(struct udevice *dev, u32 quirks)
device_get_supply_regulator(dev, "vqmmc-supply", &priv->vqmmc_dev);
#endif
- ret = clk_get_by_index(dev, 0, &clk);
- if (ret < 0) {
- dev_err(dev, "failed to get host clock\n");
- return ret;
- }
-
- /* set to max rate */
- priv->mclk = clk_set_rate(&clk, ULONG_MAX);
- if (IS_ERR_VALUE(priv->mclk)) {
- dev_err(dev, "failed to set rate for host clock\n");
- clk_free(&clk);
- return priv->mclk;
- }
-
- ret = clk_enable(&clk);
- clk_free(&clk);
- if (ret) {
- dev_err(dev, "failed to enable host clock\n");
- return ret;
- }
-
ret = mmc_of_parse(dev, &plat->cfg);
if (ret < 0) {
dev_err(dev, "failed to parse host caps\n");
diff --git a/drivers/mmc/uniphier-sd.c b/drivers/mmc/uniphier-sd.c
index 47379b0328e..61f8da4e413 100644
--- a/drivers/mmc/uniphier-sd.c
+++ b/drivers/mmc/uniphier-sd.c
@@ -32,6 +32,35 @@ static const struct udevice_id uniphier_sd_match[] = {
static int uniphier_sd_probe(struct udevice *dev)
{
+ struct tmio_sd_priv *priv = dev_get_priv(dev);
+#ifndef CONFIG_SPL_BUILD
+ struct clk clk;
+ int ret;
+
+ ret = clk_get_by_index(dev, 0, &clk);
+ if (ret < 0) {
+ dev_err(dev, "failed to get host clock\n");
+ return ret;
+ }
+
+ /* set to max rate */
+ priv->mclk = clk_set_rate(&clk, ULONG_MAX);
+ if (IS_ERR_VALUE(priv->mclk)) {
+ dev_err(dev, "failed to set rate for host clock\n");
+ clk_free(&clk);
+ return priv->mclk;
+ }
+
+ ret = clk_enable(&clk);
+ clk_free(&clk);
+ if (ret) {
+ dev_err(dev, "failed to enable host clock\n");
+ return ret;
+ }
+#else
+ priv->mclk = 100000000;
+#endif
+
return tmio_sd_probe(dev, 0);
}