1 /******************************************************************************
3 * Copyright (C) 2013 - 2016 Xilinx, Inc. All rights reserved.
5 * Permission is hereby granted, free of charge, to any person obtaining a copy
6 * of this software and associated documentation files (the "Software"), to deal
7 * in the Software without restriction, including without limitation the rights
8 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 * copies of the Software, and to permit persons to whom the Software is
10 * furnished to do so, subject to the following conditions:
12 * The above copyright notice and this permission notice shall be included in
13 * all copies or substantial portions of the Software.
15 * Use of the Software is limited solely to applications:
16 * (a) running on a Xilinx device, or
17 * (b) that interact with a Xilinx device through a bus or interconnect.
19 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
20 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
21 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
22 * XILINX BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
23 * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
24 * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
27 * Except as contained in this notice, the name of the Xilinx shall not be used
28 * in advertising or otherwise to promote the sale, use or other dealings in
29 * this Software without prior written authorization from Xilinx.
31 ******************************************************************************/
32 /*****************************************************************************/
35 * @file xsdps_options.c
36 * @addtogroup sdps_v2_5
39 * Contains API's for changing the various options in host and card.
40 * See xsdps.h for a detailed description of the device and driver.
43 * MODIFICATION HISTORY:
45 * Ver Who Date Changes
46 * ----- --- -------- -----------------------------------------------
47 * 1.00a hk/sg 10/17/13 Initial release
48 * 2.1 hk 04/18/14 Increase sleep for eMMC switch command.
49 * Add sleep for microblaze designs. CR# 781117.
50 * 2.3 sk 09/23/14 Use XSdPs_Change_ClkFreq API whenever changing
52 * 2.5 sg 07/09/15 Added SD 3.0 features
53 * kvn 07/15/15 Modified the code according to MISRAC-2012.
54 * 2.7 sk 01/08/16 Added workaround for issue in auto tuning mode
55 * of SDR50, SDR104 and HS200.
56 * sk 02/16/16 Corrected the Tuning logic.
57 * sk 03/02/16 Configured the Tap Delay values for eMMC HS200 mode.
58 * 2.8 sk 04/20/16 Added new workaround for auto tuning.
59 * 3.0 sk 07/07/16 Used usleep API for both arm and microblaze.
60 * sk 07/16/16 Added support for UHS modes.
61 * sk 07/16/16 Added Tap delays accordingly to different SD/eMMC
63 * 3.1 mi 09/07/16 Removed compilation warnings with extra compiler flags.
64 * sk 11/07/16 Enable Rst_n bit in ext_csd reg if not enabled.
65 * sk 11/16/16 Issue DLL reset at 31 iteration to load new zero value.
69 ******************************************************************************/
71 /***************************** Include Files *********************************/
75 /************************** Constant Definitions *****************************/
76 #define UHS_SDR12_SUPPORT 0x1U
77 #define UHS_SDR25_SUPPORT 0x2U
78 #define UHS_SDR50_SUPPORT 0x4U
79 #define UHS_SDR104_SUPPORT 0x8U
80 #define UHS_DDR50_SUPPORT 0x10U
81 /**************************** Type Definitions *******************************/
83 /***************** Macros (Inline Functions) Definitions *********************/
85 /************************** Function Prototypes ******************************/
86 s32 XSdPs_CmdTransfer(XSdPs *InstancePtr, u32 Cmd, u32 Arg, u32 BlkCnt);
87 void XSdPs_SetupADMA2DescTbl(XSdPs *InstancePtr, u32 BlkCnt, const u8 *Buff);
88 static s32 XSdPs_Execute_Tuning(XSdPs *InstancePtr);
89 #if defined (ARMR5) || defined (__aarch64__)
90 s32 XSdPs_Uhs_ModeInit(XSdPs *InstancePtr, u8 Mode);
91 static void XSdPs_sdr50_tapdelay(u32 Bank, u32 DeviceId, u32 CardType);
92 static void XSdPs_ddr50_tapdelay(u32 Bank, u32 DeviceId, u32 CardType);
93 void XSdPs_SetTapDelay(XSdPs *InstancePtr);
94 static void XSdPs_DllReset(XSdPs *InstancePtr);
97 /*****************************************************************************/
99 * Update Block size for read/write operations.
101 * @param InstancePtr is a pointer to the instance to be worked on.
102 * @param BlkSize - Block size passed by the user.
106 ******************************************************************************/
107 s32 XSdPs_SetBlkSize(XSdPs *InstancePtr, u16 BlkSize)
112 Xil_AssertNonvoid(InstancePtr != NULL);
113 Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY);
115 PresentStateReg = XSdPs_ReadReg(InstancePtr->Config.BaseAddress,
116 XSDPS_PRES_STATE_OFFSET);
118 if ((PresentStateReg & ((u32)XSDPS_PSR_INHIBIT_CMD_MASK |
119 (u32)XSDPS_PSR_INHIBIT_DAT_MASK |
120 (u32)XSDPS_PSR_WR_ACTIVE_MASK | (u32)XSDPS_PSR_RD_ACTIVE_MASK)) != 0U) {
121 Status = XST_FAILURE;
126 /* Send block write command */
127 Status = XSdPs_CmdTransfer(InstancePtr, CMD16, BlkSize, 0U);
128 if (Status != XST_SUCCESS) {
129 Status = XST_FAILURE;
133 Status = (s32)XSdPs_ReadReg(InstancePtr->Config.BaseAddress,
136 /* Set block size to the value passed */
137 XSdPs_WriteReg16(InstancePtr->Config.BaseAddress, XSDPS_BLK_SIZE_OFFSET,
138 BlkSize & XSDPS_BLK_SIZE_MASK);
140 Status = XST_SUCCESS;
147 /*****************************************************************************/
150 * API to get bus width support by card.
153 * @param InstancePtr is a pointer to the XSdPs instance.
154 * @param SCR - buffer to store SCR register returned by card.
157 * - XST_SUCCESS if successful.
158 * - XST_FAILURE if fail.
162 ******************************************************************************/
163 s32 XSdPs_Get_BusWidth(XSdPs *InstancePtr, u8 *SCR)
171 Xil_AssertNonvoid(InstancePtr != NULL);
172 Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY);
174 for (LoopCnt = 0; LoopCnt < 8; LoopCnt++) {
178 /* Send block write command */
179 Status = XSdPs_CmdTransfer(InstancePtr, CMD55,
180 InstancePtr->RelCardAddr, 0U);
181 if (Status != XST_SUCCESS) {
182 Status = XST_FAILURE;
186 BlkCnt = XSDPS_SCR_BLKCNT;
187 BlkSize = XSDPS_SCR_BLKSIZE;
189 /* Set block size to the value passed */
190 BlkSize &= XSDPS_BLK_SIZE_MASK;
191 XSdPs_WriteReg16(InstancePtr->Config.BaseAddress,
192 XSDPS_BLK_SIZE_OFFSET, BlkSize);
194 XSdPs_SetupADMA2DescTbl(InstancePtr, BlkCnt, SCR);
196 XSdPs_WriteReg16(InstancePtr->Config.BaseAddress,
197 XSDPS_XFER_MODE_OFFSET,
198 XSDPS_TM_DAT_DIR_SEL_MASK | XSDPS_TM_DMA_EN_MASK);
200 Xil_DCacheInvalidateRange((INTPTR)SCR, 8);
202 Status = XSdPs_CmdTransfer(InstancePtr, ACMD51, 0U, BlkCnt);
203 if (Status != XST_SUCCESS) {
204 Status = XST_FAILURE;
209 * Check for transfer complete
210 * Polling for response for now
213 StatusReg = XSdPs_ReadReg16(InstancePtr->Config.BaseAddress,
214 XSDPS_NORM_INTR_STS_OFFSET);
215 if ((StatusReg & XSDPS_INTR_ERR_MASK) != 0U) {
216 /* Write to clear error bits */
217 XSdPs_WriteReg16(InstancePtr->Config.BaseAddress,
218 XSDPS_ERR_INTR_STS_OFFSET,
219 XSDPS_ERROR_INTR_ALL_MASK);
220 Status = XST_FAILURE;
223 } while ((StatusReg & XSDPS_INTR_TC_MASK) == 0U);
225 /* Write to clear bit */
226 XSdPs_WriteReg16(InstancePtr->Config.BaseAddress,
227 XSDPS_NORM_INTR_STS_OFFSET, XSDPS_INTR_TC_MASK);
229 Status = (s32)XSdPs_ReadReg(InstancePtr->Config.BaseAddress,
232 Status = XST_SUCCESS;
239 /*****************************************************************************/
242 * API to set bus width to 4-bit in card and host
245 * @param InstancePtr is a pointer to the XSdPs instance.
248 * - XST_SUCCESS if successful.
249 * - XST_FAILURE if fail.
253 ******************************************************************************/
254 s32 XSdPs_Change_BusWidth(XSdPs *InstancePtr)
260 Xil_AssertNonvoid(InstancePtr != NULL);
261 Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY);
264 if (InstancePtr->CardType == XSDPS_CARD_SD) {
266 Status = XSdPs_CmdTransfer(InstancePtr, CMD55, InstancePtr->RelCardAddr,
268 if (Status != XST_SUCCESS) {
269 Status = XST_FAILURE;
273 InstancePtr->BusWidth = XSDPS_4_BIT_WIDTH;
275 Arg = ((u32)InstancePtr->BusWidth);
277 Status = XSdPs_CmdTransfer(InstancePtr, ACMD6, Arg, 0U);
278 if (Status != XST_SUCCESS) {
279 Status = XST_FAILURE;
284 if ((InstancePtr->HC_Version == XSDPS_HC_SPEC_V3)
285 && (InstancePtr->CardType == XSDPS_CHIP_EMMC)) {
286 /* in case of eMMC data width 8-bit */
287 InstancePtr->BusWidth = XSDPS_8_BIT_WIDTH;
289 InstancePtr->BusWidth = XSDPS_4_BIT_WIDTH;
292 if (InstancePtr->BusWidth == XSDPS_8_BIT_WIDTH) {
293 Arg = XSDPS_MMC_8_BIT_BUS_ARG;
295 Arg = XSDPS_MMC_4_BIT_BUS_ARG;
298 Status = XSdPs_CmdTransfer(InstancePtr, CMD6, Arg, 0U);
299 if (Status != XST_SUCCESS) {
300 Status = XST_FAILURE;
304 /* Check for transfer complete */
306 StatusReg = XSdPs_ReadReg16(InstancePtr->Config.BaseAddress,
307 XSDPS_NORM_INTR_STS_OFFSET);
308 if ((StatusReg & XSDPS_INTR_ERR_MASK) != 0U) {
309 /* Write to clear error bits */
310 XSdPs_WriteReg16(InstancePtr->Config.BaseAddress,
311 XSDPS_ERR_INTR_STS_OFFSET,
312 XSDPS_ERROR_INTR_ALL_MASK);
313 Status = XST_FAILURE;
316 } while((StatusReg & XSDPS_INTR_TC_MASK) == 0U);
318 /* Write to clear bit */
319 XSdPs_WriteReg16(InstancePtr->Config.BaseAddress,
320 XSDPS_NORM_INTR_STS_OFFSET, XSDPS_INTR_TC_MASK);
323 usleep(XSDPS_MMC_DELAY_FOR_SWITCH);
325 StatusReg = XSdPs_ReadReg8(InstancePtr->Config.BaseAddress,
326 XSDPS_HOST_CTRL1_OFFSET);
328 /* Width setting in controller */
329 if (InstancePtr->BusWidth == XSDPS_8_BIT_WIDTH) {
330 StatusReg |= XSDPS_HC_EXT_BUS_WIDTH;
332 StatusReg |= XSDPS_HC_WIDTH_MASK;
335 XSdPs_WriteReg8(InstancePtr->Config.BaseAddress,
336 XSDPS_HOST_CTRL1_OFFSET,
339 Status = (s32)XSdPs_ReadReg(InstancePtr->Config.BaseAddress,
342 Status = XST_SUCCESS;
349 /*****************************************************************************/
352 * API to get bus speed supported by card.
355 * @param InstancePtr is a pointer to the XSdPs instance.
356 * @param ReadBuff - buffer to store function group support data
360 * - XST_SUCCESS if successful.
361 * - XST_FAILURE if fail.
365 ******************************************************************************/
366 s32 XSdPs_Get_BusSpeed(XSdPs *InstancePtr, u8 *ReadBuff)
375 Xil_AssertNonvoid(InstancePtr != NULL);
376 Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY);
378 for (LoopCnt = 0; LoopCnt < 64; LoopCnt++) {
379 ReadBuff[LoopCnt] = 0U;
382 BlkCnt = XSDPS_SWITCH_CMD_BLKCNT;
383 BlkSize = XSDPS_SWITCH_CMD_BLKSIZE;
384 BlkSize &= XSDPS_BLK_SIZE_MASK;
385 XSdPs_WriteReg16(InstancePtr->Config.BaseAddress,
386 XSDPS_BLK_SIZE_OFFSET, BlkSize);
388 XSdPs_SetupADMA2DescTbl(InstancePtr, BlkCnt, ReadBuff);
390 XSdPs_WriteReg16(InstancePtr->Config.BaseAddress,
391 XSDPS_XFER_MODE_OFFSET,
392 XSDPS_TM_DAT_DIR_SEL_MASK | XSDPS_TM_DMA_EN_MASK);
394 Arg = XSDPS_SWITCH_CMD_HS_GET;
396 Xil_DCacheInvalidateRange((INTPTR)ReadBuff, 64);
398 Status = XSdPs_CmdTransfer(InstancePtr, CMD6, Arg, 1U);
399 if (Status != XST_SUCCESS) {
400 Status = XST_FAILURE;
405 * Check for transfer complete
406 * Polling for response for now
409 StatusReg = XSdPs_ReadReg16(InstancePtr->Config.BaseAddress,
410 XSDPS_NORM_INTR_STS_OFFSET);
411 if ((StatusReg & XSDPS_INTR_ERR_MASK) != 0U) {
412 /* Write to clear error bits */
413 XSdPs_WriteReg16(InstancePtr->Config.BaseAddress,
414 XSDPS_ERR_INTR_STS_OFFSET,
415 XSDPS_ERROR_INTR_ALL_MASK);
416 Status = XST_FAILURE;
419 } while ((StatusReg & XSDPS_INTR_TC_MASK) == 0U);
421 /* Write to clear bit */
422 XSdPs_WriteReg16(InstancePtr->Config.BaseAddress,
423 XSDPS_NORM_INTR_STS_OFFSET, XSDPS_INTR_TC_MASK);
425 Status = (s32)XSdPs_ReadReg(InstancePtr->Config.BaseAddress,
428 Status = XST_SUCCESS;
435 /*****************************************************************************/
438 * API to set high speed in card and host. Changes clock in host accordingly.
441 * @param InstancePtr is a pointer to the XSdPs instance.
444 * - XST_SUCCESS if successful.
445 * - XST_FAILURE if fail.
449 ******************************************************************************/
450 s32 XSdPs_Change_BusSpeed(XSdPs *InstancePtr)
459 Xil_AssertNonvoid(InstancePtr != NULL);
460 Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY);
462 if (InstancePtr->CardType == XSDPS_CARD_SD) {
464 BlkCnt = XSDPS_SWITCH_CMD_BLKCNT;
465 BlkSize = XSDPS_SWITCH_CMD_BLKSIZE;
466 BlkSize &= XSDPS_BLK_SIZE_MASK;
467 XSdPs_WriteReg16(InstancePtr->Config.BaseAddress,
468 XSDPS_BLK_SIZE_OFFSET, BlkSize);
470 XSdPs_SetupADMA2DescTbl(InstancePtr, BlkCnt, ReadBuff);
472 Xil_DCacheFlushRange((INTPTR)ReadBuff, 64);
474 XSdPs_WriteReg16(InstancePtr->Config.BaseAddress,
475 XSDPS_XFER_MODE_OFFSET,
476 XSDPS_TM_DAT_DIR_SEL_MASK | XSDPS_TM_DMA_EN_MASK);
478 Arg = XSDPS_SWITCH_CMD_HS_SET;
480 Status = XSdPs_CmdTransfer(InstancePtr, CMD6, Arg, 1U);
481 if (Status != XST_SUCCESS) {
482 Status = XST_FAILURE;
487 * Check for transfer complete
488 * Polling for response for now
491 StatusReg = XSdPs_ReadReg16(InstancePtr->Config.BaseAddress,
492 XSDPS_NORM_INTR_STS_OFFSET);
493 if ((StatusReg & XSDPS_INTR_ERR_MASK) != 0U) {
494 /* Write to clear error bits */
495 XSdPs_WriteReg16(InstancePtr->Config.BaseAddress,
496 XSDPS_ERR_INTR_STS_OFFSET,
497 XSDPS_ERROR_INTR_ALL_MASK);
498 Status = XST_FAILURE;
501 } while ((StatusReg & XSDPS_INTR_TC_MASK) == 0U);
503 /* Write to clear bit */
504 XSdPs_WriteReg16(InstancePtr->Config.BaseAddress,
505 XSDPS_NORM_INTR_STS_OFFSET, XSDPS_INTR_TC_MASK);
507 /* Change the clock frequency to 50 MHz */
508 InstancePtr->BusSpeed = XSDPS_CLK_50_MHZ;
509 Status = XSdPs_Change_ClkFreq(InstancePtr, InstancePtr->BusSpeed);
510 if (Status != XST_SUCCESS) {
511 Status = XST_FAILURE;
515 } else if (InstancePtr->CardType == XSDPS_CARD_MMC) {
516 Arg = XSDPS_MMC_HIGH_SPEED_ARG;
518 Status = XSdPs_CmdTransfer(InstancePtr, CMD6, Arg, 0U);
519 if (Status != XST_SUCCESS) {
520 Status = XST_FAILURE;
525 * Check for transfer complete
528 StatusReg = XSdPs_ReadReg16(InstancePtr->Config.BaseAddress,
529 XSDPS_NORM_INTR_STS_OFFSET);
530 if ((StatusReg & XSDPS_INTR_ERR_MASK) != 0U) {
532 * Write to clear error bits
534 XSdPs_WriteReg16(InstancePtr->Config.BaseAddress,
535 XSDPS_ERR_INTR_STS_OFFSET,
536 XSDPS_ERROR_INTR_ALL_MASK);
537 Status = XST_FAILURE;
540 } while ((StatusReg & XSDPS_INTR_TC_MASK) == 0U);
545 XSdPs_WriteReg16(InstancePtr->Config.BaseAddress,
546 XSDPS_NORM_INTR_STS_OFFSET, XSDPS_INTR_TC_MASK);
548 /* Change the clock frequency to 52 MHz */
549 InstancePtr->BusSpeed = XSDPS_CLK_52_MHZ;
550 Status = XSdPs_Change_ClkFreq(InstancePtr, XSDPS_CLK_52_MHZ);
551 if (Status != XST_SUCCESS) {
552 Status = XST_FAILURE;
556 Arg = XSDPS_MMC_HS200_ARG;
558 Status = XSdPs_CmdTransfer(InstancePtr, CMD6, Arg, 0U);
559 if (Status != XST_SUCCESS) {
560 Status = XST_FAILURE;
565 * Check for transfer complete
568 StatusReg = XSdPs_ReadReg16(InstancePtr->Config.BaseAddress,
569 XSDPS_NORM_INTR_STS_OFFSET);
570 if ((StatusReg & XSDPS_INTR_ERR_MASK) != 0U) {
572 * Write to clear error bits
574 XSdPs_WriteReg16(InstancePtr->Config.BaseAddress,
575 XSDPS_ERR_INTR_STS_OFFSET,
576 XSDPS_ERROR_INTR_ALL_MASK);
577 Status = XST_FAILURE;
580 } while ((StatusReg & XSDPS_INTR_TC_MASK) == 0U);
585 XSdPs_WriteReg16(InstancePtr->Config.BaseAddress,
586 XSDPS_NORM_INTR_STS_OFFSET, XSDPS_INTR_TC_MASK);
588 /* Change the clock frequency to 200 MHz */
589 InstancePtr->BusSpeed = XSDPS_MMC_HS200_MAX_CLK;
591 Status = XSdPs_Change_ClkFreq(InstancePtr, InstancePtr->BusSpeed);
592 if (Status != XST_SUCCESS) {
593 Status = XST_FAILURE;
596 Status = XSdPs_Execute_Tuning(InstancePtr);
597 if (Status != XST_SUCCESS) {
598 Status = XST_FAILURE;
603 usleep(XSDPS_MMC_DELAY_FOR_SWITCH);
605 StatusReg = (s32)XSdPs_ReadReg8(InstancePtr->Config.BaseAddress,
606 XSDPS_HOST_CTRL1_OFFSET);
607 StatusReg |= XSDPS_HC_SPEED_MASK;
608 XSdPs_WriteReg8(InstancePtr->Config.BaseAddress,
609 XSDPS_HOST_CTRL1_OFFSET, (u8)StatusReg);
611 Status = (s32)XSdPs_ReadReg(InstancePtr->Config.BaseAddress,
615 Status = XST_SUCCESS;
622 /*****************************************************************************/
625 * API to change clock freq to given value.
628 * @param InstancePtr is a pointer to the XSdPs instance.
629 * @param SelFreq - Clock frequency in Hz.
633 * @note This API will change clock frequency to the value less than
634 * or equal to the given value using the permissible dividors.
636 ******************************************************************************/
637 s32 XSdPs_Change_ClkFreq(XSdPs *InstancePtr, u32 SelFreq)
646 Xil_AssertNonvoid(InstancePtr != NULL);
647 Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY);
650 ClockReg = XSdPs_ReadReg16(InstancePtr->Config.BaseAddress,
651 XSDPS_CLK_CTRL_OFFSET);
652 ClockReg &= ~(XSDPS_CC_SD_CLK_EN_MASK | XSDPS_CC_INT_CLK_EN_MASK);
653 XSdPs_WriteReg16(InstancePtr->Config.BaseAddress,
654 XSDPS_CLK_CTRL_OFFSET, ClockReg);
656 if (InstancePtr->HC_Version == XSDPS_HC_SPEC_V3) {
657 #if defined (ARMR5) || defined (__aarch64__)
658 if ((InstancePtr->Mode != XSDPS_DEFAULT_SPEED_MODE) &&
659 (InstancePtr->Mode != XSDPS_UHS_SPEED_MODE_SDR12))
660 /* Program the Tap delays */
661 XSdPs_SetTapDelay(InstancePtr);
663 /* Calculate divisor */
664 for (DivCnt = 0x1U; DivCnt <= XSDPS_CC_EXT_MAX_DIV_CNT;DivCnt++) {
665 if (((InstancePtr->Config.InputClockHz) / DivCnt) <= SelFreq) {
666 Divisor = DivCnt >> 1;
671 if (DivCnt > XSDPS_CC_EXT_MAX_DIV_CNT) {
672 /* No valid divisor found for given frequency */
673 Status = XST_FAILURE;
677 /* Calculate divisor */
679 while (DivCnt <= XSDPS_CC_MAX_DIV_CNT) {
680 if (((InstancePtr->Config.InputClockHz) / DivCnt) <= SelFreq) {
681 Divisor = DivCnt / 2U;
684 DivCnt = DivCnt << 1U;
687 if (DivCnt > XSDPS_CC_MAX_DIV_CNT) {
688 /* No valid divisor found for given frequency */
689 Status = XST_FAILURE;
694 /* Set clock divisor */
695 if (InstancePtr->HC_Version == XSDPS_HC_SPEC_V3) {
696 ClockReg = XSdPs_ReadReg16(InstancePtr->Config.BaseAddress,
697 XSDPS_CLK_CTRL_OFFSET);
698 ClockReg &= ~(XSDPS_CC_SDCLK_FREQ_SEL_MASK |
699 XSDPS_CC_SDCLK_FREQ_SEL_EXT_MASK);
701 ExtDivisor = Divisor >> 8;
702 ExtDivisor <<= XSDPS_CC_EXT_DIV_SHIFT;
703 ExtDivisor &= XSDPS_CC_SDCLK_FREQ_SEL_EXT_MASK;
705 Divisor <<= XSDPS_CC_DIV_SHIFT;
706 Divisor &= XSDPS_CC_SDCLK_FREQ_SEL_MASK;
707 ClockReg |= Divisor | ExtDivisor | (u16)XSDPS_CC_INT_CLK_EN_MASK;
708 XSdPs_WriteReg16(InstancePtr->Config.BaseAddress, XSDPS_CLK_CTRL_OFFSET,
711 ClockReg = XSdPs_ReadReg16(InstancePtr->Config.BaseAddress,
712 XSDPS_CLK_CTRL_OFFSET);
713 ClockReg &= (~XSDPS_CC_SDCLK_FREQ_SEL_MASK);
715 Divisor <<= XSDPS_CC_DIV_SHIFT;
716 Divisor &= XSDPS_CC_SDCLK_FREQ_SEL_MASK;
717 ClockReg |= Divisor | (u16)XSDPS_CC_INT_CLK_EN_MASK;
718 XSdPs_WriteReg16(InstancePtr->Config.BaseAddress, XSDPS_CLK_CTRL_OFFSET,
722 /* Wait for internal clock to stabilize */
723 ReadReg = XSdPs_ReadReg16(InstancePtr->Config.BaseAddress,
724 XSDPS_CLK_CTRL_OFFSET);
725 while((ReadReg & XSDPS_CC_INT_CLK_STABLE_MASK) == 0U) {
726 ReadReg = XSdPs_ReadReg16(InstancePtr->Config.BaseAddress,
727 XSDPS_CLK_CTRL_OFFSET);;
730 /* Enable SD clock */
731 ClockReg = XSdPs_ReadReg16(InstancePtr->Config.BaseAddress,
732 XSDPS_CLK_CTRL_OFFSET);
733 XSdPs_WriteReg16(InstancePtr->Config.BaseAddress,
734 XSDPS_CLK_CTRL_OFFSET,
735 ClockReg | XSDPS_CC_SD_CLK_EN_MASK);
737 Status = XST_SUCCESS;
744 /*****************************************************************************/
747 * API to send pullup command to card before using DAT line 3(using 4-bit bus)
750 * @param InstancePtr is a pointer to the XSdPs instance.
753 * - XST_SUCCESS if successful.
754 * - XST_FAILURE if fail.
758 ******************************************************************************/
759 s32 XSdPs_Pullup(XSdPs *InstancePtr)
763 Xil_AssertNonvoid(InstancePtr != NULL);
764 Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY);
766 Status = XSdPs_CmdTransfer(InstancePtr, CMD55,
767 InstancePtr->RelCardAddr, 0U);
768 if (Status != XST_SUCCESS) {
769 Status = XST_FAILURE;
773 Status = XSdPs_CmdTransfer(InstancePtr, ACMD42, 0U, 0U);
774 if (Status != XST_SUCCESS) {
775 Status = XST_FAILURE;
779 Status = XST_SUCCESS;
786 /*****************************************************************************/
789 * API to get EXT_CSD register of eMMC.
792 * @param InstancePtr is a pointer to the XSdPs instance.
793 * @param ReadBuff - buffer to store EXT_CSD
796 * - XST_SUCCESS if successful.
797 * - XST_FAILURE if fail.
801 ******************************************************************************/
802 s32 XSdPs_Get_Mmc_ExtCsd(XSdPs *InstancePtr, u8 *ReadBuff)
811 Xil_AssertNonvoid(InstancePtr != NULL);
812 Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY);
814 for (LoopCnt = 0; LoopCnt < 512; LoopCnt++) {
815 ReadBuff[LoopCnt] = 0U;
818 BlkCnt = XSDPS_EXT_CSD_CMD_BLKCNT;
819 BlkSize = XSDPS_EXT_CSD_CMD_BLKSIZE;
820 BlkSize &= XSDPS_BLK_SIZE_MASK;
821 XSdPs_WriteReg16(InstancePtr->Config.BaseAddress,
822 XSDPS_BLK_SIZE_OFFSET, BlkSize);
824 XSdPs_SetupADMA2DescTbl(InstancePtr, BlkCnt, ReadBuff);
826 Xil_DCacheInvalidateRange((INTPTR)ReadBuff, 512U);
828 XSdPs_WriteReg16(InstancePtr->Config.BaseAddress,
829 XSDPS_XFER_MODE_OFFSET,
830 XSDPS_TM_DAT_DIR_SEL_MASK | XSDPS_TM_DMA_EN_MASK);
833 /* Send SEND_EXT_CSD command */
834 Status = XSdPs_CmdTransfer(InstancePtr, CMD8, Arg, 1U);
835 if (Status != XST_SUCCESS) {
836 Status = XST_FAILURE;
841 * Check for transfer complete
842 * Polling for response for now
845 StatusReg = XSdPs_ReadReg16(InstancePtr->Config.BaseAddress,
846 XSDPS_NORM_INTR_STS_OFFSET);
847 if ((StatusReg & XSDPS_INTR_ERR_MASK) != 0U) {
848 /* Write to clear error bits */
849 XSdPs_WriteReg16(InstancePtr->Config.BaseAddress,
850 XSDPS_ERR_INTR_STS_OFFSET,
851 XSDPS_ERROR_INTR_ALL_MASK);
852 Status = XST_FAILURE;
855 } while ((StatusReg & XSDPS_INTR_TC_MASK) == 0U);
857 /* Write to clear bit */
858 XSdPs_WriteReg16(InstancePtr->Config.BaseAddress,
859 XSDPS_NORM_INTR_STS_OFFSET, XSDPS_INTR_TC_MASK);
861 Status = (s32)XSdPs_ReadReg(InstancePtr->Config.BaseAddress,
864 Status = XST_SUCCESS;
871 /*****************************************************************************/
874 * API to write EXT_CSD register of eMMC.
877 * @param InstancePtr is a pointer to the XSdPs instance.
878 * @param Arg is the argument to be sent along with the command
881 * - XST_SUCCESS if successful.
882 * - XST_FAILURE if fail.
886 ******************************************************************************/
887 s32 XSdPs_Set_Mmc_ExtCsd(XSdPs *InstancePtr, u32 Arg)
892 Status = XSdPs_CmdTransfer(InstancePtr, CMD6, Arg, 0U);
893 if (Status != XST_SUCCESS) {
894 Status = XST_FAILURE;
899 * Check for transfer complete
902 StatusReg = XSdPs_ReadReg16(InstancePtr->Config.BaseAddress,
903 XSDPS_NORM_INTR_STS_OFFSET);
904 if ((StatusReg & XSDPS_INTR_ERR_MASK) != 0U) {
906 * Write to clear error bits
908 XSdPs_WriteReg16(InstancePtr->Config.BaseAddress,
909 XSDPS_ERR_INTR_STS_OFFSET,
910 XSDPS_ERROR_INTR_ALL_MASK);
911 Status = XST_FAILURE;
914 } while ((StatusReg & XSDPS_INTR_TC_MASK) == 0U);
916 /* Write to clear bit */
917 XSdPs_WriteReg16(InstancePtr->Config.BaseAddress,
918 XSDPS_NORM_INTR_STS_OFFSET, XSDPS_INTR_TC_MASK);
920 Status = (s32)XSdPs_ReadReg(InstancePtr->Config.BaseAddress,
923 Status = XST_SUCCESS;
930 #if defined (ARMR5) || defined (__aarch64__)
931 /*****************************************************************************/
934 * API to Identify the supported UHS mode. This API will assign the
935 * corresponding tap delay API to the Config_TapDelay pointer based on the
936 * supported bus speed.
939 * @param InstancePtr is a pointer to the XSdPs instance.
940 * @param ReadBuff contains the response for CMD6
946 ******************************************************************************/
947 void XSdPs_Identify_UhsMode(XSdPs *InstancePtr, u8 *ReadBuff)
950 Xil_AssertVoid(InstancePtr != NULL);
952 if (((ReadBuff[13] & UHS_SDR104_SUPPORT) != 0U) &&
953 (InstancePtr->Config.InputClockHz >= XSDPS_MMC_HS200_MAX_CLK)) {
954 InstancePtr->Mode = XSDPS_UHS_SPEED_MODE_SDR104;
955 InstancePtr->Config_TapDelay = XSdPs_sdr104_hs200_tapdelay;
957 else if (((ReadBuff[13] & UHS_SDR50_SUPPORT) != 0U) &&
958 (InstancePtr->Config.InputClockHz >= XSDPS_SD_SDR50_MAX_CLK)) {
959 InstancePtr->Mode = XSDPS_UHS_SPEED_MODE_SDR50;
960 InstancePtr->Config_TapDelay = XSdPs_sdr50_tapdelay;
962 else if (((ReadBuff[13] & UHS_DDR50_SUPPORT) != 0U) &&
963 (InstancePtr->Config.InputClockHz >= XSDPS_SD_DDR50_MAX_CLK)) {
964 InstancePtr->Mode = XSDPS_UHS_SPEED_MODE_DDR50;
965 InstancePtr->Config_TapDelay = XSdPs_ddr50_tapdelay;
967 else if (((ReadBuff[13] & UHS_SDR25_SUPPORT) != 0U) &&
968 (InstancePtr->Config.InputClockHz >= XSDPS_SD_SDR25_MAX_CLK)) {
969 InstancePtr->Mode = XSDPS_UHS_SPEED_MODE_SDR25;
970 InstancePtr->Config_TapDelay = XSdPs_hsd_sdr25_tapdelay;
973 InstancePtr->Mode = XSDPS_UHS_SPEED_MODE_SDR12;
976 /*****************************************************************************/
979 * API to UHS-I mode initialization
982 * @param InstancePtr is a pointer to the XSdPs instance.
983 * @param Mode UHS-I mode
986 * - XST_SUCCESS if successful.
987 * - XST_FAILURE if fail.
991 ******************************************************************************/
992 s32 XSdPs_Uhs_ModeInit(XSdPs *InstancePtr, u8 Mode)
1002 Xil_AssertNonvoid(InstancePtr != NULL);
1003 Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY);
1005 /* Drive strength */
1007 /* Bus speed mode selection */
1008 BlkCnt = XSDPS_SWITCH_CMD_BLKCNT;
1009 BlkSize = XSDPS_SWITCH_CMD_BLKSIZE;
1010 BlkSize &= XSDPS_BLK_SIZE_MASK;
1011 XSdPs_WriteReg16(InstancePtr->Config.BaseAddress, XSDPS_BLK_SIZE_OFFSET,
1014 XSdPs_SetupADMA2DescTbl(InstancePtr, BlkCnt, ReadBuff);
1016 Xil_DCacheFlushRange((INTPTR)ReadBuff, 64);
1018 XSdPs_WriteReg16(InstancePtr->Config.BaseAddress, XSDPS_XFER_MODE_OFFSET,
1019 XSDPS_TM_DAT_DIR_SEL_MASK | XSDPS_TM_DMA_EN_MASK);
1023 Arg = XSDPS_SWITCH_CMD_SDR12_SET;
1024 InstancePtr->BusSpeed = XSDPS_SD_SDR12_MAX_CLK;
1027 Arg = XSDPS_SWITCH_CMD_SDR25_SET;
1028 InstancePtr->BusSpeed = XSDPS_SD_SDR25_MAX_CLK;
1031 Arg = XSDPS_SWITCH_CMD_SDR50_SET;
1032 InstancePtr->BusSpeed = XSDPS_SD_SDR50_MAX_CLK;
1035 Arg = XSDPS_SWITCH_CMD_SDR104_SET;
1036 InstancePtr->BusSpeed = XSDPS_SD_SDR104_MAX_CLK;
1039 Arg = XSDPS_SWITCH_CMD_DDR50_SET;
1040 InstancePtr->BusSpeed = XSDPS_SD_DDR50_MAX_CLK;
1043 Status = XST_FAILURE;
1048 Status = XSdPs_CmdTransfer(InstancePtr, CMD6, Arg, 1U);
1049 if (Status != XST_SUCCESS) {
1050 Status = XST_FAILURE;
1055 * Check for transfer complete
1056 * Polling for response for now
1059 StatusReg = XSdPs_ReadReg16(InstancePtr->Config.BaseAddress,
1060 XSDPS_NORM_INTR_STS_OFFSET);
1061 if ((StatusReg & XSDPS_INTR_ERR_MASK) != 0U) {
1062 /* Write to clear error bits */
1063 XSdPs_WriteReg16(InstancePtr->Config.BaseAddress,
1064 XSDPS_ERR_INTR_STS_OFFSET, XSDPS_ERROR_INTR_ALL_MASK);
1065 Status = XST_FAILURE;
1068 } while ((StatusReg & XSDPS_INTR_TC_MASK) == 0U);
1070 /* Write to clear bit */
1071 XSdPs_WriteReg16(InstancePtr->Config.BaseAddress,
1072 XSDPS_NORM_INTR_STS_OFFSET, XSDPS_INTR_TC_MASK);
1077 /* Set UHS mode in controller */
1078 CtrlReg = XSdPs_ReadReg16(InstancePtr->Config.BaseAddress,
1079 XSDPS_HOST_CTRL2_OFFSET);
1080 CtrlReg &= (u16)(~XSDPS_HC2_UHS_MODE_MASK);
1082 XSdPs_WriteReg16(InstancePtr->Config.BaseAddress,
1083 XSDPS_HOST_CTRL2_OFFSET, CtrlReg);
1085 /* Change the clock frequency */
1086 Status = XSdPs_Change_ClkFreq(InstancePtr, InstancePtr->BusSpeed);
1087 if (Status != XST_SUCCESS) {
1088 Status = XST_FAILURE;
1092 if((Mode == XSDPS_UHS_SPEED_MODE_SDR104) ||
1093 (Mode == XSDPS_UHS_SPEED_MODE_SDR50)) {
1094 /* Send tuning pattern */
1095 Status = XSdPs_Execute_Tuning(InstancePtr);
1096 if (Status != XST_SUCCESS) {
1097 Status = XST_FAILURE;
1102 Status = XST_SUCCESS;
1109 static s32 XSdPs_Execute_Tuning(XSdPs *InstancePtr)
1116 Xil_AssertNonvoid(InstancePtr != NULL);
1117 Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY);
1119 BlkSize = XSDPS_TUNING_CMD_BLKSIZE;
1120 if(InstancePtr->BusWidth == XSDPS_8_BIT_WIDTH)
1122 BlkSize = BlkSize*2U;
1124 BlkSize &= XSDPS_BLK_SIZE_MASK;
1125 XSdPs_WriteReg16(InstancePtr->Config.BaseAddress, XSDPS_BLK_SIZE_OFFSET,
1128 XSdPs_WriteReg16(InstancePtr->Config.BaseAddress, XSDPS_XFER_MODE_OFFSET,
1129 XSDPS_TM_DAT_DIR_SEL_MASK);
1131 CtrlReg = XSdPs_ReadReg16(InstancePtr->Config.BaseAddress,
1132 XSDPS_HOST_CTRL2_OFFSET);
1133 CtrlReg |= XSDPS_HC2_EXEC_TNG_MASK;
1134 XSdPs_WriteReg16(InstancePtr->Config.BaseAddress,
1135 XSDPS_HOST_CTRL2_OFFSET, CtrlReg);
1138 * workaround which can work for 1.0/2.0 silicon for auto tuning.
1139 * This can be revisited for 3.0 silicon if necessary.
1141 /* Wait for ~60 clock cycles to reset the tap values */
1144 #if defined (ARMR5) || defined (__aarch64__)
1145 /* Issue DLL Reset to load new SDHC tuned tap values */
1146 XSdPs_DllReset(InstancePtr);
1149 for (TuningCount = 0U; TuningCount < MAX_TUNING_COUNT; TuningCount++) {
1151 if (InstancePtr->CardType == XSDPS_CARD_SD) {
1152 Status = XSdPs_CmdTransfer(InstancePtr, CMD19, 0U, 1U);
1154 Status = XSdPs_CmdTransfer(InstancePtr, CMD21, 0U, 1U);
1157 if (Status != XST_SUCCESS) {
1158 Status = XST_FAILURE;
1162 if ((XSdPs_ReadReg16(InstancePtr->Config.BaseAddress,
1163 XSDPS_HOST_CTRL2_OFFSET) & XSDPS_HC2_EXEC_TNG_MASK) == 0U) {
1167 if (TuningCount == 31) {
1168 #if defined (ARMR5) || defined (__aarch64__)
1169 /* Issue DLL Reset to load new SDHC tuned tap values */
1170 XSdPs_DllReset(InstancePtr);
1175 if ((XSdPs_ReadReg16(InstancePtr->Config.BaseAddress,
1176 XSDPS_HOST_CTRL2_OFFSET) & XSDPS_HC2_SAMP_CLK_SEL_MASK) == 0U) {
1177 Status = XST_FAILURE;
1181 /* Wait for ~12 clock cycles to synchronize the new tap values */
1184 #if defined (ARMR5) || defined (__aarch64__)
1185 /* Issue DLL Reset to load new SDHC tuned tap values */
1186 XSdPs_DllReset(InstancePtr);
1189 Status = XST_SUCCESS;
1191 RETURN_PATH: return Status;
1195 #if defined (ARMR5) || defined (__aarch64__)
1196 /*****************************************************************************/
1199 * API to set Tap Delay for SDR104 and HS200 modes
1202 * @param InstancePtr is a pointer to the XSdPs instance.
1208 ******************************************************************************/
1209 void XSdPs_sdr104_hs200_tapdelay(u32 Bank, u32 DeviceId, u32 CardType)
1214 #ifdef XPAR_PSU_SD_0_DEVICE_ID
1215 if (DeviceId == 0U) {
1216 /* Program the OTAPDLY */
1217 TapDelay = XSdPs_ReadReg(XPS_SYS_CTRL_BASEADDR, SD_OTAPDLY);
1218 TapDelay |= SD0_OTAPDLYENA;
1219 XSdPs_WriteReg(XPS_SYS_CTRL_BASEADDR, SD_OTAPDLY, TapDelay);
1221 TapDelay |= SD0_OTAPDLYSEL_HS200_B2;
1223 TapDelay |= SD0_OTAPDLYSEL_HS200_B0;
1224 XSdPs_WriteReg(XPS_SYS_CTRL_BASEADDR, SD_OTAPDLY, TapDelay);
1227 TapDelay = XSdPs_ReadReg(XPS_SYS_CTRL_BASEADDR, SD_OTAPDLY);
1228 TapDelay |= SD1_OTAPDLYENA;
1229 XSdPs_WriteReg(XPS_SYS_CTRL_BASEADDR, SD_OTAPDLY, TapDelay);
1231 TapDelay |= SD1_OTAPDLYSEL_HS200_B2;
1233 TapDelay |= SD1_OTAPDLYSEL_HS200_B0;
1234 XSdPs_WriteReg(XPS_SYS_CTRL_BASEADDR, SD_OTAPDLY, TapDelay);
1235 #ifdef XPAR_PSU_SD_0_DEVICE_ID
1240 /*****************************************************************************/
1243 * API to set Tap Delay for SDR50 mode
1246 * @param InstancePtr is a pointer to the XSdPs instance.
1252 ******************************************************************************/
1253 void XSdPs_sdr50_tapdelay(u32 Bank, u32 DeviceId, u32 CardType)
1259 #ifdef XPAR_PSU_SD_0_DEVICE_ID
1260 if (DeviceId == 0U) {
1261 /* Program the OTAPDLY */
1262 TapDelay = XSdPs_ReadReg(XPS_SYS_CTRL_BASEADDR, SD_OTAPDLY);
1263 TapDelay |= SD0_OTAPDLYENA;
1264 XSdPs_WriteReg(XPS_SYS_CTRL_BASEADDR, SD_OTAPDLY, TapDelay);
1265 TapDelay |= SD0_OTAPDLYSEL_SD50;
1266 XSdPs_WriteReg(XPS_SYS_CTRL_BASEADDR, SD_OTAPDLY, TapDelay);
1269 TapDelay = XSdPs_ReadReg(XPS_SYS_CTRL_BASEADDR, SD_OTAPDLY);
1270 TapDelay |= SD1_OTAPDLYENA;
1271 XSdPs_WriteReg(XPS_SYS_CTRL_BASEADDR, SD_OTAPDLY, TapDelay);
1272 TapDelay |= SD1_OTAPDLYSEL_SD50;
1273 XSdPs_WriteReg(XPS_SYS_CTRL_BASEADDR, SD_OTAPDLY, TapDelay);
1274 #ifdef XPAR_PSU_SD_0_DEVICE_ID
1279 /*****************************************************************************/
1282 * API to set Tap Delay for DDR50 mode
1285 * @param InstancePtr is a pointer to the XSdPs instance.
1291 ******************************************************************************/
1292 void XSdPs_ddr50_tapdelay(u32 Bank, u32 DeviceId, u32 CardType)
1297 #ifdef XPAR_PSU_SD_0_DEVICE_ID
1298 if (DeviceId == 0U) {
1299 TapDelay = XSdPs_ReadReg(XPS_SYS_CTRL_BASEADDR, SD_ITAPDLY);
1300 TapDelay |= SD0_ITAPCHGWIN;
1301 XSdPs_WriteReg(XPS_SYS_CTRL_BASEADDR, SD_ITAPDLY, TapDelay);
1302 /* Program the ITAPDLY */
1303 TapDelay |= SD0_ITAPDLYENA;
1304 XSdPs_WriteReg(XPS_SYS_CTRL_BASEADDR, SD_ITAPDLY, TapDelay);
1305 if (CardType== XSDPS_CARD_SD)
1306 TapDelay |= SD0_ITAPDLYSEL_SD_DDR50;
1308 TapDelay |= SD0_ITAPDLYSEL_EMMC_DDR50;
1309 XSdPs_WriteReg(XPS_SYS_CTRL_BASEADDR, SD_ITAPDLY, TapDelay);
1310 TapDelay &= ~SD0_ITAPCHGWIN;
1311 XSdPs_WriteReg(XPS_SYS_CTRL_BASEADDR, SD_ITAPDLY, TapDelay);
1312 /* Program the OTAPDLY */
1313 TapDelay = XSdPs_ReadReg(XPS_SYS_CTRL_BASEADDR, SD_OTAPDLY);
1314 TapDelay |= SD0_OTAPDLYENA;
1315 XSdPs_WriteReg(XPS_SYS_CTRL_BASEADDR, SD_OTAPDLY, TapDelay);
1316 if (CardType == XSDPS_CARD_SD)
1317 TapDelay |= SD0_OTAPDLYSEL_SD_DDR50;
1319 TapDelay |= SD0_OTAPDLYSEL_EMMC_DDR50;
1320 XSdPs_WriteReg(XPS_SYS_CTRL_BASEADDR, SD_OTAPDLY, TapDelay);
1323 TapDelay = XSdPs_ReadReg(XPS_SYS_CTRL_BASEADDR, SD_ITAPDLY);
1324 TapDelay |= SD1_ITAPCHGWIN;
1325 XSdPs_WriteReg(XPS_SYS_CTRL_BASEADDR, SD_ITAPDLY, TapDelay);
1326 /* Program the ITAPDLY */
1327 TapDelay |= SD1_ITAPDLYENA;
1328 XSdPs_WriteReg(XPS_SYS_CTRL_BASEADDR, SD_ITAPDLY, TapDelay);
1329 if (CardType == XSDPS_CARD_SD)
1330 TapDelay |= SD1_ITAPDLYSEL_SD_DDR50;
1332 TapDelay |= SD1_ITAPDLYSEL_EMMC_DDR50;
1333 XSdPs_WriteReg(XPS_SYS_CTRL_BASEADDR, SD_ITAPDLY, TapDelay);
1334 TapDelay &= ~SD1_ITAPCHGWIN;
1335 XSdPs_WriteReg(XPS_SYS_CTRL_BASEADDR, SD_ITAPDLY, TapDelay);
1336 /* Program the OTAPDLY */
1337 TapDelay = XSdPs_ReadReg(XPS_SYS_CTRL_BASEADDR, SD_OTAPDLY);
1338 TapDelay |= SD1_OTAPDLYENA;
1339 XSdPs_WriteReg(XPS_SYS_CTRL_BASEADDR, SD_OTAPDLY, TapDelay);
1340 if (CardType == XSDPS_CARD_SD)
1341 TapDelay |= SD1_OTAPDLYSEL_SD_DDR50;
1343 TapDelay |= SD1_OTAPDLYSEL_EMMC_DDR50;
1344 XSdPs_WriteReg(XPS_SYS_CTRL_BASEADDR, SD_OTAPDLY, TapDelay);
1345 #ifdef XPAR_PSU_SD_0_DEVICE_ID
1350 /*****************************************************************************/
1353 * API to set Tap Delay for HSD and SDR25 mode
1356 * @param InstancePtr is a pointer to the XSdPs instance.
1362 ******************************************************************************/
1363 void XSdPs_hsd_sdr25_tapdelay(u32 Bank, u32 DeviceId, u32 CardType)
1368 #ifdef XPAR_PSU_SD_0_DEVICE_ID
1369 if (DeviceId == 0U) {
1370 TapDelay = XSdPs_ReadReg(XPS_SYS_CTRL_BASEADDR, SD_ITAPDLY);
1371 TapDelay |= SD0_ITAPCHGWIN;
1372 XSdPs_WriteReg(XPS_SYS_CTRL_BASEADDR, SD_ITAPDLY, TapDelay);
1373 /* Program the ITAPDLY */
1374 TapDelay |= SD0_ITAPDLYENA;
1375 XSdPs_WriteReg(XPS_SYS_CTRL_BASEADDR, SD_ITAPDLY, TapDelay);
1376 TapDelay |= SD0_ITAPDLYSEL_HSD;
1377 XSdPs_WriteReg(XPS_SYS_CTRL_BASEADDR, SD_ITAPDLY, TapDelay);
1378 TapDelay &= ~SD0_ITAPCHGWIN;
1379 XSdPs_WriteReg(XPS_SYS_CTRL_BASEADDR, SD_ITAPDLY, TapDelay);
1380 /* Program the OTAPDLY */
1381 TapDelay = XSdPs_ReadReg(XPS_SYS_CTRL_BASEADDR, SD_OTAPDLY);
1382 TapDelay |= SD0_OTAPDLYENA;
1383 XSdPs_WriteReg(XPS_SYS_CTRL_BASEADDR, SD_OTAPDLY, TapDelay);
1384 if (CardType == XSDPS_CARD_SD)
1385 TapDelay |= SD0_OTAPDLYSEL_SD_HSD;
1387 TapDelay |= SD0_OTAPDLYSEL_EMMC_HSD;
1388 XSdPs_WriteReg(XPS_SYS_CTRL_BASEADDR, SD_OTAPDLY, TapDelay);
1391 TapDelay = XSdPs_ReadReg(XPS_SYS_CTRL_BASEADDR, SD_ITAPDLY);
1392 TapDelay |= SD1_ITAPCHGWIN;
1393 XSdPs_WriteReg(XPS_SYS_CTRL_BASEADDR, SD_ITAPDLY, TapDelay);
1394 /* Program the ITAPDLY */
1395 TapDelay |= SD1_ITAPDLYENA;
1396 XSdPs_WriteReg(XPS_SYS_CTRL_BASEADDR, SD_ITAPDLY, TapDelay);
1397 TapDelay |= SD1_ITAPDLYSEL_HSD;
1398 XSdPs_WriteReg(XPS_SYS_CTRL_BASEADDR, SD_ITAPDLY, TapDelay);
1399 TapDelay &= ~SD1_ITAPCHGWIN;
1400 XSdPs_WriteReg(XPS_SYS_CTRL_BASEADDR, SD_ITAPDLY, TapDelay);
1401 /* Program the OTAPDLY */
1402 TapDelay = XSdPs_ReadReg(XPS_SYS_CTRL_BASEADDR, SD_OTAPDLY);
1403 TapDelay |= SD1_OTAPDLYENA;
1404 XSdPs_WriteReg(XPS_SYS_CTRL_BASEADDR, SD_OTAPDLY, TapDelay);
1405 if (CardType == XSDPS_CARD_SD)
1406 TapDelay |= SD1_OTAPDLYSEL_SD_HSD;
1408 TapDelay |= SD1_OTAPDLYSEL_EMMC_HSD;
1409 XSdPs_WriteReg(XPS_SYS_CTRL_BASEADDR, SD_OTAPDLY, TapDelay);
1410 #ifdef XPAR_PSU_SD_0_DEVICE_ID
1415 /*****************************************************************************/
1418 * API to set Tap Delay w.r.t speed modes
1421 * @param InstancePtr is a pointer to the XSdPs instance.
1427 ******************************************************************************/
1428 void XSdPs_SetTapDelay(XSdPs *InstancePtr)
1430 u32 DllCtrl, BankNum, DeviceId, CardType;
1432 BankNum = InstancePtr->Config.BankNumber;
1433 DeviceId = InstancePtr->Config.DeviceId ;
1434 CardType = InstancePtr->CardType ;
1435 #ifdef XPAR_PSU_SD_0_DEVICE_ID
1436 if (DeviceId == 0U) {
1437 DllCtrl = XSdPs_ReadReg(XPS_SYS_CTRL_BASEADDR, SD_DLL_CTRL);
1438 DllCtrl |= SD0_DLL_RST;
1439 XSdPs_WriteReg(XPS_SYS_CTRL_BASEADDR, SD_DLL_CTRL, DllCtrl);
1440 InstancePtr->Config_TapDelay(BankNum, DeviceId, CardType);
1441 DllCtrl &= ~SD0_DLL_RST;
1442 XSdPs_WriteReg(XPS_SYS_CTRL_BASEADDR, SD_DLL_CTRL, DllCtrl);
1445 DllCtrl = XSdPs_ReadReg(XPS_SYS_CTRL_BASEADDR, SD_DLL_CTRL);
1446 DllCtrl |= SD1_DLL_RST;
1447 XSdPs_WriteReg(XPS_SYS_CTRL_BASEADDR, SD_DLL_CTRL, DllCtrl);
1448 InstancePtr->Config_TapDelay(BankNum, DeviceId, CardType);
1449 DllCtrl &= ~SD1_DLL_RST;
1450 XSdPs_WriteReg(XPS_SYS_CTRL_BASEADDR, SD_DLL_CTRL, DllCtrl);
1451 #ifdef XPAR_PSU_SD_0_DEVICE_ID
1456 /*****************************************************************************/
1459 * API to reset the DLL
1462 * @param InstancePtr is a pointer to the XSdPs instance.
1468 ******************************************************************************/
1469 static void XSdPs_DllReset(XSdPs *InstancePtr)
1471 u32 ClockReg, DllCtrl;
1474 ClockReg = XSdPs_ReadReg16(InstancePtr->Config.BaseAddress,
1475 XSDPS_CLK_CTRL_OFFSET);
1476 ClockReg &= ~XSDPS_CC_SD_CLK_EN_MASK;
1477 XSdPs_WriteReg16(InstancePtr->Config.BaseAddress,
1478 XSDPS_CLK_CTRL_OFFSET, ClockReg);
1480 /* Issue DLL Reset to load zero tap values */
1481 DllCtrl = XSdPs_ReadReg(XPS_SYS_CTRL_BASEADDR, SD_DLL_CTRL);
1482 if (InstancePtr->Config.DeviceId == 0U) {
1483 DllCtrl |= SD0_DLL_RST;
1485 DllCtrl |= SD1_DLL_RST;
1487 XSdPs_WriteReg(XPS_SYS_CTRL_BASEADDR, SD_DLL_CTRL, DllCtrl);
1489 /* Wait for 2 micro seconds */
1492 /* Release the DLL out of reset */
1493 DllCtrl = XSdPs_ReadReg(XPS_SYS_CTRL_BASEADDR, SD_DLL_CTRL);
1494 if (InstancePtr->Config.DeviceId == 0U) {
1495 DllCtrl &= ~SD0_DLL_RST;
1497 DllCtrl &= ~SD1_DLL_RST;
1499 XSdPs_WriteReg(XPS_SYS_CTRL_BASEADDR, SD_DLL_CTRL, DllCtrl);
1501 /* Wait for internal clock to stabilize */
1502 ClockReg = XSdPs_ReadReg16(InstancePtr->Config.BaseAddress,
1503 XSDPS_CLK_CTRL_OFFSET);
1504 while((ClockReg & XSDPS_CC_INT_CLK_STABLE_MASK) == 0U) {
1505 ClockReg = XSdPs_ReadReg16(InstancePtr->Config.BaseAddress,
1506 XSDPS_CLK_CTRL_OFFSET);
1509 /* Enable SD clock */
1510 ClockReg = XSdPs_ReadReg16(InstancePtr->Config.BaseAddress,
1511 XSDPS_CLK_CTRL_OFFSET);
1512 XSdPs_WriteReg16(InstancePtr->Config.BaseAddress,
1513 XSDPS_CLK_CTRL_OFFSET,
1514 ClockReg | XSDPS_CC_SD_CLK_EN_MASK);