xref: /rk3399_rockchip-uboot/drivers/mmc/mmc_legacy.c (revision 1fdafb2e3dfecdc4129a8062ad25b1adb32b0efb)
1c40fdca6SSimon Glass /*
2c40fdca6SSimon Glass  * Copyright (C) 2016 Google, Inc
3c40fdca6SSimon Glass  * Written by Simon Glass <sjg@chromium.org>
4c40fdca6SSimon Glass  *
5c40fdca6SSimon Glass  * SPDX-License-Identifier:	GPL-2.0+
6c40fdca6SSimon Glass  */
7c40fdca6SSimon Glass 
8c40fdca6SSimon Glass #include <common.h>
95aed4cbbSSimon Glass #include <malloc.h>
10c40fdca6SSimon Glass #include <mmc.h>
115aed4cbbSSimon Glass #include "mmc_private.h"
12c40fdca6SSimon Glass 
13c40fdca6SSimon Glass static struct list_head mmc_devices;
14c40fdca6SSimon Glass static int cur_dev_num = -1;
15c40fdca6SSimon Glass 
16b5b838f1SMarek Vasut #if !CONFIG_IS_ENABLED(MMC_TINY)
find_mmc_device(int dev_num)17c40fdca6SSimon Glass struct mmc *find_mmc_device(int dev_num)
18c40fdca6SSimon Glass {
19c40fdca6SSimon Glass 	struct mmc *m;
20c40fdca6SSimon Glass 	struct list_head *entry;
21c40fdca6SSimon Glass 
22c40fdca6SSimon Glass 	list_for_each(entry, &mmc_devices) {
23c40fdca6SSimon Glass 		m = list_entry(entry, struct mmc, link);
24c40fdca6SSimon Glass 
25c40fdca6SSimon Glass 		if (m->block_dev.devnum == dev_num)
26c40fdca6SSimon Glass 			return m;
27c40fdca6SSimon Glass 	}
28c40fdca6SSimon Glass 
29c40fdca6SSimon Glass #if !defined(CONFIG_SPL_BUILD) || defined(CONFIG_SPL_LIBCOMMON_SUPPORT)
30c40fdca6SSimon Glass 	printf("MMC Device %d not found\n", dev_num);
31c40fdca6SSimon Glass #endif
32c40fdca6SSimon Glass 
33c40fdca6SSimon Glass 	return NULL;
34c40fdca6SSimon Glass }
35c40fdca6SSimon Glass 
mmc_get_next_devnum(void)36c40fdca6SSimon Glass int mmc_get_next_devnum(void)
37c40fdca6SSimon Glass {
38c40fdca6SSimon Glass 	return cur_dev_num++;
39c40fdca6SSimon Glass }
40c40fdca6SSimon Glass 
mmc_get_blk_desc(struct mmc * mmc)41c40fdca6SSimon Glass struct blk_desc *mmc_get_blk_desc(struct mmc *mmc)
42c40fdca6SSimon Glass {
43c40fdca6SSimon Glass 	return &mmc->block_dev;
44c40fdca6SSimon Glass }
45c40fdca6SSimon Glass 
get_mmc_num(void)46c40fdca6SSimon Glass int get_mmc_num(void)
47c40fdca6SSimon Glass {
48c40fdca6SSimon Glass 	return cur_dev_num;
49c40fdca6SSimon Glass }
50c40fdca6SSimon Glass 
mmc_do_preinit(void)51c40fdca6SSimon Glass void mmc_do_preinit(void)
52c40fdca6SSimon Glass {
53c40fdca6SSimon Glass 	struct mmc *m;
54c40fdca6SSimon Glass 	struct list_head *entry;
55c40fdca6SSimon Glass 
56c40fdca6SSimon Glass 	list_for_each(entry, &mmc_devices) {
57c40fdca6SSimon Glass 		m = list_entry(entry, struct mmc, link);
58c40fdca6SSimon Glass 
59c40fdca6SSimon Glass #ifdef CONFIG_FSL_ESDHC_ADAPTER_IDENT
60c40fdca6SSimon Glass 		mmc_set_preinit(m, 1);
61c40fdca6SSimon Glass #endif
62c40fdca6SSimon Glass 		if (m->preinit)
63c40fdca6SSimon Glass 			mmc_start_init(m);
64c40fdca6SSimon Glass 	}
65c40fdca6SSimon Glass }
66b5b838f1SMarek Vasut #endif
67c40fdca6SSimon Glass 
mmc_list_init(void)68c40fdca6SSimon Glass void mmc_list_init(void)
69c40fdca6SSimon Glass {
70c40fdca6SSimon Glass 	INIT_LIST_HEAD(&mmc_devices);
71c40fdca6SSimon Glass 	cur_dev_num = 0;
72c40fdca6SSimon Glass }
73c40fdca6SSimon Glass 
mmc_list_add(struct mmc * mmc)74c40fdca6SSimon Glass void mmc_list_add(struct mmc *mmc)
75c40fdca6SSimon Glass {
76c40fdca6SSimon Glass 	INIT_LIST_HEAD(&mmc->link);
77c40fdca6SSimon Glass 
78c40fdca6SSimon Glass 	list_add_tail(&mmc->link, &mmc_devices);
79c40fdca6SSimon Glass }
80c40fdca6SSimon Glass 
81c40fdca6SSimon Glass #if !defined(CONFIG_SPL_BUILD) || defined(CONFIG_SPL_LIBCOMMON_SUPPORT)
print_mmc_devices(char separator)82c40fdca6SSimon Glass void print_mmc_devices(char separator)
83c40fdca6SSimon Glass {
84c40fdca6SSimon Glass 	struct mmc *m;
85c40fdca6SSimon Glass 	struct list_head *entry;
86c40fdca6SSimon Glass 	char *mmc_type;
87c40fdca6SSimon Glass 
88c40fdca6SSimon Glass 	list_for_each(entry, &mmc_devices) {
89c40fdca6SSimon Glass 		m = list_entry(entry, struct mmc, link);
90c40fdca6SSimon Glass 
91c40fdca6SSimon Glass 		if (m->has_init)
92c40fdca6SSimon Glass 			mmc_type = IS_SD(m) ? "SD" : "eMMC";
93c40fdca6SSimon Glass 		else
94c40fdca6SSimon Glass 			mmc_type = NULL;
95c40fdca6SSimon Glass 
96c40fdca6SSimon Glass 		printf("%s: %d", m->cfg->name, m->block_dev.devnum);
97c40fdca6SSimon Glass 		if (mmc_type)
98c40fdca6SSimon Glass 			printf(" (%s)", mmc_type);
99c40fdca6SSimon Glass 
100c40fdca6SSimon Glass 		if (entry->next != &mmc_devices) {
101c40fdca6SSimon Glass 			printf("%c", separator);
102c40fdca6SSimon Glass 			if (separator != '\n')
103c40fdca6SSimon Glass 				puts(" ");
104c40fdca6SSimon Glass 		}
105c40fdca6SSimon Glass 	}
106c40fdca6SSimon Glass 
107c40fdca6SSimon Glass 	printf("\n");
108c40fdca6SSimon Glass }
109c40fdca6SSimon Glass 
110c40fdca6SSimon Glass #else
print_mmc_devices(char separator)111c40fdca6SSimon Glass void print_mmc_devices(char separator) { }
112c40fdca6SSimon Glass #endif
1135aed4cbbSSimon Glass 
114b5b838f1SMarek Vasut #if CONFIG_IS_ENABLED(MMC_TINY)
115b5b838f1SMarek Vasut static struct mmc mmc_static = {
116b5b838f1SMarek Vasut 	.dsr_imp		= 0,
117b5b838f1SMarek Vasut 	.dsr			= 0xffffffff,
118b5b838f1SMarek Vasut 	.block_dev = {
119b5b838f1SMarek Vasut 		.if_type	= IF_TYPE_MMC,
120b5b838f1SMarek Vasut 		.removable	= 1,
121b5b838f1SMarek Vasut 		.devnum		= 0,
122b5b838f1SMarek Vasut 		.block_read	= mmc_bread,
123b5b838f1SMarek Vasut 		.block_write	= mmc_bwrite,
124b5b838f1SMarek Vasut 		.block_erase	= mmc_berase,
125b5b838f1SMarek Vasut 		.part_type	= 0,
126b5b838f1SMarek Vasut 	},
127b5b838f1SMarek Vasut };
128b5b838f1SMarek Vasut 
mmc_create(const struct mmc_config * cfg,void * priv)129b5b838f1SMarek Vasut struct mmc *mmc_create(const struct mmc_config *cfg, void *priv)
130b5b838f1SMarek Vasut {
131b5b838f1SMarek Vasut 	struct mmc *mmc = &mmc_static;
132b5b838f1SMarek Vasut 
133b5b838f1SMarek Vasut 	mmc->cfg = cfg;
134b5b838f1SMarek Vasut 	mmc->priv = priv;
135b5b838f1SMarek Vasut 
136b5b838f1SMarek Vasut 	return mmc;
137b5b838f1SMarek Vasut }
138b5b838f1SMarek Vasut 
mmc_destroy(struct mmc * mmc)139b5b838f1SMarek Vasut void mmc_destroy(struct mmc *mmc)
140b5b838f1SMarek Vasut {
141b5b838f1SMarek Vasut }
142b5b838f1SMarek Vasut #else
mmc_create(const struct mmc_config * cfg,void * priv)1435aed4cbbSSimon Glass struct mmc *mmc_create(const struct mmc_config *cfg, void *priv)
1445aed4cbbSSimon Glass {
1455aed4cbbSSimon Glass 	struct blk_desc *bdesc;
1465aed4cbbSSimon Glass 	struct mmc *mmc;
1475aed4cbbSSimon Glass 
1485aed4cbbSSimon Glass 	/* quick validation */
149177381a9SJaehoon Chung 	if (cfg == NULL || cfg->f_min == 0 ||
150177381a9SJaehoon Chung 	    cfg->f_max == 0 || cfg->b_max == 0)
1515aed4cbbSSimon Glass 		return NULL;
1525aed4cbbSSimon Glass 
153*e7881d85SSimon Glass #if !CONFIG_IS_ENABLED(DM_MMC)
154177381a9SJaehoon Chung 	if (cfg->ops == NULL || cfg->ops->send_cmd == NULL)
155177381a9SJaehoon Chung 		return NULL;
156177381a9SJaehoon Chung #endif
157177381a9SJaehoon Chung 
1585aed4cbbSSimon Glass 	mmc = calloc(1, sizeof(*mmc));
1595aed4cbbSSimon Glass 	if (mmc == NULL)
1605aed4cbbSSimon Glass 		return NULL;
1615aed4cbbSSimon Glass 
1625aed4cbbSSimon Glass 	mmc->cfg = cfg;
1635aed4cbbSSimon Glass 	mmc->priv = priv;
1645aed4cbbSSimon Glass 
1655aed4cbbSSimon Glass 	/* the following chunk was mmc_register() */
1665aed4cbbSSimon Glass 
1675aed4cbbSSimon Glass 	/* Setup dsr related values */
1685aed4cbbSSimon Glass 	mmc->dsr_imp = 0;
1695aed4cbbSSimon Glass 	mmc->dsr = 0xffffffff;
1705aed4cbbSSimon Glass 	/* Setup the universal parts of the block interface just once */
1715aed4cbbSSimon Glass 	bdesc = mmc_get_blk_desc(mmc);
1725aed4cbbSSimon Glass 	bdesc->if_type = IF_TYPE_MMC;
1735aed4cbbSSimon Glass 	bdesc->removable = 1;
1745aed4cbbSSimon Glass 	bdesc->devnum = mmc_get_next_devnum();
1755aed4cbbSSimon Glass 	bdesc->block_read = mmc_bread;
1765aed4cbbSSimon Glass 	bdesc->block_write = mmc_bwrite;
1775aed4cbbSSimon Glass 	bdesc->block_erase = mmc_berase;
1785aed4cbbSSimon Glass 
1795aed4cbbSSimon Glass 	/* setup initial part type */
1805aed4cbbSSimon Glass 	bdesc->part_type = mmc->cfg->part_type;
1815aed4cbbSSimon Glass 	mmc_list_add(mmc);
1825aed4cbbSSimon Glass 
1835aed4cbbSSimon Glass 	return mmc;
1845aed4cbbSSimon Glass }
1855aed4cbbSSimon Glass 
mmc_destroy(struct mmc * mmc)1865aed4cbbSSimon Glass void mmc_destroy(struct mmc *mmc)
1875aed4cbbSSimon Glass {
1885aed4cbbSSimon Glass 	/* only freeing memory for now */
1895aed4cbbSSimon Glass 	free(mmc);
1905aed4cbbSSimon Glass }
191b5b838f1SMarek Vasut #endif
1925aed4cbbSSimon Glass 
mmc_select_hwpartp(struct blk_desc * desc,int hwpart)1935aed4cbbSSimon Glass static int mmc_select_hwpartp(struct blk_desc *desc, int hwpart)
1945aed4cbbSSimon Glass {
1955aed4cbbSSimon Glass 	struct mmc *mmc = find_mmc_device(desc->devnum);
1965aed4cbbSSimon Glass 	int ret;
1975aed4cbbSSimon Glass 
1985aed4cbbSSimon Glass 	if (!mmc)
1995aed4cbbSSimon Glass 		return -ENODEV;
2005aed4cbbSSimon Glass 
2015aed4cbbSSimon Glass 	if (mmc->block_dev.hwpart == hwpart)
2025aed4cbbSSimon Glass 		return 0;
2035aed4cbbSSimon Glass 
2045aed4cbbSSimon Glass 	if (mmc->part_config == MMCPART_NOAVAILABLE)
2055aed4cbbSSimon Glass 		return -EMEDIUMTYPE;
2065aed4cbbSSimon Glass 
2075aed4cbbSSimon Glass 	ret = mmc_switch_part(mmc, hwpart);
2085aed4cbbSSimon Glass 	if (ret)
2095aed4cbbSSimon Glass 		return ret;
2105aed4cbbSSimon Glass 
2115aed4cbbSSimon Glass 	return 0;
2125aed4cbbSSimon Glass }
2135aed4cbbSSimon Glass 
mmc_get_dev(int dev,struct blk_desc ** descp)2145aed4cbbSSimon Glass static int mmc_get_dev(int dev, struct blk_desc **descp)
2155aed4cbbSSimon Glass {
2165aed4cbbSSimon Glass 	struct mmc *mmc = find_mmc_device(dev);
2175aed4cbbSSimon Glass 	int ret;
2185aed4cbbSSimon Glass 
2195aed4cbbSSimon Glass 	if (!mmc)
2205aed4cbbSSimon Glass 		return -ENODEV;
2215aed4cbbSSimon Glass 	ret = mmc_init(mmc);
2225aed4cbbSSimon Glass 	if (ret)
2235aed4cbbSSimon Glass 		return ret;
2245aed4cbbSSimon Glass 
2255aed4cbbSSimon Glass 	*descp = &mmc->block_dev;
2265aed4cbbSSimon Glass 
2275aed4cbbSSimon Glass 	return 0;
2285aed4cbbSSimon Glass }
2295aed4cbbSSimon Glass 
2305aed4cbbSSimon Glass U_BOOT_LEGACY_BLK(mmc) = {
2315aed4cbbSSimon Glass 	.if_typename	= "mmc",
2325aed4cbbSSimon Glass 	.if_type	= IF_TYPE_MMC,
2335aed4cbbSSimon Glass 	.max_devs	= -1,
2345aed4cbbSSimon Glass 	.get_dev	= mmc_get_dev,
2355aed4cbbSSimon Glass 	.select_hwpart	= mmc_select_hwpartp,
2365aed4cbbSSimon Glass };
237