XilinxProcessorIPLib/drivers/nandps/src/xnandps.c
static int XNandPs_ReadPage_HwEcc(XNandPs *InstancePtr, u8 *DstPtr)
{
	u32 Status;
	u32 BytesPerPage;
	u32 SpareBytesPerPage;
	u32 EccSteps;
	u32 EccOffset;
	u32 DataPhaseAddr;
	u32 Index;
	u32 *EccPos;
	u8 *EccCode;
	u8 *EccCalc;
	u8 *Ptr = DstPtr;
	u8 *SparePtr = InstancePtr->SpareBufPtr;

	BytesPerPage = InstancePtr->Geometry.BytesPerPage;
	SpareBytesPerPage = InstancePtr->Geometry.SpareBytesPerPage;

	EccSteps = InstancePtr->EccConfig.NumSteps;
	EccCode = &InstancePtr->EccCode[0];
	EccCalc = &InstancePtr->EccCalc[0];

	/*
	 * Read page sized bytes in one less AXI data width
	 */
	XNandPs_ReadBuf(InstancePtr, Ptr,
				(BytesPerPage - XNANDPS_AXI_DATA_WIDTH));

	Ptr += (BytesPerPage - XNANDPS_AXI_DATA_WIDTH);

	/*
	 * Set the ECC Last bit
	 */
	DataPhaseAddr = InstancePtr->DataPhaseAddr;
	DataPhaseAddr |= XNANDPS_ECC_LAST;
	InstancePtr->DataPhaseAddr = DataPhaseAddr;

	/*
	 * Read transaction with ECC enabled
	 */
	XNandPs_ReadBuf(InstancePtr, Ptr, XNANDPS_AXI_DATA_WIDTH);

	/*
	 * Calculate the hardware ECC
	 */
	Ptr = DstPtr;
	Status = XNandPs_EccCalculate(InstancePtr, EccCalc);
	if (Status != XST_SUCCESS) {
		return Status;
	}
	DataPhaseAddr = InstancePtr->DataPhaseAddr;
	DataPhaseAddr &= ~XNANDPS_ECC_LAST;
	InstancePtr->DataPhaseAddr = DataPhaseAddr;
	XNandPs_ReadBuf(InstancePtr, SparePtr,
				(SpareBytesPerPage - XNANDPS_AXI_DATA_WIDTH));

	/*
	 * Clear chip select for last AXI transaction
	 */
	DataPhaseAddr = InstancePtr->DataPhaseAddr;
	DataPhaseAddr |= XNANDPS_CLR_CS;
	InstancePtr->DataPhaseAddr = DataPhaseAddr;
	SparePtr += (SpareBytesPerPage - XNANDPS_AXI_DATA_WIDTH);
	XNandPs_ReadBuf(InstancePtr, SparePtr, XNANDPS_AXI_DATA_WIDTH);

	/*
	 * Read the stored ECC code
	 */
	EccPos = &InstancePtr->EccConfig.EccPos[0];
	for(Index = 0; Index < InstancePtr->EccConfig.TotalBytes; Index++) {
		EccCode[Index] = ~(InstancePtr->SpareBufPtr[EccPos[Index]]);
	}

	/*
	 * Check for ECC errors
	 */
	EccOffset = 0;
	for(; EccSteps; EccSteps--) {
		Status = XNandPs_EccCorrect(DstPtr,
				&EccCalc[EccOffset],&EccCode[EccOffset]);
		if (Status != XST_SUCCESS) {
			return Status;
		}
		DstPtr += InstancePtr->EccConfig.BlockSize;
		EccOffset += InstancePtr->EccConfig.BytesPerBlock;
	}

	return XST_SUCCESS;
}
/*****************************************************************************/
/**
*
* This function reads a specific page from NAND device using HW ECC block.
* It checks for the ECC errors and corrects single bit errors. The multiple bit
* error are reported as failure.
*
* @param	InstancePtr is a pointer to the XNandPs instance.
* @param	DstPtr is a pointer to the destination buffer.
* @return
*		- XST_SUCCESS if successful.
*		- XST_FAILURE if fail.
*
* @note		None
*
******************************************************************************/
This function reads a specific page from NAND device using HW ECC block.
It checks for the ECC errors and corrects single bit errors. The multiple bit
error are reported as failure.
This function reads a specific page from NAND device using HW ECC block . It checks for the ECC errors and corrects single bit errors . The multiple bit error are reported as failure .
static int XNandPs_ReadPage_HwEcc(XNandPs *InstancePtr, u8 *DstPtr)
{
	u32 Status;
	u32 BytesPerPage;
	u32 SpareBytesPerPage;
	u32 EccSteps;
	u32 EccOffset;
	u32 DataPhaseAddr;
	u32 Index;
	u32 *EccPos;
	u8 *EccCode;
	u8 *EccCalc;
	u8 *Ptr = DstPtr;
	u8 *SparePtr = InstancePtr->SpareBufPtr;
	BytesPerPage = InstancePtr->Geometry.BytesPerPage;
	SpareBytesPerPage = InstancePtr->Geometry.SpareBytesPerPage;
	EccSteps = InstancePtr->EccConfig.NumSteps;
	EccCode = &InstancePtr->EccCode[0];
	EccCalc = &InstancePtr->EccCalc[0];
	XNandPs_ReadBuf(InstancePtr, Ptr,
				(BytesPerPage - XNANDPS_AXI_DATA_WIDTH));
	Ptr += (BytesPerPage - XNANDPS_AXI_DATA_WIDTH);
	DataPhaseAddr = InstancePtr->DataPhaseAddr;
	DataPhaseAddr |= XNANDPS_ECC_LAST;
	InstancePtr->DataPhaseAddr = DataPhaseAddr;
	XNandPs_ReadBuf(InstancePtr, Ptr, XNANDPS_AXI_DATA_WIDTH);
	Ptr = DstPtr;
	Status = XNandPs_EccCalculate(InstancePtr, EccCalc);
	if (Status != XST_SUCCESS) {
		return Status;
	}
	DataPhaseAddr = InstancePtr->DataPhaseAddr;
	DataPhaseAddr &= ~XNANDPS_ECC_LAST;
	InstancePtr->DataPhaseAddr = DataPhaseAddr;
	XNandPs_ReadBuf(InstancePtr, SparePtr,
				(SpareBytesPerPage - XNANDPS_AXI_DATA_WIDTH));
	DataPhaseAddr = InstancePtr->DataPhaseAddr;
	DataPhaseAddr |= XNANDPS_CLR_CS;
	InstancePtr->DataPhaseAddr = DataPhaseAddr;
	SparePtr += (SpareBytesPerPage - XNANDPS_AXI_DATA_WIDTH);
	XNandPs_ReadBuf(InstancePtr, SparePtr, XNANDPS_AXI_DATA_WIDTH);
	EccPos = &InstancePtr->EccConfig.EccPos[0];
	for(Index = 0; Index < InstancePtr->EccConfig.TotalBytes; Index++) {
		EccCode[Index] = ~(InstancePtr->SpareBufPtr[EccPos[Index]]);
	}
	EccOffset = 0;
	for(; EccSteps; EccSteps--) {
		Status = XNandPs_EccCorrect(DstPtr,
				&EccCalc[EccOffset],&EccCode[EccOffset]);
		if (Status != XST_SUCCESS) {
			return Status;
		}
		DstPtr += InstancePtr->EccConfig.BlockSize;
		EccOffset += InstancePtr->EccConfig.BytesPerBlock;
	}
	return XST_SUCCESS;
}
static int XNandPs_ReadPage_HwEcc ( XNandPs * InstancePtr , u8 * DstPtr ) { u32 Status ; u32 BytesPerPage ; u32 SpareBytesPerPage ; u32 EccSteps ; u32 EccOffset ; u32 DataPhaseAddr ; u32 Index ; u32 * EccPos ; u8 * EccCode ; u8 * EccCalc ; u8 * Ptr = DstPtr ; u8 * SparePtr = InstancePtr -> SpareBufPtr ; BytesPerPage = InstancePtr -> Geometry . BytesPerPage ; SpareBytesPerPage = InstancePtr -> Geometry . SpareBytesPerPage ; EccSteps = InstancePtr -> EccConfig . NumSteps ; EccCode = & InstancePtr -> EccCode [ 0 ] ; EccCalc = & InstancePtr -> EccCalc [ 0 ] ; XNandPs_ReadBuf ( InstancePtr , Ptr , ( BytesPerPage - XNANDPS_AXI_DATA_WIDTH ) ) ; Ptr += ( BytesPerPage - XNANDPS_AXI_DATA_WIDTH ) ; DataPhaseAddr = InstancePtr -> DataPhaseAddr ; DataPhaseAddr |= XNANDPS_ECC_LAST ; InstancePtr -> DataPhaseAddr = DataPhaseAddr ; XNandPs_ReadBuf ( InstancePtr , Ptr , XNANDPS_AXI_DATA_WIDTH ) ; Ptr = DstPtr ; Status = XNandPs_EccCalculate ( InstancePtr , EccCalc ) ; if ( Status != XST_SUCCESS ) { return Status ; } DataPhaseAddr = InstancePtr -> DataPhaseAddr ; DataPhaseAddr &= ~ XNANDPS_ECC_LAST ; InstancePtr -> DataPhaseAddr = DataPhaseAddr ; XNandPs_ReadBuf ( InstancePtr , SparePtr , ( SpareBytesPerPage - XNANDPS_AXI_DATA_WIDTH ) ) ; DataPhaseAddr = InstancePtr -> DataPhaseAddr ; DataPhaseAddr |= XNANDPS_CLR_CS ; InstancePtr -> DataPhaseAddr = DataPhaseAddr ; SparePtr += ( SpareBytesPerPage - XNANDPS_AXI_DATA_WIDTH ) ; XNandPs_ReadBuf ( InstancePtr , SparePtr , XNANDPS_AXI_DATA_WIDTH ) ; EccPos = & InstancePtr -> EccConfig . EccPos [ 0 ] ; for ( Index = 0 ; Index < InstancePtr -> EccConfig . TotalBytes ; Index ++ ) { EccCode [ Index ] = ~ ( InstancePtr -> SpareBufPtr [ EccPos [ Index ] ] ) ; } EccOffset = 0 ; for ( ; EccSteps ; EccSteps -- ) { Status = XNandPs_EccCorrect ( DstPtr , & EccCalc [ EccOffset ] , & EccCode [ EccOffset ] ) ; if ( Status != XST_SUCCESS ) { return Status ; } DstPtr += InstancePtr -> EccConfig . BlockSize ; EccOffset += InstancePtr -> EccConfig . BytesPerBlock ; } return XST_SUCCESS ; }
This function reads a specific page from NAND device using HW ECC block.
This function reads a specific page from NAND device using HW ECC block .
/*
	 * Read page sized bytes in one less AXI data width
	 */ /*
	 * Set the ECC Last bit
	 */ /*
	 * Read transaction with ECC enabled
	 */ /*
	 * Calculate the hardware ECC
	 */ /*
	 * Clear chip select for last AXI transaction
	 */ /*
	 * Read the stored ECC code
	 */ /*
	 * Check for ECC errors
	 */