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 *