From ee32c4dda80434b0f93ec195a0360e63f4b5e64d Mon Sep 17 00:00:00 2001 From: P L Sai Krishna Date: Thu, 9 Jul 2015 16:33:36 +0530 Subject: [PATCH] sdps: sdps: Added SD 3.0 features This patch add SD 3.0 features and modified the source such that works on both Zynq and ZynqMP. This patch also converts three line comments into single line comments. Signed-off-by: Srinivas Goud --- XilinxProcessorIPLib/drivers/sdps/src/xsdps.c | 709 ++++++++++++------ XilinxProcessorIPLib/drivers/sdps/src/xsdps.h | 25 +- .../drivers/sdps/src/xsdps_g.c | 2 +- .../drivers/sdps/src/xsdps_hw.h | 581 +++++++++++++- .../drivers/sdps/src/xsdps_options.c | 591 ++++++++++----- .../drivers/sdps/src/xsdps_sinit.c | 2 +- 6 files changed, 1491 insertions(+), 419 deletions(-) diff --git a/XilinxProcessorIPLib/drivers/sdps/src/xsdps.c b/XilinxProcessorIPLib/drivers/sdps/src/xsdps.c index 7cb26db0..98c18365 100644 --- a/XilinxProcessorIPLib/drivers/sdps/src/xsdps.c +++ b/XilinxProcessorIPLib/drivers/sdps/src/xsdps.c @@ -33,7 +33,7 @@ /** * * @file xsdps.c -* @addtogroup sdps_v2_4 +* @addtogroup sdps_v2_5 * @{ * @details * @@ -58,7 +58,7 @@ * Checked for DAT Inhibit mask instead of CMD * Inhibit mask in Cmd Transfer API. * Added Support for SD Card v1.0 -* +* 2.5 sg 07/09/15 Added SD 3.0 features * * ******************************************************************************/ @@ -88,17 +88,35 @@ #define XSDPS_ACMD41_3V3 0x00300000 #define XSDPS_CMD1_HIGH_VOL 0x00FF8000 #define XSDPS_CMD1_DUAL_VOL 0x00FF8010 +#define HIGH_SPEED_SUPPORT 0x2U +#define WIDTH_4_BIT_SUPPORT 0x4U +#define SD_CLK_25_MHZ 25000000U +#define SD_CLK_26_MHZ 26000000U +#define EXT_CSD_DEVICE_TYPE_BYTE 196 +#define EXT_CSD_DEVICE_TYPE_HIGH_SPEED 0x2 +#define EXT_CSD_DEVICE_TYPE_HIGH_SPEED_DDR_1V8 0x4 +#define EXT_CSD_DEVICE_TYPE_HIGH_SPEED_DDR_1V2 0x8 +#define EXT_CSD_DEVICE_TYPE_HS200_SDR_1V8 0x10 +#define EXT_CSD_DEVICE_TYPE_HS200_SDR_1V2 0x20 /**************************** Type Definitions *******************************/ /***************** Macros (Inline Functions) Definitions *********************/ - -#define XSDPS_INIT_DELAY 2000 +#ifdef __ICCARM__ +#pragma data_alignment = 32 +static u8 ExtCsd[512]; +#pragma data_alignment = 4 +#else +static u8 ExtCsd[512] __attribute__ ((aligned(32))); +#endif /************************** Function Prototypes ******************************/ -u32 XSdPs_FrameCmd(u32 Cmd); +u32 XSdPs_FrameCmd(XSdPs *InstancePtr, u32 Cmd); int XSdPs_CmdTransfer(XSdPs *InstancePtr, u32 Cmd, u32 Arg, u32 BlkCnt); void XSdPs_SetupADMA2DescTbl(XSdPs *InstancePtr, u32 BlkCnt, const u8 *Buff); +extern int XSdPs_Uhs_ModeInit(XSdPs *InstancePtr, u8 Mode); +static int XSdPs_IdentifyCard(XSdPs *InstancePtr); +static int XSdPs_Switch_Voltage(XSdPs *InstancePtr); /*****************************************************************************/ /** @@ -135,32 +153,37 @@ void XSdPs_SetupADMA2DescTbl(XSdPs *InstancePtr, u32 BlkCnt, const u8 *Buff); int XSdPs_CfgInitialize(XSdPs *InstancePtr, XSdPs_Config *ConfigPtr, u32 EffectiveAddr) { - u32 ClockReg; u32 Status; + u8 PowerLevel; Xil_AssertNonvoid(InstancePtr != NULL); Xil_AssertNonvoid(ConfigPtr != NULL); - /* - * Set some default values. - */ + /* Set some default values. */ InstancePtr->Config.BaseAddress = EffectiveAddr; InstancePtr->Config.InputClockHz = ConfigPtr->InputClockHz; InstancePtr->IsReady = XIL_COMPONENT_IS_READY; InstancePtr->Config.CardDetect = ConfigPtr->CardDetect; InstancePtr->Config.WriteProtect = ConfigPtr->WriteProtect; - /* - * "Software reset for all" is initiated - */ + /* Disable bus power */ + XSdPs_WriteReg8(InstancePtr->Config.BaseAddress, + XSDPS_POWER_CTRL_OFFSET, 0); + + /* Delay to poweroff card */ + sleep(1); + + /* "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 - */ + /* Proceed with initialization only after reset is complete */ while (XSdPs_ReadReg8(InstancePtr->Config.BaseAddress, XSDPS_SW_RST_OFFSET) & XSDPS_SWRST_ALL_MASK); + /* Host Controller version is read. */ + InstancePtr->HC_Version = + XSdPs_ReadReg16(InstancePtr->Config.BaseAddress, + XSDPS_HOST_CTRL_VER_OFFSET) & XSDPS_HC_SPEC_VER_MASK; /* * Read capabilities register and update it in Instance pointer. @@ -169,29 +192,36 @@ int XSdPs_CfgInitialize(XSdPs *InstancePtr, XSdPs_Config *ConfigPtr, InstancePtr->Host_Caps = XSdPs_ReadReg(InstancePtr->Config.BaseAddress, XSDPS_CAPS_OFFSET); - /* - * Select voltage and enable bus power. - */ + /* 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); - /* - * Change the clock frequency to 400 KHz - */ + /* Change the clock frequency to 400 KHz */ Status = XSdPs_Change_ClkFreq(InstancePtr, XSDPS_CLK_400_KHZ); if (Status != XST_SUCCESS) { Status = XST_FAILURE; goto RETURN_PATH ; } + if (InstancePtr->Host_Caps & XSDPS_CAP_VOLT_3V3_MASK) { + PowerLevel = XSDPS_PC_BUS_VSEL_3V3_MASK; + } else if (InstancePtr->Host_Caps & XSDPS_CAP_VOLT_3V0_MASK) { + PowerLevel = XSDPS_PC_BUS_VSEL_3V0_MASK; + } else if (InstancePtr->Host_Caps & XSDPS_CAP_VOLT_1V8_MASK) { + PowerLevel = XSDPS_PC_BUS_VSEL_1V8_MASK; + } + + /* Select voltage based on capability and enable bus power. */ + XSdPs_WriteReg8(InstancePtr->Config.BaseAddress, + XSDPS_POWER_CTRL_OFFSET, + PowerLevel | XSDPS_PC_BUS_PWR_MASK); + /* Enable ADMA2 in 64bit mode. */ XSdPs_WriteReg8(InstancePtr->Config.BaseAddress, XSDPS_HOST_CTRL1_OFFSET, XSDPS_HC_DMA_ADMA2_32_MASK); - /* - * Enable all interrupt status except card interrupt initially - */ + /* 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)); @@ -200,9 +230,7 @@ int XSdPs_CfgInitialize(XSdPs *InstancePtr, XSdPs_Config *ConfigPtr, XSDPS_ERR_INTR_STS_EN_OFFSET, XSDPS_ERROR_INTR_ALL_MASK); - /* - * Disable all interrupt signals by default. - */ + /* Disable all interrupt signals by default. */ XSdPs_WriteReg16(InstancePtr->Config.BaseAddress, XSDPS_NORM_INTR_SIG_EN_OFFSET, 0x0); XSdPs_WriteReg16(InstancePtr->Config.BaseAddress, @@ -217,9 +245,7 @@ int XSdPs_CfgInitialize(XSdPs *InstancePtr, XSdPs_Config *ConfigPtr, XSDPS_TM_DMA_EN_MASK | XSDPS_TM_BLK_CNT_EN_MASK | XSDPS_TM_DAT_DIR_SEL_MASK); - /* - * Set block size to 512 by default - */ + /* Set block size to 512 by default */ XSdPs_WriteReg16(InstancePtr->Config.BaseAddress, XSDPS_BLK_SIZE_OFFSET, XSDPS_BLK_SIZE_512_MASK); @@ -261,6 +287,7 @@ int XSdPs_SdCardInitialize(XSdPs *InstancePtr) u32 Status; u32 RespOCR = 0x0; u32 CSD[4]; + u32 Arg; Xil_AssertNonvoid(InstancePtr != NULL); Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); @@ -278,26 +305,7 @@ int XSdPs_SdCardInitialize(XSdPs *InstancePtr) } } - /* - * 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 - */ + /* CMD0 no response expected */ Status = XSdPs_CmdTransfer(InstancePtr, CMD0, 0, 0); if (Status != XST_SUCCESS) { Status = XST_FAILURE; @@ -318,16 +326,14 @@ int XSdPs_SdCardInitialize(XSdPs *InstancePtr) RespOCR = XSdPs_ReadReg(InstancePtr->Config.BaseAddress, XSDPS_RESP0_OFFSET); if (RespOCR != XSDPS_CMD8_VOL_PATTERN) { - InstancePtr->CardType = CT_SD1; + InstancePtr->Card_Version = XSDPS_SD_VER_1_0; } else { - InstancePtr->CardType = CT_SD2; + InstancePtr->Card_Version = XSDPS_SD_VER_2_0; } RespOCR = 0; - /* - * Send ACMD41 while card is still busy with power up - */ + /* 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) { @@ -335,33 +341,40 @@ int XSdPs_SdCardInitialize(XSdPs *InstancePtr) goto RETURN_PATH; } - /* - * 0x40300000 - Host High Capacity support & 3.3V window - */ + Arg = XSDPS_ACMD41_HCS | XSDPS_ACMD41_3V3 | (0x1FF << 15); + if (InstancePtr->HC_Version == XSDPS_HC_SPEC_V3) { + Arg |= XSDPS_OCR_S18; + } + + /* 0x40300000 - Host High Capacity support & 3.3V window */ Status = XSdPs_CmdTransfer(InstancePtr, ACMD41, - (XSDPS_ACMD41_HCS | XSDPS_ACMD41_3V3), 0); + Arg, 0); if (Status != XST_SUCCESS) { Status = XST_FAILURE; goto RETURN_PATH; } - /* - * Response with card capacity - */ + /* Response with card capacity */ RespOCR = XSdPs_ReadReg(InstancePtr->Config.BaseAddress, XSDPS_RESP0_OFFSET); } - /* - * Update HCS support flag based on card capacity response - */ + /* Update HCS support flag based on card capacity response */ if (RespOCR & XSDPS_ACMD41_HCS) InstancePtr->HCS = 1; - /* - * CMD2 for Card ID - */ + if (RespOCR & XSDPS_OCR_S18) { + InstancePtr->Switch1v8 = 1; + Status = XSdPs_Switch_Voltage(InstancePtr); + if (Status != XST_SUCCESS) { + Status = XST_FAILURE; + goto RETURN_PATH; + } + + } + + /* CMD2 for Card ID */ Status = XSdPs_CmdTransfer(InstancePtr, CMD2, 0, 0); if (Status != XST_SUCCESS) { Status = XST_FAILURE; @@ -424,6 +437,367 @@ RETURN_PATH: /*****************************************************************************/ /** +* +* Initialize Card with Identification mode sequence +* +* +* @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 +* +* +******************************************************************************/ +int XSdPs_CardInitialize(XSdPs *InstancePtr) { + u8 Tmp; + u32 Cnt; + u32 PresentStateReg; + u32 CtrlReg; + u32 CSD[4]; + u8 SCR[8] = { 0U }; + u8 ReadBuff[64] = { 0U }; + s32 Status = XST_SUCCESS; + + Xil_AssertNonvoid(InstancePtr != NULL); + Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + + /* Default settings */ + InstancePtr->BusWidth = XSDPS_1_BIT_WIDTH; + InstancePtr->CardType = XSDPS_CARD_SD; + InstancePtr->Switch1v8 = 0; + InstancePtr->BusSpeed = XSDPS_CLK_400_KHZ; + + if ((InstancePtr->HC_Version == XSDPS_HC_SPEC_V3) && + ((InstancePtr->Host_Caps & XSDPS_CAPS_SLOT_TYPE_MASK) + == XSDPS_CAPS_EMB_SLOT)) { + InstancePtr->CardType = XSDPS_CHIP_EMMC; + } else { + Status = XSdPs_IdentifyCard(InstancePtr); + if (Status == XST_FAILURE) { + goto RETURN_PATH; + } + } + + if ((InstancePtr->CardType != XSDPS_CARD_SD) && + (InstancePtr->CardType != XSDPS_CARD_MMC) && + (InstancePtr->CardType != XSDPS_CHIP_EMMC)) { + Status = XST_FAILURE; + goto RETURN_PATH; + } + + if (InstancePtr->CardType == XSDPS_CARD_SD) { + Status = XSdPs_SdCardInitialize(InstancePtr); + if (Status != XST_SUCCESS) { + Status = XST_FAILURE; + goto RETURN_PATH; + } + + /* Change clock to default clock 25MHz */ + InstancePtr->BusSpeed = SD_CLK_25_MHZ; + Status = XSdPs_Change_ClkFreq(InstancePtr, InstancePtr->BusSpeed); + if (Status != XST_SUCCESS) { + Status = XST_FAILURE; + goto RETURN_PATH; + } + + } else if ((InstancePtr->CardType == XSDPS_CARD_MMC) + || (InstancePtr->CardType == XSDPS_CHIP_EMMC)) { + Status = XSdPs_MmcCardInitialize(InstancePtr); + if (Status != XST_SUCCESS) { + Status = XST_FAILURE; + goto RETURN_PATH; + } + /* Change clock to default clock 26MHz */ + InstancePtr->BusSpeed = SD_CLK_26_MHZ; + Status = XSdPs_Change_ClkFreq(InstancePtr, InstancePtr->BusSpeed); + if (Status != XST_SUCCESS) { + Status = XST_FAILURE; + goto RETURN_PATH; + } + } else { + Status = XST_FAILURE; + goto RETURN_PATH; + } + + Status = XSdPs_Select_Card(InstancePtr); + if (Status != XST_SUCCESS) { + Status = XST_FAILURE; + goto RETURN_PATH; + } + + if (InstancePtr->CardType == XSDPS_CARD_SD) { + /* Pull-up disconnected during data transfer */ + Status = XSdPs_Pullup(InstancePtr); + if (Status != XST_SUCCESS) { + Status = XST_FAILURE; + goto RETURN_PATH; + } + + Status = XSdPs_Get_BusWidth(InstancePtr, SCR); + if (Status != XST_SUCCESS) { + Status = XST_FAILURE; + goto RETURN_PATH; + } + + if ((SCR[1] & WIDTH_4_BIT_SUPPORT) != 0U) { + Status = XSdPs_Change_BusWidth(InstancePtr); + if (Status != XST_SUCCESS) { + Status = XST_FAILURE; + goto RETURN_PATH; + } + } + + if (InstancePtr->Switch1v8 && + (InstancePtr->BusWidth == XSDPS_4_BIT_WIDTH)) { + /* Set UHS-I SDR104 mode */ + Status = XSdPs_Uhs_ModeInit(InstancePtr, + XSDPS_UHS_SPEED_MODE_SDR104); + if (Status != XST_SUCCESS) { + Status = XST_FAILURE; + goto RETURN_PATH; + } + + } else { + /* Get speed supported by device */ + Status = XSdPs_Get_BusSpeed(InstancePtr, ReadBuff); + if (Status != XST_SUCCESS) { + Status = XST_FAILURE; + goto RETURN_PATH; + } + + /* Check for high speed support */ + if ((ReadBuff[13] & HIGH_SPEED_SUPPORT) != 0U) { + Status = XSdPs_Change_BusSpeed(InstancePtr); + if (Status != XST_SUCCESS) { + Status = XST_FAILURE; + goto RETURN_PATH; + } + } + } + + } else if (InstancePtr->CardType == XSDPS_CARD_MMC) { + + Status = XSdPs_Change_BusWidth(InstancePtr); + if (Status != XST_SUCCESS) { + Status = XST_FAILURE; + goto RETURN_PATH; + } + + Status = XSdPs_Get_Mmc_ExtCsd(InstancePtr, ExtCsd); + if (Status != XST_SUCCESS) { + Status = XST_FAILURE; + goto RETURN_PATH; + } + + if (ExtCsd[EXT_CSD_BUS_WIDTH_BYTE] != EXT_CSD_BUS_WIDTH_4_BIT) { + Status = XST_FAILURE; + goto RETURN_PATH; + } + + if (ExtCsd[EXT_CSD_DEVICE_TYPE_BYTE] & EXT_CSD_DEVICE_TYPE_HIGH_SPEED) { + Status = XSdPs_Change_BusSpeed(InstancePtr); + if (Status != XST_SUCCESS) { + Status = XST_FAILURE; + goto RETURN_PATH; + } + + Status = XSdPs_Get_Mmc_ExtCsd(InstancePtr, ExtCsd); + if (Status != XST_SUCCESS) { + Status = XST_FAILURE; + goto RETURN_PATH; + } + + if (ExtCsd[EXT_CSD_HS_TIMING_BYTE] != EXT_CSD_HS_TIMING_HIGH) { + Status = XST_FAILURE; + goto RETURN_PATH; + } + } + } else { + /* Change bus width to 8-bit */ + Status = XSdPs_Change_BusWidth(InstancePtr); + if (Status != XST_SUCCESS) { + Status = XST_FAILURE; + goto RETURN_PATH; + } + + /* Get Extended CSD */ + Status = XSdPs_Get_Mmc_ExtCsd(InstancePtr, ExtCsd); + if (Status != XST_SUCCESS) { + Status = XST_FAILURE; + goto RETURN_PATH; + } + + /* Check for 8-bit support */ + if (ExtCsd[EXT_CSD_BUS_WIDTH_BYTE] != EXT_CSD_BUS_WIDTH_8_BIT) { + Status = XST_FAILURE; + goto RETURN_PATH; + } + + if (ExtCsd[EXT_CSD_DEVICE_TYPE_BYTE] & + (EXT_CSD_DEVICE_TYPE_HS200_SDR_1V8 | + EXT_CSD_DEVICE_TYPE_HS200_SDR_1V2)) { + Status = XSdPs_Change_BusSpeed(InstancePtr); + if (Status != XST_SUCCESS) { + Status = XST_FAILURE; + goto RETURN_PATH; + } + + Status = XSdPs_Get_Mmc_ExtCsd(InstancePtr, ExtCsd); + if (Status != XST_SUCCESS) { + Status = XST_FAILURE; + goto RETURN_PATH; + } + + if (ExtCsd[EXT_CSD_HS_TIMING_BYTE] != EXT_CSD_HS_TIMING_HS200) { + Status = XST_FAILURE; + goto RETURN_PATH; + } + } + } + + Status = XSdPs_SetBlkSize(InstancePtr, XSDPS_BLK_SIZE_512_MASK); + if (Status != XST_SUCCESS) { + Status = XST_FAILURE; + goto RETURN_PATH; + } + +RETURN_PATH: + return Status; +} + +/*****************************************************************************/ +/** +* +* Identify type of card using CMD0 + CMD1 sequence +* +* +* @param InstancePtr is a pointer to the XSdPs instance. +* +******************************************************************************/ +static int XSdPs_IdentifyCard(XSdPs *InstancePtr) +{ + int Status = XST_SUCCESS; + u32 OperCondReg; + + Xil_AssertNonvoid(InstancePtr != NULL); + Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + + /* 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; + } + + /* Host High Capacity support & High voltage window */ + Status = XSdPs_CmdTransfer(InstancePtr, CMD1, + XSDPS_ACMD41_HCS | XSDPS_CMD1_HIGH_VOL, 0); + if (Status != XST_SUCCESS) { + InstancePtr->CardType = XSDPS_CARD_SD; + } else { + InstancePtr->CardType = XSDPS_CARD_MMC; + } + + 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); + + /* "Software reset for all" is initiated */ + XSdPs_WriteReg8(InstancePtr->Config.BaseAddress, XSDPS_SW_RST_OFFSET, + XSDPS_SWRST_CMD_LINE_MASK); + + /* Proceed with initialization only after reset is complete */ + while (XSdPs_ReadReg8(InstancePtr->Config.BaseAddress, + XSDPS_SW_RST_OFFSET) & XSDPS_SWRST_CMD_LINE_MASK); + + Status = XST_SUCCESS; + +RETURN_PATH: + return Status; +} + +/*****************************************************************************/ +/** +* +* Switches the SD card voltage from 3v3 to 1v8 +* +* +* @param InstancePtr is a pointer to the XSdPs instance. +* +******************************************************************************/ +static int XSdPs_Switch_Voltage(XSdPs *InstancePtr) +{ + u32 Status; + u16 CtrlReg; + + /* Send switch voltage command */ + Status = XSdPs_CmdTransfer(InstancePtr, CMD11, 0, 0); + if (Status != XST_SUCCESS) { + Status = XST_FAILURE; + } + + /* Wait for CMD and DATA line to go low */ + while (XSdPs_ReadReg(InstancePtr->Config.BaseAddress, + XSDPS_PRES_STATE_OFFSET) + & (XSDPS_PSR_CMD_SG_LVL_MASK | XSDPS_PSR_DAT30_SG_LVL_MASK)); + + /* Stop the clock */ + CtrlReg = XSdPs_ReadReg16(InstancePtr->Config.BaseAddress, + XSDPS_CLK_CTRL_OFFSET); + CtrlReg &= ~(XSDPS_CC_SD_CLK_EN_MASK | XSDPS_CC_INT_CLK_EN_MASK); + XSdPs_WriteReg16(InstancePtr->Config.BaseAddress, XSDPS_CLK_CTRL_OFFSET, + CtrlReg); + + /* Wait minimum 5mSec */ + usleep(5000); + + /* Enabling 1.8V in controller */ + CtrlReg = XSdPs_ReadReg16(InstancePtr->Config.BaseAddress, + XSDPS_HOST_CTRL2_OFFSET); + CtrlReg |= XSDPS_HC2_1V8_EN_MASK; + XSdPs_WriteReg16(InstancePtr->Config.BaseAddress, XSDPS_HOST_CTRL2_OFFSET, + CtrlReg); + + /* Start clock */ + Status = XSdPs_Change_ClkFreq(InstancePtr, XSDPS_CLK_400_KHZ); + if (Status != XST_SUCCESS) { + Status = XST_FAILURE; + goto RETURN_PATH; + } + + /* Wait for CMD and DATA line to go high */ + while ((XSdPs_ReadReg(InstancePtr->Config.BaseAddress, + XSDPS_PRES_STATE_OFFSET) + & (XSDPS_PSR_CMD_SG_LVL_MASK | XSDPS_PSR_DAT30_SG_LVL_MASK)) + != (XSDPS_PSR_CMD_SG_LVL_MASK | XSDPS_PSR_DAT30_SG_LVL_MASK)); + +RETURN_PATH: + return Status; +} + +/*****************************************************************************/ +/** + * This function does SD command generation. * * @param InstancePtr is a pointer to the instance to be worked on. @@ -459,18 +833,14 @@ int XSdPs_CmdTransfer(XSdPs *InstancePtr, u32 Cmd, u32 Arg, u32 BlkCnt) goto RETURN_PATH; } - /* - * Write block count register - */ + /* 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 - */ + /* Write argument register */ XSdPs_WriteReg(InstancePtr->Config.BaseAddress, XSDPS_ARGMT_OFFSET, Arg); @@ -478,10 +848,8 @@ int XSdPs_CmdTransfer(XSdPs *InstancePtr, u32 Cmd, u32 Arg, u32 BlkCnt) 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); + /* Command register is set to trigger transfer of command */ + CommandReg = XSdPs_FrameCmd(InstancePtr, Cmd); /* * Mask to avoid writing to reserved bits 31-30 @@ -490,9 +858,7 @@ int XSdPs_CmdTransfer(XSdPs *InstancePtr, u32 Cmd, u32 Arg, u32 BlkCnt) */ CommandReg = CommandReg & 0x3FFF; - /* - * Check for data inhibit in case of command using DAT lines - */ + /* 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_DAT_MASK) && @@ -504,18 +870,14 @@ int XSdPs_CmdTransfer(XSdPs *InstancePtr, u32 Cmd, u32 Arg, u32 BlkCnt) XSdPs_WriteReg16(InstancePtr->Config.BaseAddress, XSDPS_CMD_OFFSET, CommandReg); - /* - * Polling for response for now - */ + /* 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 - */ + /* Write to clear error bits */ XSdPs_WriteReg16(InstancePtr->Config.BaseAddress, XSDPS_ERR_INTR_STS_OFFSET, XSDPS_ERROR_INTR_ALL_MASK); @@ -523,16 +885,14 @@ int XSdPs_CmdTransfer(XSdPs *InstancePtr, u32 Cmd, u32 Arg, u32 BlkCnt) goto RETURN_PATH; } } while((StatusReg & XSDPS_INTR_CC_MASK) == 0); - /* - * Write to clear bit - */ + /* Write to clear bit */ XSdPs_WriteReg16(InstancePtr->Config.BaseAddress, XSDPS_NORM_INTR_STS_OFFSET, XSDPS_INTR_CC_MASK); Status = XST_SUCCESS; - RETURN_PATH: +RETURN_PATH: return Status; } @@ -551,7 +911,7 @@ int XSdPs_CmdTransfer(XSdPs *InstancePtr, u32 Cmd, u32 Arg, u32 BlkCnt) * data, CRC and index related flags. * ******************************************************************************/ -u32 XSdPs_FrameCmd(u32 Cmd) +u32 XSdPs_FrameCmd(XSdPs *InstancePtr, u32 Cmd) { u32 RetVal; @@ -576,37 +936,30 @@ u32 XSdPs_FrameCmd(u32 Cmd) case CMD5: RetVal |= RESP_R1B; break; - -#ifndef MMC_CARD case CMD6: - RetVal |= RESP_R1 | XSDPS_DAT_PRESENT_SEL_MASK; + if (InstancePtr->CardType == XSDPS_CARD_SD) { + RetVal |= RESP_R1 | XSDPS_DAT_PRESENT_SEL_MASK; + } else { + RetVal |= RESP_R1B; + } 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; + if (InstancePtr->CardType == XSDPS_CARD_SD) { + RetVal |= RESP_R1; + } else { + RetVal |= RESP_R1 | XSDPS_DAT_PRESENT_SEL_MASK; + } break; -#else - case CMD8: - RetVal |= RESP_R1 | XSDPS_DAT_PRESENT_SEL_MASK; - break; -#endif - case CMD9: RetVal |= RESP_R2; break; + case CMD11: case CMD10: case CMD12: case ACMD13: @@ -615,6 +968,8 @@ u32 XSdPs_FrameCmd(u32 Cmd) break; case CMD17: case CMD18: + case CMD19: + case CMD21: RetVal |= RESP_R1 | XSDPS_DAT_PRESENT_SEL_MASK; break; case CMD23: @@ -665,9 +1020,7 @@ int XSdPs_ReadPolled(XSdPs *InstancePtr, u32 Arg, u32 BlkCnt, u8 *Buff) u32 StatusReg; if(InstancePtr->Config.CardDetect) { - /* - * Check status to ensure card is initialized - */ + /* 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) { @@ -676,9 +1029,7 @@ int XSdPs_ReadPolled(XSdPs *InstancePtr, u32 Arg, u32 BlkCnt, u8 *Buff) } } - /* - * Set block size to 512 if not already set - */ + /* 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, @@ -699,25 +1050,19 @@ int XSdPs_ReadPolled(XSdPs *InstancePtr, u32 Arg, u32 BlkCnt, u8 *Buff) Xil_DCacheInvalidateRange(Buff, BlkCnt * XSDPS_BLK_SIZE_512_MASK); - /* - * Send block read command - */ + /* 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 - */ + /* 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 - */ + /* Write to clear error bits */ XSdPs_WriteReg16(InstancePtr->Config.BaseAddress, XSDPS_ERR_INTR_STS_OFFSET, XSDPS_ERROR_INTR_ALL_MASK); @@ -726,9 +1071,7 @@ int XSdPs_ReadPolled(XSdPs *InstancePtr, u32 Arg, u32 BlkCnt, u8 *Buff) } } while((StatusReg & XSDPS_INTR_TC_MASK) == 0); - /* - * Write to clear bit - */ + /* Write to clear bit */ XSdPs_WriteReg16(InstancePtr->Config.BaseAddress, XSDPS_NORM_INTR_STS_OFFSET, XSDPS_INTR_TC_MASK); Status = XSdPs_ReadReg(InstancePtr->Config.BaseAddress, @@ -736,7 +1079,7 @@ int XSdPs_ReadPolled(XSdPs *InstancePtr, u32 Arg, u32 BlkCnt, u8 *Buff) Status = XST_SUCCESS; - RETURN_PATH: +RETURN_PATH: return Status; } @@ -763,9 +1106,7 @@ int XSdPs_WritePolled(XSdPs *InstancePtr, u32 Arg, u32 BlkCnt, const u8 *Buff) u32 StatusReg; if(InstancePtr->Config.CardDetect) { - /* - * Check status to ensure card is initialized - */ + /* 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) { @@ -774,9 +1115,7 @@ int XSdPs_WritePolled(XSdPs *InstancePtr, u32 Arg, u32 BlkCnt, const u8 *Buff) } } - /* - * Set block size to 512 if not already set - */ + /* 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, @@ -797,9 +1136,7 @@ int XSdPs_WritePolled(XSdPs *InstancePtr, u32 Arg, u32 BlkCnt, const u8 *Buff) XSDPS_TM_BLK_CNT_EN_MASK | XSDPS_TM_MUL_SIN_BLK_SEL_MASK | XSDPS_TM_DMA_EN_MASK); - /* - * Send block write command - */ + /* Send block write command */ Status = XSdPs_CmdTransfer(InstancePtr, CMD25, Arg, BlkCnt); if (Status != XST_SUCCESS) { Status = XST_FAILURE; @@ -814,9 +1151,7 @@ int XSdPs_WritePolled(XSdPs *InstancePtr, u32 Arg, u32 BlkCnt, const u8 *Buff) StatusReg = XSdPs_ReadReg16(InstancePtr->Config.BaseAddress, XSDPS_NORM_INTR_STS_OFFSET); if (StatusReg & XSDPS_INTR_ERR_MASK) { - /* - * Write to clear error bits - */ + /* Write to clear error bits */ XSdPs_WriteReg16(InstancePtr->Config.BaseAddress, XSDPS_ERR_INTR_STS_OFFSET, XSDPS_ERROR_INTR_ALL_MASK); @@ -825,9 +1160,7 @@ int XSdPs_WritePolled(XSdPs *InstancePtr, u32 Arg, u32 BlkCnt, const u8 *Buff) } } while((StatusReg & XSDPS_INTR_TC_MASK) == 0); - /* - * Write to clear bit - */ + /* Write to clear bit */ XSdPs_WriteReg16(InstancePtr->Config.BaseAddress, XSDPS_NORM_INTR_STS_OFFSET, XSDPS_INTR_TC_MASK); @@ -856,9 +1189,7 @@ int XSdPs_Select_Card (XSdPs *InstancePtr) { u32 Status = 0; - /* - * Send CMD7 - Select card - */ + /* Send CMD7 - Select card */ Status = XSdPs_CmdTransfer(InstancePtr, CMD7, InstancePtr->RelCardAddr, 0); if (Status != XST_SUCCESS) { @@ -866,21 +1197,7 @@ int XSdPs_Select_Card (XSdPs *InstancePtr) 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_PATH: return Status; } @@ -906,9 +1223,7 @@ void XSdPs_SetupADMA2DescTbl(XSdPs *InstancePtr, u32 BlkCnt, const u8 *Buff) u32 DescNum = 0; u32 BlkSize = 0; - /* - * Setup ADMA2 - Write descriptor table and point ADMA SAR to it - */ + /* 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; @@ -927,18 +1242,16 @@ void XSdPs_SetupADMA2DescTbl(XSdPs *InstancePtr, u32 BlkCnt, const u8 *Buff) for (DescNum = 0; DescNum < (TotalDescLines-1); DescNum++) { InstancePtr->Adma2_DescrTbl[DescNum].Address = - (u32)(Buff + (DescNum*XSDPS_DESC_MAX_LENGTH)); + (u32)((UINTPTR)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 - */ + /* 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)); + (u32)((UINTPTR)Buff + (DescNum*XSDPS_DESC_MAX_LENGTH)); InstancePtr->Adma2_DescrTbl[TotalDescLines-1].Attribute = XSDPS_DESC_TRAN | XSDPS_DESC_END | XSDPS_DESC_VALID; @@ -948,7 +1261,7 @@ void XSdPs_SetupADMA2DescTbl(XSdPs *InstancePtr, u32 BlkCnt, const u8 *Buff) XSdPs_WriteReg(InstancePtr->Config.BaseAddress, XSDPS_ADMA_SAR_OFFSET, - (u32)&(InstancePtr->Adma2_DescrTbl[0])); + (u32)(UINTPTR)&(InstancePtr->Adma2_DescrTbl[0])); Xil_DCacheFlushRange(&(InstancePtr->Adma2_DescrTbl[0]), sizeof(XSdPs_Adma2Descriptor) * 32); @@ -1001,42 +1314,18 @@ int XSdPs_MmcCardInitialize(XSdPs *InstancePtr) } } - /* - * 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 - */ + /* CMD0 no response expected */ Status = XSdPs_CmdTransfer(InstancePtr, CMD0, 0, 0); if (Status != XST_SUCCESS) { Status = XST_FAILURE; goto RETURN_PATH; } - InstancePtr->CardType = CT_MMC; RespOCR = 0; - /* - * Send CMD1 while card is still busy with power up - */ + /* Send CMD1 while card is still busy with power up */ while ((RespOCR & XSDPS_RESPOCR_READY) == 0) { - /* - * Host High Capacity support & High volage window - */ + /* Host High Capacity support & High volage window */ Status = XSdPs_CmdTransfer(InstancePtr, CMD1, XSDPS_ACMD41_HCS | XSDPS_CMD1_HIGH_VOL, 0); if (Status != XST_SUCCESS) { @@ -1044,23 +1333,17 @@ int XSdPs_MmcCardInitialize(XSdPs *InstancePtr) goto RETURN_PATH; } - /* - * Response with card capacity - */ + /* Response with card capacity */ RespOCR = XSdPs_ReadReg(InstancePtr->Config.BaseAddress, XSDPS_RESP0_OFFSET); } - /* - * Update HCS support flag based on card capacity response - */ + /* Update HCS support flag based on card capacity response */ if (RespOCR & XSDPS_ACMD41_HCS) InstancePtr->HCS = 1; - /* - * CMD2 for Card ID - */ + /* CMD2 for Card ID */ Status = XSdPs_CmdTransfer(InstancePtr, CMD2, 0, 0); if (Status != XST_SUCCESS) { Status = XST_FAILURE; @@ -1080,20 +1363,14 @@ int XSdPs_MmcCardInitialize(XSdPs *InstancePtr) XSdPs_ReadReg16(InstancePtr->Config.BaseAddress, XSDPS_RESP3_OFFSET); - Status = XSdPs_CmdTransfer(InstancePtr, CMD3, 0, 0); + /* Set relative card address */ + InstancePtr->RelCardAddr = 0x12340000; + Status = XSdPs_CmdTransfer(InstancePtr, CMD3, (InstancePtr->RelCardAddr), 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; diff --git a/XilinxProcessorIPLib/drivers/sdps/src/xsdps.h b/XilinxProcessorIPLib/drivers/sdps/src/xsdps.h index 51edffea..fd3bc653 100644 --- a/XilinxProcessorIPLib/drivers/sdps/src/xsdps.h +++ b/XilinxProcessorIPLib/drivers/sdps/src/xsdps.h @@ -33,7 +33,7 @@ /** * * @file xsdps.h -* @addtogroup sdps_v2_4 +* @addtogroup sdps_v2_5 * @{ * @details * @@ -116,6 +116,7 @@ * Checked for DAT Inhibit mask instead of CMD * Inhibit mask in Cmd Transfer API. * Added Support for SD Card v1.0 +* 2.5 sg 07/09/15 Added SD 3.0 features * * * @@ -135,11 +136,6 @@ extern "C" { /************************** Constant Definitions *****************************/ -#define XSDPS_CLK_400_KHZ 400000 /**< 400 KHZ */ -#define XSDPS_CLK_50_MHZ 50000000 /**< 50 MHZ */ -#define CT_MMC 0x1 /**< MMC Card */ -#define CT_SD1 0x2 /**< SD ver 1 */ -#define CT_SD2 0x3 /**< SD ver 2 */ /**************************** Type Definitions *******************************/ /** * This typedef contains configuration information for the device. @@ -152,9 +148,7 @@ typedef struct { u32 WriteProtect; /**< Write Protect */ } XSdPs_Config; -/* - * ADMA2 descriptor table - */ +/* ADMA2 descriptor table */ typedef struct { u16 Attribute; /**< Attributes of descriptor */ u16 Length; /**< Length of current dma transfer */ @@ -170,10 +164,18 @@ typedef struct { XSdPs_Config Config; /**< Configuration structure */ u32 IsReady; /**< Device is initialized and ready */ u32 Host_Caps; /**< Capabilities of host controller */ + u32 Host_CapsExt; /**< Extended Capabilities */ u32 HCS; /**< High capacity support in card */ - u32 CardID[4]; /**< Card ID */ + u8 CardType; /**< Type of card - SD/MMC/eMMC */ + u8 Card_Version; /**< Card version */ + u8 HC_Version; /**< Host controller version */ + u8 BusWidth; /**< Current operating bus width */ + u32 BusSpeed; /**< Current operating bus speed */ + u8 Switch1v8; /**< 1.8V Switch support */ + u32 CardID[4]; /**< Card ID Register */ u32 RelCardAddr; /**< Relative Card Address */ - u32 CardType; /**< Card Type(version) */ + u32 CardSpecData[4]; /**< Card Specific Data Register */ + u32 SdCardConfig; /**< Sd Card Configuration Register */ /**< ADMA Descriptors */ #ifdef __ICCARM__ #pragma data_alignment = 32 @@ -202,6 +204,7 @@ int XSdPs_Get_BusWidth(XSdPs *InstancePtr, u8 *SCR); int XSdPs_Get_BusSpeed(XSdPs *InstancePtr, u8 *ReadBuff); int XSdPs_Pullup(XSdPs *InstancePtr); int XSdPs_MmcCardInitialize(XSdPs *InstancePtr); +int XSdPs_CardInitialize(XSdPs *InstancePtr); int XSdPs_Get_Mmc_ExtCsd(XSdPs *InstancePtr, u8 *ReadBuff); #ifdef __cplusplus diff --git a/XilinxProcessorIPLib/drivers/sdps/src/xsdps_g.c b/XilinxProcessorIPLib/drivers/sdps/src/xsdps_g.c index 379ee36e..ed50c696 100644 --- a/XilinxProcessorIPLib/drivers/sdps/src/xsdps_g.c +++ b/XilinxProcessorIPLib/drivers/sdps/src/xsdps_g.c @@ -33,7 +33,7 @@ /** * * @file xsdps_g.c -* @addtogroup sdps_v2_4 +* @addtogroup sdps_v2_5 * @{ * @details * diff --git a/XilinxProcessorIPLib/drivers/sdps/src/xsdps_hw.h b/XilinxProcessorIPLib/drivers/sdps/src/xsdps_hw.h index c974a3c0..6d001299 100644 --- a/XilinxProcessorIPLib/drivers/sdps/src/xsdps_hw.h +++ b/XilinxProcessorIPLib/drivers/sdps/src/xsdps_hw.h @@ -33,7 +33,7 @@ /** * * @file xsdps_hw.h -* @addtogroup sdps_v2_4 +* @addtogroup sdps_v2_5 * @{ * @details * @@ -47,7 +47,7 @@ * Ver Who Date Changes * ----- --- -------- ----------------------------------------------- * 1.00a hk/sg 10/17/13 Initial release -* +* 2.5 sg 07/09/15 Added SD 3.0 features * * ******************************************************************************/ @@ -76,9 +76,21 @@ extern "C" { #define XSDPS_SDMA_SYS_ADDR_OFFSET 0x00 /**< SDMA System Address Register */ +#define XSDPS_SDMA_SYS_ADDR_LO_OFFSET XSDPS_SDMA_SYS_ADDR_OFFSET + /**< SDMA System Address + Low Register */ +#define XSDPS_ARGMT2_LO_OFFSET 0x00 /**< Argument2 Low Register */ +#define XSDPS_SDMA_SYS_ADDR_HI_OFFSET 0x02 /**< SDMA System Address + High Register */ +#define XSDPS_ARGMT2_HI_OFFSET 0x02 /**< Argument2 High Register */ + #define XSDPS_BLK_SIZE_OFFSET 0x04 /**< Block Size Register */ #define XSDPS_BLK_CNT_OFFSET 0x06 /**< Block Count Register */ #define XSDPS_ARGMT_OFFSET 0x08 /**< Argument Register */ +#define XSDPS_ARGMT1_LO_OFFSET XSDPS_ARGMT_OFFSET + /**< Argument1 Register */ +#define XSDPS_ARGMT1_HI_OFFSET 0x0A /**< Argument1 Register */ + #define XSDPS_XFER_MODE_OFFSET 0x0C /**< Transfer Mode Register */ #define XSDPS_CMD_OFFSET 0x0E /**< Command Register */ #define XSDPS_RESP0_OFFSET 0x10 /**< Response0 Register */ @@ -130,6 +142,9 @@ extern "C" { #define XSDPS_PRE_VAL_2_OFFSET 0x64 /**< Preset Value Register */ #define XSDPS_PRE_VAL_3_OFFSET 0x68 /**< Preset Value Register */ #define XSDPS_PRE_VAL_4_OFFSET 0x6C /**< Preset Value Register */ +#define XSDPS_BOOT_TOUT_CTRL_OFFSET 0x70 /**< Boot timeout control + register */ + #define XSDPS_SHARED_BUS_CTRL_OFFSET 0xE0 /**< Shared Bus Control Register */ #define XSDPS_SLOT_INTR_STS_OFFSET 0xFC /**< Slot Interrupt Status @@ -149,6 +164,7 @@ extern "C" { #define XSDPS_HC_LED_MASK 0x00000001 /**< LED Control */ #define XSDPS_HC_WIDTH_MASK 0x00000002 /**< Bus width */ +#define XSDPS_HC_BUS_WIDTH_4 0x00000002 #define XSDPS_HC_SPEED_MASK 0x00000004 /**< High Speed */ #define XSDPS_HC_DMA_MASK 0x00000018 /**< DMA Mode Select */ #define XSDPS_HC_DMA_SDMA_MASK 0x00000000 /**< SDMA Mode */ @@ -164,6 +180,7 @@ extern "C" { #define XSDPS_PC_BUS_VSEL_3V3_MASK 0x0000000E /**< Bus Voltage 3.3V */ #define XSDPS_PC_BUS_VSEL_3V0_MASK 0x0000000C /**< Bus Voltage 3.0V */ #define XSDPS_PC_BUS_VSEL_1V8_MASK 0x0000000A /**< Bus Voltage 1.8V */ +#define XSDPS_PC_EMMC_HW_RST_MASK 0x00000010 /**< HW reset for eMMC */ #define XSDPS_BGC_STP_REQ_MASK 0x00000001 /**< Block Gap Stop Req */ #define XSDPS_BGC_CNT_REQ_MASK 0x00000002 /**< Block Gap Cont Req */ @@ -203,6 +220,9 @@ extern "C" { #define XSDPS_CC_SDCLK_FREQ_D4_MASK 0x00000200 #define XSDPS_CC_SDCLK_FREQ_D2_MASK 0x00000100 #define XSDPS_CC_SDCLK_FREQ_BASE_MASK 0x00000000 +#define XSDPS_CC_MAX_DIV_CNT 256 +#define XSDPS_CC_EXT_MAX_DIV_CNT 2046 +#define XSDPS_CC_EXT_DIV_SHIFT 6 #define XSDPS_TC_CNTR_VAL_MASK 0x0000000F @@ -251,9 +271,9 @@ extern "C" { #define XSDPS_INTR_INT_B_MASK 0x00000400 /**< INT B Interrupt */ #define XSDPS_INTR_INT_C_MASK 0x00000800 /**< INT C Interrupt */ #define XSDPS_INTR_RE_TUNING_MASK 0x00001000 /**< Re-Tuning Interrupt */ -#define XSDPS_INTR_BOOT_TERM_MASK 0x00002000 /**< Boot Terminate +#define XSDPS_INTR_BOOT_ACK_RECV_MASK 0x00002000 /**< Boot Ack Recv Interrupt */ -#define XSDPS_INTR_BOOT_ACK_RECV_MASK 0x00004000 /**< Boot Ack Recv +#define XSDPS_INTR_BOOT_TERM_MASK 0x00004000 /**< Boot Terminate Interrupt */ #define XSDPS_INTR_ERR_MASK 0x00008000 /**< Error Interrupt */ #define XSDPS_NORM_INTR_ALL_MASK 0x0000FFFF @@ -267,7 +287,7 @@ extern "C" { #define XSDPS_INTR_ERR_DT_MASK 0x00000010 /**< Data Timeout Error */ #define XSDPS_INTR_ERR_DCRC_MASK 0x00000020 /**< Data CRC Error */ #define XSDPS_INTR_ERR_DEB_MASK 0x00000040 /**< Data End Bit Error */ -#define XSDPS_INTR_ERR_I_LMT_MASK 0x00000080 /**< Current Limit Error */ +#define XSDPS_INTR_ERR_CUR_LMT_MASK 0x00000080 /**< Current Limit Error */ #define XSDPS_INTR_ERR_AUTO_CMD12_MASK 0x00000100 /**< Auto CMD12 Error */ #define XSDPS_INTR_ERR_ADMA_MASK 0x00000200 /**< ADMA Error */ #define XSDPS_INTR_ERR_TR_MASK 0x00001000 /**< Tuning Error */ @@ -286,6 +306,8 @@ extern "C" { #define XSDPS_BLK_SIZE_MASK 0x00000FFF /**< Transfer Block Size */ #define XSDPS_SDMA_BUFF_SIZE_MASK 0x00007000 /**< Host SDMA Buffer Size */ +#define XSDPS_BLK_SIZE_1024 0x400 +#define XSDPS_BLK_SIZE_2048 0x800 #define XSDPS_BLK_CNT_MASK 0x0000FFFF /**< Block Count for Current Transfer */ @@ -331,6 +353,53 @@ extern "C" { /* @} */ +/** @name Auto CMD Error Status Register + * + * This register is read only register which contains + * information about the error status of Auto CMD 12 and 23. + * Read Only + * @{ + */ +#define XSDPS_AUTO_CMD12_NT_EX_MASK 0x0001 /**< Auto CMD12 Not + executed */ +#define XSDPS_AUTO_CMD_TOUT_MASK 0x0002 /**< Auto CMD Timeout + Error */ +#define XSDPS_AUTO_CMD_CRC_MASK 0x0004 /**< Auto CMD CRC Error */ +#define XSDPS_AUTO_CMD_EB_MASK 0x0008 /**< Auto CMD End Bit + Error */ +#define XSDPS_AUTO_CMD_IND_MASK 0x0010 /**< Auto CMD Index Error */ +#define XSDPS_AUTO_CMD_CNI_ERR_MASK 0x0080 /**< Command not issued by + Auto CMD12 Error */ +/* @} */ + +/** @name Host Control2 Register + * + * This register contains extended configuration bits. + * Read Write + * @{ + */ +#define XSDPS_HC2_UHS_MODE_MASK 0x0007 /**< UHS Mode select bits */ +#define XSDPS_HC2_UHS_MODE_SDR12_MASK 0x0000 /**< SDR12 UHS Mode */ +#define XSDPS_HC2_UHS_MODE_SDR25_MASK 0x0001 /**< SDR25 UHS Mode */ +#define XSDPS_HC2_UHS_MODE_SDR50_MASK 0x0002 /**< SDR50 UHS Mode */ +#define XSDPS_HC2_UHS_MODE_SDR104_MASK 0x0003 /**< SDR104 UHS Mode */ +#define XSDPS_HC2_UHS_MODE_DDR50_MASK 0x0004 /**< DDR50 UHS Mode */ +#define XSDPS_HC2_1V8_EN_MASK 0x0008 /**< 1.8V Signal Enable */ +#define XSDPS_HC2_DRV_STR_SEL_MASK 0x0030 /**< Driver Strength + Selection */ +#define XSDPS_HC2_DRV_STR_B_MASK 0x0000 /**< Driver Strength B */ +#define XSDPS_HC2_DRV_STR_A_MASK 0x0010 /**< Driver Strength A */ +#define XSDPS_HC2_DRV_STR_C_MASK 0x0020 /**< Driver Strength C */ +#define XSDPS_HC2_DRV_STR_D_MASK 0x0030 /**< Driver Strength D */ +#define XSDPS_HC2_EXEC_TNG_MASK 0x0040 /**< Execute Tuning */ +#define XSDPS_HC2_SAMP_CLK_SEL_MASK 0x0080 /**< Sampling Clock + Selection */ +#define XSDPS_HC2_ASYNC_INTR_EN_MASK 0x4000 /**< Asynchronous Interrupt + Enable */ +#define XSDPS_HC2_PRE_VAL_EN_MASK 0x8000 /**< Preset Value Enable */ + +/* @} */ + /** @name Capabilities Register * * Capabilities register is a read only register which contains @@ -345,6 +414,10 @@ extern "C" { MHz/KHz */ #define XSDPS_CAP_MAX_BLK_LEN_MASK 0x00030000 /**< Max block length */ #define XSDPS_CAP_MAX_BLK_LEN_512B_MASK 0x00000000 /**< Max block 512 bytes */ +#define XSDPS_CAP_MAX_BL_LN_1024_MASK 0x00010000 /**< Max block 1024 bytes */ +#define XSDPS_CAP_MAX_BL_LN_2048_MASK 0x00020000 /**< Max block 2048 bytes */ +#define XSDPS_CAP_MAX_BL_LN_4096_MASK 0x00030000 /**< Max block 4096 bytes */ + #define XSDPS_CAP_EXT_MEDIA_BUS_MASK 0x00040000 /**< Extended media bus */ #define XSDPS_CAP_ADMA2_MASK 0x00080000 /**< ADMA2 support */ #define XSDPS_CAP_HIGH_SPEED_MASK 0x00200000 /**< High speed support */ @@ -354,12 +427,45 @@ extern "C" { #define XSDPS_CAP_VOLT_3V3_MASK 0x01000000 /**< 3.3V support */ #define XSDPS_CAP_VOLT_3V0_MASK 0x02000000 /**< 3.0V support */ #define XSDPS_CAP_VOLT_1V8_MASK 0x04000000 /**< 1.8V support */ -#define XSDPS_CAP_INTR_MODE_MASK 0x08000000 /**< Interrupt mode - support */ + #define XSDPS_CAP_SYS_BUS_64_MASK 0x10000000 /**< 64 bit system bus support */ +/* Spec 2.0 */ +#define XSDPS_CAP_INTR_MODE_MASK 0x08000000 /**< Interrupt mode + support */ #define XSDPS_CAP_SPI_MODE_MASK 0x20000000 /**< SPI mode */ -#define XSDPS_CAP_SPI_BLOCK_MODE_MASK 0x20000000 /**< SPI block mode */ +#define XSDPS_CAP_SPI_BLOCK_MODE_MASK 0x40000000 /**< SPI block mode */ + + +/* Spec 3.0 */ +#define XSDPS_CAPS_ASYNC_INTR_MASK 0x20000000 /**< Async Interrupt + support */ +#define XSDPS_CAPS_SLOT_TYPE_MASK 0xC0000000 /**< Slot Type */ +#define XSDPS_CAPS_REM_CARD 0x00000000 /**< Removable Slot */ +#define XSDPS_CAPS_EMB_SLOT 0x40000000 /**< Embedded Slot */ +#define XSDPS_CAPS_SHR_BUS 0x80000000 /**< Shared Bus Slot */ + +#define XSDPS_ECAPS_SDR50_MASK 0x00000001 /**< SDR50 Mode support */ +#define XSDPS_ECAPS_SDR104_MASK 0x00000002 /**< SDR104 Mode support */ +#define XSDPS_ECAPS_DDR50_MASK 0x00000004 /**< DDR50 Mode support */ +#define XSDPS_ECAPS_DRV_TYPE_A_MASK 0x00000010 /**< DriverType A support */ +#define XSDPS_ECAPS_DRV_TYPE_C_MASK 0x00000020 /**< DriverType C support */ +#define XSDPS_ECAPS_DRV_TYPE_D_MASK 0x00000040 /**< DriverType D support */ +#define XSDPS_ECAPS_TMR_CNT_MASK 0x00000F00 /**< Timer Count for + Re-tuning */ +#define XSDPS_ECAPS_USE_TNG_SDR50_MASK 0x00002000 /**< SDR50 Mode needs + tuning */ +#define XSDPS_ECAPS_RE_TNG_MODES_MASK 0x0000C000 /**< Re-tuning modes + support */ +#define XSDPS_ECAPS_RE_TNG_MODE1_MASK 0x00000000 /**< Re-tuning mode 1 */ +#define XSDPS_ECAPS_RE_TNG_MODE2_MASK 0x00004000 /**< Re-tuning mode 2 */ +#define XSDPS_ECAPS_RE_TNG_MODE3_MASK 0x00008000 /**< Re-tuning mode 3 */ +#define XSDPS_ECAPS_CLK_MULT_MASK 0x00FF0000 /**< Clock Multiplier value + for Programmable clock + mode */ +#define XSDPS_ECAPS_SPI_MODE_MASK 0x01000000 /**< SPI mode */ +#define XSDPS_ECAPS_SPI_BLK_MODE_MASK 0x02000000 /**< SPI block mode */ + /* @} */ /** @name Present State Register @@ -372,6 +478,7 @@ extern "C" { #define XSDPS_PSR_INHIBIT_CMD_MASK 0x00000001 /**< Command inhibit - CMD */ #define XSDPS_PSR_INHIBIT_DAT_MASK 0x00000002 /**< Command Inhibit - DAT */ #define XSDPS_PSR_DAT_ACTIVE_MASK 0x00000004 /**< DAT line active */ +#define XSDPS_PSR_RE_TUNING_REQ_MASK 0x00000008 /**< Re-tuning request */ #define XSDPS_PSR_WR_ACTIVE_MASK 0x00000100 /**< Write transfer active */ #define XSDPS_PSR_RD_ACTIVE_MASK 0x00000200 /**< Read transfer active */ #define XSDPS_PSR_BUFF_WR_EN_MASK 0x00000400 /**< Buffer write enable */ @@ -381,9 +488,137 @@ extern "C" { #define XSDPS_PSR_CARD_DPL_MASK 0x00040000 /**< Card detect pin level */ #define XSDPS_PSR_WPS_PL_MASK 0x00080000 /**< Write protect switch pin level */ +#define XSDPS_PSR_DAT30_SG_LVL_MASK 0x00F00000 /**< Data 3:0 signal lvl */ +#define XSDPS_PSR_CMD_SG_LVL_MASK 0x01000000 /**< Cmd Line signal lvl */ +#define XSDPS_PSR_DAT74_SG_LVL_MASK 0x1E000000 /**< Data 7:4 signal lvl */ /* @} */ +/** @name Maximum Current Capablities Register + * + * This register is read only register which contains + * information about current capabilities at each voltage levels. + * Read Only + * @{ + */ +#define XSDPS_MAX_CUR_CAPS_1V8_MASK 0x00000F00 /**< Maximum Current + Capability at 1.8V */ +#define XSDPS_MAX_CUR_CAPS_3V0_MASK 0x000000F0 /**< Maximum Current + Capability at 3.0V */ +#define XSDPS_MAX_CUR_CAPS_3V3_MASK 0x0000000F /**< Maximum Current + Capability at 3.3V */ +/* @} */ + + +/** @name Force Event for Auto CMD Error Status Register + * + * This register is write only register which contains + * control bits to generate events for Auto CMD error status. + * Write Only + * @{ + */ +#define XSDPS_FE_AUTO_CMD12_NT_EX_MASK 0x0001 /**< Auto CMD12 Not + executed */ +#define XSDPS_FE_AUTO_CMD_TOUT_MASK 0x0002 /**< Auto CMD Timeout + Error */ +#define XSDPS_FE_AUTO_CMD_CRC_MASK 0x0004 /**< Auto CMD CRC Error */ +#define XSDPS_FE_AUTO_CMD_EB_MASK 0x0008 /**< Auto CMD End Bit + Error */ +#define XSDPS_FE_AUTO_CMD_IND_MASK 0x0010 /**< Auto CMD Index Error */ +#define XSDPS_FE_AUTO_CMD_CNI_ERR_MASK 0x0080 /**< Command not issued by + Auto CMD12 Error */ +/* @} */ + + + +/** @name Force Event for Error Interrupt Status Register + * + * This register is write only register which contains + * control bits to generate events of error interrupt status register. + * Write Only + * @{ + */ +#define XSDPS_FE_INTR_ERR_CT_MASK 0x0001 /**< Command Timeout + Error */ +#define XSDPS_FE_INTR_ERR_CCRC_MASK 0x0002 /**< Command CRC Error */ +#define XSDPS_FE_INTR_ERR_CEB_MASK 0x0004 /**< Command End Bit + Error */ +#define XSDPS_FE_INTR_ERR_CI_MASK 0x0008 /**< Command Index Error */ +#define XSDPS_FE_INTR_ERR_DT_MASK 0x0010 /**< Data Timeout Error */ +#define XSDPS_FE_INTR_ERR_DCRC_MASK 0x0020 /**< Data CRC Error */ +#define XSDPS_FE_INTR_ERR_DEB_MASK 0x0040 /**< Data End Bit Error */ +#define XSDPS_FE_INTR_ERR_CUR_LMT_MASK 0x0080 /**< Current Limit Error */ +#define XSDPS_FE_INTR_ERR_AUTO_CMD_MASK 0x0100 /**< Auto CMD Error */ +#define XSDPS_FE_INTR_ERR_ADMA_MASK 0x0200 /**< ADMA Error */ +#define XSDPS_FE_INTR_ERR_TR_MASK 0x1000 /**< Target Reponse */ +#define XSDPS_FE_INTR_VEND_SPF_ERR_MASK 0xE000 /**< Vendor Specific + Error */ + +/* @} */ + +/** @name ADMA Error Status Register + * + * This register is read only register which contains + * status information about ADMA errors. + * Read Only + * @{ + */ +#define XSDPS_ADMA_ERR_MM_LEN_MASK 0x04 /**< ADMA Length Mismatch + Error */ +#define XSDPS_ADMA_ERR_STATE_MASK 0x03 /**< ADMA Error State */ +#define XSDPS_ADMA_ERR_STATE_STOP_MASK 0x00 /**< ADMA Error State + STOP */ +#define XSDPS_ADMA_ERR_STATE_FDS_MASK 0x01 /**< ADMA Error State + FDS */ +#define XSDPS_ADMA_ERR_STATE_TFR_MASK 0x03 /**< ADMA Error State + TFR */ +/* @} */ + +/** @name Preset Values Register + * + * This register is read only register which contains + * preset values for each of speed modes. + * Read Only + * @{ + */ +#define XSDPS_PRE_VAL_SDCLK_FSEL_MASK 0x03FF /**< SDCLK Frequency + Select Value */ +#define XSDPS_PRE_VAL_CLK_GEN_SEL_MASK 0x0400 /**< Clock Generator + Mode Select */ +#define XSDPS_PRE_VAL_DRV_STR_SEL_MASK 0xC000 /**< Driver Strength + Select Value */ + +/* @} */ + +/** @name Slot Interrupt Status Register + * + * This register is read only register which contains + * interrupt slot signal for each slot. + * Read Only + * @{ + */ +#define XSDPS_SLOT_INTR_STS_INT_MASK 0x0007 /**< Interrupt Signal + mask */ + +/* @} */ + +/** @name Host Controller Version Register + * + * This register is read only register which contains + * Host Controller and Vendor Specific version. + * Read Only + * @{ + */ +#define XSDPS_HC_VENDOR_VER 0xFF00 /**< Vendor + Specification + version mask */ +#define XSDPS_HC_SPEC_VER_MASK 0x00FF /**< Host + Specification + version mask */ +#define XSDPS_HC_SPEC_V3 0x0002 +#define XSDPS_HC_SPEC_V2 0x0001 +#define XSDPS_HC_SPEC_V1 0x0000 + /** @name Block size mask for 512 bytes * * Block size mask for 512 bytes - This is the default block size. @@ -413,11 +648,14 @@ extern "C" { #define CMD8 0x0800 #define CMD9 0x0900 #define CMD10 0x0A00 +#define CMD11 0x0B00 #define CMD12 0x0C00 #define ACMD13 (XSDPS_APP_CMD_PREFIX + 0x0D00) #define CMD16 0x1000 #define CMD17 0x1100 #define CMD18 0x1200 +#define CMD19 0x1300 +#define CMD21 0x1500 #define CMD23 0x1700 #define ACMD23 (XSDPS_APP_CMD_PREFIX + 0x1700) #define CMD24 0x1800 @@ -445,13 +683,226 @@ extern "C" { /* @} */ +/* Card Interface Conditions Definitions */ +#define XSDPS_CIC_CHK_PATTERN 0xAA +#define XSDPS_CIC_VOLT_MASK (0xF<<8) +#define XSDPS_CIC_VOLT_2V7_3V6 (1<<8) +#define XSDPS_CIC_VOLT_LOW (1<<9) + +/* Operation Conditions Register Definitions */ +#define XSDPS_OCR_PWRUP_STS (1<<31) +#define XSDPS_OCR_CC_STS (1<<30) +#define XSDPS_OCR_S18 (1<<24) +#define XSDPS_OCR_3V5_3V6 (1<<23) +#define XSDPS_OCR_3V4_3V5 (1<<22) +#define XSDPS_OCR_3V3_3V4 (1<<21) +#define XSDPS_OCR_3V2_3V3 (1<<20) +#define XSDPS_OCR_3V1_3V2 (1<<19) +#define XSDPS_OCR_3V0_3V1 (1<<18) +#define XSDPS_OCR_2V9_3V0 (1<<17) +#define XSDPS_OCR_2V8_2V9 (1<<16) +#define XSDPS_OCR_2V7_2V8 (1<<15) +#define XSDPS_OCR_1V7_1V95 (1<<7) +#define XSDPS_OCR_HIGH_VOL 0x00FF8000 +#define XSDPS_OCR_LOW_VOL 0x00000080 + +/* SD Card Configuration Register Definitions */ +#define XSDPS_SCR_REG_LEN 8 +#define XSDPS_SCR_STRUCT_MASK (0xF<<28) +#define XSDPS_SCR_SPEC_MASK (0xF<<24) +#define XSDPS_SCR_SPEC_1V0 0 +#define XSDPS_SCR_SPEC_1V1 (1<<24) +#define XSDPS_SCR_SPEC_2V0_3V0 (2<<24) +#define XSDPS_SCR_MEM_VAL_AF_ERASE (1<<23) +#define XSDPS_SCR_SEC_SUPP_MASK (7<<20) +#define XSDPS_SCR_SEC_SUPP_NONE 0 +#define XSDPS_SCR_SEC_SUPP_1V1 (2<<20) +#define XSDPS_SCR_SEC_SUPP_2V0 (3<<20) +#define XSDPS_SCR_SEC_SUPP_3V0 (4<<20) +#define XSDPS_SCR_BUS_WIDTH_MASK (0xF<<16) +#define XSDPS_SCR_BUS_WIDTH_1 (1<<16) +#define XSDPS_SCR_BUS_WIDTH_4 (4<<16) +#define XSDPS_SCR_SPEC3_MASK (1<<12) +#define XSDPS_SCR_SPEC3_2V0 0 +#define XSDPS_SCR_SPEC3_3V0 (1<<12) +#define XSDPS_SCR_CMD_SUPP_MASK 0x3 +#define XSDPS_SCR_CMD23_SUPP (1<<1) +#define XSDPS_SCR_CMD20_SUPP (1<<0) + +/* Card Status Register Definitions */ +#define XSDPS_CD_STS_OUT_OF_RANGE (1<<31) +#define XSDPS_CD_STS_ADDR_ERR (1<<30) +#define XSDPS_CD_STS_BLK_LEN_ERR (1<<29) +#define XSDPS_CD_STS_ER_SEQ_ERR (1<<28) +#define XSDPS_CD_STS_ER_PRM_ERR (1<<27) +#define XSDPS_CD_STS_WP_VIO (1<<26) +#define XSDPS_CD_STS_IS_LOCKED (1<<25) +#define XSDPS_CD_STS_LOCK_UNLOCK_FAIL (1<<24) +#define XSDPS_CD_STS_CMD_CRC_ERR (1<<23) +#define XSDPS_CD_STS_ILGL_CMD (1<<22) +#define XSDPS_CD_STS_CARD_ECC_FAIL (1<<21) +#define XSDPS_CD_STS_CC_ERR (1<<20) +#define XSDPS_CD_STS_ERR (1<<19) +#define XSDPS_CD_STS_CSD_OVRWR (1<<16) +#define XSDPS_CD_STS_WP_ER_SKIP (1<<15) +#define XSDPS_CD_STS_CARD_ECC_DIS (1<<14) +#define XSDPS_CD_STS_ER_RST (1<<13) +#define XSDPS_CD_STS_CUR_STATE (0xF<<9) +#define XSDPS_CD_STS_RDY_FOR_DATA (1<<8) +#define XSDPS_CD_STS_APP_CMD (1<<5) +#define XSDPS_CD_STS_AKE_SEQ_ERR (1<<2) + +/* Switch Function Definitions CMD6 */ +#define XSDPS_SWITCH_SD_RESP_LEN 64 + +#define XSDPS_SWITCH_FUNC_SWITCH (1<<31) +#define XSDPS_SWITCH_FUNC_CHECK 0 + +#define XSDPS_MODE_FUNC_GRP1 1 +#define XSDPS_MODE_FUNC_GRP2 2 +#define XSDPS_MODE_FUNC_GRP3 3 +#define XSDPS_MODE_FUNC_GRP4 4 +#define XSDPS_MODE_FUNC_GRP5 5 +#define XSDPS_MODE_FUNC_GRP6 6 + +#define XSDPS_FUNC_GRP_DEF_VAL 0xF +#define XSDPS_FUNC_ALL_GRP_DEF_VAL 0xFFFFFF + +#define XSDPS_ACC_MODE_DEF_SDR12 0 +#define XSDPS_ACC_MODE_HS_SDR25 1 +#define XSDPS_ACC_MODE_SDR50 2 +#define XSDPS_ACC_MODE_SDR104 3 +#define XSDPS_ACC_MODE_DDR50 4 + +#define XSDPS_CMD_SYS_ARG_SHIFT 4 +#define XSDPS_CMD_SYS_DEF 0 +#define XSDPS_CMD_SYS_eC 1 +#define XSDPS_CMD_SYS_OTP 3 +#define XSDPS_CMD_SYS_ASSD 4 +#define XSDPS_CMD_SYS_VEND 5 + +#define XSDPS_DRV_TYPE_ARG_SHIFT 8 +#define XSDPS_DRV_TYPE_B 0 +#define XSDPS_DRV_TYPE_A 1 +#define XSDPS_DRV_TYPE_C 2 +#define XSDPS_DRV_TYPE_D 3 + +#define XSDPS_CUR_LIM_ARG_SHIFT 12 +#define XSDPS_CUR_LIM_200 0 +#define XSDPS_CUR_LIM_400 1 +#define XSDPS_CUR_LIM_600 2 +#define XSDPS_CUR_LIM_800 3 + + +/* EXT_CSD field definitions */ +#define XSDPS_EXT_CSD_SIZE 512 + +#define EXT_CSD_WR_REL_PARAM_EN (1<<2) + +#define EXT_CSD_BOOT_WP_B_PWR_WP_DIS (0x40) +#define EXT_CSD_BOOT_WP_B_PERM_WP_DIS (0x10) +#define EXT_CSD_BOOT_WP_B_PERM_WP_EN (0x04) +#define EXT_CSD_BOOT_WP_B_PWR_WP_EN (0x01) + +#define EXT_CSD_PART_CONFIG_ACC_MASK (0x7) +#define EXT_CSD_PART_CONFIG_ACC_BOOT0 (0x1) +#define EXT_CSD_PART_CONFIG_ACC_RPMB (0x3) +#define EXT_CSD_PART_CONFIG_ACC_GP0 (0x4) + +#define EXT_CSD_PART_SUPPORT_PART_EN (0x1) + +#define EXT_CSD_CMD_SET_NORMAL (1<<0) +#define EXT_CSD_CMD_SET_SECURE (1<<1) +#define EXT_CSD_CMD_SET_CPSECURE (1<<2) + +#define EXT_CSD_CARD_TYPE_26 (1<<0) /* Card can run at 26MHz */ +#define EXT_CSD_CARD_TYPE_52 (1<<1) /* Card can run at 52MHz */ +#define EXT_CSD_CARD_TYPE_MASK 0x3F /* Mask out reserved bits */ +#define EXT_CSD_CARD_TYPE_DDR_1_8V (1<<2) /* Card can run at 52MHz */ + /* DDR mode @1.8V or 3V I/O */ +#define EXT_CSD_CARD_TYPE_DDR_1_2V (1<<3) /* Card can run at 52MHz */ + /* DDR mode @1.2V I/O */ +#define EXT_CSD_CARD_TYPE_DDR_52 (EXT_CSD_CARD_TYPE_DDR_1_8V \ + | EXT_CSD_CARD_TYPE_DDR_1_2V) +#define EXT_CSD_CARD_TYPE_SDR_1_8V (1<<4) /* Card can run at 200MHz */ +#define EXT_CSD_CARD_TYPE_SDR_1_2V (1<<5) /* Card can run at 200MHz */ + /* SDR mode @1.2V I/O */ +#define EXT_CSD_BUS_WIDTH_BYTE 183 +#define EXT_CSD_BUS_WIDTH_1_BIT 0 /* Card is in 1 bit mode */ +#define EXT_CSD_BUS_WIDTH_4_BIT 1 /* Card is in 4 bit mode */ +#define EXT_CSD_BUS_WIDTH_8_BIT 2 /* Card is in 8 bit mode */ +#define EXT_CSD_BUS_WIDTH_DDR_4_BIT 5 /* Card is in 4 bit DDR mode */ +#define EXT_CSD_BUS_WIDTH_DDR_8_BIT 6 /* Card is in 8 bit DDR mode */ + +#define EXT_CSD_HS_TIMING_BYTE 185 +#define EXT_CSD_HS_TIMING_DEF 0 +#define EXT_CSD_HS_TIMING_HIGH 1 /* Card is in high speed mode */ +#define EXT_CSD_HS_TIMING_HS200 2 /* Card is in HS200 mode */ + + +#define XSDPS_EXT_CSD_CMD_SET 0 +#define XSDPS_EXT_CSD_SET_BITS 1 +#define XSDPS_EXT_CSD_CLR_BITS 2 +#define XSDPS_EXT_CSD_WRITE_BYTE 3 + +#define XSDPS_MMC_DEF_SPEED_ARG ((XSDPS_EXT_CSD_WRITE_BYTE << 24) \ + | (EXT_CSD_HS_TIMING_BYTE << 16) \ + | (EXT_CSD_HS_TIMING_DEF << 8)) + +#define XSDPS_MMC_HIGH_SPEED_ARG ((XSDPS_EXT_CSD_WRITE_BYTE << 24) \ + | (EXT_CSD_HS_TIMING_BYTE << 16) \ + | (EXT_CSD_HS_TIMING_HIGH << 8)) + +#define XSDPS_MMC_HS200_ARG ((XSDPS_EXT_CSD_WRITE_BYTE << 24) \ + | (EXT_CSD_HS_TIMING_BYTE << 16) \ + | (EXT_CSD_HS_TIMING_HS200 << 8)) + +#define XSDPS_MMC_1_BIT_BUS_ARG ((XSDPS_EXT_CSD_WRITE_BYTE << 24) \ + | (EXT_CSD_BUS_WIDTH_BYTE << 16) \ + | (EXT_CSD_BUS_WITH_1_BIT << 8)) + +#define XSDPS_MMC_4_BIT_BUS_ARG ((XSDPS_EXT_CSD_WRITE_BYTE << 24) \ + | (EXT_CSD_BUS_WIDTH_BYTE << 16) \ + | (EXT_CSD_BUS_WIDTH_4_BIT << 8)) + +#define XSDPS_MMC_8_BIT_BUS_ARG ((XSDPS_EXT_CSD_WRITE_BYTE << 24) \ + | (EXT_CSD_BUS_WIDTH_BYTE << 16) \ + | (EXT_CSD_BUS_WIDTH_8_BIT << 8)) + +#define XSDPS_MMC_DDR_4_BIT_BUS_ARG ((XSDPS_EXT_CSD_WRITE_BYTE << 24) \ + | (EXT_CSD_BUS_WIDTH_BYTE << 16) \ + | (EXT_CSD_BUS_WIDTH_DDR_4_BIT << 8)) + +#define XSDPS_MMC_DDR_8_BIT_BUS_ARG ((XSDPS_EXT_CSD_WRITE_BYTE << 24) \ + | (EXT_CSD_BUS_WIDTH_BYTE << 16) \ + | (EXT_CSD_BUS_WIDTH_DDR_8_BIT << 8)) + +#define XSDPS_MMC_DELAY_FOR_SWITCH 1000 + +/* @} */ + +/* @400KHz, in usec */ +#define XSDPS_74CLK_DELAY 2960 +#define XSDPS_100CLK_DELAY 4000 +#define XSDPS_INIT_DELAY 10000 + +#define XSDPS_DEF_VOLT_LVL XSDPS_PC_BUS_VSEL_3V0_MASK +#define XSDPS_CARD_DEF_ADDR 0x1234 + +#define XSDPS_CARD_SD 1 +#define XSDPS_CARD_MMC 2 +#define XSDPS_CARD_SDIO 3 +#define XSDPS_CARD_SDCOMBO 4 +#define XSDPS_CHIP_EMMC 5 + + /** @name ADMA2 Descriptor related definitions * * ADMA2 Descriptor related definitions * @{ */ -#define XSDPS_DESC_MAX_LENGTH 65536 +#define XSDPS_DESC_MAX_LENGTH 65536U #define XSDPS_DESC_VALID (0x1 << 0) #define XSDPS_DESC_END (0x1 << 1) @@ -460,9 +911,84 @@ extern "C" { /* @} */ +/* For changing clock frequencies */ +#define XSDPS_CLK_400_KHZ 400000 /**< 400 KHZ */ +#define XSDPS_CLK_50_MHZ 50000000 /**< 50 MHZ */ +#define XSDPS_CLK_52_MHZ 52000000 /**< 52 MHZ */ +#define XSDPS_SD_VER_1_0 0x1 /**< SD ver 1 */ +#define XSDPS_SD_VER_2_0 0x2 /**< SD ver 2 */ +#define XSDPS_SCR_BLKCNT 1 +#define XSDPS_SCR_BLKSIZE 8 +#define XSDPS_1_BIT_WIDTH 0x1 +#define XSDPS_4_BIT_WIDTH 0x2 +#define XSDPS_8_BIT_WIDTH 0x3 +#define XSDPS_UHS_SPEED_MODE_SDR12 0x0 +#define XSDPS_UHS_SPEED_MODE_SDR25 0x1 +#define XSDPS_UHS_SPEED_MODE_SDR50 0x2 +#define XSDPS_UHS_SPEED_MODE_SDR104 0x3 +#define XSDPS_UHS_SPEED_MODE_DDR50 0x4 +#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_SWITCH_CMD_SDR12_SET 0x80FFFFF0 +#define XSDPS_SWITCH_CMD_SDR25_SET 0x80FFFFF1 +#define XSDPS_SWITCH_CMD_SDR50_SET 0x80FFFFF2 +#define XSDPS_SWITCH_CMD_SDR104_SET 0x80FFFFF3 +#define XSDPS_SWITCH_CMD_DDR50_SET 0x80FFFFF4 +#define XSDPS_EXT_CSD_CMD_BLKCNT 1 +#define XSDPS_EXT_CSD_CMD_BLKSIZE 512 +#define XSDPS_TUNING_CMD_BLKCNT 1 +#define XSDPS_TUNING_CMD_BLKSIZE 64 + +#define XSDPS_HIGH_SPEED_MAX_CLK 50000000 +#define XSDPS_UHS_SDR104_MAX_CLK 208000000 +#define XSDPS_UHS_SDR50_MAX_CLK 100000000 +#define XSDPS_UHS_DDR50_MAX_CLK 50000000 +#define XSDPS_UHS_SDR25_MAX_CLK 50000000 +#define XSDPS_UHS_SDR12_MAX_CLK 25000000 + +#define SD_DRIVER_TYPE_B 0x01 +#define SD_DRIVER_TYPE_A 0x02 +#define SD_DRIVER_TYPE_C 0x04 +#define SD_DRIVER_TYPE_D 0x08 +#define SD_SET_CURRENT_LIMIT_200 0 +#define SD_SET_CURRENT_LIMIT_400 1 +#define SD_SET_CURRENT_LIMIT_600 2 +#define SD_SET_CURRENT_LIMIT_800 3 + +#define SD_MAX_CURRENT_200 (1 << SD_SET_CURRENT_LIMIT_200) +#define SD_MAX_CURRENT_400 (1 << SD_SET_CURRENT_LIMIT_400) +#define SD_MAX_CURRENT_600 (1 << SD_SET_CURRENT_LIMIT_600) +#define SD_MAX_CURRENT_800 (1 << SD_SET_CURRENT_LIMIT_800) + +#define XSDPS_SD_SDR12_MAX_CLK 25000000 +#define XSDPS_SD_SDR25_MAX_CLK 50000000 +#define XSDPS_SD_SDR50_MAX_CLK 100000000 +#define XSDPS_SD_DDR50_MAX_CLK 50000000 +#define XSDPS_SD_SDR104_MAX_CLK 208000000 +#define XSDPS_MMC_HS200_MAX_CLK 200000000 + +#define XSDPS_CARD_STATE_IDLE 0 +#define XSDPS_CARD_STATE_RDY 1 +#define XSDPS_CARD_STATE_IDEN 2 +#define XSDPS_CARD_STATE_STBY 3 +#define XSDPS_CARD_STATE_TRAN 4 +#define XSDPS_CARD_STATE_DATA 5 +#define XSDPS_CARD_STATE_RCV 6 +#define XSDPS_CARD_STATE_PROG 7 +#define XSDPS_CARD_STATE_DIS 8 +#define XSDPS_CARD_STATE_BTST 9 +#define XSDPS_CARD_STATE_SLP 10 + +#define XSDPS_SLOT_REM 0 +#define XSDPS_SLOT_EMB 1 + /**************************** Type Definitions *******************************/ /***************** Macros (Inline Functions) Definitions *********************/ +#define XSdPs_In64 Xil_In64 +#define XSdPs_Out64 Xil_Out64 #define XSdPs_In32 Xil_In32 #define XSdPs_Out32 Xil_Out32 @@ -473,6 +999,43 @@ extern "C" { #define XSdPs_In8 Xil_In8 #define XSdPs_Out8 Xil_Out8 +/****************************************************************************/ +/** +* Read a register. +* +* @param BaseAddress contains the base address of the device. +* @param RegOffset contains the offset from the 1st register of the +* device to the target register. +* +* @return The value read from the register. +* +* @note C-Style signature: +* u32 XSdPs_ReadReg(XSdPs *InstancePtr. s32 RegOffset) +* +******************************************************************************/ +#define XSdPs_ReadReg64(InstancePtr, RegOffset) \ + XSdPs_In64((InstancePtr->Config.BaseAddress) + RegOffset) + +/***************************************************************************/ +/** +* Write to a register. +* +* @param BaseAddress contains the base address of the device. +* @param RegOffset contains the offset from the 1st register of the +* device to target register. +* @param RegisterValue is the value to be written to the register. +* +* @return None. +* +* @note C-Style signature: +* void XSdPs_WriteReg(XSdPs *InstancePtr, s32 RegOffset, +* u64 RegisterValue) +* +******************************************************************************/ +#define XSdPs_WriteReg64(InstancePtr, RegOffset, RegisterValue) \ + XSdPs_Out64((InstancePtr->Config.BaseAddress) + (RegOffset), \ + (RegisterValue)) + /****************************************************************************/ /** * Read a register. diff --git a/XilinxProcessorIPLib/drivers/sdps/src/xsdps_options.c b/XilinxProcessorIPLib/drivers/sdps/src/xsdps_options.c index 179b73c1..ce5c53da 100644 --- a/XilinxProcessorIPLib/drivers/sdps/src/xsdps_options.c +++ b/XilinxProcessorIPLib/drivers/sdps/src/xsdps_options.c @@ -33,7 +33,7 @@ /** * * @file xsdps_options.c -* @addtogroup sdps_v2_4 +* @addtogroup sdps_v2_5 * @{ * @details * @@ -50,6 +50,7 @@ * Add sleep for microblaze designs. CR# 781117. * 2.3 sk 09/23/14 Use XSdPs_Change_ClkFreq API whenever changing * clock.CR# 816586. +* 2.5 sg 07/09/15 Added SD 3.0 features * * * @@ -74,19 +75,6 @@ #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 *******************************/ @@ -95,6 +83,9 @@ /************************** Function Prototypes ******************************/ int XSdPs_CmdTransfer(XSdPs *InstancePtr, u32 Cmd, u32 Arg, u32 BlkCnt); void XSdPs_SetupADMA2DescTbl(XSdPs *InstancePtr, u32 BlkCnt, const u8 *Buff); +int XSdPs_Uhs_ModeInit(XSdPs *InstancePtr, u8 Mode); +static int XSdPs_Execute_Tuning(XSdPs *InstancePtr); +int XSdPs_Uhs_ModeInit(XSdPs *InstancePtr, u8 Mode); /*****************************************************************************/ /** @@ -125,9 +116,7 @@ int XSdPs_SetBlkSize(XSdPs *InstancePtr, u16 BlkSize) } - /* - * Send block write command - */ + /* Send block write command */ Status = XSdPs_CmdTransfer(InstancePtr, CMD16, BlkSize, 0); if (Status != XST_SUCCESS) { Status = XST_FAILURE; @@ -137,9 +126,7 @@ int XSdPs_SetBlkSize(XSdPs *InstancePtr, u16 BlkSize) Status = XSdPs_ReadReg(InstancePtr->Config.BaseAddress, XSDPS_RESP0_OFFSET); - /* - * Set block size to the value passed - */ + /* Set block size to the value passed */ BlkSize &= XSDPS_BLK_SIZE_MASK; XSdPs_WriteReg16(InstancePtr->Config.BaseAddress, XSDPS_BLK_SIZE_OFFSET, BlkSize); @@ -182,9 +169,7 @@ int XSdPs_Get_BusWidth(XSdPs *InstancePtr, u8 *SCR) SCR[LoopCnt] = 0; } - /* - * Send block write command - */ + /* Send block write command */ Status = XSdPs_CmdTransfer(InstancePtr, CMD55, InstancePtr->RelCardAddr, 0); if (Status != XST_SUCCESS) { @@ -195,9 +180,7 @@ int XSdPs_Get_BusWidth(XSdPs *InstancePtr, u8 *SCR) BlkCnt = XSDPS_SCR_BLKCNT; BlkSize = XSDPS_SCR_BLKSIZE; - /* - * Set block size to the value passed - */ + /* Set block size to the value passed */ BlkSize &= XSDPS_BLK_SIZE_MASK; XSdPs_WriteReg16(InstancePtr->Config.BaseAddress, XSDPS_BLK_SIZE_OFFSET, BlkSize); @@ -224,9 +207,7 @@ int XSdPs_Get_BusWidth(XSdPs *InstancePtr, u8 *SCR) StatusReg = XSdPs_ReadReg16(InstancePtr->Config.BaseAddress, XSDPS_NORM_INTR_STS_OFFSET); if (StatusReg & XSDPS_INTR_ERR_MASK) { - /* - * Write to clear error bits - */ + /* Write to clear error bits */ XSdPs_WriteReg16(InstancePtr->Config.BaseAddress, XSDPS_ERR_INTR_STS_OFFSET, XSDPS_ERROR_INTR_ALL_MASK); @@ -235,9 +216,7 @@ int XSdPs_Get_BusWidth(XSdPs *InstancePtr, u8 *SCR) } } while ((StatusReg & XSDPS_INTR_TC_MASK) == 0); - /* - * Write to clear bit - */ + /* Write to clear bit */ XSdPs_WriteReg16(InstancePtr->Config.BaseAddress, XSDPS_NORM_INTR_STS_OFFSET, XSDPS_INTR_TC_MASK); @@ -275,38 +254,46 @@ int XSdPs_Change_BusWidth(XSdPs *InstancePtr) 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; - } + if (InstancePtr->CardType == XSDPS_CARD_SD) { - Arg = XSDPS_4_BIT_WIDTH; - Status = XSdPs_CmdTransfer(InstancePtr, ACMD6, Arg, 0); - if (Status != XST_SUCCESS) { - Status = XST_FAILURE; - goto RETURN_PATH; - } + Status = XSdPs_CmdTransfer(InstancePtr, CMD55, InstancePtr->RelCardAddr, + 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); + InstancePtr->BusWidth = XSDPS_4_BIT_WIDTH; - Status = XSdPs_ReadReg(InstancePtr->Config.BaseAddress, - XSDPS_RESP0_OFFSET); + Arg = InstancePtr->BusWidth; -#else + Status = XSdPs_CmdTransfer(InstancePtr, ACMD6, Arg, 0); + if (Status != XST_SUCCESS) { + Status = XST_FAILURE; + goto RETURN_PATH; + } + } 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; + if ((InstancePtr->HC_Version == XSDPS_HC_SPEC_V3) + && (InstancePtr->CardType == XSDPS_CHIP_EMMC)) { + /* in case of eMMC data width 8-bit */ + InstancePtr->BusWidth = XSDPS_8_BIT_WIDTH; + } else { + InstancePtr->BusWidth = XSDPS_4_BIT_WIDTH; + } + + if (InstancePtr->BusWidth == XSDPS_8_BIT_WIDTH) { + Arg = XSDPS_MMC_8_BIT_BUS_ARG; + } else { + Arg = XSDPS_MMC_4_BIT_BUS_ARG; + } + + Status = XSdPs_CmdTransfer(InstancePtr, CMD6, Arg, 0); + if (Status != XST_SUCCESS) { + Status = XST_FAILURE; + goto RETURN_PATH; + } } #ifdef __arm__ @@ -324,15 +311,21 @@ int XSdPs_Change_BusWidth(XSdPs *InstancePtr) StatusReg = XSdPs_ReadReg8(InstancePtr->Config.BaseAddress, XSDPS_HOST_CTRL1_OFFSET); - StatusReg |= XSDPS_HC_WIDTH_MASK; + + /* Width setting in controller */ + if (InstancePtr->BusWidth == XSDPS_8_BIT_WIDTH) { + StatusReg |= XSDPS_HC_EXT_BUS_WIDTH; + } else { + StatusReg |= XSDPS_HC_WIDTH_MASK; + } + XSdPs_WriteReg8(InstancePtr->Config.BaseAddress, - XSDPS_HOST_CTRL1_OFFSET,StatusReg); + XSDPS_HOST_CTRL1_OFFSET, + StatusReg); Status = XSdPs_ReadReg(InstancePtr->Config.BaseAddress, XSDPS_RESP0_OFFSET); -#endif - Status = XST_SUCCESS; RETURN_PATH: @@ -403,9 +396,7 @@ int XSdPs_Get_BusSpeed(XSdPs *InstancePtr, u8 *ReadBuff) StatusReg = XSdPs_ReadReg16(InstancePtr->Config.BaseAddress, XSDPS_NORM_INTR_STS_OFFSET); if (StatusReg & XSDPS_INTR_ERR_MASK) { - /* - * Write to clear error bits - */ + /* Write to clear error bits */ XSdPs_WriteReg16(InstancePtr->Config.BaseAddress, XSDPS_ERR_INTR_STS_OFFSET, XSDPS_ERROR_INTR_ALL_MASK); @@ -414,9 +405,7 @@ int XSdPs_Get_BusSpeed(XSdPs *InstancePtr, u8 *ReadBuff) } } while ((StatusReg & XSDPS_INTR_TC_MASK) == 0); - /* - * Write to clear bit - */ + /* Write to clear bit */ XSdPs_WriteReg16(InstancePtr->Config.BaseAddress, XSDPS_NORM_INTR_STS_OFFSET, XSDPS_INTR_TC_MASK); @@ -450,90 +439,102 @@ 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; +#ifdef __ICCARM__ +#pragma data_alignment = 32 + u8 ReadBuff[64]; +#pragma data_alignment = 4 +#else + u8 ReadBuff[64] __attribute__ ((aligned(32))); #endif Xil_AssertNonvoid(InstancePtr != NULL); Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); -#ifndef MMC_CARD + if (InstancePtr->CardType == XSDPS_CARD_SD) { - 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); + 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_SetupADMA2DescTbl(InstancePtr, BlkCnt, ReadBuff); - Xil_DCacheInvalidateRange(ReadBuff, 64); + Xil_DCacheFlushRange(ReadBuff, 64); - XSdPs_WriteReg16(InstancePtr->Config.BaseAddress, - XSDPS_XFER_MODE_OFFSET, - XSDPS_TM_DAT_DIR_SEL_MASK | XSDPS_TM_DMA_EN_MASK); + 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; - } + Arg = XSDPS_SWITCH_CMD_HS_SET; - /* - * 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 = XSdPs_CmdTransfer(InstancePtr, CMD6, Arg, 1); + if (Status != XST_SUCCESS) { 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); + /* + * 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); - /* - * Change the clock frequency to 50 MHz - */ - Status = XSdPs_Change_ClkFreq(InstancePtr, XSDPS_CLK_50_MHZ); - if (Status != XST_SUCCESS) { + /* Write to clear bit */ + XSdPs_WriteReg16(InstancePtr->Config.BaseAddress, + XSDPS_NORM_INTR_STS_OFFSET, XSDPS_INTR_TC_MASK); + + /* Change the clock frequency to 50 MHz */ + InstancePtr->BusSpeed = XSDPS_CLK_50_MHZ; + Status = XSdPs_Change_ClkFreq(InstancePtr, InstancePtr->BusSpeed); + if (Status != XST_SUCCESS) { + Status = XST_FAILURE; + goto RETURN_PATH; + } + + } else if (InstancePtr->CardType == XSDPS_CARD_MMC) { + Arg = XSDPS_MMC_HIGH_SPEED_ARG; + + Status = XSdPs_CmdTransfer(InstancePtr, CMD6, Arg, 0); + if (Status != XST_SUCCESS) { Status = XST_FAILURE; goto RETURN_PATH; - } + } + /* Change the clock frequency to 52 MHz */ + InstancePtr->BusSpeed = XSDPS_CLK_52_MHZ; + XSdPs_Change_ClkFreq(InstancePtr, XSDPS_CLK_52_MHZ); + } else { + Arg = XSDPS_MMC_HS200_ARG; - 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_CmdTransfer(InstancePtr, CMD6, Arg, 0); + if (Status != XST_SUCCESS) { + Status = XST_FAILURE; + goto RETURN_PATH; + } - Status = XSdPs_ReadReg(InstancePtr->Config.BaseAddress, - XSDPS_RESP0_OFFSET); + /* Change the clock frequency to 200 MHz */ + InstancePtr->BusSpeed = XSDPS_MMC_HS200_MAX_CLK; -#else - - Arg = XSDPS_MMC_HIGH_SPEED_ARG; - Status = XSdPs_CmdTransfer(InstancePtr, CMD6, Arg, 0); - if (Status != XST_SUCCESS) { - Status = XST_FAILURE; - goto RETURN_PATH; + XSdPs_Change_ClkFreq(InstancePtr, InstancePtr->BusSpeed); + Status = XSdPs_Execute_Tuning(InstancePtr); + if (Status != XST_SUCCESS) { + Status = XST_FAILURE; + goto RETURN_PATH; + } } #ifdef __arm__ @@ -549,8 +550,6 @@ int XSdPs_Change_BusSpeed(XSdPs *InstancePtr) #endif - XSdPs_Change_ClkFreq(InstancePtr, XSDPS_CLK_52_MHZ); - StatusReg = XSdPs_ReadReg8(InstancePtr->Config.BaseAddress, XSDPS_HOST_CTRL1_OFFSET); StatusReg |= XSDPS_HC_SPEED_MASK; @@ -559,7 +558,7 @@ int XSdPs_Change_BusSpeed(XSdPs *InstancePtr) Status = XSdPs_ReadReg(InstancePtr->Config.BaseAddress, XSDPS_RESP0_OFFSET); -#endif + Status = XST_SUCCESS; @@ -586,67 +585,87 @@ int XSdPs_Change_BusSpeed(XSdPs *InstancePtr) int XSdPs_Change_ClkFreq(XSdPs *InstancePtr, u32 SelFreq) { u16 ClockReg; - int DivCnt; + u16 DivCnt; u16 Divisor; + u16 ExtDivisor; u16 ClkLoopCnt; int Status; Xil_AssertNonvoid(InstancePtr != NULL); Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); - /* - * Disable clock - */ + /* 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); - + ClockReg &= ~(XSDPS_CC_SD_CLK_EN_MASK | XSDPS_CC_INT_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; + if (InstancePtr->HC_Version == XSDPS_HC_SPEC_V3) { + /* Calculate divisor */ + for (DivCnt = 0x1; DivCnt <= XSDPS_CC_EXT_MAX_DIV_CNT;) { + if (((InstancePtr->Config.InputClockHz) / DivCnt) <= SelFreq) { + Divisor = DivCnt >> 1; + break; + } + DivCnt++; + } + + if (DivCnt > XSDPS_CC_EXT_MAX_DIV_CNT) { + /* No valid divisor found for given frequency */ + Status = XST_FAILURE; + goto RETURN_PATH; + } + } else { + /* Calculate divisor */ + for (DivCnt = 0x1; DivCnt <= XSDPS_CC_MAX_DIV_CNT;) { + if (((InstancePtr->Config.InputClockHz) / DivCnt) <= SelFreq) { + Divisor = DivCnt / 2; + break; + } + DivCnt = DivCnt << 1; + } + + if (DivCnt > XSDPS_CC_MAX_DIV_CNT) { + /* No valid divisor found for given frequency */ + Status = XST_FAILURE; + goto RETURN_PATH; } - DivCnt = DivCnt << 1; } - if(ClkLoopCnt == 9) { + /* Set clock divisor */ + if (InstancePtr->HC_Version == XSDPS_HC_SPEC_V3) { + ClockReg = XSdPs_ReadReg16(InstancePtr->Config.BaseAddress, + XSDPS_CLK_CTRL_OFFSET); + ClockReg &= ~(XSDPS_CC_SDCLK_FREQ_SEL_MASK | + XSDPS_CC_SDCLK_FREQ_SEL_EXT_MASK); - /* - * No valid divisor found for given frequency - */ - Status = XST_FAILURE; - goto RETURN_PATH; + ExtDivisor = Divisor >> 8; + ExtDivisor <<= XSDPS_CC_EXT_DIV_SHIFT; + ExtDivisor &= XSDPS_CC_SDCLK_FREQ_SEL_EXT_MASK; + + Divisor <<= XSDPS_CC_DIV_SHIFT; + Divisor &= XSDPS_CC_SDCLK_FREQ_SEL_MASK; + ClockReg |= Divisor | ExtDivisor | XSDPS_CC_INT_CLK_EN_MASK; + XSdPs_WriteReg16(InstancePtr->Config.BaseAddress, XSDPS_CLK_CTRL_OFFSET, + ClockReg); + } else { + ClockReg = XSdPs_ReadReg16(InstancePtr->Config.BaseAddress, + XSDPS_CLK_CTRL_OFFSET); + ClockReg &= (~XSDPS_CC_SDCLK_FREQ_SEL_MASK); + + Divisor <<= XSDPS_CC_DIV_SHIFT; + Divisor &= XSDPS_CC_SDCLK_FREQ_SEL_MASK; + ClockReg |= Divisor | XSDPS_CC_INT_CLK_EN_MASK; + XSdPs_WriteReg16(InstancePtr->Config.BaseAddress, XSDPS_CLK_CTRL_OFFSET, + ClockReg); } - /* - * 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 - */ + /* 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 - */ + /* Enable SD clock */ ClockReg = XSdPs_ReadReg16(InstancePtr->Config.BaseAddress, XSDPS_CLK_CTRL_OFFSET); XSdPs_WriteReg16(InstancePtr->Config.BaseAddress, @@ -655,7 +674,7 @@ int XSdPs_Change_ClkFreq(XSdPs *InstancePtr, u32 SelFreq) Status = XST_SUCCESS; - RETURN_PATH: +RETURN_PATH: return Status; } @@ -750,9 +769,7 @@ int XSdPs_Get_Mmc_ExtCsd(XSdPs *InstancePtr, u8 *ReadBuff) Arg = 0; - /* - * Send SEND_EXT_CSD command - */ + /* Send SEND_EXT_CSD command */ Status = XSdPs_CmdTransfer(InstancePtr, CMD8, Arg, 1); if (Status != XST_SUCCESS) { Status = XST_FAILURE; @@ -767,9 +784,7 @@ int XSdPs_Get_Mmc_ExtCsd(XSdPs *InstancePtr, u8 *ReadBuff) StatusReg = XSdPs_ReadReg16(InstancePtr->Config.BaseAddress, XSDPS_NORM_INTR_STS_OFFSET); if (StatusReg & XSDPS_INTR_ERR_MASK) { - /* - * Write to clear error bits - */ + /* Write to clear error bits */ XSdPs_WriteReg16(InstancePtr->Config.BaseAddress, XSDPS_ERR_INTR_STS_OFFSET, XSDPS_ERROR_INTR_ALL_MASK); @@ -778,9 +793,7 @@ int XSdPs_Get_Mmc_ExtCsd(XSdPs *InstancePtr, u8 *ReadBuff) } } while ((StatusReg & XSDPS_INTR_TC_MASK) == 0); - /* - * Write to clear bit - */ + /* Write to clear bit */ XSdPs_WriteReg16(InstancePtr->Config.BaseAddress, XSDPS_NORM_INTR_STS_OFFSET, XSDPS_INTR_TC_MASK); @@ -793,4 +806,220 @@ int XSdPs_Get_Mmc_ExtCsd(XSdPs *InstancePtr, u8 *ReadBuff) return Status; } + + +/*****************************************************************************/ +/** +* +* API to UHS-I mode initialization +* +* +* @param InstancePtr is a pointer to the XSdPs instance. +* @param Mode UHS-I mode +* +* @return +* - XST_SUCCESS if successful. +* - XST_FAILURE if fail. +* +* @note None. +* +******************************************************************************/ +int XSdPs_Uhs_ModeInit(XSdPs *InstancePtr, u8 Mode) +{ + u32 Status = 0; + u16 StatusReg = 0; + u16 CtrlReg = 0; + u32 Arg = 0; + u16 BlkCnt; + u16 BlkSize; +#ifdef __ICCARM__ +#pragma data_alignment = 32 + u8 ReadBuff[64]; +#pragma data_alignment = 4 +#else + u8 ReadBuff[64] __attribute__ ((aligned(32))); +#endif + + Xil_AssertNonvoid(InstancePtr != NULL); + Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + + /* Drive strength */ + + /* Bus speed mode selection */ + 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); + + Xil_DCacheFlushRange(ReadBuff, 64); + + XSdPs_WriteReg16(InstancePtr->Config.BaseAddress, XSDPS_XFER_MODE_OFFSET, + XSDPS_TM_DAT_DIR_SEL_MASK | XSDPS_TM_DMA_EN_MASK); + + switch (Mode) { + case 0: + Arg = XSDPS_SWITCH_CMD_SDR12_SET; + InstancePtr->BusSpeed = XSDPS_SD_SDR12_MAX_CLK; + break; + case 1: + Arg = XSDPS_SWITCH_CMD_SDR25_SET; + InstancePtr->BusSpeed = XSDPS_SD_SDR25_MAX_CLK; + break; + case 2: + Arg = XSDPS_SWITCH_CMD_SDR50_SET; + InstancePtr->BusSpeed = XSDPS_SD_SDR50_MAX_CLK; + break; + case 3: + Arg = XSDPS_SWITCH_CMD_SDR104_SET; + InstancePtr->BusSpeed = XSDPS_SD_SDR104_MAX_CLK; + break; + case 4: + Arg = XSDPS_SWITCH_CMD_DDR50_SET; + InstancePtr->BusSpeed = XSDPS_SD_DDR50_MAX_CLK; + break; + default: + Status = XST_FAILURE; + goto RETURN_PATH; + break; + } + + 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); + + + /* Current limit */ + + /* Set UHS mode in controller */ + CtrlReg = XSdPs_ReadReg16(InstancePtr->Config.BaseAddress, + XSDPS_HOST_CTRL2_OFFSET); + CtrlReg &= ~XSDPS_HC2_UHS_MODE_MASK; + CtrlReg |= Mode; + XSdPs_WriteReg16(InstancePtr->Config.BaseAddress, + XSDPS_HOST_CTRL2_OFFSET, CtrlReg); + + /* Change the clock frequency */ + Status = XSdPs_Change_ClkFreq(InstancePtr, InstancePtr->BusSpeed); + if (Status != XST_SUCCESS) { + Status = XST_FAILURE; + goto RETURN_PATH; + } + + if((Mode == XSDPS_UHS_SPEED_MODE_SDR104) || + (Mode == XSDPS_UHS_SPEED_MODE_DDR50)) { + /* Send tuning pattern */ + Status = XSdPs_Execute_Tuning(InstancePtr); + if (Status != XST_SUCCESS) { + Status = XST_FAILURE; + goto RETURN_PATH; + } + } + + Status = XST_SUCCESS; + + RETURN_PATH: + return Status; +} + +static int XSdPs_Execute_Tuning(XSdPs *InstancePtr) +{ + u32 Status = 0; + u32 StatusReg = 0x0; + u32 Arg = 0; + u16 BlkCnt; + u16 BlkSize; + int LoopCnt; +#ifdef __ICCARM__ +#pragma data_alignment = 32 + u8 ReadBuff[128]; +#pragma data_alignment = 4 +#else + u8 ReadBuff[128] __attribute__ ((aligned(32))); +#endif + + Xil_AssertNonvoid(InstancePtr != NULL); + Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + + BlkCnt = XSDPS_TUNING_CMD_BLKCNT; + BlkSize = XSDPS_TUNING_CMD_BLKSIZE; + if(InstancePtr->BusWidth == XSDPS_8_BIT_WIDTH) + { + BlkSize = BlkSize*2; + } + BlkSize &= XSDPS_BLK_SIZE_MASK; + XSdPs_WriteReg16(InstancePtr->Config.BaseAddress, XSDPS_BLK_SIZE_OFFSET, + BlkSize); + + for (LoopCnt = 0; LoopCnt < BlkSize; LoopCnt++) { + ReadBuff[LoopCnt] = 0; + } + + 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); + + Xil_DCacheInvalidateRange(ReadBuff, BlkSize); + + if(InstancePtr->CardType == XSDPS_CARD_SD) { + Status = XSdPs_CmdTransfer(InstancePtr, CMD19, 0, 1); + } else { + Status = XSdPs_CmdTransfer(InstancePtr, CMD21, 0, 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 = XST_SUCCESS; + + RETURN_PATH: return Status; + +} /** @} */ diff --git a/XilinxProcessorIPLib/drivers/sdps/src/xsdps_sinit.c b/XilinxProcessorIPLib/drivers/sdps/src/xsdps_sinit.c index f8cffb46..817c46c8 100644 --- a/XilinxProcessorIPLib/drivers/sdps/src/xsdps_sinit.c +++ b/XilinxProcessorIPLib/drivers/sdps/src/xsdps_sinit.c @@ -33,7 +33,7 @@ /** * * @file xsdps_sinit.c -* @addtogroup sdps_v2_4 +* @addtogroup sdps_v2_5 * @{ * @details *