]> git.sur5r.net Git - freertos/blobdiff - FreeRTOS/Demo/CORTEX_A9_Zynq_ZC702/RTOSDemo_bsp/ps7_cortexa9_0/libsrc/sdps_v2_1/src/xsdps_options.c
Add back Zynq demo - this time using SDK V14.2.
[freertos] / FreeRTOS / Demo / CORTEX_A9_Zynq_ZC702 / RTOSDemo_bsp / ps7_cortexa9_0 / libsrc / sdps_v2_1 / src / xsdps_options.c
diff --git a/FreeRTOS/Demo/CORTEX_A9_Zynq_ZC702/RTOSDemo_bsp/ps7_cortexa9_0/libsrc/sdps_v2_1/src/xsdps_options.c b/FreeRTOS/Demo/CORTEX_A9_Zynq_ZC702/RTOSDemo_bsp/ps7_cortexa9_0/libsrc/sdps_v2_1/src/xsdps_options.c
new file mode 100644 (file)
index 0000000..f14a66b
--- /dev/null
@@ -0,0 +1,813 @@
+/******************************************************************************
+*
+* (c) Copyright 2013-2014 Xilinx, Inc. All rights reserved.
+*
+* This file contains confidential and proprietary information of Xilinx, Inc.
+* and is protected under U.S. and international copyright and other
+* intellectual property laws.
+*
+* DISCLAIMER
+* This disclaimer is not a license and does not grant any rights to the
+* materials distributed herewith. Except as otherwise provided in a valid
+* license issued to you by Xilinx, and to the maximum extent permitted by
+* applicable law: (1) THESE MATERIALS ARE MADE AVAILABLE "AS IS" AND WITH ALL
+* FAULTS, AND XILINX HEREBY DISCLAIMS ALL WARRANTIES AND CONDITIONS, EXPRESS,
+* IMPLIED, OR STATUTORY, INCLUDING BUT NOT LIMITED TO WARRANTIES OF
+* MERCHANTABILITY, NON-INFRINGEMENT, OR FITNESS FOR ANY PARTICULAR PURPOSE;
+* and (2) Xilinx shall not be liable (whether in contract or tort, including
+* negligence, or under any other theory of liability) for any loss or damage
+* of any kind or nature related to, arising under or in connection with these
+* materials, including for any direct, or any indirect, special, incidental,
+* or consequential loss or damage (including loss of data, profits, goodwill,
+* or any type of loss or damage suffered as a result of any action brought by
+* a third party) even if such damage or loss was reasonably foreseeable or
+* Xilinx had been advised of the possibility of the same.
+*
+* CRITICAL APPLICATIONS
+* Xilinx products are not designed or intended to be fail-safe, or for use in
+* any application requiring fail-safe performance, such as life-support or
+* safety devices or systems, Class III medical devices, nuclear facilities,
+* applications related to the deployment of airbags, or any other applications
+* that could lead to death, personal injury, or severe property or
+* environmental damage (individually and collectively, "Critical
+* Applications"). Customer assumes the sole risk and liability of any use of
+* Xilinx products in Critical Applications, subject only to applicable laws
+* and regulations governing limitations on product liability.
+*
+* THIS COPYRIGHT NOTICE AND DISCLAIMER MUST BE RETAINED AS PART OF THIS FILE
+* AT ALL TIMES.
+*
+******************************************************************************/
+/*****************************************************************************/
+/**
+*
+* @file xsdps_options.c
+*
+* Contains API's for changing the various options in host and card.
+* See xsdps.h for a detailed description of the device and driver.
+*
+* <pre>
+* MODIFICATION HISTORY:
+*
+* Ver   Who    Date     Changes
+* ----- ---    -------- -----------------------------------------------
+* 1.00a hk/sg  10/17/13 Initial release
+* 2.1   hk     04/18/14 Increase sleep for eMMC switch command.
+*                       Add sleep for microblaze designs. CR# 781117.
+*
+* </pre>
+*
+******************************************************************************/
+
+/***************************** Include Files *********************************/
+#include "xsdps.h"
+/*
+ * The header sleep.h and API usleep() can only be used with an arm design.
+ * MB_Sleep() is used for microblaze design.
+ */
+#ifdef __arm__
+
+#include "sleep.h"
+
+#endif
+
+#ifdef __MICROBLAZE__
+
+#include "microblaze_sleep.h"
+
+#endif
+
+/************************** Constant Definitions *****************************/
+#define XSDPS_SCR_BLKCNT       1
+#define XSDPS_SCR_BLKSIZE      8
+#define XSDPS_4_BIT_WIDTH      0x2
+#define XSDPS_SWITCH_CMD_BLKCNT                1
+#define XSDPS_SWITCH_CMD_BLKSIZE       64
+#define XSDPS_SWITCH_CMD_HS_GET        0x00FFFFF0
+#define XSDPS_SWITCH_CMD_HS_SET        0x80FFFFF1
+#define XSDPS_EXT_CSD_CMD_BLKCNT       1
+#define XSDPS_EXT_CSD_CMD_BLKSIZE      512
+#define XSDPS_CLK_52_MHZ               52000000
+#define XSDPS_MMC_HIGH_SPEED_ARG       0x03B90100
+#define XSDPS_MMC_4_BIT_BUS_ARG                0x03B70100
+#define XSDPS_MMC_DELAY_FOR_SWITCH     2000
+
+/**************************** Type Definitions *******************************/
+
+/***************** Macros (Inline Functions) Definitions *********************/
+
+/************************** Function Prototypes ******************************/
+int XSdPs_CmdTransfer(XSdPs *InstancePtr, u32 Cmd, u32 Arg, u32 BlkCnt);
+void XSdPs_SetupADMA2DescTbl(XSdPs *InstancePtr, u32 BlkCnt, const u8 *Buff);
+
+/*****************************************************************************/
+/**
+* Update Block size for read/write operations.
+*
+* @param       InstancePtr is a pointer to the instance to be worked on.
+* @param       BlkSize - Block size passed by the user.
+*
+* @return      None
+*
+******************************************************************************/
+int XSdPs_SetBlkSize(XSdPs *InstancePtr, u16 BlkSize)
+{
+       u32 Status = 0;
+       u32 PresentStateReg = 0;
+
+       Xil_AssertNonvoid(InstancePtr != NULL);
+       Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY);
+
+       PresentStateReg = XSdPs_ReadReg(InstancePtr->Config.BaseAddress,
+                       XSDPS_PRES_STATE_OFFSET);
+
+       if (PresentStateReg & (XSDPS_PSR_INHIBIT_CMD_MASK |
+                       XSDPS_PSR_INHIBIT_DAT_MASK |
+                       XSDPS_PSR_WR_ACTIVE_MASK | XSDPS_PSR_RD_ACTIVE_MASK)) {
+               Status = XST_FAILURE;
+               goto RETURN_PATH;
+       }
+
+
+       /*
+        * Send block write command
+        */
+       Status = XSdPs_CmdTransfer(InstancePtr, CMD16, BlkSize, 0);
+       if (Status != XST_SUCCESS) {
+               Status = XST_FAILURE;
+               goto RETURN_PATH;
+       }
+
+       Status = XSdPs_ReadReg(InstancePtr->Config.BaseAddress,
+                       XSDPS_RESP0_OFFSET);
+
+       /*
+        * Set block size to the value passed
+        */
+       BlkSize &= XSDPS_BLK_SIZE_MASK;
+       XSdPs_WriteReg16(InstancePtr->Config.BaseAddress, XSDPS_BLK_SIZE_OFFSET,
+                        BlkSize);
+
+       Status = XST_SUCCESS;
+
+       RETURN_PATH:
+               return Status;
+
+}
+
+/*****************************************************************************/
+/**
+*
+* API to get bus width support by card.
+*
+*
+* @param       InstancePtr is a pointer to the XSdPs instance.
+* @param       SCR - buffer to store SCR register returned by card.
+*
+* @return
+*              - XST_SUCCESS if successful.
+*              - XST_FAILURE if fail.
+*
+* @note                None.
+*
+******************************************************************************/
+int XSdPs_Get_BusWidth(XSdPs *InstancePtr, u8 *SCR)
+{
+       u32 Status = 0;
+       u32 StatusReg = 0x0;
+       u16 BlkCnt;
+       u16 BlkSize;
+       int LoopCnt;
+
+       Xil_AssertNonvoid(InstancePtr != NULL);
+       Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY);
+
+       for (LoopCnt = 0; LoopCnt < 8; LoopCnt++) {
+               SCR[LoopCnt] = 0;
+       }
+
+       /*
+        * Send block write command
+        */
+       Status = XSdPs_CmdTransfer(InstancePtr, CMD55,
+                       InstancePtr->RelCardAddr, 0);
+       if (Status != XST_SUCCESS) {
+               Status = XST_FAILURE;
+               goto RETURN_PATH;
+       }
+
+       BlkCnt = XSDPS_SCR_BLKCNT;
+       BlkSize = XSDPS_SCR_BLKSIZE;
+
+       /*
+        * Set block size to the value passed
+        */
+       BlkSize &= XSDPS_BLK_SIZE_MASK;
+       XSdPs_WriteReg16(InstancePtr->Config.BaseAddress,
+                       XSDPS_BLK_SIZE_OFFSET, BlkSize);
+
+       XSdPs_SetupADMA2DescTbl(InstancePtr, BlkCnt, SCR);
+
+       XSdPs_WriteReg16(InstancePtr->Config.BaseAddress,
+                       XSDPS_XFER_MODE_OFFSET,
+                       XSDPS_TM_DAT_DIR_SEL_MASK | XSDPS_TM_DMA_EN_MASK);
+
+       Status = XSdPs_CmdTransfer(InstancePtr, ACMD51, 0, BlkCnt);
+       if (Status != XST_SUCCESS) {
+               Status = XST_FAILURE;
+               goto RETURN_PATH;
+       }
+
+       /*
+        * Check for transfer complete
+        * Polling for response for now
+        */
+       do {
+               StatusReg = XSdPs_ReadReg16(InstancePtr->Config.BaseAddress,
+                                       XSDPS_NORM_INTR_STS_OFFSET);
+               if (StatusReg & XSDPS_INTR_ERR_MASK) {
+                       /*
+                        * Write to clear error bits
+                        */
+                       XSdPs_WriteReg16(InstancePtr->Config.BaseAddress,
+                                       XSDPS_ERR_INTR_STS_OFFSET,
+                                       XSDPS_ERROR_INTR_ALL_MASK);
+                       Status = XST_FAILURE;
+                       goto RETURN_PATH;
+               }
+       } while ((StatusReg & XSDPS_INTR_TC_MASK) == 0);
+
+       /*
+        * Write to clear bit
+        */
+       XSdPs_WriteReg16(InstancePtr->Config.BaseAddress,
+                       XSDPS_NORM_INTR_STS_OFFSET, XSDPS_INTR_TC_MASK);
+
+       Status = XSdPs_ReadReg(InstancePtr->Config.BaseAddress,
+                       XSDPS_RESP0_OFFSET);
+
+       Status = XST_SUCCESS;
+
+       RETURN_PATH:
+               return Status;
+
+}
+
+/*****************************************************************************/
+/**
+*
+* API to set bus width to 4-bit in card and host
+*
+*
+* @param       InstancePtr is a pointer to the XSdPs instance.
+*
+* @return
+*              - XST_SUCCESS if successful.
+*              - XST_FAILURE if fail.
+*
+* @note                None.
+*
+******************************************************************************/
+int XSdPs_Change_BusWidth(XSdPs *InstancePtr)
+{
+       u32 Status = 0;
+       u32 StatusReg = 0x0;
+       u32 Arg = 0;
+
+       Xil_AssertNonvoid(InstancePtr != NULL);
+       Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY);
+
+#ifndef MMC_CARD
+
+       Status = XSdPs_CmdTransfer(InstancePtr, CMD55,
+                       InstancePtr->RelCardAddr, 0);
+       if (Status != XST_SUCCESS) {
+               Status = XST_FAILURE;
+               goto RETURN_PATH;
+       }
+
+       Arg = XSDPS_4_BIT_WIDTH;
+       Status = XSdPs_CmdTransfer(InstancePtr, ACMD6, Arg, 0);
+       if (Status != XST_SUCCESS) {
+               Status = XST_FAILURE;
+               goto RETURN_PATH;
+       }
+
+       StatusReg = XSdPs_ReadReg8(InstancePtr->Config.BaseAddress,
+                                       XSDPS_HOST_CTRL1_OFFSET);
+       StatusReg |= XSDPS_HC_WIDTH_MASK;
+       XSdPs_WriteReg8(InstancePtr->Config.BaseAddress,
+                       XSDPS_HOST_CTRL1_OFFSET,StatusReg);
+
+       Status = XSdPs_ReadReg(InstancePtr->Config.BaseAddress,
+                       XSDPS_RESP0_OFFSET);
+
+#else
+
+       Arg = XSDPS_MMC_4_BIT_BUS_ARG;
+       Status = XSdPs_CmdTransfer(InstancePtr, ACMD6, Arg, 0);
+       if (Status != XST_SUCCESS) {
+               Status = XST_FAILURE;
+               goto RETURN_PATH;
+       }
+
+#ifdef __arm__
+
+       usleep(XSDPS_MMC_DELAY_FOR_SWITCH);
+
+#endif
+
+#ifdef __MICROBLAZE__
+
+       /* 2 msec delay */
+       MB_Sleep(2);
+
+#endif
+
+       StatusReg = XSdPs_ReadReg8(InstancePtr->Config.BaseAddress,
+                                       XSDPS_HOST_CTRL1_OFFSET);
+       StatusReg |= XSDPS_HC_WIDTH_MASK;
+       XSdPs_WriteReg8(InstancePtr->Config.BaseAddress,
+                       XSDPS_HOST_CTRL1_OFFSET,StatusReg);
+
+       Status = XSdPs_ReadReg(InstancePtr->Config.BaseAddress,
+                       XSDPS_RESP0_OFFSET);
+
+#endif
+
+       Status = XST_SUCCESS;
+
+       RETURN_PATH:
+               return Status;
+
+}
+
+/*****************************************************************************/
+/**
+*
+* API to get bus speed supported by card.
+*
+*
+* @param       InstancePtr is a pointer to the XSdPs instance.
+* @param       ReadBuff - buffer to store function group support data
+*              returned by card.
+*
+* @return
+*              - XST_SUCCESS if successful.
+*              - XST_FAILURE if fail.
+*
+* @note                None.
+*
+******************************************************************************/
+int XSdPs_Get_BusSpeed(XSdPs *InstancePtr, u8 *ReadBuff)
+{
+       u32 Status = 0;
+       u32 StatusReg = 0x0;
+       u32 Arg = 0;
+       u16 BlkCnt;
+       u16 BlkSize;
+       int LoopCnt;
+
+       Xil_AssertNonvoid(InstancePtr != NULL);
+       Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY);
+
+       for (LoopCnt = 0; LoopCnt < 64; LoopCnt++) {
+               ReadBuff[LoopCnt] = 0;
+       }
+
+       BlkCnt = XSDPS_SWITCH_CMD_BLKCNT;
+       BlkSize = XSDPS_SWITCH_CMD_BLKSIZE;
+       BlkSize &= XSDPS_BLK_SIZE_MASK;
+       XSdPs_WriteReg16(InstancePtr->Config.BaseAddress,
+                       XSDPS_BLK_SIZE_OFFSET, BlkSize);
+
+       XSdPs_SetupADMA2DescTbl(InstancePtr, BlkCnt, ReadBuff);
+
+       XSdPs_WriteReg16(InstancePtr->Config.BaseAddress,
+                       XSDPS_XFER_MODE_OFFSET,
+                       XSDPS_TM_DAT_DIR_SEL_MASK | XSDPS_TM_DMA_EN_MASK);
+
+       Arg = XSDPS_SWITCH_CMD_HS_GET;
+
+       Status = XSdPs_CmdTransfer(InstancePtr, CMD6, Arg, 1);
+       if (Status != XST_SUCCESS) {
+               Status = XST_FAILURE;
+               goto RETURN_PATH;
+       }
+
+       /*
+        * Check for transfer complete
+        * Polling for response for now
+        */
+       do {
+               StatusReg = XSdPs_ReadReg16(InstancePtr->Config.BaseAddress,
+                                       XSDPS_NORM_INTR_STS_OFFSET);
+               if (StatusReg & XSDPS_INTR_ERR_MASK) {
+                       /*
+                        * Write to clear error bits
+                        */
+                       XSdPs_WriteReg16(InstancePtr->Config.BaseAddress,
+                                       XSDPS_ERR_INTR_STS_OFFSET,
+                                       XSDPS_ERROR_INTR_ALL_MASK);
+                       Status = XST_FAILURE;
+                       goto RETURN_PATH;
+               }
+       } while ((StatusReg & XSDPS_INTR_TC_MASK) == 0);
+
+       /*
+        * Write to clear bit
+        */
+       XSdPs_WriteReg16(InstancePtr->Config.BaseAddress,
+                       XSDPS_NORM_INTR_STS_OFFSET, XSDPS_INTR_TC_MASK);
+
+       Status = XSdPs_ReadReg(InstancePtr->Config.BaseAddress,
+                       XSDPS_RESP0_OFFSET);
+
+       Status = XST_SUCCESS;
+
+       RETURN_PATH:
+               return Status;
+
+}
+
+/*****************************************************************************/
+/**
+*
+* API to set high speed in card and host. Changes clock in host accordingly.
+*
+*
+* @param       InstancePtr is a pointer to the XSdPs instance.
+*
+* @return
+*              - XST_SUCCESS if successful.
+*              - XST_FAILURE if fail.
+*
+* @note                None.
+*
+******************************************************************************/
+int XSdPs_Change_BusSpeed(XSdPs *InstancePtr)
+{
+       u32 Status = 0;
+       u32 StatusReg = 0x0;
+       u32 Arg = 0;
+
+#ifndef MMC_CARD
+       u32 ClockReg;
+       u8 ReadBuff[64];
+       u16 BlkCnt;
+       u16 BlkSize;
+#endif
+
+       Xil_AssertNonvoid(InstancePtr != NULL);
+       Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY);
+
+#ifndef MMC_CARD
+
+       BlkCnt = XSDPS_SWITCH_CMD_BLKCNT;
+       BlkSize = XSDPS_SWITCH_CMD_BLKSIZE;
+       BlkSize &= XSDPS_BLK_SIZE_MASK;
+       XSdPs_WriteReg16(InstancePtr->Config.BaseAddress,
+                       XSDPS_BLK_SIZE_OFFSET, BlkSize);
+
+       XSdPs_SetupADMA2DescTbl(InstancePtr, BlkCnt, ReadBuff);
+
+       XSdPs_WriteReg16(InstancePtr->Config.BaseAddress,
+                       XSDPS_XFER_MODE_OFFSET,
+                       XSDPS_TM_DAT_DIR_SEL_MASK | XSDPS_TM_DMA_EN_MASK);
+
+       Arg = XSDPS_SWITCH_CMD_HS_SET;
+       Status = XSdPs_CmdTransfer(InstancePtr, CMD6, Arg, 1);
+       if (Status != XST_SUCCESS) {
+               Status = XST_FAILURE;
+               goto RETURN_PATH;
+       }
+
+       /*
+        * Check for transfer complete
+        * Polling for response for now
+        */
+       do {
+               StatusReg = XSdPs_ReadReg16(InstancePtr->Config.BaseAddress,
+                                       XSDPS_NORM_INTR_STS_OFFSET);
+               if (StatusReg & XSDPS_INTR_ERR_MASK) {
+                       /*
+                        * Write to clear error bits
+                        */
+                       XSdPs_WriteReg16(InstancePtr->Config.BaseAddress,
+                                       XSDPS_ERR_INTR_STS_OFFSET,
+                                       XSDPS_ERROR_INTR_ALL_MASK);
+                       Status = XST_FAILURE;
+                       goto RETURN_PATH;
+               }
+       } while ((StatusReg & XSDPS_INTR_TC_MASK) == 0);
+
+       /*
+        * Write to clear bit
+        */
+       XSdPs_WriteReg16(InstancePtr->Config.BaseAddress,
+                       XSDPS_NORM_INTR_STS_OFFSET, XSDPS_INTR_TC_MASK);
+
+       ClockReg = XSdPs_ReadReg16(InstancePtr->Config.BaseAddress,
+                       XSDPS_CLK_CTRL_OFFSET);
+       ClockReg &= ~(XSDPS_CC_INT_CLK_EN_MASK | XSDPS_CC_SD_CLK_EN_MASK);
+
+       XSdPs_WriteReg16(InstancePtr->Config.BaseAddress,
+                       XSDPS_CLK_CTRL_OFFSET, ClockReg);
+
+       ClockReg = XSdPs_ReadReg16(InstancePtr->Config.BaseAddress,
+                       XSDPS_CLK_CTRL_OFFSET);
+       ClockReg &= (~XSDPS_CC_SDCLK_FREQ_SEL_MASK);
+       ClockReg |= XSDPS_CC_SDCLK_FREQ_BASE_MASK | XSDPS_CC_INT_CLK_EN_MASK;
+       XSdPs_WriteReg16(InstancePtr->Config.BaseAddress,
+                       XSDPS_CLK_CTRL_OFFSET, ClockReg);
+
+       /*
+        * Wait for internal clock to stabilize
+        */
+       while((XSdPs_ReadReg16(InstancePtr->Config.BaseAddress,
+               XSDPS_CLK_CTRL_OFFSET) & XSDPS_CC_INT_CLK_STABLE_MASK) == 0);
+
+       /*
+        * Enable SD clock
+        */
+       ClockReg = XSdPs_ReadReg16(InstancePtr->Config.BaseAddress,
+                       XSDPS_CLK_CTRL_OFFSET);
+       XSdPs_WriteReg16(InstancePtr->Config.BaseAddress,
+                       XSDPS_CLK_CTRL_OFFSET,
+                       ClockReg | XSDPS_CC_SD_CLK_EN_MASK);
+
+
+       StatusReg = XSdPs_ReadReg8(InstancePtr->Config.BaseAddress,
+                                       XSDPS_HOST_CTRL1_OFFSET);
+       StatusReg |= XSDPS_HC_SPEED_MASK;
+       XSdPs_WriteReg8(InstancePtr->Config.BaseAddress,
+                       XSDPS_HOST_CTRL1_OFFSET,StatusReg);
+
+       Status = XSdPs_ReadReg(InstancePtr->Config.BaseAddress,
+                       XSDPS_RESP0_OFFSET);
+
+#else
+
+       Arg = XSDPS_MMC_HIGH_SPEED_ARG;
+       Status = XSdPs_CmdTransfer(InstancePtr, CMD6, Arg, 0);
+       if (Status != XST_SUCCESS) {
+               Status = XST_FAILURE;
+               goto RETURN_PATH;
+       }
+
+#ifdef __arm__
+
+       usleep(XSDPS_MMC_DELAY_FOR_SWITCH);
+
+#endif
+
+#ifdef __MICROBLAZE__
+
+       /* 2 msec delay */
+       MB_Sleep(2);
+
+#endif
+
+       XSdPs_Change_ClkFreq(InstancePtr, XSDPS_CLK_52_MHZ);
+
+       StatusReg = XSdPs_ReadReg8(InstancePtr->Config.BaseAddress,
+                                       XSDPS_HOST_CTRL1_OFFSET);
+       StatusReg |= XSDPS_HC_SPEED_MASK;
+       XSdPs_WriteReg8(InstancePtr->Config.BaseAddress,
+                       XSDPS_HOST_CTRL1_OFFSET,StatusReg);
+
+       Status = XSdPs_ReadReg(InstancePtr->Config.BaseAddress,
+                       XSDPS_RESP0_OFFSET);
+#endif
+
+       Status = XST_SUCCESS;
+
+       RETURN_PATH:
+               return Status;
+
+}
+
+/*****************************************************************************/
+/**
+*
+* API to change clock freq to given value.
+*
+*
+* @param       InstancePtr is a pointer to the XSdPs instance.
+* @param       SelFreq - Clock frequency in Hz.
+*
+* @return      None
+*
+* @note                This API will change clock frequency to the value less than
+*              or equal to the given value using the permissible dividors.
+*
+******************************************************************************/
+int XSdPs_Change_ClkFreq(XSdPs *InstancePtr, u32 SelFreq)
+{
+       u16 ClockReg;
+       int DivCnt;
+       u16 Divisor;
+       u16 ClkLoopCnt;
+       int Status;
+
+       Xil_AssertNonvoid(InstancePtr != NULL);
+       Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY);
+
+       /*
+        * Disable clock
+        */
+       ClockReg = XSdPs_ReadReg16(InstancePtr->Config.BaseAddress,
+                       XSDPS_CLK_CTRL_OFFSET);
+       ClockReg &= ~(XSDPS_CC_INT_CLK_EN_MASK | XSDPS_CC_SD_CLK_EN_MASK);
+
+       XSdPs_WriteReg16(InstancePtr->Config.BaseAddress,
+                       XSDPS_CLK_CTRL_OFFSET, ClockReg);
+
+       /*
+        * Calculate divisor
+        */
+       DivCnt = 0x1;
+       for(ClkLoopCnt = 0; ClkLoopCnt < XSDPS_CC_MAX_NUM_OF_DIV;
+               ClkLoopCnt++) {
+               if( ((InstancePtr->Config.InputClockHz)/DivCnt) <= SelFreq) {
+                       Divisor = DivCnt/2;
+                       Divisor = Divisor << XSDPS_CC_DIV_SHIFT;
+                       break;
+               }
+               DivCnt = DivCnt << 1;
+       }
+
+       if(ClkLoopCnt == 9) {
+
+               /*
+                * No valid divisor found for given frequency
+                */
+               Status = XST_FAILURE;
+               goto RETURN_PATH;
+       }
+
+       /*
+        * Set clock divisor
+        */
+       ClockReg = XSdPs_ReadReg16(InstancePtr->Config.BaseAddress,
+                       XSDPS_CLK_CTRL_OFFSET);
+       ClockReg &= (~XSDPS_CC_SDCLK_FREQ_SEL_MASK);
+
+       ClockReg |= Divisor | XSDPS_CC_INT_CLK_EN_MASK;
+       XSdPs_WriteReg16(InstancePtr->Config.BaseAddress,
+                       XSDPS_CLK_CTRL_OFFSET, ClockReg);
+
+       /*
+        * Wait for internal clock to stabilize
+        */
+       while((XSdPs_ReadReg16(InstancePtr->Config.BaseAddress,
+               XSDPS_CLK_CTRL_OFFSET) & XSDPS_CC_INT_CLK_STABLE_MASK) == 0);
+
+       /*
+        * Enable SD clock
+        */
+       ClockReg = XSdPs_ReadReg16(InstancePtr->Config.BaseAddress,
+                       XSDPS_CLK_CTRL_OFFSET);
+       XSdPs_WriteReg16(InstancePtr->Config.BaseAddress,
+                       XSDPS_CLK_CTRL_OFFSET,
+                       ClockReg | XSDPS_CC_SD_CLK_EN_MASK);
+
+       Status = XST_SUCCESS;
+
+       RETURN_PATH:
+               return Status;
+
+}
+
+/*****************************************************************************/
+/**
+*
+* API to send pullup command to card before using DAT line 3(using 4-bit bus)
+*
+*
+* @param       InstancePtr is a pointer to the XSdPs instance.
+*
+* @return
+*              - XST_SUCCESS if successful.
+*              - XST_FAILURE if fail.
+*
+* @note                None.
+*
+******************************************************************************/
+int XSdPs_Pullup(XSdPs *InstancePtr)
+{
+       u32 Status = 0;
+
+       Xil_AssertNonvoid(InstancePtr != NULL);
+       Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY);
+
+       Status = XSdPs_CmdTransfer(InstancePtr, CMD55,
+                       InstancePtr->RelCardAddr, 0);
+       if (Status != XST_SUCCESS) {
+               Status = XST_FAILURE;
+               goto RETURN_PATH;
+       }
+
+       Status = XSdPs_CmdTransfer(InstancePtr, ACMD42, 0, 0);
+       if (Status != XST_SUCCESS) {
+               Status = XST_FAILURE;
+               goto RETURN_PATH;
+       }
+
+       Status = XST_SUCCESS;
+
+       RETURN_PATH:
+               return Status;
+
+}
+
+/*****************************************************************************/
+/**
+*
+* API to get EXT_CSD register of eMMC.
+*
+*
+* @param       InstancePtr is a pointer to the XSdPs instance.
+* @param       ReadBuff - buffer to store EXT_CSD
+*
+* @return
+*              - XST_SUCCESS if successful.
+*              - XST_FAILURE if fail.
+*
+* @note                None.
+*
+******************************************************************************/
+int XSdPs_Get_Mmc_ExtCsd(XSdPs *InstancePtr, u8 *ReadBuff)
+{
+       u32 Status = 0;
+       u32 StatusReg = 0x0;
+       u32 Arg = 0;
+       u16 BlkCnt;
+       u16 BlkSize;
+       int LoopCnt;
+
+       Xil_AssertNonvoid(InstancePtr != NULL);
+       Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY);
+
+       for (LoopCnt = 0; LoopCnt < 512; LoopCnt++) {
+               ReadBuff[LoopCnt] = 0;
+       }
+
+       BlkCnt = XSDPS_EXT_CSD_CMD_BLKCNT;
+       BlkSize = XSDPS_EXT_CSD_CMD_BLKSIZE;
+       BlkSize &= XSDPS_BLK_SIZE_MASK;
+       XSdPs_WriteReg16(InstancePtr->Config.BaseAddress,
+                       XSDPS_BLK_SIZE_OFFSET, BlkSize);
+
+       XSdPs_SetupADMA2DescTbl(InstancePtr, BlkCnt, ReadBuff);
+
+       XSdPs_WriteReg16(InstancePtr->Config.BaseAddress,
+                       XSDPS_XFER_MODE_OFFSET,
+                       XSDPS_TM_DAT_DIR_SEL_MASK | XSDPS_TM_DMA_EN_MASK);
+
+       Arg = 0;
+
+       /*
+        * Send SEND_EXT_CSD command
+        */
+       Status = XSdPs_CmdTransfer(InstancePtr, CMD8, Arg, 1);
+       if (Status != XST_SUCCESS) {
+               Status = XST_FAILURE;
+               goto RETURN_PATH;
+       }
+
+       /*
+        * Check for transfer complete
+        * Polling for response for now
+        */
+       do {
+               StatusReg = XSdPs_ReadReg16(InstancePtr->Config.BaseAddress,
+                                       XSDPS_NORM_INTR_STS_OFFSET);
+               if (StatusReg & XSDPS_INTR_ERR_MASK) {
+                       /*
+                        * Write to clear error bits
+                        */
+                       XSdPs_WriteReg16(InstancePtr->Config.BaseAddress,
+                                       XSDPS_ERR_INTR_STS_OFFSET,
+                                       XSDPS_ERROR_INTR_ALL_MASK);
+                       Status = XST_FAILURE;
+                       goto RETURN_PATH;
+               }
+       } while ((StatusReg & XSDPS_INTR_TC_MASK) == 0);
+
+       /*
+        * Write to clear bit
+        */
+       XSdPs_WriteReg16(InstancePtr->Config.BaseAddress,
+                       XSDPS_NORM_INTR_STS_OFFSET, XSDPS_INTR_TC_MASK);
+
+       Status = XSdPs_ReadReg(InstancePtr->Config.BaseAddress,
+                       XSDPS_RESP0_OFFSET);
+
+       Status = XST_SUCCESS;
+
+       RETURN_PATH:
+               return Status;
+
+}
+