1 // SPDX-License-Identifier: GPL-2.0+ 2 /* 3 * Copyright (C) 2017, STMicroelectronics - All Rights Reserved 4 * Author(s): Patrice Chotard, <patrice.chotard@st.com> for STMicroelectronics. 5 */ 6 7 #include <common.h> 8 #include <dm.h> 9 #include <mmc.h> 10 #include <reset-uclass.h> 11 #include <sdhci.h> 12 #include <asm/arch/sdhci.h> 13 14 DECLARE_GLOBAL_DATA_PTR; 15 16 struct sti_sdhci_plat { 17 struct mmc_config cfg; 18 struct mmc mmc; 19 struct reset_ctl reset; 20 int instance; 21 }; 22 23 /** 24 * sti_mmc_core_config: configure the Arasan HC 25 * @dev : udevice 26 * 27 * Description: this function is to configure the Arasan MMC HC. 28 * This should be called when the system starts in case of, on the SoC, 29 * it is needed to configure the host controller. 30 * This happens on some SoCs, i.e. StiH410, where the MMC0 inside the flashSS 31 * needs to be configured as MMC 4.5 to have full capabilities. 32 * W/o these settings the SDHCI could configure and use the embedded controller 33 * with limited features. 34 */ 35 static int sti_mmc_core_config(struct udevice *dev) 36 { 37 struct sti_sdhci_plat *plat = dev_get_platdata(dev); 38 struct sdhci_host *host = dev_get_priv(dev); 39 int ret; 40 41 /* only MMC1 has a reset line */ 42 if (plat->instance) { 43 ret = reset_deassert(&plat->reset); 44 if (ret < 0) { 45 pr_err("MMC1 deassert failed: %d", ret); 46 return ret; 47 } 48 } 49 50 writel(STI_FLASHSS_MMC_CORE_CONFIG_1, 51 host->ioaddr + FLASHSS_MMC_CORE_CONFIG_1); 52 53 if (plat->instance) { 54 writel(STI_FLASHSS_MMC_CORE_CONFIG2, 55 host->ioaddr + FLASHSS_MMC_CORE_CONFIG_2); 56 writel(STI_FLASHSS_MMC_CORE_CONFIG3, 57 host->ioaddr + FLASHSS_MMC_CORE_CONFIG_3); 58 } else { 59 writel(STI_FLASHSS_SDCARD_CORE_CONFIG2, 60 host->ioaddr + FLASHSS_MMC_CORE_CONFIG_2); 61 writel(STI_FLASHSS_SDCARD_CORE_CONFIG3, 62 host->ioaddr + FLASHSS_MMC_CORE_CONFIG_3); 63 } 64 writel(STI_FLASHSS_MMC_CORE_CONFIG4, 65 host->ioaddr + FLASHSS_MMC_CORE_CONFIG_4); 66 67 return 0; 68 } 69 70 static int sti_sdhci_probe(struct udevice *dev) 71 { 72 struct mmc_uclass_priv *upriv = dev_get_uclass_priv(dev); 73 struct sti_sdhci_plat *plat = dev_get_platdata(dev); 74 struct sdhci_host *host = dev_get_priv(dev); 75 int ret; 76 77 /* 78 * identify current mmc instance, mmc1 has a reset, not mmc0 79 * MMC0 is wired to the SD slot, 80 * MMC1 is wired on the high speed connector 81 */ 82 ret = reset_get_by_index(dev, 0, &plat->reset); 83 if (!ret) 84 plat->instance = 1; 85 else 86 if (ret == -ENOENT) 87 plat->instance = 0; 88 else 89 return ret; 90 91 ret = sti_mmc_core_config(dev); 92 if (ret) 93 return ret; 94 95 host->quirks = SDHCI_QUIRK_WAIT_SEND_CMD | 96 SDHCI_QUIRK_32BIT_DMA_ADDR | 97 SDHCI_QUIRK_NO_HISPD_BIT; 98 99 host->host_caps = MMC_MODE_DDR_52MHz; 100 101 ret = sdhci_setup_cfg(&plat->cfg, host, 50000000, 400000); 102 if (ret) 103 return ret; 104 105 host->mmc = &plat->mmc; 106 host->mmc->priv = host; 107 host->mmc->dev = dev; 108 upriv->mmc = host->mmc; 109 110 return sdhci_probe(dev); 111 } 112 113 static int sti_sdhci_ofdata_to_platdata(struct udevice *dev) 114 { 115 struct sdhci_host *host = dev_get_priv(dev); 116 117 host->name = strdup(dev->name); 118 host->ioaddr = (void *)devfdt_get_addr(dev); 119 120 host->bus_width = fdtdec_get_int(gd->fdt_blob, dev_of_offset(dev), 121 "bus-width", 4); 122 123 return 0; 124 } 125 126 static int sti_sdhci_bind(struct udevice *dev) 127 { 128 struct sti_sdhci_plat *plat = dev_get_platdata(dev); 129 130 return sdhci_bind(dev, &plat->mmc, &plat->cfg); 131 } 132 133 static const struct udevice_id sti_sdhci_ids[] = { 134 { .compatible = "st,sdhci" }, 135 { } 136 }; 137 138 U_BOOT_DRIVER(sti_mmc) = { 139 .name = "sti_sdhci", 140 .id = UCLASS_MMC, 141 .of_match = sti_sdhci_ids, 142 .bind = sti_sdhci_bind, 143 .ops = &sdhci_ops, 144 .ofdata_to_platdata = sti_sdhci_ofdata_to_platdata, 145 .probe = sti_sdhci_probe, 146 .priv_auto_alloc_size = sizeof(struct sdhci_host), 147 .platdata_auto_alloc_size = sizeof(struct sti_sdhci_plat), 148 }; 149