sdhci-platform.c 3.6 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 rt_sdhci_ops sdhci_pltfm_ops = {
  12. .set_clock = rt_sdhci_set_clock,
  13. .set_bus_width = rt_sdhci_set_bus_width,
  14. .reset = rt_sdhci_reset,
  15. .set_uhs_signaling = rt_sdhci_set_uhs,
  16. };
  17. void rt_sdhci_get_property(struct rt_platform_device *pdev)
  18. {
  19. struct rt_device *dev = &pdev->parent;
  20. struct rt_sdhci_host *host = pdev->priv;
  21. struct rt_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 |= RT_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 |= RT_SDHCI_QUIRK_FORCE_1_BIT_DATA;
  27. if (rt_dm_dev_prop_read_bool(dev, "broken-cd"))
  28. host->quirks |= RT_SDHCI_QUIRK_BROKEN_CARD_DETECTION;
  29. if (rt_dm_dev_prop_read_bool(dev, "no-1-8-v"))
  30. host->quirks2 |= RT_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 rt_sdhci_host *rt_sdhci_pltfm_init(struct rt_platform_device *pdev,
  38. const struct rt_sdhci_pltfm_data *pdata,
  39. size_t priv_size)
  40. {
  41. struct rt_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 = rt_sdhci_alloc_host(dev,sizeof(struct rt_sdhci_pltfm_host) + 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 rt_sdhci_pltfm_init_and_add_host(struct rt_platform_device *pdev,
  76. const struct rt_sdhci_pltfm_data *pdata,
  77. size_t priv_size)
  78. {
  79. struct rt_sdhci_host *host;
  80. int ret = 0;
  81. host = rt_sdhci_pltfm_init(pdev, pdata, priv_size);
  82. if (!host)
  83. return -RT_ERROR;
  84. rt_sdhci_get_property(pdev);
  85. ret = rt_sdhci_init_host(host);
  86. if (ret)
  87. rt_sdhci_pltfm_free(pdev);
  88. return ret;
  89. }
  90. void rt_sdhci_pltfm_free(struct rt_platform_device *pdev)
  91. {
  92. struct rt_sdhci_host *host = pdev->priv;
  93. rt_sdhci_free_host(host);
  94. }
  95. void rt_sdhci_pltfm_remove(struct rt_platform_device *pdev)
  96. {
  97. struct rt_sdhci_host *host = pdev->priv;
  98. int dead = (readl(host->ioaddr + RT_SDHCI_INT_STATUS) == 0xffffffff);
  99. rt_sdhci_uninit_host(host, dead);
  100. rt_sdhci_pltfm_free(pdev);
  101. }