]> git.sur5r.net Git - u-boot/blob - drivers/mmc/mmc_legacy.c
Merge git://www.denx.de/git/u-boot-imx
[u-boot] / 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_OPS)
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 };