xref: /rk3399_ARM-atf/drivers/mmc/mmc.c (revision 3af48da77120248aa7159eb929fabcced8390012)
1 /*
2  * Copyright (c) 2018, ARM Limited and Contributors. All rights reserved.
3  *
4  * SPDX-License-Identifier: BSD-3-Clause
5  */
6 
7 /* Define a simple and generic interface to access eMMC and SD-card devices. */
8 
9 #include <arch_helpers.h>
10 #include <assert.h>
11 #include <debug.h>
12 #include <delay_timer.h>
13 #include <errno.h>
14 #include <mmc.h>
15 #include <stdbool.h>
16 #include <string.h>
17 #include <utils.h>
18 
19 #define MMC_DEFAULT_MAX_RETRIES		5
20 #define SEND_OP_COND_MAX_RETRIES	100
21 
22 #define MULT_BY_512K_SHIFT		19
23 
24 static const struct mmc_ops *ops;
25 static unsigned int mmc_ocr_value;
26 static struct mmc_csd_emmc mmc_csd;
27 static unsigned char mmc_ext_csd[512] __aligned(16);
28 static unsigned int mmc_flags;
29 static struct mmc_device_info *mmc_dev_info;
30 static unsigned int rca;
31 
32 static const unsigned char tran_speed_base[16] = {
33 	0, 10, 12, 13, 15, 20, 26, 30, 35, 40, 45, 52, 55, 60, 70, 80
34 };
35 
36 static const unsigned char sd_tran_speed_base[16] = {
37 	0, 10, 12, 13, 15, 20, 25, 30, 35, 40, 45, 50, 55, 60, 70, 80
38 };
39 
40 static bool is_cmd23_enabled(void)
41 {
42 	return ((mmc_flags & MMC_FLAG_CMD23) != 0U);
43 }
44 
45 static int mmc_send_cmd(unsigned int idx, unsigned int arg,
46 			unsigned int r_type, unsigned int *r_data)
47 {
48 	struct mmc_cmd cmd;
49 	int ret;
50 
51 	zeromem(&cmd, sizeof(struct mmc_cmd));
52 
53 	cmd.cmd_idx = idx;
54 	cmd.cmd_arg = arg;
55 	cmd.resp_type = r_type;
56 
57 	ret = ops->send_cmd(&cmd);
58 
59 	if ((ret == 0) && (r_data != NULL)) {
60 		int i;
61 
62 		for (i = 0; i < 4; i++) {
63 			*r_data = cmd.resp_data[i];
64 			r_data++;
65 		}
66 	}
67 
68 	if (ret != 0) {
69 		VERBOSE("Send command %u error: %d\n", idx, ret);
70 	}
71 
72 	return ret;
73 }
74 
75 static int mmc_device_state(void)
76 {
77 	int retries = MMC_DEFAULT_MAX_RETRIES;
78 	unsigned int resp_data[4];
79 
80 	do {
81 		int ret;
82 
83 		if (retries == 0) {
84 			ERROR("CMD13 failed after %d retries\n",
85 			      MMC_DEFAULT_MAX_RETRIES);
86 			return -EIO;
87 		}
88 
89 		ret = mmc_send_cmd(MMC_CMD(13), rca << RCA_SHIFT_OFFSET,
90 				   MMC_RESPONSE_R1, &resp_data[0]);
91 		if (ret != 0) {
92 			return ret;
93 		}
94 
95 		if ((resp_data[0] & STATUS_SWITCH_ERROR) != 0U) {
96 			return -EIO;
97 		}
98 
99 		retries--;
100 	} while ((resp_data[0] & STATUS_READY_FOR_DATA) == 0U);
101 
102 	return MMC_GET_STATE(resp_data[0]);
103 }
104 
105 static int mmc_set_ext_csd(unsigned int ext_cmd, unsigned int value)
106 {
107 	int ret;
108 
109 	ret = mmc_send_cmd(MMC_CMD(6),
110 			   EXTCSD_WRITE_BYTES | EXTCSD_CMD(ext_cmd) |
111 			   EXTCSD_VALUE(value) | EXTCSD_CMD_SET_NORMAL,
112 			   MMC_RESPONSE_R1B, NULL);
113 	if (ret != 0) {
114 		return ret;
115 	}
116 
117 	do {
118 		ret = mmc_device_state();
119 		if (ret < 0) {
120 			return ret;
121 		}
122 	} while (ret == MMC_STATE_PRG);
123 
124 	return 0;
125 }
126 
127 static int mmc_sd_switch(unsigned int bus_width)
128 {
129 	int ret;
130 	int retries = MMC_DEFAULT_MAX_RETRIES;
131 	unsigned int scr[2] = { 0 };
132 	unsigned int bus_width_arg = 0;
133 
134 	ret = ops->prepare(0, (uintptr_t)&scr, sizeof(scr));
135 	if (ret != 0) {
136 		return ret;
137 	}
138 
139 	/* CMD55: Application Specific Command */
140 	ret = mmc_send_cmd(MMC_CMD(55), rca << RCA_SHIFT_OFFSET,
141 			   MMC_RESPONSE_R5, NULL);
142 	if (ret != 0) {
143 		return ret;
144 	}
145 
146 	/* ACMD51: SEND_SCR */
147 	do {
148 		ret = mmc_send_cmd(MMC_ACMD(51), 0, MMC_RESPONSE_R1, NULL);
149 		if ((ret != 0) && (retries == 0)) {
150 			ERROR("ACMD51 failed after %d retries (ret=%d)\n",
151 			      MMC_DEFAULT_MAX_RETRIES, ret);
152 			return ret;
153 		}
154 
155 		retries--;
156 	} while (ret != 0);
157 
158 	ret = ops->read(0, (uintptr_t)&scr, sizeof(scr));
159 	if (ret != 0) {
160 		return ret;
161 	}
162 
163 	if (((scr[0] & SD_SCR_BUS_WIDTH_4) != 0U) &&
164 	    (bus_width == MMC_BUS_WIDTH_4)) {
165 		bus_width_arg = 2;
166 	}
167 
168 	/* CMD55: Application Specific Command */
169 	ret = mmc_send_cmd(MMC_CMD(55), rca << RCA_SHIFT_OFFSET,
170 			   MMC_RESPONSE_R5, NULL);
171 	if (ret != 0) {
172 		return ret;
173 	}
174 
175 	/* ACMD6: SET_BUS_WIDTH */
176 	ret = mmc_send_cmd(MMC_ACMD(6), bus_width_arg, MMC_RESPONSE_R1, NULL);
177 	if (ret != 0) {
178 		return ret;
179 	}
180 
181 	do {
182 		ret = mmc_device_state();
183 		if (ret < 0) {
184 			return ret;
185 		}
186 	} while (ret == MMC_STATE_PRG);
187 
188 	return 0;
189 }
190 
191 static int mmc_set_ios(unsigned int clk, unsigned int bus_width)
192 {
193 	int ret;
194 	unsigned int width = bus_width;
195 
196 	if (mmc_dev_info->mmc_dev_type != MMC_IS_EMMC) {
197 		if (width == MMC_BUS_WIDTH_8) {
198 			WARN("Wrong bus config for SD-card, force to 4\n");
199 			width = MMC_BUS_WIDTH_4;
200 		}
201 		ret = mmc_sd_switch(width);
202 		if (ret != 0) {
203 			return ret;
204 		}
205 	} else if (mmc_csd.spec_vers == 4U) {
206 		ret = mmc_set_ext_csd(CMD_EXTCSD_BUS_WIDTH,
207 				      (unsigned int)width);
208 		if (ret != 0) {
209 			return ret;
210 		}
211 	} else {
212 		VERBOSE("Wrong MMC type or spec version\n");
213 	}
214 
215 	return ops->set_ios(clk, width);
216 }
217 
218 static int mmc_fill_device_info(void)
219 {
220 	unsigned long long c_size;
221 	unsigned int speed_idx;
222 	unsigned int nb_blocks;
223 	unsigned int freq_unit;
224 	int ret = 0;
225 	struct mmc_csd_sd_v2 *csd_sd_v2;
226 
227 	switch (mmc_dev_info->mmc_dev_type) {
228 	case MMC_IS_EMMC:
229 		mmc_dev_info->block_size = MMC_BLOCK_SIZE;
230 
231 		ret = ops->prepare(0, (uintptr_t)&mmc_ext_csd,
232 				   sizeof(mmc_ext_csd));
233 		if (ret != 0) {
234 			return ret;
235 		}
236 
237 		/* MMC CMD8: SEND_EXT_CSD */
238 		ret = mmc_send_cmd(MMC_CMD(8), 0, MMC_RESPONSE_R1, NULL);
239 		if (ret != 0) {
240 			return ret;
241 		}
242 
243 		ret = ops->read(0, (uintptr_t)&mmc_ext_csd,
244 				sizeof(mmc_ext_csd));
245 		if (ret != 0) {
246 			return ret;
247 		}
248 
249 		do {
250 			ret = mmc_device_state();
251 			if (ret < 0) {
252 				return ret;
253 			}
254 		} while (ret != MMC_STATE_TRAN);
255 
256 		nb_blocks = (mmc_ext_csd[CMD_EXTCSD_SEC_CNT] << 0) |
257 			    (mmc_ext_csd[CMD_EXTCSD_SEC_CNT + 1] << 8) |
258 			    (mmc_ext_csd[CMD_EXTCSD_SEC_CNT + 2] << 16) |
259 			    (mmc_ext_csd[CMD_EXTCSD_SEC_CNT + 3] << 24);
260 
261 		mmc_dev_info->device_size = (unsigned long long)nb_blocks *
262 			mmc_dev_info->block_size;
263 
264 		break;
265 
266 	case MMC_IS_SD:
267 		/*
268 		 * Use the same mmc_csd struct, as required fields here
269 		 * (READ_BL_LEN, C_SIZE, CSIZE_MULT) are common with eMMC.
270 		 */
271 		mmc_dev_info->block_size = BIT_32(mmc_csd.read_bl_len);
272 
273 		c_size = ((unsigned long long)mmc_csd.c_size_high << 2U) |
274 			 (unsigned long long)mmc_csd.c_size_low;
275 		assert(c_size != 0xFFFU);
276 
277 		mmc_dev_info->device_size = (c_size + 1U) *
278 					    BIT_64(mmc_csd.c_size_mult + 2U) *
279 					    mmc_dev_info->block_size;
280 
281 		break;
282 
283 	case MMC_IS_SD_HC:
284 		assert(mmc_csd.csd_structure == 1U);
285 
286 		mmc_dev_info->block_size = MMC_BLOCK_SIZE;
287 
288 		/* Need to use mmc_csd_sd_v2 struct */
289 		csd_sd_v2 = (struct mmc_csd_sd_v2 *)&mmc_csd;
290 		c_size = ((unsigned long long)csd_sd_v2->c_size_high << 16) |
291 			 (unsigned long long)csd_sd_v2->c_size_low;
292 
293 		mmc_dev_info->device_size = (c_size + 1U) << MULT_BY_512K_SHIFT;
294 
295 		break;
296 
297 	default:
298 		ret = -EINVAL;
299 		break;
300 	}
301 
302 	if (ret != 0) {
303 		return ret;
304 	}
305 
306 	speed_idx = (mmc_csd.tran_speed & CSD_TRAN_SPEED_MULT_MASK) >>
307 			 CSD_TRAN_SPEED_MULT_SHIFT;
308 
309 	assert(speed_idx > 0U);
310 
311 	if (mmc_dev_info->mmc_dev_type == MMC_IS_EMMC) {
312 		mmc_dev_info->max_bus_freq = tran_speed_base[speed_idx];
313 	} else {
314 		mmc_dev_info->max_bus_freq = sd_tran_speed_base[speed_idx];
315 	}
316 
317 	freq_unit = mmc_csd.tran_speed & CSD_TRAN_SPEED_UNIT_MASK;
318 	while (freq_unit != 0U) {
319 		mmc_dev_info->max_bus_freq *= 10U;
320 		--freq_unit;
321 	}
322 
323 	mmc_dev_info->max_bus_freq *= 10000U;
324 
325 	return 0;
326 }
327 
328 static int sd_send_op_cond(void)
329 {
330 	int n;
331 	unsigned int resp_data[4];
332 
333 	for (n = 0; n < SEND_OP_COND_MAX_RETRIES; n++) {
334 		int ret;
335 
336 		/* CMD55: Application Specific Command */
337 		ret = mmc_send_cmd(MMC_CMD(55), 0, MMC_RESPONSE_R1, NULL);
338 		if (ret != 0) {
339 			return ret;
340 		}
341 
342 		/* ACMD41: SD_SEND_OP_COND */
343 		ret = mmc_send_cmd(MMC_ACMD(41), OCR_HCS, MMC_RESPONSE_R3,
344 				   &resp_data[0]);
345 		if (ret != 0) {
346 			return ret;
347 		}
348 
349 		if ((resp_data[0] & OCR_POWERUP) != 0U) {
350 			mmc_ocr_value = resp_data[0];
351 
352 			if ((mmc_ocr_value & OCR_HCS) != 0U) {
353 				mmc_dev_info->mmc_dev_type = MMC_IS_SD_HC;
354 			} else {
355 				mmc_dev_info->mmc_dev_type = MMC_IS_SD;
356 			}
357 
358 			return 0;
359 		}
360 
361 		mdelay(1);
362 	}
363 
364 	ERROR("ACMD41 failed after %d retries\n", SEND_OP_COND_MAX_RETRIES);
365 
366 	return -EIO;
367 }
368 
369 static int mmc_reset_to_idle(void)
370 {
371 	int ret;
372 
373 	/* CMD0: reset to IDLE */
374 	ret = mmc_send_cmd(MMC_CMD(0), 0, 0, NULL);
375 	if (ret != 0) {
376 		return ret;
377 	}
378 
379 	mdelay(2);
380 
381 	return 0;
382 }
383 
384 static int mmc_send_op_cond(void)
385 {
386 	int ret, n;
387 	unsigned int resp_data[4];
388 
389 	mmc_reset_to_idle();
390 
391 	for (n = 0; n < SEND_OP_COND_MAX_RETRIES; n++) {
392 		ret = mmc_send_cmd(MMC_CMD(1), OCR_SECTOR_MODE |
393 				   OCR_VDD_MIN_2V7 | OCR_VDD_MIN_1V7,
394 				   MMC_RESPONSE_R3, &resp_data[0]);
395 		if (ret != 0) {
396 			return ret;
397 		}
398 
399 		if ((resp_data[0] & OCR_POWERUP) != 0U) {
400 			mmc_ocr_value = resp_data[0];
401 			return 0;
402 		}
403 
404 		mdelay(1);
405 	}
406 
407 	ERROR("CMD1 failed after %d retries\n", SEND_OP_COND_MAX_RETRIES);
408 
409 	return -EIO;
410 }
411 
412 static int mmc_enumerate(unsigned int clk, unsigned int bus_width)
413 {
414 	int ret;
415 	unsigned int resp_data[4];
416 
417 	ops->init();
418 
419 	mmc_reset_to_idle();
420 
421 	if (mmc_dev_info->mmc_dev_type == MMC_IS_EMMC) {
422 		ret = mmc_send_op_cond();
423 	} else {
424 		/* CMD8: Send Interface Condition Command */
425 		ret = mmc_send_cmd(MMC_CMD(8), VHS_2_7_3_6_V | CMD8_CHECK_PATTERN,
426 				   MMC_RESPONSE_R5, &resp_data[0]);
427 
428 		if ((ret == 0) && ((resp_data[0] & 0xffU) == CMD8_CHECK_PATTERN)) {
429 			ret = sd_send_op_cond();
430 		}
431 	}
432 	if (ret != 0) {
433 		return ret;
434 	}
435 
436 	/* CMD2: Card Identification */
437 	ret = mmc_send_cmd(MMC_CMD(2), 0, MMC_RESPONSE_R2, NULL);
438 	if (ret != 0) {
439 		return ret;
440 	}
441 
442 	/* CMD3: Set Relative Address */
443 	if (mmc_dev_info->mmc_dev_type == MMC_IS_EMMC) {
444 		rca = MMC_FIX_RCA;
445 		ret = mmc_send_cmd(MMC_CMD(3), rca << RCA_SHIFT_OFFSET,
446 				   MMC_RESPONSE_R1, NULL);
447 		if (ret != 0) {
448 			return ret;
449 		}
450 	} else {
451 		ret = mmc_send_cmd(MMC_CMD(3), 0,
452 				   MMC_RESPONSE_R6, &resp_data[0]);
453 		if (ret != 0) {
454 			return ret;
455 		}
456 
457 		rca = (resp_data[0] & 0xFFFF0000U) >> 16;
458 	}
459 
460 	/* CMD9: CSD Register */
461 	ret = mmc_send_cmd(MMC_CMD(9), rca << RCA_SHIFT_OFFSET,
462 			   MMC_RESPONSE_R2, &resp_data[0]);
463 	if (ret != 0) {
464 		return ret;
465 	}
466 
467 	memcpy(&mmc_csd, &resp_data, sizeof(resp_data));
468 
469 	/* CMD7: Select Card */
470 	ret = mmc_send_cmd(MMC_CMD(7), rca << RCA_SHIFT_OFFSET,
471 			   MMC_RESPONSE_R1, NULL);
472 	if (ret != 0) {
473 		return ret;
474 	}
475 
476 	do {
477 		ret = mmc_device_state();
478 		if (ret < 0) {
479 			return ret;
480 		}
481 	} while (ret != MMC_STATE_TRAN);
482 
483 	ret = mmc_set_ios(clk, bus_width);
484 	if (ret != 0) {
485 		return ret;
486 	}
487 
488 	return mmc_fill_device_info();
489 }
490 
491 size_t mmc_read_blocks(int lba, uintptr_t buf, size_t size)
492 {
493 	int ret;
494 	unsigned int cmd_idx, cmd_arg;
495 
496 	assert((ops != NULL) &&
497 	       (ops->read != NULL) &&
498 	       (size != 0U) &&
499 	       ((size & MMC_BLOCK_MASK) == 0U));
500 
501 	ret = ops->prepare(lba, buf, size);
502 	if (ret != 0) {
503 		return 0;
504 	}
505 
506 	if (is_cmd23_enabled()) {
507 		/* Set block count */
508 		ret = mmc_send_cmd(MMC_CMD(23), size / MMC_BLOCK_SIZE,
509 				   MMC_RESPONSE_R1, NULL);
510 		if (ret != 0) {
511 			return 0;
512 		}
513 
514 		cmd_idx = MMC_CMD(18);
515 	} else {
516 		if (size > MMC_BLOCK_SIZE) {
517 			cmd_idx = MMC_CMD(18);
518 		} else {
519 			cmd_idx = MMC_CMD(17);
520 		}
521 	}
522 
523 	if (((mmc_ocr_value & OCR_ACCESS_MODE_MASK) == OCR_BYTE_MODE) &&
524 	    (mmc_dev_info->mmc_dev_type != MMC_IS_SD_HC)) {
525 		cmd_arg = lba * MMC_BLOCK_SIZE;
526 	} else {
527 		cmd_arg = lba;
528 	}
529 
530 	ret = mmc_send_cmd(cmd_idx, cmd_arg, MMC_RESPONSE_R1, NULL);
531 	if (ret != 0) {
532 		return 0;
533 	}
534 
535 	ret = ops->read(lba, buf, size);
536 	if (ret != 0) {
537 		return 0;
538 	}
539 
540 	/* Wait buffer empty */
541 	do {
542 		ret = mmc_device_state();
543 		if (ret < 0) {
544 			return 0;
545 		}
546 	} while ((ret != MMC_STATE_TRAN) && (ret != MMC_STATE_DATA));
547 
548 	if (!is_cmd23_enabled() && (size > MMC_BLOCK_SIZE)) {
549 		ret = mmc_send_cmd(MMC_CMD(12), 0, MMC_RESPONSE_R1B, NULL);
550 		if (ret != 0) {
551 			return 0;
552 		}
553 	}
554 
555 	return size;
556 }
557 
558 size_t mmc_write_blocks(int lba, const uintptr_t buf, size_t size)
559 {
560 	int ret;
561 	unsigned int cmd_idx, cmd_arg;
562 
563 	assert((ops != NULL) &&
564 	       (ops->write != NULL) &&
565 	       (size != 0U) &&
566 	       ((buf & MMC_BLOCK_MASK) == 0U) &&
567 	       ((size & MMC_BLOCK_MASK) == 0U));
568 
569 	ret = ops->prepare(lba, buf, size);
570 	if (ret != 0) {
571 		return 0;
572 	}
573 
574 	if (is_cmd23_enabled()) {
575 		/* Set block count */
576 		ret = mmc_send_cmd(MMC_CMD(23), size / MMC_BLOCK_SIZE,
577 				   MMC_RESPONSE_R1, NULL);
578 		if (ret != 0) {
579 			return 0;
580 		}
581 
582 		cmd_idx = MMC_CMD(25);
583 	} else {
584 		if (size > MMC_BLOCK_SIZE) {
585 			cmd_idx = MMC_CMD(25);
586 		} else {
587 			cmd_idx = MMC_CMD(24);
588 		}
589 	}
590 
591 	if ((mmc_ocr_value & OCR_ACCESS_MODE_MASK) == OCR_BYTE_MODE) {
592 		cmd_arg = lba * MMC_BLOCK_SIZE;
593 	} else {
594 		cmd_arg = lba;
595 	}
596 
597 	ret = mmc_send_cmd(cmd_idx, cmd_arg, MMC_RESPONSE_R1, NULL);
598 	if (ret != 0) {
599 		return 0;
600 	}
601 
602 	ret = ops->write(lba, buf, size);
603 	if (ret != 0) {
604 		return 0;
605 	}
606 
607 	/* Wait buffer empty */
608 	do {
609 		ret = mmc_device_state();
610 		if (ret < 0) {
611 			return 0;
612 		}
613 	} while ((ret != MMC_STATE_TRAN) && (ret != MMC_STATE_RCV));
614 
615 	if (!is_cmd23_enabled() && (size > MMC_BLOCK_SIZE)) {
616 		ret = mmc_send_cmd(MMC_CMD(12), 0, MMC_RESPONSE_R1B, NULL);
617 		if (ret != 0) {
618 			return 0;
619 		}
620 	}
621 
622 	return size;
623 }
624 
625 size_t mmc_erase_blocks(int lba, size_t size)
626 {
627 	int ret;
628 
629 	assert(ops != NULL);
630 	assert((size != 0U) && ((size & MMC_BLOCK_MASK) == 0U));
631 
632 	ret = mmc_send_cmd(MMC_CMD(35), lba, MMC_RESPONSE_R1, NULL);
633 	if (ret != 0) {
634 		return 0;
635 	}
636 
637 	ret = mmc_send_cmd(MMC_CMD(36), lba + (size / MMC_BLOCK_SIZE) - 1U,
638 			   MMC_RESPONSE_R1, NULL);
639 	if (ret != 0) {
640 		return 0;
641 	}
642 
643 	ret = mmc_send_cmd(MMC_CMD(38), lba, MMC_RESPONSE_R1B, NULL);
644 	if (ret != 0) {
645 		return 0;
646 	}
647 
648 	do {
649 		ret = mmc_device_state();
650 		if (ret < 0) {
651 			return 0;
652 		}
653 	} while (ret != MMC_STATE_TRAN);
654 
655 	return size;
656 }
657 
658 static inline void mmc_rpmb_enable(void)
659 {
660 	mmc_set_ext_csd(CMD_EXTCSD_PARTITION_CONFIG,
661 			PART_CFG_BOOT_PARTITION1_ENABLE |
662 			PART_CFG_PARTITION1_ACCESS);
663 }
664 
665 static inline void mmc_rpmb_disable(void)
666 {
667 	mmc_set_ext_csd(CMD_EXTCSD_PARTITION_CONFIG,
668 			PART_CFG_BOOT_PARTITION1_ENABLE);
669 }
670 
671 size_t mmc_rpmb_read_blocks(int lba, uintptr_t buf, size_t size)
672 {
673 	size_t size_read;
674 
675 	mmc_rpmb_enable();
676 	size_read = mmc_read_blocks(lba, buf, size);
677 	mmc_rpmb_disable();
678 
679 	return size_read;
680 }
681 
682 size_t mmc_rpmb_write_blocks(int lba, const uintptr_t buf, size_t size)
683 {
684 	size_t size_written;
685 
686 	mmc_rpmb_enable();
687 	size_written = mmc_write_blocks(lba, buf, size);
688 	mmc_rpmb_disable();
689 
690 	return size_written;
691 }
692 
693 size_t mmc_rpmb_erase_blocks(int lba, size_t size)
694 {
695 	size_t size_erased;
696 
697 	mmc_rpmb_enable();
698 	size_erased = mmc_erase_blocks(lba, size);
699 	mmc_rpmb_disable();
700 
701 	return size_erased;
702 }
703 
704 int mmc_init(const struct mmc_ops *ops_ptr, unsigned int clk,
705 	     unsigned int width, unsigned int flags,
706 	     struct mmc_device_info *device_info)
707 {
708 	assert((ops_ptr != NULL) &&
709 	       (ops_ptr->init != NULL) &&
710 	       (ops_ptr->send_cmd != NULL) &&
711 	       (ops_ptr->set_ios != NULL) &&
712 	       (ops_ptr->prepare != NULL) &&
713 	       (ops_ptr->read != NULL) &&
714 	       (ops_ptr->write != NULL) &&
715 	       (device_info != NULL) &&
716 	       (clk != 0) &&
717 	       ((width == MMC_BUS_WIDTH_1) ||
718 		(width == MMC_BUS_WIDTH_4) ||
719 		(width == MMC_BUS_WIDTH_8) ||
720 		(width == MMC_BUS_WIDTH_DDR_4) ||
721 		(width == MMC_BUS_WIDTH_DDR_8)));
722 
723 	ops = ops_ptr;
724 	mmc_flags = flags;
725 	mmc_dev_info = device_info;
726 
727 	return mmc_enumerate(clk, width);
728 }
729