nandps_v2_2: Deprecated exiting version of nandps driver, Added new version.

Deprecated existing version v2_1, Added new version V2_2.

Signed-off-by: Shakti Bhatnagar <shaktib@xilinx.com>
This commit is contained in:
Shakti Bhatnagar 2015-02-02 10:21:09 +05:30 committed by Suneel Garapati
parent a84c7db3c2
commit 31c7177fc4
16 changed files with 6506 additions and 0 deletions

View file

@ -0,0 +1,42 @@
###############################################################################
#
# 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.
#
###############################################################################
OPTION psf_version = 2.1;
BEGIN driver nandps
OPTION supported_peripherals = (ps7_nand);
OPTION driver_state = ACTIVE;
OPTION copyfiles = all;
OPTION VERSION = 2.2;
OPTION NAME = nandps;
END driver

View file

@ -0,0 +1,194 @@
###############################################################################
#
# Copyright (C) 2012 - 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.
#
###############################################################################
##############################################################################
#
# Modification History
#
# Ver Who Date Changes
# ----- ---- -------- -----------------------------------------------
# 1.00a sdm 11/22/11 Created
# 2.0 adk 12/10/13 Updated as per the New Tcl API's
#
##############################################################################
#uses "xillib.tcl"
proc generate {drv_handle} {
xdefine_zynq_include_file $drv_handle "xparameters.h" "XNandPs" "NUM_INSTANCES" "DEVICE_ID" "C_S_AXI_BASEADDR" "C_S_AXI_HIGHADDR" "C_NAND_CLK_FREQ_HZ" "C_SMC_BASEADDR" "C_NAND_WIDTH"
xdefine_zynq_config_file $drv_handle "xnandps_g.c" "XNandPs" "DEVICE_ID" "C_SMC_BASEADDR" "C_S_AXI_BASEADDR" "C_NAND_WIDTH"
xdefine_zynq_canonical_xpars $drv_handle "xparameters.h" "XNandPs" "DEVICE_ID" "C_S_AXI_BASEADDR" "C_S_AXI_HIGHADDR" "C_NAND_CLK_FREQ_HZ" "C_SMC_BASEADDR" "C_NAND_WIDTH"
}
#
# Given a list of arguments, define them all in an include file.
# Similar to proc xdefine_include_file, except that uses regsub
# to replace "S_AXI_" with "".
#
proc xdefine_zynq_include_file {drv_handle file_name drv_string args} {
# Open include file
set file_handle [::hsi::utils::open_include_file $file_name]
# Get all peripherals connected to this driver
set periphs [::hsi::utils::get_common_driver_ips $drv_handle]
# Handle special cases
set arg "NUM_INSTANCES"
set posn [lsearch -exact $args $arg]
if {$posn > -1} {
puts $file_handle "/* Definitions for driver [string toupper [common::get_property NAME $drv_handle]] */"
# Define NUM_INSTANCES
puts $file_handle "#define [::hsi::utils::get_driver_param_name $drv_string $arg] [llength $periphs]"
set args [lreplace $args $posn $posn]
}
# Check if it is a driver parameter
lappend newargs
foreach arg $args {
set value [common::get_property CONFIG.$arg $drv_handle]
if {[llength $value] == 0} {
lappend newargs $arg
} else {
puts $file_handle "#define [::hsi::utils::get_driver_param_name $drv_string $arg] [common::get_property CONFIG.$arg $drv_handle]"
}
}
set args $newargs
# Print all parameters for all peripherals
set device_id 0
foreach periph $periphs {
puts $file_handle ""
puts $file_handle "/* Definitions for peripheral [string toupper [common::get_property NAME $periph]] */"
foreach arg $args {
if {[string compare -nocase "DEVICE_ID" $arg] == 0} {
set value $device_id
incr device_id
} elseif {[string compare -nocase "C_SMC_BASEADDR" $arg] == 0} {
set value 0xE000E000
} else {
set value [::hsi::utils::get_param_value $periph $arg]
}
if {[llength $value] == 0} {
set value 0
}
set value [::hsi::utils::format_addr_string $value $arg]
set arg_name [::hsi::utils::get_ip_param_name $periph $arg]
regsub "S_AXI_" $arg_name "" arg_name
if {[string compare -nocase "HW_VER" $arg] == 0} {
puts $file_handle "#define $arg_name \"$value\""
} else {
puts $file_handle "#define $arg_name $value"
}
}
puts $file_handle ""
}
puts $file_handle "\n/******************************************************************/\n"
close $file_handle
}
#-----------------------------------------------------------------------------
# xdefine_zynq_canonical_xpars - Used to print out canonical defines for a driver.
# Similar to proc xdefine_config_file, except that uses regsub to replace "S_AXI_"
# with "".
#-----------------------------------------------------------------------------
proc xdefine_zynq_canonical_xpars {drv_handle file_name drv_string args} {
# Open include file
set file_handle [::hsi::utils::open_include_file $file_name]
# Get all the peripherals connected to this driver
set periphs [::hsi::utils::get_common_driver_ips $drv_handle]
# Get the names of all the peripherals connected to this driver
foreach periph $periphs {
set peripheral_name [string toupper [common::get_property NAME $periph]]
lappend peripherals $peripheral_name
}
# Get possible canonical names for all the peripherals connected to this
# driver
set device_id 0
foreach periph $periphs {
set canonical_name [string toupper [format "%s_%s" $drv_string $device_id]]
lappend canonicals $canonical_name
# Create a list of IDs of the peripherals whose hardware instance name
# doesn't match the canonical name. These IDs can be used later to
# generate canonical definitions
if { [lsearch $peripherals $canonical_name] < 0 } {
lappend indices $device_id
}
incr device_id
}
set i 0
foreach periph $periphs {
set periph_name [string toupper [common::get_property NAME $periph]]
# Generate canonical definitions only for the peripherals whose
# canonical name is not the same as hardware instance name
if { [lsearch $canonicals $periph_name] < 0 } {
puts $file_handle "/* Canonical definitions for peripheral $periph_name */"
set canonical_name [format "%s_%s" $drv_string [lindex $indices $i]]
foreach arg $args {
set lvalue [::hsi::utils::get_driver_param_name $canonical_name $arg]
# replace S_SXI_ with CPU_. This is a temporary fix. Revist when the
# S_AXI_DIST_BASEADDR is generated by the tools
regsub "S_AXI_" $lvalue "CPU_" lvalue
# The commented out rvalue is the name of the instance-specific constant
# set rvalue [::hsi::utils::get_ip_param_name $periph $arg]
# The rvalue set below is the actual value of the parameter
if {[string compare -nocase "C_SMC_BASEADDR" $arg] == 0} {
set rvalue 0xE000E000
} else {
set rvalue [::hsi::utils::get_param_value $periph $arg]
}
if {[llength $rvalue] == 0} {
set rvalue 0
}
set rvalue [::hsi::utils::format_addr_string $rvalue $arg]
puts $file_handle "#define $lvalue $rvalue"
}
puts $file_handle ""
incr i
}
}
puts $file_handle "\n/******************************************************************/\n"
close $file_handle
}

View file

@ -0,0 +1,19 @@
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN">
<html>
<head>
<meta http-equiv="Content-Language" content="en-us">
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Driver example applications</title>
<link rel="stylesheet" type="text/css" href="../help.css">
</head>
<body bgcolor="#FFFFFF">
<h1> Example Applications for the driver nandps_v2_1</h1>
<HR>
<ul>
<li>xnandps_example.c <a href="xnandps_example.c">(source)</a> </li>
<li>xnandps_skip_example.c <a href="xnandps_skip_example.c">(source)</a> </li>
<li>xnandps_cache_example.c <a href="xnandps_cache_example.c">(source)</a> </li>
</ul>
<p><font face="Times New Roman" color="#800000">Copyright <20> 2009-2014 Xilinx, Inc. All rights reserved.</font></p>
</body>
</html>

View file

@ -0,0 +1,258 @@
/******************************************************************************
*
* Copyright (C) 2013 - 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_cache_example.c
**
* This file contains a design example using the NAND driver (XNandPs).
* This example tests NAND page cache read and write commands. The page cache
* commands are not supported by OnDie ECC flash since ECC is enabled by
* default. Tested Spansion S34ML04G100TFI00 flash with this example.
*
* This example tests the block erase, block read and block write features.
* The flash blocks are erased and written. The data is read back and compared
* with the data written for correctness. The bad blocks are not erased/programmed.
*
* @note
*
* None.
*
* <pre>
* MODIFICATION HISTORY:
*
* Ver Who Date Changes
* ----- ---- ---------- -----------------------------------------------
* 1.00 nm 04/25/2013 First release.
*
*</pre>
*
******************************************************************************/
/***************************** Include Files *********************************/
#include <stdio.h>
#include <stdlib.h>
#include <xil_types.h>
#include <xil_printf.h>
#include <xparameters.h>
#include <xnandps.h>
#include <xnandps_bbm.h>
/************************** Constant Definitions *****************************/
/*
* The following constants map to the XPAR parameters created in the
* xparameters.h file. They are defined here such that a user can easily
* change all the needed parameters in one place.
*/
#define NAND_DEVICE_ID XPAR_XNANDPS_0_DEVICE_ID
/* Test parameters */
#define NAND_TEST_START_BLOCK 64 /**< Starting block to test */
#define NAND_TEST_NUM_BLOCKS 16 /**< Number of blocks to test */
#define NAND_TEST_BLOCK_SIZE 0x20000 /**< Test Block Size, must be same as
the flash block size */
/**************************** Type Definitions *******************************/
/***************** Macros (Inline Functions) Definitions *********************/
/************************** Function Prototypes ******************************/
int NandReadWriteCacheExample(u32 NandDeviceId);
/************************** Variable Definitions *****************************/
XNandPs NandInstance; /* XNand Instance. */
XNandPs *NandInstPtr = &NandInstance;
/*
* Buffers used during read and write transactions.
*/
u8 ReadBuffer[NAND_TEST_BLOCK_SIZE]; /**< Block sized Read buffer */
u8 WriteBuffer[NAND_TEST_BLOCK_SIZE]; /**< Block sized write buffer */
/************************** Function Definitions ******************************/
/****************************************************************************/
/**
*
* Main function to execute the Nand Flash read write example.
*
* @param None.
*
* @return
* - XST_SUCCESS if the example has completed successfully.
* - XST_FAILURE if the example has failed.
*
* @note None.
*
*****************************************************************************/
int main(void)
{
int Status;
xil_printf("Nand Flash Read Write Example Test\r\n");
/*
* Run the NAND read write example, specify the Base Address that
* is generated in xparameters.h .
*/
Status = NandReadWriteCacheExample(NAND_DEVICE_ID);
if (Status != XST_SUCCESS) {
xil_printf("Nand Flash Read Write Example Test Failed\r\n");
return XST_FAILURE;
}
xil_printf("Successfully ran Nand Flash Read Write Example Test\r\n");
return XST_SUCCESS;
}
/****************************************************************************/
/**
*
* This function runs a test on the NAND flash device using the basic driver
* functions.
* The function does the following tasks:
* - Initialize the driver.
* - Erase the blocks.
* - Write in to all the blocks.
* - Read back the data from the blocks.
* - Compare the data read against the data Written.
*
* @param NandDeviceId is is the XPAR_<NAND_instance>_DEVICE_ID value
* from xparameters.h.
*
* @return
* - XST_SUCCESS if successful.
* - XST_FAILURE if failed.
*
* @note When bad blocks are encountered, they are not erased and
* programmed.
*
****************************************************************************/
int NandReadWriteCacheExample(u32 NandDeviceId)
{
int Status;
u32 Index;
u32 BlockIndex;
XNandPs_Config *ConfigPtr;
u64 Offset;
u32 Length;
u32 StartBlock;
u32 EndBlock;
/*
* Initialize the flash driver.
*/
ConfigPtr = XNandPs_LookupConfig(NandDeviceId);
if (ConfigPtr == NULL) {
return XST_FAILURE;
}
Status = XNandPs_CfgInitialize(NandInstPtr, ConfigPtr,
ConfigPtr->SmcBase,ConfigPtr->FlashBase);
if (Status != XST_SUCCESS) {
return XST_FAILURE;
}
StartBlock = NAND_TEST_START_BLOCK;
EndBlock = NAND_TEST_START_BLOCK + NAND_TEST_NUM_BLOCKS;
Length = NAND_TEST_BLOCK_SIZE;
/*
* Prepare the write buffer. Fill in the data need to be written into
* Flash Device.
*/
for (Index = 0; Index < Length; Index++) {
WriteBuffer[Index] = Index % 256;
}
/*
* Erase the blocks in the flash
*/
for (BlockIndex = StartBlock; BlockIndex < EndBlock; BlockIndex++) {
/*
* Don't erase bad blocks.
*/
if (XNandPs_IsBlockBad(NandInstPtr, BlockIndex) == XST_SUCCESS)
{
continue;
}
/*
* Perform erase operation.
*/
Status = XNandPs_EraseBlock(NandInstPtr, BlockIndex);
if (Status != XST_SUCCESS) {
return Status;
}
}
/*
* Perform the read/write operation
*/
for (BlockIndex = StartBlock; BlockIndex < EndBlock; BlockIndex++) {
/*
* Don't program bad blocks.
*/
if (XNandPs_IsBlockBad(NandInstPtr, BlockIndex) == XST_SUCCESS)
{
continue;
}
Offset = BlockIndex * NandInstPtr->Geometry.BlockSize;
/*
* Perform the write operation.
*/
Status = XNandPs_WriteCache(NandInstPtr, Offset, Length, WriteBuffer, NULL);
if (Status != XST_SUCCESS) {
return Status;
}
/*
* Perform the read operation.
*/
Status = XNandPs_ReadCache(NandInstPtr, Offset, Length, ReadBuffer, NULL);
if (Status != XST_SUCCESS) {
return Status;
}
/*
* Compare the data read against the data Written.
*/
for (Index = 0; Index < Length; Index++) {
if (ReadBuffer[Index] != WriteBuffer[Index]) {
return XST_FAILURE;
}
}
/*
* Clear the Receive buffer for next iteration
*/
memset(ReadBuffer, 0, Length);
}
return XST_SUCCESS;
}

View file

@ -0,0 +1,255 @@
/******************************************************************************
*
* 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_example.c
**
* This file contains a design example using the NAND driver (XNandPs).
* This example tests the block erase, block read and block write features.
* The flash blocks are erased and written. The data is read back and compared
* with the data written for correctness. The bad blocks are not erased/programmed.
*
* @note
*
* None.
*
* <pre>
* MODIFICATION HISTORY:
*
* Ver Who Date Changes
* ----- ---- ---------- -----------------------------------------------
* 1.00 nm 12/10/2010 First release.
* 1.01a nm 28/02/2012 Modified the test offsets.
*
*</pre>
*
******************************************************************************/
/***************************** Include Files *********************************/
#include <stdio.h>
#include <stdlib.h>
#include <xil_types.h>
#include <xil_printf.h>
#include <xparameters.h>
#include <xnandps.h>
#include <xnandps_bbm.h>
/************************** Constant Definitions *****************************/
/*
* The following constants map to the XPAR parameters created in the
* xparameters.h file. They are defined here such that a user can easily
* change all the needed parameters in one place.
*/
#define NAND_DEVICE_ID XPAR_XNANDPS_0_DEVICE_ID
/* Test parameters */
#define NAND_TEST_START_BLOCK 64 /**< Starting block to test */
#define NAND_TEST_NUM_BLOCKS 16 /**< Number of blocks to test */
#define NAND_TEST_BLOCK_SIZE 0x20000 /**< Test Block Size, must be same as
the flash block size */
/**************************** Type Definitions *******************************/
/***************** Macros (Inline Functions) Definitions *********************/
/************************** Function Prototypes ******************************/
int NandReadWriteExample(u32 NandDeviceId);
/************************** Variable Definitions *****************************/
XNandPs NandInstance; /* XNand Instance. */
XNandPs *NandInstPtr = &NandInstance;
/*
* Buffers used during read and write transactions.
*/
u8 ReadBuffer[NAND_TEST_BLOCK_SIZE]; /**< Block sized Read buffer */
u8 WriteBuffer[NAND_TEST_BLOCK_SIZE]; /**< Block sized write buffer */
/************************** Function Definitions ******************************/
/****************************************************************************/
/**
*
* Main function to execute the Nand Flash read write example.
*
* @param None.
*
* @return
* - XST_SUCCESS if the example has completed successfully.
* - XST_FAILURE if the example has failed.
*
* @note None.
*
*****************************************************************************/
int main(void)
{
int Status;
xil_printf("Nand Flash Read Write Example Test\r\n");
/*
* Run the NAND read write example, specify the Base Address that
* is generated in xparameters.h .
*/
Status = NandReadWriteExample(NAND_DEVICE_ID);
if (Status != XST_SUCCESS) {
xil_printf("Nand Flash Read Write Example Test Failed\r\n");
return XST_FAILURE;
}
xil_printf("Successfully ran Nand Flash Read Write Example Test\r\n");
return XST_SUCCESS;
}
/****************************************************************************/
/**
*
* This function runs a test on the NAND flash device using the basic driver
* functions.
* The function does the following tasks:
* - Initialize the driver.
* - Erase the blocks.
* - Write in to all the blocks.
* - Read back the data from the blocks.
* - Compare the data read against the data Written.
*
* @param NandDeviceId is is the XPAR_<NAND_instance>_DEVICE_ID value
* from xparameters.h.
*
* @return
* - XST_SUCCESS if successful.
* - XST_FAILURE if failed.
*
* @note When bad blocks are encountered, they are not erased and
* programmed.
*
****************************************************************************/
int NandReadWriteExample(u32 NandDeviceId)
{
int Status;
u32 Index;
u32 BlockIndex;
XNandPs_Config *ConfigPtr;
u64 Offset;
u32 Length;
u32 StartBlock;
u32 EndBlock;
/*
* Initialize the flash driver.
*/
ConfigPtr = XNandPs_LookupConfig(NandDeviceId);
if (ConfigPtr == NULL) {
return XST_FAILURE;
}
Status = XNandPs_CfgInitialize(NandInstPtr, ConfigPtr,
ConfigPtr->SmcBase,ConfigPtr->FlashBase);
if (Status != XST_SUCCESS) {
return XST_FAILURE;
}
StartBlock = NAND_TEST_START_BLOCK;
EndBlock = NAND_TEST_START_BLOCK + NAND_TEST_NUM_BLOCKS;
Length = NAND_TEST_BLOCK_SIZE;
/*
* Prepare the write buffer. Fill in the data need to be written into
* Flash Device.
*/
for (Index = 0; Index < Length; Index++) {
WriteBuffer[Index] = Index % 256;
}
/*
* Erase the blocks in the flash
*/
for (BlockIndex = StartBlock; BlockIndex < EndBlock; BlockIndex++) {
/*
* Don't erase bad blocks.
*/
if (XNandPs_IsBlockBad(NandInstPtr, BlockIndex) == XST_SUCCESS)
{
continue;
}
/*
* Perform erase operation.
*/
Status = XNandPs_EraseBlock(NandInstPtr, BlockIndex);
if (Status != XST_SUCCESS) {
return Status;
}
}
/*
* Perform the read/write operation
*/
for (BlockIndex = StartBlock; BlockIndex < EndBlock; BlockIndex++) {
/*
* Don't program bad blocks.
*/
if (XNandPs_IsBlockBad(NandInstPtr, BlockIndex) == XST_SUCCESS)
{
continue;
}
Offset = BlockIndex * NandInstPtr->Geometry.BlockSize;
/*
* Perform the write operation.
*/
Status = XNandPs_Write(NandInstPtr, Offset, Length, WriteBuffer, NULL);
if (Status != XST_SUCCESS) {
return Status;
}
/*
* Perform the read operation.
*/
Status = XNandPs_Read(NandInstPtr, Offset, Length, ReadBuffer, NULL);
if (Status != XST_SUCCESS) {
return Status;
}
/*
* Compare the data read against the data Written.
*/
for (Index = 0; Index < Length; Index++) {
if (ReadBuffer[Index] != WriteBuffer[Index]) {
return XST_FAILURE;
}
}
/*
* Clear the Receive buffer for next iteration
*/
memset(ReadBuffer, 0, Length);
}
return XST_SUCCESS;
}

View file

@ -0,0 +1,514 @@
/******************************************************************************
*
* 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_skip_example.c
**
* This file contains a design example using the NAND driver (XNandPs).
* This example tests the skip block method of erase/read/write operations.
* The skip block method is useful while reading/writing images on to the flash.
* The flash is erased and programming by considering the bad blocks. The data is
* read back and compared with the data written for correctness.
*
* @note
*
* None.
*
* <pre>
* MODIFICATION HISTORY:
*
* Ver Who Date Changes
* ----- ---- ---------- -----------------------------------------------
* 1.00 nm 12/10/2010 First release
* 1.01a nm 28/02/2012 Modified the test offsets.
*
*</pre>
*
******************************************************************************/
/***************************** Include Files *********************************/
#include <stdio.h>
#include <stdlib.h>
#include <xil_types.h>
#include <xil_printf.h>
#include <xparameters.h>
#include <xnandps.h>
#include <xnandps_bbm.h>
/************************** Constant Definitions *****************************/
/*
* The following constants map to the XPAR parameters created in the
* xparameters.h file. They are defined here such that a user can easily
* change all the needed parameters in one place.
*/
#define NAND_DEVICE_ID XPAR_XNANDPS_0_DEVICE_ID
/* Test parameters */
#define NAND_TEST_OFFSET 0x01000000 /**< Flash Test Offset */
#define NAND_TEST_LENGTH 0x00080000 /**< Test Length */
/**************************** Type Definitions *******************************/
/***************** Macros (Inline Functions) Definitions *********************/
/************************** Function Prototypes ******************************/
int NandSkipBlockExample(u32 NandDeviceId);
int XNandPs_SkipRead(XNandPs *InstancePtr, u64 Offset, u32 Length, void
*DestPtr);
int XNandPs_SkipWrite(XNandPs *InstancePtr, u64 Offset, u32 Length, void
*SrcPtr);
int XNandPs_SkipErase(XNandPs *InstancePtr, u64 Offset, u32 Length);
/************************** Variable Definitions *****************************/
XNandPs NandInstance; /* XNand Instance. */
XNandPs *NandInstPtr = &NandInstance;
/*
* Buffers used during read and write transactions.
*/
u8 ReadBuffer[NAND_TEST_LENGTH];
u8 WriteBuffer[NAND_TEST_LENGTH];
/************************** Function Definitions ******************************/
/****************************************************************************/
/**
*
* Main function to execute the Skip Block based Nand read/write example.
*
* @param None.
*
* @return
* - XST_SUCCESS if the example has completed successfully.
* - XST_FAILURE if the example has failed.
*
* @note None.
*
*****************************************************************************/
int main(void)
{
int Status;
xil_printf("Nand Flash Skip Block Method Example Test\r\n");
/*
* Run the NAND read write example, specify the Base Address that
* is generated in xparameters.h .
*/
Status = NandSkipBlockExample(NAND_DEVICE_ID);
if (Status != XST_SUCCESS) {
xil_printf("Nand Flash Skip Block Method Example Test Failed\r\n");
return XST_FAILURE;
}
xil_printf("Successfully ran Nand Flash Skip Block Method Example Test\r\n");
return XST_SUCCESS;
}
/****************************************************************************/
/**
*
* This function runs a test on the NAND flash device using the basic driver
* functions.
* The function does the following tasks:
* - Initialize the driver.
* - Erase the required length of bytes by taking bad blocks into account.
* - Write the number of bytes from given offset by taking bad blocks
* into account.
* - Read the number of bytes from given offset by taking bad blocks
* into account.
* - Compare the data read against the data Written.
*
* @param NandDeviceId is the XPAR_<NAND_instance>_DEVICE_ID value
* from xparameters.h.
*
* @return
* - XST_SUCCESS if successful.
* - XST_FAILURE if failed.
*
* @note None.
*
****************************************************************************/
int NandSkipBlockExample(u32 NandDeviceId)
{
int Status;
u32 Index;
XNandPs_Config *ConfigPtr;
u64 Offset;
u32 Length;
/*
* Initialize the flash driver.
*/
ConfigPtr = XNandPs_LookupConfig(NandDeviceId);
if (ConfigPtr == NULL) {
return XST_FAILURE;
}
Status = XNandPs_CfgInitialize(NandInstPtr, ConfigPtr,
ConfigPtr->SmcBase,ConfigPtr->FlashBase);
if (Status != XST_SUCCESS) {
return XST_FAILURE;
}
Offset = NAND_TEST_OFFSET;
Length = NAND_TEST_LENGTH;
/*
* Prepare the write buffer. Fill in the data need to be written into
* Flash Device.
*/
for (Index = 0; Index < Length; Index++) {
WriteBuffer[Index] = Index % 256;
}
/*
* Erase the blocks using skip block method
*/
Status = XNandPs_SkipErase(NandInstPtr, Offset, Length);
if (Status != XST_SUCCESS) {
return XST_FAILURE;
}
/*
* Write into the flash offset.
*/
Status = XNandPs_SkipWrite(NandInstPtr, Offset, Length, WriteBuffer);
if (Status != XST_SUCCESS) {
return XST_FAILURE;
}
/*
* Read back from the flash.
*/
Status = XNandPs_SkipRead(NandInstPtr, Offset, Length, ReadBuffer);
if (Status != XST_SUCCESS) {
return XST_FAILURE;
}
/*
* Compare the data read against the data Written.
*/
for (Index = 0; Index < Length; Index++) {
if (ReadBuffer[Index] != WriteBuffer[Index]) {
return XST_FAILURE;
}
}
return XST_SUCCESS;
}
/*****************************************************************************/
/**
*
* This function returns the length including bad blocks from a given offset and
* length.
*
* @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.
*
* @return
* - Return actual length including bad blocks.
*
* @note None.
*
******************************************************************************/
u32 XNandPs_CalculateLength(XNandPs *InstancePtr, u64 Offset, u32 Length)
{
u32 BlockSize = InstancePtr->Geometry.BlockSize;
u32 CurBlockLen;
u32 CurBlock;
u32 Status;
u32 TempLen = 0;
u32 ActLen = 0;
while (TempLen < Length) {
CurBlockLen = BlockSize - (Offset & (BlockSize - 1));
CurBlock = (Offset & ~(BlockSize - 1))/BlockSize;
/*
* Check if the block is bad
*/
Status = XNandPs_IsBlockBad(InstancePtr, CurBlock);
if (Status != XST_SUCCESS) {
/* Good Block */
TempLen += CurBlockLen;
}
ActLen += CurBlockLen;
Offset += CurBlockLen;
if (Offset >= InstancePtr->Geometry.DeviceSize) {
break;
}
}
return ActLen;
}
/*****************************************************************************/
/**
*
* This function reads the data from the Flash device and copies it into the
* specified user buffer. This function considers bad blocks and skips them
* to read next 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.
*
* @return
* - XST_SUCCESS if successful.
* - XST_FAILURE if fail.
*
* @note None.
*
******************************************************************************/
int XNandPs_SkipRead(XNandPs *InstancePtr, u64 Offset, u32 Length, void
*DestPtr)
{
u32 ActLen;
u32 BlockOffset;
u32 Block;
u32 Status;
u32 BytesLeft = Length;
u32 BlockSize = InstancePtr->Geometry.BlockSize;
u8 *BufPtr = (u8 *)DestPtr;
u32 ReadLen;
u32 BlockReadLen;
/*
* Calculate the actual length including bad blocks
*/
ActLen = XNandPs_CalculateLength(InstancePtr, Offset, Length);
/*
* Check if the actual length cross flash size
*/
if (Offset + ActLen > InstancePtr->Geometry.DeviceSize) {
return XST_FAILURE;
}
while (BytesLeft > 0) {
BlockOffset = Offset & (BlockSize - 1);
Block = (Offset & ~(BlockSize - 1))/BlockSize;
BlockReadLen = BlockSize - BlockOffset;
Status = XNandPs_IsBlockBad(InstancePtr, Block);
if (Status == XST_SUCCESS) {
/* Move to next block */
Offset += BlockReadLen;
continue;
}
/*
* Check if we cross block boundary
*/
if (BytesLeft < BlockReadLen) {
ReadLen = BytesLeft;
} else {
ReadLen = BlockReadLen;
}
/*
* Read from the NAND flash
*/
Status = XNandPs_Read(InstancePtr, Offset, ReadLen, BufPtr, NULL);
if (Status != XST_SUCCESS) {
return Status;
}
BytesLeft -= ReadLen;
Offset += ReadLen;
BufPtr += ReadLen;
}
return XST_SUCCESS;
}
/*****************************************************************************/
/**
*
* This function programs the flash device(s) with data specified in the user
* buffer. This function considers bad blocks and skips them.
*
* @param InstancePtr is the pointer to the XNandPs instance.
* @param Offset is the flash data address to write to.
* @param Length is number of bytes to write.
* @param SrcPtr is the source address to write the data from.
*
* @return
* - XST_SUCCESS if successful.
* - XST_FAILURE if fail.
*
* @note None.
*
******************************************************************************/
int XNandPs_SkipWrite(XNandPs *InstancePtr, u64 Offset, u32 Length, void
*SrcPtr)
{
u32 ActLen;
u32 BlockOffset;
u32 Block;
u32 Status;
u32 BytesLeft = Length;
u32 BlockSize = InstancePtr->Geometry.BlockSize;
u8 *BufPtr = (u8 *)SrcPtr;
u32 WriteLen;
u32 BlockWriteLen;
/*
* Calculate the actual length including bad blocks
*/
ActLen = XNandPs_CalculateLength(InstancePtr, Offset, Length);
/*
* Check if the actual length cross flash size
*/
if (Offset + ActLen > InstancePtr->Geometry.DeviceSize) {
return XST_FAILURE;
}
while (BytesLeft > 0) {
BlockOffset = Offset & (BlockSize - 1);
Block = (Offset & ~(BlockSize - 1))/BlockSize;
BlockWriteLen = BlockSize - BlockOffset;
/*
* Check if the block is bad
*/
Status = XNandPs_IsBlockBad(InstancePtr, Block);
if (Status == XST_SUCCESS) {
/* Move to next block */
Offset += BlockWriteLen;
continue;
}
/*
* Check if we cross block boundary
*/
if (BytesLeft < BlockWriteLen) {
WriteLen = BytesLeft;
} else {
WriteLen = BlockWriteLen;
}
/*
* Read from the NAND flash
*/
Status = XNandPs_Write(InstancePtr, Offset, WriteLen, BufPtr, NULL);
if (Status != XST_SUCCESS) {
return Status;
}
BytesLeft -= WriteLen;
Offset += WriteLen;
BufPtr += WriteLen;
}
return XST_SUCCESS;
}
/*****************************************************************************/
/**
*
* This function erases length bytes in the flash device from a given offset.
* The Offset and Length must be block aligned. This functions skips bad blocks.
*
* @param InstancePtr is the pointer to the XNand instance.
* @param Offset is the flash address to start erasing from.
* @param Length is number of bytes to erase.
*
* @return
* - XST_SUCCESS if successful.
* - XST_FAILURE if error in erase.
*
* @note None.
*
******************************************************************************/
int XNandPs_SkipErase(XNandPs *InstancePtr, u64 Offset, u32 Length)
{
u32 StartBlock;
u32 NumOfBlocks;
u32 BlockSize;
u32 Block;
int Status;
BlockSize = InstancePtr->Geometry.BlockSize;
/*
* Start address must align on block boundary
*/
if (Offset & (BlockSize - 1)) {
/* Unalinged offset */
return XST_FAILURE;
}
/*
* Length must align on block boundary
*/
if (Length & (BlockSize - 1)) {
/* Length is not block aligned */
return XST_FAILURE;
}
StartBlock = (Offset & ~(BlockSize - 1))/BlockSize;
NumOfBlocks = (Length & ~(BlockSize - 1))/BlockSize;
for (Block = StartBlock; Block < (StartBlock + NumOfBlocks)
; Block++) {
/*
* Check if the block is bad
*/
Status = XNandPs_IsBlockBad(InstancePtr, Block);
if (Status == XST_SUCCESS) {
NumOfBlocks++;
if ((StartBlock + NumOfBlocks) >=
InstancePtr->Geometry.NumBlocks) {
return XST_FAILURE;
}
/* Increase the block count for skip block method */
continue;
}
/*
* Erase the Nand flash block
*/
Status = XNandPs_EraseBlock(InstancePtr, Block);
if (Status == XST_NAND_WRITE_PROTECTED) {
/* Flash is write protected */
return XST_FAILURE;
}
if (Status != XST_SUCCESS) {
/* Erase operation error */
return XST_FAILURE;
}
}
return XST_SUCCESS;
}

View file

@ -0,0 +1,40 @@
COMPILER=
ARCHIVER=
CP=cp
COMPILER_FLAGS=
EXTRA_COMPILER_FLAGS=
LIB=libxil.a
CC_FLAGS = $(COMPILER_FLAGS)
ECC_FLAGS = $(EXTRA_COMPILER_FLAGS)
RELEASEDIR=../../../lib
INCLUDEDIR=../../../include
INCLUDES=-I./. -I${INCLUDEDIR}
OUTS = *.o
LIBSOURCES:=*.c
INCLUDEFILES:=*.h
OBJECTS = $(addsuffix .o, $(basename $(wildcard *.c)))
libs: banner xnandps_libs clean
%.o: %.c
${COMPILER} $(CC_FLAGS) $(ECC_FLAGS) $(INCLUDES) -o $@ $<
banner:
echo "Compiling nandps"
xnandps_libs: ${OBJECTS}
$(ARCHIVER) -r ${RELEASEDIR}/${LIB} ${OBJECTS}
.PHONY: include
include: xnandps_includes
xnandps_includes:
${CP} ${INCLUDEFILES} ${INCLUDEDIR}
clean:
rm -rf ${OBJECTS}

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,447 @@
/******************************************************************************
*
* 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.h
*
* This file implements a driver for the NAND flash controller.
*
* <b>Driver Initialization</b>
*
* The function call XNandPs_CfgInitialize() should be called by the application
* before any other function in the driver. The initialization function takes
* device specific data (like device id, instance id, and base address) and
* initializes the XNandPs instance with the device specific data.
*
* <b>Device Geometry</b>
*
* NAND flash device is memory device and it is segmented into areas called
* Logical Unit(s) (LUN) and further in to blocks and pages. A NAND flash device
* can have multiple LUN. LUN is sequential raw of multiple blocks of the same
* size. A block is the smallest erasable unit of data within the Flash array of
* a LUN. The size of each block is based on a power of 2. There is no
* restriction on the number of blocks within the LUN. A block contains a number
* of pages. A page is the smallest addressable unit for read and program
* operations. The arrangement of LUN, blocks, and pages is referred to by this
* module as the part's geometry.
*
* The cells within the part can be programmed from a logic 1 to a logic 0
* and not the other way around. To change a cell back to a logic 1, the
* entire block containing that cell must be erased. When a block is erased
* all bytes contain the value 0xFF. The number of times a block can be
* erased is finite. Eventually the block will wear out and will no longer
* be capable of erasure. As of this writing, the typical flash block can
* be erased 100,000 or more times.
*
* The jobs done by this driver typically are:
* - 8/16 bit operational mode
* - Read, Write, and Erase operation
* - Read, Write cache operation
* - Read, Write Spare area operation
* - HW Error Check and Correction (ECC)
*
* <b>Write Operation</b>
*
* The write call can be used to write a minimum of one byte and a maximum
* entire flash. If the address offset specified to write is out of flash or if
* the number of bytes specified from the offset exceed flash boundaries
* an error is reported back to the user. The write is blocking in nature in that
* the control is returned back to user only after the write operation is
* completed successfully or an error is reported.
*
* <b>Read Operation</b>
*
* The read call can be used to read a minimum of one byte and maximum of
* entire flash. If the address offset specified to read is out of flash or if
* the number of bytes specified from the offset exceed flash boundaries
* an error is reported back to the user. The read is blocking in nature in that
* the control is returned back to user only after the read operation is
* completed successfully or an error is reported.
*
* <b>Erase Operation</b>
*
* The erase operations are provided to erase a Block in the Flash memory. The
* erase call is blocking in nature in that the control is returned back to user
* only after the erase operation is completed successfully or an error is
* reported.
*
* <b>Page Cache Write Operation</b>
*
* The page cache write call is same as write call except that it uses cache
* commands to write. This enhances the performance. This operation can't be
* performed on OnDie ECC with internal ECC enabled. There is no way to disable
* internal ECC for OnDie ECC flash parts in current driver. This operation
* is tested with Spansion S34ML04G100TFI00 flash. We have to use this operation
* only on the flash parts which supports program page cache command.
*
* <b>Page Cache Read Operation</b>
*
* The page cache read call is same as read call except that it uses cache
* commands to read. This enhances the performance.
* The read cache random command is used since the HW ECC block doesn't
* support commands without address for starting ECC.
* This operation can't be performed on OnDie ECC with internal ECC enabled.
* There is no way to disable internal ECC for OnDie ECC flash parts in current
* driver. This operation is tested with Spansion S34ML04G100TFI00 flash.
* We have to use this operation only on the flash parts which supports
* read page cache command (random).
*
* <b>Write Spare Bytes Operation</b>
*
* This call writes to user specified buffer into spare bytes of a page.
*
* <b>Read Spare Bytes Operation</b>
*
* This call reads spare bytes of a page into user specified buffer.
*
* @note
*
* This driver is intended to be RTOS and processor independent. It works with
* physical addresses only. Any needs for dynamic memory management, threads,
* mutual exclusion, virtual memory, cache control, or HW write protection
* management must be satisfied by the layer above this driver.
*
* <pre>
* MODIFICATION HISTORY:
*
* Ver Who Date Changes
* ----- ---- ---------- -----------------------------------------------
* 1.00a nm 12/10/2010 First release
* nm 29/09/2011 Added support for On-Die ECC NAND and Clean NAND
* flash parts.
* Added user spare buffer pointer to read/write
* API's. Added new API's for reading and writing
* spare buffer area.
* Changes nand_cycles with ONFI timing mode 0.
* Modified ONFI parameter page reading to read 3
* mandatory pages.
* 1.01a nm 28/02/2012 Added tcl file to generate xparameters.h.
* 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.02a nm 20/09/2012 Removed setting of set_cycles and set_opmode
* register values as it is now done in FSBL using
* the PCW generated files. CR#678949.
* 1.03a nm 10/22/2012 Fixed CR# 683787,673348.
* 1.04a nm 04/15/2013 Fixed CR# 704401. Removed warnings when compiled
* with -Wall and -Wextra option in bsp.
* 04/25/2013 Implemented PR# 699544. Added page cache read
* and program support. Added API's XNandPs_ReadCache
* and XNandPs_WriteCache for page cache support.
* Added XNandPs_Features structure to XNandPs instance
* which contains features handled by driver.
* Added function prototypes for Page cache read/write
* and spare byte read/write API's.
* 2.0 adk 12/10/13 Updated as per the New Tcl API's
* 2.1 kpc 07/24/13 Fixed CR#808770. Update command register twice only
* if flash device requires >= four address cycles.
* </pre>
*
******************************************************************************/
#ifndef XNANDPS_H /* prevent circular inclusions */
#define XNANDPS_H /* by using protection macros */
#ifdef __cplusplus
extern "C" {
#endif
/***************************** Include Files *********************************/
#include <string.h> /* For memcpy, memset */
#include "xil_types.h"
#include "xil_assert.h"
#include "xil_io.h"
#include "xstatus.h"
#include "xnandps_hw.h"
/************************** Constant Definitions *****************************/
#define XNANDPS_MAX_TARGETS 1 /**< Max number of targets
supported */
#define XNANDPS_MAX_BLOCKS 32768 /**< Max number of Blocks */
#define XNANDPS_MAX_PAGE_SIZE 16384 /**< Max page size of NAND
flash */
#define XNANDPS_MAX_SPARE_SIZE 512 /**< Max spare bytes of a NAND
flash page */
#define XNANDPS_ECC_BLOCK_SIZE 512 /**< ECC block size */
#define XNANDPS_ECC_BYTES 3 /**< ECC bytes per ECC block */
#define XNANDPS_PAGE_SIZE_512 512 /**< Page size 512 */
#define XNANDPS_PAGE_SIZE_1024 1024 /**< Page size 1024 */
#define XNANDPS_PAGE_SIZE_2048 2048 /**< Page size 2048 */
#define XNANDPS_PAGE_SIZE_4096 4096 /**< Page size 4096 */
#define XNANDPS_PAGE_SIZE_8192 8192 /**< Page size 8192 */
#define XNANDPS_SPARE_SIZE_8 8 /**< Spare bytes size 8 */
#define XNANDPS_SPARE_SIZE_16 16 /**< Spare bytes size 16 */
#define XNANDPS_SPARE_SIZE_32 32 /**< Spare bytes size 32 */
#define XNANDPS_SPARE_SIZE_64 64 /**< Spare bytes size 64 */
#define XNANDPS_SPARE_SIZE_128 128 /**< Spare bytes size 128 */
#define XNANDPS_SPARE_SIZE_256 256 /**< Spare bytes size 256 */
#define XNANDPS_FLASH_WIDTH_8 8 /**< NAND Flash width 8-bit */
#define XNANDPS_FLASH_WIDTH_16 16 /**< NAND Flash width 16-bit */
/* Macros used for framing SMC AXI command phase and Data phase address */
#define XNANDPS_END_CMD_NONE 0 /**< No End command */
#define XNANDPS_END_CMD_INVALID 0 /**< End command invalid */
#define XNANDPS_CMD_PHASE 1 /**< End command in command
phase */
#define XNANDPS_DATA_PHASE 2 /**< End command in data
phase */
#define XNANDPS_PAGE_NOT_VALID -1 /**< Page is not valid in
command phase */
#define XNANDPS_COLUMN_NOT_VALID -1 /**< Column is not valid in
command phase */
#define XNANDPS_AXI_DATA_WIDTH 4 /**< AXI Data width for last
transaction while reading
and writing */
/* Bit shift for AXI Command/Data phase address calculation */
#define XNANDPS_START_CMD_SHIFT 3 /**< Start command shift */
#define XNANDPS_END_CMD_SHIFT 11 /**< End command shift */
#define XNANDPS_END_CMD_VALID_SHIFT 20 /**< End command valid shift */
#define XNANDPS_ADDR_CYCLES_SHIFT 21 /**< Address cycles shift */
#define XNANDPS_CHIP_ADDR_SHIFT 24 /**< Chip address shift */
#define XNANDPS_ECC_LAST_SHIFT 10 /**< Ecc last shift */
#define XNANDPS_CLEAR_CS_SHIFT 21 /**< clear chip select shift */
#define XNANDPS_COMMAND_PHASE_MASK 0x00000000 /**< Command
phase mask */
#define XNANDPS_DATA_PHASE_MASK 0x00080000 /**< Data phase mask */
/* Macros used for correcting ECC errors */
#define XNANDPS_ECC_CORRECT_BYTE_MASK 0x1FF /**< ECC error correction byte
position mask, bits[11:3] of
error code */
#define XNANDPS_ECC_CORRECT_BIT_MASK 0x7 /**< ECC error correction bit
position mask, bits[0:2] of
error code */
/* Flash memory controller operating parameters */
#define XNANDPS_CLR_CONFIG \
((XNANDPS_MEMC_CLR_CONFIG_INT_DISABLE1_MASK) | \
(XNANDPS_MEMC_CLR_CONFIG_INT_CLR1_MASK) | \
(XNANDPS_MEMC_CLR_CONFIG_ECC_INT_DISABLE1_MASK))
/**< Interrupt settings */
#define XNANDPS_ECC_MEMCFG \
((0x1 << XNANDPS_ECC_MEMCFG_ECC_MODE_SHIFT) | \
(0x1 << XNANDPS_ECC_MEMCFG_ECC_READ_END_SHIFT) | \
(0x0 << XNANDPS_ECC_MEMCFG_ECC_JUMP_SHIFT))
/**< ECC memory configuration settings */
#define XNANDPS_ECC_CMD1 \
((0x80 << XNANDPS_ECC_MEMCOMMAND1_WR_CMD_SHIFT) | \
(0x00 << XNANDPS_ECC_MEMCOMMAND1_RD_CMD_SHIFT) | \
(0x30 << XNANDPS_ECC_MEMCOMMAND1_RD_CMD_END_SHIFT) | \
(0x1 << XNANDPS_ECC_MEMCOMMAND1_RD_CMD_END_VALID_SHIFT))
/**< ECC command 1 settings */
#define XNANDPS_ECC_CMD2 \
((0x85 << XNANDPS_ECC_MEMCOMMAND2_WR_COL_CHANGE_SHIFT) | \
(0x05 << XNANDPS_ECC_MEMCOMMAND2_RD_COL_CHANGE_SHIFT) | \
(0xE0 << XNANDPS_ECC_MEMCOMMAND2_RD_COL_CHANGE_END_SHIFT) | \
(0x1 << XNANDPS_ECC_MEMCOMMAND2_RD_COL_CHANGE_END_VALID_SHIFT))
/**< ECC command 2 settings */
#define XNANDPS_CLR_CS (0x1 << XNANDPS_CLEAR_CS_SHIFT)
/**< set Clear chip select */
#define XNANDPS_ECC_LAST (0x1 << XNANDPS_ECC_LAST_SHIFT)
/**< set Ecc last */
/**************************** Type Definitions *******************************/
/*
* This enum contains ECC Mode
*/
typedef enum {
XNANDPS_ECC_NONE = 0, /**< No ECC */
XNANDPS_ECC_SW, /**< Software ECC */
XNANDPS_ECC_HW, /**< Hardware controller ECC */
XNANDPS_ECC_ONDIE /**< On-Die ECC */
} XNandPs_EccMode;
/**
* This typedef contains configuration information for the flash device.
*/
typedef struct {
u16 DeviceId; /**< Instance ID of device */
u32 SmcBase; /**< SMC Base address */
u32 FlashBase; /**< NAND base address */
u32 FlashWidth; /**< Flash width */
} XNandPs_Config;
/**
* Flash geometry
*/
typedef struct {
u32 BytesPerPage; /**< Bytes per page */
u16 SpareBytesPerPage; /**< Size of spare area in bytes */
u32 PagesPerBlock; /**< Pages per block */
u32 BlocksPerLun; /**< Bocks per LUN */
u8 NumLun; /**< Total number of LUN */
u8 FlashWidth; /**< Data width of flash device */
u64 NumPages; /**< Total number of pages in device */
u64 NumBlocks; /**< Total number of blocks in device */
u64 BlockSize; /**< Size of a block in bytes */
u64 DeviceSize; /**< Total device size in bytes */
u8 RowAddrCycles; /**< Row address cycles */
u8 ColAddrCycles; /**< Column address cycles */
} XNandPs_Geometry;
/**
* ONFI Features and Optional commands supported
* See parameter page byte 6-7 and 8-9
*/
typedef struct {
int ProgramCache;
int ReadCache;
} XNandPs_Features;
/**
* Bad block table descriptor
*/
typedef struct {
u32 PageOffset; /**< Page offset where BBT resides */
u32 SigOffset; /**< Signature offset in Spare area */
u32 VerOffset; /**< Offset of BBT version */
u32 SigLength; /**< Length of the signature */
u32 MaxBlocks; /**< Max blocks to search for BBT */
char Signature[4]; /**< BBT signature */
u8 Version; /**< BBT version */
u32 Valid; /**< BBT descriptor is valid or not */
} XNandPs_BbtDesc;
/**
* Bad block pattern
*/
typedef struct {
u32 Options; /**< Options to search the bad block pattern */
u32 Offset; /**< Offset to search for specified pattern */
u32 Length; /**< Number of bytes to check the pattern */
u8 Pattern[2]; /**< Pattern format to search for */
} XNandPs_BadBlockPattern;
/**
* ECC configuration structure.
* Contains information related to ECC.
*/
typedef struct {
u32 NumSteps; /**< Number of ECC steps for the flash page */
u32 BlockSize; /**< ECC block size */
u32 BytesPerBlock; /**< Number of ECC bytes for a block */
u32 TotalBytes; /**< Total number of ECC bytes for Page */
u32 EccPos[XNANDPS_MAX_SPARE_SIZE];
/**< ECC position in the spare area */
} XNandPs_EccConfig;
/**
* The XNandPs driver instance data. The user is required to allocate a
* variable of this type for every flash device in the system. A pointer to a
* variable of this type is then passed to the driver API functions.
*/
typedef struct XNandPsTag {
u32 IsReady; /**< Device is initialized and ready */
XNandPs_Config Config; /**< XNandPs_Config of current
device */
XNandPs_Geometry Geometry; /**< Part geometry */
XNandPs_Features Features; /**< Features and Optional commands */
u32 CommandPhaseAddr; /**< NAND command phase address */
u32 DataPhaseAddr; /**< NAND Data phase address */
XNandPs_EccConfig EccConfig; /**< ECC configuration parameters */
/* Bad block table definitions */
XNandPs_BbtDesc BbtDesc; /**< Bad block table descriptor */
XNandPs_BbtDesc BbtMirrorDesc; /**< Mirror BBT descriptor */
XNandPs_BadBlockPattern BbPattern; /**< Bad block pattern to
search */
u8 Bbt[XNANDPS_MAX_BLOCKS >> 2]; /**< Bad block table array */
u8 DataBuf[XNANDPS_MAX_PAGE_SIZE + XNANDPS_MAX_SPARE_SIZE];
/**< Data buffer for partial read/writes */
u8 *SpareBufPtr; /**< Pointer to store spare buffer */
u8 EccCalc[XNANDPS_MAX_SPARE_SIZE]; /**< Buffer for calculated
ECC */
u8 EccCode[XNANDPS_MAX_SPARE_SIZE]; /**< Buffer for stored ECC */
XNandPs_EccMode EccMode; /**< ECC Mode */
int (*ReadPage) (struct XNandPsTag *InstancePtr, u8 *DstPtr);
/**< Read Page routine */
int (*WritePage) (struct XNandPsTag *InstancePtr, u8 *SrcPtr);
/**< Write Page routine */
} XNandPs;
/**
* NAND Command format structures
*/
typedef struct {
int StartCmd; /**< Start command */
int EndCmd; /**< End command */
u8 AddrCycles; /**< Number of address cycles */
u8 EndCmdValid; /**< End command valid */
} XNandPs_CommandFormat;
/***************** Macros (Inline Functions) Definitions *********************/
/**
* OneHot is used to check if one and only one bit is set.
* This Macro returns 1 if the value passed is OneHot.
*/
#define OneHot(Value) (!((Value) & (Value - 1)))
/************************** Function Prototypes ******************************/
/*
* Functions in xnandps_sinit.c
*/
XNandPs_Config *XNandPs_LookupConfig(u16 DeviceId);
/*
* Functions in xnandps.c
*/
/*
* Initialization, read, write and erase functions.
*/
int XNandPs_CfgInitialize(XNandPs *InstancePtr, XNandPs_Config *ConfigPtr,
u32 SmcBaseAddr, u32 FlashBaseAddr);
int XNandPs_Read(XNandPs *InstancePtr, u64 Offset, u32 Bytes, void *DestPtr,
u8 *UserSparePtr);
int XNandPs_ReadCache(XNandPs *InstancePtr, u64 Offset, u32 Bytes,
void *SrcPtr, u8 *UserSparePtr);
int XNandPs_Write(XNandPs *InstancePtr, u64 Offset, u32 Bytes, void *SrcPtr,
u8 *UserSparePtr);
int XNandPs_WriteCache(XNandPs *InstancePtr, u64 Offset, u32 Length,
void *SrcPtr, u8 *UserSparePtr);
int XNandPs_ReadSpareBytes(XNandPs *InstancePtr, u32 Page, u8 *Buf);
int XNandPs_WriteSpareBytes(XNandPs *InstancePtr, u32 Page, u8 *Buf);
int XNandPs_EraseBlock(XNandPs *InstancePtr, u32 BlockNum);
#ifdef __cplusplus
}
#endif
#endif /* end of protection macro */

View file

@ -0,0 +1,869 @@
/******************************************************************************
*
* 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_bbm.c
* This file implements the Bad Block Management (BBM) functionality.
* See xnandps_bbm.h for more details.
*
* @note None
*
* <pre>
* MODIFICATION HISTORY:
*
* Ver Who Date Changes
* ----- ---- ---------- -----------------------------------------------
* 1.00a nm 12/10/2010 First release
* 1.03a nm 10/22/2012 Fixed CR# 683787.
* </pre>
*
******************************************************************************/
/***************************** Include Files *********************************/
#include <string.h> /**< For memcpy and memset */
#include "xil_types.h"
#include "xnandps_bbm.h"
/************************** Constant Definitions *****************************/
/**************************** Type Definitions *******************************/
/***************** Macros (Inline Functions) Definitions *********************/
/************************** Function Prototypes ******************************/
static int XNandPs_ReadBbt(XNandPs *InstancePtr);
static int XNandPs_SearchBbt(XNandPs *InstancePtr, XNandPs_BbtDesc *Desc);
static void XNandPs_CreateBbt(XNandPs *InstancePtr);
static void XNandPs_ConvertBbt(XNandPs *InstancePtr, u8 *Buf);
static int XNandPs_WriteBbt(XNandPs *InstancePtr, XNandPs_BbtDesc *Desc,
XNandPs_BbtDesc *MirrorDesc);
static int XNandPs_MarkBbt(XNandPs* InstancePtr, XNandPs_BbtDesc *Desc);
static int XNandPs_UpdateBbt(XNandPs *InstancePtr);
extern int XNandPs_ReadSpareBytes(XNandPs *InstancePtr, u32 Page, u8 *Buf);
/************************** Variable Definitions *****************************/
/*****************************************************************************/
/**
* This function initializes the Bad Block Table(BBT) descriptors with a
* predefined pattern for searching Bad Block Table(BBT) in flash.
*
* @param InstancePtr is a pointer to the XNandPs instance.
*
* @return
* - NONE
*
******************************************************************************/
void XNandPs_InitBbtDesc(XNandPs *InstancePtr)
{
int Index;
Xil_AssertVoid(InstancePtr != NULL);
Xil_AssertVoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY);
/*
* Initialize primary Bad Block Table(BBT)
*/
InstancePtr->BbtDesc.PageOffset = XNANDPS_BBT_DESC_PAGE_OFFSET;
if (InstancePtr->EccMode == XNANDPS_ECC_ONDIE) {
InstancePtr->BbtDesc.SigOffset = 0x4;
InstancePtr->BbtDesc.VerOffset = 0x14;
} else {
InstancePtr->BbtDesc.SigOffset = XNANDPS_BBT_DESC_SIG_OFFSET;
InstancePtr->BbtDesc.VerOffset = XNANDPS_BBT_DESC_VER_OFFSET;
}
InstancePtr->BbtDesc.SigLength = XNANDPS_BBT_DESC_SIG_LEN;
InstancePtr->BbtDesc.MaxBlocks = XNANDPS_BBT_DESC_MAX_BLOCKS;
strcpy(&InstancePtr->BbtDesc.Signature[0], "Bbt0");
InstancePtr->BbtDesc.Version = 0;
InstancePtr->BbtDesc.Valid = 0;
/*
* Initialize mirror Bad Block Table(BBT)
*/
InstancePtr->BbtMirrorDesc.PageOffset = XNANDPS_BBT_DESC_PAGE_OFFSET;
if (InstancePtr->EccMode == XNANDPS_ECC_ONDIE) {
InstancePtr->BbtMirrorDesc.SigOffset = 0x4;
InstancePtr->BbtMirrorDesc.VerOffset = 0x14;
} else {
InstancePtr->BbtMirrorDesc.SigOffset = XNANDPS_BBT_DESC_SIG_OFFSET;
InstancePtr->BbtMirrorDesc.VerOffset = XNANDPS_BBT_DESC_VER_OFFSET;
}
InstancePtr->BbtMirrorDesc.SigLength = XNANDPS_BBT_DESC_SIG_LEN;
InstancePtr->BbtMirrorDesc.MaxBlocks = XNANDPS_BBT_DESC_MAX_BLOCKS;
strcpy(&InstancePtr->BbtMirrorDesc.Signature[0], "1tbB");
InstancePtr->BbtMirrorDesc.Version = 0;
InstancePtr->BbtMirrorDesc.Valid = 0;
/*
* Initialize Bad block search pattern structure
*/
if (InstancePtr->Geometry.BytesPerPage > 512) {
/* For flash page size > 512 bytes */
InstancePtr->BbPattern.Options = XNANDPS_BBT_SCAN_2ND_PAGE;
InstancePtr->BbPattern.Offset =
XNANDPS_BB_PATTERN_OFFSET_LARGE_PAGE;
InstancePtr->BbPattern.Length =
XNANDPS_BB_PATTERN_LENGTH_LARGE_PAGE;
} else {
InstancePtr->BbPattern.Options = XNANDPS_BBT_SCAN_2ND_PAGE;
InstancePtr->BbPattern.Offset =
XNANDPS_BB_PATTERN_OFFSET_SMALL_PAGE;
InstancePtr->BbPattern.Length =
XNANDPS_BB_PATTERN_LENGTH_SMALL_PAGE;
}
for(Index=0; Index < XNANDPS_BB_PATTERN_LENGTH_LARGE_PAGE; Index++) {
InstancePtr->BbPattern.Pattern[Index] = XNANDPS_BB_PATTERN;
}
}
/*****************************************************************************/
/**
* This function scans the NAND flash for factory marked bad blocks and creates
* a RAM based Bad Block Table(BBT).
*
* @param InstancePtr is a pointer to the XNandPs instance.
*
* @return
* - NONE
*
******************************************************************************/
static void XNandPs_CreateBbt(XNandPs *InstancePtr)
{
u32 BlockIndex;
u32 PageIndex;
u32 Length;
u32 BlockOffset;
u32 BlockShift;
u32 NumPages;
u32 Page;
u8 Buf[XNANDPS_MAX_SPARE_SIZE];
u32 BbtLen = InstancePtr->Geometry.NumBlocks >>
XNANDPS_BBT_BLOCK_SHIFT;
int Status;
/*
* Number of pages to search for bad block pattern
*/
if (InstancePtr->BbPattern.Options & XNANDPS_BBT_SCAN_2ND_PAGE) {
NumPages = 2;
} else {
NumPages = 1;
}
/*
* Zero the RAM based Bad Block Table(BBT) entries
*/
memset(&InstancePtr->Bbt[0], 0, BbtLen);
/*
* Scan all the blocks for factory marked bad blocks
*/
for(BlockIndex = 0; BlockIndex <
InstancePtr->Geometry.NumBlocks; BlockIndex++) {
/*
* Block offset in Bad Block Table(BBT) entry
*/
BlockOffset = BlockIndex >> XNANDPS_BBT_BLOCK_SHIFT;
/*
* Block shift value in the byte
*/
BlockShift = XNandPs_BbtBlockShift(BlockIndex);
Page = BlockIndex * InstancePtr->Geometry.PagesPerBlock;
/*
* Search for the bad block pattern
*/
for(PageIndex = 0; PageIndex < NumPages; PageIndex++) {
Status = XNandPs_ReadSpareBytes(InstancePtr,
(Page + PageIndex), &Buf[0]);
if (Status != XST_SUCCESS) {
/* Marking as bad block */
InstancePtr->Bbt[BlockOffset] |=
(XNANDPS_BLOCK_FACTORY_BAD <<
BlockShift);
break;
}
/*
* Read the spare bytes to check for bad block
* pattern
*/
for(Length = 0; Length <
InstancePtr->BbPattern.Length; Length++) {
if (Buf[InstancePtr->BbPattern.Offset + Length]
!=
InstancePtr->BbPattern.Pattern[Length])
{
/* Bad block found */
InstancePtr->Bbt[BlockOffset] |=
(XNANDPS_BLOCK_FACTORY_BAD <<
BlockShift);
break;
}
}
}
}
}
/*****************************************************************************/
/**
* This function reads the Bad Block Table(BBT) if present in flash. If not it
* scans the flash for detecting factory marked bad blocks and creates a bad
* block table and write the Bad Block Table(BBT) into the flash.
*
* @param InstancePtr is a pointer to the XNandPs instance.
*
* @return
* - XST_SUCCESS if successful.
* - XST_FAILURE if fail.
*
******************************************************************************/
int XNandPs_ScanBbt(XNandPs *InstancePtr)
{
int Status;
Xil_AssertNonvoid(InstancePtr != NULL);
Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY);
if (XNandPs_ReadBbt(InstancePtr) != XST_SUCCESS) {
/*
* Create memory based Bad Block Table(BBT)
*/
XNandPs_CreateBbt(InstancePtr);
/*
* Write the Bad Block Table(BBT) to the flash
*/
Status = XNandPs_WriteBbt(InstancePtr,
&InstancePtr->BbtDesc,
&InstancePtr->BbtMirrorDesc);
if (Status != XST_SUCCESS) {
return Status;
}
/*
* Write the Mirror Bad Block Table(BBT) to the flash
*/
Status = XNandPs_WriteBbt(InstancePtr,
&InstancePtr->BbtMirrorDesc,
&InstancePtr->BbtDesc);
if (Status != XST_SUCCESS) {
return Status;
}
/*
* Mark the blocks containing Bad Block Table(BBT) as Reserved
*/
XNandPs_MarkBbt(InstancePtr, &InstancePtr->BbtDesc);
XNandPs_MarkBbt(InstancePtr, &InstancePtr->BbtMirrorDesc);
}
return XST_SUCCESS;
}
/*****************************************************************************/
/**
* This function converts the Bad Block Table(BBT) read from the flash to the RAM
* based Bad Block Table(BBT).
*
* @param InstancePtr is a pointer to the XNandPs instance.
* @param Buf is the buffer which contains BBT read from flash.
*
* @return
* - NONE.
*
******************************************************************************/
static void XNandPs_ConvertBbt(XNandPs *InstancePtr, u8 *Buf)
{
u32 BlockOffset;
u32 BlockShift;
u32 Data;
u8 BlockType;
u32 BlockIndex;
u32 BbtLen = InstancePtr->Geometry.NumBlocks >>
XNANDPS_BBT_BLOCK_SHIFT;
for(BlockOffset = 0; BlockOffset < BbtLen; BlockOffset++) {
Data = Buf[BlockOffset];
/*
* Clear the RAM based Bad Block Table(BBT) contents
*/
InstancePtr->Bbt[BlockOffset] = 0x0;
/*
* Loop through the every 4 blocks in the bitmap
*/
for(BlockIndex = 0; BlockIndex < XNANDPS_BBT_ENTRY_NUM_BLOCKS;
BlockIndex++) {
BlockShift = XNandPs_BbtBlockShift(BlockIndex);
BlockType = (Data >> BlockShift) &
XNANDPS_BLOCK_TYPE_MASK;
switch(BlockType) {
case XNANDPS_FLASH_BLOCK_FACTORY_BAD:
/* Factory bad block */
InstancePtr->Bbt[BlockOffset] |=
XNANDPS_BLOCK_FACTORY_BAD <<
BlockShift;
break;
case XNANDPS_FLASH_BLOCK_RESERVED:
/* Reserved block */
InstancePtr->Bbt[BlockOffset] |=
XNANDPS_BLOCK_RESERVED <<
BlockShift;
break;
case XNANDPS_FLASH_BLOCK_BAD:
/* Bad block due to wear */
InstancePtr->Bbt[BlockOffset] |=
XNANDPS_BLOCK_BAD <<
BlockShift;
break;
default:
/* Good block */
/* The BBT entry already defaults to
* zero */
break;
}
}
}
}
/*****************************************************************************/
/**
* This function searches the Bad Bloock Table(BBT) in flash and loads into the
* memory based Bad Block Table(BBT).
*
* @param InstancePtr is the pointer to the XNandPs instance.
* @return
* - XST_SUCCESS if successful.
* - XST_FAILURE if fail.
*
******************************************************************************/
static int XNandPs_ReadBbt(XNandPs *InstancePtr)
{
u64 Offset;
u8 Buf[XNANDPS_MAX_BLOCKS >> XNANDPS_BBT_BLOCK_SHIFT];
u32 Status1;
u32 Status2;
u32 Status;
u32 BbtLen;
XNandPs_BbtDesc *Desc = &InstancePtr->BbtDesc;
XNandPs_BbtDesc *MirrorDesc = &InstancePtr->BbtMirrorDesc;
BbtLen = InstancePtr->Geometry.NumBlocks >> XNANDPS_BBT_BLOCK_SHIFT;
/*
* Search the Bad Block Table(BBT) in flash
*/
Status1 = XNandPs_SearchBbt(InstancePtr, Desc);
Status2 = XNandPs_SearchBbt(InstancePtr, MirrorDesc);
if ((Status1 != XST_SUCCESS) && (Status2 != XST_SUCCESS)) {
return XST_FAILURE;
}
/*
* Bad Block Table found
*/
if (Desc->Valid && MirrorDesc->Valid) {
/*
* Valid BBT & Mirror BBT found
*/
if (Desc->Version > MirrorDesc->Version) {
Offset = Desc->PageOffset *
InstancePtr->Geometry.BytesPerPage;
XNandPs_Read(InstancePtr, Offset, BbtLen, &Buf, NULL);
/*
* Convert flash BBT to memory based BBT
*/
XNandPs_ConvertBbt(InstancePtr, &Buf[0]);
MirrorDesc->Version = Desc->Version;
/*
* Write the BBT to Mirror BBT location in flash
*/
Status = XNandPs_WriteBbt(InstancePtr, MirrorDesc,
Desc);
if (Status != XST_SUCCESS) {
return Status;
}
} else if (Desc->Version < MirrorDesc->Version) {
Offset = MirrorDesc->PageOffset *
InstancePtr->Geometry.BytesPerPage;
XNandPs_Read(InstancePtr, Offset, BbtLen, &Buf, NULL);
/*
* Convert flash BBT to memory based BBT
*/
XNandPs_ConvertBbt(InstancePtr, &Buf[0]);
Desc->Version = MirrorDesc->Version;
/*
* Write the Mirror BBT to BBT location in flash
*/
Status = XNandPs_WriteBbt(InstancePtr, Desc,
MirrorDesc);
if (Status != XST_SUCCESS) {
return Status;
}
} else {
/* Both are up-to-date */
Offset = Desc->PageOffset *
InstancePtr->Geometry.BytesPerPage;
XNandPs_Read(InstancePtr, Offset, BbtLen, &Buf, NULL);
/*
* Convert flash BBT to memory based BBT
*/
XNandPs_ConvertBbt(InstancePtr, &Buf[0]);
}
} else if (Desc->Valid) {
/*
* Valid Primary BBT found
*/
Offset = Desc->PageOffset * InstancePtr->Geometry.BytesPerPage;
XNandPs_Read(InstancePtr, Offset, BbtLen, &Buf, NULL);
/*
* Convert flash BBT to memory based BBT
*/
XNandPs_ConvertBbt(InstancePtr, &Buf[0]);
MirrorDesc->Version = Desc->Version;
/*
* Write the BBT to Mirror BBT location in flash
*/
Status = XNandPs_WriteBbt(InstancePtr, MirrorDesc, Desc);
if (Status != XST_SUCCESS) {
return Status;
}
} else {
/*
* Valid Mirror BBT found
*/
Offset = MirrorDesc->PageOffset *
InstancePtr->Geometry.BytesPerPage;
XNandPs_Read(InstancePtr, Offset, BbtLen, &Buf, NULL);
/*
* Convert flash BBT to memory based BBT
*/
XNandPs_ConvertBbt(InstancePtr, &Buf[0]);
Desc->Version = MirrorDesc->Version;
/*
* Write the Mirror BBT to BBT location in flash
*/
Status = XNandPs_WriteBbt(InstancePtr, Desc, MirrorDesc);
if (Status != XST_SUCCESS) {
return Status;
}
}
return XST_SUCCESS;
}
/*****************************************************************************/
/**
* This function searches the BBT in flash.
*
* @param InstancePtr is the pointer to the XNandPs instance.
* @param Desc is the BBT descriptor pattern to search.
*
* @return
* - XST_SUCCESS if successful.
* - XST_FAILURE if fail.
*
******************************************************************************/
static int XNandPs_SearchBbt(XNandPs *InstancePtr, XNandPs_BbtDesc *Desc)
{
u32 StartBlock;
u32 SigOffset;
u32 VerOffset;
u32 MaxBlocks;
u32 PageOff;
u32 SigLength;
u8 Buf[XNANDPS_MAX_SPARE_SIZE];
u32 Block;
u32 Offset;
int Status;
StartBlock = InstancePtr->Geometry.NumBlocks - 1;
SigOffset = Desc->SigOffset;
VerOffset = Desc->VerOffset;
MaxBlocks = Desc->MaxBlocks;
SigLength = Desc->SigLength;
/*
* Read the last 4 blocks for Bad Block Table(BBT) signature
*/
for(Block = 0; Block < MaxBlocks; Block++) {
PageOff = (StartBlock - Block) *
InstancePtr->Geometry.PagesPerBlock;
Status = XNandPs_ReadSpareBytes(InstancePtr, PageOff, &Buf[0]);
if (Status != XST_SUCCESS) {
continue;
}
/*
* Check the Bad Block Table(BBT) signature
*/
for(Offset = 0; Offset < SigLength; Offset++) {
if (Buf[Offset + SigOffset] != Desc->Signature[Offset])
{
break; /* Check the next blocks */
}
}
if (Offset >= SigLength) {
/*
* Bad Block Table(BBT) found
*/
Desc->PageOffset = PageOff;
Desc->Version = Buf[VerOffset];
Desc->Valid = 1;
return XST_SUCCESS;
}
}
/*
* Bad Block Table(BBT) not found
*/
return XST_FAILURE;
}
/*****************************************************************************/
/**
* This function writes Bad Block Table(BBT) from RAM to flash.
*
* @param InstancePtr is the pointer to the XNandPs instance.
* @param Desc is the BBT descriptor to be written to flash.
* @param MirrorDesc is the mirror BBT descriptor.
*
* @return
* - XST_SUCCESS if successful.
* - XST_FAILURE if fail.
*
******************************************************************************/
static int XNandPs_WriteBbt(XNandPs *InstancePtr, XNandPs_BbtDesc *Desc,
XNandPs_BbtDesc *MirrorDesc)
{
u64 Offset;
u32 Block = InstancePtr->Geometry.NumBlocks - 1;
u8 Buf[XNANDPS_MAX_BLOCKS >> XNANDPS_BBT_BLOCK_SHIFT];
u8 SpareBuf[XNANDPS_MAX_SPARE_SIZE];
u8 Mask[4] = {0x00, 0x01, 0x02, 0x03};
u8 Data;
u32 BlockOffset;
u32 BlockShift;
u32 Status;
u32 BlockIndex;
u32 Index;
u8 BlockType;
u32 BbtLen = InstancePtr->Geometry.NumBlocks >>
XNANDPS_BBT_BLOCK_SHIFT;
/*
* Find a valid block to write the Bad Block Table(BBT)
*/
if (!Desc->Valid) {
for(Index = 0; Index < Desc->MaxBlocks; Index++) {
Block = (Block - Index);
BlockOffset = Block >> XNANDPS_BBT_BLOCK_SHIFT;
BlockShift = XNandPs_BbtBlockShift(Block);
BlockType = (InstancePtr->Bbt[BlockOffset] >>
BlockShift) & XNANDPS_BLOCK_TYPE_MASK;
switch(BlockType)
{
case XNANDPS_BLOCK_BAD:
case XNANDPS_BLOCK_FACTORY_BAD:
continue;
default:
/* Good Block */
break;
}
Desc->PageOffset = Block *
InstancePtr->Geometry.PagesPerBlock;
if (Desc->PageOffset != MirrorDesc->PageOffset) {
/* Free block found */
Desc->Valid = 1;
break;
}
}
/*
* Block not found for writing Bad Block Table(BBT)
*/
if (Index >= Desc->MaxBlocks) {
return XST_FAILURE;
}
} else {
Block = Desc->PageOffset/InstancePtr->Geometry.PagesPerBlock;
}
/*
* Convert the memory based BBT to flash based table
*/
memset(Buf, 0xff, BbtLen);
/*
* Loop through the number of blocks
*/
for(BlockOffset = 0; BlockOffset < BbtLen; BlockOffset++) {
Data = InstancePtr->Bbt[BlockOffset];
/*
* Calculate the bit mask for 4 blocks at a time in loop
*/
for(BlockIndex = 0; BlockIndex < XNANDPS_BBT_ENTRY_NUM_BLOCKS;
BlockIndex++) {
BlockShift = XNandPs_BbtBlockShift(BlockIndex);
Buf[BlockOffset] &= ~(Mask[Data &
XNANDPS_BLOCK_TYPE_MASK] <<
BlockShift);
Data >>= XNANDPS_BBT_BLOCK_SHIFT;
}
}
/*
* Write the Bad Block Table(BBT) to flash
*/
Status = XNandPs_EraseBlock(InstancePtr, Block);
if (Status != XST_SUCCESS) {
return Status;
}
/*
* Write the signature and version in the spare data area
*/
memset(SpareBuf, 0xff, InstancePtr->Geometry.SpareBytesPerPage);
memcpy(SpareBuf + Desc->SigOffset, &Desc->Signature[0],
Desc->SigLength);
memcpy(SpareBuf + Desc->VerOffset, &Desc->Version, 1);
/*
* Write the BBT to page offset
*/
Offset = Desc->PageOffset * InstancePtr->Geometry.BytesPerPage;
Status = XNandPs_Write(InstancePtr, Offset, BbtLen, &Buf[0], SpareBuf);
if (Status != XST_SUCCESS) {
return Status;
}
return XST_SUCCESS;
}
/*****************************************************************************/
/**
* This function updates the primary and mirror Bad Block Table(BBT) in the
* flash.
*
* @param InstancePtr is the pointer to the XNandPs instance.
* @return
* - XST_SUCCESS if successful.
* - XST_FAILURE if fail.
*
******************************************************************************/
static int XNandPs_UpdateBbt(XNandPs *InstancePtr)
{
int Status;
u8 Version;
/*
* Update the version number
*/
Version = InstancePtr->BbtDesc.Version;
InstancePtr->BbtDesc.Version = (Version + 1) % 256;
Version = InstancePtr->BbtMirrorDesc.Version;
InstancePtr->BbtMirrorDesc.Version = (Version + 1) % 256;
/*
* Update the primary Bad Block Table(BBT) in flash
*/
Status = XNandPs_WriteBbt(InstancePtr, &InstancePtr->BbtDesc,
&InstancePtr->BbtMirrorDesc);
if (Status != XST_SUCCESS) {
return Status;
}
/*
* Update the mirrored Bad Block Table(BBT) in flash
*/
Status = XNandPs_WriteBbt(InstancePtr, &InstancePtr->BbtMirrorDesc,
&InstancePtr->BbtDesc);
if (Status != XST_SUCCESS) {
return Status;
}
return XST_SUCCESS;
}
/*****************************************************************************/
/**
* This function marks the block containing Bad Block Table as reserved
* and updates the BBT.
*
* @param InstancePtr is the pointer to the XNandPs instance.
* @param Desc is the BBT descriptor pointer.
* @return
* - XST_SUCCESS if successful.
* - XST_FAILURE if fail.
*
******************************************************************************/
static int XNandPs_MarkBbt(XNandPs* InstancePtr, XNandPs_BbtDesc *Desc)
{
u32 BlockIndex;
u32 BlockOffset;
u8 BlockShift;
u8 OldVal;
u8 NewVal;
int Status;
u32 UpdateBbt = 0;
u32 Index;
/*
* Mark the last four blocks as Reserved
*/
BlockIndex = InstancePtr->Geometry.NumBlocks - Desc->MaxBlocks - 1;
for(Index = 0; Index < Desc->MaxBlocks; Index++,BlockIndex++) {
BlockOffset = BlockIndex >> XNANDPS_BBT_BLOCK_SHIFT;
BlockShift = XNandPs_BbtBlockShift(BlockIndex);
OldVal = InstancePtr->Bbt[BlockOffset];
NewVal = OldVal | (XNANDPS_BLOCK_RESERVED << BlockShift);
InstancePtr->Bbt[BlockOffset] = NewVal;
if (OldVal != NewVal) {
UpdateBbt = 1;
}
}
/*
* Update the BBT to flash
*/
if (UpdateBbt) {
Status = XNandPs_UpdateBbt(InstancePtr);
if (Status != XST_SUCCESS) {
return Status;
}
}
return XST_SUCCESS;
}
/*****************************************************************************/
/**
*
* This function checks whether a block is bad or not.
*
* @param InstancePtr is the pointer to the XNandPs instance.
*
* @param Block is the block number.
*
* @return
* - XST_SUCCESS if successful.
* - XST_FAILURE if fail.
*
******************************************************************************/
int XNandPs_IsBlockBad(XNandPs *InstancePtr, u32 Block)
{
u8 Data;
u8 BlockShift;
u8 BlockType;
u32 BlockOffset;
Xil_AssertNonvoid(InstancePtr != NULL);
Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY);
Xil_AssertNonvoid(Block < InstancePtr->Geometry.NumBlocks);
BlockOffset = Block >> XNANDPS_BBT_BLOCK_SHIFT;
BlockShift = XNandPs_BbtBlockShift(Block);
Data = InstancePtr->Bbt[BlockOffset]; /* Block information in BBT */
BlockType = (Data >> BlockShift) & XNANDPS_BLOCK_TYPE_MASK;
if (BlockType != XNANDPS_BLOCK_GOOD)
return XST_SUCCESS;
else
return XST_FAILURE;
}
/*****************************************************************************/
/**
* This function marks a block as bad in the RAM based Bad Block Table(BBT). It
* also updates the Bad Block Table(BBT) in the flash.
*
* @param InstancePtr is the pointer to the XNandPs instance.
* @param Block is the block number.
*
* @return
* - XST_SUCCESS if successful.
* - XST_FAILURE if fail.
*
******************************************************************************/
int XNandPs_MarkBlockBad(XNandPs *InstancePtr, u32 Block)
{
u8 Data;
u8 BlockShift;
u32 BlockOffset;
u8 OldVal;
u8 NewVal;
u32 Status;
Xil_AssertNonvoid(InstancePtr != NULL);
Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY);
Xil_AssertNonvoid(Block < InstancePtr->Geometry.NumBlocks);
BlockOffset = Block >> XNANDPS_BBT_BLOCK_SHIFT;
BlockShift = XNandPs_BbtBlockShift(Block);
Data = InstancePtr->Bbt[BlockOffset]; /* Block information in BBT */
/*
* Mark the block as bad in the RAM based Bad Block Table
*/
OldVal = Data;
Data &= ~(XNANDPS_BLOCK_TYPE_MASK << BlockShift);
Data |= (XNANDPS_BLOCK_BAD << BlockShift);
NewVal = Data;
InstancePtr->Bbt[BlockOffset] = Data;
/*
* Update the Bad Block Table(BBT) in flash
*/
if (OldVal != NewVal) {
Status = XNandPs_UpdateBbt(InstancePtr);
if (Status != XST_SUCCESS) {
return Status;
}
}
return XST_SUCCESS;
}

View file

@ -0,0 +1,185 @@
/******************************************************************************
*
* 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_bbm.h
*
* This file implements the Bad Block Management(BBM) functionality. This is
* similar to the Bad Block Management which is a part of the MTD subsystem in
* Linux. The factory marked bad blocks are scanned initially and a Bad Block
* Table(BBT) is created in the memory. This table is also written to the flash
* so that upon reboot, the BBT is read back from the flash and loaded into the
* memory instead of scanning every time. The Bad Block Table(BBT) is written
* into one of the the last four blocks in the flash memory. The last four
* blocks are marked as Reserved so that user can't erase/program those blocks.
*
* There are two bad block tables, a primary table and a mirror table. The
* tables are versioned and incrementing version number is used to detect and
* recover from interrupted updates. Each table is stored in a separate block,
* beginning in the first page of that block. Only two blocks would be necessary
* in the absence of bad blocks within the last four; the range of four provides
* a little slack in case one or two of those blocks is bad. These blocks are
* marked as reserved and cannot be programmed by the user. A NAND Flash device
* with 3 or more factory bad blocks in the last 4 cannot be used. The bad block
* table signature is written into the spare data area of the pages containing
* bad block table so that upon rebooting the bad block table signature is
* searched and the bad block table is loaded into RAM. The signature is "Bbt0"
* for primary Bad Block Table and "1tbB" for Mirror Bad Block Table. The
* version offset follows the signature offset in the spare data area. The
* version number increments on every update to the bad block table and the
* version wraps at 0xff.
*
* Each block in the Bad Block Table(BBT) is represented by 2 bits.
* The two bits are encoded as follows in RAM BBT.
* 0'b00 -> Good Block
* 0'b01 -> Block is bad due to wear
* 0'b10 -> Reserved block
* 0'b11 -> Factory marked bad block
*
* While writing to the flash the two bits are encoded as follows.
* 0'b00 -> Factory marked bad block
* 0'b01 -> Reserved block
* 0'b10 -> Block is bad due to wear
* 0'b11 -> Good Block
*
* The user can check for the validity of the block using the API
* XNandPs_IsBlockBad and take the action based on the return value. Also user
* can update the bad block table using XNandPs_MarkBlockBad API.
*
* @note None
*
* <pre>
* MODIFICATION HISTORY:
*
* Ver Who Date Changes
* ----- ---- ---------- -----------------------------------------------
* 1.00a nm 12/10/2010 First release
* </pre>
*
******************************************************************************/
#ifndef BBM_H /* prevent circular inclusions */
#define BBM_H /* by using protection macros */
#ifdef __cplusplus
extern "C" {
#endif
/***************************** Include Files *********************************/
#include "xnandps.h"
/************************** Constant Definitions *****************************/
/*
* Block definitions for RAM based Bad Block Table (BBT)
*/
#define XNANDPS_BLOCK_GOOD 0x0 /**< Block is good */
#define XNANDPS_BLOCK_BAD 0x1 /**< Block is bad */
#define XNANDPS_BLOCK_RESERVED 0x2 /**< Reserved block */
#define XNANDPS_BLOCK_FACTORY_BAD 0x3 /**< Factory marked bad
block */
/*
* Block definitions for FLASH based Bad Block Table (BBT)
*/
#define XNANDPS_FLASH_BLOCK_GOOD 0x3 /**< Block is good */
#define XNANDPS_FLASH_BLOCK_BAD 0x2 /**< Block is bad */
#define XNANDPS_FLASH_BLOCK_RESERVED 0x1 /**< Reserved block */
#define XNANDPS_FLASH_BLOCK_FACTORY_BAD 0x0 /**< Factory marked bad
block */
#define XNANDPS_BBT_SCAN_2ND_PAGE 0x00000001 /**< Scan the
second page
for bad block
information
*/
#define XNANDPS_BBT_DESC_PAGE_OFFSET 0 /**< Page offset of Bad
Block Table Desc */
#define XNANDPS_BBT_DESC_SIG_OFFSET 8 /**< Bad Block Table
signature offset */
#define XNANDPS_BBT_DESC_VER_OFFSET 12 /**< Bad block Table
version offset */
#define XNANDPS_BBT_DESC_SIG_LEN 4 /**< Bad block Table
signature length */
#define XNANDPS_BBT_DESC_MAX_BLOCKS 4 /**< Bad block Table
max blocks */
#define XNANDPS_BBT_BLOCK_SHIFT 2 /**< Block shift value
for a block in BBT */
#define XNANDPS_BBT_ENTRY_NUM_BLOCKS 4 /**< Num of blocks in
one BBT entry */
#define XNANDPS_BB_PATTERN_OFFSET_SMALL_PAGE 5 /**< Bad block pattern
offset in a page */
#define XNANDPS_BB_PATTERN_LENGTH_SMALL_PAGE 1 /**< Bad block pattern
length */
#define XNANDPS_BB_PATTERN_OFFSET_LARGE_PAGE 0 /**< Bad block pattern
offset in a large
page */
#define XNANDPS_BB_PATTERN_LENGTH_LARGE_PAGE 2 /**< Bad block pattern
length */
#define XNANDPS_BB_PATTERN 0xFF /**< Bad block pattern
to search in a page
*/
#define XNANDPS_BLOCK_TYPE_MASK 0x03 /**< Block type mask */
#define XNANDPS_BLOCK_SHIFT_MASK 0x06 /**< Block shift mask
for a Bad Block Table
entry byte */
/**************************** Type Definitions *******************************/
/***************** Macros (Inline Functions) Definitions *********************/
/****************************************************************************/
/**
*
* This macro returns the Block shift value corresponding to a Block.
*
* @param Block is the block number.
*
* @return Block shift value
*
* @note None.
*
*****************************************************************************/
#define XNandPs_BbtBlockShift(Block) \
((Block * 2) & XNANDPS_BLOCK_SHIFT_MASK)
/************************** Variable Definitions *****************************/
/************************** Function Prototypes ******************************/
int XNandPs_IsBlockBad(XNandPs *InstancePtr, u32 Block);
int XNandPs_MarkBlockBad(XNandPs *InstancePtr, u32 Block);
#ifdef __cplusplus
}
#endif
#endif /* end of protection macro */

View file

@ -0,0 +1,84 @@
/******************************************************************************
*
* 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_g.c
*
* This file contains a configuration table that specifies the configuration
* of NAND flash devices in the system.
*
* See xnandps.h for more information about this driver.
*
* @note None.
*
* <pre>
*
* MODIFICATION HISTORY:
*
* Ver Who Date Changes
* ----- ---- ---------- -----------------------------------------------
* 1.00a nm 12/10/2010 First release
* </pre>
*
******************************************************************************/
/***************************** Include Files *********************************/
#include "xnandps.h"
#include "xparameters.h"
/************************** Constant Definitions *****************************/
/**************************** Type Definitions *******************************/
/***************** Macros (Inline Functions) Definitions *********************/
/************************** Function Prototypes ******************************/
/************************** Variable Prototypes ******************************/
/**
* This table contains configuration information for each System Monitor/ADC
* device in the system.
*/
XNandPs_Config XNandPs_ConfigTable[XPAR_XNANDPS_NUM_INSTANCES] =
{
{
XPAR_XNANDPS_0_DEVICE_ID, /**< Device ID of device */
XPAR_XPARPORTPS_CTRL_BASEADDR, /**< SMC Base address
0xE000E000 */
XPAR_XNANDPS_0_BASEADDR, /**< NAND flash Base address
0xE1000000 */
XPAR_XNANDPS_0_FLASH_WIDTH /**< Flash data width */
}
};

View file

@ -0,0 +1,570 @@
/******************************************************************************
*
* 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_hw.h
*
* This file contains identifiers and low-level macros/functions for the NAND
* Flash controller driver.
* See xnandps.h for more information.
*
* @note None
*
* <pre>
* MODIFICATION HISTORY:
*
* Ver Who Date Changes
* ----- ---- ---------- -----------------------------------------------
* 1.00a nm 12/10/2010 First release
* </pre>
*
******************************************************************************/
#ifndef XNANDPS_HW_H /* prevent circular inclusions */
#define XNANDPS_HW_H /* by using protection macros */
#ifdef __cplusplus
extern "C" {
#endif
/***************************** Include Files *********************************/
/************************** Constant Definitions *****************************/
/*
* Memory controller configuration register offset
*/
#define XNANDPS_MEMC_STATUS_OFFSET 0x000 /**< Controller status
reg, RO */
#define XNANDPS_MEMC_IF_CONFIG_OFFSET 0x004 /**< Interface config
reg, RO */
#define XNANDPS_MEMC_SET_CONFIG_OFFSET 0x008 /**< Set configuration
reg, WO */
#define XNANDPS_MEMC_CLR_CONFIG_OFFSET 0x00C /**< Clear config reg,
WO */
#define XNANDPS_DIRECT_CMD_OFFSET 0x010 /**< Direct command
reg, WO */
#define XNANDPS_SET_CYCLES_OFFSET 0x014 /**< Set cycles
register, WO */
#define XNANDPS_SET_OPMODE_OFFSET 0x018 /**< Set opmode
register, WO */
#define XNANDPS_REFRESH_PERIOD_0_OFFSET 0x020 /**< Refresh period_0
reg, RW */
#define XNANDPS_REFRESH_PERIOD_1_OFFSET 0x024 /**< Refresh period_1
reg, RW */
/*
* Chip configuration register offset
*/
#define XNANDPS_IF0_CHIP_0_CONFIG_OFFSET 0x100 /**< Interface 0 chip 0
config */
#define XNANDPS_IF0_CHIP_1_CONFIG_OFFSET 0x120 /**< Interface 0 chip 1
config */
#define XNANDPS_IF0_CHIP_2_CONFIG_OFFSET 0x140 /**< Interface 0 chip 2
config */
#define XNANDPS_IF0_CHIP_3_CONFIG_OFFSET 0x160 /**< Interface 0 chip 3
config */
#define XNANDPS_IF1_CHIP_0_CONFIG_OFFSET 0x180 /**< Interface 1 chip 0
config */
#define XNANDPS_IF1_CHIP_1_CONFIG_OFFSET 0x1A0 /**< Interface 1 chip 1
config */
#define XNANDPS_IF1_CHIP_2_CONFIG_OFFSET 0x1C0 /**< Interface 1 chip 2
config */
#define XNANDPS_IF1_CHIP_3_CONFIG_OFFSET 0x1E0 /**< Interface 1 chip 3
config */
/*
* nand_cycles (RO), sram_cycles (RO) and opmode_x_n (RO) registers offsets
*/
#define XNANDPS_FLASH_CYCLES(addr) (0x000 + addr) /**< NAND & SRAM
cycle,RO*/
#define XNANDPS_OPMODE(addr) (0x004 + addr) /**< Chip opmode
reg, RO */
/*
* User configuration register offset
*/
#define XNANDPS_USER_STATUS_OFFSET 0x200 /**< User status reg,
RO */
#define XNANDPS_USER_CONFIG_OFFSET 0x204 /**< User config reg,
WO */
/*
* ECC register offset
*/
#define XNANDPS_IF0_ECC_OFFSET 0x300 /**< Interface 0 ECC
register */
#define XNANDPS_IF1_ECC_OFFSET 0x400 /**< Interface 1 ECC
register */
#define XNANDPS_ECC_STATUS_OFFSET(addr) (0x000 + addr) /**< ECC status
register */
#define XNANDPS_ECC_MEMCFG_OFFSET(addr) (0x004 + addr) /**< ECC mem
config reg */
#define XNANDPS_ECC_MEMCMD1_OFFSET(addr) (0x008 + addr) /**< ECC mem
com1 reg*/
#define XNANDPS_ECC_MEMCMD2_OFFSET(addr) (0x00C + addr) /**< ECC mem
com2 reg*/
#define XNANDPS_ECC_ADDR0_OFFSET(addr) (0x010 + addr) /**< ECC
address0 reg
*/
#define XNANDPS_ECC_ADDR1_OFFSET(addr) (0x014 + addr) /**< ECC
address1 reg
*/
#define XNANDPS_ECC_VALUE0_OFFSET(addr) (0x018 + addr) /**< ECC value 0
reg */
#define XNANDPS_ECC_VALUE1_OFFSET(addr) (0x01C + addr) /**< ECC value 1
reg */
#define XNANDPS_ECC_VALUE2_OFFSET(addr) (0x020 + addr) /**< ECC value 2
reg */
#define XNANDPS_ECC_VALUE3_OFFSET(addr) (0x024 + addr) /**< ECC value 3
reg */
#define XNANDPS_ECC_VALUE4_OFFSET(addr) (0x028 + addr) /**< ECC value 4
reg */
/*
* Integration test register offset
*/
#define XNANDPS_INTGTEST_OFFSET 0xE00 /**< Integration test
offset */
/*
* ID configuration register offset
*/
#define XNANDPS_PERIPH_ID0_OFFSET 0xFE0 /**< Peripheral id0
register */
#define XNANDPS_PERIPH_ID1_OFFSET 0xFE4 /**< Peripheral id1
register */
#define XNANDPS_PERIPH_ID2_OFFSET 0xFE8 /**< Peripheral id2
register */
#define XNANDPS_PERIPH_ID3_OFFSET 0xFEC /**< Peripheral id3
register */
#define XNANDPS_PCELL_ID0_OFFSET 0xFF0 /**< Primecell id0
register */
#define XNANDPS_PCELL_ID1_OFFSET 0xFF4 /**< Primecell id1
register */
#define XNANDPS_PCELL_ID2_OFFSET 0xFF8 /**< Primecell id2
register */
#define XNANDPS_PCELL_ID3_OFFSET 0xFFC /**< Primecell id3
register */
/** @name Memory controller status register bit definitions and masks
* @{
*/
#define XNANDPS_MEMC_STATUS_STATE_MASK 0x00000001 /**< Memory
controller operating state mask */
#define XNANDPS_MEMC_STATUS_INT_EN0_MASK 0x00000002 /**< Memory
controller interface 0 interrupt enable mask */
#define XNANDPS_MEMC_STATUS_INT_EN1_MASK 0x00000004 /**< Memory
controller interface 1 interrupt enable mask */
#define XNANDPS_MEMC_STATUS_INT_STATUS0_MASK 0x00000008 /**< Memory
controller interface 0 interrupt status mask */
#define XNANDPS_MEMC_STATUS_INT_STATUS1_MASK 0x00000010 /**< Memory
controller interface 1 interrupt status mask */
#define XNANDPS_MEMC_STATUS_RAW_INT_STATUS0_MASK 0x00000020 /**< Memory
controller interface 0 raw interrupt status mask */
#define XNANDPS_MEMC_STATUS_RAW_INT_STATUS1_MASK 0x00000040 /**< Memory
controller interface 1 raw interrupt status mask */
#define XNANDPS_MEMC_STATUS_ECC_INT_EN0_MASK 0x00000080 /**< Memory
controller interface 0 ECC interrupt enable mask */
#define XNANDPS_MEMC_STATUS_ECC_INT_EN1_MASK 0x00000100 /**< Memory
controller interface 1 ECC interrupt enable mask */
#define XNANDPS_MEMC_STATUS_ECC_INT0_MASK 0x00000200 /**< Memory
controller interface 0 ECC interrupt status mask */
#define XNANDPS_MEMC_STATUS_ECC_INT1_MASK 0x00000400 /**< Memory
controller interface 1 ECC interrupt status mask */
#define XNANDPS_MEMC_STATUS_RAW_ECC_INT0_MASK 0x00000800 /**< Memory
controller interface 0 raw ECC interrupt status mask */
#define XNANDPS_MEMC_STATUS_RAW_ECC_INT1_MASK 0x00001000 /**< Memory
controller interface 1 raw ECC interrupt status mask */
/* @} */
/** @name Memory interface configurartion register bit definitions and masks
* @{
*/
#define XNANDPS_MEMC_IF_CONFIG_MEMORY_TYPE0_MASK 0x00000003 /**< Memory
controller interface 0 type mask */
#define XNANDPS_MEMC_IF_CONFIG_MEMORY_CHIPS0_MASK 0x0000000C /**< Memory
controller interface 0 chip select mask */
#define XNANDPS_MEMC_IF_CONFIG_MEMORY_WIDTH0_MASK 0x00000030 /**< Memory
controller interface 0 data width mask */
#define XNANDPS_MEMC_IF_CONFIG_REMAP0_MASK 0x00000040 /**< Memory
controller interface 0 remap0 mask */
#define XNANDPS_MEMC_IF_CONFIG_MEMORY_TYPE1_MASK 0x00000300 /**< Memory
controller interface 1 type mask */
#define XNANDPS_MEMC_IF_CONFIG_MEMORY_CHIPS1_MASK 0x00000C00 /**< Memory
controller interface 1 chip select mask */
#define XNANDPS_MEMC_IF_CONFIG_MEMORY_WIDTH1_MASK 0x00003000 /**< Memory
controller interface 1 data width mask */
#define XNANDPS_MEMC_IF_CONFIG_REMAP1_MASK 0x00004000 /**< Memory
controller interface 1 remap0 mask */
#define XNANDPS_MEMC_IF_CONFIG_EX_MONITORS_MASK 0x00030000 /**< Memory
controller interface exclusive masks mask */
/* @} */
/** @name Set configuration register bit definitions and masks
* @{
*/
#define XNANDPS_MEMC_SET_CONFIG_INT_ENABLE0_MASK 0x00000001 /**< Memory
controller interfce0 interrupt enable mask */
#define XNANDPS_MEMC_SET_CONFIG_INT_ENABLE1_MASK 0x00000002 /**< Memory
controller interfce1 interrupt enable mask */
#define XNANDPS_MEMC_SET_CONFIG_LOW_POWER_REQ_MASK 0x00000004 /**< Memory
controller low power state mask */
#define XNANDPS_MEMC_SET_CONFIG_ECC_INT_ENABLE0_MASK 0x00000020 /**< Memory
controller interfce0 ECC interrupt enable mask */
#define XNANDPS_MEMC_SET_CONFIG_ECC_INT_ENABLE1_MASK 0x00000040 /**< Memory
controller interfce1 ECC interrupt enable mask */
/* @} */
/** @name Clear configuration register bit definitions and masks
* @{
*/
#define XNANDPS_MEMC_CLR_CONFIG_INT_DISABLE0_MASK 0x00000001 /**< Memory
controller interface 0 interrupt disable mask */
#define XNANDPS_MEMC_CLR_CONFIG_INT_DISABLE1_MASK 0x00000002 /**< Memory
controller interface 1 interrupt disable mask */
#define XNANDPS_MEMC_CLR_CONFIG_LOW_POWER_EXIT_MASK 0x00000004 /**< Memory
controller low power exit mask */
#define XNANDPS_MEMC_CLR_CONFIG_INT_CLR0_MASK 0x00000008 /**< Memory
controller interface0 interrupt clear mask */
#define XNANDPS_MEMC_CLR_CONFIG_INT_CLR1_MASK 0x00000010 /**< Memory
controller interface1 interrupt clear mask */
#define XNANDPS_MEMC_CLR_CONFIG_ECC_INT_DISABLE0_MASK 0x00000020 /**< Memory
controller interface0 ECC interrupt disable mask */
#define XNANDPS_MEMC_CLR_CONFIG_ECC_INT_DISABLE1_MASK 0x00000040 /**< Memory
controller interface1 ECC interrupt disable mask */
/* @} */
/** @name Clear configuration register bit definitions and masks and shift
* @{
*/
#define XNANDPS_DIRECT_CMD_ADDR_MASK 0x000FFFFF /**< Direct
command address mask */
#define XNANDPS_DIRECT_CMD_SET_CRE_MASK 0x00100000 /**< Direct
command set cre mask */
#define XNANDPS_DIRECT_CMD_TYPE_MASK 0x00600000 /**< Direct
command type mask */
#define XNANDPS_DIRECT_CMD_CHIP_SELECT_MASK 0x03800000 /**< Direct
command chip select mask */
#define XNANDPS_DIRECT_CMD_SET_CRE_SHIFT 20 /**< Direct command
set_cre shift */
#define XNANDPS_DIRECT_CMD_CMD_TYPE_SHIFT 21 /**< Direct command
cmd_type shift */
#define XNANDPS_DIRECT_CMD_CHIP_SELECT_SHIFT 23 /**< Direct command
chip select shift */
/* @} */
/** @name Set cycles register bit definitions and masks and shift
* @{
*/
#define XNANDPS_SET_CYCLES_SET_T0_MASK 0x0000000F /**< Set
cycles set_t0 mask */
#define XNANDPS_SET_CYCLES_SET_T1_MASK 0x000000F0 /**< Set
cycles set_t1 mask */
#define XNANDPS_SET_CYCLES_SET_T2_MASK 0x00000700 /**< Set
cycles set_t2 mask */
#define XNANDPS_SET_CYCLES_SET_T3_MASK 0x00003800 /**< Set
cycles set_t3 mask */
#define XNANDPS_SET_CYCLES_SET_T4_MASK 0x0001C000 /**< Set
cycles set_t4 mask */
#define XNANDPS_SET_CYCLES_SET_T5_MASK 0x000E0000 /**< Set
cycles set_t5 mask */
#define XNANDPS_SET_CYCLES_SET_T6_MASK 0x00F00000 /**< Set
cycles set_t6 mask */
#define XNANDPS_SET_CYCLES_SET_T0_SHIFT 0 /**< Set cycles set_t0
shift */
#define XNANDPS_SET_CYCLES_SET_T1_SHIFT 4 /**< Set cycles set_t1
shift */
#define XNANDPS_SET_CYCLES_SET_T2_SHIFT 8 /**< Set cycles set_t2
shift */
#define XNANDPS_SET_CYCLES_SET_T3_SHIFT 11 /**< Set cycles set_t3
shift */
#define XNANDPS_SET_CYCLES_SET_T4_SHIFT 14 /**< Set cycles set_t4
shift */
#define XNANDPS_SET_CYCLES_SET_T5_SHIFT 17 /**< Set cycles set_t5
shift */
#define XNANDPS_SET_CYCLES_SET_T6_SHIFT 20 /**< Set cycles set_t6
shift */
/* @} */
/** @name Set opmode register bit definitions and masks
* @{
*/
#define XNANDPS_SET_OPMODE_SET_MW_MASK 0x00000003 /**< Set
opmode set memory width mask */
#define XNANDPS_SET_OPMODE_SET_RD_SYNC_MASK 0x00000004 /**< Set
opmode set rd_sync mask */
#define XNANDPS_SET_OPMODE_SET_RD_BL_MASK 0x00000038 /**< Set
opmode set rd_bl mask */
#define XNANDPS_SET_OPMODE_SET_WR_SYNC_MASK 0x00000040 /**< Set
opmode set wr_sync mask */
#define XNANDPS_SET_OPMODE_SET_WR_BL_MASK 0x00000380 /**< Set
opmode set wr_bl mask */
#define XNANDPS_SET_OPMODE_SET_BAA_MASK 0x00000400 /**< Set
opmode set baa mask */
#define XNANDPS_SET_OPMODE_SET_ADV_MASK 0x00000800 /**< Set
opmode set adv mask */
#define XNANDPS_SET_OPMODE_SET_BLS_MASK 0x00001000 /**< Set
opmode set bls mask */
#define XNANDPS_SET_OPMODE_SET_BURST_ALIGN_MASK 0x0000E000 /**< Set
opmode set burst align mask */
#define XNANDPS_SET_OPMODE_MW_8_BITS 0x0 /**< Set opmode
memory width value for 8-bit flash */
#define XNANDPS_SET_OPMODE_MW_16_BITS 0x1 /**< Set opmode
memory width value for 16-bit flash */
#define XNANDPS_SET_OPMODE_MW_32_BITS 0x2 /**< Set opmode
memory width value for 32-bit flash */
/* @} */
/** @name Refresh period register bit definitions and masks
* @{
*/
#define XNANDPS_REFRESH_PERIOD_0_MASK 0x0000000F
/**< Interface 0 refresh period mask */
#define XNANDPS_REFRESH_PERIOD_1_MASK 0x0000000F
/**< Interface 1 refresh period mask */
/* @} */
/** @name Opmode register bit definitions and masks
* @{
*/
#define XNANDPS_OPMODE_MW_MASK 0x00000003
/**< Opmode Memory width mask */
#define XNANDPS_OPMODE_RD_SYNC_MASK 0x00000004
/**< Opmode rd_sync mask */
#define XNANDPS_OPMODE_RD_BL_MASK 0x00000038
/**< Opmode rd_bl mask */
#define XNANDPS_OPMODE_WR_SYNC_MASK 0x00000040
/**< Opmode wr_sync mask */
#define XNANDPS_OPMODE_WR_BL_MASK 0x00000380
/**< Opmode BAA mask */
#define XNANDPS_OPMODE_BAA_MASK 0x00000400
/**< Opmode ADV mask */
#define XNANDPS_OPMODE_ADV_MASK 0x00000800
/**< Opmode BLS mask */
#define XNANDPS_OPMODE_BLS_MASK 0x00001000
/**< Opmode Burst align mask */
#define XNANDPS_OPMODE_BURST_ALIGN_MASK 0x0000E000
/**< Opmode Address mask */
#define XNANDPS_OPMODE_ADDRESS_MASK 0x00FF0000
/**< Opmode Address match mask */
#define XNANDPS_OPMODE_ADDRESS_MATCH_MASK 0xFF000000
/* @} */
/** @name User status register bit definitions and masks
* @{
*/
#define XNANDPS_USER_STATUS_MASK 0x000000FF /**< User
status mask */
/* @} */
/** @name User config register bit definitions and masks
* @{
*/
#define XNANDPS_USER_CONFIG_MASK 0x000000FF /**< User
config mask */
/* @} */
/** @name ECC status register bit definitions and masks
* @{
*/
#define XNANDPS_ECC_STATUS_RAW_INT_STATUS_MASK 0x0000003F /**< Ecc
status raw_int_status mask */
#define XNANDPS_ECC_STATUS_MASK 0x00000040 /**< Ecc
status ecc_status mask */
#define XNANDPS_ECC_LAST_MASK 0x00000180 /**< Ecc
status ecc_last mask */
#define XNANDPS_ECC_READ_NOT_WRITE_MASK 0x00000200 /**< Ecc
status ecc_read_not_write mask */
#define XNANDPS_ECC_VALID_MASK 0x00007C00 /**< Ecc
status ecc_valid mask */
#define XNANDPS_ECC_FAIL_MASK 0x000F8000 /**< Ecc
status ecc_fail mask */
#define XNANDPS_ECC_CAN_CORRECT_MASK 0x01F00000 /**< Ecc
status ecc_can_correct mask */
#define XNANDPS_ECC_READ_MASK 0x37000000 /**< Ecc
status ecc_read mask */
/* @} */
/** @name ECC mem config register bit definitions and masks and shifts
* @{
*/
#define XNANDPS_ECC_MEMCFG_PAGE_SIZE_MASK 0x00000003
/**< Ecc cfg page_size mask */
#define XNANDPS_ECC_MEMCFG_ECC_MODE_MASK 0x0000000C
/**< Ecc cfg ecc_mode mask */
#define XNANDPS_ECC_MEMCFG_ECC_READ_END_MASK 0x00000010
/**< Ecc cfg ecc_read_end mask */
#define XNANDPS_ECC_MEMCFG_ECC_JUMP_MASK 0x00000060
/**< Ecc cfg ecc_jump mask */
#define XNANDPS_ECC_MEMCFG_IGNORE_ADD8_MASK 0x00000080
/**< Ecc cfg ecc_ignore_add_eight mask */
#define XNANDPS_ECC_MEMCFG_ECC_INT_PASS_MASK 0x00000100
/**< Ecc cfg ecc_int_pass mask */
#define XNANDPS_ECC_MEMCFG_ECC_INT_ABORT_MASK 0x00000200
/**< Ecc cfg ecc_int_abort mask */
#define XNANDPS_ECC_MEMCFG_ECC_EXTRA_BLOCK_MASK 0x00000400
/**< Ecc cfg ecc_extra_block mask */
#define XNANDPS_ECC_MEMCFG_ECC_EXTRA_BLOCK_SIZE_MASK 0x00001800
/**< Ecc cfg ecc_extra_block_size mask */
#define XNANDPS_ECC_MEMCFG_PAGE_SIZE_SHIFT 0
/**< Ecc cfg page_size shift */
#define XNANDPS_ECC_MEMCFG_ECC_MODE_SHIFT 2
/**< Ecc cfg ecc_mode shift */
#define XNANDPS_ECC_MEMCFG_ECC_READ_END_SHIFT 4
/**< Ecc cfg ecc_read_end shift */
#define XNANDPS_ECC_MEMCFG_ECC_JUMP_SHIFT 5
/**< Ecc cfg ecc_jump shift */
#define XNANDPS_ECC_MEMCFG_IGNORE_ADD8_SHIFT 7
/**< Ecc cfg ecc_ignore_add_eight shift */
#define XNANDPS_ECC_MEMCFG_ECC_INT_PASS_SHIFT 8
/**< Ecc cfg ecc_int_pass shift */
#define XNANDPS_ECC_MEMCFG_ECC_INT_ABORT_SHIFT 9
/**< Ecc cfg ecc_int_abort shift */
#define XNANDPS_ECC_MEMCFG_ECC_EXTRA_BLOCK_SHIFT 10
/**< Ecc cfg ecc_extra_block shift */
#define XNANDPS_ECC_MEMCFG_ECC_EXTRA_BLOCK_SIZE_SHIFT 11
/**< Ecc cfg ecc_extra_block_size shift */
#define XNANDPS_ECC_MEMCFG_PAGE_SIZE_512 0x1 /**< ECC cfg
page size value for 512 byte page */
#define XNANDPS_ECC_MEMCFG_PAGE_SIZE_1024 0x2 /**< ECC cfg
page size value for 1024 byte page */
#define XNANDPS_ECC_MEMCFG_PAGE_SIZE_2048 0x3 /**< ECC cfg
page size value for 2048 byte page */
/* @} */
/* @} */
/** @name ECC mem command1 register bit definitions and masks and shifts
* @{
*/
#define XNANDPS_ECC_MEMCOMMAND1_WR_CMD_MASK 0x000000FF
/**< Ecc command 1 nand_wr_cmd mask */
#define XNANDPS_ECC_MEMCOMMAND1_RD_CMD_MASK 0x0000FF00
/**< Ecc command 1 nand_rd_cmd mask */
#define XNANDPS_ECC_MEMCOMMAND1_RD_CMD_END_MASK 0x00FF0000
/**< Ecc command 1 nand_rd_cmd_end mask */
#define XNANDPS_ECC_MEMCOMMAND1_RD_CMD_END_VALID_MASK 0x01000000
/**< Ecc command 1 nand_rd_cmd_end_valid mask */
#define XNANDPS_ECC_MEMCOMMAND1_WR_CMD_SHIFT 0
/**< Ecc command 1 nand_wr_cmd shift */
#define XNANDPS_ECC_MEMCOMMAND1_RD_CMD_SHIFT 8
/**< Ecc command 1 nand_rd_cmd shift */
#define XNANDPS_ECC_MEMCOMMAND1_RD_CMD_END_SHIFT 16
/**< Ecc command 1 nand_rd_cmd_end shift */
#define XNANDPS_ECC_MEMCOMMAND1_RD_CMD_END_VALID_SHIFT 24
/**< Ecc command 1 nand_rd_cmd_end_valid shift */
/* @} */
/** @name ECC mem command2 register bit definitions and masks
* @{
*/
#define XNANDPS_ECC_MEMCOMMAND2_WR_COL_CHANGE_MASK 0x000000FF
/**< Ecc command2 nand_wr_col_change mask */
#define XNANDPS_ECC_MEMCOMMAND2_RD_COL_CHANGE_MASK 0x0000FF00
/**< Ecc command2 nand_rd_col_change mask */
#define XNANDPS_ECC_MEMCOMMAND2_RD_COL_CHANGE_END_MASK 0x00FF0000
/**< Ecc command2 nand_rd_col_change_end mask */
#define XNANDPS_ECC_MEMCOMMAND2_RD_COL_CHANGE_END_VALID_MASK 0x00FF0000
/**< Ecc command2 nand_rd_col_change_end_valid mask */
#define XNANDPS_ECC_MEMCOMMAND2_WR_COL_CHANGE_SHIFT 0
/**< Ecc command2 nand_wr_col_change shift */
#define XNANDPS_ECC_MEMCOMMAND2_RD_COL_CHANGE_SHIFT 8
/**< Ecc command2 nand_rd_col_change shift */
#define XNANDPS_ECC_MEMCOMMAND2_RD_COL_CHANGE_END_SHIFT 16
/**< Ecc command2 nand_rd_col_change_end shift */
#define XNANDPS_ECC_MEMCOMMAND2_RD_COL_CHANGE_END_VALID_SHIFT 24
/**< Ecc command2 nand_rd_col_change_end_valid shift */
/* @} */
/** @name ECC value register bit definitions and masks
* @{
*/
#define XNANDPS_ECC_VALUE_MASK 0x00FFFFFF
/**< Ecc value ecc_value mask */
#define XNANDPS_ECC_VALUE_CORRECT_MASK 0x08000000
/**< Ecc value ecc_correct mask */
#define XNANDPS_ECC_VALUE_FAIL_MASK 0x10000000
/**< Ecc value ecc_fail mask */
#define XNANDPS_ECC_VALUE_READ_MASK 0x20000000
/**< Ecc value ecc_read mask */
#define XNANDPS_ECC_VALUE_VALID_MASK 0x40000000
/**< Ecc value ecc_valid mask */
#define XNANDPS_ECC_VALUE_INT_MASK 0x80000000
/**< Ecc value ecc_int mask */
/* @} */
/** @name Peripheral ID register bit definitions and masks
* @{
*/
#define XNANDPS_PERIPH_ID_PART_NUM_MASK 0x00000FFF
/**< Peripheral ID part_num mask */
#define XNANDPS_PERIPH_ID_DESIGNER_ID_MASK 0x000FF000
/**< Peripheral ID designed id mask */
#define XNANDPS_PERIPH_ID_REVISION_MASK 0x00F00000
/**< Peripheral ID revision mask */
#define XNANDPS_PERIPH_ID_INTG_CFG_MASK 0x01000000
/**< Peripheral ID integration_cfg mask */
/* @} */
/** @name Peripheral ID register bit definitions and masks
* @{
*/
#define XNANDPS_PCELL_ID_MASK 0x000000FF
/**< Primecell identification register mask */
/* @} */
/**************************** Type Definitions *******************************/
/***************** Macros (Inline Functions) Definitions *********************/
#define XNandPs_ReadReg Xil_In32 /**< XNandPs Register register */
#define XNandPs_WriteReg Xil_Out32 /**< XNandPs register write */
/************************** Function Prototypes ******************************/
/************************** Variable Definitions *****************************/
#ifdef __cplusplus
}
#endif
#endif /* end of protection macro */

View file

@ -0,0 +1,654 @@
/******************************************************************************
*
* 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;
}

View file

@ -0,0 +1,314 @@
/******************************************************************************
*
* 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.h
*
* This file implements ONFI specific commands which are used to get the
* parameter page information.
*
* The following commands are supported currently.
* - Reset
* - Read ID
* - READ Parameter Page
* - Read Status
* - Change Read Column
* - Get Features
* - Set Features
*
* @note None
*
* <pre>
* MODIFICATION HISTORY:
*
* Ver Who Date Changes
* ----- ---- ---------- -----------------------------------------------
* 1.00a nm 12/10/2010 First release
* 1.04a nm 04/25/2013 Implemented PR# 699544. Added page cache read
* and program commands to ONFI command list.
* </pre>
*
******************************************************************************/
#ifndef ONFI_H /* prevent circular inclusions */
#define ONFI_H /* by using protection macros */
#ifdef __cplusplus
extern "C" {
#endif
/***************************** Include Files *********************************/
#include "xnandps.h"
/************************** Constant Definitions *****************************/
/*
* Standard ONFI NAND flash commands
*/
/*
* Mandatory commands
*/
#define ONFI_CMD_READ1 0x00 /**< ONFI Read command
(1st cycle) */
#define ONFI_CMD_READ2 0x30 /**< ONFI Read command
(2nd cycle) */
#define ONFI_CMD_CHANGE_READ_COLUMN1 0x05 /**< ONFI Change Read
Column command (1st
cycle) */
#define ONFI_CMD_CHANGE_READ_COLUMN2 0xE0 /**< ONFI Change Read
Column command (2nd
cycle) */
#define ONFI_CMD_BLOCK_ERASE1 0x60 /**< ONFI Block Erase
(1st cycle) */
#define ONFI_CMD_BLOCK_ERASE2 0xD0 /**< ONFI Block Erase
(2nd cycle) */
#define ONFI_CMD_READ_STATUS 0x70 /**< ONFI Read status
command */
#define ONFI_CMD_PAGE_PROG1 0x80 /**< ONFI Page Program
command (1st cycle)
*/
#define ONFI_CMD_PAGE_PROG2 0x10 /**< ONFI Page Program
command (2nd cycle)
*/
#define ONFI_CMD_CHANGE_WRITE_COLUMN 0x85 /**< ONFI Change Write
Column command */
#define ONFI_CMD_READ_ID 0x90 /**< ONFI Read ID
command */
#define ONFI_CMD_READ_PARAM_PAGE 0xEC /**< ONFI Read
Parameter Page
command */
#define ONFI_CMD_RESET 0xFF /**< ONFI Reset
command */
/*
* Optional commands
*/
#define ONFI_CMD_COPYBACK_READ1 0x00 /**< ONFI Copyback Read
command (1st cycle)
*/
#define ONFI_CMD_COPYBACK_READ2 0x35 /**< ONFI Copyback Read
command (2nd cycle)
*/
#define ONFI_CMD_READ_CACHE_ENHANCED1 0x00 /**< ONFI Read cache
enhanced command (1st
cycle) */
#define ONFI_CMD_READ_CACHE_ENHANCED2 0x31 /**< ONFI Read cache
enhanced command (2nd
cycle) */
#define ONFI_CMD_READ_CACHE 0x31 /**< ONFI Read cache
command */
#define ONFI_CMD_READ_CACHE_END 0x3F /**< ONFI Read cache
end command */
#define ONFI_CMD_BLOCK_ERASE_INTERLEAVED2 0xD1 /**< ONFI Block Erase
interleaved command
(2nd cycle) */
#define ONFI_CMD_READ_STATUS_ENHANCED 0x78 /**< ONFI Read Status
enhanced command */
#define ONFI_CMD_PAGE_PROGRAM_INTERLEAVED2 0x11 /**< ONFI Page Program
interleaved command
(2nd cycle) */
#define ONFI_CMD_PAGE_CACHE_PROGRAM1 0x80 /**< ONFI Page cache
program (1st cycle)
*/
#define ONFI_CMD_PAGE_CACHE_PROGRAM2 0x15 /**< ONFI Page cache
program (2nd cycle)
*/
#define ONFI_CMD_COPYBACK_PROGRAM1 0x85 /**< ONFI Copyback
program command (1st
cycle) */
#define ONFI_CMD_COPYBACK_PROGRAM2 0x10 /**< ONFI Copyback
program command (2nd
cycle) */
#define ONFI_CMD_COPYBACK_PROGRAM_INTERLEAVED2 0x11 /**< ONFI Copyback
program interleaved
command (2nd cycle)
*/
#define ONFI_CMD_READ_UNIQUEID 0xED /**< ONFI Read Unique
ID command */
#define ONFI_CMD_GET_FEATURES 0xEE /**< ONFI Get features
command */
#define ONFI_CMD_SET_FEATURES 0xEF /**< ONFI Set features
command */
/*
* ONFI Status Register bit offsets
*/
#define ONFI_STATUS_FAIL 0x01 /**< ONFI Status
Register : FAIL */
#define ONFI_STATUS_FAILC 0x02 /**< ONFI Status
Register : FAILC */
#define ONFI_STATUS_ARDY 0x20 /**< ONFI Status
Register : ARDY */
#define ONFI_STATUS_RDY 0x40 /**< ONFI Status
Register : RDY */
#define ONFI_STATUS_WP 0x80 /**< ONFI Status
Register : WR */
/*
* ONFI constants
*/
#define ONFI_ID_LEN 4 /**< ONFI ID Length */
#define ONFI_CRC_INIT 0x4F4E /**< ONFI CRC16
Inititialization constant */
#define ONFI_CRC_POLYNOM 0x8005 /**< ONFI CRC16 polynomial */
#define ONFI_CRC_ORDER 16 /**< ONFI CRC16 order */
#define ONFI_PARAM_PAGE_LEN 256 /**< ONFI Parameter page length
*/
#define ONFI_CRC_LEN 254 /**< ONFI CRC16 length */
#define ONFI_SIGNATURE_LEN 4 /**< ONFI Signature Length */
/**
* This enum defines the onfi commands.
*/
enum OnfiCommandsEnum {
READ=0, /**< ONFI Read */
CHANGE_READ_COLUMN, /**< ONFI Change Read Column */
BLOCK_ERASE, /**< ONFI Block Erase */
READ_STATUS, /**< ONFI Read Status */
PAGE_PROGRAM, /**< ONFI Page Program */
CHANGE_WRITE_COLUMN, /**< ONFI Change Write Column */
READ_ID, /**< ONFI Read ID */
READ_PARAM_PAGE, /**< ONFI Read Parameter Page */
RESET, /**< ONFI Reset */
GET_FEATURES, /**< ONFI Get Features */
SET_FEATURES, /**< ONFI Set Features */
READ_CACHE_RANDOM, /**< ONFI Read page cache random */
READ_CACHE_END_SEQ, /**< ONFI Read page cache end */
PAGE_CACHE_PROGRAM /**< ONFI Program page cache */
};
/**************************** Type Definitions *******************************/
/**
* ONFI 1.0 support
*/
/*
* Parameter page structure of ONFI 1.0 specification.
* Enhanced this sturcture to include ONFI 2.3 information for EZ NAND support.
*/
typedef struct {
/*
* Revision information and features block
*/
u8 Signature[4]; /**< Parameter page signature */
u16 Revision; /**< Revision Number */
u16 Features; /**< Features supported */
u16 OptionalCmds; /**< Optional commands supported */
u8 Reserved0[2]; /**< ONFI 2.3: Reserved */
u16 ExtParamPageLen; /**< ONFI 2.3: extended parameter page
length */
u8 NumOfParamPages; /**< ONFI 2.3: No of parameter pages */
u8 Reserved1[17]; /**< Reserved */
/*
* Manufacturer information block
*/
u8 DeviceManufacturer[12]; /**< Device manufacturer */
u8 DeviceModel[20]; /**< Device model */
u8 JedecManufacturerId; /**< JEDEC Manufacturer ID */
u8 DateCode[2]; /**< Date code */
u8 Reserved2[13]; /**< Reserved */
/*
* Memory organization block
*/
u32 BytesPerPage; /**< Number of data bytes per page */
u16 SpareBytesPerPage; /**< Number of spare bytes per page */
u32 BytesPerPartialPage; /**< Number of data bytes per partial
page */
u16 SpareBytesPerPartialPage; /**< Number of spare bytes per partial
page */
u32 PagesPerBlock; /**< Number of pages per block */
u32 BlocksPerLun; /**< Number of blocks per logical unit
(LUN) */
u8 NumLuns; /**< Number of LUN's */
u8 AddrCycles; /**< Number of address cycles */
u8 BitsPerCell; /**< Number of bits per cell */
u16 MaxBadBlocksPerLun; /**< Bad blocks maximum per LUN */
u16 BlockEndurance; /**< Block endurance */
u8 GuaranteedValidBlock; /**< Guaranteed valid blocks at
beginning of target */
u16 BlockEnduranceGvb; /**< Block endurance for guaranteed
valid block */
u8 ProgramsPerPage; /**< Number of programs per page */
u8 PartialProgAttr; /**< Partial programming attributes */
u8 EccBits; /**< Number of bits ECC
correctability */
u8 InterleavedAddrBits; /**< Number of interleaved address
bits */
u8 InterleavedOperation; /**< Interleaved operation
attributes */
u8 EzNandSupport; /**< ONFI 2.3: EZ NAND support
parameters */
u8 Reserved3[12]; /**< Reserved */
/*
* Electrical parameters block
*/
u8 IOPinCapacitance; /**< I/O pin capacitance */
u16 TimingMode; /**< Timing mode support */
u16 PagecacheTimingMode; /**< Program cache timing mode */
u16 TProg; /**< Maximum page program time */
u16 TBers; /**< Maximum block erase time */
u16 TR; /**< Maximum page read time */
u16 TCcs; /**< Maximum change column setup
time */
u16 SynTimingMode; /**< ONFI 2.3: Source synchronous
timing mode support */
u8 SynFeatures; /**< ONFI 2.3: Source synchronous
features */
u16 ClkInputPinCap; /**< ONFI 2.3: CLK input pin
capacitance */
u16 IOPinCap; /**< ONFI 2.3: I/O pin capacitance */
u16 InputPinCap; /**< ONFI 2.3: Input pin capacitance
typical */
u8 InputPinCapMax; /**< ONFI 2.3: Input pin capacitance
maximum */
u8 DrvStrength; /**< ONFI 2.3: Driver strength
support */
u16 TMr; /**< ONFI 2.3: Maximum multi-plane
read time */
u16 TAdl; /**< ONFI 2.3: Program page register
clear enhancement value */
u16 TEr; /**< ONFI 2.3: Typical page read time
for EZ NAND */
u8 Reserved4[6]; /**< Reserved */
/*
* Vendor block
*/
u16 VendorRevisionNum; /**< Vendor specific revision
number */
u8 VendorSpecific[88]; /**< Vendor specific */
u16 Crc; /**< Integrity CRC */
}__attribute__((packed))OnfiNand_Geometry;
/************************** Function Prototypes ******************************/
#ifdef __cplusplus
}
#endif
#endif /* end of protection macro */

View file

@ -0,0 +1,98 @@
/******************************************************************************
*
* 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_sinit.c
*
* This file contains the implementation of the XNand driver's static
* initialization functionality.
*
* @note None.
*
* <pre>
*
* MODIFICATION HISTORY:
*
* Ver Who Date Changes
* ----- ---- ---------- -----------------------------------------------
* 1.00a nm 12/10/2010 First release
* </pre>
*
******************************************************************************/
/***************************** Include Files *********************************/
#include "xparameters.h"
#include "xnandps.h"
/************************** Constant Definitions *****************************/
/**************************** Type Definitions *******************************/
/***************** Macros (Inline Functions) Definitions *********************/
/************************** Function Prototypes ******************************/
/************************** Variable Definitions *****************************/
extern XNandPs_Config XNandPs_ConfigTable[];
/*****************************************************************************/
/**
*
* This function looks up the device configuration based on the unique device ID.
* The table XNandPs_ConfigTable contains the configuration info for each device
* in the system.
*
* @param DeviceId contains the ID of the device for which the
* device configuration pointer is to be returned.
*
* @return
* - A pointer to the configuration found.
* - NULL if the specified device ID was not found.
*
* @note None.
*
******************************************************************************/
XNandPs_Config *XNandPs_LookupConfig(u16 DeviceId)
{
XNandPs_Config *CfgPtr = NULL;
u32 Index;
for (Index=0; Index < XPAR_XNANDPS_NUM_INSTANCES; Index++) {
if (XNandPs_ConfigTable[Index].DeviceId == DeviceId) {
CfgPtr = &XNandPs_ConfigTable[Index];
break;
}
}
return CfgPtr;
}