]> git.sur5r.net Git - freertos/blobdiff - FreeRTOS/Demo/CORTEX_A9_Zynq_ZC702/RTOSDemo_bsp/ps7_cortexa9_0/libsrc/sdps_v2_1/src/xsdps.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.c
diff --git a/FreeRTOS/Demo/CORTEX_A9_Zynq_ZC702/RTOSDemo_bsp/ps7_cortexa9_0/libsrc/sdps_v2_1/src/xsdps.c b/FreeRTOS/Demo/CORTEX_A9_Zynq_ZC702/RTOSDemo_bsp/ps7_cortexa9_0/libsrc/sdps_v2_1/src/xsdps.c
new file mode 100644 (file)
index 0000000..34c5c08
--- /dev/null
@@ -0,0 +1,1109 @@
+/******************************************************************************
+*
+* (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.c
+*
+* Contains the interface functions of the XSdPs driver.
+* 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.0   hk     12/13/13 Added check for arm to use sleep.h and its API's
+* 2.1   hk     04/18/14 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_CMD8_VOL_PATTERN 0x1AA
+#define XSDPS_RESPOCR_READY    0x80000000
+#define XSDPS_ACMD41_HCS       0x40000000
+#define XSDPS_ACMD41_3V3       0x00300000
+#define XSDPS_CMD1_HIGH_VOL    0x00FF8000
+#define XSDPS_CMD1_DUAL_VOL    0x00FF8010
+
+/**************************** Type Definitions *******************************/
+
+/***************** Macros (Inline Functions) Definitions *********************/
+
+#define XSDPS_INIT_DELAY       2000
+
+/************************** Function Prototypes ******************************/
+u32 XSdPs_FrameCmd(u32 Cmd);
+int XSdPs_CmdTransfer(XSdPs *InstancePtr, u32 Cmd, u32 Arg, u32 BlkCnt);
+void XSdPs_SetupADMA2DescTbl(XSdPs *InstancePtr, u32 BlkCnt, const u8 *Buff);
+
+/*****************************************************************************/
+/**
+*
+* Initializes a specific XSdPs instance such that the driver is ready to use.
+*
+*
+* @param       InstancePtr is a pointer to the XSdPs instance.
+* @param       ConfigPtr is a reference to a structure containing information
+*              about a specific SD device. This function initializes an
+*              InstancePtr object for a specific device specified by the
+*              contents of Config.
+* @param       EffectiveAddr is the device base address in the virtual memory
+*              address space. The caller is responsible for keeping the address
+*              mapping from EffectiveAddr to the device physical base address
+*              unchanged once this function is invoked. Unexpected errors may
+*              occur if the address mapping changes after this function is
+*              called. If address translation is not used, use
+*              ConfigPtr->Config.BaseAddress for this device.
+*
+* @return
+*              - XST_SUCCESS if successful.
+*              - XST_DEVICE_IS_STARTED if the device is already started.
+*              It must be stopped to re-initialize.
+*
+* @note                This function initializes the host controller.
+*              Initial clock of 400KHz is set.
+*              Voltage of 3.3V is selected as that is supported by host.
+*              Interrupts status is enabled and signal disabled by default.
+*              Default data direction is card to host and
+*              32 bit ADMA2 is selected. Defualt Block size is 512 bytes.
+*
+******************************************************************************/
+int XSdPs_CfgInitialize(XSdPs *InstancePtr, XSdPs_Config *ConfigPtr,
+                               u32 EffectiveAddr)
+{
+       u32 ClockReg;
+
+       Xil_AssertNonvoid(InstancePtr != NULL);
+       Xil_AssertNonvoid(ConfigPtr != NULL);
+
+       /*
+        * Set some default values.
+        */
+       InstancePtr->Config.BaseAddress = EffectiveAddr;
+       InstancePtr->Config.InputClockHz = ConfigPtr->InputClockHz;
+       InstancePtr->IsReady = XIL_COMPONENT_IS_READY;
+
+       /*
+        * "Software reset for all" is initiated
+        */
+       XSdPs_WriteReg8(InstancePtr->Config.BaseAddress, XSDPS_SW_RST_OFFSET,
+                       XSDPS_SWRST_ALL_MASK);
+
+       /*
+        * Proceed with initialization only after reset is complete
+        */
+       while (XSdPs_ReadReg8(InstancePtr->Config.BaseAddress,
+                       XSDPS_SW_RST_OFFSET) & XSDPS_SWRST_ALL_MASK);
+
+       /*
+        * Read capabilities register and update it in Instance pointer.
+        * It is sufficient to read this once on power on.
+        */
+       InstancePtr->Host_Caps = XSdPs_ReadReg(InstancePtr->Config.BaseAddress,
+                                               XSDPS_CAPS_OFFSET);
+
+       /*
+        * SD clock frequency divider 128
+        * Enable the internal clock
+        */
+       XSdPs_WriteReg16(InstancePtr->Config.BaseAddress,
+               XSDPS_CLK_CTRL_OFFSET,
+               XSDPS_CC_SDCLK_FREQ_D128_MASK | XSDPS_CC_INT_CLK_EN_MASK);
+
+       /*
+        * 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);
+
+       /*
+        * Select voltage and enable bus power.
+        */
+       XSdPs_WriteReg8(InstancePtr->Config.BaseAddress,
+                       XSDPS_POWER_CTRL_OFFSET,
+                       XSDPS_PC_BUS_VSEL_3V3_MASK | XSDPS_PC_BUS_PWR_MASK);
+
+       XSdPs_WriteReg8(InstancePtr->Config.BaseAddress,
+                       XSDPS_HOST_CTRL1_OFFSET,
+                       XSDPS_HC_DMA_ADMA2_32_MASK);
+
+       /*
+        * Enable all interrupt status except card interrupt initially
+        */
+       XSdPs_WriteReg16(InstancePtr->Config.BaseAddress,
+                       XSDPS_NORM_INTR_STS_EN_OFFSET,
+                       XSDPS_NORM_INTR_ALL_MASK & (~XSDPS_INTR_CARD_MASK));
+
+       XSdPs_WriteReg16(InstancePtr->Config.BaseAddress,
+                       XSDPS_ERR_INTR_STS_EN_OFFSET,
+                       XSDPS_ERROR_INTR_ALL_MASK);
+
+       /*
+        * Disable all interrupt signals by default.
+        */
+       XSdPs_WriteReg16(InstancePtr->Config.BaseAddress,
+                       XSDPS_NORM_INTR_SIG_EN_OFFSET, 0x0);
+       XSdPs_WriteReg16(InstancePtr->Config.BaseAddress,
+                       XSDPS_ERR_INTR_SIG_EN_OFFSET, 0x0);
+
+       /*
+        * Transfer mode register - default value
+        * DMA enabled, block count enabled, data direction card to host(read)
+        */
+       XSdPs_WriteReg16(InstancePtr->Config.BaseAddress,
+                       XSDPS_XFER_MODE_OFFSET,
+                       XSDPS_TM_DMA_EN_MASK | XSDPS_TM_BLK_CNT_EN_MASK |
+                       XSDPS_TM_DAT_DIR_SEL_MASK);
+
+       /*
+        * Set block size to 512 by default
+        */
+       XSdPs_WriteReg16(InstancePtr->Config.BaseAddress,
+                       XSDPS_BLK_SIZE_OFFSET, XSDPS_BLK_SIZE_512_MASK);
+
+       return XST_SUCCESS;
+}
+
+/*****************************************************************************/
+/**
+* SD initialization is done in this function
+*
+*
+* @param       InstancePtr is a pointer to the instance to be worked on.
+*
+* @return
+*              - XST_SUCCESS if initialization was successful
+*              - XST_FAILURE if failure - could be because
+*                      a) SD is already initialized
+*                      b) There is no card inserted
+*                      c) One of the steps (commands) in the
+                          initialization cycle failed
+*
+* @note                This function initializes the SD card by following its
+*              initialization and identification state diagram.
+*              CMD0 is sent to reset card.
+*              CMD8 and ACDM41 are sent to identify voltage and
+*              high capacity support
+*              CMD2 and CMD3 are sent to obtain Card ID and
+*              Relative card address respectively.
+*              CMD9 is sent to read the card specific data.
+*
+******************************************************************************/
+int XSdPs_SdCardInitialize(XSdPs *InstancePtr)
+{
+       u32 PresentStateReg;
+       u32 Status;
+       u32 RespOCR = 0x0;
+       u32 CSD[4];
+
+       Xil_AssertNonvoid(InstancePtr != NULL);
+       Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY);
+
+       /*
+        * Check the present state register to make sure
+        * card is inserted and detected by host controller
+        */
+       PresentStateReg = XSdPs_ReadReg(InstancePtr->Config.BaseAddress,
+                       XSDPS_PRES_STATE_OFFSET);
+       if ((PresentStateReg & XSDPS_PSR_CARD_INSRT_MASK) == 0) {
+               Status = XST_FAILURE;
+               goto RETURN_PATH;
+       }
+
+       /*
+        * 74 CLK delay after card is powered up, before the first command.
+        */
+
+#ifdef __arm__
+
+       usleep(XSDPS_INIT_DELAY);
+
+#endif
+
+#ifdef __MICROBLAZE__
+
+       /* 2 msec delay */
+       MB_Sleep(2);
+
+#endif
+
+       /*
+        * CMD0 no response expected
+        */
+       Status = XSdPs_CmdTransfer(InstancePtr, CMD0, 0, 0);
+       if (Status != XST_SUCCESS) {
+               Status = XST_FAILURE;
+               goto RETURN_PATH;
+       }
+
+       /*
+        * CMD8; response expected
+        * 0x1AA - Supply Voltage 2.7 - 3.6V and AA is pattern
+        */
+       Status = XSdPs_CmdTransfer(InstancePtr, CMD8,
+                       XSDPS_CMD8_VOL_PATTERN, 0);
+       if (Status != XST_SUCCESS) {
+               Status = XST_FAILURE;
+               goto RETURN_PATH;
+       }
+
+       RespOCR = XSdPs_ReadReg(InstancePtr->Config.BaseAddress,
+                                               XSDPS_RESP0_OFFSET);
+       if (RespOCR != XSDPS_CMD8_VOL_PATTERN) {
+               Status = XST_FAILURE;
+               goto RETURN_PATH;
+       }
+
+       RespOCR = 0;
+       /*
+        * Send ACMD41 while card is still busy with power up
+        */
+       while ((RespOCR & XSDPS_RESPOCR_READY) == 0) {
+               Status = XSdPs_CmdTransfer(InstancePtr, CMD55, 0, 0);
+               if (Status != XST_SUCCESS) {
+                       Status = XST_FAILURE;
+                       goto RETURN_PATH;
+               }
+
+               /*
+                * 0x40300000 - Host High Capacity support & 3.3V window
+                */
+               Status = XSdPs_CmdTransfer(InstancePtr, ACMD41,
+                               (XSDPS_ACMD41_HCS | XSDPS_ACMD41_3V3), 0);
+               if (Status != XST_SUCCESS) {
+                       Status = XST_FAILURE;
+                       goto RETURN_PATH;
+               }
+
+               /*
+                * Response with card capacity
+                */
+               RespOCR = XSdPs_ReadReg(InstancePtr->Config.BaseAddress,
+                               XSDPS_RESP0_OFFSET);
+
+       }
+
+       /*
+        * Update HCS support flag based on card capacity response
+        */
+       if (RespOCR & XSDPS_ACMD41_HCS)
+               InstancePtr->HCS = 1;
+
+       /*
+        * CMD2 for Card ID
+        */
+       Status = XSdPs_CmdTransfer(InstancePtr, CMD2, 0, 0);
+       if (Status != XST_SUCCESS) {
+               Status = XST_FAILURE;
+               goto RETURN_PATH;
+       }
+
+       InstancePtr->CardID[0] =
+                       XSdPs_ReadReg16(InstancePtr->Config.BaseAddress,
+                       XSDPS_RESP0_OFFSET);
+       InstancePtr->CardID[1] =
+                       XSdPs_ReadReg16(InstancePtr->Config.BaseAddress,
+                       XSDPS_RESP1_OFFSET);
+       InstancePtr->CardID[2] =
+                       XSdPs_ReadReg16(InstancePtr->Config.BaseAddress,
+                       XSDPS_RESP2_OFFSET);
+       InstancePtr->CardID[3] =
+                       XSdPs_ReadReg16(InstancePtr->Config.BaseAddress,
+                       XSDPS_RESP3_OFFSET);
+
+       while (InstancePtr->RelCardAddr == 0) {
+               Status = XSdPs_CmdTransfer(InstancePtr, CMD3, 0, 0);
+               if (Status != XST_SUCCESS) {
+                       Status = XST_FAILURE;
+                       goto RETURN_PATH;
+               }
+
+               /*
+                * Relative card address is stored as the upper 16 bits
+                * This is to avoid shifting when sending commands
+                */
+               InstancePtr->RelCardAddr =
+                               XSdPs_ReadReg(InstancePtr->Config.BaseAddress,
+                                       XSDPS_RESP0_OFFSET) & 0xFFFF0000;
+       }
+
+       Status = XSdPs_CmdTransfer(InstancePtr, CMD9, (InstancePtr->RelCardAddr), 0);
+       if (Status != XST_SUCCESS) {
+               Status = XST_FAILURE;
+               goto RETURN_PATH;
+       }
+
+       /*
+        * Card specific data is read.
+        * Currently not used for any operation.
+        */
+       CSD[0] = XSdPs_ReadReg(InstancePtr->Config.BaseAddress,
+                       XSDPS_RESP0_OFFSET);
+       CSD[1] = XSdPs_ReadReg(InstancePtr->Config.BaseAddress,
+                       XSDPS_RESP1_OFFSET);
+       CSD[2] = XSdPs_ReadReg(InstancePtr->Config.BaseAddress,
+                       XSDPS_RESP2_OFFSET);
+       CSD[3] = XSdPs_ReadReg(InstancePtr->Config.BaseAddress,
+                       XSDPS_RESP3_OFFSET);
+
+       Status = XST_SUCCESS;
+
+RETURN_PATH:
+       return Status;
+
+}
+
+/*****************************************************************************/
+/**
+* This function does SD command generation.
+*
+* @param       InstancePtr is a pointer to the instance to be worked on.
+* @param       Cmd is the command to be sent.
+* @param       Arg is the argument to be sent along with the command.
+*              This could be address or any other information
+* @param       BlkCnt - Block count passed by the user.
+*
+* @return
+*              - XST_SUCCESS if initialization was successful
+*              - XST_FAILURE if failure - could be because another transfer
+*                      is in progress or command or data inhibit is set
+*
+******************************************************************************/
+int XSdPs_CmdTransfer(XSdPs *InstancePtr, u32 Cmd, u32 Arg, u32 BlkCnt)
+{
+       u32 PresentStateReg;
+       u32 CommandReg;
+       u32 StatusReg;
+       u32 Status;
+
+       Xil_AssertNonvoid(InstancePtr != NULL);
+       Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY);
+
+       /*
+        * Check the command inhibit to make sure no other
+        * command transfer is in progress
+        */
+       PresentStateReg = XSdPs_ReadReg(InstancePtr->Config.BaseAddress,
+                       XSDPS_PRES_STATE_OFFSET);
+       if (PresentStateReg & XSDPS_PSR_INHIBIT_CMD_MASK) {
+               Status = XST_FAILURE;
+               goto RETURN_PATH;
+       }
+
+       /*
+        * Write block count register
+        */
+       XSdPs_WriteReg16(InstancePtr->Config.BaseAddress,
+                       XSDPS_BLK_CNT_OFFSET, BlkCnt);
+
+       XSdPs_WriteReg8(InstancePtr->Config.BaseAddress,
+                       XSDPS_TIMEOUT_CTRL_OFFSET, 0xE);
+
+       /*
+        * Write argument register
+        */
+       XSdPs_WriteReg(InstancePtr->Config.BaseAddress,
+                       XSDPS_ARGMT_OFFSET, Arg);
+
+       XSdPs_WriteReg16(InstancePtr->Config.BaseAddress,
+                       XSDPS_NORM_INTR_STS_OFFSET, XSDPS_NORM_INTR_ALL_MASK);
+       XSdPs_WriteReg16(InstancePtr->Config.BaseAddress,
+                       XSDPS_ERR_INTR_STS_OFFSET, XSDPS_ERROR_INTR_ALL_MASK);
+       /*
+        * Command register is set to trigger transfer of command
+        */
+       CommandReg = XSdPs_FrameCmd(Cmd);
+
+       /*
+        * Mask to avoid writing to reserved bits 31-30
+        * This is necessary because 0x80000000 is used  by this software to
+        * distinguish between ACMD and CMD of same number
+        */
+       CommandReg = CommandReg & 0x3FFF;
+
+       /*
+        * Check for data inhibit in case of command using DAT lines
+        */
+       PresentStateReg = XSdPs_ReadReg(InstancePtr->Config.BaseAddress,
+                       XSDPS_PRES_STATE_OFFSET);
+       if ((PresentStateReg & XSDPS_PSR_INHIBIT_CMD_MASK) &&
+                       (CommandReg & XSDPS_DAT_PRESENT_SEL_MASK)) {
+               Status = XST_FAILURE;
+               goto RETURN_PATH;
+       }
+
+       XSdPs_WriteReg16(InstancePtr->Config.BaseAddress, XSDPS_CMD_OFFSET,
+                       CommandReg);
+
+       /*
+        * 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_CC_MASK) == 0);
+       /*
+        * Write to clear bit
+        */
+       XSdPs_WriteReg16(InstancePtr->Config.BaseAddress,
+                       XSDPS_NORM_INTR_STS_OFFSET,
+                       XSDPS_INTR_CC_MASK);
+
+       Status = XST_SUCCESS;
+
+       RETURN_PATH:
+               return Status;
+
+}
+
+/*****************************************************************************/
+/**
+* This function frames the Command register for a particular command.
+* Note that this generates only the command register value i.e.
+* the upper 16 bits of the transfer mode and command register.
+* This value is already shifted to be upper 16 bits and can be directly
+* OR'ed with transfer mode register value.
+*
+* @param       Command to be sent.
+*
+* @return      Command register value complete with response type and
+*              data, CRC and index related flags.
+*
+******************************************************************************/
+u32 XSdPs_FrameCmd(u32 Cmd)
+{
+               u32 RetVal;
+
+               RetVal = Cmd;
+
+               switch(Cmd) {
+               case CMD0:
+                       RetVal |= RESP_NONE;
+               break;
+               case CMD1:
+                       RetVal |= RESP_R3;
+               break;
+               case CMD2:
+                       RetVal |= RESP_R2;
+               break;
+               case CMD3:
+                       RetVal |= RESP_R6;
+               break;
+               case CMD4:
+                       RetVal |= RESP_NONE;
+                       break;
+               case CMD5:
+                       RetVal |= RESP_R1B;
+               break;
+
+#ifndef MMC_CARD
+               case CMD6:
+                       RetVal |= RESP_R1 | XSDPS_DAT_PRESENT_SEL_MASK;
+                       break;
+#else
+               case CMD6:
+                       RetVal |= RESP_R1B;
+                       break;
+#endif
+
+               case ACMD6:
+                       RetVal |= RESP_R1;
+               break;
+               case CMD7:
+                       RetVal |= RESP_R1;
+               break;
+
+#ifndef MMC_CARD
+               case CMD8:
+                       RetVal |= RESP_R1;
+                       break;
+#else
+               case CMD8:
+                       RetVal |= RESP_R1 | XSDPS_DAT_PRESENT_SEL_MASK;
+                       break;
+#endif
+
+               case CMD9:
+                       RetVal |= RESP_R2;
+               break;
+               case CMD10:
+               case CMD12:
+               case ACMD13:
+               case CMD16:
+                       RetVal |= RESP_R1;
+               break;
+               case CMD17:
+               case CMD18:
+                       RetVal |= RESP_R1 | XSDPS_DAT_PRESENT_SEL_MASK;
+               break;
+               case CMD23:
+               case ACMD23:
+               case CMD24:
+               case CMD25:
+                       RetVal |= RESP_R1 | XSDPS_DAT_PRESENT_SEL_MASK;
+               case ACMD41:
+                       RetVal |= RESP_R3;
+               break;
+               case ACMD42:
+                       RetVal |= RESP_R1;
+               break;
+               case ACMD51:
+                       RetVal |= RESP_R1 | XSDPS_DAT_PRESENT_SEL_MASK;
+               break;
+               case CMD52:
+               case CMD55:
+                       RetVal |= RESP_R1;
+               break;
+               case CMD58:
+               break;
+               }
+
+               return RetVal;
+}
+
+/*****************************************************************************/
+/**
+* This function performs SD read in polled mode.
+*
+* @param       InstancePtr is a pointer to the instance to be worked on.
+* @param       Arg is the address passed by the user that is to be sent as
+*              argument along with the command.
+* @param       BlkCnt - Block count passed by the user.
+* @param       Buff - Pointer to the data buffer for a DMA transfer.
+*
+* @return
+*              - XST_SUCCESS if initialization was successful
+*              - XST_FAILURE if failure - could be because another transfer
+*              is in progress or command or data inhibit is set
+*
+******************************************************************************/
+int XSdPs_ReadPolled(XSdPs *InstancePtr, u32 Arg, u32 BlkCnt, u8 *Buff)
+{
+       u32 Status;
+       u32 PresentStateReg;
+       u32 StatusReg;
+
+       /*
+        * Check status to ensure card is initialized
+        */
+       PresentStateReg = XSdPs_ReadReg(InstancePtr->Config.BaseAddress,
+                       XSDPS_PRES_STATE_OFFSET);
+       if ((PresentStateReg & XSDPS_PSR_CARD_INSRT_MASK) == 0x0) {
+               Status = XST_FAILURE;
+               goto RETURN_PATH;
+       }
+
+       /*
+        * Set block size to 512 if not already set
+        */
+       if( XSdPs_ReadReg(InstancePtr->Config.BaseAddress,
+                       XSDPS_BLK_SIZE_OFFSET) != XSDPS_BLK_SIZE_512_MASK ) {
+               Status = XSdPs_SetBlkSize(InstancePtr,
+                       XSDPS_BLK_SIZE_512_MASK);
+               if (Status != XST_SUCCESS) {
+                       Status = XST_FAILURE;
+                       goto RETURN_PATH;
+               }
+       }
+
+       XSdPs_SetupADMA2DescTbl(InstancePtr, BlkCnt, Buff);
+
+       XSdPs_WriteReg16(InstancePtr->Config.BaseAddress,
+                       XSDPS_XFER_MODE_OFFSET,
+                       XSDPS_TM_AUTO_CMD12_EN_MASK |
+                       XSDPS_TM_BLK_CNT_EN_MASK | XSDPS_TM_DAT_DIR_SEL_MASK |
+                       XSDPS_TM_DMA_EN_MASK | XSDPS_TM_MUL_SIN_BLK_SEL_MASK);
+
+       /*
+        * Send block read command
+        */
+       Status = XSdPs_CmdTransfer(InstancePtr, CMD18, Arg, BlkCnt);
+       if (Status != XST_SUCCESS) {
+               Status = XST_FAILURE;
+               goto RETURN_PATH;
+       }
+
+       /*
+        * Check for transfer complete
+        */
+       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;
+}
+
+/*****************************************************************************/
+/**
+* This function performs SD write in polled mode.
+*
+* @param       InstancePtr is a pointer to the instance to be worked on.
+* @param       Arg is the address passed by the user that is to be sent as
+*              argument along with the command.
+* @param       BlkCnt - Block count passed by the user.
+* @param       Buff - Pointer to the data buffer for a DMA transfer.
+*
+* @return
+*              - XST_SUCCESS if initialization was successful
+*              - XST_FAILURE if failure - could be because another transfer
+*              is in progress or command or data inhibit is set
+*
+******************************************************************************/
+int XSdPs_WritePolled(XSdPs *InstancePtr, u32 Arg, u32 BlkCnt, const u8 *Buff)
+{
+       u32 Status;
+       u32 PresentStateReg;
+       u32 StatusReg;
+
+       /*
+        * Check status to ensure card is initialized
+        */
+       PresentStateReg = XSdPs_ReadReg(InstancePtr->Config.BaseAddress,
+                       XSDPS_PRES_STATE_OFFSET);
+       if ((PresentStateReg & XSDPS_PSR_CARD_INSRT_MASK) == 0x0) {
+               Status = XST_FAILURE;
+               goto RETURN_PATH;
+       }
+
+       /*
+        * Set block size to 512 if not already set
+        */
+       if( XSdPs_ReadReg(InstancePtr->Config.BaseAddress,
+                       XSDPS_BLK_SIZE_OFFSET) != XSDPS_BLK_SIZE_512_MASK ) {
+               Status = XSdPs_SetBlkSize(InstancePtr,
+                       XSDPS_BLK_SIZE_512_MASK);
+               if (Status != XST_SUCCESS) {
+                       Status = XST_FAILURE;
+                       goto RETURN_PATH;
+               }
+
+       }
+
+       XSdPs_SetupADMA2DescTbl(InstancePtr, BlkCnt, Buff);
+
+       XSdPs_WriteReg16(InstancePtr->Config.BaseAddress,
+                       XSDPS_XFER_MODE_OFFSET,
+                       XSDPS_TM_AUTO_CMD12_EN_MASK |
+                       XSDPS_TM_BLK_CNT_EN_MASK |
+                       XSDPS_TM_MUL_SIN_BLK_SEL_MASK | XSDPS_TM_DMA_EN_MASK);
+
+       /*
+        * Send block write command
+        */
+       Status = XSdPs_CmdTransfer(InstancePtr, CMD25, Arg, 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 = XST_SUCCESS;
+
+       RETURN_PATH:
+               return Status;
+}
+
+/*****************************************************************************/
+/**
+*
+* Selects card and sets default block size
+*
+*
+* @param       InstancePtr is a pointer to the XSdPs instance.
+*
+* @return
+*              - XST_SUCCESS if successful.
+*              - XST_FAILURE if fail.
+*
+* @note                None.
+*
+******************************************************************************/
+int XSdPs_Select_Card (XSdPs *InstancePtr)
+{
+       u32 Status = 0;
+
+       /*
+        * Send CMD7 - Select card
+        */
+       Status = XSdPs_CmdTransfer(InstancePtr, CMD7,
+                       InstancePtr->RelCardAddr, 0);
+       if (Status != XST_SUCCESS) {
+               Status = XST_FAILURE;
+               goto RETURN_PATH;
+       }
+
+       Status = XSdPs_ReadReg(InstancePtr->Config.BaseAddress,
+                       XSDPS_RESP0_OFFSET);
+
+       /*
+        * Set default block size
+        */
+       Status = XSdPs_SetBlkSize(InstancePtr, XSDPS_BLK_SIZE_512_MASK);
+       if (Status != XST_SUCCESS) {
+               Status = XST_FAILURE;
+               goto RETURN_PATH;
+       }
+
+       Status = XST_SUCCESS;
+
+       RETURN_PATH:
+               return Status;
+
+}
+
+/*****************************************************************************/
+/**
+*
+* API to setup ADMA2 descriptor table
+*
+*
+* @param       InstancePtr is a pointer to the XSdPs instance.
+* @param       BlkCnt - block count.
+* @param       Buff pointer to data buffer.
+*
+* @return      None
+*
+* @note                None.
+*
+******************************************************************************/
+void XSdPs_SetupADMA2DescTbl(XSdPs *InstancePtr, u32 BlkCnt, const u8 *Buff)
+{
+       u32 TotalDescLines = 0;
+       u32 DescNum = 0;
+       u32 BlkSize = 0;
+
+       /*
+        * Setup ADMA2 - Write descriptor table and point ADMA SAR to it
+        */
+       BlkSize = XSdPs_ReadReg16(InstancePtr->Config.BaseAddress,
+                                       XSDPS_BLK_SIZE_OFFSET);
+       BlkSize = BlkSize & XSDPS_BLK_SIZE_MASK;
+
+       if((BlkCnt*BlkSize) < XSDPS_DESC_MAX_LENGTH) {
+
+               TotalDescLines = 1;
+
+       }else {
+
+               TotalDescLines = ((BlkCnt*BlkSize) / XSDPS_DESC_MAX_LENGTH);
+               if ((BlkCnt * BlkSize) % XSDPS_DESC_MAX_LENGTH)
+                       TotalDescLines += 1;
+
+       }
+
+       for (DescNum = 0; DescNum < (TotalDescLines-1); DescNum++) {
+               InstancePtr->Adma2_DescrTbl[DescNum].Address =
+                               (u32)(Buff + (DescNum*XSDPS_DESC_MAX_LENGTH));
+               InstancePtr->Adma2_DescrTbl[DescNum].Attribute =
+                               XSDPS_DESC_TRAN | XSDPS_DESC_VALID;
+               /*
+                * This will write '0' to length field which indicates 65536
+                */
+               InstancePtr->Adma2_DescrTbl[DescNum].Length =
+                               (u16)XSDPS_DESC_MAX_LENGTH;
+       }
+
+       InstancePtr->Adma2_DescrTbl[TotalDescLines-1].Address =
+                       (u32)(Buff + (DescNum*XSDPS_DESC_MAX_LENGTH));
+
+       InstancePtr->Adma2_DescrTbl[TotalDescLines-1].Attribute =
+                       XSDPS_DESC_TRAN | XSDPS_DESC_END | XSDPS_DESC_VALID;
+
+       InstancePtr->Adma2_DescrTbl[TotalDescLines-1].Length =
+                       (BlkCnt*BlkSize) - (DescNum*XSDPS_DESC_MAX_LENGTH);
+
+
+       XSdPs_WriteReg(InstancePtr->Config.BaseAddress, XSDPS_ADMA_SAR_OFFSET,
+                       (u32)&(InstancePtr->Adma2_DescrTbl[0]));
+
+}
+
+/*****************************************************************************/
+/**
+* Mmc initialization is done in this function
+*
+*
+* @param       InstancePtr is a pointer to the instance to be worked on.
+*
+* @return
+*              - XST_SUCCESS if initialization was successful
+*              - XST_FAILURE if failure - could be because
+*                      a) MMC is already initialized
+*                      b) There is no card inserted
+*                      c) One of the steps (commands) in the initialization
+*                         cycle failed
+* @note        This function initializes the SD card by following its
+*              initialization and identification state diagram.
+*              CMD0 is sent to reset card.
+*              CMD1 sent to identify voltage and high capacity support
+*              CMD2 and CMD3 are sent to obtain Card ID and
+*              Relative card address respectively.
+*              CMD9 is sent to read the card specific data.
+*
+******************************************************************************/
+int XSdPs_MmcCardInitialize(XSdPs *InstancePtr)
+{
+       u32 PresentStateReg;
+       u32 Status;
+       u32 RespOCR = 0x0;
+       u32 CSD[4];
+
+       Xil_AssertNonvoid(InstancePtr != NULL);
+       Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY);
+
+       /*
+        * Check the present state register to make sure
+        * card is inserted and detected by host controller
+        */
+       PresentStateReg = XSdPs_ReadReg(InstancePtr->Config.BaseAddress,
+                       XSDPS_PRES_STATE_OFFSET);
+       if ((PresentStateReg & XSDPS_PSR_CARD_INSRT_MASK) == 0) {
+               Status = XST_FAILURE;
+               goto RETURN_PATH;
+       }
+
+       /*
+        * 74 CLK delay after card is powered up, before the first command.
+        */
+
+#ifdef __arm__
+
+       usleep(XSDPS_INIT_DELAY);
+
+#endif
+
+#ifdef __MICROBLAZE__
+
+       /* 2 msec delay */
+       MB_Sleep(2);
+
+#endif
+
+       /*
+        * CMD0 no response expected
+        */
+       Status = XSdPs_CmdTransfer(InstancePtr, CMD0, 0, 0);
+       if (Status != XST_SUCCESS) {
+               Status = XST_FAILURE;
+               goto RETURN_PATH;
+       }
+
+       RespOCR = 0;
+       /*
+        * Send CMD1 while card is still busy with power up
+        */
+       while ((RespOCR & XSDPS_RESPOCR_READY) == 0) {
+
+               /*
+                * Host High Capacity support & High volage window
+                */
+               Status = XSdPs_CmdTransfer(InstancePtr, CMD1,
+                               XSDPS_ACMD41_HCS | XSDPS_CMD1_HIGH_VOL, 0);
+               if (Status != XST_SUCCESS) {
+                       Status = XST_FAILURE;
+                       goto RETURN_PATH;
+               }
+
+               /*
+                * Response with card capacity
+                */
+               RespOCR = XSdPs_ReadReg(InstancePtr->Config.BaseAddress,
+                               XSDPS_RESP0_OFFSET);
+
+       }
+
+       /*
+        * Update HCS support flag based on card capacity response
+        */
+       if (RespOCR & XSDPS_ACMD41_HCS)
+               InstancePtr->HCS = 1;
+
+       /*
+        * CMD2 for Card ID
+        */
+       Status = XSdPs_CmdTransfer(InstancePtr, CMD2, 0, 0);
+       if (Status != XST_SUCCESS) {
+               Status = XST_FAILURE;
+               goto RETURN_PATH;
+       }
+
+       InstancePtr->CardID[0] =
+                       XSdPs_ReadReg16(InstancePtr->Config.BaseAddress,
+                       XSDPS_RESP0_OFFSET);
+       InstancePtr->CardID[1] =
+                       XSdPs_ReadReg16(InstancePtr->Config.BaseAddress,
+                       XSDPS_RESP1_OFFSET);
+       InstancePtr->CardID[2] =
+                       XSdPs_ReadReg16(InstancePtr->Config.BaseAddress,
+                       XSDPS_RESP2_OFFSET);
+       InstancePtr->CardID[3] =
+                       XSdPs_ReadReg16(InstancePtr->Config.BaseAddress,
+                       XSDPS_RESP3_OFFSET);
+
+       Status = XSdPs_CmdTransfer(InstancePtr, CMD3, 0, 0);
+       if (Status != XST_SUCCESS) {
+               Status = XST_FAILURE;
+               goto RETURN_PATH;
+       }
+
+       /*
+        * Relative card address is stored as the upper 16 bits
+        * This is to avoid shifting when sending commands
+        */
+       InstancePtr->RelCardAddr =
+                       XSdPs_ReadReg(InstancePtr->Config.BaseAddress,
+                               XSDPS_RESP0_OFFSET) & 0xFFFF0000;
+
+       Status = XSdPs_CmdTransfer(InstancePtr, CMD9, (InstancePtr->RelCardAddr), 0);
+       if (Status != XST_SUCCESS) {
+               Status = XST_FAILURE;
+               goto RETURN_PATH;
+       }
+
+       /*
+        * Card specific data is read.
+        * Currently not used for any operation.
+        */
+       CSD[0] = XSdPs_ReadReg(InstancePtr->Config.BaseAddress,
+                       XSDPS_RESP0_OFFSET);
+       CSD[1] = XSdPs_ReadReg(InstancePtr->Config.BaseAddress,
+                       XSDPS_RESP1_OFFSET);
+       CSD[2] = XSdPs_ReadReg(InstancePtr->Config.BaseAddress,
+                       XSDPS_RESP2_OFFSET);
+       CSD[3] = XSdPs_ReadReg(InstancePtr->Config.BaseAddress,
+                       XSDPS_RESP3_OFFSET);
+
+       Status = XST_SUCCESS;
+
+RETURN_PATH:
+       return Status;
+
+}
+
+