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