#include <common.h>
#include <dm.h>
#include <fdtdec.h>
+#include <linux/delay.h>
#include "mmc_private.h"
+#include <log.h>
+#include <dm/device_compat.h>
+#include <linux/err.h>
#include <linux/libfdt.h>
#include <malloc.h>
#include <sdhci.h>
#include <zynqmp_tap_delay.h>
-DECLARE_GLOBAL_DATA_PTR;
-
struct arasan_sdhci_plat {
struct mmc_config cfg;
struct mmc mmc;
- unsigned int f_max;
};
struct arasan_sdhci_priv {
struct sdhci_host *host;
u8 deviceid;
u8 bank;
- u8 no_1p8;
- bool pwrseq;
};
#if defined(CONFIG_ARCH_ZYNQMP)
+#define MMC_HS200_BUS_SPEED 5
+
static const u8 mode2timing[] = {
- [UHS_SDR12] = UHS_SDR12_BUS_SPEED,
- [UHS_SDR25] = UHS_SDR25_BUS_SPEED,
- [UHS_SDR50] = UHS_SDR50_BUS_SPEED,
- [UHS_SDR104] = UHS_SDR104_BUS_SPEED,
- [UHS_DDR50] = UHS_DDR50_BUS_SPEED,
+ [MMC_LEGACY] = UHS_SDR12_BUS_SPEED,
+ [MMC_HS] = HIGH_SPEED_BUS_SPEED,
+ [SD_HS] = HIGH_SPEED_BUS_SPEED,
+ [MMC_HS_52] = HIGH_SPEED_BUS_SPEED,
+ [MMC_DDR_52] = HIGH_SPEED_BUS_SPEED,
+ [UHS_SDR12] = UHS_SDR12_BUS_SPEED,
+ [UHS_SDR25] = UHS_SDR25_BUS_SPEED,
+ [UHS_SDR50] = UHS_SDR50_BUS_SPEED,
+ [UHS_DDR50] = UHS_DDR50_BUS_SPEED,
+ [UHS_SDR104] = UHS_SDR104_BUS_SPEED,
+ [MMC_HS_200] = MMC_HS200_BUS_SPEED,
};
-#define SDHCI_HOST_CTRL2 0x3E
-#define SDHCI_CTRL2_MODE_MASK 0x7
-#define SDHCI_18V_SIGNAL 0x8
-#define SDHCI_CTRL_EXEC_TUNING 0x0040
-#define SDHCI_CTRL_TUNED_CLK 0x80
#define SDHCI_TUNING_LOOP_COUNT 40
static void arasan_zynqmp_dll_reset(struct sdhci_host *host, u8 deviceid)
u32 ctrl;
struct sdhci_host *host;
struct arasan_sdhci_priv *priv = dev_get_priv(mmc->dev);
- u8 tuning_loop_counter = SDHCI_TUNING_LOOP_COUNT;
+ char tuning_loop_counter = SDHCI_TUNING_LOOP_COUNT;
u8 deviceid;
debug("%s\n", __func__);
host = priv->host;
deviceid = priv->deviceid;
- ctrl = sdhci_readw(host, SDHCI_HOST_CTRL2);
+ ctrl = sdhci_readw(host, SDHCI_HOST_CONTROL2);
ctrl |= SDHCI_CTRL_EXEC_TUNING;
- sdhci_writew(host, ctrl, SDHCI_HOST_CTRL2);
+ sdhci_writew(host, ctrl, SDHCI_HOST_CONTROL2);
mdelay(1);
sdhci_writew(host, SDHCI_TRNS_READ, SDHCI_TRANSFER_MODE);
mmc_send_cmd(mmc, &cmd, NULL);
- ctrl = sdhci_readw(host, SDHCI_HOST_CTRL2);
+ ctrl = sdhci_readw(host, SDHCI_HOST_CONTROL2);
if (cmd.cmdidx == MMC_CMD_SEND_TUNING_BLOCK)
udelay(1);
if (tuning_loop_counter < 0) {
ctrl &= ~SDHCI_CTRL_TUNED_CLK;
- sdhci_writel(host, ctrl, SDHCI_HOST_CTRL2);
+ sdhci_writel(host, ctrl, SDHCI_HOST_CONTROL2);
}
if (!(ctrl & SDHCI_CTRL_TUNED_CLK)) {
struct mmc *mmc = (struct mmc *)host->mmc;
u8 uhsmode;
- if (!IS_SD(mmc))
- return;
-
uhsmode = mode2timing[mmc->selected_mode];
if (uhsmode >= UHS_SDR25_BUS_SPEED)
struct mmc *mmc = (struct mmc *)host->mmc;
u32 reg;
+ if (!IS_SD(mmc))
+ return;
+
if (mmc->signal_voltage == MMC_SIGNAL_VOLTAGE_180) {
- reg = sdhci_readw(host, SDHCI_HOST_CTRL2);
- reg |= SDHCI_18V_SIGNAL;
- sdhci_writew(host, reg, SDHCI_HOST_CTRL2);
+ reg = sdhci_readw(host, SDHCI_HOST_CONTROL2);
+ reg |= SDHCI_CTRL_VDD_180;
+ sdhci_writew(host, reg, SDHCI_HOST_CONTROL2);
}
if (mmc->selected_mode > SD_HS &&
- mmc->selected_mode <= UHS_DDR50) {
- reg = sdhci_readw(host, SDHCI_HOST_CTRL2);
- reg &= ~SDHCI_CTRL2_MODE_MASK;
- switch (mmc->selected_mode) {
- case UHS_SDR12:
- reg |= UHS_SDR12_BUS_SPEED;
- break;
- case UHS_SDR25:
- reg |= UHS_SDR25_BUS_SPEED;
- break;
- case UHS_SDR50:
- reg |= UHS_SDR50_BUS_SPEED;
- break;
- case UHS_SDR104:
- reg |= UHS_SDR104_BUS_SPEED;
- break;
- case UHS_DDR50:
- reg |= UHS_DDR50_BUS_SPEED;
- break;
- default:
- break;
- }
- sdhci_writew(host, reg, SDHCI_HOST_CTRL2);
- }
+ mmc->selected_mode <= UHS_DDR50)
+ sdhci_set_uhs_timing(host);
}
#endif
-#if defined(CONFIG_DM_MMC) && defined(CONFIG_ARCH_ZYNQMP)
+#if defined(CONFIG_ARCH_ZYNQMP)
const struct sdhci_ops arasan_ops = {
.platform_execute_tuning = &arasan_sdhci_execute_tuning,
.set_delay = &arasan_sdhci_set_tapdelay,
host->quirks |= SDHCI_QUIRK_BROKEN_HISPD_MODE;
#endif
- if (priv->no_1p8)
- host->quirks |= SDHCI_QUIRK_NO_1_8_V;
+ plat->cfg.f_max = CONFIG_ZYNQ_SDHCI_MAX_FREQ;
+
+ ret = mmc_of_parse(dev, &plat->cfg);
+ if (ret)
+ return ret;
host->max_clk = clock;
- ret = sdhci_setup_cfg(&plat->cfg, host, plat->f_max,
- CONFIG_ZYNQ_SDHCI_MIN_FREQ);
host->mmc = &plat->mmc;
+ host->mmc->dev = dev;
+ host->mmc->priv = host;
+
+ ret = sdhci_setup_cfg(&plat->cfg, host, plat->cfg.f_max,
+ CONFIG_ZYNQ_SDHCI_MIN_FREQ);
if (ret)
return ret;
- host->mmc->priv = host;
- host->mmc->dev = dev;
upriv->mmc = host->mmc;
return sdhci_probe(dev);
static int arasan_sdhci_ofdata_to_platdata(struct udevice *dev)
{
- struct arasan_sdhci_plat *plat = dev_get_platdata(dev);
struct arasan_sdhci_priv *priv = dev_get_priv(dev);
priv->host = calloc(1, sizeof(struct sdhci_host));
priv->host->name = dev->name;
-#if defined(CONFIG_DM_MMC) && defined(CONFIG_ARCH_ZYNQMP)
+#if defined(CONFIG_ARCH_ZYNQMP)
priv->host->ops = &arasan_ops;
#endif
priv->deviceid = dev_read_u32_default(dev, "xlnx,device_id", -1);
priv->bank = dev_read_u32_default(dev, "xlnx,mio_bank", -1);
- priv->no_1p8 = dev_read_bool(dev, "no-1-8-v");
- plat->f_max = dev_read_u32_default(dev, "max-frequency",
- CONFIG_ZYNQ_SDHCI_MAX_FREQ);
return 0;
}