sdhci-platform.c 3.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125
  1. /*
  2. * Copyright (c) 2006-2024 RT-Thread Development Team
  3. *
  4. * SPDX-License-Identifier: Apache-2.0
  5. *
  6. * Change Logs:
  7. * Date Author Notes
  8. * 2024-08-16 zhujiale first version
  9. */
  10. #include "sdhci-platform.h"
  11. static const struct sdhci_ops sdhci_pltfm_ops = {
  12. .set_clock = sdhci_set_clock,
  13. .set_bus_width = sdhci_set_bus_width,
  14. .reset = sdhci_reset,
  15. .set_uhs_signaling = sdhci_set_uhs_signaling,
  16. };
  17. void sdhci_get_property(struct rt_platform_device *pdev)
  18. {
  19. struct rt_device *dev = &pdev->parent;
  20. struct sdhci_host *host = pdev->priv;
  21. struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
  22. rt_uint32_t bus_width;
  23. if (rt_dm_dev_prop_read_bool(dev, "sdhci,auto-cmd12"))
  24. host->quirks |= SDHCI_QUIRK_MULTIBLOCK_READ_ACMD12;
  25. if (rt_dm_dev_prop_read_bool(dev, "sdhci,1-bit-only") || (rt_dm_dev_prop_read_u32(dev, "bus-width", &bus_width) == 0 && bus_width == 1))
  26. host->quirks |= SDHCI_QUIRK_FORCE_1_BIT_DATA;
  27. if (rt_dm_dev_prop_read_bool(dev, "broken-cd"))
  28. host->quirks |= SDHCI_QUIRK_BROKEN_CARD_DETECTION;
  29. if (rt_dm_dev_prop_read_bool(dev, "no-1-8-v"))
  30. host->quirks2 |= SDHCI_QUIRK2_NO_1_8_V;
  31. rt_dm_dev_prop_read_u32(dev, "clock-frequency", &pltfm_host->clock);
  32. if (rt_dm_dev_prop_read_bool(dev, "keep-power-in-suspend"))
  33. host->mmc->pm_caps |= MMC_PM_KEEP_POWER;
  34. if (rt_dm_dev_prop_read_bool(dev, "wakeup-source") || rt_dm_dev_prop_read_bool(dev, "enable-sdio-wakeup")) /* legacy */
  35. host->mmc->pm_caps |= MMC_PM_WAKE_SDIO_IRQ;
  36. }
  37. struct sdhci_host *sdhci_pltfm_init(struct rt_platform_device *pdev,
  38. const struct sdhci_pltfm_data *pdata,
  39. size_t priv_size)
  40. {
  41. struct sdhci_host *host;
  42. struct rt_device *dev = &pdev->parent;
  43. void *ioaddr;
  44. int irq;
  45. ioaddr = rt_dm_dev_iomap(dev, 0);
  46. if (!ioaddr)
  47. {
  48. return RT_NULL;
  49. }
  50. irq = rt_dm_dev_get_irq(dev, 0);
  51. if (irq < 0)
  52. {
  53. return RT_NULL;
  54. }
  55. host = sdhci_alloc_host(dev, priv_size);
  56. if (!host)
  57. {
  58. return RT_NULL;
  59. }
  60. host->irq = irq;
  61. host->ioaddr = ioaddr;
  62. host->hw_name = rt_dm_dev_get_name(dev);
  63. if (pdata && pdata->ops)
  64. host->ops = pdata->ops;
  65. else
  66. host->ops = &sdhci_pltfm_ops;
  67. if (pdata)
  68. {
  69. host->quirks = pdata->quirks;
  70. host->quirks2 = pdata->quirks2;
  71. }
  72. pdev->priv = host;
  73. return host;
  74. }
  75. int sdhci_pltfm_init_and_add_host(struct rt_platform_device *pdev,
  76. const struct sdhci_pltfm_data *pdata,
  77. size_t priv_size)
  78. {
  79. struct sdhci_host *host;
  80. int ret = 0;
  81. host = sdhci_pltfm_init(pdev, pdata, priv_size);
  82. if (!host)
  83. return -RT_ERROR;
  84. sdhci_get_property(pdev);
  85. ret = sdhci_add_host(host);
  86. if (ret)
  87. sdhci_pltfm_free(pdev);
  88. return ret;
  89. }
  90. void sdhci_pltfm_free(struct rt_platform_device *pdev)
  91. {
  92. struct sdhci_host *host = pdev->priv;
  93. sdhci_free_host(host);
  94. }
  95. void sdhci_pltfm_remove(struct rt_platform_device *pdev)
  96. {
  97. struct sdhci_host *host = pdev->priv;
  98. int dead = (readl(host->ioaddr + SDHCI_INT_STATUS) == 0xffffffff);
  99. sdhci_remove_host(host, dead);
  100. sdhci_pltfm_free(pdev);
  101. }