XilinxProcessorIPLib/drivers/nandps/src/xnandps_onfi.c
int Onfi_NandInit(XNandPs *InstancePtr)
{
	u32 Target;
	int Status;
	u8 Id[ONFI_ID_LEN];
	u8 JedecId[2];
	u8 EccSetFeature[4] = {0x08, 0x00, 0x00, 0x00};
	u8 EccGetFeature[4];
	OnfiNand_Geometry Nand_Geometry;

	Xil_AssertNonvoid(InstancePtr != NULL);

	for(Target=0; Target < XNANDPS_MAX_TARGETS; Target++) {
		/*
		 * Reset the target
		 */
		Onfi_CmdReset(InstancePtr);

		/*
		 * Read the ONFI ID
		 */
		Onfi_CmdReadId(InstancePtr, 0x20);
		Onfi_ReadData(InstancePtr, &Id[0], ONFI_ID_LEN);

		/*
		 * Check the ONFI signature to know that the target supports
		 * ONFI
		 */
		if (Id[0]=='O' && Id[1]=='N' && Id[2]=='F' && Id[3]=='I') {
			/* Read the parameter page structure */
			Status = Onfi_ReadParamPage(InstancePtr,
					(u8 *)&Nand_Geometry);
			if (Status != XST_FAILURE) {
				if (Nand_Geometry.BytesPerPage > XNANDPS_MAX_PAGE_SIZE ||
					Nand_Geometry.SpareBytesPerPage > XNANDPS_MAX_SPARE_SIZE ||
					Nand_Geometry.PagesPerBlock > XNANDPS_MAX_PAGES_PER_BLOCK ||
					Nand_Geometry.BlocksPerLun > XNANDPS_MAX_BLOCKS ||
					Nand_Geometry.NumLuns > XNANDPS_MAX_LUNS) {
					return XST_FAILURE;
				}

				InstancePtr->Geometry.NumLun =
					Nand_Geometry.NumLuns;
				InstancePtr->Geometry.PagesPerBlock =
					Nand_Geometry.PagesPerBlock;
				InstancePtr->Geometry.SpareBytesPerPage =
					Nand_Geometry.SpareBytesPerPage;
				InstancePtr->Geometry.BytesPerPage =
					Nand_Geometry.BytesPerPage;
				InstancePtr->Geometry.BlocksPerLun =
					Nand_Geometry.BlocksPerLun;
				InstancePtr->Geometry.NumBlocks =
					(Nand_Geometry.NumLuns *
					 InstancePtr->Geometry.BlocksPerLun);
				InstancePtr->Geometry.NumPages =
					(Nand_Geometry.NumLuns *
					 Nand_Geometry.BlocksPerLun *
					 Nand_Geometry.PagesPerBlock);
				InstancePtr->Geometry.BlockSize =
					 (Nand_Geometry.PagesPerBlock *
					 Nand_Geometry.BytesPerPage);
				InstancePtr->Geometry.DeviceSize =
					(InstancePtr->Geometry.NumBlocks *
					 InstancePtr->Geometry.PagesPerBlock *
					 InstancePtr->Geometry.BytesPerPage);
				/*
				 * Calculate the address cycles
				 */
				InstancePtr->Geometry.RowAddrCycles =
					(Nand_Geometry.AddrCycles & 0xf);
				InstancePtr->Geometry.ColAddrCycles =
					((Nand_Geometry.AddrCycles >> 4) & 0xf);

				OnfiCommands[READ].AddrCycles =
						(InstancePtr->Geometry.RowAddrCycles +
						InstancePtr->Geometry.ColAddrCycles);

				OnfiCommands[PAGE_PROGRAM].AddrCycles =
						(InstancePtr->Geometry.RowAddrCycles +
						InstancePtr->Geometry.ColAddrCycles);

				OnfiCommands[BLOCK_ERASE].AddrCycles =
						InstancePtr->Geometry.RowAddrCycles;

				OnfiCommands[CHANGE_READ_COLUMN].AddrCycles =
						InstancePtr->Geometry.ColAddrCycles;

				OnfiCommands[CHANGE_WRITE_COLUMN].AddrCycles =
						InstancePtr->Geometry.ColAddrCycles;
				/*
				 * Read JEDEC ID
				 */
				Onfi_CmdReadId(InstancePtr, 0x00);
				Onfi_ReadData(InstancePtr, &JedecId[0], 2);

				if ((JedecId[0] == 0x2C) &&
						/* 1 Gb flash devices */
						((JedecId[1] == 0xF1) ||
						(JedecId[1] == 0xA1) ||
						(JedecId[1] == 0xB1) ||
						/* 2 Gb flash devices */
						(JedecId[1] == 0xAA) ||
						(JedecId[1] == 0xBA) ||
						(JedecId[1] == 0xDA) ||
						(JedecId[1] == 0xCA) ||
						/* 4 Gb flash devices */
						(JedecId[1] == 0xAC) ||
						(JedecId[1] == 0xBC) ||
						(JedecId[1] == 0xDC) ||
						(JedecId[1] == 0xCC) ||
						/* 8 Gb flash devices */
						(JedecId[1] == 0xA3) ||
						(JedecId[1] == 0xB3) ||
						(JedecId[1] == 0xD3) ||
						(JedecId[1] == 0xC3))) {
					/*
					 * Check if this flash supports On-Die ECC.
					 * Micron Flash: MT29F1G08ABADA, MT29F1G08ABBDA
					 *		 MT29F1G16ABBDA,
					 *		 MT29F2G08ABBEA, MT29F2G16ABBEA,
					 *		 MT29F2G08ABAEA, MT29F2G16ABAEA,
					 *		 MT29F4G08ABBDA, MT29F4G16ABBDA,
					 *		 MT29F4G08ABADA, MT29F4G16ABADA,
					 *		 MT29F8G08ADBDA, MT29F8G16ADBDA,
					 *		 MT29F8G08ADADA, MT29F8G16ADADA
					 */

					Onfi_SetFeature(InstancePtr, 0x90,
								&EccSetFeature[0]);
					/* Check to see if ECC feature is set */
					Onfi_GetFeature(InstancePtr, 0x90,
								&EccGetFeature[0]);
					if (EccGetFeature[0] & 0x08) {
						InstancePtr->EccMode = XNANDPS_ECC_ONDIE;
					} else {
						InstancePtr->EccMode = XNANDPS_ECC_HW;
					}
				} else if (Nand_Geometry.BytesPerPage < 512 ||
					Nand_Geometry.BytesPerPage > 2048) {
					/*
					 * This controller doesn't support ECC for
					 * page size < 512 & > 2048 bytes.
					 */
					InstancePtr->EccMode = XNANDPS_ECC_NONE;
				} else {
					/* SMC controller ECC (1-bit correction) */
					InstancePtr->EccMode = XNANDPS_ECC_HW;
				}
				/*
				 * Updating the instance flash width after checking
				 * for on-die ECC
				 */
				InstancePtr->Geometry.FlashWidth =
					(Nand_Geometry.Features & 0x1) ?
						XNANDPS_FLASH_WIDTH_16 :
						XNANDPS_FLASH_WIDTH_8;
				/*
				 * Features and Optional commands supported.
				 * On-Die ECC flash doesn't support these
				 * commands when ECC is enabled.
				 */
				if (InstancePtr->EccMode != XNANDPS_ECC_ONDIE) {
					InstancePtr->Features.ProgramCache =
						(Nand_Geometry.OptionalCmds & 0x1) ? 1:0;
					InstancePtr->Features.ReadCache =
						(Nand_Geometry.OptionalCmds & 0x2) ? 1:0;
				}
			} else {
				return XST_FAILURE;
			}
		} else {
			return XST_FAILURE;
		}
	}

	return XST_SUCCESS;
}
/**************************************************************************/
/**
*
* This function initializes the NAND flash and gets the geometry information.
*
* @param	InstancePtr is a pointer to the XNandPs instance.
*
* @return
*		- XST_SUCCESS if successful.
*		- XST_FAILURE if failed.
*
* @note		None
*
***************************************************************************/
This function initializes the NAND flash and gets the geometry information.
This function initializes the NAND flash and gets the geometry information .
int Onfi_NandInit(XNandPs *InstancePtr)
{
	u32 Target;
	int Status;
	u8 Id[ONFI_ID_LEN];
	u8 JedecId[2];
	u8 EccSetFeature[4] = {0x08, 0x00, 0x00, 0x00};
	u8 EccGetFeature[4];
	OnfiNand_Geometry Nand_Geometry;
	Xil_AssertNonvoid(InstancePtr != NULL);
	for(Target=0; Target < XNANDPS_MAX_TARGETS; Target++) {
		Onfi_CmdReset(InstancePtr);
		Onfi_CmdReadId(InstancePtr, 0x20);
		Onfi_ReadData(InstancePtr, &Id[0], ONFI_ID_LEN);
		if (Id[0]=='O' && Id[1]=='N' && Id[2]=='F' && Id[3]=='I') {
			Status = Onfi_ReadParamPage(InstancePtr,
					(u8 *)&Nand_Geometry);
			if (Status != XST_FAILURE) {
				if (Nand_Geometry.BytesPerPage > XNANDPS_MAX_PAGE_SIZE ||
					Nand_Geometry.SpareBytesPerPage > XNANDPS_MAX_SPARE_SIZE ||
					Nand_Geometry.PagesPerBlock > XNANDPS_MAX_PAGES_PER_BLOCK ||
					Nand_Geometry.BlocksPerLun > XNANDPS_MAX_BLOCKS ||
					Nand_Geometry.NumLuns > XNANDPS_MAX_LUNS) {
					return XST_FAILURE;
				}
				InstancePtr->Geometry.NumLun =
					Nand_Geometry.NumLuns;
				InstancePtr->Geometry.PagesPerBlock =
					Nand_Geometry.PagesPerBlock;
				InstancePtr->Geometry.SpareBytesPerPage =
					Nand_Geometry.SpareBytesPerPage;
				InstancePtr->Geometry.BytesPerPage =
					Nand_Geometry.BytesPerPage;
				InstancePtr->Geometry.BlocksPerLun =
					Nand_Geometry.BlocksPerLun;
				InstancePtr->Geometry.NumBlocks =
					(Nand_Geometry.NumLuns *
					 InstancePtr->Geometry.BlocksPerLun);
				InstancePtr->Geometry.NumPages =
					(Nand_Geometry.NumLuns *
					 Nand_Geometry.BlocksPerLun *
					 Nand_Geometry.PagesPerBlock);
				InstancePtr->Geometry.BlockSize =
					 (Nand_Geometry.PagesPerBlock *
					 Nand_Geometry.BytesPerPage);
				InstancePtr->Geometry.DeviceSize =
					(InstancePtr->Geometry.NumBlocks *
					 InstancePtr->Geometry.PagesPerBlock *
					 InstancePtr->Geometry.BytesPerPage);
				InstancePtr->Geometry.RowAddrCycles =
					(Nand_Geometry.AddrCycles & 0xf);
				InstancePtr->Geometry.ColAddrCycles =
					((Nand_Geometry.AddrCycles >> 4) & 0xf);
				OnfiCommands[READ].AddrCycles =
						(InstancePtr->Geometry.RowAddrCycles +
						InstancePtr->Geometry.ColAddrCycles);
				OnfiCommands[PAGE_PROGRAM].AddrCycles =
						(InstancePtr->Geometry.RowAddrCycles +
						InstancePtr->Geometry.ColAddrCycles);
				OnfiCommands[BLOCK_ERASE].AddrCycles =
						InstancePtr->Geometry.RowAddrCycles;
				OnfiCommands[CHANGE_READ_COLUMN].AddrCycles =
						InstancePtr->Geometry.ColAddrCycles;
				OnfiCommands[CHANGE_WRITE_COLUMN].AddrCycles =
						InstancePtr->Geometry.ColAddrCycles;
				Onfi_CmdReadId(InstancePtr, 0x00);
				Onfi_ReadData(InstancePtr, &JedecId[0], 2);
				if ((JedecId[0] == 0x2C) &&
						((JedecId[1] == 0xF1) ||
						(JedecId[1] == 0xA1) ||
						(JedecId[1] == 0xB1) ||
						(JedecId[1] == 0xAA) ||
						(JedecId[1] == 0xBA) ||
						(JedecId[1] == 0xDA) ||
						(JedecId[1] == 0xCA) ||
						(JedecId[1] == 0xAC) ||
						(JedecId[1] == 0xBC) ||
						(JedecId[1] == 0xDC) ||
						(JedecId[1] == 0xCC) ||
						(JedecId[1] == 0xA3) ||
						(JedecId[1] == 0xB3) ||
						(JedecId[1] == 0xD3) ||
						(JedecId[1] == 0xC3))) {
					Onfi_SetFeature(InstancePtr, 0x90,
								&EccSetFeature[0]);
					Onfi_GetFeature(InstancePtr, 0x90,
								&EccGetFeature[0]);
					if (EccGetFeature[0] & 0x08) {
						InstancePtr->EccMode = XNANDPS_ECC_ONDIE;
					} else {
						InstancePtr->EccMode = XNANDPS_ECC_HW;
					}
				} else if (Nand_Geometry.BytesPerPage < 512 ||
					Nand_Geometry.BytesPerPage > 2048) {
					InstancePtr->EccMode = XNANDPS_ECC_NONE;
				} else {
					InstancePtr->EccMode = XNANDPS_ECC_HW;
				}
				InstancePtr->Geometry.FlashWidth =
					(Nand_Geometry.Features & 0x1) ?
						XNANDPS_FLASH_WIDTH_16 :
						XNANDPS_FLASH_WIDTH_8;
				if (InstancePtr->EccMode != XNANDPS_ECC_ONDIE) {
					InstancePtr->Features.ProgramCache =
						(Nand_Geometry.OptionalCmds & 0x1) ? 1:0;
					InstancePtr->Features.ReadCache =
						(Nand_Geometry.OptionalCmds & 0x2) ? 1:0;
				}
			} else {
				return XST_FAILURE;
			}
		} else {
			return XST_FAILURE;
		}
	}
	return XST_SUCCESS;
}
int Onfi_NandInit ( XNandPs * InstancePtr ) { u32 Target ; int Status ; u8 Id [ ONFI_ID_LEN ] ; u8 JedecId [ 2 ] ; u8 EccSetFeature [ 4 ] = { 0x08 , 0x00 , 0x00 , 0x00 } ; u8 EccGetFeature [ 4 ] ; OnfiNand_Geometry Nand_Geometry ; Xil_AssertNonvoid ( InstancePtr != NULL ) ; for ( Target = 0 ; Target < XNANDPS_MAX_TARGETS ; Target ++ ) { Onfi_CmdReset ( InstancePtr ) ; Onfi_CmdReadId ( InstancePtr , 0x20 ) ; Onfi_ReadData ( InstancePtr , & Id [ 0 ] , ONFI_ID_LEN ) ; if ( Id [ 0 ] == ' ' && Id [ 1 ] == ' ' && Id [ 2 ] == ' ' && Id [ 3 ] == ' ' ) { Status = Onfi_ReadParamPage ( InstancePtr , ( u8 * ) & Nand_Geometry ) ; if ( Status != XST_FAILURE ) { if ( Nand_Geometry . BytesPerPage > XNANDPS_MAX_PAGE_SIZE || Nand_Geometry . SpareBytesPerPage > XNANDPS_MAX_SPARE_SIZE || Nand_Geometry . PagesPerBlock > XNANDPS_MAX_PAGES_PER_BLOCK || Nand_Geometry . BlocksPerLun > XNANDPS_MAX_BLOCKS || Nand_Geometry . NumLuns > XNANDPS_MAX_LUNS ) { return XST_FAILURE ; } InstancePtr -> Geometry . NumLun = Nand_Geometry . NumLuns ; InstancePtr -> Geometry . PagesPerBlock = Nand_Geometry . PagesPerBlock ; InstancePtr -> Geometry . SpareBytesPerPage = Nand_Geometry . SpareBytesPerPage ; InstancePtr -> Geometry . BytesPerPage = Nand_Geometry . BytesPerPage ; InstancePtr -> Geometry . BlocksPerLun = Nand_Geometry . BlocksPerLun ; InstancePtr -> Geometry . NumBlocks = ( Nand_Geometry . NumLuns * InstancePtr -> Geometry . BlocksPerLun ) ; InstancePtr -> Geometry . NumPages = ( Nand_Geometry . NumLuns * Nand_Geometry . BlocksPerLun * Nand_Geometry . PagesPerBlock ) ; InstancePtr -> Geometry . BlockSize = ( Nand_Geometry . PagesPerBlock * Nand_Geometry . BytesPerPage ) ; InstancePtr -> Geometry . DeviceSize = ( InstancePtr -> Geometry . NumBlocks * InstancePtr -> Geometry . PagesPerBlock * InstancePtr -> Geometry . BytesPerPage ) ; InstancePtr -> Geometry . RowAddrCycles = ( Nand_Geometry . AddrCycles & 0xf ) ; InstancePtr -> Geometry . ColAddrCycles = ( ( Nand_Geometry . AddrCycles >> 4 ) & 0xf ) ; OnfiCommands [ READ ] . AddrCycles = ( InstancePtr -> Geometry . RowAddrCycles + InstancePtr -> Geometry . ColAddrCycles ) ; OnfiCommands [ PAGE_PROGRAM ] . AddrCycles = ( InstancePtr -> Geometry . RowAddrCycles + InstancePtr -> Geometry . ColAddrCycles ) ; OnfiCommands [ BLOCK_ERASE ] . AddrCycles = InstancePtr -> Geometry . RowAddrCycles ; OnfiCommands [ CHANGE_READ_COLUMN ] . AddrCycles = InstancePtr -> Geometry . ColAddrCycles ; OnfiCommands [ CHANGE_WRITE_COLUMN ] . AddrCycles = InstancePtr -> Geometry . ColAddrCycles ; Onfi_CmdReadId ( InstancePtr , 0x00 ) ; Onfi_ReadData ( InstancePtr , & JedecId [ 0 ] , 2 ) ; if ( ( JedecId [ 0 ] == 0x2C ) && ( ( JedecId [ 1 ] == 0xF1 ) || ( JedecId [ 1 ] == 0xA1 ) || ( JedecId [ 1 ] == 0xB1 ) || ( JedecId [ 1 ] == 0xAA ) || ( JedecId [ 1 ] == 0xBA ) || ( JedecId [ 1 ] == 0xDA ) || ( JedecId [ 1 ] == 0xCA ) || ( JedecId [ 1 ] == 0xAC ) || ( JedecId [ 1 ] == 0xBC ) || ( JedecId [ 1 ] == 0xDC ) || ( JedecId [ 1 ] == 0xCC ) || ( JedecId [ 1 ] == 0xA3 ) || ( JedecId [ 1 ] == 0xB3 ) || ( JedecId [ 1 ] == 0xD3 ) || ( JedecId [ 1 ] == 0xC3 ) ) ) { Onfi_SetFeature ( InstancePtr , 0x90 , & EccSetFeature [ 0 ] ) ; Onfi_GetFeature ( InstancePtr , 0x90 , & EccGetFeature [ 0 ] ) ; if ( EccGetFeature [ 0 ] & 0x08 ) { InstancePtr -> EccMode = XNANDPS_ECC_ONDIE ; } else { InstancePtr -> EccMode = XNANDPS_ECC_HW ; } } else if ( Nand_Geometry . BytesPerPage < 512 || Nand_Geometry . BytesPerPage > 2048 ) { InstancePtr -> EccMode = XNANDPS_ECC_NONE ; } else { InstancePtr -> EccMode = XNANDPS_ECC_HW ; } InstancePtr -> Geometry . FlashWidth = ( Nand_Geometry . Features & 0x1 ) ? XNANDPS_FLASH_WIDTH_16 : XNANDPS_FLASH_WIDTH_8 ; if ( InstancePtr -> EccMode != XNANDPS_ECC_ONDIE ) { InstancePtr -> Features . ProgramCache = ( Nand_Geometry . OptionalCmds & 0x1 ) ? 1 : 0 ; InstancePtr -> Features . ReadCache = ( Nand_Geometry . OptionalCmds & 0x2 ) ? 1 : 0 ; } } else { return XST_FAILURE ; } } else { return XST_FAILURE ; } } return XST_SUCCESS ; }
This function initializes the NAND flash and gets the geometry information.
This function initializes the NAND flash and gets the geometry information .
/*
		 * Reset the target
		 */ /*
		 * Read the ONFI ID
		 */ /*
		 * Check the ONFI signature to know that the target supports
		 * ONFI
		 */ /* Read the parameter page structure */ /*
				 * Calculate the address cycles
				 */ /*
				 * Read JEDEC ID
				 */ /* 1 Gb flash devices */ /* 2 Gb flash devices */ /* 4 Gb flash devices */ /* 8 Gb flash devices */ /*
					 * Check if this flash supports On-Die ECC.
					 * Micron Flash: MT29F1G08ABADA, MT29F1G08ABBDA
					 *		 MT29F1G16ABBDA,
					 *		 MT29F2G08ABBEA, MT29F2G16ABBEA,
					 *		 MT29F2G08ABAEA, MT29F2G16ABAEA,
					 *		 MT29F4G08ABBDA, MT29F4G16ABBDA,
					 *		 MT29F4G08ABADA, MT29F4G16ABADA,
					 *		 MT29F8G08ADBDA, MT29F8G16ADBDA,
					 *		 MT29F8G08ADADA, MT29F8G16ADADA
					 */ /* Check to see if ECC feature is set */ /*
					 * This controller doesn't support ECC for
					 * page size < 512 & > 2048 bytes.
					 */ /* SMC controller ECC (1-bit correction) */ /*
				 * Updating the instance flash width after checking
				 * for on-die ECC
				 */ /*
				 * Features and Optional commands supported.
				 * On-Die ECC flash doesn't support these
				 * commands when ECC is enabled.
				 */