dm: mmc: Move CONFIG_BLK code into the mmc uclass
[platform/kernel/u-boot.git] / drivers / mmc / mmc-uclass.c
1 /*
2  * Copyright (C) 2015 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 <mmc.h>
10 #include <dm.h>
11 #include <dm/device-internal.h>
12 #include <dm/lists.h>
13 #include <dm/root.h>
14 #include "mmc_private.h"
15
16 struct mmc *mmc_get_mmc_dev(struct udevice *dev)
17 {
18         struct mmc_uclass_priv *upriv;
19
20         if (!device_active(dev))
21                 return NULL;
22         upriv = dev_get_uclass_priv(dev);
23         return upriv->mmc;
24 }
25
26 #ifdef CONFIG_BLK
27 struct mmc *find_mmc_device(int dev_num)
28 {
29         struct udevice *dev, *mmc_dev;
30         int ret;
31
32         ret = blk_get_device(IF_TYPE_MMC, dev_num, &dev);
33
34         if (ret) {
35 #if !defined(CONFIG_SPL_BUILD) || defined(CONFIG_SPL_LIBCOMMON_SUPPORT)
36                 printf("MMC Device %d not found\n", dev_num);
37 #endif
38                 return NULL;
39         }
40
41         mmc_dev = dev_get_parent(dev);
42
43         return mmc_get_mmc_dev(mmc_dev);
44 }
45
46 int get_mmc_num(void)
47 {
48         return max(blk_find_max_devnum(IF_TYPE_MMC), 0);
49 }
50
51 int mmc_get_next_devnum(void)
52 {
53         int ret;
54
55         ret = get_mmc_num();
56         if (ret < 0)
57                 return ret;
58
59         return ret + 1;
60 }
61
62 struct blk_desc *mmc_get_blk_desc(struct mmc *mmc)
63 {
64         struct blk_desc *desc;
65         struct udevice *dev;
66
67         device_find_first_child(mmc->dev, &dev);
68         if (!dev)
69                 return NULL;
70         desc = dev_get_uclass_platdata(dev);
71
72         return desc;
73 }
74
75 void mmc_do_preinit(void)
76 {
77         struct udevice *dev;
78         struct uclass *uc;
79         int ret;
80
81         ret = uclass_get(UCLASS_MMC, &uc);
82         if (ret)
83                 return;
84         uclass_foreach_dev(dev, uc) {
85                 struct mmc *m = mmc_get_mmc_dev(dev);
86
87                 if (!m)
88                         continue;
89 #ifdef CONFIG_FSL_ESDHC_ADAPTER_IDENT
90                 mmc_set_preinit(m, 1);
91 #endif
92                 if (m->preinit)
93                         mmc_start_init(m);
94         }
95 }
96
97 #if !defined(CONFIG_SPL_BUILD) || defined(CONFIG_SPL_LIBCOMMON_SUPPORT)
98 void print_mmc_devices(char separator)
99 {
100         struct udevice *dev;
101         char *mmc_type;
102         bool first = true;
103
104         for (uclass_first_device(UCLASS_MMC, &dev);
105              dev;
106              uclass_next_device(&dev)) {
107                 struct mmc *m = mmc_get_mmc_dev(dev);
108
109                 if (!first) {
110                         printf("%c", separator);
111                         if (separator != '\n')
112                                 puts(" ");
113                 }
114                 if (m->has_init)
115                         mmc_type = IS_SD(m) ? "SD" : "eMMC";
116                 else
117                         mmc_type = NULL;
118
119                 printf("%s: %d", m->cfg->name, mmc_get_blk_desc(m)->devnum);
120                 if (mmc_type)
121                         printf(" (%s)", mmc_type);
122         }
123
124         printf("\n");
125 }
126
127 #else
128 void print_mmc_devices(char separator) { }
129 #endif
130
131 int mmc_bind(struct udevice *dev, struct mmc *mmc, const struct mmc_config *cfg)
132 {
133         struct blk_desc *bdesc;
134         struct udevice *bdev;
135         int ret;
136
137         ret = blk_create_devicef(dev, "mmc_blk", "blk", IF_TYPE_MMC, -1, 512,
138                                  0, &bdev);
139         if (ret) {
140                 debug("Cannot create block device\n");
141                 return ret;
142         }
143         bdesc = dev_get_uclass_platdata(bdev);
144         mmc->cfg = cfg;
145         mmc->priv = dev;
146
147         /* the following chunk was from mmc_register() */
148
149         /* Setup dsr related values */
150         mmc->dsr_imp = 0;
151         mmc->dsr = 0xffffffff;
152         /* Setup the universal parts of the block interface just once */
153         bdesc->removable = 1;
154
155         /* setup initial part type */
156         bdesc->part_type = cfg->part_type;
157         mmc->dev = dev;
158
159         return 0;
160 }
161
162 int mmc_unbind(struct udevice *dev)
163 {
164         struct udevice *bdev;
165
166         device_find_first_child(dev, &bdev);
167         if (bdev) {
168                 device_remove(bdev);
169                 device_unbind(bdev);
170         }
171
172         return 0;
173 }
174
175 static int mmc_select_hwpart(struct udevice *bdev, int hwpart)
176 {
177         struct udevice *mmc_dev = dev_get_parent(bdev);
178         struct mmc *mmc = mmc_get_mmc_dev(mmc_dev);
179         struct blk_desc *desc = dev_get_uclass_platdata(bdev);
180         int ret;
181
182         if (desc->hwpart == hwpart)
183                 return 0;
184
185         if (mmc->part_config == MMCPART_NOAVAILABLE)
186                 return -EMEDIUMTYPE;
187
188         ret = mmc_switch_part(mmc, hwpart);
189         if (ret)
190                 return ret;
191
192         return 0;
193 }
194
195 static const struct blk_ops mmc_blk_ops = {
196         .read   = mmc_bread,
197 #ifndef CONFIG_SPL_BUILD
198         .write  = mmc_bwrite,
199 #endif
200         .select_hwpart  = mmc_select_hwpart,
201 };
202
203 U_BOOT_DRIVER(mmc_blk) = {
204         .name           = "mmc_blk",
205         .id             = UCLASS_BLK,
206         .ops            = &mmc_blk_ops,
207 };
208 #endif /* CONFIG_BLK */
209
210 U_BOOT_DRIVER(mmc) = {
211         .name   = "mmc",
212         .id     = UCLASS_MMC,
213 };
214
215 UCLASS_DRIVER(mmc) = {
216         .id             = UCLASS_MMC,
217         .name           = "mmc",
218         .flags          = DM_UC_FLAG_SEQ_ALIAS,
219         .per_device_auto_alloc_size = sizeof(struct mmc_uclass_priv),
220 };