1 // SPDX-License-Identifier: GPL-2.0+
3 * Copyright (C) 2016 Google, Inc
12 #include "mmc_private.h"
14 static struct list_head mmc_devices;
15 static int cur_dev_num = -1;
17 #if CONFIG_IS_ENABLED(MMC_TINY)
18 static struct mmc mmc_static;
19 struct mmc *find_mmc_device(int dev_num)
24 void mmc_do_preinit(void)
26 struct mmc *m = &mmc_static;
31 struct blk_desc *mmc_get_blk_desc(struct mmc *mmc)
33 return &mmc->block_dev;
36 struct mmc *find_mmc_device(int dev_num)
39 struct list_head *entry;
41 list_for_each(entry, &mmc_devices) {
42 m = list_entry(entry, struct mmc, link);
44 if (m->block_dev.devnum == dev_num)
48 #if !defined(CONFIG_SPL_BUILD) || defined(CONFIG_SPL_LIBCOMMON_SUPPORT)
49 printf("MMC Device %d not found\n", dev_num);
55 int mmc_get_next_devnum(void)
60 struct blk_desc *mmc_get_blk_desc(struct mmc *mmc)
62 return &mmc->block_dev;
70 void mmc_do_preinit(void)
73 struct list_head *entry;
75 list_for_each(entry, &mmc_devices) {
76 m = list_entry(entry, struct mmc, link);
84 void mmc_list_init(void)
86 INIT_LIST_HEAD(&mmc_devices);
90 void mmc_list_add(struct mmc *mmc)
92 INIT_LIST_HEAD(&mmc->link);
94 list_add_tail(&mmc->link, &mmc_devices);
97 #if !defined(CONFIG_SPL_BUILD) || defined(CONFIG_SPL_LIBCOMMON_SUPPORT)
98 void print_mmc_devices(char separator)
101 struct list_head *entry;
104 list_for_each(entry, &mmc_devices) {
105 m = list_entry(entry, struct mmc, link);
108 mmc_type = IS_SD(m) ? "SD" : "eMMC";
112 printf("%s: %d", m->cfg->name, m->block_dev.devnum);
114 printf(" (%s)", mmc_type);
116 if (entry->next != &mmc_devices) {
117 printf("%c", separator);
118 if (separator != '\n')
127 void print_mmc_devices(char separator) { }
130 #if CONFIG_IS_ENABLED(MMC_TINY)
131 static struct mmc mmc_static = {
135 .if_type = IF_TYPE_MMC,
138 .block_read = mmc_bread,
139 .block_write = mmc_bwrite,
140 .block_erase = mmc_berase,
145 struct mmc *mmc_create(const struct mmc_config *cfg, void *priv)
147 struct mmc *mmc = &mmc_static;
149 /* First MMC device registered, fail to register a new one.
150 * Given users are not expecting this to fail, instead
151 * of failing let's just return the only MMC device
154 debug("Warning: MMC_TINY doesn't support multiple MMC devices\n");
164 void mmc_destroy(struct mmc *mmc)
168 struct mmc *mmc_create(const struct mmc_config *cfg, void *priv)
170 struct blk_desc *bdesc;
173 /* quick validation */
174 if (cfg == NULL || cfg->f_min == 0 ||
175 cfg->f_max == 0 || cfg->b_max == 0)
178 #if !CONFIG_IS_ENABLED(DM_MMC)
179 if (cfg->ops == NULL || cfg->ops->send_cmd == NULL)
183 mmc = calloc(1, sizeof(*mmc));
190 /* the following chunk was mmc_register() */
192 /* Setup dsr related values */
194 mmc->dsr = 0xffffffff;
195 /* Setup the universal parts of the block interface just once */
196 bdesc = mmc_get_blk_desc(mmc);
197 bdesc->if_type = IF_TYPE_MMC;
198 bdesc->removable = 1;
199 bdesc->devnum = mmc_get_next_devnum();
200 bdesc->block_read = mmc_bread;
201 bdesc->block_write = mmc_bwrite;
202 bdesc->block_erase = mmc_berase;
204 /* setup initial part type */
205 bdesc->part_type = mmc->cfg->part_type;
211 void mmc_destroy(struct mmc *mmc)
213 /* only freeing memory for now */
218 static int mmc_select_hwpartp(struct blk_desc *desc, int hwpart)
220 struct mmc *mmc = find_mmc_device(desc->devnum);
226 if (mmc->block_dev.hwpart == hwpart)
229 if (mmc->part_config == MMCPART_NOAVAILABLE)
232 ret = mmc_switch_part(mmc, hwpart);
239 static int mmc_get_dev(int dev, struct blk_desc **descp)
241 struct mmc *mmc = find_mmc_device(dev);
250 *descp = &mmc->block_dev;
255 U_BOOT_LEGACY_BLK(mmc) = {
256 .if_typename = "mmc",
257 .if_type = IF_TYPE_MMC,
259 .get_dev = mmc_get_dev,
260 .select_hwpart = mmc_select_hwpartp,