X-Git-Url: https://git.librecmc.org/?a=blobdiff_plain;f=drivers%2Fmmc%2Fsh_mmcif.c;h=2e994d0178d9ff8186294134c38cfbf221e95818;hb=c927d65873c7706f436ab59a78d44a0eb80fe939;hp=001bf185a72a4dde4f7a469df36cb01220c8172a;hpb=45fe3809b9923b92f221d70eb45ae071059fd5e0;p=oweals%2Fu-boot.git diff --git a/drivers/mmc/sh_mmcif.c b/drivers/mmc/sh_mmcif.c index 001bf185a7..2e994d0178 100644 --- a/drivers/mmc/sh_mmcif.c +++ b/drivers/mmc/sh_mmcif.c @@ -1,19 +1,26 @@ +// SPDX-License-Identifier: GPL-2.0 /* * MMCIF driver. * * Copyright (C) 2011 Renesas Solutions Corp. - * - * SPDX-License-Identifier: GPL-2.0 */ #include #include +#include #include #include #include +#include +#include #include -#include -#include +#include +#include +#include +#include +#include +#include +#include #include "sh_mmcif.h" #define DRIVER_NAME "sh_mmcif" @@ -168,7 +175,7 @@ static int sh_mmcif_error_manage(struct sh_mmcif_host *host) if (state2 & STS2_CRC_ERR) ret = -EILSEQ; else if (state2 & STS2_TIMEOUT_ERR) - ret = TIMEOUT; + ret = -ETIMEDOUT; else ret = -EILSEQ; return ret; @@ -483,7 +490,7 @@ static int sh_mmcif_start_cmd(struct sh_mmcif_host *host, case MMC_CMD_ALL_SEND_CID: case MMC_CMD_SELECT_CARD: case MMC_CMD_APP_CMD: - ret = TIMEOUT; + ret = -ETIMEDOUT; break; default: printf(DRIVER_NAME": Cmd(d'%d) err\n", cmd->cmdidx); @@ -510,24 +517,23 @@ 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(); switch (cmd->cmdidx) { case MMC_CMD_APP_CMD: - return TIMEOUT; + return -ETIMEDOUT; case MMC_CMD_SEND_EXT_CSD: /* = SD_SEND_IF_COND (8) */ if (data) /* ext_csd */ break; else /* send_if_cond cmd (not support) */ - return TIMEOUT; + return -ETIMEDOUT; default: break; } @@ -539,10 +545,8 @@ 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_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); @@ -554,21 +558,49 @@ 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) +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 = { @@ -604,3 +636,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_set_rate(&sh_mmcif_clk, 97500000); + + 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