xref: /OK3568_Linux_fs/u-boot/drivers/mmc/rockchip_dw_mmc.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1 /*
2  * Copyright (c) 2013 Google, Inc
3  *
4  * SPDX-License-Identifier:	GPL-2.0+
5  */
6 
7 #include <common.h>
8 #include <clk.h>
9 #include <dm.h>
10 #include <dt-structs.h>
11 #include <dwmmc.h>
12 #include <errno.h>
13 #include <mapmem.h>
14 #include <pwrseq.h>
15 #include <syscon.h>
16 #include <asm/gpio.h>
17 #include <asm/arch/clock.h>
18 #include <asm/arch/periph.h>
19 #include <linux/err.h>
20 
21 DECLARE_GLOBAL_DATA_PTR;
22 
23 struct rockchip_mmc_plat {
24 #if CONFIG_IS_ENABLED(OF_PLATDATA)
25 	struct dtd_rockchip_rk3288_dw_mshc dtplat;
26 #endif
27 	struct mmc_config cfg;
28 	struct mmc mmc;
29 };
30 
31 struct rockchip_dwmmc_priv {
32 	struct clk clk;
33 	struct clk sample_clk;
34 	struct dwmci_host host;
35 	int fifo_depth;
36 	bool fifo_mode;
37 	u32 minmax[2];
38 };
39 
40 #ifdef CONFIG_USING_KERNEL_DTB
board_mmc_dm_reinit(struct udevice * dev)41 int board_mmc_dm_reinit(struct udevice *dev)
42 {
43 	struct rockchip_dwmmc_priv *priv = dev_get_priv(dev);
44 
45 	if (!priv)
46 		return 0;
47 
48 	if (!memcmp(dev->name, "dwmmc", strlen("dwmmc")))
49 		return clk_get_by_index(dev, 0, &priv->clk);
50 	else
51 		return 0;
52 }
53 #endif
54 
55 #ifdef CONFIG_SPL_BUILD
mmc_gpio_init_direct(void)56 __weak void mmc_gpio_init_direct(void) {}
57 #endif
58 
rockchip_dwmmc_get_mmc_clk(struct dwmci_host * host,uint freq)59 static uint rockchip_dwmmc_get_mmc_clk(struct dwmci_host *host, uint freq)
60 {
61 	struct udevice *dev = host->priv;
62 	struct rockchip_dwmmc_priv *priv = dev_get_priv(dev);
63 	int ret;
64 
65 	/*
66 	 * If DDR52 8bit mode(only emmc work in 8bit mode),
67 	 * divider must be set 1
68 	 */
69 	if (mmc_card_ddr52(host->mmc) && host->mmc->bus_width == 8)
70 		freq *= 2;
71 
72 	ret = clk_set_rate(&priv->clk, freq);
73 	if (ret < 0) {
74 		debug("%s: err=%d\n", __func__, ret);
75 		return 0;
76 	}
77 
78 	return freq;
79 }
80 
rockchip_dwmmc_ofdata_to_platdata(struct udevice * dev)81 static int rockchip_dwmmc_ofdata_to_platdata(struct udevice *dev)
82 {
83 #if !CONFIG_IS_ENABLED(OF_PLATDATA)
84 	struct rockchip_dwmmc_priv *priv = dev_get_priv(dev);
85 	struct dwmci_host *host = &priv->host;
86 
87 	host->name = dev->name;
88 	host->ioaddr = dev_read_addr_ptr(dev);
89 	host->buswidth = dev_read_u32_default(dev, "bus-width", 4);
90 	host->get_mmc_clk = rockchip_dwmmc_get_mmc_clk;
91 	host->priv = dev;
92 
93 	/* use non-removeable as sdcard and emmc as judgement */
94 	if (dev_read_bool(dev, "non-removable"))
95 		host->dev_index = 0;
96 	else
97 		host->dev_index = 1;
98 
99 	priv->fifo_depth = dev_read_u32_default(dev, "fifo-depth", 0);
100 
101 	if (priv->fifo_depth < 0)
102 		return -EINVAL;
103 	priv->fifo_mode = dev_read_bool(dev, "fifo-mode");
104 
105 	/*
106 	 * 'clock-freq-min-max' is deprecated
107 	 * (see https://github.com/torvalds/linux/commit/b023030f10573de738bbe8df63d43acab64c9f7b)
108 	 */
109 	if (dev_read_u32_array(dev, "clock-freq-min-max", priv->minmax, 2)) {
110 		int val = dev_read_u32_default(dev, "max-frequency", -EINVAL);
111 
112 		if (val < 0)
113 			return val;
114 
115 		priv->minmax[0] = 400000;  /* 400 kHz */
116 		priv->minmax[1] = val;
117 	} else {
118 		debug("%s: 'clock-freq-min-max' property was deprecated.\n",
119 		      __func__);
120 	}
121 #endif
122 	return 0;
123 }
124 
125 #ifndef CONFIG_MMC_SIMPLE
rockchip_dwmmc_execute_tuning(struct dwmci_host * host,u32 opcode)126 static int rockchip_dwmmc_execute_tuning(struct dwmci_host *host, u32 opcode)
127 {
128 	int i = 0;
129 	int ret = -1;
130 	struct mmc *mmc = host->mmc;
131 	struct udevice *dev = host->priv;
132 	struct rockchip_dwmmc_priv *priv = dev_get_priv(dev);
133 
134 	if (IS_ERR(&priv->sample_clk))
135 		return -EIO;
136 
137 	if (mmc->default_phase > 0 && mmc->default_phase < 360) {
138 		ret = clk_set_phase(&priv->sample_clk, mmc->default_phase);
139 		if (ret)
140 			printf("set clk phase fail\n");
141 		else
142 			ret = mmc_send_tuning(mmc, opcode);
143 		mmc->default_phase = 0;
144 	}
145 	/*
146 	 * If use default_phase to tune successfully, return.
147 	 * Otherwise, use the othe phase to tune.
148 	 */
149 	if (!ret)
150 		return ret;
151 
152 	for (i = 0; i < 5; i++) {
153 		/* mmc->init_retry must be 0, 1, 2, 3 */
154 		if (mmc->init_retry == 4)
155 			mmc->init_retry = 0;
156 
157 		ret = clk_set_phase(&priv->sample_clk, 90 * mmc->init_retry);
158 		if (ret) {
159 			printf("set clk phase fail\n");
160 			break;
161 		}
162 		ret = mmc_send_tuning(mmc, opcode);
163 		debug("Tuning phase is %d, ret is %d\n", mmc->init_retry * 90, ret);
164 		mmc->init_retry++;
165 		if (!ret)
166 			break;
167 	}
168 
169 	return ret;
170 }
171 #else
rockchip_dwmmc_execute_tuning(struct dwmci_host * host,u32 opcode)172 static int rockchip_dwmmc_execute_tuning(struct dwmci_host *host, u32 opcode) { return 0; }
173 #endif
174 
rockchip_dwmmc_probe(struct udevice * dev)175 static int rockchip_dwmmc_probe(struct udevice *dev)
176 {
177 	struct rockchip_mmc_plat *plat = dev_get_platdata(dev);
178 	struct mmc_uclass_priv *upriv = dev_get_uclass_priv(dev);
179 	struct rockchip_dwmmc_priv *priv = dev_get_priv(dev);
180 	struct dwmci_host *host = &priv->host;
181 	struct udevice *pwr_dev __maybe_unused;
182 	int ret;
183 
184 #ifdef CONFIG_SPL_BUILD
185 	mmc_gpio_init_direct();
186 #endif
187 #if CONFIG_IS_ENABLED(OF_PLATDATA)
188 	struct dtd_rockchip_rk3288_dw_mshc *dtplat = &plat->dtplat;
189 
190 	host->name = dev->name;
191 	host->ioaddr = map_sysmem(dtplat->reg[0], dtplat->reg[1]);
192 	host->buswidth = dtplat->bus_width;
193 	host->get_mmc_clk = rockchip_dwmmc_get_mmc_clk;
194 	host->execute_tuning = rockchip_dwmmc_execute_tuning;
195 	host->priv = dev;
196 	host->dev_index = 0;
197 	priv->fifo_depth = dtplat->fifo_depth;
198 	priv->fifo_mode = 0;
199 	priv->minmax[0] = 400000;  /*  400 kHz */
200 	priv->minmax[1] = dtplat->max_frequency;
201 
202 	ret = clk_get_by_index_platdata(dev, 0, dtplat->clocks, &priv->clk);
203 	if (ret < 0)
204 		return ret;
205 #else
206 	ret = clk_get_by_index(dev, 0, &priv->clk);
207 	if (ret < 0)
208 		return ret;
209 
210 	ret = clk_get_by_name(dev, "ciu-sample", &priv->sample_clk);
211 	if (ret < 0)
212 		debug("MMC: sample clock not found, not support hs200!\n");
213 	host->execute_tuning = rockchip_dwmmc_execute_tuning;
214 #endif
215 	host->fifoth_val = MSIZE(DWMCI_MSIZE) |
216 		RX_WMARK(priv->fifo_depth / 2 - 1) |
217 		TX_WMARK(priv->fifo_depth / 2);
218 
219 	host->fifo_mode = priv->fifo_mode;
220 
221 #ifdef CONFIG_ROCKCHIP_RK3128
222 	host->stride_pio = true;
223 #else
224 	host->stride_pio = false;
225 #endif
226 
227 #ifdef CONFIG_PWRSEQ
228 	/* Enable power if needed */
229 	ret = uclass_get_device_by_phandle(UCLASS_PWRSEQ, dev, "mmc-pwrseq",
230 					   &pwr_dev);
231 	if (!ret) {
232 		ret = pwrseq_set_power(pwr_dev, true);
233 		if (ret)
234 			return ret;
235 	}
236 #endif
237 	dwmci_setup_cfg(&plat->cfg, host, priv->minmax[1], priv->minmax[0]);
238 	if (dev_read_bool(dev, "mmc-hs200-1_8v"))
239 		plat->cfg.host_caps |= MMC_MODE_HS200;
240 	plat->mmc.default_phase =
241 		dev_read_u32_default(dev, "default-sample-phase", 0);
242 #ifdef CONFIG_ROCKCHIP_RV1106
243 	if (!(ret < 0) && (&priv->sample_clk)) {
244 		ret = clk_set_phase(&priv->sample_clk, plat->mmc.default_phase);
245 		if (ret < 0)
246 			debug("MMC: can not set default phase!\n");
247 	}
248 #endif
249 
250 	plat->mmc.init_retry = 0;
251 	host->mmc = &plat->mmc;
252 	host->mmc->priv = &priv->host;
253 	host->mmc->dev = dev;
254 	upriv->mmc = host->mmc;
255 
256 	return dwmci_probe(dev);
257 }
258 
rockchip_dwmmc_bind(struct udevice * dev)259 static int rockchip_dwmmc_bind(struct udevice *dev)
260 {
261 	struct rockchip_mmc_plat *plat = dev_get_platdata(dev);
262 
263 	return dwmci_bind(dev, &plat->mmc, &plat->cfg);
264 }
265 
266 static const struct udevice_id rockchip_dwmmc_ids[] = {
267 	{ .compatible = "rockchip,rk3288-dw-mshc" },
268 	{ .compatible = "rockchip,rk2928-dw-mshc" },
269 	{ }
270 };
271 
272 U_BOOT_DRIVER(rockchip_dwmmc_drv) = {
273 	.name		= "rockchip_rk3288_dw_mshc",
274 	.id		= UCLASS_MMC,
275 	.of_match	= rockchip_dwmmc_ids,
276 	.ofdata_to_platdata = rockchip_dwmmc_ofdata_to_platdata,
277 	.ops		= &dm_dwmci_ops,
278 	.bind		= rockchip_dwmmc_bind,
279 	.probe		= rockchip_dwmmc_probe,
280 	.priv_auto_alloc_size = sizeof(struct rockchip_dwmmc_priv),
281 	.platdata_auto_alloc_size = sizeof(struct rockchip_mmc_plat),
282 };
283 
284 #ifdef CONFIG_PWRSEQ
rockchip_dwmmc_pwrseq_set_power(struct udevice * dev,bool enable)285 static int rockchip_dwmmc_pwrseq_set_power(struct udevice *dev, bool enable)
286 {
287 	struct gpio_desc reset;
288 	int ret;
289 
290 	ret = gpio_request_by_name(dev, "reset-gpios", 0, &reset, GPIOD_IS_OUT);
291 	if (ret)
292 		return ret;
293 	dm_gpio_set_value(&reset, 1);
294 	udelay(1);
295 	dm_gpio_set_value(&reset, 0);
296 	udelay(200);
297 
298 	return 0;
299 }
300 
301 static const struct pwrseq_ops rockchip_dwmmc_pwrseq_ops = {
302 	.set_power	= rockchip_dwmmc_pwrseq_set_power,
303 };
304 
305 static const struct udevice_id rockchip_dwmmc_pwrseq_ids[] = {
306 	{ .compatible = "mmc-pwrseq-emmc" },
307 	{ }
308 };
309 
310 U_BOOT_DRIVER(rockchip_dwmmc_pwrseq_drv) = {
311 	.name		= "mmc_pwrseq_emmc",
312 	.id		= UCLASS_PWRSEQ,
313 	.of_match	= rockchip_dwmmc_pwrseq_ids,
314 	.ops		= &rockchip_dwmmc_pwrseq_ops,
315 };
316 #endif
317