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
is_cmd23_enabled(void)44 static bool is_cmd23_enabled(void)
45 {
46 return ((mmc_flags & MMC_FLAG_CMD23) != 0U);
47 }
48
is_sd_cmd6_enabled(void)49 static bool is_sd_cmd6_enabled(void)
50 {
51 return ((mmc_flags & MMC_FLAG_SD_CMD6) != 0U);
52 }
53
mmc_send_cmd(unsigned int idx,unsigned int arg,unsigned int r_type,unsigned int * r_data)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
mmc_device_state(void)83 static int mmc_device_state(void)
84 {
85 int retries = MMC_DEFAULT_MAX_RETRIES;
86 unsigned int resp_data[4] = {0};
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
mmc_send_part_switch_cmd(unsigned char part_config)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
mmc_set_ext_csd(unsigned int ext_cmd,unsigned int value)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
mmc_sd_switch(unsigned int bus_width)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
mmc_set_ios(unsigned int clk,unsigned int bus_width)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
mmc_fill_device_info(void)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
sd_switch(unsigned int mode,unsigned char group,unsigned char func)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
sd_send_op_cond(void)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
mmc_reset_to_idle(void)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
mmc_send_op_cond(void)450 static int mmc_send_op_cond(void)
451 {
452 int ret, n;
453 unsigned int resp_data[4];
454
455 for (n = 0; n < SEND_OP_COND_MAX_RETRIES; n++) {
456 ret = mmc_send_cmd(MMC_CMD(1), OCR_SECTOR_MODE |
457 OCR_VDD_MIN_2V7 | OCR_VDD_MIN_1V7,
458 MMC_RESPONSE_R3, &resp_data[0]);
459 if (ret != 0) {
460 return ret;
461 }
462
463 if ((resp_data[0] & OCR_POWERUP) != 0U) {
464 mmc_ocr_value = resp_data[0];
465 return 0;
466 }
467
468 mdelay(10);
469 }
470
471 ERROR("CMD1 failed after %d retries\n", SEND_OP_COND_MAX_RETRIES);
472
473 return -EIO;
474 }
475
mmc_enumerate(unsigned int clk,unsigned int bus_width)476 static int mmc_enumerate(unsigned int clk, unsigned int bus_width)
477 {
478 int ret;
479 unsigned int resp_data[4];
480
481 ops->init();
482
483 ret = mmc_reset_to_idle();
484 if (ret != 0) {
485 return ret;
486 }
487
488 if (mmc_dev_info->mmc_dev_type == MMC_IS_EMMC) {
489 ret = mmc_send_op_cond();
490 } else {
491 /* CMD8: Send Interface Condition Command */
492 ret = mmc_send_cmd(MMC_CMD(8), VHS_2_7_3_6_V | CMD8_CHECK_PATTERN,
493 MMC_RESPONSE_R5, &resp_data[0]);
494
495 if ((ret == 0) && ((resp_data[0] & 0xffU) == CMD8_CHECK_PATTERN)) {
496 ret = sd_send_op_cond();
497 }
498 }
499 if (ret != 0) {
500 return ret;
501 }
502
503 /* CMD2: Card Identification */
504 ret = mmc_send_cmd(MMC_CMD(2), 0, MMC_RESPONSE_R2, NULL);
505 if (ret != 0) {
506 return ret;
507 }
508
509 /* CMD3: Set Relative Address */
510 if (mmc_dev_info->mmc_dev_type == MMC_IS_EMMC) {
511 rca = MMC_FIX_RCA;
512 ret = mmc_send_cmd(MMC_CMD(3), rca << RCA_SHIFT_OFFSET,
513 MMC_RESPONSE_R1, NULL);
514 if (ret != 0) {
515 return ret;
516 }
517 } else {
518 ret = mmc_send_cmd(MMC_CMD(3), 0,
519 MMC_RESPONSE_R6, &resp_data[0]);
520 if (ret != 0) {
521 return ret;
522 }
523
524 rca = (resp_data[0] & 0xFFFF0000U) >> 16;
525 }
526
527 /* CMD9: CSD Register */
528 ret = mmc_send_cmd(MMC_CMD(9), rca << RCA_SHIFT_OFFSET,
529 MMC_RESPONSE_R2, &resp_data[0]);
530 if (ret != 0) {
531 return ret;
532 }
533
534 memcpy(&mmc_csd, &resp_data, sizeof(resp_data));
535
536 /* CMD7: Select Card */
537 ret = mmc_send_cmd(MMC_CMD(7), rca << RCA_SHIFT_OFFSET,
538 MMC_RESPONSE_R1, NULL);
539 if (ret != 0) {
540 return ret;
541 }
542
543 do {
544 ret = mmc_device_state();
545 if (ret < 0) {
546 return ret;
547 }
548 } while (ret != MMC_STATE_TRAN);
549
550 ret = mmc_set_ios(clk, bus_width);
551 if (ret != 0) {
552 return ret;
553 }
554
555 ret = mmc_fill_device_info();
556 if (ret != 0) {
557 return ret;
558 }
559
560 if (is_sd_cmd6_enabled() &&
561 (mmc_dev_info->mmc_dev_type == MMC_IS_SD_HC)) {
562 /* Try to switch to High Speed Mode */
563 ret = sd_switch(SD_SWITCH_FUNC_CHECK, 1U, 1U);
564 if (ret != 0) {
565 return ret;
566 }
567
568 if ((sd_switch_func_status.support_g1 & BIT(9)) == 0U) {
569 /* High speed not supported, keep default speed */
570 return 0;
571 }
572
573 ret = sd_switch(SD_SWITCH_FUNC_SWITCH, 1U, 1U);
574 if (ret != 0) {
575 return ret;
576 }
577
578 if ((sd_switch_func_status.sel_g2_g1 & 0x1U) == 0U) {
579 /* Cannot switch to high speed, keep default speed */
580 return 0;
581 }
582
583 mmc_dev_info->max_bus_freq = 50000000U;
584 ret = ops->set_ios(clk, bus_width);
585 }
586
587 return ret;
588 }
589
mmc_read_blocks(int lba,uintptr_t buf,size_t size)590 size_t mmc_read_blocks(int lba, uintptr_t buf, size_t size)
591 {
592 int ret;
593 unsigned int cmd_idx, cmd_arg;
594
595 assert((ops != NULL) &&
596 (ops->read != NULL) &&
597 (size != 0U) &&
598 ((size & MMC_BLOCK_MASK) == 0U));
599
600 ret = ops->prepare(lba, buf, size);
601 if (ret != 0) {
602 return 0;
603 }
604
605 if (is_cmd23_enabled()) {
606 /* Set block count */
607 ret = mmc_send_cmd(MMC_CMD(23), size / MMC_BLOCK_SIZE,
608 MMC_RESPONSE_R1, NULL);
609 if (ret != 0) {
610 return 0;
611 }
612
613 cmd_idx = MMC_CMD(18);
614 } else {
615 if (size > MMC_BLOCK_SIZE) {
616 cmd_idx = MMC_CMD(18);
617 } else {
618 cmd_idx = MMC_CMD(17);
619 }
620 }
621
622 if (((mmc_ocr_value & OCR_ACCESS_MODE_MASK) == OCR_BYTE_MODE) &&
623 (mmc_dev_info->mmc_dev_type != MMC_IS_SD_HC)) {
624 cmd_arg = lba * MMC_BLOCK_SIZE;
625 } else {
626 cmd_arg = lba;
627 }
628
629 ret = mmc_send_cmd(cmd_idx, cmd_arg, MMC_RESPONSE_R1, NULL);
630 if (ret != 0) {
631 return 0;
632 }
633
634 ret = ops->read(lba, buf, size);
635 if (ret != 0) {
636 return 0;
637 }
638
639 /* Wait buffer empty */
640 do {
641 ret = mmc_device_state();
642 if (ret < 0) {
643 return 0;
644 }
645 } while ((ret != MMC_STATE_TRAN) && (ret != MMC_STATE_DATA));
646
647 if (!is_cmd23_enabled() && (size > MMC_BLOCK_SIZE)) {
648 ret = mmc_send_cmd(MMC_CMD(12), 0, MMC_RESPONSE_R1B, NULL);
649 if (ret != 0) {
650 return 0;
651 }
652 }
653
654 return size;
655 }
656
mmc_write_blocks(int lba,const uintptr_t buf,size_t size)657 size_t mmc_write_blocks(int lba, const uintptr_t buf, size_t size)
658 {
659 int ret;
660 unsigned int cmd_idx, cmd_arg;
661
662 assert((ops != NULL) &&
663 (ops->write != NULL) &&
664 (size != 0U) &&
665 ((buf & MMC_BLOCK_MASK) == 0U) &&
666 ((size & MMC_BLOCK_MASK) == 0U));
667
668 ret = ops->prepare(lba, buf, size);
669 if (ret != 0) {
670 return 0;
671 }
672
673 if (is_cmd23_enabled()) {
674 /* Set block count */
675 ret = mmc_send_cmd(MMC_CMD(23), size / MMC_BLOCK_SIZE,
676 MMC_RESPONSE_R1, NULL);
677 if (ret != 0) {
678 return 0;
679 }
680
681 cmd_idx = MMC_CMD(25);
682 } else {
683 if (size > MMC_BLOCK_SIZE) {
684 cmd_idx = MMC_CMD(25);
685 } else {
686 cmd_idx = MMC_CMD(24);
687 }
688 }
689
690 if ((mmc_ocr_value & OCR_ACCESS_MODE_MASK) == OCR_BYTE_MODE) {
691 cmd_arg = lba * MMC_BLOCK_SIZE;
692 } else {
693 cmd_arg = lba;
694 }
695
696 ret = mmc_send_cmd(cmd_idx, cmd_arg, MMC_RESPONSE_R1, NULL);
697 if (ret != 0) {
698 return 0;
699 }
700
701 ret = ops->write(lba, buf, size);
702 if (ret != 0) {
703 return 0;
704 }
705
706 /* Wait buffer empty */
707 do {
708 ret = mmc_device_state();
709 if (ret < 0) {
710 return 0;
711 }
712 } while ((ret != MMC_STATE_TRAN) && (ret != MMC_STATE_RCV));
713
714 if (!is_cmd23_enabled() && (size > MMC_BLOCK_SIZE)) {
715 ret = mmc_send_cmd(MMC_CMD(12), 0, MMC_RESPONSE_R1B, NULL);
716 if (ret != 0) {
717 return 0;
718 }
719 }
720
721 return size;
722 }
723
mmc_erase_blocks(int lba,size_t size)724 size_t mmc_erase_blocks(int lba, size_t size)
725 {
726 int ret;
727
728 assert(ops != NULL);
729 assert((size != 0U) && ((size & MMC_BLOCK_MASK) == 0U));
730
731 ret = mmc_send_cmd(MMC_CMD(35), lba, MMC_RESPONSE_R1, NULL);
732 if (ret != 0) {
733 return 0;
734 }
735
736 ret = mmc_send_cmd(MMC_CMD(36), lba + (size / MMC_BLOCK_SIZE) - 1U,
737 MMC_RESPONSE_R1, NULL);
738 if (ret != 0) {
739 return 0;
740 }
741
742 ret = mmc_send_cmd(MMC_CMD(38), lba, MMC_RESPONSE_R1B, NULL);
743 if (ret != 0) {
744 return 0;
745 }
746
747 do {
748 ret = mmc_device_state();
749 if (ret < 0) {
750 return 0;
751 }
752 } while (ret != MMC_STATE_TRAN);
753
754 return size;
755 }
756
mmc_part_switch(unsigned char part_type)757 static int mmc_part_switch(unsigned char part_type)
758 {
759 unsigned char part_config = mmc_ext_csd[CMD_EXTCSD_PARTITION_CONFIG];
760
761 part_config &= ~EXT_CSD_PART_CONFIG_ACC_MASK;
762 part_config |= part_type;
763
764 return mmc_send_part_switch_cmd(part_config);
765 }
766
mmc_current_boot_part(void)767 static unsigned char mmc_current_boot_part(void)
768 {
769 return PART_CFG_CURRENT_BOOT_PARTITION(mmc_ext_csd[CMD_EXTCSD_PARTITION_CONFIG]);
770 }
771
mmc_part_switch_current_boot(void)772 int mmc_part_switch_current_boot(void)
773 {
774 unsigned char current_boot_part = mmc_current_boot_part();
775 int ret;
776
777 if ((current_boot_part != 1U) && (current_boot_part != 2U)) {
778 ERROR("Got unexpected value for active boot partition, %u\n", current_boot_part);
779 return -EIO;
780 }
781
782 ret = mmc_part_switch(current_boot_part);
783 if (ret < 0) {
784 ERROR("Failed to switch to boot partition, %d\n", ret);
785 }
786
787 return ret;
788 }
789
mmc_part_switch_user(void)790 int mmc_part_switch_user(void)
791 {
792 int ret;
793
794 ret = mmc_part_switch(PART_CFG_BOOT_PARTITION_NO_ACCESS);
795 if (ret < 0) {
796 ERROR("Failed to switch to user partition, %d\n", ret);
797 }
798
799 return ret;
800 }
801
mmc_boot_part_size(void)802 size_t mmc_boot_part_size(void)
803 {
804 return mmc_ext_csd[CMD_EXTCSD_BOOT_SIZE_MULT] * SZ_128K;
805 }
806
mmc_boot_part_read_blocks(int lba,uintptr_t buf,size_t size)807 size_t mmc_boot_part_read_blocks(int lba, uintptr_t buf, size_t size)
808 {
809 size_t size_read;
810 int ret;
811
812 ret = mmc_part_switch_current_boot();
813 if (ret < 0) {
814 return 0;
815 }
816
817 size_read = mmc_read_blocks(lba, buf, size);
818
819 ret = mmc_part_switch_user();
820 if (ret < 0) {
821 return 0;
822 }
823
824 return size_read;
825 }
826
mmc_init(const struct mmc_ops * ops_ptr,unsigned int clk,unsigned int width,unsigned int flags,struct mmc_device_info * device_info)827 int mmc_init(const struct mmc_ops *ops_ptr, unsigned int clk,
828 unsigned int width, unsigned int flags,
829 struct mmc_device_info *device_info)
830 {
831 assert((ops_ptr != NULL) &&
832 (ops_ptr->init != NULL) &&
833 (ops_ptr->send_cmd != NULL) &&
834 (ops_ptr->set_ios != NULL) &&
835 (ops_ptr->prepare != NULL) &&
836 (ops_ptr->read != NULL) &&
837 (ops_ptr->write != NULL) &&
838 (device_info != NULL) &&
839 (clk != 0) &&
840 ((width == MMC_BUS_WIDTH_1) ||
841 (width == MMC_BUS_WIDTH_4) ||
842 (width == MMC_BUS_WIDTH_8) ||
843 (width == MMC_BUS_WIDTH_DDR_4) ||
844 (width == MMC_BUS_WIDTH_DDR_8)));
845
846 ops = ops_ptr;
847 mmc_flags = flags;
848 mmc_dev_info = device_info;
849
850 return mmc_enumerate(clk, width);
851 }
852