]>
Commit | Line | Data |
---|---|---|
25681826 MV |
1 | The U-Boot Driver Model Project |
2 | =============================== | |
3 | MMC system analysis | |
4 | =================== | |
5 | Marek Vasut <[email protected]> | |
6 | 2012-02-25 | |
7 | ||
8 | I) Overview | |
9 | ----------- | |
10 | ||
11 | The MMC subsystem is already quite dynamic in it's nature. It's only necessary | |
12 | to flip the subsystem to properly defined API. | |
13 | ||
14 | The probing process of MMC drivers start by calling "mmc_initialize()", | |
15 | implemented by MMC framework, from the architecture initialization file. The | |
16 | "mmc_initialize()" function in turn calls "board_mmc_init()" function and if | |
17 | this doesn't succeed, "cpu_mmc_init()" function is called. It is important to | |
18 | note that both of the "*_mmc_init()" functions have weak aliases to functions | |
19 | which automatically fail. | |
20 | ||
21 | Both of the "*_mmc_init()" functions though serve only one purpose. To call | |
22 | driver specific probe function, which in turn actually registers the driver with | |
23 | MMC subsystem. Each of the driver specific probe functions is currently done in | |
24 | very ad-hoc manner. | |
25 | ||
26 | The registration with the MMC subsystem is done by calling "mmc_register()", | |
27 | whose argument is a runtime configured structure of information about the MMC | |
28 | driver. Currently, the information structure is intermixed with driver's internal | |
29 | data. The description of the structure follows: | |
30 | ||
31 | struct mmc { | |
32 | /* | |
33 | * API: Allows this driver to be a member of the linked list of all MMC drivers | |
34 | * registered with MMC subsystem | |
35 | */ | |
36 | struct list_head link; | |
37 | ||
38 | /* DRIVER: Name of the registered driver */ | |
39 | char name[32]; | |
40 | ||
41 | /* DRIVER: Driver's private data */ | |
42 | void *priv; | |
43 | ||
44 | /* DRIVER: Voltages the host bus can provide */ | |
45 | uint voltages; | |
46 | ||
47 | /* API: Version of the card */ | |
48 | uint version; | |
49 | ||
50 | /* API: Test if the driver was already initialized */ | |
51 | uint has_init; | |
52 | ||
53 | /* DRIVER: Minimum frequency the host bus can provide */ | |
54 | uint f_min; | |
55 | ||
56 | /* DRIVER: Maximum frequency the host bus can provide */ | |
57 | uint f_max; | |
58 | ||
59 | /* API: Is the card SDHC */ | |
60 | int high_capacity; | |
61 | ||
62 | /* API: Actual width of the bus used by the current card */ | |
63 | uint bus_width; | |
64 | ||
65 | /* | |
66 | * DRIVER: Clock frequency to be configured on the host bus, this is read-only | |
67 | * for the driver. | |
68 | */ | |
69 | uint clock; | |
70 | ||
71 | /* API: Capabilities of the card */ | |
72 | uint card_caps; | |
73 | ||
74 | /* DRIVER: MMC bus capabilities */ | |
75 | uint host_caps; | |
76 | ||
77 | /* API: Configuration and ID data retrieved from the card */ | |
78 | uint ocr; | |
79 | uint scr[2]; | |
80 | uint csd[4]; | |
81 | uint cid[4]; | |
82 | ushort rca; | |
83 | ||
84 | /* API: Partition configuration */ | |
85 | char part_config; | |
86 | ||
87 | /* API: Number of partitions */ | |
88 | char part_num; | |
89 | ||
90 | /* API: Transmission speed */ | |
91 | uint tran_speed; | |
92 | ||
93 | /* API: Read block length */ | |
94 | uint read_bl_len; | |
95 | ||
96 | /* API: Write block length */ | |
97 | uint write_bl_len; | |
98 | ||
99 | /* API: Erase group size */ | |
100 | uint erase_grp_size; | |
101 | ||
102 | /* API: Capacity of the card */ | |
103 | u64 capacity; | |
104 | ||
105 | /* API: Descriptor of this block device */ | |
106 | block_dev_desc_t block_dev; | |
107 | ||
108 | /* DRIVER: Function used to submit command to the card */ | |
109 | int (*send_cmd)(struct mmc *mmc, | |
93e14596 | 110 | struct mmc_cmd *cmd, struct mmc_data *data); |
25681826 MV |
111 | |
112 | /* DRIVER: Function used to configure the host */ | |
113 | void (*set_ios)(struct mmc *mmc); | |
114 | ||
115 | /* DRIVER: Function used to initialize the host */ | |
116 | int (*init)(struct mmc *mmc); | |
117 | ||
118 | /* DRIVER: Function used to report the status of Card Detect pin */ | |
119 | int (*getcd)(struct mmc *mmc); | |
120 | ||
121 | /* | |
122 | * DRIVER: Maximum amount of blocks sent during multiblock xfer, | |
123 | * set to 0 to autodetect. | |
124 | */ | |
125 | uint b_max; | |
126 | }; | |
127 | ||
128 | The API above is the new API used by most of the drivers. There're still drivers | |
129 | in the tree that use old, legacy API though. | |
130 | ||
131 | 2) Approach | |
132 | ----------- | |
133 | ||
134 | To convert the MMC subsystem to a proper driver model, the "struct mmc" | |
135 | structure will have to be properly split in the first place. The result will | |
136 | consist of multiple parts, first will be the structure defining operations | |
137 | provided by the MMC driver: | |
138 | ||
139 | struct mmc_driver_ops { | |
140 | /* Function used to submit command to the card */ | |
141 | int (*send_cmd)(struct mmc *mmc, | |
93e14596 | 142 | struct mmc_cmd *cmd, struct mmc_data *data); |
25681826 MV |
143 | /* DRIVER: Function used to configure the host */ |
144 | void (*set_ios)(struct mmc *mmc); | |
145 | /* Function used to initialize the host */ | |
146 | int (*init)(struct mmc *mmc); | |
147 | /* Function used to report the status of Card Detect pin */ | |
148 | int (*getcd)(struct mmc *mmc); | |
149 | } | |
150 | ||
151 | The second part will define the parameters of the MMC driver: | |
152 | ||
153 | struct mmc_driver_params { | |
154 | /* Voltages the host bus can provide */ | |
155 | uint32_t voltages; | |
156 | /* Minimum frequency the host bus can provide */ | |
157 | uint32_t f_min; | |
158 | /* Maximum frequency the host bus can provide */ | |
159 | uint32_t f_max; | |
160 | /* MMC bus capabilities */ | |
161 | uint32_t host_caps; | |
162 | /* | |
163 | * Maximum amount of blocks sent during multiblock xfer, | |
164 | * set to 0 to autodetect. | |
165 | */ | |
166 | uint32_t b_max; | |
167 | } | |
168 | ||
169 | And finally, the internal per-card data of the MMC subsystem core: | |
170 | ||
171 | struct mmc_card_props { | |
172 | /* Version of the card */ | |
173 | uint32_t version; | |
174 | /* Test if the driver was already initializes */ | |
175 | bool has_init; | |
176 | /* Is the card SDHC */ | |
177 | bool high_capacity; | |
178 | /* Actual width of the bus used by the current card */ | |
179 | uint8_t bus_width; | |
180 | /* Capabilities of the card */ | |
181 | uint32_t card_caps; | |
182 | /* Configuration and ID data retrieved from the card */ | |
183 | uint32_t ocr; | |
184 | uint32_t scr[2]; | |
185 | uint32_t csd[4]; | |
186 | uint32_t cid[4]; | |
187 | uint16_t rca; | |
188 | /* Partition configuration */ | |
189 | uint8_t part_config; | |
190 | /* Number of partitions */ | |
191 | uint8_t part_num; | |
192 | /* Transmission speed */ | |
193 | uint32_t tran_speed; | |
194 | /* Read block length */ | |
195 | uint32_t read_bl_len; | |
196 | /* Write block length */ | |
197 | uint32_t write_bl_len; | |
198 | /* Erase group size */ | |
199 | uint32_t erase_grp_size; | |
200 | /* Capacity of the card */ | |
201 | uint64_t capacity; | |
202 | /* Descriptor of this block device */ | |
203 | block_dev_desc_t block_dev; | |
204 | } | |
205 | ||
206 | The probe() function will then register the MMC driver by calling: | |
207 | ||
208 | mmc_device_register(struct instance *i, struct mmc_driver_ops *o, | |
93e14596 | 209 | struct mmc_driver_params *p); |
25681826 MV |
210 | |
211 | The struct mmc_driver_params will have to be dynamic in some cases, but the | |
212 | driver shouldn't modify it's contents elsewhere than in probe() call. | |
213 | ||
214 | Next, since the MMC drivers will now be consistently registered into the driver | |
215 | tree from board file, the functions "board_mmc_init()" and "cpu_mmc_init()" will | |
216 | disappear altogether. | |
217 | ||
218 | As for the legacy drivers, these will either be converted or removed altogether. | |
219 | ||
220 | III) Analysis of in-tree drivers | |
221 | -------------------------------- | |
222 | ||
223 | 1) arm_pl180_mmci.c | |
224 | ------------------- | |
225 | Follows the new API and also has a good encapsulation of the whole driver. The | |
226 | conversion here will be simple. | |
227 | ||
228 | 2) atmel_mci.c | |
229 | -------------- | |
230 | This driver uses the legacy API and should be removed unless converted. It is | |
231 | probably possbible to replace this driver with gen_atmel_mci.c . No conversion | |
232 | will be done on this driver. | |
233 | ||
234 | 3) bfin_sdh.c | |
235 | ------------- | |
236 | Follows the new API and also has a good encapsulation of the whole driver. The | |
237 | conversion here will be simple. | |
238 | ||
239 | 4) davinci_mmc.c | |
240 | ---------------- | |
241 | Follows the new API and also has a good encapsulation of the whole driver. The | |
242 | conversion here will be simple. | |
243 | ||
244 | 5) fsl_esdhc.c | |
245 | -------------- | |
246 | Follows the new API and also has a good encapsulation of the whole driver. The | |
247 | conversion here will be simple, unless some problem appears due to the FDT | |
248 | component of the driver. | |
249 | ||
250 | 6) ftsdc010_esdhc.c | |
251 | ------------------- | |
252 | Follows the new API and also has a good encapsulation of the whole driver. The | |
253 | conversion here will be simple. | |
254 | ||
255 | 7) gen_atmel_mci.c | |
256 | ------------------ | |
257 | Follows the new API and also has a good encapsulation of the whole driver. The | |
258 | conversion here will be simple. | |
259 | ||
260 | 8) mmc_spi.c | |
261 | ------------ | |
262 | Follows the new API and also has a good encapsulation of the whole driver. The | |
263 | conversion here will be simple. | |
264 | ||
265 | 9) mv_sdhci.c | |
266 | ------------- | |
267 | This is a component of the SDHCI support, allowing it to run on Marvell | |
268 | Kirkwood chip. It is probable the SDHCI support will have to be modified to | |
269 | allow calling functions from this file based on information passed via | |
270 | platform_data. | |
271 | ||
272 | 10) mxcmmc.c | |
273 | ------------ | |
274 | Follows the new API and also has a good encapsulation of the whole driver. The | |
275 | conversion here will be simple. | |
276 | ||
277 | 11) mxsmmc.c | |
278 | ------------ | |
279 | Follows the new API and also has a good encapsulation of the whole driver. The | |
280 | conversion here will be simple. | |
281 | ||
282 | 12) omap_hsmmc.c | |
283 | ---------------- | |
284 | Follows the new API and also has a good encapsulation of the whole driver. The | |
285 | conversion here will be simple. | |
286 | ||
287 | 13) pxa_mmc.c | |
288 | ------------- | |
289 | This driver uses the legacy API and is written in a severely ad-hoc manner. | |
290 | This driver will be removed in favor of pxa_mmc_gen.c, which is proved to work | |
291 | better and is already well tested. No conversion will be done on this driver | |
292 | anymore. | |
293 | ||
294 | 14) pxa_mmc_gen.c | |
295 | ----------------- | |
296 | Follows the new API and also has a good encapsulation of the whole driver. The | |
297 | conversion here will be simple. | |
298 | ||
299 | 15) s5p_mmc.c | |
300 | ------------- | |
301 | Follows the new API and also has a good encapsulation of the whole driver. The | |
302 | conversion here will be simple. | |
303 | ||
304 | 16) sdhci.c | |
305 | ----------- | |
306 | Follows the new API and also has a good encapsulation of the whole driver. The | |
307 | conversion here will be simple, though it'd be necessary to modify this driver | |
308 | to also support the Kirkwood series and probably also Tegra series of CPUs. | |
309 | See the respective parts of this section for details. | |
310 | ||
311 | 17) sh_mmcif.c | |
312 | -------------- | |
313 | Follows the new API and also has a good encapsulation of the whole driver. The | |
314 | conversion here will be simple. | |
315 | ||
316 | 18) tegra2_mmc.c | |
317 | ---------------- | |
318 | Follows the new API and also has a good encapsulation of the whole driver. The | |
319 | conversion here will be simple. |