xref: /rk3399_rockchip-uboot/drivers/mmc/rockchip_dw_mmc.c (revision 337e8c3e6ab86cfcd2e9e165e9e2d88ea8d9d210)
1a8cb4fb5SSimon Glass /*
2a8cb4fb5SSimon Glass  * Copyright (c) 2013 Google, Inc
3a8cb4fb5SSimon Glass  *
4a8cb4fb5SSimon Glass  * SPDX-License-Identifier:	GPL-2.0+
5a8cb4fb5SSimon Glass  */
6a8cb4fb5SSimon Glass 
7a8cb4fb5SSimon Glass #include <common.h>
8a8cb4fb5SSimon Glass #include <clk.h>
9a8cb4fb5SSimon Glass #include <dm.h>
10bfeb443eSSimon Glass #include <dt-structs.h>
11a8cb4fb5SSimon Glass #include <dwmmc.h>
12a8cb4fb5SSimon Glass #include <errno.h>
13bfeb443eSSimon Glass #include <mapmem.h>
14e1efec4eSSimon Glass #include <pwrseq.h>
15a8cb4fb5SSimon Glass #include <syscon.h>
16e1efec4eSSimon Glass #include <asm/gpio.h>
17a8cb4fb5SSimon Glass #include <asm/arch/clock.h>
18a8cb4fb5SSimon Glass #include <asm/arch/periph.h>
19a8cb4fb5SSimon Glass #include <linux/err.h>
20a8cb4fb5SSimon Glass 
21a8cb4fb5SSimon Glass DECLARE_GLOBAL_DATA_PTR;
22a8cb4fb5SSimon Glass 
23f6e41d17SSimon Glass struct rockchip_mmc_plat {
24bfeb443eSSimon Glass #if CONFIG_IS_ENABLED(OF_PLATDATA)
25bfeb443eSSimon Glass 	struct dtd_rockchip_rk3288_dw_mshc dtplat;
26bfeb443eSSimon Glass #endif
27f6e41d17SSimon Glass 	struct mmc_config cfg;
28f6e41d17SSimon Glass 	struct mmc mmc;
29f6e41d17SSimon Glass };
30f6e41d17SSimon Glass 
31a8cb4fb5SSimon Glass struct rockchip_dwmmc_priv {
32135aa950SStephen Warren 	struct clk clk;
334455fdd9SZiyuan Xu 	struct clk sample_clk;
34a8cb4fb5SSimon Glass 	struct dwmci_host host;
356809b04fSSimon Glass 	int fifo_depth;
366809b04fSSimon Glass 	bool fifo_mode;
376809b04fSSimon Glass 	u32 minmax[2];
38a8cb4fb5SSimon Glass };
39a8cb4fb5SSimon Glass 
40a8cb4fb5SSimon Glass static uint rockchip_dwmmc_get_mmc_clk(struct dwmci_host *host, uint freq)
41a8cb4fb5SSimon Glass {
42a8cb4fb5SSimon Glass 	struct udevice *dev = host->priv;
43a8cb4fb5SSimon Glass 	struct rockchip_dwmmc_priv *priv = dev_get_priv(dev);
44a8cb4fb5SSimon Glass 	int ret;
45a8cb4fb5SSimon Glass 
4624527ef9SZiyuan Xu 	/*
4724527ef9SZiyuan Xu 	 * If DDR52 8bit mode(only emmc work in 8bit mode),
4824527ef9SZiyuan Xu 	 * divider must be set 1
4924527ef9SZiyuan Xu 	 */
5024527ef9SZiyuan Xu 	if (mmc_card_ddr52(host->mmc) && host->mmc->bus_width == 8)
5124527ef9SZiyuan Xu 		freq *= 2;
5224527ef9SZiyuan Xu 
53135aa950SStephen Warren 	ret = clk_set_rate(&priv->clk, freq);
54a8cb4fb5SSimon Glass 	if (ret < 0) {
55419b0801SKever Yang 		debug("%s: err=%d\n", __func__, ret);
56a8cb4fb5SSimon Glass 		return ret;
57a8cb4fb5SSimon Glass 	}
58a8cb4fb5SSimon Glass 
59a8cb4fb5SSimon Glass 	return freq;
60a8cb4fb5SSimon Glass }
61a8cb4fb5SSimon Glass 
62a8cb4fb5SSimon Glass static int rockchip_dwmmc_ofdata_to_platdata(struct udevice *dev)
63a8cb4fb5SSimon Glass {
64bfeb443eSSimon Glass #if !CONFIG_IS_ENABLED(OF_PLATDATA)
65a8cb4fb5SSimon Glass 	struct rockchip_dwmmc_priv *priv = dev_get_priv(dev);
66a8cb4fb5SSimon Glass 	struct dwmci_host *host = &priv->host;
67a8cb4fb5SSimon Glass 
68a8cb4fb5SSimon Glass 	host->name = dev->name;
69a821c4afSSimon Glass 	host->ioaddr = (void *)devfdt_get_addr(dev);
70fd1bf8dfSPhilipp Tomsich 	host->buswidth = dev_read_u32_default(dev, "bus-width", 4);
71a8cb4fb5SSimon Glass 	host->get_mmc_clk = rockchip_dwmmc_get_mmc_clk;
72a8cb4fb5SSimon Glass 	host->priv = dev;
73a8cb4fb5SSimon Glass 
74ace2198bShuang lin 	/* use non-removeable as sdcard and emmc as judgement */
75fd1bf8dfSPhilipp Tomsich 	if (dev_read_bool(dev, "non-removable"))
766579385bShuang lin 		host->dev_index = 0;
776579385bShuang lin 	else
78ace2198bShuang lin 		host->dev_index = 1;
79a8cb4fb5SSimon Glass 
80fd1bf8dfSPhilipp Tomsich 	priv->fifo_depth = dev_read_u32_default(dev, "fifo-depth", 0);
81fd1bf8dfSPhilipp Tomsich 
826809b04fSSimon Glass 	if (priv->fifo_depth < 0)
836809b04fSSimon Glass 		return -EINVAL;
84fd1bf8dfSPhilipp Tomsich 	priv->fifo_mode = dev_read_bool(dev, "fifo-mode");
85ff71f9acSPhilipp Tomsich 
86ff71f9acSPhilipp Tomsich 	/*
87ff71f9acSPhilipp Tomsich 	 * 'clock-freq-min-max' is deprecated
88ff71f9acSPhilipp Tomsich 	 * (see https://github.com/torvalds/linux/commit/b023030f10573de738bbe8df63d43acab64c9f7b)
89ff71f9acSPhilipp Tomsich 	 */
90fd1bf8dfSPhilipp Tomsich 	if (dev_read_u32_array(dev, "clock-freq-min-max", priv->minmax, 2)) {
91fd1bf8dfSPhilipp Tomsich 		int val = dev_read_u32_default(dev, "max-frequency", -EINVAL);
92ff71f9acSPhilipp Tomsich 
93ff71f9acSPhilipp Tomsich 		if (val < 0)
94ff71f9acSPhilipp Tomsich 			return val;
95ff71f9acSPhilipp Tomsich 
96ff71f9acSPhilipp Tomsich 		priv->minmax[0] = 400000;  /* 400 kHz */
97ff71f9acSPhilipp Tomsich 		priv->minmax[1] = val;
98ff71f9acSPhilipp Tomsich 	} else {
99ff71f9acSPhilipp Tomsich 		debug("%s: 'clock-freq-min-max' property was deprecated.\n",
100ff71f9acSPhilipp Tomsich 		      __func__);
101ff71f9acSPhilipp Tomsich 	}
102bfeb443eSSimon Glass #endif
103a8cb4fb5SSimon Glass 	return 0;
104a8cb4fb5SSimon Glass }
105a8cb4fb5SSimon Glass 
1064455fdd9SZiyuan Xu #define NUM_PHASES			270
1074455fdd9SZiyuan Xu #define TUNING_ITERATION_TO_PHASE(i)	(DIV_ROUND_UP((i) * 270, NUM_PHASES))
1084455fdd9SZiyuan Xu 
1094455fdd9SZiyuan Xu static int rockchip_dwmmc_execute_tuning(struct dwmci_host *host, u32 opcode)
1104455fdd9SZiyuan Xu {
1114455fdd9SZiyuan Xu 	int ret = 0;
1124455fdd9SZiyuan Xu 	int i;
1134455fdd9SZiyuan Xu 	bool v, prev_v = 0, first_v;
1144455fdd9SZiyuan Xu 	struct range_t {
1154455fdd9SZiyuan Xu 		int start;
1164455fdd9SZiyuan Xu 		int end; /* inclusive */
1174455fdd9SZiyuan Xu 	};
1184455fdd9SZiyuan Xu 	struct range_t *ranges;
1194455fdd9SZiyuan Xu 	unsigned int range_count = 0;
1204455fdd9SZiyuan Xu 	int longest_range_len = -1;
1214455fdd9SZiyuan Xu 	int longest_range = -1;
1224455fdd9SZiyuan Xu 	int middle_phase;
1234455fdd9SZiyuan Xu 	struct udevice *dev = host->priv;
1244455fdd9SZiyuan Xu 	struct rockchip_dwmmc_priv *priv = dev_get_priv(dev);
1254455fdd9SZiyuan Xu 	struct mmc *mmc = host->mmc;
1264455fdd9SZiyuan Xu 
1274455fdd9SZiyuan Xu 	if (IS_ERR(&priv->sample_clk))
1284455fdd9SZiyuan Xu 		return -EIO;
1294455fdd9SZiyuan Xu 
1304455fdd9SZiyuan Xu 	ranges = calloc(sizeof(*ranges), NUM_PHASES / 2 + 1);
1314455fdd9SZiyuan Xu 	if (!ranges)
1324455fdd9SZiyuan Xu 		return -ENOMEM;
1334455fdd9SZiyuan Xu 
1344455fdd9SZiyuan Xu 	/* Try each phase and extract good ranges */
1354455fdd9SZiyuan Xu 	for (i = 0; i < NUM_PHASES; ) {
1364455fdd9SZiyuan Xu 		clk_set_phase(&priv->sample_clk, TUNING_ITERATION_TO_PHASE(i));
1374455fdd9SZiyuan Xu 
1384455fdd9SZiyuan Xu 		v = !mmc_send_tuning(mmc, opcode);
1394455fdd9SZiyuan Xu 
1404455fdd9SZiyuan Xu 		if (i == 0)
1414455fdd9SZiyuan Xu 			first_v = v;
1424455fdd9SZiyuan Xu 
1434455fdd9SZiyuan Xu 		if ((!prev_v) && v) {
1444455fdd9SZiyuan Xu 			range_count++;
1454455fdd9SZiyuan Xu 			ranges[range_count - 1].start = i;
1464455fdd9SZiyuan Xu 		}
1474455fdd9SZiyuan Xu 		if (v) {
1484455fdd9SZiyuan Xu 			ranges[range_count - 1].end = i;
1494455fdd9SZiyuan Xu 			i++;
1504455fdd9SZiyuan Xu 		} else if (i == NUM_PHASES - 1) {
1514455fdd9SZiyuan Xu 			/* No extra skipping rules if we're at the end */
1524455fdd9SZiyuan Xu 			i++;
1534455fdd9SZiyuan Xu 		} else {
1544455fdd9SZiyuan Xu 			/*
1554455fdd9SZiyuan Xu 			 * No need to check too close to an invalid
1564455fdd9SZiyuan Xu 			 * one since testing bad phases is slow.  Skip
1574455fdd9SZiyuan Xu 			 * 20 degrees.
1584455fdd9SZiyuan Xu 			 */
1594455fdd9SZiyuan Xu 			i += DIV_ROUND_UP(20 * NUM_PHASES, NUM_PHASES);
1604455fdd9SZiyuan Xu 
1614455fdd9SZiyuan Xu 			/* Always test the last one */
1624455fdd9SZiyuan Xu 			if (i >= NUM_PHASES)
1634455fdd9SZiyuan Xu 				i = NUM_PHASES - 1;
1644455fdd9SZiyuan Xu 		}
1654455fdd9SZiyuan Xu 
1664455fdd9SZiyuan Xu 		prev_v = v;
1674455fdd9SZiyuan Xu 	}
1684455fdd9SZiyuan Xu 
1694455fdd9SZiyuan Xu 	if (range_count == 0) {
1704455fdd9SZiyuan Xu 		debug("All phases bad!");
1714455fdd9SZiyuan Xu 		ret = -EIO;
1724455fdd9SZiyuan Xu 		goto free;
1734455fdd9SZiyuan Xu 	}
1744455fdd9SZiyuan Xu 
1754455fdd9SZiyuan Xu 	/* wrap around case, merge the end points */
1764455fdd9SZiyuan Xu 	if ((range_count > 1) && first_v && v) {
1774455fdd9SZiyuan Xu 		ranges[0].start = ranges[range_count - 1].start;
1784455fdd9SZiyuan Xu 		range_count--;
1794455fdd9SZiyuan Xu 	}
1804455fdd9SZiyuan Xu 
1814455fdd9SZiyuan Xu 	if (ranges[0].start == 0 && ranges[0].end == NUM_PHASES - 1) {
1824455fdd9SZiyuan Xu 		clk_set_phase(&priv->sample_clk,
1834455fdd9SZiyuan Xu 			      TUNING_ITERATION_TO_PHASE(NUM_PHASES / 2));
1844455fdd9SZiyuan Xu 		debug("All phases work, using middle phase.\n");
1854455fdd9SZiyuan Xu 		goto free;
1864455fdd9SZiyuan Xu 	}
1874455fdd9SZiyuan Xu 
1884455fdd9SZiyuan Xu 	/* Find the longest range */
1894455fdd9SZiyuan Xu 	for (i = 0; i < range_count; i++) {
1904455fdd9SZiyuan Xu 		int len = (ranges[i].end - ranges[i].start + 1);
1914455fdd9SZiyuan Xu 
1924455fdd9SZiyuan Xu 		if (len < 0)
1934455fdd9SZiyuan Xu 			len += NUM_PHASES;
1944455fdd9SZiyuan Xu 
1954455fdd9SZiyuan Xu 		if (longest_range_len < len) {
1964455fdd9SZiyuan Xu 			longest_range_len = len;
1974455fdd9SZiyuan Xu 			longest_range = i;
1984455fdd9SZiyuan Xu 		}
1994455fdd9SZiyuan Xu 
2004455fdd9SZiyuan Xu 		debug("Good phase range %d-%d (%d len)\n",
2014455fdd9SZiyuan Xu 		      TUNING_ITERATION_TO_PHASE(ranges[i].start),
2024455fdd9SZiyuan Xu 		      TUNING_ITERATION_TO_PHASE(ranges[i].end), len);
2034455fdd9SZiyuan Xu 	}
2044455fdd9SZiyuan Xu 
2054455fdd9SZiyuan Xu 	printf("Best phase range %d-%d (%d len)\n",
2064455fdd9SZiyuan Xu 	       TUNING_ITERATION_TO_PHASE(ranges[longest_range].start),
2074455fdd9SZiyuan Xu 	       TUNING_ITERATION_TO_PHASE(ranges[longest_range].end),
2084455fdd9SZiyuan Xu 	       longest_range_len);
2094455fdd9SZiyuan Xu 
2104455fdd9SZiyuan Xu 	middle_phase = ranges[longest_range].start + longest_range_len / 2;
2114455fdd9SZiyuan Xu 	middle_phase %= NUM_PHASES;
2124455fdd9SZiyuan Xu 	debug("Successfully tuned phase to %d\n",
2134455fdd9SZiyuan Xu 	      TUNING_ITERATION_TO_PHASE(middle_phase));
2144455fdd9SZiyuan Xu 
2154455fdd9SZiyuan Xu 	clk_set_phase(&priv->sample_clk,
2164455fdd9SZiyuan Xu 		      TUNING_ITERATION_TO_PHASE(middle_phase));
2174455fdd9SZiyuan Xu 
2184455fdd9SZiyuan Xu free:
2194455fdd9SZiyuan Xu 	free(ranges);
2204455fdd9SZiyuan Xu 	return ret;
2214455fdd9SZiyuan Xu }
2224455fdd9SZiyuan Xu 
223a8cb4fb5SSimon Glass static int rockchip_dwmmc_probe(struct udevice *dev)
224a8cb4fb5SSimon Glass {
225f6e41d17SSimon Glass 	struct rockchip_mmc_plat *plat = dev_get_platdata(dev);
226a8cb4fb5SSimon Glass 	struct mmc_uclass_priv *upriv = dev_get_uclass_priv(dev);
227a8cb4fb5SSimon Glass 	struct rockchip_dwmmc_priv *priv = dev_get_priv(dev);
228a8cb4fb5SSimon Glass 	struct dwmci_host *host = &priv->host;
229e1efec4eSSimon Glass 	struct udevice *pwr_dev __maybe_unused;
230a8cb4fb5SSimon Glass 	int ret;
231a8cb4fb5SSimon Glass 
232bfeb443eSSimon Glass #if CONFIG_IS_ENABLED(OF_PLATDATA)
233bfeb443eSSimon Glass 	struct dtd_rockchip_rk3288_dw_mshc *dtplat = &plat->dtplat;
234bfeb443eSSimon Glass 
235bfeb443eSSimon Glass 	host->name = dev->name;
236bfeb443eSSimon Glass 	host->ioaddr = map_sysmem(dtplat->reg[0], dtplat->reg[1]);
237bfeb443eSSimon Glass 	host->buswidth = dtplat->bus_width;
238bfeb443eSSimon Glass 	host->get_mmc_clk = rockchip_dwmmc_get_mmc_clk;
2394455fdd9SZiyuan Xu 	host->execute_tuning = rockchip_dwmmc_execute_tuning;
240bfeb443eSSimon Glass 	host->priv = dev;
241bfeb443eSSimon Glass 	host->dev_index = 0;
242bfeb443eSSimon Glass 	priv->fifo_depth = dtplat->fifo_depth;
243bfeb443eSSimon Glass 	priv->fifo_mode = 0;
24480935298SKever Yang 	priv->minmax[0] = 400000;  /*  400 kHz */
24580935298SKever Yang 	priv->minmax[1] = dtplat->max_frequency;
246bfeb443eSSimon Glass 
247bfeb443eSSimon Glass 	ret = clk_get_by_index_platdata(dev, 0, dtplat->clocks, &priv->clk);
248bfeb443eSSimon Glass 	if (ret < 0)
249bfeb443eSSimon Glass 		return ret;
250bfeb443eSSimon Glass #else
251419b0801SKever Yang 	ret = clk_get_by_index(dev, 0, &priv->clk);
252898d6439SSimon Glass 	if (ret < 0)
253a8cb4fb5SSimon Glass 		return ret;
2544455fdd9SZiyuan Xu 	clk_get_by_name(dev, "ciu_sample", &priv->sample_clk);
2554455fdd9SZiyuan Xu 	host->execute_tuning = rockchip_dwmmc_execute_tuning;
256bfeb443eSSimon Glass #endif
25728637248Shuang lin 	host->fifoth_val = MSIZE(0x2) |
2586809b04fSSimon Glass 		RX_WMARK(priv->fifo_depth / 2 - 1) |
2596809b04fSSimon Glass 		TX_WMARK(priv->fifo_depth / 2);
26028637248Shuang lin 
2616809b04fSSimon Glass 	host->fifo_mode = priv->fifo_mode;
26228637248Shuang lin 
263bda599f7SShawn Lin #ifdef CONFIG_ROCKCHIP_RK3128
264bda599f7SShawn Lin 	host->stride_pio = true;
265bda599f7SShawn Lin #else
266bda599f7SShawn Lin 	host->stride_pio = false;
267bda599f7SShawn Lin #endif
268bda599f7SShawn Lin 
269e1efec4eSSimon Glass #ifdef CONFIG_PWRSEQ
270e1efec4eSSimon Glass 	/* Enable power if needed */
271e1efec4eSSimon Glass 	ret = uclass_get_device_by_phandle(UCLASS_PWRSEQ, dev, "mmc-pwrseq",
272e1efec4eSSimon Glass 					   &pwr_dev);
273e1efec4eSSimon Glass 	if (!ret) {
274e1efec4eSSimon Glass 		ret = pwrseq_set_power(pwr_dev, true);
275e1efec4eSSimon Glass 		if (ret)
276e1efec4eSSimon Glass 			return ret;
277e1efec4eSSimon Glass 	}
278e1efec4eSSimon Glass #endif
279e5113c33SJaehoon Chung 	dwmci_setup_cfg(&plat->cfg, host, priv->minmax[1], priv->minmax[0]);
280f6e41d17SSimon Glass 	host->mmc = &plat->mmc;
281f6e41d17SSimon Glass 	host->mmc->priv = &priv->host;
282cffe5d86SSimon Glass 	host->mmc->dev = dev;
283a8cb4fb5SSimon Glass 	upriv->mmc = host->mmc;
284a8cb4fb5SSimon Glass 
28542b37d8dSSimon Glass 	return dwmci_probe(dev);
286a8cb4fb5SSimon Glass }
287a8cb4fb5SSimon Glass 
288f6e41d17SSimon Glass static int rockchip_dwmmc_bind(struct udevice *dev)
289f6e41d17SSimon Glass {
290f6e41d17SSimon Glass 	struct rockchip_mmc_plat *plat = dev_get_platdata(dev);
291f6e41d17SSimon Glass 
29224f5aec3SMasahiro Yamada 	return dwmci_bind(dev, &plat->mmc, &plat->cfg);
293f6e41d17SSimon Glass }
294f6e41d17SSimon Glass 
295a8cb4fb5SSimon Glass static const struct udevice_id rockchip_dwmmc_ids[] = {
296a8cb4fb5SSimon Glass 	{ .compatible = "rockchip,rk3288-dw-mshc" },
297*337e8c3eSPaweł Jarosz 	{ .compatible = "rockchip,rk2928-dw-mshc" },
298a8cb4fb5SSimon Glass 	{ }
299a8cb4fb5SSimon Glass };
300a8cb4fb5SSimon Glass 
301a8cb4fb5SSimon Glass U_BOOT_DRIVER(rockchip_dwmmc_drv) = {
302bfeb443eSSimon Glass 	.name		= "rockchip_rk3288_dw_mshc",
303a8cb4fb5SSimon Glass 	.id		= UCLASS_MMC,
304a8cb4fb5SSimon Glass 	.of_match	= rockchip_dwmmc_ids,
305a8cb4fb5SSimon Glass 	.ofdata_to_platdata = rockchip_dwmmc_ofdata_to_platdata,
30642b37d8dSSimon Glass 	.ops		= &dm_dwmci_ops,
307f6e41d17SSimon Glass 	.bind		= rockchip_dwmmc_bind,
308a8cb4fb5SSimon Glass 	.probe		= rockchip_dwmmc_probe,
309a8cb4fb5SSimon Glass 	.priv_auto_alloc_size = sizeof(struct rockchip_dwmmc_priv),
310f6e41d17SSimon Glass 	.platdata_auto_alloc_size = sizeof(struct rockchip_mmc_plat),
311a8cb4fb5SSimon Glass };
312e1efec4eSSimon Glass 
313e1efec4eSSimon Glass #ifdef CONFIG_PWRSEQ
314e1efec4eSSimon Glass static int rockchip_dwmmc_pwrseq_set_power(struct udevice *dev, bool enable)
315e1efec4eSSimon Glass {
316e1efec4eSSimon Glass 	struct gpio_desc reset;
317e1efec4eSSimon Glass 	int ret;
318e1efec4eSSimon Glass 
319e1efec4eSSimon Glass 	ret = gpio_request_by_name(dev, "reset-gpios", 0, &reset, GPIOD_IS_OUT);
320e1efec4eSSimon Glass 	if (ret)
321e1efec4eSSimon Glass 		return ret;
322e1efec4eSSimon Glass 	dm_gpio_set_value(&reset, 1);
323e1efec4eSSimon Glass 	udelay(1);
324e1efec4eSSimon Glass 	dm_gpio_set_value(&reset, 0);
325e1efec4eSSimon Glass 	udelay(200);
326e1efec4eSSimon Glass 
327e1efec4eSSimon Glass 	return 0;
328e1efec4eSSimon Glass }
329e1efec4eSSimon Glass 
330e1efec4eSSimon Glass static const struct pwrseq_ops rockchip_dwmmc_pwrseq_ops = {
331e1efec4eSSimon Glass 	.set_power	= rockchip_dwmmc_pwrseq_set_power,
332e1efec4eSSimon Glass };
333e1efec4eSSimon Glass 
334e1efec4eSSimon Glass static const struct udevice_id rockchip_dwmmc_pwrseq_ids[] = {
335e1efec4eSSimon Glass 	{ .compatible = "mmc-pwrseq-emmc" },
336e1efec4eSSimon Glass 	{ }
337e1efec4eSSimon Glass };
338e1efec4eSSimon Glass 
339e1efec4eSSimon Glass U_BOOT_DRIVER(rockchip_dwmmc_pwrseq_drv) = {
340e1efec4eSSimon Glass 	.name		= "mmc_pwrseq_emmc",
341e1efec4eSSimon Glass 	.id		= UCLASS_PWRSEQ,
342e1efec4eSSimon Glass 	.of_match	= rockchip_dwmmc_pwrseq_ids,
343e1efec4eSSimon Glass 	.ops		= &rockchip_dwmmc_pwrseq_ops,
344e1efec4eSSimon Glass };
345e1efec4eSSimon Glass #endif
346