1 /******************************************************************************
2 * Copyright (C) 2013 - 2020 Xilinx, Inc. All rights reserved.
3 * SPDX-License-Identifier: MIT
4 ******************************************************************************/
5
6 /*****************************************************************************/
7 /**
8 *
9 * @file xsdps_card.c
10 * @addtogroup sdps_v3_9
11 * @{
12 *
13 * Contains the interface functions of the XSdPs driver.
14 * See xsdps.h for a detailed description of the device and driver.
15 *
16 * <pre>
17 * MODIFICATION HISTORY:
18 *
19 * Ver Who Date Changes
20 * ----- --- -------- -----------------------------------------------
21 * 3.9 mn 03/03/20 Restructured the code for more readability and modularity
22 * mn 03/16/20 Move XSdPs_Select_Card API to User APIs
23 *
24 * </pre>
25 *
26 ******************************************************************************/
27
28 /***************************** Include Files *********************************/
29 #include "xsdps_core.h"
30
31 /************************** Constant Definitions *****************************/
32
33 /**************************** Type Definitions *******************************/
34
35 /***************** Macros (Inline Functions) Definitions *********************/
36
37 /************************** Function Prototypes ******************************/
38
39 /*****************************************************************************/
40 /**
41 * @brief
42 * This function performs SD read in polled mode.
43 *
44 * @param InstancePtr is a pointer to the instance to be worked on.
45 * @param Arg is the address passed by the user that is to be sent as
46 * argument along with the command.
47 * @param BlkCnt - Block count passed by the user.
48 * @param Buff - Pointer to the data buffer for a DMA transfer.
49 *
50 * @return
51 * - XST_SUCCESS if initialization was successful
52 * - XST_FAILURE if failure - could be because another transfer
53 * is in progress or command or data inhibit is set
54 *
55 ******************************************************************************/
XSdPs_Read(XSdPs * InstancePtr,u32 Arg,u32 BlkCnt,u8 * Buff)56 s32 XSdPs_Read(XSdPs *InstancePtr, u32 Arg, u32 BlkCnt, u8 *Buff)
57 {
58 s32 Status;
59 u16 BlkSize;
60
61 BlkSize = XSDPS_BLK_SIZE_512_MASK;
62
63 XSdPs_SetupReadDma(InstancePtr, BlkCnt, BlkSize, Buff);
64
65 if (BlkCnt == 1U) {
66 /* Send single block read command */
67 Status = XSdPs_CmdTransfer(InstancePtr, CMD17, Arg, BlkCnt);
68 if (Status != XST_SUCCESS) {
69 Status = XST_FAILURE;
70 goto RETURN_PATH;
71 }
72 } else {
73 /* Send multiple blocks read command */
74 Status = XSdPs_CmdTransfer(InstancePtr, CMD18, Arg, BlkCnt);
75 if (Status != XST_SUCCESS) {
76 Status = XST_FAILURE;
77 goto RETURN_PATH;
78 }
79 }
80
81 /* Check for transfer done */
82 Status = XSdps_CheckTransferDone(InstancePtr);
83 if (Status != XST_SUCCESS) {
84 Status = XST_FAILURE;
85 }
86
87 if (InstancePtr->Config.IsCacheCoherent == 0U) {
88 Xil_DCacheInvalidateRange((INTPTR)Buff,
89 (INTPTR)BlkCnt * BlkSize);
90 }
91
92 Status = XST_SUCCESS;
93
94 RETURN_PATH:
95 return Status;
96 }
97
98 /*****************************************************************************/
99 /**
100 * @brief
101 * This function performs SD write in polled mode.
102 *
103 * @param InstancePtr is a pointer to the instance to be worked on.
104 * @param Arg is the address passed by the user that is to be sent as
105 * argument along with the command.
106 * @param BlkCnt - Block count passed by the user.
107 * @param Buff - Pointer to the data buffer for a DMA transfer.
108 *
109 * @return
110 * - XST_SUCCESS if initialization was successful
111 * - XST_FAILURE if failure - could be because another transfer
112 * is in progress or command or data inhibit is set
113 *
114 ******************************************************************************/
XSdPs_Write(XSdPs * InstancePtr,u32 Arg,u32 BlkCnt,const u8 * Buff)115 s32 XSdPs_Write(XSdPs *InstancePtr, u32 Arg, u32 BlkCnt, const u8 *Buff)
116 {
117 s32 Status;
118 u16 BlkSize;
119
120 BlkSize = XSDPS_BLK_SIZE_512_MASK;
121
122 XSdPs_SetupWriteDma(InstancePtr, BlkCnt, BlkSize, Buff);
123
124 if (BlkCnt == 1U) {
125 /* Send single block write command */
126 Status = XSdPs_CmdTransfer(InstancePtr, CMD24, Arg, BlkCnt);
127 if (Status != XST_SUCCESS) {
128 Status = XST_FAILURE;
129 goto RETURN_PATH;
130 }
131 } else {
132 /* Send multiple blocks write command */
133 Status = XSdPs_CmdTransfer(InstancePtr, CMD25, Arg, BlkCnt);
134 if (Status != XST_SUCCESS) {
135 Status = XST_FAILURE;
136 goto RETURN_PATH;
137 }
138 }
139
140 /* Check for transfer done */
141 Status = XSdps_CheckTransferDone(InstancePtr);
142 if (Status != XST_SUCCESS) {
143 Status = XST_FAILURE;
144 }
145
146 Status = XST_SUCCESS;
147
148 RETURN_PATH:
149 return Status;
150 }
151 /*****************************************************************************/
152 /**
153 *
154 * @brief
155 * Identify type of card using CMD0 + CMD1 sequence
156 *
157 *
158 * @param InstancePtr is a pointer to the XSdPs instance.
159 *
160 ******************************************************************************/
XSdPs_IdentifyCard(XSdPs * InstancePtr)161 s32 XSdPs_IdentifyCard(XSdPs *InstancePtr)
162 {
163 s32 Status;
164
165 if ((InstancePtr->HC_Version == XSDPS_HC_SPEC_V3) &&
166 ((InstancePtr->Host_Caps & XSDPS_CAPS_SLOT_TYPE_MASK)
167 == XSDPS_CAPS_EMB_SLOT)) {
168 InstancePtr->CardType = XSDPS_CHIP_EMMC;
169 Status = XST_SUCCESS;
170 goto RETURN_PATH;
171 }
172
173 /* 74 CLK delay after card is powered up, before the first command. */
174 usleep(XSDPS_INIT_DELAY);
175
176 /* CMD0 no response expected */
177 Status = XSdPs_CmdTransfer(InstancePtr, CMD0, 0U, 0U);
178 if (Status != XST_SUCCESS) {
179 Status = XST_FAILURE;
180 goto RETURN_PATH;
181 }
182
183 /* Host High Capacity support & High voltage window */
184 Status = XSdPs_CmdTransfer(InstancePtr, CMD1,
185 XSDPS_ACMD41_HCS | XSDPS_CMD1_HIGH_VOL, 0U);
186 if (Status != XST_SUCCESS) {
187 InstancePtr->CardType = XSDPS_CARD_SD;
188 } else {
189 InstancePtr->CardType = XSDPS_CARD_MMC;
190 }
191
192 XSdPs_WriteReg16(InstancePtr->Config.BaseAddress,
193 XSDPS_NORM_INTR_STS_OFFSET, XSDPS_NORM_INTR_ALL_MASK);
194 XSdPs_WriteReg16(InstancePtr->Config.BaseAddress,
195 XSDPS_ERR_INTR_STS_OFFSET, XSDPS_ERROR_INTR_ALL_MASK);
196
197 Status = XSdPs_Reset(InstancePtr, XSDPS_SWRST_CMD_LINE_MASK);
198 if (Status != XST_SUCCESS) {
199 Status = XST_FAILURE;
200 goto RETURN_PATH ;
201 }
202
203 Status = XST_SUCCESS;
204
205 RETURN_PATH:
206 return Status;
207 }
208
209 /*****************************************************************************/
210 /**
211 * @brief
212 * SD initialization is done in this function
213 *
214 *
215 * @param InstancePtr is a pointer to the instance to be worked on.
216 *
217 * @return
218 * - XST_SUCCESS if initialization was successful
219 * - XST_FAILURE if failure - could be because
220 * a) SD is already initialized
221 * b) There is no card inserted
222 * c) One of the steps (commands) in the
223 initialization cycle failed
224 *
225 * @note This function initializes the SD card by following its
226 * initialization and identification state diagram.
227 * CMD0 is sent to reset card.
228 * CMD8 and ACDM41 are sent to identify voltage and
229 * high capacity support
230 * CMD2 and CMD3 are sent to obtain Card ID and
231 * Relative card address respectively.
232 * CMD9 is sent to read the card specific data.
233 *
234 ******************************************************************************/
XSdPs_SdCardInitialize(XSdPs * InstancePtr)235 s32 XSdPs_SdCardInitialize(XSdPs *InstancePtr)
236 {
237 s32 Status;
238
239 #ifndef UHS_MODE_ENABLE
240 InstancePtr->Config.BusWidth = XSDPS_WIDTH_4;
241 #endif
242
243 Status = XSdPs_SdCardEnum(InstancePtr);
244 if (Status != XST_SUCCESS) {
245 Status = XST_FAILURE;
246 goto RETURN_PATH;
247 }
248
249 Status = XSdPs_SdModeInit(InstancePtr);
250 if (Status != XST_SUCCESS) {
251 Status = XST_FAILURE;
252 goto RETURN_PATH;
253 }
254
255 Status = XST_SUCCESS;
256
257 RETURN_PATH:
258 return Status;
259
260 }
261
262 /*****************************************************************************/
263 /**
264 * @brief
265 * Mmc initialization is done in this function
266 *
267 *
268 * @param InstancePtr is a pointer to the instance to be worked on.
269 *
270 * @return
271 * - XST_SUCCESS if initialization was successful
272 * - XST_FAILURE if failure - could be because
273 * a) MMC is already initialized
274 * b) There is no card inserted
275 * c) One of the steps (commands) in the initialization
276 * cycle failed
277 * @note This function initializes the SD card by following its
278 * initialization and identification state diagram.
279 * CMD0 is sent to reset card.
280 * CMD1 sent to identify voltage and high capacity support
281 * CMD2 and CMD3 are sent to obtain Card ID and
282 * Relative card address respectively.
283 * CMD9 is sent to read the card specific data.
284 *
285 ******************************************************************************/
XSdPs_MmcCardInitialize(XSdPs * InstancePtr)286 s32 XSdPs_MmcCardInitialize(XSdPs *InstancePtr)
287 {
288 s32 Status;
289
290 Status = XSdPs_MmcCardEnum(InstancePtr);
291 if (Status != XST_SUCCESS) {
292 Status = XST_FAILURE;
293 goto RETURN_PATH;
294 }
295
296 if (((InstancePtr->CardType == XSDPS_CARD_MMC) &&
297 (InstancePtr->Card_Version > CSD_SPEC_VER_3)) &&
298 (InstancePtr->HC_Version == XSDPS_HC_SPEC_V2)) {
299 Status = XSdPs_MmcModeInit(InstancePtr);
300 if (Status != XST_SUCCESS) {
301 Status = XST_FAILURE;
302 goto RETURN_PATH;
303 }
304 } else if (InstancePtr->CardType == XSDPS_CHIP_EMMC) {
305 Status = XSdPs_EmmcModeInit(InstancePtr);
306 if (Status != XST_SUCCESS) {
307 Status = XST_FAILURE;
308 goto RETURN_PATH;
309 }
310 } else {
311 Status = XST_FAILURE;
312 goto RETURN_PATH;
313
314 }
315
316 if (InstancePtr->Mode != XSDPS_DDR52_MODE) {
317 Status = XSdPs_SetBlkSize(InstancePtr, XSDPS_BLK_SIZE_512_MASK);
318 if (Status != XST_SUCCESS) {
319 Status = XST_FAILURE;
320 goto RETURN_PATH;
321 }
322 }
323
324 Status = XST_SUCCESS;
325
326 RETURN_PATH:
327 return Status;
328 }
329
330 /*****************************************************************************/
331 /**
332 * @brief
333 * This function checks if the card is present or not.
334 *
335 * @param InstancePtr is a pointer to the instance to be worked on.
336 *
337 * @return None
338 *
339 ******************************************************************************/
XSdPs_CheckCardDetect(XSdPs * InstancePtr)340 s32 XSdPs_CheckCardDetect(XSdPs *InstancePtr)
341 {
342 u32 PresentStateReg;
343 s32 Status;
344
345 if ((InstancePtr->HC_Version == XSDPS_HC_SPEC_V3) &&
346 ((InstancePtr->Host_Caps & XSDPS_CAPS_SLOT_TYPE_MASK)
347 == XSDPS_CAPS_EMB_SLOT)) {
348 Status = XST_SUCCESS;
349 goto RETURN_PATH;
350 }
351
352 if(InstancePtr->Config.CardDetect != 0U) {
353 /*
354 * Check the present state register to make sure
355 * card is inserted and detected by host controller
356 */
357 PresentStateReg = XSdPs_ReadReg(InstancePtr->Config.BaseAddress,
358 XSDPS_PRES_STATE_OFFSET);
359 if ((PresentStateReg & XSDPS_PSR_CARD_INSRT_MASK) == 0U) {
360 Status = XST_FAILURE;
361 goto RETURN_PATH;
362 }
363 }
364
365 Status = XST_SUCCESS;
366
367 RETURN_PATH:
368 return Status;
369 }
370
371 /*****************************************************************************/
372 /**
373 * @brief
374 * This function sends CMD0 to reset the card.
375 *
376 * @param InstancePtr is a pointer to the instance to be worked on.
377 *
378 * @return None
379 *
380 ******************************************************************************/
XSdPs_CardReset(XSdPs * InstancePtr)381 s32 XSdPs_CardReset(XSdPs *InstancePtr)
382 {
383 s32 Status;
384
385 /* CMD0 no response expected */
386 Status = XSdPs_CmdTransfer(InstancePtr, (u32)CMD0, 0U, 0U);
387 if (Status != XST_SUCCESS) {
388 Status = XST_FAILURE;
389 }
390
391 return Status;
392 }
393
394 /*****************************************************************************/
395 /**
396 * @brief
397 * This function sends command to get the card interface details.
398 *
399 * @param InstancePtr is a pointer to the instance to be worked on.
400 *
401 * @return None
402 *
403 ******************************************************************************/
XSdPs_CardIfCond(XSdPs * InstancePtr)404 s32 XSdPs_CardIfCond(XSdPs *InstancePtr)
405 {
406 u32 RespOCR;
407 s32 Status;
408
409 /*
410 * CMD8; response expected
411 * 0x1AA - Supply Voltage 2.7 - 3.6V and AA is pattern
412 */
413 Status = XSdPs_CmdTransfer(InstancePtr, CMD8,
414 XSDPS_CMD8_VOL_PATTERN, 0U);
415 if ((Status != XST_SUCCESS) && (Status != XSDPS_CT_ERROR)) {
416 Status = XST_FAILURE;
417 goto RETURN_PATH;
418 }
419
420 if (Status == XSDPS_CT_ERROR) {
421 Status = XSdPs_Reset(InstancePtr, XSDPS_SWRST_CMD_LINE_MASK);
422 if (Status != XST_SUCCESS) {
423 Status = XST_FAILURE;
424 goto RETURN_PATH ;
425 }
426 }
427
428 RespOCR = XSdPs_ReadReg(InstancePtr->Config.BaseAddress,
429 XSDPS_RESP0_OFFSET);
430 if (RespOCR != XSDPS_CMD8_VOL_PATTERN) {
431 InstancePtr->Card_Version = XSDPS_SD_VER_1_0;
432 } else {
433 InstancePtr->Card_Version = XSDPS_SD_VER_2_0;
434 }
435
436 Status = XST_SUCCESS;
437
438 RETURN_PATH:
439 return Status;
440 }
441
442 /*****************************************************************************/
443 /**
444 * @brief
445 * This function sends command to get the card operating condition.
446 *
447 * @param InstancePtr is a pointer to the instance to be worked on.
448 *
449 * @return None
450 *
451 ******************************************************************************/
XSdPs_CardOpCond(XSdPs * InstancePtr)452 s32 XSdPs_CardOpCond(XSdPs *InstancePtr)
453 {
454 u32 RespOCR;
455 s32 Status;
456 u32 Arg;
457
458 /* Send ACMD41 while card is still busy with power up */
459 do {
460 if (InstancePtr->CardType == XSDPS_CARD_SD) {
461 Status = XSdPs_CmdTransfer(InstancePtr, CMD55, 0U, 0U);
462 if (Status != XST_SUCCESS) {
463 Status = XST_FAILURE;
464 goto RETURN_PATH;
465 }
466
467 Arg = XSDPS_ACMD41_HCS | XSDPS_ACMD41_3V3 | (0x1FFU << 15U);
468 if ((InstancePtr->HC_Version == XSDPS_HC_SPEC_V3) &&
469 (InstancePtr->Config.BusWidth == XSDPS_WIDTH_8)) {
470 Arg |= XSDPS_OCR_S18;
471 }
472
473 /* 0x40300000 - Host High Capacity support & 3.3V window */
474 Status = XSdPs_CmdTransfer(InstancePtr, ACMD41,
475 Arg, 0U);
476 } else {
477 /* Send CMD1 while card is still busy with power up */
478 Status = XSdPs_CmdTransfer(InstancePtr, CMD1,
479 XSDPS_ACMD41_HCS | XSDPS_CMD1_HIGH_VOL, 0U);
480 }
481 if (Status != XST_SUCCESS) {
482 Status = XST_FAILURE;
483 goto RETURN_PATH;
484 }
485
486 /* Response with card capacity */
487 RespOCR = XSdPs_ReadReg(InstancePtr->Config.BaseAddress,
488 XSDPS_RESP0_OFFSET);
489 } while ((RespOCR & XSDPS_RESPOCR_READY) == 0U);
490
491 /* Update HCS support flag based on card capacity response */
492 if ((RespOCR & XSDPS_ACMD41_HCS) != 0U) {
493 InstancePtr->HCS = 1U;
494 }
495
496 if ((RespOCR & XSDPS_OCR_S18) != 0U) {
497 InstancePtr->Switch1v8 = 1U;
498 Status = XSdPs_Switch_Voltage(InstancePtr);
499 if (Status != XST_SUCCESS) {
500 Status = XST_FAILURE;
501 goto RETURN_PATH;
502 }
503 }
504
505 Status = XST_SUCCESS;
506
507 RETURN_PATH:
508 return Status;
509 }
510
511 /*****************************************************************************/
512 /**
513 * @brief
514 * This function is used to get the card ID.
515 *
516 * @param InstancePtr is a pointer to the instance to be worked on.
517 *
518 * @return None
519 *
520 ******************************************************************************/
XSdPs_GetCardId(XSdPs * InstancePtr)521 s32 XSdPs_GetCardId(XSdPs *InstancePtr)
522 {
523 s32 Status;
524
525 /* CMD2 for Card ID */
526 Status = XSdPs_CmdTransfer(InstancePtr, CMD2, 0U, 0U);
527 if (Status != XST_SUCCESS) {
528 Status = XST_FAILURE;
529 goto RETURN_PATH;
530 }
531
532 InstancePtr->CardID[0] =
533 XSdPs_ReadReg16(InstancePtr->Config.BaseAddress,
534 XSDPS_RESP0_OFFSET);
535 InstancePtr->CardID[1] =
536 XSdPs_ReadReg16(InstancePtr->Config.BaseAddress,
537 XSDPS_RESP1_OFFSET);
538 InstancePtr->CardID[2] =
539 XSdPs_ReadReg16(InstancePtr->Config.BaseAddress,
540 XSDPS_RESP2_OFFSET);
541 InstancePtr->CardID[3] =
542 XSdPs_ReadReg16(InstancePtr->Config.BaseAddress,
543 XSDPS_RESP3_OFFSET);
544
545 if(InstancePtr->CardType == XSDPS_CARD_SD) {
546 do {
547 Status = XSdPs_CmdTransfer(InstancePtr, CMD3, 0U, 0U);
548 if (Status != XST_SUCCESS) {
549 Status = XST_FAILURE;
550 goto RETURN_PATH;
551 }
552
553 /*
554 * Relative card address is stored as the upper 16 bits
555 * This is to avoid shifting when sending commands
556 */
557 InstancePtr->RelCardAddr =
558 XSdPs_ReadReg(InstancePtr->Config.BaseAddress,
559 XSDPS_RESP0_OFFSET) & 0xFFFF0000U;
560 } while (InstancePtr->RelCardAddr == 0U);
561 } else {
562 /* Set relative card address */
563 InstancePtr->RelCardAddr = 0x12340000U;
564 Status = XSdPs_CmdTransfer(InstancePtr, CMD3, (InstancePtr->RelCardAddr), 0U);
565 if (Status != XST_SUCCESS) {
566 Status = XST_FAILURE;
567 goto RETURN_PATH;
568 }
569 }
570
571 Status = XST_SUCCESS;
572
573 RETURN_PATH:
574 return Status;
575 }
576
577 /*****************************************************************************/
578 /**
579 * @brief
580 * This function is used to get the CSD register from the card.
581 *
582 * @param InstancePtr is a pointer to the instance to be worked on.
583 *
584 * @return None
585 *
586 ******************************************************************************/
XSdPs_GetCsd(XSdPs * InstancePtr)587 s32 XSdPs_GetCsd(XSdPs *InstancePtr)
588 {
589 s32 Status;
590 u32 CSD[4];
591 u32 BlkLen;
592 u32 DeviceSize;
593 u32 Mult;
594
595 Status = XSdPs_CmdTransfer(InstancePtr, CMD9, (InstancePtr->RelCardAddr), 0U);
596 if (Status != XST_SUCCESS) {
597 Status = XST_FAILURE;
598 goto RETURN_PATH;
599 }
600
601 /*
602 * Card specific data is read.
603 * Currently not used for any operation.
604 */
605 CSD[0] = XSdPs_ReadReg(InstancePtr->Config.BaseAddress,
606 XSDPS_RESP0_OFFSET);
607 CSD[1] = XSdPs_ReadReg(InstancePtr->Config.BaseAddress,
608 XSDPS_RESP1_OFFSET);
609 CSD[2] = XSdPs_ReadReg(InstancePtr->Config.BaseAddress,
610 XSDPS_RESP2_OFFSET);
611 CSD[3] = XSdPs_ReadReg(InstancePtr->Config.BaseAddress,
612 XSDPS_RESP3_OFFSET);
613
614 if (InstancePtr->CardType != XSDPS_CARD_SD) {
615 InstancePtr->Card_Version = (u8)((u32)(CSD[3] & CSD_SPEC_VER_MASK) >>18U);
616 Status = XST_SUCCESS;
617 goto RETURN_PATH;
618 }
619
620 if (((CSD[3] & CSD_STRUCT_MASK) >> 22U) == 0U) {
621 BlkLen = 1U << ((u32)(CSD[2] & READ_BLK_LEN_MASK) >> 8U);
622 Mult = 1U << ((u32)((CSD[1] & C_SIZE_MULT_MASK) >> 7U) + 2U);
623 DeviceSize = (CSD[1] & C_SIZE_LOWER_MASK) >> 22U;
624 DeviceSize |= (CSD[2] & C_SIZE_UPPER_MASK) << 10U;
625 DeviceSize = (DeviceSize + 1U) * Mult;
626 DeviceSize = DeviceSize * BlkLen;
627 InstancePtr->SectorCount = (DeviceSize/XSDPS_BLK_SIZE_512_MASK);
628 } else if (((CSD[3] & CSD_STRUCT_MASK) >> 22U) == 1U) {
629 InstancePtr->SectorCount = (((CSD[1] & CSD_V2_C_SIZE_MASK) >> 8U) +
630 1U) * 1024U;
631 } else {
632 Status = XST_FAILURE;
633 goto RETURN_PATH;
634 }
635
636 Status = XST_SUCCESS;
637
638 RETURN_PATH:
639 return Status;
640 }
641
642 /*****************************************************************************/
643 /**
644 * @brief
645 * This function is used to set the card voltage to 1.8V.
646 *
647 * @param InstancePtr is a pointer to the instance to be worked on.
648 *
649 * @return None
650 *
651 ******************************************************************************/
XSdPs_CardSetVoltage18(XSdPs * InstancePtr)652 s32 XSdPs_CardSetVoltage18(XSdPs *InstancePtr)
653 {
654 s32 Status;
655 u16 CtrlReg;
656 u16 ClockReg;
657
658 /* Stop the clock */
659 CtrlReg = XSdPs_ReadReg16(InstancePtr->Config.BaseAddress,
660 XSDPS_CLK_CTRL_OFFSET);
661 CtrlReg &= ~(XSDPS_CC_SD_CLK_EN_MASK | XSDPS_CC_INT_CLK_EN_MASK);
662 XSdPs_WriteReg16(InstancePtr->Config.BaseAddress, XSDPS_CLK_CTRL_OFFSET,
663 CtrlReg);
664
665 /* Check for 1.8V signal enable bit is cleared by Host */
666 Status = XSdPs_SetVoltage18(InstancePtr);
667 if (Status != XST_SUCCESS) {
668 Status = XST_FAILURE;
669 goto RETURN_PATH;
670 }
671
672 ClockReg = XSdPs_ReadReg16(InstancePtr->Config.BaseAddress,
673 XSDPS_CLK_CTRL_OFFSET);
674 /* Enable the clock in the controller */
675 Status = XSdPs_EnableClock(InstancePtr, ClockReg);
676 if (Status != XST_SUCCESS) {
677 Status = XST_FAILURE;
678 }
679
680 /* Wait for 1mSec */
681 (void)usleep(1000U);
682
683 Status = XST_SUCCESS;
684
685 RETURN_PATH:
686 return Status;
687 }
688
689 /*****************************************************************************/
690 /**
691 * @brief
692 * This function is used to do initial Reset Configuration.
693 *
694 * @param InstancePtr is a pointer to the instance to be worked on.
695 *
696 * @return None
697 *
698 ******************************************************************************/
XSdPs_ResetConfig(XSdPs * InstancePtr)699 s32 XSdPs_ResetConfig(XSdPs *InstancePtr)
700 {
701 s32 Status;
702
703 XSdPs_DisableBusPower(InstancePtr);
704
705 Status = XSdPs_Reset(InstancePtr, XSDPS_SWRST_ALL_MASK);
706 if (Status != XST_SUCCESS) {
707 Status = XST_FAILURE;
708 goto RETURN_PATH ;
709 }
710
711 XSdPs_EnableBusPower(InstancePtr);
712
713 RETURN_PATH:
714 return Status;
715 }
716
717 /*****************************************************************************/
718 /**
719 * @brief
720 * This function is used to do initial Host Configuration.
721 *
722 * @param InstancePtr is a pointer to the instance to be worked on.
723 *
724 * @return None
725 *
726 ******************************************************************************/
XSdPs_HostConfig(XSdPs * InstancePtr)727 void XSdPs_HostConfig(XSdPs *InstancePtr)
728 {
729 XSdPs_ConfigPower(InstancePtr);
730
731 XSdPs_ConfigDma(InstancePtr);
732
733 XSdPs_ConfigInterrupt(InstancePtr);
734
735 /*
736 * Transfer mode register - default value
737 * DMA enabled, block count enabled, data direction card to host(read)
738 */
739 InstancePtr->TransferMode = XSDPS_TM_DMA_EN_MASK | XSDPS_TM_BLK_CNT_EN_MASK |
740 XSDPS_TM_DAT_DIR_SEL_MASK;
741
742 /* Set block size to 512 by default */
743 XSdPs_WriteReg16(InstancePtr->Config.BaseAddress,
744 XSDPS_BLK_SIZE_OFFSET, XSDPS_BLK_SIZE_512_MASK);
745 }
746
747 /*****************************************************************************/
748 /**
749 * @brief
750 * This function checks for Reset Done bits to be cleared after a reset assert.
751 *
752 * @param InstancePtr is a pointer to the instance to be worked on.
753 * @param Value is the bits to be checked to be cleared.
754 *
755 * @return None
756 *
757 ******************************************************************************/
XSdPs_CheckResetDone(XSdPs * InstancePtr,u8 Value)758 s32 XSdPs_CheckResetDone(XSdPs *InstancePtr, u8 Value)
759 {
760 u32 Timeout = 1000000U;
761 u32 ReadReg;
762 s32 Status;
763
764 /* Proceed with initialization only after reset is complete */
765 do {
766 ReadReg = XSdPs_ReadReg8(InstancePtr->Config.BaseAddress,
767 XSDPS_SW_RST_OFFSET);
768 Timeout = Timeout - 1U;
769 usleep(1);
770 } while (((ReadReg & Value) != 0U)
771 && (Timeout != 0U));
772
773 if (Timeout == 0U) {
774 Status = XST_FAILURE;
775 goto RETURN_PATH ;
776 }
777
778 Status = XST_SUCCESS;
779
780 RETURN_PATH:
781 return Status;
782 }
783
784 /*****************************************************************************/
785 /**
786 * @brief
787 * This function is used to setup the voltage switch.
788 *
789 * @param InstancePtr is a pointer to the instance to be worked on.
790 *
791 * @return None
792 *
793 ******************************************************************************/
XSdPs_SetupVoltageSwitch(XSdPs * InstancePtr)794 s32 XSdPs_SetupVoltageSwitch(XSdPs *InstancePtr)
795 {
796 u32 Timeout = 10000;
797 s32 Status;
798 u32 ReadReg;
799
800 /* Send switch voltage command */
801 Status = XSdPs_CmdTransfer(InstancePtr, CMD11, 0U, 0U);
802 if (Status != XST_SUCCESS) {
803 Status = XST_FAILURE;
804 goto RETURN_PATH;
805 }
806
807 /* Wait for CMD and DATA line to go low */
808 do {
809 ReadReg = XSdPs_ReadReg(InstancePtr->Config.BaseAddress,
810 XSDPS_PRES_STATE_OFFSET);
811 Timeout = Timeout - 1;
812 usleep(1);
813 } while (((ReadReg & (XSDPS_PSR_CMD_SG_LVL_MASK |
814 XSDPS_PSR_DAT30_SG_LVL_MASK)) != 0U)
815 && (Timeout != 0U));
816
817 if (Timeout == 0U) {
818 Status = XST_FAILURE;
819 goto RETURN_PATH ;
820 }
821
822 RETURN_PATH:
823 return Status;
824 }
825
826 /*****************************************************************************/
827 /**
828 * @brief
829 * This function is used to check if the Cmd and Dat buses are high.
830 *
831 * @param InstancePtr is a pointer to the instance to be worked on.
832 *
833 * @return None
834 *
835 ******************************************************************************/
XSdPs_CheckBusHigh(XSdPs * InstancePtr)836 s32 XSdPs_CheckBusHigh(XSdPs *InstancePtr)
837 {
838 u32 Timeout = 10000;
839 s32 Status;
840 u32 ReadReg;
841
842 /* Wait for CMD and DATA line to go high */
843 Timeout = MAX_TIMEOUT;
844 do {
845 ReadReg = XSdPs_ReadReg(InstancePtr->Config.BaseAddress,
846 XSDPS_PRES_STATE_OFFSET);
847 Timeout = Timeout - 1;
848 usleep(1);
849 } while (((ReadReg & (XSDPS_PSR_CMD_SG_LVL_MASK | XSDPS_PSR_DAT30_SG_LVL_MASK))
850 != (XSDPS_PSR_CMD_SG_LVL_MASK | XSDPS_PSR_DAT30_SG_LVL_MASK))
851 && (Timeout != 0U));
852
853 if (Timeout == 0U) {
854 Status = XST_FAILURE;
855 goto RETURN_PATH ;
856 }
857
858 Status = XST_SUCCESS;
859
860 RETURN_PATH:
861 return Status;
862 }
863
864 /*****************************************************************************/
865 /**
866 *
867 * @brief
868 * API to Identify the supported UHS mode. This API will assign the
869 * corresponding tap delay API to the Config_TapDelay pointer based on the
870 * supported bus speed.
871 *
872 *
873 * @param InstancePtr is a pointer to the XSdPs instance.
874 * @param ReadBuff contains the response for CMD6
875 *
876 * @return None.
877 *
878 * @note None.
879 *
880 ******************************************************************************/
XSdPs_Identify_UhsMode(XSdPs * InstancePtr,u8 * ReadBuff)881 void XSdPs_Identify_UhsMode(XSdPs *InstancePtr, u8 *ReadBuff)
882 {
883 if (((ReadBuff[13] & UHS_SDR104_SUPPORT) != 0U) &&
884 (InstancePtr->Config.InputClockHz >= XSDPS_SD_INPUT_MAX_CLK)) {
885 InstancePtr->Mode = XSDPS_UHS_SPEED_MODE_SDR104;
886 if (InstancePtr->Config.BankNumber == 2U) {
887 InstancePtr->OTapDelay = SD_OTAPDLYSEL_HS200_B2;
888 } else {
889 InstancePtr->OTapDelay = SD_OTAPDLYSEL_HS200_B0;
890 }
891 } else if (((ReadBuff[13] & UHS_SDR50_SUPPORT) != 0U) &&
892 (InstancePtr->Config.InputClockHz >= XSDPS_SD_SDR50_MAX_CLK)) {
893 InstancePtr->Mode = XSDPS_UHS_SPEED_MODE_SDR50;
894 InstancePtr->OTapDelay = SD_OTAPDLYSEL_SD50;
895 } else if (((ReadBuff[13] & UHS_DDR50_SUPPORT) != 0U) &&
896 (InstancePtr->Config.InputClockHz >= XSDPS_SD_DDR50_MAX_CLK)) {
897 InstancePtr->Mode = XSDPS_UHS_SPEED_MODE_DDR50;
898 InstancePtr->OTapDelay = SD_OTAPDLYSEL_SD_DDR50;
899 InstancePtr->ITapDelay = SD_ITAPDLYSEL_SD_DDR50;
900 } else if (((ReadBuff[13] & UHS_SDR25_SUPPORT) != 0U) &&
901 (InstancePtr->Config.InputClockHz >= XSDPS_SD_SDR25_MAX_CLK)) {
902 InstancePtr->Mode = XSDPS_UHS_SPEED_MODE_SDR25;
903 InstancePtr->OTapDelay = SD_OTAPDLYSEL_SD_HSD;
904 InstancePtr->ITapDelay = SD_ITAPDLYSEL_HSD;
905 } else {
906 InstancePtr->Mode = XSDPS_UHS_SPEED_MODE_SDR12;
907 }
908 }
909
910 /*****************************************************************************/
911 /**
912 *
913 * @brief
914 * API to set Tap Delay w.r.t speed modes
915 *
916 *
917 * @param InstancePtr is a pointer to the XSdPs instance.
918 *
919 * @return None
920 *
921 * @note None.
922 *
923 ******************************************************************************/
XSdPs_SetTapDelay(XSdPs * InstancePtr)924 void XSdPs_SetTapDelay(XSdPs *InstancePtr)
925 {
926 if ((InstancePtr->Mode == XSDPS_DEFAULT_SPEED_MODE) ||
927 (InstancePtr->Mode == XSDPS_UHS_SPEED_MODE_SDR12)) {
928 return;
929 }
930
931 #ifndef versal
932 /* Issue DLL Reset */
933 XSdPs_DllRstCtrl(InstancePtr, 1U);
934 #endif
935
936 /* Configure the Tap Delay Registers */
937 XSdPs_ConfigTapDelay(InstancePtr);
938
939 #ifndef versal
940 /* Release the DLL out of reset */
941 XSdPs_DllRstCtrl(InstancePtr, 0U);
942 #endif
943 }
944
945 /*****************************************************************************/
946 /**
947 * @brief
948 * This function is used to change the SD Bus Speed.
949 *
950 * @param InstancePtr is a pointer to the instance to be worked on.
951 *
952 * @return None
953 *
954 ******************************************************************************/
XSdPs_Change_SdBusSpeed(XSdPs * InstancePtr)955 s32 XSdPs_Change_SdBusSpeed(XSdPs *InstancePtr)
956 {
957 s32 Status;
958 u32 Arg;
959 u16 BlkCnt;
960 u16 BlkSize;
961 u16 CtrlReg;
962 u8 ReadBuff[64] = {0U};
963
964 Status = XSdPs_CalcBusSpeed(InstancePtr, &Arg);
965 if (Status != XST_SUCCESS) {
966 Status = XST_FAILURE;
967 goto RETURN_PATH;
968 }
969
970 BlkCnt = XSDPS_SWITCH_CMD_BLKCNT;
971 BlkSize = XSDPS_SWITCH_CMD_BLKSIZE;
972
973 XSdPs_SetupReadDma(InstancePtr, BlkCnt, BlkSize, ReadBuff);
974
975 Status = XSdPs_CmdTransfer(InstancePtr, CMD6, Arg, BlkCnt);
976 if (Status != XST_SUCCESS) {
977 Status = XST_FAILURE;
978 goto RETURN_PATH;
979 }
980
981 /* Check for transfer done */
982 Status = XSdps_CheckTransferDone(InstancePtr);
983 if (Status != XST_SUCCESS) {
984 Status = XST_FAILURE;
985 }
986
987 if (InstancePtr->Switch1v8 != 0U) {
988 /* Set UHS mode in controller */
989 CtrlReg = XSdPs_ReadReg16(InstancePtr->Config.BaseAddress,
990 XSDPS_HOST_CTRL2_OFFSET);
991 CtrlReg &= (u16)(~XSDPS_HC2_UHS_MODE_MASK);
992 XSdPs_WriteReg16(InstancePtr->Config.BaseAddress,
993 XSDPS_HOST_CTRL2_OFFSET,
994 CtrlReg | InstancePtr->Mode);
995 }
996
997 Status = XST_SUCCESS;
998
999 RETURN_PATH:
1000 return Status;
1001 }
1002
1003 /*****************************************************************************/
1004 /**
1005 * @brief
1006 * This function is used to change the eMMC bus speed.
1007 *
1008 * @param InstancePtr is a pointer to the instance to be worked on.
1009 *
1010 * @return None
1011 *
1012 ******************************************************************************/
XSdPs_Change_MmcBusSpeed(XSdPs * InstancePtr)1013 s32 XSdPs_Change_MmcBusSpeed(XSdPs *InstancePtr)
1014 {
1015 s32 Status;
1016 u32 Arg;
1017
1018 Status = XSdPs_CalcBusSpeed(InstancePtr, &Arg);
1019 if (Status != XST_SUCCESS) {
1020 Status = XST_FAILURE;
1021 goto RETURN_PATH;
1022 }
1023
1024 Status = XSdPs_CmdTransfer(InstancePtr, CMD6, Arg, 0U);
1025 if (Status != XST_SUCCESS) {
1026 Status = XST_FAILURE;
1027 goto RETURN_PATH;
1028 }
1029
1030 /* Check for transfer done */
1031 Status = XSdps_CheckTransferDone(InstancePtr);
1032 if (Status != XST_SUCCESS) {
1033 Status = XST_FAILURE;
1034 }
1035
1036 Status = XST_SUCCESS;
1037
1038 RETURN_PATH:
1039 return Status;
1040 }
1041
1042 /*****************************************************************************/
1043 /**
1044 * @brief
1045 * This function is used to do the Auto tuning.
1046 *
1047 * @param InstancePtr is a pointer to the instance to be worked on.
1048 *
1049 * @return None
1050 *
1051 ******************************************************************************/
XSdPs_AutoTuning(XSdPs * InstancePtr)1052 s32 XSdPs_AutoTuning(XSdPs *InstancePtr)
1053 {
1054 s32 Status;
1055 u16 BlkSize;
1056 u8 TuningCount;
1057
1058 BlkSize = XSDPS_TUNING_CMD_BLKSIZE;
1059 if(InstancePtr->BusWidth == XSDPS_8_BIT_WIDTH)
1060 {
1061 BlkSize = BlkSize*2U;
1062 }
1063 BlkSize &= XSDPS_BLK_SIZE_MASK;
1064 XSdPs_WriteReg16(InstancePtr->Config.BaseAddress, XSDPS_BLK_SIZE_OFFSET,
1065 BlkSize);
1066
1067 InstancePtr->TransferMode = XSDPS_TM_DAT_DIR_SEL_MASK;
1068
1069 XSdPs_SetExecTuning(InstancePtr);
1070 /*
1071 * workaround which can work for 1.0/2.0 silicon for auto tuning.
1072 * This can be revisited for 3.0 silicon if necessary.
1073 */
1074 /* Wait for ~60 clock cycles to reset the tap values */
1075 (void)usleep(1U);
1076
1077 for (TuningCount = 0U; TuningCount < MAX_TUNING_COUNT; TuningCount++) {
1078
1079 if (InstancePtr->CardType == XSDPS_CARD_SD) {
1080 Status = XSdPs_CmdTransfer(InstancePtr, CMD19, 0U, 1U);
1081 } else {
1082 Status = XSdPs_CmdTransfer(InstancePtr, CMD21, 0U, 1U);
1083 }
1084
1085 if (Status != XST_SUCCESS) {
1086 Status = XST_FAILURE;
1087 goto RETURN_PATH;
1088 }
1089
1090 if ((XSdPs_ReadReg16(InstancePtr->Config.BaseAddress,
1091 XSDPS_HOST_CTRL2_OFFSET) & XSDPS_HC2_EXEC_TNG_MASK) == 0U) {
1092 break;
1093 }
1094 }
1095
1096 if ((XSdPs_ReadReg16(InstancePtr->Config.BaseAddress,
1097 XSDPS_HOST_CTRL2_OFFSET) & XSDPS_HC2_SAMP_CLK_SEL_MASK) == 0U) {
1098 Status = XST_FAILURE;
1099 goto RETURN_PATH;
1100 }
1101
1102 /* Wait for ~12 clock cycles to synchronize the new tap values */
1103 (void)usleep(1U);
1104
1105 Status = XST_SUCCESS;
1106
1107 RETURN_PATH:
1108 return Status;
1109 }
1110
1111 /*****************************************************************************/
1112 /**
1113 *
1114 * @brief
1115 * API to setup ADMA2 descriptor table
1116 *
1117 *
1118 * @param InstancePtr is a pointer to the XSdPs instance.
1119 * @param BlkCnt - block count.
1120 * @param Buff pointer to data buffer.
1121 *
1122 * @return None
1123 *
1124 * @note None.
1125 *
1126 ******************************************************************************/
XSdPs_SetupADMA2DescTbl(XSdPs * InstancePtr,u32 BlkCnt,const u8 * Buff)1127 void XSdPs_SetupADMA2DescTbl(XSdPs *InstancePtr, u32 BlkCnt, const u8 *Buff)
1128 {
1129 if (InstancePtr->HC_Version == XSDPS_HC_SPEC_V3) {
1130 XSdPs_Setup64ADMA2DescTbl(InstancePtr, BlkCnt, Buff);
1131 } else {
1132 XSdPs_Setup32ADMA2DescTbl(InstancePtr, BlkCnt, Buff);
1133 }
1134 }
1135
1136 /*****************************************************************************/
1137 /**
1138 *
1139 * @brief
1140 * API to setup ADMA2 descriptor table for 64 Bit DMA
1141 *
1142 *
1143 * @param InstancePtr is a pointer to the XSdPs instance.
1144 * @param BlkCnt - block count.
1145 *
1146 * @return None
1147 *
1148 * @note None.
1149 *
1150 ******************************************************************************/
XSdPs_SetupADMA2DescTbl64Bit(XSdPs * InstancePtr,u32 BlkCnt)1151 void XSdPs_SetupADMA2DescTbl64Bit(XSdPs *InstancePtr, u32 BlkCnt)
1152 {
1153 #ifdef __ICCARM__
1154 #pragma data_alignment = 32
1155 static XSdPs_Adma2Descriptor64 Adma2_DescrTbl[32];
1156 #else
1157 static XSdPs_Adma2Descriptor64 Adma2_DescrTbl[32] __attribute__ ((aligned(32)));
1158 #endif
1159 u32 TotalDescLines;
1160 u64 DescNum;
1161 u32 BlkSize;
1162
1163 /* Setup ADMA2 - Write descriptor table and point ADMA SAR to it */
1164 BlkSize = (u32)XSdPs_ReadReg16(InstancePtr->Config.BaseAddress,
1165 XSDPS_BLK_SIZE_OFFSET) &
1166 XSDPS_BLK_SIZE_MASK;
1167
1168 if((BlkCnt*BlkSize) < XSDPS_DESC_MAX_LENGTH) {
1169
1170 TotalDescLines = 1U;
1171
1172 } else {
1173
1174 TotalDescLines = ((BlkCnt*BlkSize) / XSDPS_DESC_MAX_LENGTH);
1175 if (((BlkCnt * BlkSize) % XSDPS_DESC_MAX_LENGTH) != 0U) {
1176 TotalDescLines += 1U;
1177 }
1178
1179 }
1180
1181 for (DescNum = 0U; DescNum < (TotalDescLines-1); DescNum++) {
1182 Adma2_DescrTbl[DescNum].Address =
1183 InstancePtr->Dma64BitAddr +
1184 (DescNum*XSDPS_DESC_MAX_LENGTH);
1185 Adma2_DescrTbl[DescNum].Attribute =
1186 XSDPS_DESC_TRAN | XSDPS_DESC_VALID;
1187 Adma2_DescrTbl[DescNum].Length = 0U;
1188 }
1189
1190 Adma2_DescrTbl[TotalDescLines-1].Address =
1191 InstancePtr->Dma64BitAddr +
1192 (DescNum*XSDPS_DESC_MAX_LENGTH);
1193
1194 Adma2_DescrTbl[TotalDescLines-1].Attribute =
1195 XSDPS_DESC_TRAN | XSDPS_DESC_END | XSDPS_DESC_VALID;
1196
1197 Adma2_DescrTbl[TotalDescLines-1].Length =
1198 (u16)((BlkCnt*BlkSize) - (u32)(DescNum*XSDPS_DESC_MAX_LENGTH));
1199
1200 XSdPs_WriteReg(InstancePtr->Config.BaseAddress, XSDPS_ADMA_SAR_OFFSET,
1201 (u32)((UINTPTR)&(Adma2_DescrTbl[0]) & (u32)~0x0));
1202
1203 if (InstancePtr->Config.IsCacheCoherent == 0U) {
1204 Xil_DCacheFlushRange((INTPTR)&(Adma2_DescrTbl[0]),
1205 sizeof(XSdPs_Adma2Descriptor64) * 32U);
1206 }
1207
1208 /* Clear the 64-Bit Address variable */
1209 InstancePtr->Dma64BitAddr = 0U;
1210
1211 }
1212
1213 /*****************************************************************************/
1214 /**
1215 *
1216 * @brief
1217 * API to reset the DLL
1218 *
1219 *
1220 * @param InstancePtr is a pointer to the XSdPs instance.
1221 *
1222 * @return None
1223 *
1224 * @note None.
1225 *
1226 ******************************************************************************/
XSdPs_DllReset(XSdPs * InstancePtr)1227 s32 XSdPs_DllReset(XSdPs *InstancePtr)
1228 {
1229 u32 ClockReg;
1230 s32 Status;
1231
1232 /* Disable clock */
1233 ClockReg = XSdPs_ReadReg16(InstancePtr->Config.BaseAddress,
1234 XSDPS_CLK_CTRL_OFFSET);
1235 ClockReg &= ~XSDPS_CC_SD_CLK_EN_MASK;
1236 XSdPs_WriteReg16(InstancePtr->Config.BaseAddress,
1237 XSDPS_CLK_CTRL_OFFSET, (u16)ClockReg);
1238
1239 /* Issue DLL Reset to load zero tap values */
1240 XSdPs_DllRstCtrl(InstancePtr, 1U);
1241
1242 /* Wait for 2 micro seconds */
1243 (void)usleep(2U);
1244
1245 XSdPs_DllRstCtrl(InstancePtr, 0U);
1246
1247 ClockReg = XSdPs_ReadReg16(InstancePtr->Config.BaseAddress,
1248 XSDPS_CLK_CTRL_OFFSET);
1249 /* Enable the clock in the controller */
1250 Status = XSdPs_EnableClock(InstancePtr, ClockReg);
1251 if (Status != XST_SUCCESS) {
1252 Status = XST_FAILURE;
1253 }
1254
1255 return Status;
1256 }
1257
1258 /*****************************************************************************/
1259 /**
1260 * @brief
1261 * This function is used to identify the eMMC speed mode.
1262 *
1263 * @param InstancePtr is a pointer to the instance to be worked on.
1264 * @param ExtCsd is the extended CSD register from the card
1265 *
1266 * @return None
1267 *
1268 ******************************************************************************/
XSdPs_IdentifyEmmcMode(XSdPs * InstancePtr,const u8 * ExtCsd)1269 void XSdPs_IdentifyEmmcMode(XSdPs *InstancePtr, const u8 *ExtCsd)
1270 {
1271 if (InstancePtr->BusWidth < XSDPS_4_BIT_WIDTH) {
1272 InstancePtr->Mode = XSDPS_DEFAULT_SPEED_MODE;
1273 } else {
1274 /* Check for card supported speed */
1275 if ((ExtCsd[EXT_CSD_DEVICE_TYPE_BYTE] &
1276 (EXT_CSD_DEVICE_TYPE_SDR_1V8_HS200 |
1277 EXT_CSD_DEVICE_TYPE_SDR_1V2_HS200)) != 0U) {
1278 InstancePtr->Mode = XSDPS_HS200_MODE;
1279 if (InstancePtr->Config.BankNumber == 2U) {
1280 InstancePtr->OTapDelay = SD_OTAPDLYSEL_HS200_B2;
1281 } else {
1282 InstancePtr->OTapDelay = SD_OTAPDLYSEL_HS200_B0;
1283 }
1284 } else if ((ExtCsd[EXT_CSD_DEVICE_TYPE_BYTE] &
1285 (EXT_CSD_DEVICE_TYPE_DDR_1V8_HIGH_SPEED |
1286 EXT_CSD_DEVICE_TYPE_DDR_1V2_HIGH_SPEED)) != 0U) {
1287 InstancePtr->Mode = XSDPS_DDR52_MODE;
1288 InstancePtr->OTapDelay = SD_ITAPDLYSEL_EMMC_DDR50;
1289 InstancePtr->ITapDelay = SD_ITAPDLYSEL_EMMC_DDR50;
1290 } else if ((ExtCsd[EXT_CSD_DEVICE_TYPE_BYTE] &
1291 EXT_CSD_DEVICE_TYPE_HIGH_SPEED) != 0U) {
1292 InstancePtr->Mode = XSDPS_HIGH_SPEED_MODE;
1293 InstancePtr->OTapDelay = SD_OTAPDLYSEL_EMMC_HSD;
1294 InstancePtr->ITapDelay = SD_ITAPDLYSEL_HSD;
1295 } else {
1296 InstancePtr->Mode = XSDPS_DEFAULT_SPEED_MODE;
1297 }
1298 }
1299 }
1300
1301 /*****************************************************************************/
1302 /**
1303 * @brief
1304 * This function is used to check the eMMC timing.
1305 *
1306 * @param InstancePtr is a pointer to the instance to be worked on.
1307 * @param ExtCsd is the extended CSD register from the card
1308 *
1309 * @return None
1310 *
1311 ******************************************************************************/
XSdPs_CheckEmmcTiming(XSdPs * InstancePtr,u8 * ExtCsd)1312 s32 XSdPs_CheckEmmcTiming(XSdPs *InstancePtr, u8 *ExtCsd)
1313 {
1314 s32 Status;
1315
1316 Status = XSdPs_Get_Mmc_ExtCsd(InstancePtr, ExtCsd);
1317 if (Status != XST_SUCCESS) {
1318 Status = XST_FAILURE;
1319 goto RETURN_PATH;
1320 }
1321
1322 if (InstancePtr->Mode == XSDPS_HS200_MODE) {
1323 if (ExtCsd[EXT_CSD_HS_TIMING_BYTE] != EXT_CSD_HS_TIMING_HS200) {
1324 Status = XST_FAILURE;
1325 goto RETURN_PATH;
1326 }
1327 } else if ((InstancePtr->Mode == XSDPS_HIGH_SPEED_MODE) ||
1328 (InstancePtr->Mode == XSDPS_DDR52_MODE)) {
1329 if (ExtCsd[EXT_CSD_HS_TIMING_BYTE] != EXT_CSD_HS_TIMING_HIGH) {
1330 Status = XST_FAILURE;
1331 goto RETURN_PATH;
1332 }
1333 } else {
1334 Status = XST_FAILURE;
1335 }
1336
1337 RETURN_PATH:
1338 return Status;
1339 }
1340
1341 /*****************************************************************************/
1342 /**
1343 * @brief
1344 * This function is used to set the clock to the passed frequency.
1345 *
1346 * @param InstancePtr is a pointer to the instance to be worked on.
1347 * @param SelFreq is the selected frequency
1348 *
1349 * @return None
1350 *
1351 ******************************************************************************/
XSdPs_SetClock(XSdPs * InstancePtr,u32 SelFreq)1352 s32 XSdPs_SetClock(XSdPs *InstancePtr, u32 SelFreq)
1353 {
1354 u16 ClockReg;
1355 s32 Status;
1356
1357 /* Disable clock */
1358 XSdPs_WriteReg16(InstancePtr->Config.BaseAddress,
1359 XSDPS_CLK_CTRL_OFFSET, 0U);
1360
1361 /* If selected frequency is zero, return from here */
1362 if (SelFreq == 0U) {
1363 Status = XST_SUCCESS;
1364 goto RETURN_PATH ;
1365 }
1366
1367 /* Calculate the clock */
1368 ClockReg = XSdPs_CalcClock(InstancePtr, SelFreq);
1369
1370 /* Enable the clock in the controller */
1371 Status = XSdPs_EnableClock(InstancePtr, ClockReg);
1372 if (Status != XST_SUCCESS) {
1373 Status = XST_FAILURE;
1374 }
1375
1376 RETURN_PATH:
1377 return Status;
1378 }
1379
1380 /*****************************************************************************/
1381 /**
1382 * @brief
1383 * This function checks if the voltage is set to 1.8V or not.
1384 *
1385 * @param InstancePtr is a pointer to the instance to be worked on.
1386 *
1387 * @return
1388 * - XST_SUCCESS if voltage is 1.8V
1389 * - XST_FAILURE if voltage is not 1.8V
1390 *
1391 ******************************************************************************/
XSdPs_CheckVoltage18(XSdPs * InstancePtr)1392 s32 XSdPs_CheckVoltage18(XSdPs *InstancePtr)
1393 {
1394 u32 Status;
1395
1396 if ((XSdPs_ReadReg16(InstancePtr->Config.BaseAddress,
1397 XSDPS_HOST_CTRL2_OFFSET) & XSDPS_HC2_1V8_EN_MASK) == 0U) {
1398 Status = XST_FAILURE;
1399 goto RETURN_PATH;
1400 }
1401
1402 Status = XST_SUCCESS;
1403
1404 RETURN_PATH:
1405 return Status;
1406 }
1407
1408 /*****************************************************************************/
1409 /**
1410 * @brief
1411 * This function initializes the command sequence.
1412 *
1413 * @param InstancePtr is a pointer to the instance to be worked on.
1414 * @param Arg is the address passed by the user that is to be sent as
1415 * argument along with the command.
1416 * @param BlkCnt - Block count passed by the user.
1417 *
1418 * @return None
1419 *
1420 ******************************************************************************/
XSdPs_SetupCmd(XSdPs * InstancePtr,u32 Arg,u32 BlkCnt)1421 s32 XSdPs_SetupCmd(XSdPs *InstancePtr, u32 Arg, u32 BlkCnt)
1422 {
1423 s32 Status;
1424
1425 /*
1426 * Check the command inhibit to make sure no other
1427 * command transfer is in progress
1428 */
1429 Status = XSdPs_CheckBusIdle(InstancePtr, XSDPS_PSR_INHIBIT_CMD_MASK);
1430 if (Status != XST_SUCCESS) {
1431 Status = XST_FAILURE;
1432 goto RETURN_PATH ;
1433 }
1434
1435 /* Write block count register */
1436 XSdPs_WriteReg16(InstancePtr->Config.BaseAddress,
1437 XSDPS_BLK_CNT_OFFSET, (u16)BlkCnt);
1438
1439 XSdPs_WriteReg8(InstancePtr->Config.BaseAddress,
1440 XSDPS_TIMEOUT_CTRL_OFFSET, 0xEU);
1441
1442 /* Write argument register */
1443 XSdPs_WriteReg(InstancePtr->Config.BaseAddress,
1444 XSDPS_ARGMT_OFFSET, Arg);
1445
1446 XSdPs_WriteReg16(InstancePtr->Config.BaseAddress,
1447 XSDPS_NORM_INTR_STS_OFFSET, XSDPS_NORM_INTR_ALL_MASK);
1448 XSdPs_WriteReg16(InstancePtr->Config.BaseAddress,
1449 XSDPS_ERR_INTR_STS_OFFSET, XSDPS_ERROR_INTR_ALL_MASK);
1450
1451 Status = XST_SUCCESS;
1452
1453 RETURN_PATH:
1454 return Status;
1455 }
1456
1457 /*****************************************************************************/
1458 /**
1459 * @brief
1460 * This function initiates the Cmd transfer to SD card.
1461 *
1462 * @param InstancePtr is a pointer to the instance to be worked on.
1463 * @param Cmd is the command to be sent
1464 *
1465 * @return
1466 * - XST_SUCCESS if initialization was successful
1467 * - XST_FAILURE if failure
1468 *
1469 ******************************************************************************/
XSdPs_SendCmd(XSdPs * InstancePtr,u32 Cmd)1470 s32 XSdPs_SendCmd(XSdPs *InstancePtr, u32 Cmd)
1471 {
1472 u32 PresentStateReg;
1473 u32 CommandReg;
1474 s32 Status;
1475
1476 /* Command register is set to trigger transfer of command */
1477 CommandReg = XSdPs_FrameCmd(InstancePtr, Cmd);
1478
1479 /*
1480 * Mask to avoid writing to reserved bits 31-30
1481 * This is necessary because 0x8000 is used by this software to
1482 * distinguish between ACMD and CMD of same number
1483 */
1484 CommandReg = CommandReg & 0x3FFFU;
1485
1486 /*
1487 * Check for data inhibit in case of command using DAT lines.
1488 * For Tuning Commands DAT lines check can be ignored.
1489 */
1490 if ((Cmd != CMD21) && (Cmd != CMD19)) {
1491 PresentStateReg = XSdPs_ReadReg(InstancePtr->Config.BaseAddress,
1492 XSDPS_PRES_STATE_OFFSET);
1493 if (((PresentStateReg & XSDPS_PSR_INHIBIT_DAT_MASK) != 0U) &&
1494 ((CommandReg & XSDPS_DAT_PRESENT_SEL_MASK) != 0U)) {
1495 Status = XST_FAILURE;
1496 goto RETURN_PATH;
1497 }
1498 }
1499
1500 XSdPs_WriteReg(InstancePtr->Config.BaseAddress, XSDPS_XFER_MODE_OFFSET,
1501 (CommandReg << 16) | InstancePtr->TransferMode);
1502
1503 Status = XST_SUCCESS;
1504
1505 RETURN_PATH:
1506 return Status;
1507
1508 }
1509
1510 /** @} */
1511