XilinxProcessorIPLib/drivers/nandps/src/xnandps.c
int XNandPs_ReadCache(XNandPs *InstancePtr, u64 Offset, u32 Length,
			void *DestPtr, u8 *UserSparePtr)
{
	u32 Page;
	u32 Col;
	u32 PartialBytes;
	u32 NumOfBytes;
	int Status;
	u32 PartialPageRead = 0;
	u32 CopyOffset;
	u8 *BufPtr;
	u8 *Ptr = (u8 *)DestPtr;
	u32 NumPages;
	u32 EccConfig = 0;

	Xil_AssertNonvoid(InstancePtr != NULL);
	Xil_AssertNonvoid(DestPtr != NULL);
	Xil_AssertNonvoid((Offset + Length) < InstancePtr->Geometry.DeviceSize);
	Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY);
	Xil_AssertNonvoid(Length != 0);

	/*
	 * Check if the flash supports read cache
	 */
	if (!InstancePtr->Features.ReadCache) {
		return XNandPs_Read(InstancePtr, Offset, Length, DestPtr,
							UserSparePtr);
	}

	Page = (u32) (Offset/InstancePtr->Geometry.BytesPerPage);
	Col = (u32) (Offset & (InstancePtr->Geometry.BytesPerPage - 1));
	PartialBytes = InstancePtr->Geometry.BytesPerPage - Col;
	NumOfBytes = (PartialBytes < Length) ? PartialBytes:Length;
	CopyOffset = InstancePtr->Geometry.BytesPerPage - PartialBytes;
	/*
	 * Calculate number of pages to read
	 */
	NumPages = Length/InstancePtr->Geometry.BytesPerPage;
	NumPages += (Length % InstancePtr->Geometry.BytesPerPage) ? 1:0;
	/*
	 * Read, Read Cache start, Read Cache end
	 */
	if (NumPages <= 1) {
		return XNandPs_Read(InstancePtr, Offset, Length, DestPtr,
							UserSparePtr);
	}

	/*
	 * Change ECC commands in ECC registers for page cache support
	 */
	EccConfig |= ONFI_CMD_PAGE_CACHE_PROGRAM1;
	EccConfig |= ONFI_CMD_READ_CACHE_ENHANCED1 << 8;
	EccConfig |= ONFI_CMD_READ_CACHE_ENHANCED2 << 16;
	EccConfig |= (XNANDPS_ECC_MEMCOMMAND1_RD_CMD_END_VALID_MASK);
	XNandPs_EccSetMemCmd1(InstancePtr, EccConfig);

	/*
	 * Send the ONFI Read command
	 */
	XNandPs_SendCommand(InstancePtr, &OnfiCommands[READ], Page, 0);

	/*
	 * Poll the Memory controller status register
	 */
	while (XNandPs_IsBusy(InstancePtr) == TRUE) {
	}

	/*
	 * Clear the interrupt condition
	 */
	XNandPs_WriteReg((InstancePtr->Config.SmcBase +
				XNANDPS_MEMC_CLR_CONFIG_OFFSET),
			XNANDPS_MEMC_CLR_CONFIG_INT_CLR1_MASK);

	/*
	 * Check ONFI Status Register
	 */
	Status = Onfi_CmdReadStatus(InstancePtr);
	if (Status & ONFI_STATUS_FAIL) {
		return XST_FAILURE;
	}

	while (Length && (NumPages > 0)) {
		/*
		 * Check if partial read
		 */
		if (NumOfBytes < InstancePtr->Geometry.BytesPerPage) {
			BufPtr = &InstancePtr->DataBuf[0];
			PartialPageRead = 1;
		} else {
			BufPtr = (u8 *)Ptr;
			PartialPageRead = 0;
		}

		/* Increment the page */
		Page++;

		if (NumPages <= 1) {
			/*
			 * Change ECC commands in ECC registers to check
			 * change read column for ECC calculation
			 */
			EccConfig = 0;
			EccConfig |= ONFI_CMD_PAGE_CACHE_PROGRAM1;
			EccConfig |= ONFI_CMD_CHANGE_READ_COLUMN1 << 8;
			EccConfig |= ONFI_CMD_CHANGE_READ_COLUMN2 << 16;
			EccConfig |=
				XNANDPS_ECC_MEMCOMMAND1_RD_CMD_END_VALID_MASK;
			XNandPs_EccSetMemCmd1(InstancePtr, EccConfig);

			/*
			 * Send NAND page cache end command 0x3F
			 */
			XNandPs_SendCommand(InstancePtr,
					&OnfiCommands[READ_CACHE_END_SEQ],
					XNANDPS_PAGE_NOT_VALID,
					XNANDPS_COLUMN_NOT_VALID);
		} else {
			XNandPs_SendCommand(InstancePtr,
					&OnfiCommands[READ_CACHE_RANDOM],
					Page, 0);
		}

		/*
		 * Poll the Memory controller status register
		 */
		while (XNandPs_IsBusy(InstancePtr) == TRUE) {
		}

		/*
		 * Clear the interrupt condition
		 */
		XNandPs_WriteReg((InstancePtr->Config.SmcBase +
					XNANDPS_MEMC_CLR_CONFIG_OFFSET),
				XNANDPS_MEMC_CLR_CONFIG_INT_CLR1_MASK);

		if (NumPages <= 1) {
			XNandPs_SendCommand(InstancePtr,
					&OnfiCommands[CHANGE_READ_COLUMN],
					XNANDPS_PAGE_NOT_VALID,
					0);
		}

		/*
		 *  Read the page data
		 */
		Status = InstancePtr->ReadPage(InstancePtr, BufPtr);
		if (Status != XST_SUCCESS) {
			return Status;
		}

		/*
		 * Fill the partial data in the buffer
		 */
		if (PartialPageRead) {
			memcpy(Ptr, BufPtr + CopyOffset, NumOfBytes);
		}

		Ptr += NumOfBytes;
		Length -= NumOfBytes;
		NumPages--;
		NumOfBytes = (Length > InstancePtr->Geometry.BytesPerPage) ?
				InstancePtr->Geometry.BytesPerPage:Length;
		CopyOffset = 0;
	}

	/*
	 * Copy the spare data to user spare buffer
	 */
	if (UserSparePtr) {
		memcpy(UserSparePtr, InstancePtr->SpareBufPtr,
				InstancePtr->Geometry.SpareBytesPerPage);
	}

	return XST_SUCCESS;
}
/*****************************************************************************/
/**
*
* This function reads the data from the Flash device using read page cache
* command and copies it into the specified user buffer.
* It doesn't check for the bad blocks while reading the flash pages that
* cross block boundary. User must take care of handling bad blocks.
*
* @param	InstancePtr is the pointer to the XNandPs instance.
* @param	Offset is the flash data address to read from.
* @param	Length is number of bytes to read.
* @param	DestPtr is the destination address to copy data to.
* @param	UserSparePtr is the user buffer to which spare data must be
*		copied.
*
* @return
*		- XST_SUCCESS if successful.
*		- XST_FAILURE if fail.
*
* @note		This function reads sequential pages from the Flash device.
*
******************************************************************************/
This function reads the data from the Flash device using read page cache
command and copies it into the specified user buffer.
It doesn't check for the bad blocks while reading the flash pages that
cross block boundary. User must take care of handling bad blocks.
This function reads the data from the Flash device using read page cache command and copies it into the specified user buffer . It doesn ' t check for the bad blocks while reading the flash pages that cross block boundary . User must take care of handling bad blocks .
int XNandPs_ReadCache(XNandPs *InstancePtr, u64 Offset, u32 Length,
			void *DestPtr, u8 *UserSparePtr)
{
	u32 Page;
	u32 Col;
	u32 PartialBytes;
	u32 NumOfBytes;
	int Status;
	u32 PartialPageRead = 0;
	u32 CopyOffset;
	u8 *BufPtr;
	u8 *Ptr = (u8 *)DestPtr;
	u32 NumPages;
	u32 EccConfig = 0;
	Xil_AssertNonvoid(InstancePtr != NULL);
	Xil_AssertNonvoid(DestPtr != NULL);
	Xil_AssertNonvoid((Offset + Length) < InstancePtr->Geometry.DeviceSize);
	Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY);
	Xil_AssertNonvoid(Length != 0);
	if (!InstancePtr->Features.ReadCache) {
		return XNandPs_Read(InstancePtr, Offset, Length, DestPtr,
							UserSparePtr);
	}
	Page = (u32) (Offset/InstancePtr->Geometry.BytesPerPage);
	Col = (u32) (Offset & (InstancePtr->Geometry.BytesPerPage - 1));
	PartialBytes = InstancePtr->Geometry.BytesPerPage - Col;
	NumOfBytes = (PartialBytes < Length) ? PartialBytes:Length;
	CopyOffset = InstancePtr->Geometry.BytesPerPage - PartialBytes;
	NumPages = Length/InstancePtr->Geometry.BytesPerPage;
	NumPages += (Length % InstancePtr->Geometry.BytesPerPage) ? 1:0;
	if (NumPages <= 1) {
		return XNandPs_Read(InstancePtr, Offset, Length, DestPtr,
							UserSparePtr);
	}
	EccConfig |= ONFI_CMD_PAGE_CACHE_PROGRAM1;
	EccConfig |= ONFI_CMD_READ_CACHE_ENHANCED1 << 8;
	EccConfig |= ONFI_CMD_READ_CACHE_ENHANCED2 << 16;
	EccConfig |= (XNANDPS_ECC_MEMCOMMAND1_RD_CMD_END_VALID_MASK);
	XNandPs_EccSetMemCmd1(InstancePtr, EccConfig);
	XNandPs_SendCommand(InstancePtr, &OnfiCommands[READ], Page, 0);
	while (XNandPs_IsBusy(InstancePtr) == TRUE) {
	}
	XNandPs_WriteReg((InstancePtr->Config.SmcBase +
				XNANDPS_MEMC_CLR_CONFIG_OFFSET),
			XNANDPS_MEMC_CLR_CONFIG_INT_CLR1_MASK);
	Status = Onfi_CmdReadStatus(InstancePtr);
	if (Status & ONFI_STATUS_FAIL) {
		return XST_FAILURE;
	}
	while (Length && (NumPages > 0)) {
		if (NumOfBytes < InstancePtr->Geometry.BytesPerPage) {
			BufPtr = &InstancePtr->DataBuf[0];
			PartialPageRead = 1;
		} else {
			BufPtr = (u8 *)Ptr;
			PartialPageRead = 0;
		}
		Page++;
		if (NumPages <= 1) {
			EccConfig = 0;
			EccConfig |= ONFI_CMD_PAGE_CACHE_PROGRAM1;
			EccConfig |= ONFI_CMD_CHANGE_READ_COLUMN1 << 8;
			EccConfig |= ONFI_CMD_CHANGE_READ_COLUMN2 << 16;
			EccConfig |=
				XNANDPS_ECC_MEMCOMMAND1_RD_CMD_END_VALID_MASK;
			XNandPs_EccSetMemCmd1(InstancePtr, EccConfig);
			XNandPs_SendCommand(InstancePtr,
					&OnfiCommands[READ_CACHE_END_SEQ],
					XNANDPS_PAGE_NOT_VALID,
					XNANDPS_COLUMN_NOT_VALID);
		} else {
			XNandPs_SendCommand(InstancePtr,
					&OnfiCommands[READ_CACHE_RANDOM],
					Page, 0);
		}
		while (XNandPs_IsBusy(InstancePtr) == TRUE) {
		}
		XNandPs_WriteReg((InstancePtr->Config.SmcBase +
					XNANDPS_MEMC_CLR_CONFIG_OFFSET),
				XNANDPS_MEMC_CLR_CONFIG_INT_CLR1_MASK);
		if (NumPages <= 1) {
			XNandPs_SendCommand(InstancePtr,
					&OnfiCommands[CHANGE_READ_COLUMN],
					XNANDPS_PAGE_NOT_VALID,
					0);
		}
		Status = InstancePtr->ReadPage(InstancePtr, BufPtr);
		if (Status != XST_SUCCESS) {
			return Status;
		}
		if (PartialPageRead) {
			memcpy(Ptr, BufPtr + CopyOffset, NumOfBytes);
		}
		Ptr += NumOfBytes;
		Length -= NumOfBytes;
		NumPages--;
		NumOfBytes = (Length > InstancePtr->Geometry.BytesPerPage) ?
				InstancePtr->Geometry.BytesPerPage:Length;
		CopyOffset = 0;
	}
	if (UserSparePtr) {
		memcpy(UserSparePtr, InstancePtr->SpareBufPtr,
				InstancePtr->Geometry.SpareBytesPerPage);
	}
	return XST_SUCCESS;
}
int XNandPs_ReadCache ( XNandPs * InstancePtr , u64 Offset , u32 Length , void * DestPtr , u8 * UserSparePtr ) { u32 Page ; u32 Col ; u32 PartialBytes ; u32 NumOfBytes ; int Status ; u32 PartialPageRead = 0 ; u32 CopyOffset ; u8 * BufPtr ; u8 * Ptr = ( u8 * ) DestPtr ; u32 NumPages ; u32 EccConfig = 0 ; Xil_AssertNonvoid ( InstancePtr != NULL ) ; Xil_AssertNonvoid ( DestPtr != NULL ) ; Xil_AssertNonvoid ( ( Offset + Length ) < InstancePtr -> Geometry . DeviceSize ) ; Xil_AssertNonvoid ( InstancePtr -> IsReady == XIL_COMPONENT_IS_READY ) ; Xil_AssertNonvoid ( Length != 0 ) ; if ( ! InstancePtr -> Features . ReadCache ) { return XNandPs_Read ( InstancePtr , Offset , Length , DestPtr , UserSparePtr ) ; } Page = ( u32 ) ( Offset / InstancePtr -> Geometry . BytesPerPage ) ; Col = ( u32 ) ( Offset & ( InstancePtr -> Geometry . BytesPerPage - 1 ) ) ; PartialBytes = InstancePtr -> Geometry . BytesPerPage - Col ; NumOfBytes = ( PartialBytes < Length ) ? PartialBytes : Length ; CopyOffset = InstancePtr -> Geometry . BytesPerPage - PartialBytes ; NumPages = Length / InstancePtr -> Geometry . BytesPerPage ; NumPages += ( Length % InstancePtr -> Geometry . BytesPerPage ) ? 1 : 0 ; if ( NumPages <= 1 ) { return XNandPs_Read ( InstancePtr , Offset , Length , DestPtr , UserSparePtr ) ; } EccConfig |= ONFI_CMD_PAGE_CACHE_PROGRAM1 ; EccConfig |= ONFI_CMD_READ_CACHE_ENHANCED1 << 8 ; EccConfig |= ONFI_CMD_READ_CACHE_ENHANCED2 << 16 ; EccConfig |= ( XNANDPS_ECC_MEMCOMMAND1_RD_CMD_END_VALID_MASK ) ; XNandPs_EccSetMemCmd1 ( InstancePtr , EccConfig ) ; XNandPs_SendCommand ( InstancePtr , & OnfiCommands [ READ ] , Page , 0 ) ; while ( XNandPs_IsBusy ( InstancePtr ) == TRUE ) { } XNandPs_WriteReg ( ( InstancePtr -> Config . SmcBase + XNANDPS_MEMC_CLR_CONFIG_OFFSET ) , XNANDPS_MEMC_CLR_CONFIG_INT_CLR1_MASK ) ; Status = Onfi_CmdReadStatus ( InstancePtr ) ; if ( Status & ONFI_STATUS_FAIL ) { return XST_FAILURE ; } while ( Length && ( NumPages > 0 ) ) { if ( NumOfBytes < InstancePtr -> Geometry . BytesPerPage ) { BufPtr = & InstancePtr -> DataBuf [ 0 ] ; PartialPageRead = 1 ; } else { BufPtr = ( u8 * ) Ptr ; PartialPageRead = 0 ; } Page ++ ; if ( NumPages <= 1 ) { EccConfig = 0 ; EccConfig |= ONFI_CMD_PAGE_CACHE_PROGRAM1 ; EccConfig |= ONFI_CMD_CHANGE_READ_COLUMN1 << 8 ; EccConfig |= ONFI_CMD_CHANGE_READ_COLUMN2 << 16 ; EccConfig |= XNANDPS_ECC_MEMCOMMAND1_RD_CMD_END_VALID_MASK ; XNandPs_EccSetMemCmd1 ( InstancePtr , EccConfig ) ; XNandPs_SendCommand ( InstancePtr , & OnfiCommands [ READ_CACHE_END_SEQ ] , XNANDPS_PAGE_NOT_VALID , XNANDPS_COLUMN_NOT_VALID ) ; } else { XNandPs_SendCommand ( InstancePtr , & OnfiCommands [ READ_CACHE_RANDOM ] , Page , 0 ) ; } while ( XNandPs_IsBusy ( InstancePtr ) == TRUE ) { } XNandPs_WriteReg ( ( InstancePtr -> Config . SmcBase + XNANDPS_MEMC_CLR_CONFIG_OFFSET ) , XNANDPS_MEMC_CLR_CONFIG_INT_CLR1_MASK ) ; if ( NumPages <= 1 ) { XNandPs_SendCommand ( InstancePtr , & OnfiCommands [ CHANGE_READ_COLUMN ] , XNANDPS_PAGE_NOT_VALID , 0 ) ; } Status = InstancePtr -> ReadPage ( InstancePtr , BufPtr ) ; if ( Status != XST_SUCCESS ) { return Status ; } if ( PartialPageRead ) { memcpy ( Ptr , BufPtr + CopyOffset , NumOfBytes ) ; } Ptr += NumOfBytes ; Length -= NumOfBytes ; NumPages -- ; NumOfBytes = ( Length > InstancePtr -> Geometry . BytesPerPage ) ? InstancePtr -> Geometry . BytesPerPage : Length ; CopyOffset = 0 ; } if ( UserSparePtr ) { memcpy ( UserSparePtr , InstancePtr -> SpareBufPtr , InstancePtr -> Geometry . SpareBytesPerPage ) ; } return XST_SUCCESS ; }
This function reads the data from the Flash device using read page cache
command and copies it into the specified user buffer.
This function reads the data from the Flash device using read page cache command and copies it into the specified user buffer .
/*
	 * Check if the flash supports read cache
	 */ /*
	 * Calculate number of pages to read
	 */ /*
	 * Read, Read Cache start, Read Cache end
	 */ /*
	 * Change ECC commands in ECC registers for page cache support
	 */ /*
	 * Send the ONFI Read command
	 */ /*
	 * Poll the Memory controller status register
	 */ /*
	 * Clear the interrupt condition
	 */ /*
	 * Check ONFI Status Register
	 */ /*
		 * Check if partial read
		 */ /* Increment the page */ /*
			 * Change ECC commands in ECC registers to check
			 * change read column for ECC calculation
			 */ /*
			 * Send NAND page cache end command 0x3F
			 */ /*
		 * Poll the Memory controller status register
		 */ /*
		 * Clear the interrupt condition
		 */ /*
		 *  Read the page data
		 */ /*
		 * Fill the partial data in the buffer
		 */ /*
	 * Copy the spare data to user spare buffer
	 */