xref: /rk3399_rockchip-uboot/drivers/mmc/mmc-uclass.c (revision eede897e2782a90efc8190ff8424e216730ced7d)
1 /*
2  * Copyright (C) 2015 Google, Inc
3  * Written by Simon Glass <sjg@chromium.org>
4  *
5  * SPDX-License-Identifier:	GPL-2.0+
6  */
7 
8 #include <common.h>
9 #include <mmc.h>
10 #include <dm.h>
11 #include <dm/device-internal.h>
12 #include <dm/lists.h>
13 #include <dm/root.h>
14 #include "mmc_private.h"
15 
16 struct mmc *mmc_get_mmc_dev(struct udevice *dev)
17 {
18 	struct mmc_uclass_priv *upriv;
19 
20 	if (!device_active(dev))
21 		return NULL;
22 	upriv = dev_get_uclass_priv(dev);
23 	return upriv->mmc;
24 }
25 
26 #ifdef CONFIG_BLK
27 struct mmc *find_mmc_device(int dev_num)
28 {
29 	struct udevice *dev, *mmc_dev;
30 	int ret;
31 
32 	ret = blk_get_device(IF_TYPE_MMC, dev_num, &dev);
33 
34 	if (ret) {
35 #if !defined(CONFIG_SPL_BUILD) || defined(CONFIG_SPL_LIBCOMMON_SUPPORT)
36 		printf("MMC Device %d not found\n", dev_num);
37 #endif
38 		return NULL;
39 	}
40 
41 	mmc_dev = dev_get_parent(dev);
42 
43 	return mmc_get_mmc_dev(mmc_dev);
44 }
45 
46 int get_mmc_num(void)
47 {
48 	return max(blk_find_max_devnum(IF_TYPE_MMC), 0);
49 }
50 
51 int mmc_get_next_devnum(void)
52 {
53 	int ret;
54 
55 	ret = get_mmc_num();
56 	if (ret < 0)
57 		return ret;
58 
59 	return ret + 1;
60 }
61 
62 struct blk_desc *mmc_get_blk_desc(struct mmc *mmc)
63 {
64 	struct blk_desc *desc;
65 	struct udevice *dev;
66 
67 	device_find_first_child(mmc->dev, &dev);
68 	if (!dev)
69 		return NULL;
70 	desc = dev_get_uclass_platdata(dev);
71 
72 	return desc;
73 }
74 
75 void mmc_do_preinit(void)
76 {
77 	struct udevice *dev;
78 	struct uclass *uc;
79 	int ret;
80 
81 	ret = uclass_get(UCLASS_MMC, &uc);
82 	if (ret)
83 		return;
84 	uclass_foreach_dev(dev, uc) {
85 		struct mmc *m = mmc_get_mmc_dev(dev);
86 
87 		if (!m)
88 			continue;
89 #ifdef CONFIG_FSL_ESDHC_ADAPTER_IDENT
90 		mmc_set_preinit(m, 1);
91 #endif
92 		if (m->preinit)
93 			mmc_start_init(m);
94 	}
95 }
96 
97 #if !defined(CONFIG_SPL_BUILD) || defined(CONFIG_SPL_LIBCOMMON_SUPPORT)
98 void print_mmc_devices(char separator)
99 {
100 	struct udevice *dev;
101 	char *mmc_type;
102 	bool first = true;
103 
104 	for (uclass_first_device(UCLASS_MMC, &dev);
105 	     dev;
106 	     uclass_next_device(&dev)) {
107 		struct mmc *m = mmc_get_mmc_dev(dev);
108 
109 		if (!first) {
110 			printf("%c", separator);
111 			if (separator != '\n')
112 				puts(" ");
113 		}
114 		if (m->has_init)
115 			mmc_type = IS_SD(m) ? "SD" : "eMMC";
116 		else
117 			mmc_type = NULL;
118 
119 		printf("%s: %d", m->cfg->name, mmc_get_blk_desc(m)->devnum);
120 		if (mmc_type)
121 			printf(" (%s)", mmc_type);
122 	}
123 
124 	printf("\n");
125 }
126 
127 #else
128 void print_mmc_devices(char separator) { }
129 #endif
130 
131 int mmc_bind(struct udevice *dev, struct mmc *mmc, const struct mmc_config *cfg)
132 {
133 	struct blk_desc *bdesc;
134 	struct udevice *bdev;
135 	int ret;
136 
137 	ret = blk_create_devicef(dev, "mmc_blk", "blk", IF_TYPE_MMC, -1, 512,
138 				 0, &bdev);
139 	if (ret) {
140 		debug("Cannot create block device\n");
141 		return ret;
142 	}
143 	bdesc = dev_get_uclass_platdata(bdev);
144 	mmc->cfg = cfg;
145 	mmc->priv = dev;
146 
147 	/* the following chunk was from mmc_register() */
148 
149 	/* Setup dsr related values */
150 	mmc->dsr_imp = 0;
151 	mmc->dsr = 0xffffffff;
152 	/* Setup the universal parts of the block interface just once */
153 	bdesc->removable = 1;
154 
155 	/* setup initial part type */
156 	bdesc->part_type = cfg->part_type;
157 	mmc->dev = dev;
158 
159 	return 0;
160 }
161 
162 int mmc_unbind(struct udevice *dev)
163 {
164 	struct udevice *bdev;
165 
166 	device_find_first_child(dev, &bdev);
167 	if (bdev) {
168 		device_remove(bdev);
169 		device_unbind(bdev);
170 	}
171 
172 	return 0;
173 }
174 
175 static int mmc_select_hwpart(struct udevice *bdev, int hwpart)
176 {
177 	struct udevice *mmc_dev = dev_get_parent(bdev);
178 	struct mmc *mmc = mmc_get_mmc_dev(mmc_dev);
179 	struct blk_desc *desc = dev_get_uclass_platdata(bdev);
180 	int ret;
181 
182 	if (desc->hwpart == hwpart)
183 		return 0;
184 
185 	if (mmc->part_config == MMCPART_NOAVAILABLE)
186 		return -EMEDIUMTYPE;
187 
188 	ret = mmc_switch_part(mmc, hwpart);
189 	if (ret)
190 		return ret;
191 
192 	return 0;
193 }
194 
195 static const struct blk_ops mmc_blk_ops = {
196 	.read	= mmc_bread,
197 #ifndef CONFIG_SPL_BUILD
198 	.write	= mmc_bwrite,
199 #endif
200 	.select_hwpart	= mmc_select_hwpart,
201 };
202 
203 U_BOOT_DRIVER(mmc_blk) = {
204 	.name		= "mmc_blk",
205 	.id		= UCLASS_BLK,
206 	.ops		= &mmc_blk_ops,
207 };
208 #endif /* CONFIG_BLK */
209 
210 U_BOOT_DRIVER(mmc) = {
211 	.name	= "mmc",
212 	.id	= UCLASS_MMC,
213 };
214 
215 UCLASS_DRIVER(mmc) = {
216 	.id		= UCLASS_MMC,
217 	.name		= "mmc",
218 	.flags		= DM_UC_FLAG_SEQ_ALIAS,
219 	.per_device_auto_alloc_size = sizeof(struct mmc_uclass_priv),
220 };
221