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