1 // SPDX-License-Identifier: GPL-2.0+
3 * (C) Copyright 2015 Linaro
14 #include <asm/global_data.h>
15 #include <dm/device_compat.h>
17 DECLARE_GLOBAL_DATA_PTR;
19 enum hi6220_dwmmc_clk_type {
25 struct hi6220_dwmmc_plat {
26 struct mmc_config cfg;
30 struct hi6220_dwmmc_priv_data {
31 struct dwmci_host host;
32 struct clk *clks[HI6220_DWMMC_CLK_CNT];
33 struct reset_ctl_bulk rsts;
36 struct hisi_mmc_data {
42 static int hi6220_dwmmc_of_to_plat(struct udevice *dev)
44 struct hi6220_dwmmc_priv_data *priv = dev_get_priv(dev);
45 struct dwmci_host *host = &priv->host;
48 if (CONFIG_IS_ENABLED(CLK) && CONFIG_IS_ENABLED(DM_RESET)) {
49 priv->clks[HI6220_DWMMC_CLK_BIU] = devm_clk_get(dev, "biu");
50 if (IS_ERR(priv->clks[HI6220_DWMMC_CLK_BIU])) {
51 ret = PTR_ERR(priv->clks[HI6220_DWMMC_CLK_BIU]);
52 dev_err(dev, "Failed to get BIU clock(ret = %d).\n", ret);
53 return log_msg_ret("clk", ret);
56 priv->clks[HI6220_DWMMC_CLK_CIU] = devm_clk_get(dev, "ciu");
57 if (IS_ERR(priv->clks[HI6220_DWMMC_CLK_CIU])) {
58 ret = PTR_ERR(priv->clks[HI6220_DWMMC_CLK_CIU]);
59 dev_err(dev, "Failed to get CIU clock(ret = %d).\n", ret);
60 return log_msg_ret("clk", ret);
63 ret = reset_get_bulk(dev, &priv->rsts);
65 dev_err(dev, "Failed to get resets(ret = %d)", ret);
66 return log_msg_ret("rst", ret);
69 host->name = dev->name;
70 host->ioaddr = dev_read_addr_ptr(dev);
71 host->buswidth = fdtdec_get_int(gd->fdt_blob, dev_of_offset(dev),
74 /* use non-removable property for differentiating SD card and eMMC */
75 if (dev_read_bool(dev, "non-removable"))
85 static int hi6220_dwmmc_probe(struct udevice *dev)
87 struct hi6220_dwmmc_plat *plat = dev_get_plat(dev);
88 struct mmc_uclass_priv *upriv = dev_get_uclass_priv(dev);
89 struct hi6220_dwmmc_priv_data *priv = dev_get_priv(dev);
90 struct dwmci_host *host = &priv->host;
91 struct hisi_mmc_data *mmc_data;
94 mmc_data = (struct hisi_mmc_data *)dev_get_driver_data(dev);
96 host->bus_hz = mmc_data->clock;
97 if (CONFIG_IS_ENABLED(CLK) && CONFIG_IS_ENABLED(DM_RESET)) {
98 ret = clk_prepare_enable(priv->clks[HI6220_DWMMC_CLK_BIU]);
100 dev_err(dev, "Failed to enable biu clock(ret = %d).\n", ret);
101 return log_msg_ret("clk", ret);
104 ret = clk_prepare_enable(priv->clks[HI6220_DWMMC_CLK_CIU]);
106 dev_err(dev, "Failed to enable ciu clock(ret = %d).\n", ret);
107 return log_msg_ret("clk", ret);
110 ret = reset_deassert_bulk(&priv->rsts);
112 dev_err(dev, "Failed to deassert resets(ret = %d).\n", ret);
113 return log_msg_ret("rst", ret);
116 host->bus_hz = clk_get_rate(priv->clks[HI6220_DWMMC_CLK_CIU]);
117 if (host->bus_hz <= 0) {
118 dev_err(dev, "Failed to get ciu clock rate(ret = %d).\n", ret);
119 return log_msg_ret("clk", ret);
122 dev_dbg(dev, "bus clock rate: %d.\n", host->bus_hz);
124 dwmci_setup_cfg(&plat->cfg, host, host->bus_hz, 400000);
125 host->mmc = &plat->mmc;
127 host->fifo_mode = mmc_data->use_fifo;
128 host->fifoth_val = mmc_data->fifoth_val;
129 host->mmc->priv = &priv->host;
130 upriv->mmc = host->mmc;
131 host->mmc->dev = dev;
133 return dwmci_probe(dev);
136 static int hi6220_dwmmc_bind(struct udevice *dev)
138 struct hi6220_dwmmc_plat *plat = dev_get_plat(dev);
141 ret = dwmci_bind(dev, &plat->mmc, &plat->cfg);
148 static const struct hisi_mmc_data hi3660_mmc_data = {
153 static const struct hisi_mmc_data hi6220_mmc_data = {
158 static const struct hisi_mmc_data hi3798mv2x_mmc_data = {
162 .fifoth_val = MSIZE(4) | RX_WMARK(0x7f) | TX_WMARK(0x80),
165 static const struct udevice_id hi6220_dwmmc_ids[] = {
166 { .compatible = "hisilicon,hi6220-dw-mshc",
167 .data = (ulong)&hi6220_mmc_data },
168 { .compatible = "hisilicon,hi3798cv200-dw-mshc",
169 .data = (ulong)&hi6220_mmc_data },
170 { .compatible = "hisilicon,hi3798mv200-dw-mshc",
171 .data = (ulong)&hi3798mv2x_mmc_data },
172 { .compatible = "hisilicon,hi3660-dw-mshc",
173 .data = (ulong)&hi3660_mmc_data },
177 U_BOOT_DRIVER(hi6220_dwmmc_drv) = {
178 .name = "hi6220_dwmmc",
180 .of_match = hi6220_dwmmc_ids,
181 .of_to_plat = hi6220_dwmmc_of_to_plat,
182 .ops = &dm_dwmci_ops,
183 .bind = hi6220_dwmmc_bind,
184 .probe = hi6220_dwmmc_probe,
185 .priv_auto = sizeof(struct hi6220_dwmmc_priv_data),
186 .plat_auto = sizeof(struct hi6220_dwmmc_plat),