1293eb33fSMichal Simek /* 2d9ae52c8SMichal Simek * (C) Copyright 2013 - 2015 Xilinx, Inc. 3293eb33fSMichal Simek * 4293eb33fSMichal Simek * Xilinx Zynq SD Host Controller Interface 5293eb33fSMichal Simek * 61a459660SWolfgang Denk * SPDX-License-Identifier: GPL-2.0+ 7293eb33fSMichal Simek */ 8293eb33fSMichal Simek 9293eb33fSMichal Simek #include <common.h> 10d9ae52c8SMichal Simek #include <dm.h> 11345d3c0fSMichal Simek #include <fdtdec.h> 12345d3c0fSMichal Simek #include <libfdt.h> 13293eb33fSMichal Simek #include <malloc.h> 14293eb33fSMichal Simek #include <sdhci.h> 15293eb33fSMichal Simek 16a57a4a5dSSiva Durga Prasad Paladugu #ifndef CONFIG_ZYNQ_SDHCI_MIN_FREQ 17a57a4a5dSSiva Durga Prasad Paladugu # define CONFIG_ZYNQ_SDHCI_MIN_FREQ 0 18a57a4a5dSSiva Durga Prasad Paladugu #endif 19a57a4a5dSSiva Durga Prasad Paladugu 20329a449fSSimon Glass struct arasan_sdhci_plat { 21329a449fSSimon Glass struct mmc_config cfg; 22329a449fSSimon Glass struct mmc mmc; 23329a449fSSimon Glass }; 24329a449fSSimon Glass 25d9ae52c8SMichal Simek static int arasan_sdhci_probe(struct udevice *dev) 26293eb33fSMichal Simek { 27329a449fSSimon Glass struct arasan_sdhci_plat *plat = dev_get_platdata(dev); 28d9ae52c8SMichal Simek struct mmc_uclass_priv *upriv = dev_get_uclass_priv(dev); 29d9ae52c8SMichal Simek struct sdhci_host *host = dev_get_priv(dev); 30329a449fSSimon Glass u32 caps; 31329a449fSSimon Glass int ret; 32293eb33fSMichal Simek 33eddabd16SSiva Durga Prasad Paladugu host->quirks = SDHCI_QUIRK_WAIT_SEND_CMD | 34f9ec45d1SSiva Durga Prasad Paladugu SDHCI_QUIRK_BROKEN_R1B; 35b2156146SSiva Durga Prasad Paladugu 36b2156146SSiva Durga Prasad Paladugu #ifdef CONFIG_ZYNQ_HISPD_BROKEN 37b2156146SSiva Durga Prasad Paladugu host->quirks |= SDHCI_QUIRK_NO_HISPD_BIT; 38b2156146SSiva Durga Prasad Paladugu #endif 39b2156146SSiva Durga Prasad Paladugu 40293eb33fSMichal Simek host->version = sdhci_readw(host, SDHCI_HOST_VERSION); 41293eb33fSMichal Simek 42329a449fSSimon Glass caps = sdhci_readl(host, SDHCI_CAPABILITIES); 43*14bed52dSJaehoon Chung ret = sdhci_setup_cfg(&plat->cfg, host, CONFIG_ZYNQ_SDHCI_MAX_FREQ, 44*14bed52dSJaehoon Chung CONFIG_ZYNQ_SDHCI_MIN_FREQ); 45329a449fSSimon Glass host->mmc = &plat->mmc; 46329a449fSSimon Glass if (ret) 47329a449fSSimon Glass return ret; 48329a449fSSimon Glass host->mmc->priv = host; 49cffe5d86SSimon Glass host->mmc->dev = dev; 50329a449fSSimon Glass upriv->mmc = host->mmc; 51d9ae52c8SMichal Simek 52329a449fSSimon Glass return sdhci_probe(dev); 53293eb33fSMichal Simek } 54d9ae52c8SMichal Simek 55d9ae52c8SMichal Simek static int arasan_sdhci_ofdata_to_platdata(struct udevice *dev) 56d9ae52c8SMichal Simek { 57d9ae52c8SMichal Simek struct sdhci_host *host = dev_get_priv(dev); 58d9ae52c8SMichal Simek 59cacd1d2fSMasahiro Yamada host->name = dev->name; 60d9ae52c8SMichal Simek host->ioaddr = (void *)dev_get_addr(dev); 61d9ae52c8SMichal Simek 62d9ae52c8SMichal Simek return 0; 63d9ae52c8SMichal Simek } 64d9ae52c8SMichal Simek 65329a449fSSimon Glass static int arasan_sdhci_bind(struct udevice *dev) 66329a449fSSimon Glass { 67329a449fSSimon Glass struct arasan_sdhci_plat *plat = dev_get_platdata(dev); 68329a449fSSimon Glass int ret; 69329a449fSSimon Glass 70329a449fSSimon Glass ret = sdhci_bind(dev, &plat->mmc, &plat->cfg); 71329a449fSSimon Glass if (ret) 72329a449fSSimon Glass return ret; 73329a449fSSimon Glass 74329a449fSSimon Glass return 0; 75329a449fSSimon Glass } 76329a449fSSimon Glass 77d9ae52c8SMichal Simek static const struct udevice_id arasan_sdhci_ids[] = { 78d9ae52c8SMichal Simek { .compatible = "arasan,sdhci-8.9a" }, 79d9ae52c8SMichal Simek { } 80d9ae52c8SMichal Simek }; 81d9ae52c8SMichal Simek 82d9ae52c8SMichal Simek U_BOOT_DRIVER(arasan_sdhci_drv) = { 83d9ae52c8SMichal Simek .name = "arasan_sdhci", 84d9ae52c8SMichal Simek .id = UCLASS_MMC, 85d9ae52c8SMichal Simek .of_match = arasan_sdhci_ids, 86d9ae52c8SMichal Simek .ofdata_to_platdata = arasan_sdhci_ofdata_to_platdata, 87329a449fSSimon Glass .ops = &sdhci_ops, 88329a449fSSimon Glass .bind = arasan_sdhci_bind, 89d9ae52c8SMichal Simek .probe = arasan_sdhci_probe, 90d9ae52c8SMichal Simek .priv_auto_alloc_size = sizeof(struct sdhci_host), 91329a449fSSimon Glass .platdata_auto_alloc_size = sizeof(struct arasan_sdhci_plat), 92d9ae52c8SMichal Simek }; 93