1 /******************************************************************************
3 * Copyright (C) 2013 - 2015 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.
61 ******************************************************************************/
63 /***************************** Include Files *********************************/
66 * The header sleep.h and API usleep() can only be used with an arm design.
67 * MB_Sleep() is used for microblaze design.
69 #if defined (__arm__) || defined (__aarch64__)
77 #include "microblaze_sleep.h"
81 /************************** Constant Definitions *****************************/
83 /**************************** Type Definitions *******************************/
85 /***************** Macros (Inline Functions) Definitions *********************/
87 /************************** Function Prototypes ******************************/
88 s32 XSdPs_CmdTransfer(XSdPs *InstancePtr, u32 Cmd, u32 Arg, u32 BlkCnt);
89 void XSdPs_SetupADMA2DescTbl(XSdPs *InstancePtr, u32 BlkCnt, const u8 *Buff);
90 s32 XSdPs_Uhs_ModeInit(XSdPs *InstancePtr, u8 Mode);
91 static s32 XSdPs_Execute_Tuning(XSdPs *InstancePtr);
92 s32 XSdPs_Uhs_ModeInit(XSdPs *InstancePtr, u8 Mode);
93 #if defined (__arm__) || defined (__aarch64__)
94 void XSdPs_SetTapDelay(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 #if defined (__arm__) || defined (__aarch64__)
325 usleep(XSDPS_MMC_DELAY_FOR_SWITCH);
329 #ifdef __MICROBLAZE__
336 StatusReg = XSdPs_ReadReg8(InstancePtr->Config.BaseAddress,
337 XSDPS_HOST_CTRL1_OFFSET);
339 /* Width setting in controller */
340 if (InstancePtr->BusWidth == XSDPS_8_BIT_WIDTH) {
341 StatusReg |= XSDPS_HC_EXT_BUS_WIDTH;
343 StatusReg |= XSDPS_HC_WIDTH_MASK;
346 XSdPs_WriteReg8(InstancePtr->Config.BaseAddress,
347 XSDPS_HOST_CTRL1_OFFSET,
350 Status = (s32)XSdPs_ReadReg(InstancePtr->Config.BaseAddress,
353 Status = XST_SUCCESS;
360 /*****************************************************************************/
363 * API to get bus speed supported by card.
366 * @param InstancePtr is a pointer to the XSdPs instance.
367 * @param ReadBuff - buffer to store function group support data
371 * - XST_SUCCESS if successful.
372 * - XST_FAILURE if fail.
376 ******************************************************************************/
377 s32 XSdPs_Get_BusSpeed(XSdPs *InstancePtr, u8 *ReadBuff)
386 Xil_AssertNonvoid(InstancePtr != NULL);
387 Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY);
389 for (LoopCnt = 0; LoopCnt < 64; LoopCnt++) {
390 ReadBuff[LoopCnt] = 0U;
393 BlkCnt = XSDPS_SWITCH_CMD_BLKCNT;
394 BlkSize = XSDPS_SWITCH_CMD_BLKSIZE;
395 BlkSize &= XSDPS_BLK_SIZE_MASK;
396 XSdPs_WriteReg16(InstancePtr->Config.BaseAddress,
397 XSDPS_BLK_SIZE_OFFSET, BlkSize);
399 XSdPs_SetupADMA2DescTbl(InstancePtr, BlkCnt, ReadBuff);
401 XSdPs_WriteReg16(InstancePtr->Config.BaseAddress,
402 XSDPS_XFER_MODE_OFFSET,
403 XSDPS_TM_DAT_DIR_SEL_MASK | XSDPS_TM_DMA_EN_MASK);
405 Arg = XSDPS_SWITCH_CMD_HS_GET;
407 Xil_DCacheInvalidateRange((INTPTR)ReadBuff, 64);
409 Status = XSdPs_CmdTransfer(InstancePtr, CMD6, Arg, 1U);
410 if (Status != XST_SUCCESS) {
411 Status = XST_FAILURE;
416 * Check for transfer complete
417 * Polling for response for now
420 StatusReg = XSdPs_ReadReg16(InstancePtr->Config.BaseAddress,
421 XSDPS_NORM_INTR_STS_OFFSET);
422 if ((StatusReg & XSDPS_INTR_ERR_MASK) != 0U) {
423 /* Write to clear error bits */
424 XSdPs_WriteReg16(InstancePtr->Config.BaseAddress,
425 XSDPS_ERR_INTR_STS_OFFSET,
426 XSDPS_ERROR_INTR_ALL_MASK);
427 Status = XST_FAILURE;
430 } while ((StatusReg & XSDPS_INTR_TC_MASK) == 0U);
432 /* Write to clear bit */
433 XSdPs_WriteReg16(InstancePtr->Config.BaseAddress,
434 XSDPS_NORM_INTR_STS_OFFSET, XSDPS_INTR_TC_MASK);
436 Status = (s32)XSdPs_ReadReg(InstancePtr->Config.BaseAddress,
439 Status = XST_SUCCESS;
446 /*****************************************************************************/
449 * API to set high speed in card and host. Changes clock in host accordingly.
452 * @param InstancePtr is a pointer to the XSdPs instance.
455 * - XST_SUCCESS if successful.
456 * - XST_FAILURE if fail.
460 ******************************************************************************/
461 s32 XSdPs_Change_BusSpeed(XSdPs *InstancePtr)
471 Xil_AssertNonvoid(InstancePtr != NULL);
472 Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY);
474 if (InstancePtr->CardType == XSDPS_CARD_SD) {
476 BlkCnt = XSDPS_SWITCH_CMD_BLKCNT;
477 BlkSize = XSDPS_SWITCH_CMD_BLKSIZE;
478 BlkSize &= XSDPS_BLK_SIZE_MASK;
479 XSdPs_WriteReg16(InstancePtr->Config.BaseAddress,
480 XSDPS_BLK_SIZE_OFFSET, BlkSize);
482 XSdPs_SetupADMA2DescTbl(InstancePtr, BlkCnt, ReadBuff);
484 Xil_DCacheFlushRange((INTPTR)ReadBuff, 64);
486 XSdPs_WriteReg16(InstancePtr->Config.BaseAddress,
487 XSDPS_XFER_MODE_OFFSET,
488 XSDPS_TM_DAT_DIR_SEL_MASK | XSDPS_TM_DMA_EN_MASK);
490 Arg = XSDPS_SWITCH_CMD_HS_SET;
492 Status = XSdPs_CmdTransfer(InstancePtr, CMD6, Arg, 1U);
493 if (Status != XST_SUCCESS) {
494 Status = XST_FAILURE;
499 * Check for transfer complete
500 * Polling for response for now
503 StatusReg = XSdPs_ReadReg16(InstancePtr->Config.BaseAddress,
504 XSDPS_NORM_INTR_STS_OFFSET);
505 if ((StatusReg & XSDPS_INTR_ERR_MASK) != 0U) {
506 /* Write to clear error bits */
507 XSdPs_WriteReg16(InstancePtr->Config.BaseAddress,
508 XSDPS_ERR_INTR_STS_OFFSET,
509 XSDPS_ERROR_INTR_ALL_MASK);
510 Status = XST_FAILURE;
513 } while ((StatusReg & XSDPS_INTR_TC_MASK) == 0U);
515 /* Write to clear bit */
516 XSdPs_WriteReg16(InstancePtr->Config.BaseAddress,
517 XSDPS_NORM_INTR_STS_OFFSET, XSDPS_INTR_TC_MASK);
519 /* Change the clock frequency to 50 MHz */
520 InstancePtr->BusSpeed = XSDPS_CLK_50_MHZ;
521 Status = XSdPs_Change_ClkFreq(InstancePtr, InstancePtr->BusSpeed);
522 if (Status != XST_SUCCESS) {
523 Status = XST_FAILURE;
527 } else if (InstancePtr->CardType == XSDPS_CARD_MMC) {
528 Arg = XSDPS_MMC_HIGH_SPEED_ARG;
530 Status = XSdPs_CmdTransfer(InstancePtr, CMD6, Arg, 0U);
531 if (Status != XST_SUCCESS) {
532 Status = XST_FAILURE;
537 * Check for transfer complete
540 StatusReg = XSdPs_ReadReg16(InstancePtr->Config.BaseAddress,
541 XSDPS_NORM_INTR_STS_OFFSET);
542 if ((StatusReg & XSDPS_INTR_ERR_MASK) != 0U) {
544 * Write to clear error bits
546 XSdPs_WriteReg16(InstancePtr->Config.BaseAddress,
547 XSDPS_ERR_INTR_STS_OFFSET,
548 XSDPS_ERROR_INTR_ALL_MASK);
549 Status = XST_FAILURE;
552 } while ((StatusReg & XSDPS_INTR_TC_MASK) == 0U);
557 XSdPs_WriteReg16(InstancePtr->Config.BaseAddress,
558 XSDPS_NORM_INTR_STS_OFFSET, XSDPS_INTR_TC_MASK);
560 /* Change the clock frequency to 52 MHz */
561 InstancePtr->BusSpeed = XSDPS_CLK_52_MHZ;
562 Status = XSdPs_Change_ClkFreq(InstancePtr, XSDPS_CLK_52_MHZ);
563 if (Status != XST_SUCCESS) {
564 Status = XST_FAILURE;
568 Arg = XSDPS_MMC_HS200_ARG;
570 Status = XSdPs_CmdTransfer(InstancePtr, CMD6, Arg, 0U);
571 if (Status != XST_SUCCESS) {
572 Status = XST_FAILURE;
577 * Check for transfer complete
580 StatusReg = XSdPs_ReadReg16(InstancePtr->Config.BaseAddress,
581 XSDPS_NORM_INTR_STS_OFFSET);
582 if ((StatusReg & XSDPS_INTR_ERR_MASK) != 0U) {
584 * Write to clear error bits
586 XSdPs_WriteReg16(InstancePtr->Config.BaseAddress,
587 XSDPS_ERR_INTR_STS_OFFSET,
588 XSDPS_ERROR_INTR_ALL_MASK);
589 Status = XST_FAILURE;
592 } while ((StatusReg & XSDPS_INTR_TC_MASK) == 0U);
597 XSdPs_WriteReg16(InstancePtr->Config.BaseAddress,
598 XSDPS_NORM_INTR_STS_OFFSET, XSDPS_INTR_TC_MASK);
600 /* Change the clock frequency to 200 MHz */
601 InstancePtr->BusSpeed = XSDPS_MMC_HS200_MAX_CLK;
603 Status = XSdPs_Change_ClkFreq(InstancePtr, InstancePtr->BusSpeed);
604 if (Status != XST_SUCCESS) {
605 Status = XST_FAILURE;
608 Status = XSdPs_Execute_Tuning(InstancePtr);
609 if (Status != XST_SUCCESS) {
610 Status = XST_FAILURE;
613 #if defined (__arm__) || defined (__aarch64__)
614 /* Program the Tap delays */
615 XSdPs_SetTapDelay(InstancePtr);
619 #if defined (__arm__) || defined (__aarch64__)
621 usleep(XSDPS_MMC_DELAY_FOR_SWITCH);
625 #ifdef __MICROBLAZE__
632 StatusReg = (s32)XSdPs_ReadReg8(InstancePtr->Config.BaseAddress,
633 XSDPS_HOST_CTRL1_OFFSET);
634 StatusReg |= XSDPS_HC_SPEED_MASK;
635 XSdPs_WriteReg8(InstancePtr->Config.BaseAddress,
636 XSDPS_HOST_CTRL1_OFFSET, (u8)StatusReg);
638 Status = (s32)XSdPs_ReadReg(InstancePtr->Config.BaseAddress,
642 Status = XST_SUCCESS;
649 /*****************************************************************************/
652 * API to change clock freq to given value.
655 * @param InstancePtr is a pointer to the XSdPs instance.
656 * @param SelFreq - Clock frequency in Hz.
660 * @note This API will change clock frequency to the value less than
661 * or equal to the given value using the permissible dividors.
663 ******************************************************************************/
664 s32 XSdPs_Change_ClkFreq(XSdPs *InstancePtr, u32 SelFreq)
674 Xil_AssertNonvoid(InstancePtr != NULL);
675 Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY);
678 ClockReg = XSdPs_ReadReg16(InstancePtr->Config.BaseAddress,
679 XSDPS_CLK_CTRL_OFFSET);
680 ClockReg &= ~(XSDPS_CC_SD_CLK_EN_MASK | XSDPS_CC_INT_CLK_EN_MASK);
681 XSdPs_WriteReg16(InstancePtr->Config.BaseAddress,
682 XSDPS_CLK_CTRL_OFFSET, ClockReg);
684 if (InstancePtr->HC_Version == XSDPS_HC_SPEC_V3) {
685 /* Calculate divisor */
686 for (DivCnt = 0x1U; DivCnt <= XSDPS_CC_EXT_MAX_DIV_CNT;DivCnt++) {
687 if (((InstancePtr->Config.InputClockHz) / DivCnt) <= SelFreq) {
688 Divisor = DivCnt >> 1;
693 if (DivCnt > XSDPS_CC_EXT_MAX_DIV_CNT) {
694 /* No valid divisor found for given frequency */
695 Status = XST_FAILURE;
699 /* Calculate divisor */
701 while (DivCnt <= XSDPS_CC_MAX_DIV_CNT) {
702 if (((InstancePtr->Config.InputClockHz) / DivCnt) <= SelFreq) {
703 Divisor = DivCnt / 2U;
706 DivCnt = DivCnt << 1U;
709 if (DivCnt > XSDPS_CC_MAX_DIV_CNT) {
710 /* No valid divisor found for given frequency */
711 Status = XST_FAILURE;
716 /* Set clock divisor */
717 if (InstancePtr->HC_Version == XSDPS_HC_SPEC_V3) {
718 ClockReg = XSdPs_ReadReg16(InstancePtr->Config.BaseAddress,
719 XSDPS_CLK_CTRL_OFFSET);
720 ClockReg &= ~(XSDPS_CC_SDCLK_FREQ_SEL_MASK |
721 XSDPS_CC_SDCLK_FREQ_SEL_EXT_MASK);
723 ExtDivisor = Divisor >> 8;
724 ExtDivisor <<= XSDPS_CC_EXT_DIV_SHIFT;
725 ExtDivisor &= XSDPS_CC_SDCLK_FREQ_SEL_EXT_MASK;
727 Divisor <<= XSDPS_CC_DIV_SHIFT;
728 Divisor &= XSDPS_CC_SDCLK_FREQ_SEL_MASK;
729 ClockReg |= Divisor | ExtDivisor | (u16)XSDPS_CC_INT_CLK_EN_MASK;
730 XSdPs_WriteReg16(InstancePtr->Config.BaseAddress, XSDPS_CLK_CTRL_OFFSET,
733 ClockReg = XSdPs_ReadReg16(InstancePtr->Config.BaseAddress,
734 XSDPS_CLK_CTRL_OFFSET);
735 ClockReg &= (~XSDPS_CC_SDCLK_FREQ_SEL_MASK);
737 Divisor <<= XSDPS_CC_DIV_SHIFT;
738 Divisor &= XSDPS_CC_SDCLK_FREQ_SEL_MASK;
739 ClockReg |= Divisor | (u16)XSDPS_CC_INT_CLK_EN_MASK;
740 XSdPs_WriteReg16(InstancePtr->Config.BaseAddress, XSDPS_CLK_CTRL_OFFSET,
744 /* Wait for internal clock to stabilize */
745 ReadReg = XSdPs_ReadReg16(InstancePtr->Config.BaseAddress,
746 XSDPS_CLK_CTRL_OFFSET);
747 while((ReadReg & XSDPS_CC_INT_CLK_STABLE_MASK) == 0U) {
748 ReadReg = XSdPs_ReadReg16(InstancePtr->Config.BaseAddress,
749 XSDPS_CLK_CTRL_OFFSET);;
752 /* Enable SD clock */
753 ClockReg = XSdPs_ReadReg16(InstancePtr->Config.BaseAddress,
754 XSDPS_CLK_CTRL_OFFSET);
755 XSdPs_WriteReg16(InstancePtr->Config.BaseAddress,
756 XSDPS_CLK_CTRL_OFFSET,
757 ClockReg | XSDPS_CC_SD_CLK_EN_MASK);
759 Status = XST_SUCCESS;
766 /*****************************************************************************/
769 * API to send pullup command to card before using DAT line 3(using 4-bit bus)
772 * @param InstancePtr is a pointer to the XSdPs instance.
775 * - XST_SUCCESS if successful.
776 * - XST_FAILURE if fail.
780 ******************************************************************************/
781 s32 XSdPs_Pullup(XSdPs *InstancePtr)
785 Xil_AssertNonvoid(InstancePtr != NULL);
786 Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY);
788 Status = XSdPs_CmdTransfer(InstancePtr, CMD55,
789 InstancePtr->RelCardAddr, 0U);
790 if (Status != XST_SUCCESS) {
791 Status = XST_FAILURE;
795 Status = XSdPs_CmdTransfer(InstancePtr, ACMD42, 0U, 0U);
796 if (Status != XST_SUCCESS) {
797 Status = XST_FAILURE;
801 Status = XST_SUCCESS;
808 /*****************************************************************************/
811 * API to get EXT_CSD register of eMMC.
814 * @param InstancePtr is a pointer to the XSdPs instance.
815 * @param ReadBuff - buffer to store EXT_CSD
818 * - XST_SUCCESS if successful.
819 * - XST_FAILURE if fail.
823 ******************************************************************************/
824 s32 XSdPs_Get_Mmc_ExtCsd(XSdPs *InstancePtr, u8 *ReadBuff)
833 Xil_AssertNonvoid(InstancePtr != NULL);
834 Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY);
836 for (LoopCnt = 0; LoopCnt < 512; LoopCnt++) {
837 ReadBuff[LoopCnt] = 0U;
840 BlkCnt = XSDPS_EXT_CSD_CMD_BLKCNT;
841 BlkSize = XSDPS_EXT_CSD_CMD_BLKSIZE;
842 BlkSize &= XSDPS_BLK_SIZE_MASK;
843 XSdPs_WriteReg16(InstancePtr->Config.BaseAddress,
844 XSDPS_BLK_SIZE_OFFSET, BlkSize);
846 XSdPs_SetupADMA2DescTbl(InstancePtr, BlkCnt, ReadBuff);
848 Xil_DCacheInvalidateRange((INTPTR)ReadBuff, 512U);
850 XSdPs_WriteReg16(InstancePtr->Config.BaseAddress,
851 XSDPS_XFER_MODE_OFFSET,
852 XSDPS_TM_DAT_DIR_SEL_MASK | XSDPS_TM_DMA_EN_MASK);
855 /* Send SEND_EXT_CSD command */
856 Status = XSdPs_CmdTransfer(InstancePtr, CMD8, Arg, 1U);
857 if (Status != XST_SUCCESS) {
858 Status = XST_FAILURE;
863 * Check for transfer complete
864 * Polling for response for now
867 StatusReg = XSdPs_ReadReg16(InstancePtr->Config.BaseAddress,
868 XSDPS_NORM_INTR_STS_OFFSET);
869 if ((StatusReg & XSDPS_INTR_ERR_MASK) != 0U) {
870 /* Write to clear error bits */
871 XSdPs_WriteReg16(InstancePtr->Config.BaseAddress,
872 XSDPS_ERR_INTR_STS_OFFSET,
873 XSDPS_ERROR_INTR_ALL_MASK);
874 Status = XST_FAILURE;
877 } while ((StatusReg & XSDPS_INTR_TC_MASK) == 0U);
879 /* Write to clear bit */
880 XSdPs_WriteReg16(InstancePtr->Config.BaseAddress,
881 XSDPS_NORM_INTR_STS_OFFSET, XSDPS_INTR_TC_MASK);
883 Status = (s32)XSdPs_ReadReg(InstancePtr->Config.BaseAddress,
886 Status = XST_SUCCESS;
894 /*****************************************************************************/
897 * API to UHS-I mode initialization
900 * @param InstancePtr is a pointer to the XSdPs instance.
901 * @param Mode UHS-I mode
904 * - XST_SUCCESS if successful.
905 * - XST_FAILURE if fail.
909 ******************************************************************************/
910 s32 XSdPs_Uhs_ModeInit(XSdPs *InstancePtr, u8 Mode)
920 Xil_AssertNonvoid(InstancePtr != NULL);
921 Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY);
925 /* Bus speed mode selection */
926 BlkCnt = XSDPS_SWITCH_CMD_BLKCNT;
927 BlkSize = XSDPS_SWITCH_CMD_BLKSIZE;
928 BlkSize &= XSDPS_BLK_SIZE_MASK;
929 XSdPs_WriteReg16(InstancePtr->Config.BaseAddress, XSDPS_BLK_SIZE_OFFSET,
932 XSdPs_SetupADMA2DescTbl(InstancePtr, BlkCnt, ReadBuff);
934 Xil_DCacheFlushRange((INTPTR)ReadBuff, 64);
936 XSdPs_WriteReg16(InstancePtr->Config.BaseAddress, XSDPS_XFER_MODE_OFFSET,
937 XSDPS_TM_DAT_DIR_SEL_MASK | XSDPS_TM_DMA_EN_MASK);
941 Arg = XSDPS_SWITCH_CMD_SDR12_SET;
942 InstancePtr->BusSpeed = XSDPS_SD_SDR12_MAX_CLK;
945 Arg = XSDPS_SWITCH_CMD_SDR25_SET;
946 InstancePtr->BusSpeed = XSDPS_SD_SDR25_MAX_CLK;
949 Arg = XSDPS_SWITCH_CMD_SDR50_SET;
950 InstancePtr->BusSpeed = XSDPS_SD_SDR50_MAX_CLK;
953 Arg = XSDPS_SWITCH_CMD_SDR104_SET;
954 InstancePtr->BusSpeed = XSDPS_SD_SDR104_MAX_CLK;
957 Arg = XSDPS_SWITCH_CMD_DDR50_SET;
958 InstancePtr->BusSpeed = XSDPS_SD_DDR50_MAX_CLK;
961 Status = XST_FAILURE;
966 Status = XSdPs_CmdTransfer(InstancePtr, CMD6, Arg, 1U);
967 if (Status != XST_SUCCESS) {
968 Status = XST_FAILURE;
973 * Check for transfer complete
974 * Polling for response for now
977 StatusReg = XSdPs_ReadReg16(InstancePtr->Config.BaseAddress,
978 XSDPS_NORM_INTR_STS_OFFSET);
979 if ((StatusReg & XSDPS_INTR_ERR_MASK) != 0U) {
980 /* Write to clear error bits */
981 XSdPs_WriteReg16(InstancePtr->Config.BaseAddress,
982 XSDPS_ERR_INTR_STS_OFFSET, XSDPS_ERROR_INTR_ALL_MASK);
983 Status = XST_FAILURE;
986 } while ((StatusReg & XSDPS_INTR_TC_MASK) == 0U);
988 /* Write to clear bit */
989 XSdPs_WriteReg16(InstancePtr->Config.BaseAddress,
990 XSDPS_NORM_INTR_STS_OFFSET, XSDPS_INTR_TC_MASK);
995 /* Set UHS mode in controller */
996 CtrlReg = XSdPs_ReadReg16(InstancePtr->Config.BaseAddress,
997 XSDPS_HOST_CTRL2_OFFSET);
998 CtrlReg &= (u16)(~XSDPS_HC2_UHS_MODE_MASK);
1000 XSdPs_WriteReg16(InstancePtr->Config.BaseAddress,
1001 XSDPS_HOST_CTRL2_OFFSET, CtrlReg);
1003 /* Change the clock frequency */
1004 Status = XSdPs_Change_ClkFreq(InstancePtr, InstancePtr->BusSpeed);
1005 if (Status != XST_SUCCESS) {
1006 Status = XST_FAILURE;
1010 if((Mode == XSDPS_UHS_SPEED_MODE_SDR104) ||
1011 (Mode == XSDPS_UHS_SPEED_MODE_DDR50)) {
1012 /* Send tuning pattern */
1013 Status = XSdPs_Execute_Tuning(InstancePtr);
1014 if (Status != XST_SUCCESS) {
1015 Status = XST_FAILURE;
1020 Status = XST_SUCCESS;
1026 static s32 XSdPs_Execute_Tuning(XSdPs *InstancePtr)
1037 Xil_AssertNonvoid(InstancePtr != NULL);
1038 Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY);
1040 BlkCnt = XSDPS_TUNING_CMD_BLKCNT;
1041 BlkSize = XSDPS_TUNING_CMD_BLKSIZE;
1042 if(InstancePtr->BusWidth == XSDPS_8_BIT_WIDTH)
1044 BlkSize = BlkSize*2U;
1046 BlkSize &= XSDPS_BLK_SIZE_MASK;
1047 XSdPs_WriteReg16(InstancePtr->Config.BaseAddress, XSDPS_BLK_SIZE_OFFSET,
1050 XSdPs_WriteReg16(InstancePtr->Config.BaseAddress, XSDPS_XFER_MODE_OFFSET,
1051 XSDPS_TM_DAT_DIR_SEL_MASK);
1053 CtrlReg = XSdPs_ReadReg16(InstancePtr->Config.BaseAddress,
1054 XSDPS_HOST_CTRL2_OFFSET);
1055 CtrlReg |= XSDPS_HC2_EXEC_TNG_MASK;
1056 XSdPs_WriteReg16(InstancePtr->Config.BaseAddress,
1057 XSDPS_HOST_CTRL2_OFFSET, CtrlReg);
1059 for (TuningCount = 0U; TuningCount < MAX_TUNING_COUNT; TuningCount++) {
1061 if (InstancePtr->CardType == XSDPS_CARD_SD) {
1062 Status = XSdPs_CmdTransfer(InstancePtr, CMD19, 0U, 1U);
1064 Status = XSdPs_CmdTransfer(InstancePtr, CMD21, 0U, 1U);
1067 if (Status != XST_SUCCESS) {
1068 Status = XST_FAILURE;
1072 if ((XSdPs_ReadReg16(InstancePtr->Config.BaseAddress,
1073 XSDPS_HOST_CTRL2_OFFSET) & XSDPS_HC2_EXEC_TNG_MASK) == 0U) {
1078 if ((XSdPs_ReadReg16(InstancePtr->Config.BaseAddress,
1079 XSDPS_HOST_CTRL2_OFFSET) & XSDPS_HC2_SAMP_CLK_SEL_MASK) == 0U) {
1080 Status = XST_FAILURE;
1085 * As per controller erratum, program the "SDCLK Frequency
1086 * Select" of clock control register with a value, say
1087 * clock/2. Wait for the Internal clock stable and program
1088 * the desired frequency.
1090 CtrlReg = XSdPs_ReadReg16(InstancePtr->Config.BaseAddress,
1091 XSDPS_HOST_CTRL2_OFFSET);
1092 if ((CtrlReg & XSDPS_HC2_SAMP_CLK_SEL_MASK) != 0U) {
1093 Status = XSdPs_Change_ClkFreq(InstancePtr, InstancePtr->BusSpeed/2);
1094 if (Status != XST_SUCCESS) {
1097 Status = XSdPs_Change_ClkFreq(InstancePtr, InstancePtr->BusSpeed);
1098 if (Status != XST_SUCCESS) {
1104 Status = XST_SUCCESS;
1106 RETURN_PATH: return Status;
1110 #if defined (__arm__) || defined (__aarch64__)
1111 /*****************************************************************************/
1114 * API to set Tap Delay w.r.t speed modes
1117 * @param InstancePtr is a pointer to the XSdPs instance.
1123 ******************************************************************************/
1124 void XSdPs_SetTapDelay(XSdPs *InstancePtr)
1126 u32 DllCtrl, TapDelay;
1127 if (InstancePtr->Config.DeviceId == XPAR_XSDPS_0_DEVICE_ID) {
1128 DllCtrl = XSdPs_ReadReg(XPS_SYS_CTRL_BASEADDR, SD_DLL_CTRL);
1129 DllCtrl |= SD0_DLL_RST;
1130 XSdPs_WriteReg(XPS_SYS_CTRL_BASEADDR, SD_DLL_CTRL, DllCtrl);
1131 if(InstancePtr->BusSpeed == XSDPS_MMC_HS200_MAX_CLK) {
1132 /* Program the ITAPDLY */
1133 TapDelay = XSdPs_ReadReg(XPS_SYS_CTRL_BASEADDR, SD_ITAPDLY);
1134 TapDelay |= SD0_ITAPCHGWIN;
1135 XSdPs_WriteReg(XPS_SYS_CTRL_BASEADDR, SD_ITAPDLY, TapDelay);
1136 TapDelay |= SD0_ITAPDLYENA;
1137 XSdPs_WriteReg(XPS_SYS_CTRL_BASEADDR, SD_ITAPDLY, TapDelay);
1138 TapDelay &= ~SD0_ITAPCHGWIN;
1139 XSdPs_WriteReg(XPS_SYS_CTRL_BASEADDR, SD_ITAPDLY, TapDelay);
1140 /* Program the OTAPDLY */
1141 TapDelay = XSdPs_ReadReg(XPS_SYS_CTRL_BASEADDR, SD_OTAPDLYSEL);
1142 TapDelay |= SD0_OTAPDLYENA;
1143 XSdPs_WriteReg(XPS_SYS_CTRL_BASEADDR, SD_OTAPDLYSEL, TapDelay);
1144 TapDelay |= SD0_OTAPDLYSEL_HS200;
1145 XSdPs_WriteReg(XPS_SYS_CTRL_BASEADDR, SD_OTAPDLYSEL, TapDelay);
1147 DllCtrl &= ~SD0_DLL_RST;
1148 XSdPs_WriteReg(XPS_SYS_CTRL_BASEADDR, SD_DLL_CTRL, DllCtrl);