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 int ret; 31293eb33fSMichal Simek 32eddabd16SSiva Durga Prasad Paladugu host->quirks = SDHCI_QUIRK_WAIT_SEND_CMD | 33f9ec45d1SSiva Durga Prasad Paladugu SDHCI_QUIRK_BROKEN_R1B; 34b2156146SSiva Durga Prasad Paladugu 35b2156146SSiva Durga Prasad Paladugu #ifdef CONFIG_ZYNQ_HISPD_BROKEN 36b2156146SSiva Durga Prasad Paladugu host->quirks |= SDHCI_QUIRK_NO_HISPD_BIT; 37b2156146SSiva Durga Prasad Paladugu #endif 38b2156146SSiva Durga Prasad Paladugu 39*6d0e34bfSStefan Herbrechtsmeier host->max_clk = CONFIG_ZYNQ_SDHCI_MAX_FREQ; 40*6d0e34bfSStefan Herbrechtsmeier 41*6d0e34bfSStefan Herbrechtsmeier ret = sdhci_setup_cfg(&plat->cfg, host, 0, 4214bed52dSJaehoon Chung CONFIG_ZYNQ_SDHCI_MIN_FREQ); 43329a449fSSimon Glass host->mmc = &plat->mmc; 44329a449fSSimon Glass if (ret) 45329a449fSSimon Glass return ret; 46329a449fSSimon Glass host->mmc->priv = host; 47cffe5d86SSimon Glass host->mmc->dev = dev; 48329a449fSSimon Glass upriv->mmc = host->mmc; 49d9ae52c8SMichal Simek 50329a449fSSimon Glass return sdhci_probe(dev); 51293eb33fSMichal Simek } 52d9ae52c8SMichal Simek 53d9ae52c8SMichal Simek static int arasan_sdhci_ofdata_to_platdata(struct udevice *dev) 54d9ae52c8SMichal Simek { 55d9ae52c8SMichal Simek struct sdhci_host *host = dev_get_priv(dev); 56d9ae52c8SMichal Simek 57cacd1d2fSMasahiro Yamada host->name = dev->name; 58d9ae52c8SMichal Simek host->ioaddr = (void *)dev_get_addr(dev); 59d9ae52c8SMichal Simek 60d9ae52c8SMichal Simek return 0; 61d9ae52c8SMichal Simek } 62d9ae52c8SMichal Simek 63329a449fSSimon Glass static int arasan_sdhci_bind(struct udevice *dev) 64329a449fSSimon Glass { 65329a449fSSimon Glass struct arasan_sdhci_plat *plat = dev_get_platdata(dev); 66329a449fSSimon Glass 6724f5aec3SMasahiro Yamada return sdhci_bind(dev, &plat->mmc, &plat->cfg); 68329a449fSSimon Glass } 69329a449fSSimon Glass 70d9ae52c8SMichal Simek static const struct udevice_id arasan_sdhci_ids[] = { 71d9ae52c8SMichal Simek { .compatible = "arasan,sdhci-8.9a" }, 72d9ae52c8SMichal Simek { } 73d9ae52c8SMichal Simek }; 74d9ae52c8SMichal Simek 75d9ae52c8SMichal Simek U_BOOT_DRIVER(arasan_sdhci_drv) = { 76d9ae52c8SMichal Simek .name = "arasan_sdhci", 77d9ae52c8SMichal Simek .id = UCLASS_MMC, 78d9ae52c8SMichal Simek .of_match = arasan_sdhci_ids, 79d9ae52c8SMichal Simek .ofdata_to_platdata = arasan_sdhci_ofdata_to_platdata, 80329a449fSSimon Glass .ops = &sdhci_ops, 81329a449fSSimon Glass .bind = arasan_sdhci_bind, 82d9ae52c8SMichal Simek .probe = arasan_sdhci_probe, 83d9ae52c8SMichal Simek .priv_auto_alloc_size = sizeof(struct sdhci_host), 84329a449fSSimon Glass .platdata_auto_alloc_size = sizeof(struct arasan_sdhci_plat), 85d9ae52c8SMichal Simek }; 86