1 The U-Boot Driver Model Project
2 ===============================
5 Marek Vasut <marek.vasut@gmail.com>
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.
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.
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
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:
33 * API: Allows this driver to be a member of the linked list of all MMC drivers
34 * registered with MMC subsystem
36 struct list_head link;
38 /* DRIVER: Name of the registered driver */
41 /* DRIVER: Driver's private data */
44 /* DRIVER: Voltages the host bus can provide */
47 /* API: Version of the card */
50 /* API: Test if the driver was already initialized */
53 /* DRIVER: Minimum frequency the host bus can provide */
56 /* DRIVER: Maximum frequency the host bus can provide */
59 /* API: Is the card SDHC */
62 /* API: Actual width of the bus used by the current card */
66 * DRIVER: Clock frequency to be configured on the host bus, this is read-only
71 /* API: Capabilities of the card */
74 /* DRIVER: MMC bus capabilities */
77 /* API: Configuration and ID data retrieved from the card */
84 /* API: Partition configuration */
87 /* API: Number of partitions */
90 /* API: Transmission speed */
93 /* API: Read block length */
96 /* API: Write block length */
99 /* API: Erase group size */
102 /* API: Capacity of the card */
105 /* API: Descriptor of this block device */
106 block_dev_desc_t block_dev;
108 /* DRIVER: Function used to submit command to the card */
109 int (*send_cmd)(struct mmc *mmc,
110 struct mmc_cmd *cmd, struct mmc_data *data);
112 /* DRIVER: Function used to configure the host */
113 void (*set_ios)(struct mmc *mmc);
115 /* DRIVER: Function used to initialize the host */
116 int (*init)(struct mmc *mmc);
118 /* DRIVER: Function used to report the status of Card Detect pin */
119 int (*getcd)(struct mmc *mmc);
122 * DRIVER: Maximum amount of blocks sent during multiblock xfer,
123 * set to 0 to autodetect.
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.
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:
139 struct mmc_driver_ops {
140 /* Function used to submit command to the card */
141 int (*send_cmd)(struct mmc *mmc,
142 struct mmc_cmd *cmd, struct mmc_data *data);
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);
151 The second part will define the parameters of the MMC driver:
153 struct mmc_driver_params {
154 /* Voltages the host bus can provide */
156 /* Minimum frequency the host bus can provide */
158 /* Maximum frequency the host bus can provide */
160 /* MMC bus capabilities */
163 * Maximum amount of blocks sent during multiblock xfer,
164 * set to 0 to autodetect.
169 And finally, the internal per-card data of the MMC subsystem core:
171 struct mmc_card_props {
172 /* Version of the card */
174 /* Test if the driver was already initializes */
176 /* Is the card SDHC */
178 /* Actual width of the bus used by the current card */
180 /* Capabilities of the card */
182 /* Configuration and ID data retrieved from the card */
188 /* Partition configuration */
190 /* Number of partitions */
192 /* Transmission 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 */
202 /* Descriptor of this block device */
203 block_dev_desc_t block_dev;
206 The probe() function will then register the MMC driver by calling:
208 mmc_device_register(struct instance *i, struct mmc_driver_ops *o,
209 struct mmc_driver_params *p);
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.
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.
218 As for the legacy drivers, these will either be converted or removed altogether.
220 III) Analysis of in-tree drivers
221 --------------------------------
225 Follows the new API and also has a good encapsulation of the whole driver. The
226 conversion here will be simple.
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.
236 Follows the new API and also has a good encapsulation of the whole driver. The
237 conversion here will be simple.
241 Follows the new API and also has a good encapsulation of the whole driver. The
242 conversion here will be simple.
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.
252 Follows the new API and also has a good encapsulation of the whole driver. The
253 conversion here will be simple.
257 Follows the new API and also has a good encapsulation of the whole driver. The
258 conversion here will be simple.
262 Follows the new API and also has a good encapsulation of the whole driver. The
263 conversion here will be simple.
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
274 Follows the new API and also has a good encapsulation of the whole driver. The
275 conversion here will be simple.
279 Follows the new API and also has a good encapsulation of the whole driver. The
280 conversion here will be simple.
284 Follows the new API and also has a good encapsulation of the whole driver. The
285 conversion here will be simple.
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
296 Follows the new API and also has a good encapsulation of the whole driver. The
297 conversion here will be simple.
301 Follows the new API and also has a good encapsulation of the whole driver. The
302 conversion here will be simple.
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.
313 Follows the new API and also has a good encapsulation of the whole driver. The
314 conversion here will be simple.
318 Follows the new API and also has a good encapsulation of the whole driver. The
319 conversion here will be simple.