sti_sdhci.c 3.7 KB

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