xref: /openbmc/u-boot/drivers/mmc/mmc-uclass.c (revision eede897e)
1e7ecf7cbSSimon Glass /*
2e7ecf7cbSSimon Glass  * Copyright (C) 2015 Google, Inc
3e7ecf7cbSSimon Glass  * Written by Simon Glass <sjg@chromium.org>
4e7ecf7cbSSimon Glass  *
5e7ecf7cbSSimon Glass  * SPDX-License-Identifier:	GPL-2.0+
6e7ecf7cbSSimon Glass  */
7e7ecf7cbSSimon Glass 
8e7ecf7cbSSimon Glass #include <common.h>
9e7ecf7cbSSimon Glass #include <mmc.h>
10e7ecf7cbSSimon Glass #include <dm.h>
11*eede897eSSimon Glass #include <dm/device-internal.h>
12e7ecf7cbSSimon Glass #include <dm/lists.h>
13e7ecf7cbSSimon Glass #include <dm/root.h>
14*eede897eSSimon Glass #include "mmc_private.h"
15e7ecf7cbSSimon Glass 
16e7ecf7cbSSimon Glass struct mmc *mmc_get_mmc_dev(struct udevice *dev)
17e7ecf7cbSSimon Glass {
18e7ecf7cbSSimon Glass 	struct mmc_uclass_priv *upriv;
19e7ecf7cbSSimon Glass 
20e7ecf7cbSSimon Glass 	if (!device_active(dev))
21e7ecf7cbSSimon Glass 		return NULL;
22e7ecf7cbSSimon Glass 	upriv = dev_get_uclass_priv(dev);
23e7ecf7cbSSimon Glass 	return upriv->mmc;
24e7ecf7cbSSimon Glass }
25e7ecf7cbSSimon Glass 
268ef761edSSimon Glass #ifdef CONFIG_BLK
278ef761edSSimon Glass struct mmc *find_mmc_device(int dev_num)
288ef761edSSimon Glass {
298ef761edSSimon Glass 	struct udevice *dev, *mmc_dev;
308ef761edSSimon Glass 	int ret;
318ef761edSSimon Glass 
328ef761edSSimon Glass 	ret = blk_get_device(IF_TYPE_MMC, dev_num, &dev);
338ef761edSSimon Glass 
348ef761edSSimon Glass 	if (ret) {
358ef761edSSimon Glass #if !defined(CONFIG_SPL_BUILD) || defined(CONFIG_SPL_LIBCOMMON_SUPPORT)
368ef761edSSimon Glass 		printf("MMC Device %d not found\n", dev_num);
378ef761edSSimon Glass #endif
388ef761edSSimon Glass 		return NULL;
398ef761edSSimon Glass 	}
408ef761edSSimon Glass 
418ef761edSSimon Glass 	mmc_dev = dev_get_parent(dev);
428ef761edSSimon Glass 
438ef761edSSimon Glass 	return mmc_get_mmc_dev(mmc_dev);
448ef761edSSimon Glass }
458ef761edSSimon Glass 
468ef761edSSimon Glass int get_mmc_num(void)
478ef761edSSimon Glass {
488ef761edSSimon Glass 	return max(blk_find_max_devnum(IF_TYPE_MMC), 0);
498ef761edSSimon Glass }
508ef761edSSimon Glass 
518ef761edSSimon Glass int mmc_get_next_devnum(void)
528ef761edSSimon Glass {
538ef761edSSimon Glass 	int ret;
548ef761edSSimon Glass 
558ef761edSSimon Glass 	ret = get_mmc_num();
568ef761edSSimon Glass 	if (ret < 0)
578ef761edSSimon Glass 		return ret;
588ef761edSSimon Glass 
598ef761edSSimon Glass 	return ret + 1;
608ef761edSSimon Glass }
618ef761edSSimon Glass 
628ef761edSSimon Glass struct blk_desc *mmc_get_blk_desc(struct mmc *mmc)
638ef761edSSimon Glass {
648ef761edSSimon Glass 	struct blk_desc *desc;
658ef761edSSimon Glass 	struct udevice *dev;
668ef761edSSimon Glass 
678ef761edSSimon Glass 	device_find_first_child(mmc->dev, &dev);
688ef761edSSimon Glass 	if (!dev)
698ef761edSSimon Glass 		return NULL;
708ef761edSSimon Glass 	desc = dev_get_uclass_platdata(dev);
718ef761edSSimon Glass 
728ef761edSSimon Glass 	return desc;
738ef761edSSimon Glass }
748ef761edSSimon Glass 
758ef761edSSimon Glass void mmc_do_preinit(void)
768ef761edSSimon Glass {
778ef761edSSimon Glass 	struct udevice *dev;
788ef761edSSimon Glass 	struct uclass *uc;
798ef761edSSimon Glass 	int ret;
808ef761edSSimon Glass 
818ef761edSSimon Glass 	ret = uclass_get(UCLASS_MMC, &uc);
828ef761edSSimon Glass 	if (ret)
838ef761edSSimon Glass 		return;
848ef761edSSimon Glass 	uclass_foreach_dev(dev, uc) {
858ef761edSSimon Glass 		struct mmc *m = mmc_get_mmc_dev(dev);
868ef761edSSimon Glass 
878ef761edSSimon Glass 		if (!m)
888ef761edSSimon Glass 			continue;
898ef761edSSimon Glass #ifdef CONFIG_FSL_ESDHC_ADAPTER_IDENT
908ef761edSSimon Glass 		mmc_set_preinit(m, 1);
918ef761edSSimon Glass #endif
928ef761edSSimon Glass 		if (m->preinit)
938ef761edSSimon Glass 			mmc_start_init(m);
948ef761edSSimon Glass 	}
958ef761edSSimon Glass }
968ef761edSSimon Glass 
978ef761edSSimon Glass #if !defined(CONFIG_SPL_BUILD) || defined(CONFIG_SPL_LIBCOMMON_SUPPORT)
988ef761edSSimon Glass void print_mmc_devices(char separator)
998ef761edSSimon Glass {
1008ef761edSSimon Glass 	struct udevice *dev;
1018ef761edSSimon Glass 	char *mmc_type;
1028ef761edSSimon Glass 	bool first = true;
1038ef761edSSimon Glass 
1048ef761edSSimon Glass 	for (uclass_first_device(UCLASS_MMC, &dev);
1058ef761edSSimon Glass 	     dev;
1068ef761edSSimon Glass 	     uclass_next_device(&dev)) {
1078ef761edSSimon Glass 		struct mmc *m = mmc_get_mmc_dev(dev);
1088ef761edSSimon Glass 
1098ef761edSSimon Glass 		if (!first) {
1108ef761edSSimon Glass 			printf("%c", separator);
1118ef761edSSimon Glass 			if (separator != '\n')
1128ef761edSSimon Glass 				puts(" ");
1138ef761edSSimon Glass 		}
1148ef761edSSimon Glass 		if (m->has_init)
1158ef761edSSimon Glass 			mmc_type = IS_SD(m) ? "SD" : "eMMC";
1168ef761edSSimon Glass 		else
1178ef761edSSimon Glass 			mmc_type = NULL;
1188ef761edSSimon Glass 
1198ef761edSSimon Glass 		printf("%s: %d", m->cfg->name, mmc_get_blk_desc(m)->devnum);
1208ef761edSSimon Glass 		if (mmc_type)
1218ef761edSSimon Glass 			printf(" (%s)", mmc_type);
1228ef761edSSimon Glass 	}
1238ef761edSSimon Glass 
1248ef761edSSimon Glass 	printf("\n");
1258ef761edSSimon Glass }
1268ef761edSSimon Glass 
1278ef761edSSimon Glass #else
1288ef761edSSimon Glass void print_mmc_devices(char separator) { }
1298ef761edSSimon Glass #endif
130*eede897eSSimon Glass 
131*eede897eSSimon Glass int mmc_bind(struct udevice *dev, struct mmc *mmc, const struct mmc_config *cfg)
132*eede897eSSimon Glass {
133*eede897eSSimon Glass 	struct blk_desc *bdesc;
134*eede897eSSimon Glass 	struct udevice *bdev;
135*eede897eSSimon Glass 	int ret;
136*eede897eSSimon Glass 
137*eede897eSSimon Glass 	ret = blk_create_devicef(dev, "mmc_blk", "blk", IF_TYPE_MMC, -1, 512,
138*eede897eSSimon Glass 				 0, &bdev);
139*eede897eSSimon Glass 	if (ret) {
140*eede897eSSimon Glass 		debug("Cannot create block device\n");
141*eede897eSSimon Glass 		return ret;
142*eede897eSSimon Glass 	}
143*eede897eSSimon Glass 	bdesc = dev_get_uclass_platdata(bdev);
144*eede897eSSimon Glass 	mmc->cfg = cfg;
145*eede897eSSimon Glass 	mmc->priv = dev;
146*eede897eSSimon Glass 
147*eede897eSSimon Glass 	/* the following chunk was from mmc_register() */
148*eede897eSSimon Glass 
149*eede897eSSimon Glass 	/* Setup dsr related values */
150*eede897eSSimon Glass 	mmc->dsr_imp = 0;
151*eede897eSSimon Glass 	mmc->dsr = 0xffffffff;
152*eede897eSSimon Glass 	/* Setup the universal parts of the block interface just once */
153*eede897eSSimon Glass 	bdesc->removable = 1;
154*eede897eSSimon Glass 
155*eede897eSSimon Glass 	/* setup initial part type */
156*eede897eSSimon Glass 	bdesc->part_type = cfg->part_type;
157*eede897eSSimon Glass 	mmc->dev = dev;
158*eede897eSSimon Glass 
159*eede897eSSimon Glass 	return 0;
160*eede897eSSimon Glass }
161*eede897eSSimon Glass 
162*eede897eSSimon Glass int mmc_unbind(struct udevice *dev)
163*eede897eSSimon Glass {
164*eede897eSSimon Glass 	struct udevice *bdev;
165*eede897eSSimon Glass 
166*eede897eSSimon Glass 	device_find_first_child(dev, &bdev);
167*eede897eSSimon Glass 	if (bdev) {
168*eede897eSSimon Glass 		device_remove(bdev);
169*eede897eSSimon Glass 		device_unbind(bdev);
170*eede897eSSimon Glass 	}
171*eede897eSSimon Glass 
172*eede897eSSimon Glass 	return 0;
173*eede897eSSimon Glass }
174*eede897eSSimon Glass 
175*eede897eSSimon Glass static int mmc_select_hwpart(struct udevice *bdev, int hwpart)
176*eede897eSSimon Glass {
177*eede897eSSimon Glass 	struct udevice *mmc_dev = dev_get_parent(bdev);
178*eede897eSSimon Glass 	struct mmc *mmc = mmc_get_mmc_dev(mmc_dev);
179*eede897eSSimon Glass 	struct blk_desc *desc = dev_get_uclass_platdata(bdev);
180*eede897eSSimon Glass 	int ret;
181*eede897eSSimon Glass 
182*eede897eSSimon Glass 	if (desc->hwpart == hwpart)
183*eede897eSSimon Glass 		return 0;
184*eede897eSSimon Glass 
185*eede897eSSimon Glass 	if (mmc->part_config == MMCPART_NOAVAILABLE)
186*eede897eSSimon Glass 		return -EMEDIUMTYPE;
187*eede897eSSimon Glass 
188*eede897eSSimon Glass 	ret = mmc_switch_part(mmc, hwpart);
189*eede897eSSimon Glass 	if (ret)
190*eede897eSSimon Glass 		return ret;
191*eede897eSSimon Glass 
192*eede897eSSimon Glass 	return 0;
193*eede897eSSimon Glass }
194*eede897eSSimon Glass 
195*eede897eSSimon Glass static const struct blk_ops mmc_blk_ops = {
196*eede897eSSimon Glass 	.read	= mmc_bread,
197*eede897eSSimon Glass #ifndef CONFIG_SPL_BUILD
198*eede897eSSimon Glass 	.write	= mmc_bwrite,
199*eede897eSSimon Glass #endif
200*eede897eSSimon Glass 	.select_hwpart	= mmc_select_hwpart,
201*eede897eSSimon Glass };
202*eede897eSSimon Glass 
203*eede897eSSimon Glass U_BOOT_DRIVER(mmc_blk) = {
204*eede897eSSimon Glass 	.name		= "mmc_blk",
205*eede897eSSimon Glass 	.id		= UCLASS_BLK,
206*eede897eSSimon Glass 	.ops		= &mmc_blk_ops,
207*eede897eSSimon Glass };
2088ef761edSSimon Glass #endif /* CONFIG_BLK */
2098ef761edSSimon Glass 
210e7ecf7cbSSimon Glass U_BOOT_DRIVER(mmc) = {
211e7ecf7cbSSimon Glass 	.name	= "mmc",
212e7ecf7cbSSimon Glass 	.id	= UCLASS_MMC,
213e7ecf7cbSSimon Glass };
214e7ecf7cbSSimon Glass 
215e7ecf7cbSSimon Glass UCLASS_DRIVER(mmc) = {
216e7ecf7cbSSimon Glass 	.id		= UCLASS_MMC,
217e7ecf7cbSSimon Glass 	.name		= "mmc",
218e7ecf7cbSSimon Glass 	.flags		= DM_UC_FLAG_SEQ_ALIAS,
219e7ecf7cbSSimon Glass 	.per_device_auto_alloc_size = sizeof(struct mmc_uclass_priv),
220e7ecf7cbSSimon Glass };
221