dev_sdhci_dm.c 3.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163
  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 "dev_sdhci_dm.h"
  11. static const struct rt_sdhci_ops sdhci_pltfm_ops =
  12. {
  13. .set_clock = rt_sdhci_set_clock,
  14. .set_bus_width = rt_sdhci_set_bus_width,
  15. .reset = rt_sdhci_reset,
  16. .set_uhs_signaling = rt_sdhci_set_uhs,
  17. };
  18. void rt_sdhci_get_property(struct rt_platform_device *pdev)
  19. {
  20. rt_uint32_t bus_width;
  21. struct rt_device *dev = &pdev->parent;
  22. struct rt_sdhci_host *host = pdev->priv;
  23. struct rt_sdhci_pltfm_host *pltfm_host = rt_sdhci_priv(host);
  24. if (rt_dm_dev_prop_read_bool(dev, "sdhci,auto-cmd12"))
  25. {
  26. host->quirks |= RT_SDHCI_QUIRK_MULTIBLOCK_READ_ACMD12;
  27. }
  28. if (rt_dm_dev_prop_read_bool(dev, "sdhci,1-bit-only") ||
  29. (!rt_dm_dev_prop_read_u32(dev, "bus-width", &bus_width) && bus_width == 1))
  30. {
  31. host->quirks |= RT_SDHCI_QUIRK_FORCE_1_BIT_DATA;
  32. }
  33. if (rt_dm_dev_prop_read_bool(dev, "broken-cd"))
  34. {
  35. host->quirks |= RT_SDHCI_QUIRK_BROKEN_CARD_DETECTION;
  36. }
  37. if (rt_dm_dev_prop_read_bool(dev, "no-1-8-v"))
  38. {
  39. host->quirks2 |= RT_SDHCI_QUIRK2_NO_1_8_V;
  40. }
  41. rt_dm_dev_prop_read_u32(dev, "clock-frequency", &pltfm_host->clock);
  42. if (rt_dm_dev_prop_read_bool(dev, "keep-power-in-suspend"))
  43. {
  44. host->mmc->pm_caps |= MMC_PM_KEEP_POWER;
  45. }
  46. if (rt_dm_dev_prop_read_bool(dev, "wakeup-source") ||
  47. rt_dm_dev_prop_read_bool(dev, "enable-sdio-wakeup")) /* legacy */
  48. {
  49. host->mmc->pm_caps |= MMC_PM_WAKE_SDIO_IRQ;
  50. }
  51. }
  52. struct rt_sdhci_host *rt_sdhci_pltfm_init(struct rt_platform_device *pdev,
  53. const struct rt_sdhci_pltfm_data *pdata,
  54. rt_size_t priv_size)
  55. {
  56. int irq;
  57. void *ioaddr;
  58. struct rt_sdhci_host *host;
  59. struct rt_device *dev = &pdev->parent;
  60. ioaddr = rt_dm_dev_iomap(dev, 0);
  61. if (!ioaddr)
  62. {
  63. return RT_NULL;
  64. }
  65. irq = rt_dm_dev_get_irq(dev, 0);
  66. if (irq < 0)
  67. {
  68. return RT_NULL;
  69. }
  70. host = rt_sdhci_alloc_host(dev, sizeof(struct rt_sdhci_pltfm_host) + priv_size);
  71. if (!host)
  72. {
  73. return RT_NULL;
  74. }
  75. host->irq = irq;
  76. host->ioaddr = ioaddr;
  77. host->hw_name = rt_dm_dev_get_name(dev);
  78. if (pdata && pdata->ops)
  79. {
  80. host->ops = pdata->ops;
  81. }
  82. else
  83. {
  84. host->ops = &sdhci_pltfm_ops;
  85. }
  86. if (pdata)
  87. {
  88. host->quirks = pdata->quirks;
  89. host->quirks2 = pdata->quirks2;
  90. }
  91. pdev->priv = host;
  92. return host;
  93. }
  94. rt_err_t rt_sdhci_pltfm_init_and_add_host(struct rt_platform_device *pdev,
  95. const struct rt_sdhci_pltfm_data *pdata,
  96. rt_size_t priv_size)
  97. {
  98. rt_err_t ret = RT_EOK;
  99. struct rt_sdhci_host *host;
  100. host = rt_sdhci_pltfm_init(pdev, pdata, priv_size);
  101. if (!host)
  102. {
  103. return -RT_ERROR;
  104. }
  105. rt_sdhci_get_property(pdev);
  106. ret = rt_sdhci_init_host(host);
  107. if (ret)
  108. {
  109. rt_sdhci_pltfm_free(pdev);
  110. }
  111. return ret;
  112. }
  113. void rt_sdhci_pltfm_free(struct rt_platform_device *pdev)
  114. {
  115. struct rt_sdhci_host *host = pdev->priv;
  116. rt_sdhci_free_host(host);
  117. }
  118. rt_err_t rt_sdhci_pltfm_remove(struct rt_platform_device *pdev)
  119. {
  120. rt_bool_t dead;
  121. struct rt_sdhci_host *host = pdev->priv;
  122. dead = (HWREG32(host->ioaddr + RT_SDHCI_INT_STATUS) == 0xffffffff);
  123. rt_sdhci_uninit_host(host, dead);
  124. rt_sdhci_pltfm_free(pdev);
  125. return RT_EOK;
  126. }
  127. rt_uint32_t rt_sdhci_pltfm_clk_get_max_clock(struct rt_sdhci_host *host)
  128. {
  129. struct rt_sdhci_pltfm_host *pltfm_host = rt_sdhci_priv(host);
  130. return rt_clk_get_rate(pltfm_host->clk);
  131. }