/**
*
* 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;

}
Example #2
0
/**
*
* 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;
}
Example #3
0
/**
* 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;
}