/** * * Selects card and sets default block size * * * @param InstancePtr is a pointer to the XSdPs instance. * * @return * - XST_SUCCESS if successful. * - XST_FAILURE if fail. * * @note None. * ******************************************************************************/ int XSdPs_Select_Card (XSdPs *InstancePtr) { u32 Status = 0; /* * Send CMD7 - Select card */ Status = XSdPs_CmdTransfer(InstancePtr, CMD7, InstancePtr->RelCardAddr, 0); if (Status != XST_SUCCESS) { Status = XST_FAILURE; goto RETURN_PATH; } Status = XSdPs_ReadReg(InstancePtr->Config.BaseAddress, XSDPS_RESP0_OFFSET); /* * Set default block size */ Status = XSdPs_SetBlkSize(InstancePtr, XSDPS_BLK_SIZE_512_MASK); if (Status != XST_SUCCESS) { Status = XST_FAILURE; goto RETURN_PATH; } Status = XST_SUCCESS; RETURN_PATH: return Status; }
/** * * 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 * * ******************************************************************************/ s32 XSdPs_CardInitialize(XSdPs *InstancePtr) { u8 Tmp; u32 Cnt; u32 PresentStateReg; u32 CtrlReg; u32 CSD[4]; #ifdef __ICCARM__ #pragma data_alignment = 32 static u8 ExtCsd[512]; #pragma data_alignment = 4 #else static u8 ExtCsd[512] __attribute__ ((aligned(32))); #endif u8 SCR[8] = { 0U }; u8 ReadBuff[64] = { 0U }; s32 Status; 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 = 0U; 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 != 0U) && (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 { /* * card supports CMD6 when SD_SPEC field in SCR register * indicates that the Physical Layer Specification Version * is 1.10 or later. So for SD v1.0 cmd6 is not supported. */ if (SCR[0] != 0U) { /* 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) && (InstancePtr->Card_Version > CSD_SPEC_VER_3)) && (InstancePtr->HC_Version == XSDPS_HC_SPEC_V2)) { 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_DEVICE_TYPE_BYTE] & EXT_CSD_DEVICE_TYPE_HIGH_SPEED) != 0U) { 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 if (InstancePtr->CardType == XSDPS_CHIP_EMMC){ /* 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; } if ((ExtCsd[EXT_CSD_DEVICE_TYPE_BYTE] & (EXT_CSD_DEVICE_TYPE_SDR_1V8_HS200 | EXT_CSD_DEVICE_TYPE_SDR_1V2_HS200)) != 0U) { 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; }
/** * This function performs SD write in polled mode. * * @param InstancePtr is a pointer to the instance to be worked on. * @param Arg is the address passed by the user that is to be sent as * argument along with the command. * @param BlkCnt - Block count passed by the user. * @param Buff - Pointer to the data buffer for a DMA transfer. * * @return * - XST_SUCCESS if initialization was successful * - XST_FAILURE if failure - could be because another transfer * is in progress or command or data inhibit is set * ******************************************************************************/ s32 XSdPs_WritePolled(XSdPs *InstancePtr, u32 Arg, u32 BlkCnt, const u8 *Buff) { s32 Status; u32 PresentStateReg; u32 StatusReg; if ((InstancePtr->HC_Version != XSDPS_HC_SPEC_V3) || ((InstancePtr->Host_Caps & XSDPS_CAPS_SLOT_TYPE_MASK) != XSDPS_CAPS_EMB_SLOT)) { if(InstancePtr->Config.CardDetect != 0U) { /* Check status to ensure card is initialized */ PresentStateReg = XSdPs_ReadReg(InstancePtr->Config.BaseAddress, XSDPS_PRES_STATE_OFFSET); if ((PresentStateReg & XSDPS_PSR_CARD_INSRT_MASK) == 0x0U) { Status = XST_FAILURE; goto RETURN_PATH; } } } /* Set block size to 512 if not already set */ if( XSdPs_ReadReg(InstancePtr->Config.BaseAddress, XSDPS_BLK_SIZE_OFFSET) != XSDPS_BLK_SIZE_512_MASK ) { Status = XSdPs_SetBlkSize(InstancePtr, XSDPS_BLK_SIZE_512_MASK); if (Status != XST_SUCCESS) { Status = XST_FAILURE; goto RETURN_PATH; } } XSdPs_SetupADMA2DescTbl(InstancePtr, BlkCnt, Buff); Xil_DCacheFlushRange((INTPTR)Buff, BlkCnt * XSDPS_BLK_SIZE_512_MASK); XSdPs_WriteReg16(InstancePtr->Config.BaseAddress, XSDPS_XFER_MODE_OFFSET, XSDPS_TM_AUTO_CMD12_EN_MASK | XSDPS_TM_BLK_CNT_EN_MASK | XSDPS_TM_MUL_SIN_BLK_SEL_MASK | XSDPS_TM_DMA_EN_MASK); /* Send block write command */ Status = XSdPs_CmdTransfer(InstancePtr, CMD25, Arg, BlkCnt); if (Status != XST_SUCCESS) { Status = XST_FAILURE; goto RETURN_PATH; } /* * Check for transfer complete * Polling for response for now */ do { StatusReg = XSdPs_ReadReg16(InstancePtr->Config.BaseAddress, XSDPS_NORM_INTR_STS_OFFSET); if ((StatusReg & XSDPS_INTR_ERR_MASK) != 0U) { /* 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) == 0U); /* 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; }
/** * This function performs SD read in polled mode. * * @param InstancePtr is a pointer to the instance to be worked on. * @param Arg is the address passed by the user that is to be sent as * argument along with the command. * @param BlkCnt - Block count passed by the user. * @param Buff - Pointer to the data buffer for a DMA transfer. * * @return * - XST_SUCCESS if initialization was successful * - XST_FAILURE if failure - could be because another transfer * is in progress or command or data inhibit is set * ******************************************************************************/ int XSdPs_ReadPolled(XSdPs *InstancePtr, u32 Arg, u32 BlkCnt, u8 *Buff) { u32 Status; u32 PresentStateReg; u32 StatusReg; /* * Check status to ensure card is initialized */ PresentStateReg = XSdPs_ReadReg(InstancePtr->Config.BaseAddress, XSDPS_PRES_STATE_OFFSET); if ((PresentStateReg & XSDPS_PSR_CARD_INSRT_MASK) == 0x0) { Status = XST_FAILURE; goto RETURN_PATH; } /* * Set block size to 512 if not already set */ if( XSdPs_ReadReg(InstancePtr->Config.BaseAddress, XSDPS_BLK_SIZE_OFFSET) != XSDPS_BLK_SIZE_512_MASK ) { Status = XSdPs_SetBlkSize(InstancePtr, XSDPS_BLK_SIZE_512_MASK); if (Status != XST_SUCCESS) { Status = XST_FAILURE; goto RETURN_PATH; } } XSdPs_SetupADMA2DescTbl(InstancePtr, BlkCnt, Buff); XSdPs_WriteReg16(InstancePtr->Config.BaseAddress, XSDPS_XFER_MODE_OFFSET, XSDPS_TM_AUTO_CMD12_EN_MASK | XSDPS_TM_BLK_CNT_EN_MASK | XSDPS_TM_DAT_DIR_SEL_MASK | XSDPS_TM_DMA_EN_MASK | XSDPS_TM_MUL_SIN_BLK_SEL_MASK); Xil_DCacheInvalidateRange(Buff, BlkCnt * XSDPS_BLK_SIZE_512_MASK); /* * Send block read command */ Status = XSdPs_CmdTransfer(InstancePtr, CMD18, Arg, BlkCnt); if (Status != XST_SUCCESS) { Status = XST_FAILURE; goto RETURN_PATH; } /* * Check for transfer complete */ do { StatusReg = XSdPs_ReadReg16(InstancePtr->Config.BaseAddress, XSDPS_NORM_INTR_STS_OFFSET); if (StatusReg & XSDPS_INTR_ERR_MASK) { /* * Write to clear error bits */ XSdPs_WriteReg16(InstancePtr->Config.BaseAddress, XSDPS_ERR_INTR_STS_OFFSET, XSDPS_ERROR_INTR_ALL_MASK); Status = XST_FAILURE; goto RETURN_PATH; } } while((StatusReg & XSDPS_INTR_TC_MASK) == 0); /* * Write to clear bit */ XSdPs_WriteReg16(InstancePtr->Config.BaseAddress, XSDPS_NORM_INTR_STS_OFFSET, XSDPS_INTR_TC_MASK); Status = XSdPs_ReadReg(InstancePtr->Config.BaseAddress, XSDPS_RESP0_OFFSET); Status = XST_SUCCESS; RETURN_PATH: return Status; }