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