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