
Added initial support Xilinx Embedded Software. Signed-off-by: Jagannadha Sutradharudu Teki <jaganna@xilinx.com>
654 lines
19 KiB
C
Executable file
654 lines
19 KiB
C
Executable file
/******************************************************************************
|
|
*
|
|
* Copyright (C) 2009 - 2014 Xilinx, Inc. All rights reserved.
|
|
*
|
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
* of this software and associated documentation files (the "Software"), to deal
|
|
* in the Software without restriction, including without limitation the rights
|
|
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
* copies of the Software, and to permit persons to whom the Software is
|
|
* furnished to do so, subject to the following conditions:
|
|
*
|
|
* The above copyright notice and this permission notice shall be included in
|
|
* all copies or substantial portions of the Software.
|
|
*
|
|
* Use of the Software is limited solely to applications:
|
|
* (a) running on a Xilinx device, or
|
|
* (b) that interact with a Xilinx device through a bus or interconnect.
|
|
*
|
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
* XILINX CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
|
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
|
|
* OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
* SOFTWARE.
|
|
*
|
|
* Except as contained in this notice, the name of the Xilinx shall not be used
|
|
* in advertising or otherwise to promote the sale, use or other dealings in
|
|
* this Software without prior written authorization from Xilinx.
|
|
*
|
|
******************************************************************************/
|
|
/*****************************************************************************/
|
|
/**
|
|
*
|
|
* @file xnandps_onfi.c
|
|
*
|
|
* This module implements the ONFI specific commands.
|
|
* See xnandps_onfi.h for more information.
|
|
*
|
|
* @note None
|
|
*
|
|
* <pre>
|
|
* MODIFICATION HISTORY:
|
|
*
|
|
* Ver Who Date Changes
|
|
* ----- ---- ---------- -----------------------------------------------
|
|
* 1.00a nm 12/10/2010 First release
|
|
* 1.01a nm 28/02/2012 Added support for 8Gb On-Die ECC NAND flash
|
|
* parts (CR 648463).
|
|
* Fixed 16-bit issue with ONFI commands like
|
|
* read, write and read status command.
|
|
* 1.03a nm 10/22/2012 Fixed CR# 673348.
|
|
* 1.04a nm 04/25/2013 Implemented PR# 699544. Added page cache read
|
|
* and program commands to ONFI command list.
|
|
* Reading the cache features during read param page.
|
|
* </pre>
|
|
*
|
|
******************************************************************************/
|
|
|
|
/***************************** Include Files *********************************/
|
|
#include "xnandps_onfi.h"
|
|
|
|
/************************** Constant Definitions *****************************/
|
|
|
|
/**************************** Type Definitions *******************************/
|
|
|
|
/***************** Macros (Inline Functions) Definitions *********************/
|
|
|
|
/************************** Function Prototypes ******************************/
|
|
static void Onfi_ReadData(XNandPs *InstancePtr, u8 *Buf, u32 Length);
|
|
|
|
static void Onfi_CmdReset(XNandPs *InstancePtr);
|
|
|
|
static void Onfi_CmdReadId(XNandPs *InstancePtr, u8 Address);
|
|
|
|
static void Onfi_CmdReadParamPage(XNandPs *InstancePtr);
|
|
|
|
static unsigned long Onfi_Crc16(u8 *Buf);
|
|
|
|
static int Onfi_ReadParamPage(XNandPs *InstancePtr, u8 *Buf);
|
|
|
|
extern void XNandPs_SendCommand(XNandPs *InstancePtr, XNandPs_CommandFormat
|
|
*Command, int Page, int Column);
|
|
/************************** Variable Definitions *****************************/
|
|
|
|
/**
|
|
* This structure defines the onfi command format sent to the flash.
|
|
*/
|
|
XNandPs_CommandFormat OnfiCommands[] = {
|
|
{ONFI_CMD_READ1, ONFI_CMD_READ2, 5, XNANDPS_CMD_PHASE},
|
|
/*<< Read command format */
|
|
{ONFI_CMD_CHANGE_READ_COLUMN1, ONFI_CMD_CHANGE_READ_COLUMN2,
|
|
2, XNANDPS_CMD_PHASE}, /*<< Change Read column format */
|
|
{ONFI_CMD_BLOCK_ERASE1, ONFI_CMD_BLOCK_ERASE2, 3, XNANDPS_CMD_PHASE},
|
|
/*<<Block Erase command format */
|
|
{ONFI_CMD_READ_STATUS, XNANDPS_END_CMD_NONE, 0,
|
|
XNANDPS_END_CMD_INVALID},
|
|
/*<< Read Status command format */
|
|
{ONFI_CMD_PAGE_PROG1, ONFI_CMD_PAGE_PROG2, 5, XNANDPS_DATA_PHASE},
|
|
/*<< Page program command format */
|
|
{ONFI_CMD_CHANGE_WRITE_COLUMN, XNANDPS_END_CMD_NONE, 2,
|
|
XNANDPS_END_CMD_INVALID}, /*<< Change Write Column
|
|
command format */
|
|
{ONFI_CMD_READ_ID, XNANDPS_END_CMD_NONE, 1, XNANDPS_END_CMD_INVALID},
|
|
/*<< Read ID command format */
|
|
{ONFI_CMD_READ_PARAM_PAGE, XNANDPS_END_CMD_NONE, 1,
|
|
XNANDPS_END_CMD_INVALID},
|
|
/*<< Read Param Page command format */
|
|
{ONFI_CMD_RESET, XNANDPS_END_CMD_NONE, 0, XNANDPS_END_CMD_INVALID},
|
|
/*<< Reset command format */
|
|
{ONFI_CMD_GET_FEATURES, XNANDPS_END_CMD_NONE, 1,
|
|
XNANDPS_END_CMD_INVALID},
|
|
/*<< Get Features */
|
|
{ONFI_CMD_SET_FEATURES, XNANDPS_END_CMD_NONE, 1,
|
|
XNANDPS_END_CMD_INVALID},
|
|
/*<< Set Features */
|
|
{ONFI_CMD_READ_CACHE_ENHANCED1, ONFI_CMD_READ_CACHE_ENHANCED2, 5,
|
|
XNANDPS_CMD_PHASE},
|
|
/*<< Read page cache random */
|
|
{ONFI_CMD_READ_CACHE_END, XNANDPS_END_CMD_NONE, 0,
|
|
XNANDPS_END_CMD_INVALID},
|
|
/*<< Read page cache end */
|
|
{ONFI_CMD_PAGE_CACHE_PROGRAM1, ONFI_CMD_PAGE_CACHE_PROGRAM2, 5,
|
|
XNANDPS_DATA_PHASE},
|
|
/*<< Program page cache */
|
|
};
|
|
|
|
/**************************************************************************/
|
|
/**
|
|
*
|
|
* This function reads the data from flash. It is used for reading the control
|
|
* information from flash like ID and Parameter page.
|
|
*
|
|
* @param InstancePtr is a pointer to the XNandPs instance.
|
|
* @param Buf is the buffer pointer to read the data.
|
|
* @param Length is the length of data to read.
|
|
*
|
|
* @return None
|
|
*
|
|
* @note None
|
|
*
|
|
***************************************************************************/
|
|
static void Onfi_ReadData(XNandPs *InstancePtr, u8 *Buf, u32 Length)
|
|
{
|
|
u32 Index;
|
|
|
|
/*
|
|
* 8-bit/16-bit access for basic read operations
|
|
*/
|
|
for(Index = 0; Index < Length; Index++) {
|
|
|
|
if (InstancePtr->Config.FlashWidth == XNANDPS_FLASH_WIDTH_16)
|
|
Buf[Index] = (u8)Xil_In16(InstancePtr->DataPhaseAddr);
|
|
else
|
|
Buf[Index] = Xil_In8(InstancePtr->DataPhaseAddr);
|
|
}
|
|
}
|
|
|
|
/**************************************************************************/
|
|
/**
|
|
*
|
|
* This function writes command data to flash. It is used for writing the
|
|
* control information like set features.
|
|
*
|
|
* @param InstancePtr is a pointer to the XNandPs instance.
|
|
* @param Buf is the buffer pointer to write the data.
|
|
* @param Length is the length of data to write.
|
|
*
|
|
* @return None
|
|
*
|
|
* @note None
|
|
*
|
|
***************************************************************************/
|
|
static void Onfi_WriteData(XNandPs *InstancePtr, u8 *Buf, u32 Length)
|
|
{
|
|
u32 Index;
|
|
|
|
/*
|
|
* 8-bit/16-bit access for basic write operations
|
|
*/
|
|
for(Index = 0; Index < Length; Index++) {
|
|
if (InstancePtr->Config.FlashWidth == XNANDPS_FLASH_WIDTH_16)
|
|
Xil_Out16(InstancePtr->DataPhaseAddr, Buf[Index]);
|
|
else
|
|
Xil_Out8(InstancePtr->DataPhaseAddr, Buf[Index]);
|
|
}
|
|
}
|
|
|
|
/**************************************************************************/
|
|
/**
|
|
*
|
|
* This function sends read status command to the flash device.
|
|
*
|
|
* @param InstancePtr is a pointer to the XNandPs instance.
|
|
*
|
|
* @return flash status value read
|
|
*
|
|
* @note None
|
|
*
|
|
***************************************************************************/
|
|
u8 Onfi_CmdReadStatus(XNandPs *InstancePtr)
|
|
{
|
|
u8 Status;
|
|
|
|
XNandPs_SendCommand(InstancePtr, &OnfiCommands[READ_STATUS],
|
|
XNANDPS_PAGE_NOT_VALID, XNANDPS_COLUMN_NOT_VALID);
|
|
|
|
if(InstancePtr->Config.FlashWidth == XNANDPS_FLASH_WIDTH_16)
|
|
Status = (u8) Xil_In16(InstancePtr->DataPhaseAddr);
|
|
else
|
|
Status = Xil_In8(InstancePtr->DataPhaseAddr);
|
|
|
|
return Status;
|
|
}
|
|
|
|
/**************************************************************************/
|
|
/**
|
|
*
|
|
* This function sends reset command to the flash device.
|
|
*
|
|
* @param InstancePtr is a pointer to the XNandPs instance.
|
|
*
|
|
* @return None
|
|
*
|
|
* @note None
|
|
*
|
|
***************************************************************************/
|
|
static void Onfi_CmdReset(XNandPs *InstancePtr)
|
|
{
|
|
u8 Status;
|
|
|
|
XNandPs_SendCommand(InstancePtr, &OnfiCommands[RESET],
|
|
XNANDPS_PAGE_NOT_VALID, XNANDPS_COLUMN_NOT_VALID);
|
|
|
|
/*
|
|
* Check the Status Register SR[6]
|
|
*/
|
|
do {
|
|
Status = Onfi_CmdReadStatus(InstancePtr);
|
|
}while ((Status & ONFI_STATUS_RDY) != ONFI_STATUS_RDY);
|
|
}
|
|
|
|
/**************************************************************************/
|
|
/**
|
|
*
|
|
* This function sends read ID command to the flash device.
|
|
*
|
|
* @param InstancePtr is a pointer to the XNandPs instance.
|
|
*
|
|
* @return None
|
|
*
|
|
* @note None
|
|
*
|
|
***************************************************************************/
|
|
static void Onfi_CmdReadId(XNandPs *InstancePtr, u8 Address)
|
|
{
|
|
XNandPs_SendCommand(InstancePtr, &OnfiCommands[READ_ID],
|
|
XNANDPS_PAGE_NOT_VALID, Address);
|
|
}
|
|
|
|
/**************************************************************************/
|
|
/**
|
|
*
|
|
* This function sends read parameter page command to the flash device.
|
|
*
|
|
* @param InstancePtr is a pointer to the XNandPs instance.
|
|
*
|
|
* @return None
|
|
*
|
|
* @note None
|
|
*
|
|
***************************************************************************/
|
|
static void Onfi_CmdReadParamPage(XNandPs *InstancePtr)
|
|
{
|
|
u8 Status;
|
|
u32 ZeroCommand;
|
|
|
|
XNandPs_SendCommand(InstancePtr, &OnfiCommands[READ_PARAM_PAGE],
|
|
XNANDPS_PAGE_NOT_VALID, 0x00);
|
|
/*
|
|
* Check the Status Register SR[6]
|
|
*/
|
|
do {
|
|
Status = Onfi_CmdReadStatus(InstancePtr);
|
|
}while ((Status & ONFI_STATUS_RDY) != ONFI_STATUS_RDY);
|
|
|
|
/*
|
|
* ONFI : Reissue the 0x00 on the command line to start reading data
|
|
*/
|
|
ZeroCommand = InstancePtr->Config.FlashBase |
|
|
(0 << XNANDPS_ADDR_CYCLES_SHIFT)|
|
|
(0 << XNANDPS_END_CMD_VALID_SHIFT)|
|
|
(XNANDPS_COMMAND_PHASE_MASK)|
|
|
(0 << XNANDPS_END_CMD_SHIFT)|
|
|
(0 << XNANDPS_START_CMD_SHIFT);
|
|
|
|
/*
|
|
* Dummy AXI transaction for sending command 0x00 to the flash
|
|
*/
|
|
Xil_Out32(ZeroCommand, 0x0);
|
|
}
|
|
|
|
/**************************************************************************/
|
|
/**
|
|
*
|
|
* This function sends Get Feature command to the flash device.
|
|
*
|
|
* @param InstancePtr is a pointer to the XNandPs instance.
|
|
* @param Feature is the feature value to read.
|
|
*
|
|
* @return None
|
|
*
|
|
* @note None
|
|
*
|
|
***************************************************************************/
|
|
static void Onfi_GetFeature(XNandPs *InstancePtr, u8 Feature, u8 *Val)
|
|
{
|
|
u8 Status;
|
|
u32 ZeroCommand;
|
|
|
|
XNandPs_SendCommand(InstancePtr, &OnfiCommands[GET_FEATURES],
|
|
XNANDPS_PAGE_NOT_VALID, Feature);
|
|
/*
|
|
* Check the Status Register SR[6]
|
|
*/
|
|
do {
|
|
Status = Onfi_CmdReadStatus(InstancePtr);
|
|
}while ((Status & ONFI_STATUS_RDY) != ONFI_STATUS_RDY);
|
|
|
|
/*
|
|
* ONFI 2.3: Reissue the 0x00 on the command line to start reading
|
|
* data.
|
|
*/
|
|
ZeroCommand = InstancePtr->Config.FlashBase |
|
|
(0 << XNANDPS_ADDR_CYCLES_SHIFT)|
|
|
(0 << XNANDPS_END_CMD_VALID_SHIFT)|
|
|
(XNANDPS_COMMAND_PHASE_MASK)|
|
|
(0 << XNANDPS_END_CMD_SHIFT)|
|
|
(0 << XNANDPS_START_CMD_SHIFT);
|
|
|
|
/*
|
|
* Dummy AXI transaction for sending command 0x00 to the flash
|
|
*/
|
|
Xil_Out32(ZeroCommand, 0x00);
|
|
|
|
/*
|
|
* Read the feature value
|
|
*/
|
|
Onfi_ReadData(InstancePtr, Val, 4);
|
|
}
|
|
|
|
/**************************************************************************/
|
|
/**
|
|
*
|
|
* This function sends Set Feature command to the flash device.
|
|
*
|
|
* @param InstancePtr is a pointer to the XNandPs instance.
|
|
* @param Feature is the feature value to Set.
|
|
*
|
|
* @return None
|
|
*
|
|
* @note None
|
|
*
|
|
***************************************************************************/
|
|
static void Onfi_SetFeature(XNandPs *InstancePtr, u8 Feature, u8 *Val)
|
|
{
|
|
u8 Status;
|
|
|
|
XNandPs_SendCommand(InstancePtr, &OnfiCommands[SET_FEATURES],
|
|
XNANDPS_PAGE_NOT_VALID, Feature);
|
|
|
|
Onfi_WriteData(InstancePtr, Val, 4);
|
|
|
|
/*
|
|
* Check the Status Register SR[6]
|
|
*/
|
|
do {
|
|
Status = Onfi_CmdReadStatus(InstancePtr);
|
|
}while ((Status & ONFI_STATUS_RDY) != ONFI_STATUS_RDY);
|
|
}
|
|
|
|
/**************************************************************************/
|
|
/**
|
|
*
|
|
* This function calculates the CRC on the parameter page buffer. This is taken
|
|
* from the ONFI 1.0 specification.
|
|
*
|
|
* @param Buf is the parameter page buffer.
|
|
*
|
|
* @return CRC value calculated.
|
|
*
|
|
* @note None
|
|
*
|
|
***************************************************************************/
|
|
static unsigned long Onfi_Crc16(u8 *Buf)
|
|
{
|
|
const int Order = ONFI_CRC_ORDER;
|
|
const unsigned long Polynom = ONFI_CRC_POLYNOM;
|
|
u32 Crc = ONFI_CRC_INIT;
|
|
u32 Index;
|
|
u32 j;
|
|
u32 c;
|
|
u32 Bit;
|
|
u32 DataIn;
|
|
int DataByteCount = 0;
|
|
u32 CrcMask = ((((u32)1 << (Order - 1)) -1) << 1) | 1;
|
|
u32 CrcHighBit = (u32)1 << (Order - 1);
|
|
|
|
/*
|
|
* CRC covers the data bytes between byte 0 and byte 253 (ONFI 1.0, sec
|
|
* 5.4.1.36)
|
|
*/
|
|
for(Index = 0; Index < ONFI_CRC_LEN; Index++)
|
|
{
|
|
DataIn = Buf[Index];
|
|
c = (u32)DataIn;
|
|
DataByteCount++;
|
|
for(j = 0x80; j; j >>= 1) {
|
|
Bit = Crc & CrcHighBit;
|
|
Crc <<= 1;
|
|
if (c & j) Bit ^= CrcHighBit;
|
|
if (Bit) Crc ^= Polynom;
|
|
}
|
|
Crc &= CrcMask;
|
|
}
|
|
return Crc;
|
|
}
|
|
|
|
/**************************************************************************/
|
|
/**
|
|
*
|
|
* This function reads the NAND flash parameter page defined by ONFI 1.0
|
|
* specfication.
|
|
*
|
|
* @param InstancePtr is a pointer to the XNandPs instance.
|
|
* @param Buf is a buffer pointer to fill the data.
|
|
*
|
|
* @return
|
|
* - XST_SUCCESS if parameter page read successfully.
|
|
* - XST_FAILURE if parameter page is not read successfully.
|
|
*
|
|
* @note None
|
|
*
|
|
***************************************************************************/
|
|
static int Onfi_ReadParamPage(XNandPs *InstancePtr, u8 *Buf)
|
|
{
|
|
u32 Index;
|
|
u32 CrcCalc;
|
|
OnfiNand_Geometry *Geometry;
|
|
|
|
/*
|
|
* Read the first 256 bytes of parameter page
|
|
*/
|
|
Onfi_CmdReadParamPage(InstancePtr);
|
|
/* Read the 3 mandatory parameter pages */
|
|
for(Index = 0; Index < 3; Index++) {
|
|
Onfi_ReadData(InstancePtr, Buf, ONFI_PARAM_PAGE_LEN);
|
|
Geometry = (OnfiNand_Geometry *)Buf;
|
|
/* Check the CRC */
|
|
CrcCalc = Onfi_Crc16(Buf);
|
|
if(CrcCalc == Geometry->Crc) {
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (Index == 3) {
|
|
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
|
|
*
|
|
***************************************************************************/
|
|
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) {
|
|
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;
|
|
}
|