]> git.ipfire.org Git - people/ms/u-boot.git/blob - drivers/mmc/mmc_legacy.c
Merge git://git.denx.de/u-boot-mmc
[people/ms/u-boot.git] / drivers / mmc / mmc_legacy.c
1 /*
2 * Copyright (C) 2016 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 <malloc.h>
10 #include <mmc.h>
11 #include "mmc_private.h"
12
13 static struct list_head mmc_devices;
14 static int cur_dev_num = -1;
15
16 #if !CONFIG_IS_ENABLED(MMC_TINY)
17 struct mmc *find_mmc_device(int dev_num)
18 {
19 struct mmc *m;
20 struct list_head *entry;
21
22 list_for_each(entry, &mmc_devices) {
23 m = list_entry(entry, struct mmc, link);
24
25 if (m->block_dev.devnum == dev_num)
26 return m;
27 }
28
29 #if !defined(CONFIG_SPL_BUILD) || defined(CONFIG_SPL_LIBCOMMON_SUPPORT)
30 printf("MMC Device %d not found\n", dev_num);
31 #endif
32
33 return NULL;
34 }
35
36 int mmc_get_next_devnum(void)
37 {
38 return cur_dev_num++;
39 }
40
41 struct blk_desc *mmc_get_blk_desc(struct mmc *mmc)
42 {
43 return &mmc->block_dev;
44 }
45
46 int get_mmc_num(void)
47 {
48 return cur_dev_num;
49 }
50
51 void mmc_do_preinit(void)
52 {
53 struct mmc *m;
54 struct list_head *entry;
55
56 list_for_each(entry, &mmc_devices) {
57 m = list_entry(entry, struct mmc, link);
58
59 #ifdef CONFIG_FSL_ESDHC_ADAPTER_IDENT
60 mmc_set_preinit(m, 1);
61 #endif
62 if (m->preinit)
63 mmc_start_init(m);
64 }
65 }
66 #endif
67
68 void mmc_list_init(void)
69 {
70 INIT_LIST_HEAD(&mmc_devices);
71 cur_dev_num = 0;
72 }
73
74 void mmc_list_add(struct mmc *mmc)
75 {
76 INIT_LIST_HEAD(&mmc->link);
77
78 list_add_tail(&mmc->link, &mmc_devices);
79 }
80
81 #if !defined(CONFIG_SPL_BUILD) || defined(CONFIG_SPL_LIBCOMMON_SUPPORT)
82 void print_mmc_devices(char separator)
83 {
84 struct mmc *m;
85 struct list_head *entry;
86 char *mmc_type;
87
88 list_for_each(entry, &mmc_devices) {
89 m = list_entry(entry, struct mmc, link);
90
91 if (m->has_init)
92 mmc_type = IS_SD(m) ? "SD" : "eMMC";
93 else
94 mmc_type = NULL;
95
96 printf("%s: %d", m->cfg->name, m->block_dev.devnum);
97 if (mmc_type)
98 printf(" (%s)", mmc_type);
99
100 if (entry->next != &mmc_devices) {
101 printf("%c", separator);
102 if (separator != '\n')
103 puts(" ");
104 }
105 }
106
107 printf("\n");
108 }
109
110 #else
111 void print_mmc_devices(char separator) { }
112 #endif
113
114 #if CONFIG_IS_ENABLED(MMC_TINY)
115 static struct mmc mmc_static = {
116 .dsr_imp = 0,
117 .dsr = 0xffffffff,
118 .block_dev = {
119 .if_type = IF_TYPE_MMC,
120 .removable = 1,
121 .devnum = 0,
122 .block_read = mmc_bread,
123 .block_write = mmc_bwrite,
124 .block_erase = mmc_berase,
125 .part_type = 0,
126 },
127 };
128
129 struct mmc *mmc_create(const struct mmc_config *cfg, void *priv)
130 {
131 struct mmc *mmc = &mmc_static;
132
133 mmc->cfg = cfg;
134 mmc->priv = priv;
135
136 return mmc;
137 }
138
139 void mmc_destroy(struct mmc *mmc)
140 {
141 }
142 #else
143 struct mmc *mmc_create(const struct mmc_config *cfg, void *priv)
144 {
145 struct blk_desc *bdesc;
146 struct mmc *mmc;
147
148 /* quick validation */
149 if (cfg == NULL || cfg->f_min == 0 ||
150 cfg->f_max == 0 || cfg->b_max == 0)
151 return NULL;
152
153 #if !CONFIG_IS_ENABLED(DM_MMC)
154 if (cfg->ops == NULL || cfg->ops->send_cmd == NULL)
155 return NULL;
156 #endif
157
158 mmc = calloc(1, sizeof(*mmc));
159 if (mmc == NULL)
160 return NULL;
161
162 mmc->cfg = cfg;
163 mmc->priv = priv;
164
165 /* the following chunk was mmc_register() */
166
167 /* Setup dsr related values */
168 mmc->dsr_imp = 0;
169 mmc->dsr = 0xffffffff;
170 /* Setup the universal parts of the block interface just once */
171 bdesc = mmc_get_blk_desc(mmc);
172 bdesc->if_type = IF_TYPE_MMC;
173 bdesc->removable = 1;
174 bdesc->devnum = mmc_get_next_devnum();
175 bdesc->block_read = mmc_bread;
176 bdesc->block_write = mmc_bwrite;
177 bdesc->block_erase = mmc_berase;
178
179 /* setup initial part type */
180 bdesc->part_type = mmc->cfg->part_type;
181 mmc_list_add(mmc);
182
183 return mmc;
184 }
185
186 void mmc_destroy(struct mmc *mmc)
187 {
188 /* only freeing memory for now */
189 free(mmc);
190 }
191 #endif
192
193 static int mmc_select_hwpartp(struct blk_desc *desc, int hwpart)
194 {
195 struct mmc *mmc = find_mmc_device(desc->devnum);
196 int ret;
197
198 if (!mmc)
199 return -ENODEV;
200
201 if (mmc->block_dev.hwpart == hwpart)
202 return 0;
203
204 if (mmc->part_config == MMCPART_NOAVAILABLE)
205 return -EMEDIUMTYPE;
206
207 ret = mmc_switch_part(mmc, hwpart);
208 if (ret)
209 return ret;
210
211 return 0;
212 }
213
214 static int mmc_get_dev(int dev, struct blk_desc **descp)
215 {
216 struct mmc *mmc = find_mmc_device(dev);
217 int ret;
218
219 if (!mmc)
220 return -ENODEV;
221 ret = mmc_init(mmc);
222 if (ret)
223 return ret;
224
225 *descp = &mmc->block_dev;
226
227 return 0;
228 }
229
230 U_BOOT_LEGACY_BLK(mmc) = {
231 .if_typename = "mmc",
232 .if_type = IF_TYPE_MMC,
233 .max_devs = -1,
234 .get_dev = mmc_get_dev,
235 .select_hwpart = mmc_select_hwpartp,
236 };