mirror of
https://github.com/u-boot/u-boot.git
synced 2024-11-29 15:43:44 +08:00
mmc: sh_mmcif: Add DM and DT probing support
Add MMC DM and DT probing support into the SH MMCIF driver. This patch abstracts out the common bits of the send command and set ios functions, so they can be used both by DM and non DM setups and adds the DM probe support. Signed-off-by: Marek Vasut <marek.vasut+renesas@gmail.com> Cc: Nobuhiro Iwamatsu <iwamatsu@nigauri.org> Cc: Jaehoon Chung <jh80.chung@samsung.com>
This commit is contained in:
parent
010bbe7331
commit
48f54a2d74
@ -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
|
||||
|
Loading…
Reference in New Issue
Block a user