summaryrefslogtreecommitdiff
path: root/drivers
diff options
context:
space:
mode:
Diffstat (limited to 'drivers')
-rw-r--r--drivers/core/regmap.c42
-rw-r--r--drivers/i2c/Kconfig2
-rw-r--r--drivers/mmc/Kconfig9
-rw-r--r--drivers/mmc/Makefile2
-rw-r--r--drivers/mmc/am654_sdhci.c333
-rw-r--r--drivers/mmc/k3_arsan_sdhci.c109
-rw-r--r--drivers/mmc/sdhci.c50
-rw-r--r--drivers/mmc/xenon_sdhci.c4
-rw-r--r--drivers/mmc/zynq_sdhci.c45
9 files changed, 439 insertions, 157 deletions
diff --git a/drivers/core/regmap.c b/drivers/core/regmap.c
index 5ef0f71c8b..d1d12eef38 100644
--- a/drivers/core/regmap.c
+++ b/drivers/core/regmap.c
@@ -108,6 +108,48 @@ static int init_range(ofnode node, struct regmap_range *range, int addr_len,
return 0;
}
+int regmap_init_mem_index(ofnode node, struct regmap **mapp, int index)
+{
+ struct regmap *map;
+ int addr_len, size_len;
+ int ret;
+
+ addr_len = ofnode_read_simple_addr_cells(ofnode_get_parent(node));
+ if (addr_len < 0) {
+ debug("%s: Error while reading the addr length (ret = %d)\n",
+ ofnode_get_name(node), addr_len);
+ return addr_len;
+ }
+
+ size_len = ofnode_read_simple_size_cells(ofnode_get_parent(node));
+ if (size_len < 0) {
+ debug("%s: Error while reading the size length: (ret = %d)\n",
+ ofnode_get_name(node), size_len);
+ return size_len;
+ }
+
+ map = regmap_alloc(1);
+ if (!map)
+ return -ENOMEM;
+
+ ret = init_range(node, map->ranges, addr_len, size_len, index);
+ if (ret)
+ return ret;
+
+ if (ofnode_read_bool(node, "little-endian"))
+ map->endianness = REGMAP_LITTLE_ENDIAN;
+ else if (ofnode_read_bool(node, "big-endian"))
+ map->endianness = REGMAP_BIG_ENDIAN;
+ else if (ofnode_read_bool(node, "native-endian"))
+ map->endianness = REGMAP_NATIVE_ENDIAN;
+ else /* Default: native endianness */
+ map->endianness = REGMAP_NATIVE_ENDIAN;
+
+ *mapp = map;
+
+ return ret;
+}
+
int regmap_init_mem(ofnode node, struct regmap **mapp)
{
struct regmap_range *range;
diff --git a/drivers/i2c/Kconfig b/drivers/i2c/Kconfig
index 095a9bc6a4..4772db3837 100644
--- a/drivers/i2c/Kconfig
+++ b/drivers/i2c/Kconfig
@@ -330,7 +330,7 @@ endif
config SYS_I2C_OMAP24XX
bool "TI OMAP2+ I2C driver"
- depends on ARCH_OMAP2PLUS
+ depends on ARCH_OMAP2PLUS || ARCH_K3
help
Add support for the OMAP2+ I2C driver.
diff --git a/drivers/mmc/Kconfig b/drivers/mmc/Kconfig
index 890ef358a0..4cdae41b59 100644
--- a/drivers/mmc/Kconfig
+++ b/drivers/mmc/Kconfig
@@ -468,14 +468,15 @@ config MMC_SDHCI_CADENCE
If unsure, say N.
-config MMC_SDHCI_K3_ARASAN
- bool "Arasan SDHCI controller for TI's K3 based SoCs"
+config MMC_SDHCI_AM654
+ bool "SDHCI Controller on TI's Am654 devices"
depends on ARCH_K3
depends on MMC_SDHCI
depends on DM_MMC && OF_CONTROL && BLK
+ depends on REGMAP
help
- Support for Arasan SDHCI host controller on Texas Instruments'
- K3 family based SoC platforms
+ Support for Secure Digital Host Controller Interface (SDHCI)
+ controllers present on TI's AM654 SOCs.
config MMC_SDHCI_KONA
bool "SDHCI support on Broadcom KONA platform"
diff --git a/drivers/mmc/Makefile b/drivers/mmc/Makefile
index 3c8c53a9e1..6cc018bb67 100644
--- a/drivers/mmc/Makefile
+++ b/drivers/mmc/Makefile
@@ -50,7 +50,7 @@ obj-$(CONFIG_MMC_SDHCI_ATMEL) += atmel_sdhci.o
obj-$(CONFIG_MMC_SDHCI_BCM2835) += bcm2835_sdhci.o
obj-$(CONFIG_MMC_SDHCI_BCMSTB) += bcmstb_sdhci.o
obj-$(CONFIG_MMC_SDHCI_CADENCE) += sdhci-cadence.o
-obj-$(CONFIG_MMC_SDHCI_K3_ARASAN) += k3_arsan_sdhci.o
+obj-$(CONFIG_MMC_SDHCI_AM654) += am654_sdhci.o
obj-$(CONFIG_MMC_SDHCI_KONA) += kona_sdhci.o
obj-$(CONFIG_MMC_SDHCI_MSM) += msm_sdhci.o
obj-$(CONFIG_MMC_SDHCI_MV) += mv_sdhci.o
diff --git a/drivers/mmc/am654_sdhci.c b/drivers/mmc/am654_sdhci.c
new file mode 100644
index 0000000000..fb0fb58070
--- /dev/null
+++ b/drivers/mmc/am654_sdhci.c
@@ -0,0 +1,333 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (C) 2018 Texas Instruments Incorporated - http://www.ti.com/
+ *
+ * Texas Instruments' K3 SD Host Controller Interface
+ */
+
+#include <clk.h>
+#include <common.h>
+#include <dm.h>
+#include <malloc.h>
+#include <power-domain.h>
+#include <regmap.h>
+#include <sdhci.h>
+
+/* CTL_CFG Registers */
+#define CTL_CFG_2 0x14
+
+#define SLOTTYPE_MASK GENMASK(31, 30)
+#define SLOTTYPE_EMBEDDED BIT(30)
+
+/* PHY Registers */
+#define PHY_CTRL1 0x100
+#define PHY_CTRL2 0x104
+#define PHY_CTRL3 0x108
+#define PHY_CTRL4 0x10C
+#define PHY_CTRL5 0x110
+#define PHY_CTRL6 0x114
+#define PHY_STAT1 0x130
+#define PHY_STAT2 0x134
+
+#define IOMUX_ENABLE_SHIFT 31
+#define IOMUX_ENABLE_MASK BIT(IOMUX_ENABLE_SHIFT)
+#define OTAPDLYENA_SHIFT 20
+#define OTAPDLYENA_MASK BIT(OTAPDLYENA_SHIFT)
+#define OTAPDLYSEL_SHIFT 12
+#define OTAPDLYSEL_MASK GENMASK(15, 12)
+#define STRBSEL_SHIFT 24
+#define STRBSEL_MASK GENMASK(27, 24)
+#define SEL50_SHIFT 8
+#define SEL50_MASK BIT(SEL50_SHIFT)
+#define SEL100_SHIFT 9
+#define SEL100_MASK BIT(SEL100_SHIFT)
+#define DLL_TRIM_ICP_SHIFT 4
+#define DLL_TRIM_ICP_MASK GENMASK(7, 4)
+#define DR_TY_SHIFT 20
+#define DR_TY_MASK GENMASK(22, 20)
+#define ENDLL_SHIFT 1
+#define ENDLL_MASK BIT(ENDLL_SHIFT)
+#define DLLRDY_SHIFT 0
+#define DLLRDY_MASK BIT(DLLRDY_SHIFT)
+#define PDB_SHIFT 0
+#define PDB_MASK BIT(PDB_SHIFT)
+#define CALDONE_SHIFT 1
+#define CALDONE_MASK BIT(CALDONE_SHIFT)
+#define RETRIM_SHIFT 17
+#define RETRIM_MASK BIT(RETRIM_SHIFT)
+
+#define DRIVER_STRENGTH_50_OHM 0x0
+#define DRIVER_STRENGTH_33_OHM 0x1
+#define DRIVER_STRENGTH_66_OHM 0x2
+#define DRIVER_STRENGTH_100_OHM 0x3
+#define DRIVER_STRENGTH_40_OHM 0x4
+
+#define AM654_SDHCI_MIN_FREQ 400000
+
+struct am654_sdhci_plat {
+ struct mmc_config cfg;
+ struct mmc mmc;
+ struct regmap *base;
+ bool non_removable;
+ u32 otap_del_sel;
+ u32 trm_icp;
+ u32 drv_strength;
+ bool dll_on;
+};
+
+static void am654_sdhci_set_control_reg(struct sdhci_host *host)
+{
+ struct mmc *mmc = (struct mmc *)host->mmc;
+ u32 reg;
+
+ if (IS_SD(host->mmc) &&
+ mmc->signal_voltage == MMC_SIGNAL_VOLTAGE_180) {
+ reg = sdhci_readw(host, SDHCI_HOST_CONTROL2);
+ reg |= SDHCI_CTRL_VDD_180;
+ sdhci_writew(host, reg, SDHCI_HOST_CONTROL2);
+ }
+
+ sdhci_set_uhs_timing(host);
+}
+
+static int am654_sdhci_set_ios_post(struct sdhci_host *host)
+{
+ struct udevice *dev = host->mmc->dev;
+ struct am654_sdhci_plat *plat = dev_get_platdata(dev);
+ unsigned int speed = host->mmc->clock;
+ int sel50, sel100;
+ u32 mask, val;
+ int ret;
+
+ /* Reset SD Clock Enable */
+ val = sdhci_readw(host, SDHCI_CLOCK_CONTROL);
+ val &= ~SDHCI_CLOCK_CARD_EN;
+ sdhci_writew(host, val, SDHCI_CLOCK_CONTROL);
+
+ /* power off phy */
+ if (plat->dll_on) {
+ regmap_update_bits(plat->base, PHY_CTRL1, ENDLL_MASK, 0);
+
+ plat->dll_on = false;
+ }
+
+ /* restart clock */
+ sdhci_set_clock(host->mmc, speed);
+
+ /* switch phy back on */
+ if (speed > AM654_SDHCI_MIN_FREQ) {
+ mask = OTAPDLYENA_MASK | OTAPDLYSEL_MASK;
+ val = (1 << OTAPDLYENA_SHIFT) |
+ (plat->otap_del_sel << OTAPDLYSEL_SHIFT);
+ regmap_update_bits(plat->base, PHY_CTRL4, mask, val);
+ switch (speed) {
+ case 200000000:
+ sel50 = 0;
+ sel100 = 0;
+ break;
+ case 100000000:
+ sel50 = 0;
+ sel100 = 1;
+ break;
+ default:
+ sel50 = 1;
+ sel100 = 0;
+ }
+
+ /* Configure PHY DLL frequency */
+ mask = SEL50_MASK | SEL100_MASK;
+ val = (sel50 << SEL50_SHIFT) | (sel100 << SEL100_SHIFT);
+ regmap_update_bits(plat->base, PHY_CTRL5, mask, val);
+
+ /* Enable DLL */
+ regmap_update_bits(plat->base, PHY_CTRL1, ENDLL_MASK,
+ 0x1 << ENDLL_SHIFT);
+ /*
+ * Poll for DLL ready. Use a one second timeout.
+ * Works in all experiments done so far
+ */
+ ret = regmap_read_poll_timeout(plat->base, PHY_STAT1, val,
+ val & DLLRDY_MASK, 1000, 1000000);
+ if (ret)
+ return ret;
+
+ plat->dll_on = true;
+ }
+
+ return 0;
+}
+
+const struct sdhci_ops am654_sdhci_ops = {
+ .set_ios_post = &am654_sdhci_set_ios_post,
+ .set_control_reg = &am654_sdhci_set_control_reg,
+};
+
+int am654_sdhci_init(struct am654_sdhci_plat *plat)
+{
+ u32 ctl_cfg_2 = 0;
+ u32 mask, val;
+ int ret;
+
+ /* Reset OTAP to default value */
+ mask = OTAPDLYENA_MASK | OTAPDLYSEL_MASK;
+ regmap_update_bits(plat->base, PHY_CTRL4, mask, 0x0);
+
+ regmap_read(plat->base, PHY_STAT1, &val);
+ if (~val & CALDONE_MASK) {
+ /* Calibrate IO lines */
+ regmap_update_bits(plat->base, PHY_CTRL1, PDB_MASK, PDB_MASK);
+ ret = regmap_read_poll_timeout(plat->base, PHY_STAT1, val,
+ val & CALDONE_MASK, 1, 20);
+ if (ret)
+ return ret;
+ }
+
+ /* Configure DLL TRIM */
+ mask = DLL_TRIM_ICP_MASK;
+ val = plat->trm_icp << DLL_TRIM_ICP_SHIFT;
+
+ /* Configure DLL driver strength */
+ mask |= DR_TY_MASK;
+ val |= plat->drv_strength << DR_TY_SHIFT;
+ regmap_update_bits(plat->base, PHY_CTRL1, mask, val);
+
+ /* Enable pins by setting IO mux to 0 */
+ regmap_update_bits(plat->base, PHY_CTRL1, IOMUX_ENABLE_MASK, 0);
+
+ /* Set slot type based on SD or eMMC */
+ if (plat->non_removable)
+ ctl_cfg_2 = SLOTTYPE_EMBEDDED;
+
+ regmap_update_bits(plat->base, CTL_CFG_2, SLOTTYPE_MASK, ctl_cfg_2);
+
+ return 0;
+}
+
+static int am654_sdhci_probe(struct udevice *dev)
+{
+ struct am654_sdhci_plat *plat = dev_get_platdata(dev);
+ struct mmc_uclass_priv *upriv = dev_get_uclass_priv(dev);
+ struct sdhci_host *host = dev_get_priv(dev);
+ struct mmc_config *cfg = &plat->cfg;
+ struct power_domain sdhci_pwrdmn;
+ struct clk clk;
+ unsigned long clock;
+ int ret;
+
+ ret = power_domain_get_by_index(dev, &sdhci_pwrdmn, 0);
+ if (!ret) {
+ ret = power_domain_on(&sdhci_pwrdmn);
+ if (ret) {
+ dev_err(dev, "Power domain on failed (%d)\n", ret);
+ return ret;
+ }
+ } else if (ret != -ENOENT && ret != -ENODEV && ret != -ENOSYS) {
+ dev_err(dev, "failed to get power domain (%d)\n", ret);
+ return ret;
+ }
+
+ ret = clk_get_by_index(dev, 0, &clk);
+ if (ret) {
+ dev_err(dev, "failed to get clock\n");
+ return ret;
+ }
+
+ clock = clk_get_rate(&clk);
+ if (IS_ERR_VALUE(clock)) {
+ dev_err(dev, "failed to get rate\n");
+ return clock;
+ }
+
+ host->max_clk = clock;
+ host->mmc = &plat->mmc;
+ host->mmc->dev = dev;
+ ret = sdhci_setup_cfg(cfg, host, cfg->f_max,
+ AM654_SDHCI_MIN_FREQ);
+ if (ret)
+ return ret;
+ host->ops = &am654_sdhci_ops;
+ host->mmc->priv = host;
+ upriv->mmc = host->mmc;
+
+ regmap_init_mem_index(dev_ofnode(dev), &plat->base, 1);
+
+ am654_sdhci_init(plat);
+
+ return sdhci_probe(dev);
+}
+
+static int am654_sdhci_ofdata_to_platdata(struct udevice *dev)
+{
+ struct am654_sdhci_plat *plat = dev_get_platdata(dev);
+ struct sdhci_host *host = dev_get_priv(dev);
+ struct mmc_config *cfg = &plat->cfg;
+ u32 drv_strength;
+ int ret;
+
+ host->name = dev->name;
+ host->ioaddr = (void *)dev_read_addr(dev);
+ plat->non_removable = dev_read_bool(dev, "non-removable");
+
+ ret = dev_read_u32(dev, "ti,trm-icp", &plat->trm_icp);
+ if (ret)
+ return ret;
+
+ ret = dev_read_u32(dev, "ti,otap-del-sel", &plat->otap_del_sel);
+ if (ret)
+ return ret;
+
+ ret = dev_read_u32(dev, "ti,driver-strength-ohm", &drv_strength);
+ if (ret)
+ return ret;
+
+ switch (drv_strength) {
+ case 50:
+ plat->drv_strength = DRIVER_STRENGTH_50_OHM;
+ break;
+ case 33:
+ plat->drv_strength = DRIVER_STRENGTH_33_OHM;
+ break;
+ case 66:
+ plat->drv_strength = DRIVER_STRENGTH_66_OHM;
+ break;
+ case 100:
+ plat->drv_strength = DRIVER_STRENGTH_100_OHM;
+ break;
+ case 40:
+ plat->drv_strength = DRIVER_STRENGTH_40_OHM;
+ break;
+ default:
+ dev_err(dev, "Invalid driver strength\n");
+ return -EINVAL;
+ }
+
+ ret = mmc_of_parse(dev, cfg);
+ if (ret)
+ return ret;
+
+ return 0;
+}
+
+static int am654_sdhci_bind(struct udevice *dev)
+{
+ struct am654_sdhci_plat *plat = dev_get_platdata(dev);
+
+ return sdhci_bind(dev, &plat->mmc, &plat->cfg);
+}
+
+static const struct udevice_id am654_sdhci_ids[] = {
+ { .compatible = "ti,am654-sdhci-5.1" },
+ { }
+};
+
+U_BOOT_DRIVER(am654_sdhci_drv) = {
+ .name = "am654_sdhci",
+ .id = UCLASS_MMC,
+ .of_match = am654_sdhci_ids,
+ .ofdata_to_platdata = am654_sdhci_ofdata_to_platdata,
+ .ops = &sdhci_ops,
+ .bind = am654_sdhci_bind,
+ .probe = am654_sdhci_probe,
+ .priv_auto_alloc_size = sizeof(struct sdhci_host),
+ .platdata_auto_alloc_size = sizeof(struct am654_sdhci_plat),
+};
diff --git a/drivers/mmc/k3_arsan_sdhci.c b/drivers/mmc/k3_arsan_sdhci.c
deleted file mode 100644
index d5f2857382..0000000000
--- a/drivers/mmc/k3_arsan_sdhci.c
+++ /dev/null
@@ -1,109 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0+
-/*
- * Copyright (C) 2018 Texas Instruments Incorporated - http://www.ti.com/
- *
- * Texas Instruments' K3 SD Host Controller Interface
- */
-
-#include <clk.h>
-#include <common.h>
-#include <dm.h>
-#include <malloc.h>
-#include <power-domain.h>
-#include <sdhci.h>
-
-#define K3_ARASAN_SDHCI_MIN_FREQ 0
-
-struct k3_arasan_sdhci_plat {
- struct mmc_config cfg;
- struct mmc mmc;
- unsigned int f_max;
-};
-
-static int k3_arasan_sdhci_probe(struct udevice *dev)
-{
- struct k3_arasan_sdhci_plat *plat = dev_get_platdata(dev);
- struct mmc_uclass_priv *upriv = dev_get_uclass_priv(dev);
- struct sdhci_host *host = dev_get_priv(dev);
- struct power_domain sdhci_pwrdmn;
- struct clk clk;
- unsigned long clock;
- int ret;
-
- ret = power_domain_get_by_index(dev, &sdhci_pwrdmn, 0);
- if (ret) {
- dev_err(dev, "failed to get power domain\n");
- return ret;
- }
-
- ret = power_domain_on(&sdhci_pwrdmn);
- if (ret) {
- dev_err(dev, "Power domain on failed\n");
- return ret;
- }
-
- ret = clk_get_by_index(dev, 0, &clk);
- if (ret) {
- dev_err(dev, "failed to get clock\n");
- return ret;
- }
-
- clock = clk_get_rate(&clk);
- if (IS_ERR_VALUE(clock)) {
- dev_err(dev, "failed to get rate\n");
- return clock;
- }
-
- host->quirks = SDHCI_QUIRK_WAIT_SEND_CMD |
- SDHCI_QUIRK_BROKEN_R1B;
-
- host->max_clk = clock;
-
- ret = sdhci_setup_cfg(&plat->cfg, host, plat->f_max,
- K3_ARASAN_SDHCI_MIN_FREQ);
- host->mmc = &plat->mmc;
- if (ret)
- return ret;
- host->mmc->priv = host;
- host->mmc->dev = dev;
- upriv->mmc = host->mmc;
-
- return sdhci_probe(dev);
-}
-
-static int k3_arasan_sdhci_ofdata_to_platdata(struct udevice *dev)
-{
- struct k3_arasan_sdhci_plat *plat = dev_get_platdata(dev);
- struct sdhci_host *host = dev_get_priv(dev);
-
- host->name = dev->name;
- host->ioaddr = (void *)dev_read_addr(dev);
- host->bus_width = dev_read_u32_default(dev, "bus-width", 4);
- plat->f_max = dev_read_u32_default(dev, "max-frequency", 0);
-
- return 0;
-}
-
-static int k3_arasan_sdhci_bind(struct udevice *dev)
-{
- struct k3_arasan_sdhci_plat *plat = dev_get_platdata(dev);
-
- return sdhci_bind(dev, &plat->mmc, &plat->cfg);
-}
-
-static const struct udevice_id k3_arasan_sdhci_ids[] = {
- { .compatible = "arasan,sdhci-5.1" },
- { }
-};
-
-U_BOOT_DRIVER(k3_arasan_sdhci_drv) = {
- .name = "k3_arasan_sdhci",
- .id = UCLASS_MMC,
- .of_match = k3_arasan_sdhci_ids,
- .ofdata_to_platdata = k3_arasan_sdhci_ofdata_to_platdata,
- .ops = &sdhci_ops,
- .bind = k3_arasan_sdhci_bind,
- .probe = k3_arasan_sdhci_probe,
- .priv_auto_alloc_size = sizeof(struct sdhci_host),
- .platdata_auto_alloc_size = sizeof(struct k3_arasan_sdhci_plat),
-};
diff --git a/drivers/mmc/sdhci.c b/drivers/mmc/sdhci.c
index c4e88790bc..0a0770cc20 100644
--- a/drivers/mmc/sdhci.c
+++ b/drivers/mmc/sdhci.c
@@ -8,6 +8,7 @@
*/
#include <common.h>
+#include <dm.h>
#include <errno.h>
#include <malloc.h>
#include <mmc.h>
@@ -409,7 +410,7 @@ static int sdhci_execute_tuning(struct udevice *dev, uint opcode)
return 0;
}
#endif
-static int sdhci_set_clock(struct mmc *mmc, unsigned int clock)
+int sdhci_set_clock(struct mmc *mmc, unsigned int clock)
{
struct sdhci_host *host = mmc->priv;
unsigned int div, clk = 0, timeout;
@@ -533,6 +534,34 @@ static void sdhci_set_power(struct sdhci_host *host, unsigned short power)
sdhci_writeb(host, pwr, SDHCI_POWER_CONTROL);
}
+void sdhci_set_uhs_timing(struct sdhci_host *host)
+{
+ struct mmc *mmc = (struct mmc *)host->mmc;
+ u32 reg;
+
+ reg = sdhci_readw(host, SDHCI_HOST_CONTROL2);
+ reg &= ~SDHCI_CTRL_UHS_MASK;
+
+ switch (mmc->selected_mode) {
+ case UHS_SDR50:
+ case MMC_HS_52:
+ reg |= SDHCI_CTRL_UHS_SDR50;
+ break;
+ case UHS_DDR50:
+ case MMC_DDR_52:
+ reg |= SDHCI_CTRL_UHS_DDR50;
+ break;
+ case UHS_SDR104:
+ case MMC_HS_200:
+ reg |= SDHCI_CTRL_UHS_SDR104;
+ break;
+ default:
+ reg |= SDHCI_CTRL_UHS_SDR12;
+ }
+
+ sdhci_writew(host, reg, SDHCI_HOST_CONTROL2);
+}
+
#ifdef CONFIG_DM_MMC
static int sdhci_set_ios(struct udevice *dev)
{
@@ -583,7 +612,7 @@ static int sdhci_set_ios(struct mmc *mmc)
/* If available, call the driver specific "post" set_ios() function */
if (host->ops && host->ops->set_ios_post)
- host->ops->set_ios_post(host);
+ return host->ops->set_ios_post(host);
return 0;
}
@@ -681,8 +710,18 @@ int sdhci_setup_cfg(struct mmc_config *cfg, struct sdhci_host *host,
u32 f_max, u32 f_min)
{
u32 caps, caps_1 = 0;
+#if CONFIG_IS_ENABLED(DM_MMC)
+ u32 mask[2] = {0};
+ int ret;
+ ret = dev_read_u32_array(host->mmc->dev, "sdhci-caps-mask",
+ mask, 2);
+ if (ret && ret != -1)
+ return ret;
+ caps = ~mask[1] & sdhci_readl(host, SDHCI_CAPABILITIES);
+#else
caps = sdhci_readl(host, SDHCI_CAPABILITIES);
+#endif
#ifdef CONFIG_MMC_SDHCI_SDMA
if (!(caps & SDHCI_CAN_DO_SDMA)) {
@@ -722,7 +761,11 @@ int sdhci_setup_cfg(struct mmc_config *cfg, struct sdhci_host *host,
/* Check whether the clock multiplier is supported or not */
if (SDHCI_GET_VERSION(host) >= SDHCI_SPEC_300) {
+#if CONFIG_IS_ENABLED(DM_MMC)
+ caps_1 = ~mask[0] & sdhci_readl(host, SDHCI_CAPABILITIES_1);
+#else
caps_1 = sdhci_readl(host, SDHCI_CAPABILITIES_1);
+#endif
host->clk_mul = (caps_1 & SDHCI_CLOCK_MUL_MASK) >>
SDHCI_CLOCK_MUL_SHIFT;
}
@@ -779,9 +822,6 @@ int sdhci_setup_cfg(struct mmc_config *cfg, struct sdhci_host *host,
cfg->host_caps &= ~MMC_MODE_HS_52MHz;
}
- if (SDHCI_GET_VERSION(host) >= SDHCI_SPEC_300)
- caps_1 = sdhci_readl(host, SDHCI_CAPABILITIES_1);
-
if (!(cfg->voltages & MMC_VDD_165_195) ||
(host->quirks & SDHCI_QUIRK_NO_1_8_V))
caps_1 &= ~(SDHCI_SUPPORT_SDR104 | SDHCI_SUPPORT_SDR50 |
diff --git a/drivers/mmc/xenon_sdhci.c b/drivers/mmc/xenon_sdhci.c
index b576511338..829b75683b 100644
--- a/drivers/mmc/xenon_sdhci.c
+++ b/drivers/mmc/xenon_sdhci.c
@@ -326,7 +326,7 @@ static void xenon_mask_cmd_conflict_err(struct sdhci_host *host)
}
/* Platform specific function for post set_ios configuration */
-static void xenon_sdhci_set_ios_post(struct sdhci_host *host)
+static int xenon_sdhci_set_ios_post(struct sdhci_host *host)
{
struct xenon_sdhci_priv *priv = host->mmc->priv;
uint speed = host->mmc->tran_speed;
@@ -364,6 +364,8 @@ static void xenon_sdhci_set_ios_post(struct sdhci_host *host)
/* Re-init the PHY */
xenon_mmc_phy_set(host);
+
+ return 0;
}
/* Install a driver specific handler for post set_ios configuration */
diff --git a/drivers/mmc/zynq_sdhci.c b/drivers/mmc/zynq_sdhci.c
index 08023783de..c525084250 100644
--- a/drivers/mmc/zynq_sdhci.c
+++ b/drivers/mmc/zynq_sdhci.c
@@ -48,11 +48,6 @@ static const u8 mode2timing[] = {
[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)
@@ -99,9 +94,9 @@ static int arasan_sdhci_execute_tuning(struct mmc *mmc, u8 opcode)
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);
@@ -133,7 +128,7 @@ static int arasan_sdhci_execute_tuning(struct mmc *mmc, u8 opcode)
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);
@@ -142,7 +137,7 @@ static int arasan_sdhci_execute_tuning(struct mmc *mmc, u8 opcode)
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)) {
@@ -184,36 +179,14 @@ static void arasan_sdhci_set_control_reg(struct sdhci_host *host)
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