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