diff --git a/drivers/mmc/Kconfig b/drivers/mmc/Kconfig index 78091cc217..05e0b10f34 100644 --- a/drivers/mmc/Kconfig +++ b/drivers/mmc/Kconfig @@ -325,6 +325,20 @@ config MMC_SDHCI_XENON If unsure, say N. +config MMC_SDHCI_TANGIER + bool "Tangier SDHCI controller support" + depends on DM_MMC && BLK + depends on MMC_SDHCI + help + This selects support for SDHCI controller on Tanginer + SoC. Note that this controller does not sit on PCI bus and, + hence, cannot be enumerated by standard PCI means. + + If you're using an Intel Tangier SoC (available on Intel + Edison board), say Y here. + + If unsure, say N. + config MMC_SDHCI_TEGRA bool "SDHCI platform support for the Tegra SD/MMC Controller" depends on TEGRA diff --git a/drivers/mmc/Makefile b/drivers/mmc/Makefile index 1e8d23f012..6a26a52c28 100644 --- a/drivers/mmc/Makefile +++ b/drivers/mmc/Makefile @@ -62,6 +62,7 @@ obj-$(CONFIG_MMC_SDHCI_ROCKCHIP) += rockchip_sdhci.o obj-$(CONFIG_MMC_SDHCI_S5P) += s5p_sdhci.o obj-$(CONFIG_MMC_SDHCI_SPEAR) += spear_sdhci.o obj-$(CONFIG_MMC_SDHCI_STI) += sti_sdhci.o +obj-$(CONFIG_MMC_SDHCI_TANGIER) += tangier_sdhci.o obj-$(CONFIG_MMC_SDHCI_TEGRA) += tegra_mmc.o obj-$(CONFIG_MMC_SDHCI_XENON) += xenon_sdhci.o obj-$(CONFIG_MMC_SDHCI_ZYNQ) += zynq_sdhci.o diff --git a/drivers/mmc/tangier_sdhci.c b/drivers/mmc/tangier_sdhci.c new file mode 100644 index 0000000000..77b18e75f0 --- /dev/null +++ b/drivers/mmc/tangier_sdhci.c @@ -0,0 +1,81 @@ +/* + * Copyright (c) 2017 Intel Corporation + * + * SPDX-License-Identifier: GPL-2.0+ + */ +#include +#include +#include +#include +#include +#include +#include +#include + +#define SDHCI_TANGIER_FMAX 200000000 +#define SDHCI_TANGIER_FMIN 400000 + +struct sdhci_tangier_plat { + struct mmc_config cfg; + struct mmc mmc; + void __iomem *ioaddr; +}; + +static int sdhci_tangier_bind(struct udevice *dev) +{ + struct sdhci_tangier_plat *plat = dev_get_platdata(dev); + + return sdhci_bind(dev, &plat->mmc, &plat->cfg); +} + +static int sdhci_tangier_probe(struct udevice *dev) +{ + struct mmc_uclass_priv *upriv = dev_get_uclass_priv(dev); + struct sdhci_tangier_plat *plat = dev_get_platdata(dev); + struct sdhci_host *host = dev_get_priv(dev); + fdt_addr_t base; + int ret; + + base = dev_get_addr(dev); + if (base == FDT_ADDR_T_NONE) + return -EINVAL; + + plat->ioaddr = devm_ioremap(dev, base, SZ_1K); + if (!plat->ioaddr) + return -ENOMEM; + + host->name = dev->name; + host->ioaddr = plat->ioaddr; + host->quirks = SDHCI_QUIRK_NO_HISPD_BIT | SDHCI_QUIRK_BROKEN_VOLTAGE | + SDHCI_QUIRK_32BIT_DMA_ADDR | SDHCI_QUIRK_WAIT_SEND_CMD; + + /* MMC_VDD_32_33 | MMC_VDD_33_34 | MMC_VDD_165_195 */ + host->voltages = MMC_VDD_165_195; + + ret = sdhci_setup_cfg(&plat->cfg, host, SDHCI_TANGIER_FMAX, + SDHCI_TANGIER_FMIN); + if (ret) + return ret; + + upriv->mmc = &plat->mmc; + host->mmc = &plat->mmc; + host->mmc->priv = host; + + return sdhci_probe(dev); +} + +static const struct udevice_id sdhci_tangier_match[] = { + { .compatible = "intel,sdhci-tangier" }, + { /* sentinel */ } +}; + +U_BOOT_DRIVER(sdhci_tangier) = { + .name = "sdhci-tangier", + .id = UCLASS_MMC, + .of_match = sdhci_tangier_match, + .bind = sdhci_tangier_bind, + .probe = sdhci_tangier_probe, + .ops = &sdhci_ops, + .priv_auto_alloc_size = sizeof(struct sdhci_host), + .platdata_auto_alloc_size = sizeof(struct sdhci_tangier_plat), +};