blob: c68a9157bfccf16e642cb237dc57e58ab59173dc [file] [log] [blame]
Tom Rini10e47792018-05-06 17:58:06 -04001// SPDX-License-Identifier: GPL-2.0+
Peter Griffinaf0c1be2015-07-30 18:55:22 +01002/*
3 * (C) Copyright 2015 Linaro
4 * peter.griffin <peter.griffin@linaro.org>
Peter Griffinaf0c1be2015-07-30 18:55:22 +01005 */
6
Yang Xiwen04259472024-02-01 22:05:42 +08007#include <clk.h>
Manivannan Sadhasivam6ad4f8c2018-12-27 19:04:04 +05308#include <dm.h>
Peter Griffinaf0c1be2015-07-30 18:55:22 +01009#include <dwmmc.h>
Manivannan Sadhasivam6ad4f8c2018-12-27 19:04:04 +053010#include <errno.h>
11#include <fdtdec.h>
Peter Griffinaf0c1be2015-07-30 18:55:22 +010012#include <malloc.h>
Yang Xiwen04259472024-02-01 22:05:42 +080013#include <reset.h>
Simon Glass3ba929a2020-10-30 21:38:53 -060014#include <asm/global_data.h>
Yang Xiwen04259472024-02-01 22:05:42 +080015#include <dm/device_compat.h>
Peter Griffinaf0c1be2015-07-30 18:55:22 +010016
Manivannan Sadhasivam6ad4f8c2018-12-27 19:04:04 +053017DECLARE_GLOBAL_DATA_PTR;
Peter Griffinaf0c1be2015-07-30 18:55:22 +010018
Yang Xiwen04259472024-02-01 22:05:42 +080019enum hi6220_dwmmc_clk_type {
20 HI6220_DWMMC_CLK_BIU,
21 HI6220_DWMMC_CLK_CIU,
22 HI6220_DWMMC_CLK_CNT,
23};
24
Manivannan Sadhasivam6ad4f8c2018-12-27 19:04:04 +053025struct hi6220_dwmmc_plat {
26 struct mmc_config cfg;
27 struct mmc mmc;
28};
Peter Griffinaf0c1be2015-07-30 18:55:22 +010029
Manivannan Sadhasivam6ad4f8c2018-12-27 19:04:04 +053030struct hi6220_dwmmc_priv_data {
31 struct dwmci_host host;
Yang Xiwen04259472024-02-01 22:05:42 +080032 struct clk *clks[HI6220_DWMMC_CLK_CNT];
33 struct reset_ctl_bulk rsts;
Manivannan Sadhasivam6ad4f8c2018-12-27 19:04:04 +053034};
Peter Griffinaf0c1be2015-07-30 18:55:22 +010035
Manivannan Sadhasivam759c45a2019-08-02 20:40:10 +053036struct hisi_mmc_data {
37 unsigned int clock;
38 bool use_fifo;
Yang Xiwene52d3c02024-02-01 22:05:44 +080039 u32 fifoth_val;
Manivannan Sadhasivam759c45a2019-08-02 20:40:10 +053040};
41
Simon Glassaad29ae2020-12-03 16:55:21 -070042static int hi6220_dwmmc_of_to_plat(struct udevice *dev)
Peter Griffinaf0c1be2015-07-30 18:55:22 +010043{
Manivannan Sadhasivam6ad4f8c2018-12-27 19:04:04 +053044 struct hi6220_dwmmc_priv_data *priv = dev_get_priv(dev);
45 struct dwmci_host *host = &priv->host;
Yang Xiwen04259472024-02-01 22:05:42 +080046 int ret;
Peter Griffinaf0c1be2015-07-30 18:55:22 +010047
Yang Xiwen04259472024-02-01 22:05:42 +080048 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);
54 }
55
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);
61 }
62
63 ret = reset_get_bulk(dev, &priv->rsts);
64 if (ret) {
65 dev_err(dev, "Failed to get resets(ret = %d)", ret);
66 return log_msg_ret("rst", ret);
67 }
68 }
Manivannan Sadhasivam6ad4f8c2018-12-27 19:04:04 +053069 host->name = dev->name;
Masahiro Yamada1096ae12020-07-17 14:36:46 +090070 host->ioaddr = dev_read_addr_ptr(dev);
Manivannan Sadhasivam6ad4f8c2018-12-27 19:04:04 +053071 host->buswidth = fdtdec_get_int(gd->fdt_blob, dev_of_offset(dev),
72 "bus-width", 4);
Peter Griffinaf0c1be2015-07-30 18:55:22 +010073
Manivannan Sadhasivam6ad4f8c2018-12-27 19:04:04 +053074 /* use non-removable property for differentiating SD card and eMMC */
75 if (dev_read_bool(dev, "non-removable"))
76 host->dev_index = 0;
77 else
78 host->dev_index = 1;
79
80 host->priv = priv;
81
Peter Griffinaf0c1be2015-07-30 18:55:22 +010082 return 0;
83}
84
Manivannan Sadhasivam6ad4f8c2018-12-27 19:04:04 +053085static int hi6220_dwmmc_probe(struct udevice *dev)
Peter Griffinaf0c1be2015-07-30 18:55:22 +010086{
Simon Glassfa20e932020-12-03 16:55:20 -070087 struct hi6220_dwmmc_plat *plat = dev_get_plat(dev);
Manivannan Sadhasivam6ad4f8c2018-12-27 19:04:04 +053088 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;
Manivannan Sadhasivam759c45a2019-08-02 20:40:10 +053091 struct hisi_mmc_data *mmc_data;
Yang Xiwen04259472024-02-01 22:05:42 +080092 int ret;
Manivannan Sadhasivam759c45a2019-08-02 20:40:10 +053093
94 mmc_data = (struct hisi_mmc_data *)dev_get_driver_data(dev);
Manivannan Sadhasivam6ad4f8c2018-12-27 19:04:04 +053095
Manivannan Sadhasivam759c45a2019-08-02 20:40:10 +053096 host->bus_hz = mmc_data->clock;
Yang Xiwen04259472024-02-01 22:05:42 +080097 if (CONFIG_IS_ENABLED(CLK) && CONFIG_IS_ENABLED(DM_RESET)) {
98 ret = clk_prepare_enable(priv->clks[HI6220_DWMMC_CLK_BIU]);
99 if (ret) {
100 dev_err(dev, "Failed to enable biu clock(ret = %d).\n", ret);
101 return log_msg_ret("clk", ret);
102 }
103
104 ret = clk_prepare_enable(priv->clks[HI6220_DWMMC_CLK_CIU]);
105 if (ret) {
106 dev_err(dev, "Failed to enable ciu clock(ret = %d).\n", ret);
107 return log_msg_ret("clk", ret);
108 }
109
110 ret = reset_deassert_bulk(&priv->rsts);
111 if (ret) {
112 dev_err(dev, "Failed to deassert resets(ret = %d).\n", ret);
113 return log_msg_ret("rst", ret);
114 }
115
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);
120 }
121 }
122 dev_dbg(dev, "bus clock rate: %d.\n", host->bus_hz);
Peter Griffinaf0c1be2015-07-30 18:55:22 +0100123
Manivannan Sadhasivam6ad4f8c2018-12-27 19:04:04 +0530124 dwmci_setup_cfg(&plat->cfg, host, host->bus_hz, 400000);
125 host->mmc = &plat->mmc;
Peter Griffinaf0c1be2015-07-30 18:55:22 +0100126
Manivannan Sadhasivam759c45a2019-08-02 20:40:10 +0530127 host->fifo_mode = mmc_data->use_fifo;
Yang Xiwene52d3c02024-02-01 22:05:44 +0800128 host->fifoth_val = mmc_data->fifoth_val;
Manivannan Sadhasivam6ad4f8c2018-12-27 19:04:04 +0530129 host->mmc->priv = &priv->host;
130 upriv->mmc = host->mmc;
131 host->mmc->dev = dev;
Peter Griffinaf0c1be2015-07-30 18:55:22 +0100132
Manivannan Sadhasivam6ad4f8c2018-12-27 19:04:04 +0530133 return dwmci_probe(dev);
Peter Griffinaf0c1be2015-07-30 18:55:22 +0100134}
Manivannan Sadhasivam6ad4f8c2018-12-27 19:04:04 +0530135
136static int hi6220_dwmmc_bind(struct udevice *dev)
137{
Simon Glassfa20e932020-12-03 16:55:20 -0700138 struct hi6220_dwmmc_plat *plat = dev_get_plat(dev);
Manivannan Sadhasivam6ad4f8c2018-12-27 19:04:04 +0530139 int ret;
140
141 ret = dwmci_bind(dev, &plat->mmc, &plat->cfg);
142 if (ret)
143 return ret;
144
145 return 0;
146}
147
Manivannan Sadhasivam759c45a2019-08-02 20:40:10 +0530148static const struct hisi_mmc_data hi3660_mmc_data = {
149 .clock = 3200000,
150 .use_fifo = true,
151};
152
153static const struct hisi_mmc_data hi6220_mmc_data = {
154 .clock = 50000000,
155 .use_fifo = false,
156};
157
Yang Xiwene52d3c02024-02-01 22:05:44 +0800158static const struct hisi_mmc_data hi3798mv2x_mmc_data = {
159 .clock = 50000000,
160 .use_fifo = false,
161 // FIFO depth is 256
162 .fifoth_val = MSIZE(4) | RX_WMARK(0x7f) | TX_WMARK(0x80),
163};
164
Manivannan Sadhasivam6ad4f8c2018-12-27 19:04:04 +0530165static const struct udevice_id hi6220_dwmmc_ids[] = {
Manivannan Sadhasivam759c45a2019-08-02 20:40:10 +0530166 { .compatible = "hisilicon,hi6220-dw-mshc",
167 .data = (ulong)&hi6220_mmc_data },
168 { .compatible = "hisilicon,hi3798cv200-dw-mshc",
169 .data = (ulong)&hi6220_mmc_data },
Yang Xiwen464c2be2023-04-01 19:17:34 +0800170 { .compatible = "hisilicon,hi3798mv200-dw-mshc",
Yang Xiwene52d3c02024-02-01 22:05:44 +0800171 .data = (ulong)&hi3798mv2x_mmc_data },
Manivannan Sadhasivam759c45a2019-08-02 20:40:10 +0530172 { .compatible = "hisilicon,hi3660-dw-mshc",
173 .data = (ulong)&hi3660_mmc_data },
Manivannan Sadhasivam6ad4f8c2018-12-27 19:04:04 +0530174 { }
175};
176
177U_BOOT_DRIVER(hi6220_dwmmc_drv) = {
178 .name = "hi6220_dwmmc",
179 .id = UCLASS_MMC,
180 .of_match = hi6220_dwmmc_ids,
Simon Glassaad29ae2020-12-03 16:55:21 -0700181 .of_to_plat = hi6220_dwmmc_of_to_plat,
Manivannan Sadhasivam6ad4f8c2018-12-27 19:04:04 +0530182 .ops = &dm_dwmci_ops,
183 .bind = hi6220_dwmmc_bind,
184 .probe = hi6220_dwmmc_probe,
Simon Glass8a2b47f2020-12-03 16:55:17 -0700185 .priv_auto = sizeof(struct hi6220_dwmmc_priv_data),
Simon Glass71fa5b42020-12-03 16:55:18 -0700186 .plat_auto = sizeof(struct hi6220_dwmmc_plat),
Manivannan Sadhasivam6ad4f8c2018-12-27 19:04:04 +0530187};