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