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