1 /* 2 * (C) Copyright 2013 - 2015 Xilinx, Inc. 3 * 4 * Xilinx Zynq SD Host Controller Interface 5 * 6 * SPDX-License-Identifier: GPL-2.0+ 7 */ 8 9 #include <clk.h> 10 #include <common.h> 11 #include <dm.h> 12 #include <fdtdec.h> 13 #include <libfdt.h> 14 #include <malloc.h> 15 #include <sdhci.h> 16 17 DECLARE_GLOBAL_DATA_PTR; 18 19 #ifndef CONFIG_ZYNQ_SDHCI_MIN_FREQ 20 # define CONFIG_ZYNQ_SDHCI_MIN_FREQ 0 21 #endif 22 23 struct arasan_sdhci_plat { 24 struct mmc_config cfg; 25 struct mmc mmc; 26 unsigned int f_max; 27 }; 28 29 static int arasan_sdhci_probe(struct udevice *dev) 30 { 31 struct arasan_sdhci_plat *plat = dev_get_platdata(dev); 32 struct mmc_uclass_priv *upriv = dev_get_uclass_priv(dev); 33 struct sdhci_host *host = dev_get_priv(dev); 34 struct clk clk; 35 unsigned long clock; 36 int ret; 37 38 ret = clk_get_by_index(dev, 0, &clk); 39 if (ret < 0) { 40 dev_err(dev, "failed to get clock\n"); 41 return ret; 42 } 43 44 clock = clk_get_rate(&clk); 45 if (IS_ERR_VALUE(clock)) { 46 dev_err(dev, "failed to get rate\n"); 47 return clock; 48 } 49 debug("%s: CLK %ld\n", __func__, clock); 50 51 ret = clk_enable(&clk); 52 if (ret && ret != -ENOSYS) { 53 dev_err(dev, "failed to enable clock\n"); 54 return ret; 55 } 56 57 host->quirks = SDHCI_QUIRK_WAIT_SEND_CMD | 58 SDHCI_QUIRK_BROKEN_R1B; 59 60 #ifdef CONFIG_ZYNQ_HISPD_BROKEN 61 host->quirks |= SDHCI_QUIRK_NO_HISPD_BIT; 62 #endif 63 64 host->max_clk = clock; 65 66 ret = sdhci_setup_cfg(&plat->cfg, host, plat->f_max, 67 CONFIG_ZYNQ_SDHCI_MIN_FREQ); 68 host->mmc = &plat->mmc; 69 if (ret) 70 return ret; 71 host->mmc->priv = host; 72 host->mmc->dev = dev; 73 upriv->mmc = host->mmc; 74 75 return sdhci_probe(dev); 76 } 77 78 static int arasan_sdhci_ofdata_to_platdata(struct udevice *dev) 79 { 80 struct arasan_sdhci_plat *plat = dev_get_platdata(dev); 81 struct sdhci_host *host = dev_get_priv(dev); 82 83 host->name = dev->name; 84 host->ioaddr = (void *)devfdt_get_addr(dev); 85 86 plat->f_max = fdtdec_get_int(gd->fdt_blob, dev_of_offset(dev), 87 "max-frequency", CONFIG_ZYNQ_SDHCI_MAX_FREQ); 88 89 return 0; 90 } 91 92 static int arasan_sdhci_bind(struct udevice *dev) 93 { 94 struct arasan_sdhci_plat *plat = dev_get_platdata(dev); 95 96 return sdhci_bind(dev, &plat->mmc, &plat->cfg); 97 } 98 99 static const struct udevice_id arasan_sdhci_ids[] = { 100 { .compatible = "arasan,sdhci-8.9a" }, 101 { } 102 }; 103 104 U_BOOT_DRIVER(arasan_sdhci_drv) = { 105 .name = "arasan_sdhci", 106 .id = UCLASS_MMC, 107 .of_match = arasan_sdhci_ids, 108 .ofdata_to_platdata = arasan_sdhci_ofdata_to_platdata, 109 .ops = &sdhci_ops, 110 .bind = arasan_sdhci_bind, 111 .probe = arasan_sdhci_probe, 112 .priv_auto_alloc_size = sizeof(struct sdhci_host), 113 .platdata_auto_alloc_size = sizeof(struct arasan_sdhci_plat), 114 }; 115