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