diff --git a/XilinxProcessorIPLib/drivers/nandps8_v2_0/data/nandps8.mdd b/XilinxProcessorIPLib/drivers/nandps8_v2_0/data/nandps8.mdd new file mode 100755 index 00000000..bcec1446 --- /dev/null +++ b/XilinxProcessorIPLib/drivers/nandps8_v2_0/data/nandps8.mdd @@ -0,0 +1,54 @@ +############################################################################### +# +# Copyright (C) 2014 Xilinx, Inc. All rights reserved. +# +# This file contains confidential and proprietary information of Xilinx, Inc. +# and is protected under U.S. and international copyright and other +# intellectual property laws. +# +# DISCLAIMER +# This disclaimer is not a license and does not grant any rights to the +# materials distributed herewith. Except as otherwise provided in a valid +# license issued to you by Xilinx, and to the maximum extent permitted by +# applicable law: (1) THESE MATERIALS ARE MADE AVAILABLE "AS IS" AND WITH ALL +# FAULTS, AND XILINX HEREBY DISCLAIMS ALL WARRANTIES AND CONDITIONS, EXPRESS, +# IMPLIED, OR STATUTORY, INCLUDING BUT NOT LIMITED TO WARRANTIES OF +# MERCHANTABILITY, NON- INFRINGEMENT, OR FITNESS FOR ANY PARTICULAR PURPOSE; +# and +# (2) Xilinx shall not be liable (whether in contract or tort, including +# negligence, or under any other theory of liability) for any loss or damage +# of any kind or nature related to, arising under or in connection with these +# materials, including for any direct, or any indirect, special, incidental, +# or consequential loss or damage (including loss of data, profits, +# goodwill, or any type of loss or damage suffered as a result of any +# action brought by a third party) even if such damage or loss was +# reasonably foreseeable or Xilinx had been advised of the possibility +# of the same. +# +# CRITICAL APPLICATIONS +# Xilinx products are not designed or intended to be fail- safe, or for use +# in any application requiring fail-safe performance, such as life-support +# or safety devices or systems, Class III medical devices, nuclear +# facilities, applications related to the deployment of airbags, or any +# other applications that could lead to death, personal injury, or severe +# property or environmental damage (individually and collectively, +# "Critical Applications"). Customer assumes the sole risk and liability +# of any use of Xilinx products in Critical Applications, subject only to +# applicable laws and regulations governing limitations on product liability. +# +# THIS COPYRIGHT NOTICE AND DISCLAIMER MUST BE RETAINED AS PART +# OF THIS FILE AT ALL TIMES. +# +############################################################################### + +OPTION psf_version = 2.1; + +BEGIN driver nandps8 + + OPTION supported_peripherals = (ps8_nand pss_nand); + OPTION driver_state = ACTIVE; + OPTION copyfiles = all; + OPTION VERSION = 2.0; + OPTION NAME = nandps8; + +END driver diff --git a/XilinxProcessorIPLib/drivers/nandps8_v2_0/data/nandps8.tcl b/XilinxProcessorIPLib/drivers/nandps8_v2_0/data/nandps8.tcl new file mode 100755 index 00000000..fbd52974 --- /dev/null +++ b/XilinxProcessorIPLib/drivers/nandps8_v2_0/data/nandps8.tcl @@ -0,0 +1,62 @@ +############################################################################### +# +# Copyright (C) 2014 Xilinx, Inc. All rights reserved. +# +# This file contains confidential and proprietary information of Xilinx, Inc. +# and is protected under U.S. and international copyright and other +# intellectual property laws. +# +# DISCLAIMER +# This disclaimer is not a license and does not grant any rights to the +# materials distributed herewith. Except as otherwise provided in a valid +# license issued to you by Xilinx, and to the maximum extent permitted by +# applicable law: (1) THESE MATERIALS ARE MADE AVAILABLE "AS IS" AND WITH ALL +# FAULTS, AND XILINX HEREBY DISCLAIMS ALL WARRANTIES AND CONDITIONS, EXPRESS, +# IMPLIED, OR STATUTORY, INCLUDING BUT NOT LIMITED TO WARRANTIES OF +# MERCHANTABILITY, NON- INFRINGEMENT, OR FITNESS FOR ANY PARTICULAR PURPOSE; +# and +# (2) Xilinx shall not be liable (whether in contract or tort, including +# negligence, or under any other theory of liability) for any loss or damage +# of any kind or nature related to, arising under or in connection with these +# materials, including for any direct, or any indirect, special, incidental, +# or consequential loss or damage (including loss of data, profits, +# goodwill, or any type of loss or damage suffered as a result of any +# action brought by a third party) even if such damage or loss was +# reasonably foreseeable or Xilinx had been advised of the possibility +# of the same. +# +# CRITICAL APPLICATIONS +# Xilinx products are not designed or intended to be fail- safe, or for use +# in any application requiring fail-safe performance, such as life-support +# or safety devices or systems, Class III medical devices, nuclear +# facilities, applications related to the deployment of airbags, or any +# other applications that could lead to death, personal injury, or severe +# property or environmental damage (individually and collectively, +# "Critical Applications"). Customer assumes the sole risk and liability +# of any use of Xilinx products in Critical Applications, subject only to +# applicable laws and regulations governing limitations on product liability. +# +# THIS COPYRIGHT NOTICE AND DISCLAIMER MUST BE RETAINED AS PART +# OF THIS FILE AT ALL TIMES. +# +############################################################################### + +############################################################################## +# +# Modification History +# +# Ver Who Date Changes +# ----- ---- -------- ----------------------------------------------- +# 1.00a nm 05/06/14 Created +# +############################################################################## + +#uses "xillib.tcl" + +proc generate {drv_handle} { + xdefine_zynq_include_file $drv_handle "xparameters.h" "XNandPs8" "NUM_INSTANCES" "DEVICE_ID" "C_S_AXI_BASEADDR" "C_S_AXI_HIGHADDR" + + xdefine_zynq_config_file $drv_handle "xnandps_g.c" "XNandPs8" "DEVICE_ID" "C_S_AXI_BASEADDR" + + xdefine_zynq_canonical_xpars $drv_handle "xparameters.h" "XNandPs8" "DEVICE_ID" "C_S_AXI_BASEADDR" "C_S_AXI_HIGHADDR" +} diff --git a/XilinxProcessorIPLib/drivers/nandps8_v2_0/examples/Makefile b/XilinxProcessorIPLib/drivers/nandps8_v2_0/examples/Makefile new file mode 100755 index 00000000..e32824d0 --- /dev/null +++ b/XilinxProcessorIPLib/drivers/nandps8_v2_0/examples/Makefile @@ -0,0 +1,91 @@ +#/****************************************************************************** +#* +#* Copyright (C) 2014 Xilinx, Inc. All rights reserved. +#* +#* This file contains confidential and proprietary information of Xilinx, Inc. +#* and is protected under U.S. and international copyright and other +#* intellectual property laws. +#* +#* DISCLAIMER +#* This disclaimer is not a license and does not grant any rights to the +#* materials distributed herewith. Except as otherwise provided in a valid +#* license issued to you by Xilinx, and to the maximum extent permitted by +#* applicable law: (1) THESE MATERIALS ARE MADE AVAILABLE "AS IS" AND WITH ALL +#* FAULTS, AND XILINX HEREBY DISCLAIMS ALL WARRANTIES AND CONDITIONS, EXPRESS, +#* IMPLIED, OR STATUTORY, INCLUDING BUT NOT LIMITED TO WARRANTIES OF +#* MERCHANTABILITY, NON- INFRINGEMENT, OR FITNESS FOR ANY PARTICULAR PURPOSE; +#* and +#* (2) Xilinx shall not be liable (whether in contract or tort, including +#* negligence, or under any other theory of liability) for any loss or damage +#* of any kind or nature related to, arising under or in connection with these +#* materials, including for any direct, or any indirect, special, incidental, +#* or consequential loss or damage (including loss of data, profits, +#* goodwill, or any type of loss or damage suffered as a result of any +#* action brought by a third party) even if such damage or loss was +#* reasonably foreseeable or Xilinx had been advised of the possibility +#* of the same. +#* +#* CRITICAL APPLICATIONS +#* Xilinx products are not designed or intended to be fail- safe, or for use +#* in any application requiring fail-safe performance, such as life-support +#* or safety devices or systems, Class III medical devices, nuclear +#* facilities, applications related to the deployment of airbags, or any +#* other applications that could lead to death, personal injury, or severe +#* property or environmental damage (individually and collectively, +#* "Critical Applications"). Customer assumes the sole risk and liability +#* of any use of Xilinx products in Critical Applications, subject only to +#* applicable laws and regulations governing limitations on product liability. +#* +#* THIS COPYRIGHT NOTICE AND DISCLAIMER MUST BE RETAINED AS PART +#* OF THIS FILE AT ALL TIMES. +#* +#******************************************************************************/ + +c_SOURCES := $(wildcard *.c) +INCLUDES := $(wildcard *.h) +EXECS := xnandps8_example.elf +OBJS := $(patsubst %.c, %.o, $(c_SOURCES)) + +ifeq '$(PROC)' 'r5' +BSP_DIR := ../../../../build/target/cortex-r5 +LSCRIPT_DIR := ../../../../build/scripts/bsp_utils +CC := ${CROSS_COMPILE}gcc +AS := ${CROSS_COMPILE}gcc +LINKER := ${CROSS_COMPILE}gcc +AR := ${CROSS_COMPILE}ar +LIBPATH := $(BSP_DIR)/ps8_cortexr5_0/lib +DUMP := ${CROSS_COMPILE}objdump -xSD +INCLUDEPATH := -I$(BSP_DIR)/ps8_cortexr5_0/include -I. -I./include/ +CFLAGS = -Wall -O0 -g3 -fmessage-length=0 \ + -mcpu=cortex-r5 -mfloat-abi=softfp +LDFLAGS := -Wl,--start-group,-lxil,-lxilffs,-lgcc,-lc,--end-group -L$(LIBPATH) -L./ +LSCRIPT := -T$(LSCRIPT_DIR)/LinkScr.ld +endif + +ifeq '$(PROC)' 'a53' +BSP_DIR := ../../../../build/target/cortex-a53 +LSCRIPT_DIR := ../../../../build/scripts/bsp_utils +CC := ${CROSS_COMPILE}gcc +AS := ${CROSS_COMPILE}gcc +LINKER := ${CROSS_COMPILE}gcc +AR := ${CROSS_COMPILE}gcc +DUMP := ${CROSS_COMPILE}objdump -xSD +INCLUDEPATH := -I$(BSP_DIR)/ps8_cortexa53_0/include -I. -I./include/ +LIBPATH := $(BSP_DIR)/ps8_cortexa53_0/lib +CFLAGS = -Wall -O0 -g3 -fmessage-length=0 \ + -march=armv8-a +LSCRIPT := -T$(LSCRIPT_DIR)/DDRA53_LinkScr.ld +LDFLAGS := -Wl,--start-group,-lxil,-lxilffs,-lgcc,-lc,--end-group -L$(LIBPATH) -L./ +endif + +all: $(EXECS) + +%.elf: %.o $(INCLUDES) + $(LINKER) $< $(CC_FLAGS) $(LDFLAGS) $(LSCRIPT) -o $@ + $(DUMP) $@ > dump + +%.o:%.c + $(CC) $(CC_FLAGS) $(CFLAGS) $(ECFLAGS) -c $< -o $@ $(INCLUDEPATH) + +clean: + rm -rf $(OBJS) *.elf dump diff --git a/XilinxProcessorIPLib/drivers/nandps8_v2_0/examples/xnandps8_example.c b/XilinxProcessorIPLib/drivers/nandps8_v2_0/examples/xnandps8_example.c new file mode 100755 index 00000000..6149ceac --- /dev/null +++ b/XilinxProcessorIPLib/drivers/nandps8_v2_0/examples/xnandps8_example.c @@ -0,0 +1,238 @@ +/****************************************************************************** +* +* Copyright (C) 2014 Xilinx, Inc. All rights reserved. +* +* This file contains confidential and proprietary information of Xilinx, Inc. +* and is protected under U.S. and international copyright and other +* intellectual property laws. +* +* DISCLAIMER +* This disclaimer is not a license and does not grant any rights to the +* materials distributed herewith. Except as otherwise provided in a valid +* license issued to you by Xilinx, and to the maximum extent permitted by +* applicable law: (1) THESE MATERIALS ARE MADE AVAILABLE "AS IS" AND WITH ALL +* FAULTS, AND XILINX HEREBY DISCLAIMS ALL WARRANTIES AND CONDITIONS, EXPRESS, +* IMPLIED, OR STATUTORY, INCLUDING BUT NOT LIMITED TO WARRANTIES OF +* MERCHANTABILITY, NON- INFRINGEMENT, OR FITNESS FOR ANY PARTICULAR PURPOSE; +* and +* (2) Xilinx shall not be liable (whether in contract or tort, including +* negligence, or under any other theory of liability) for any loss or damage +* of any kind or nature related to, arising under or in connection with these +* materials, including for any direct, or any indirect, special, incidental, +* or consequential loss or damage (including loss of data, profits, +* goodwill, or any type of loss or damage suffered as a result of any +* action brought by a third party) even if such damage or loss was +* reasonably foreseeable or Xilinx had been advised of the possibility +* of the same. +* +* CRITICAL APPLICATIONS +* Xilinx products are not designed or intended to be fail- safe, or for use +* in any application requiring fail-safe performance, such as life-support +* or safety devices or systems, Class III medical devices, nuclear +* facilities, applications related to the deployment of airbags, or any +* other applications that could lead to death, personal injury, or severe +* property or environmental damage (individually and collectively, +* "Critical Applications"). Customer assumes the sole risk and liability +* of any use of Xilinx products in Critical Applications, subject only to +* applicable laws and regulations governing limitations on product liability. +* +* THIS COPYRIGHT NOTICE AND DISCLAIMER MUST BE RETAINED AS PART +* OF THIS FILE AT ALL TIMES. +* +******************************************************************************/ + +/****************************************************************************** +* +* @file xnandps8_example.c +* +* This file contains a design example using the NAND driver (XNandPs8). +* This example tests the erase, read and write features of the controller. +* The flash is erased and written. The data is read back and compared +* with the data written for correctness. +* +* @note +* +* None. +* +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who  Date        Changes
+* ----- ---- ----------  -----------------------------------------------
+* 1.0  nm   05/06/2014  First release.
+*
+* +******************************************************************************/ + +/***************************** Include Files *********************************/ +#include +#include +#include +#include +#include +#include "xnandps8.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 0U +#define TEST_BUF_SIZE 0x8000U +#define TEST_PAGE_START 0x2U + +/**************************** Type Definitions *******************************/ + +/***************** Macros (Inline Functions) Definitions *********************/ + +/************************** Function Prototypes ******************************/ + +s32 NandReadWriteExample(u16 NandDeviceId); + +/************************** Variable Definitions *****************************/ + +XNandPs8 NandInstance; /* XNand Instance */ +XNandPs8 *NandInstPtr = &NandInstance; + +/* + * Buffers used during read and write transactions. + */ +u8 ReadBuffer[TEST_BUF_SIZE] __attribute__ ((aligned(64))); /**< Block sized Read buffer */ +u8 WriteBuffer[TEST_BUF_SIZE] __attribute__ ((aligned(64))); /**< 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. +* +*****************************************************************************/ +s32 main(void) +{ + s32 Status = XST_FAILURE; + + 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"); + goto Out; + } + + Status = XST_SUCCESS; + xil_printf("Successfully ran Nand Flash Read Write Example Test\r\n"); +Out: + return Status; +} + +/****************************************************************************/ +/** +* +* This function runs a test on the NAND flash device using the basic driver +* functions in polled mode. +* The function does the following tasks: +* - Initialize the driver. +* - Erase the flash. +* - Write data to the flash. +* - Read back the data from the flash. +* - Compare the data read against the data Written. +* +* @param NandDeviceId is is the XPAR__DEVICE_ID value +* from xparameters.h. +* +* @return +* - XST_SUCCESS if successful. +* - XST_FAILURE if failed. +* +* @note +* None +* +****************************************************************************/ +s32 NandReadWriteExample(u16 NandDeviceId) +{ + s32 Status = XST_FAILURE; + XNandPs8_Config *Config; + u32 Index; + u64 Offset; + u32 Length; + + Config = XNandPs8_LookupConfig(NandDeviceId); + if (Config == NULL) { + Status = XST_FAILURE; + goto Out; + } + /* + * Initialize the flash driver. + */ + Status = XNandPs8_CfgInitialize(NandInstPtr, Config, + Config->BaseAddress); + if (Status != XST_SUCCESS) { + goto Out; + } + + XNandPs8_EnableDmaMode(NandInstPtr); + + Offset = (u64)(TEST_PAGE_START * NandInstPtr->Geometry.BytesPerPage); + Length = TEST_BUF_SIZE; + + /* + * Initialize the write buffer + */ + for (Index = 0; Index < Length;Index++) { + WriteBuffer[Index] = (u8) (rand() % 256); + } + /* + * Erase the flash + */ + Status = XNandPs8_Erase(NandInstPtr, (u64)Offset, (u64)Length); + if (Status != XST_SUCCESS) { + goto Out; + } + /* + * Write to flash + */ + Status = XNandPs8_Write(NandInstPtr, (u64)Offset, (u64)Length, + &WriteBuffer[0]); + if (Status != XST_SUCCESS) { + goto Out; + } + /* + * Read the flash after writing + */ + Status = XNandPs8_Read(NandInstPtr, (u64)Offset, (u64)Length, + &ReadBuffer[0]); + if (Status != XST_SUCCESS) { + goto Out; + } + /* + * Compare the results + */ + for (Index = 0U; Index < Length;Index++) { + if (ReadBuffer[Index] != WriteBuffer[Index]) { + xil_printf("Index 0x%x: Read 0x%x != Write 0x%x\n", + Index, + ReadBuffer[Index], + WriteBuffer[Index]); + Status = XST_FAILURE; + goto Out; + } + } + + Status = XST_SUCCESS; +Out: + return Status; +} diff --git a/XilinxProcessorIPLib/drivers/nandps8_v2_0/intgTest/README.txt b/XilinxProcessorIPLib/drivers/nandps8_v2_0/intgTest/README.txt new file mode 100755 index 00000000..3946e2be --- /dev/null +++ b/XilinxProcessorIPLib/drivers/nandps8_v2_0/intgTest/README.txt @@ -0,0 +1,14 @@ +NandPs8 Integration test + +- On A53 processors use the linker script for DDR region to run the integration test + With OCM linker script which is the default linker script, the integration test may hang. + In order to run on OCM, you can use Xil_DCacheDisable() in the main and run the integration test. + +- On R5 processors, you may get compilation error for bsp stating "undefined reference to `end'" + Add end = .; at the end of the linker script to remove this error + + } > ps8_ocm_ram_0_S_AXI_BASEADDR + + _end = .; + end = .; +} diff --git a/XilinxProcessorIPLib/drivers/nandps8_v2_0/intgTest/ct.h b/XilinxProcessorIPLib/drivers/nandps8_v2_0/intgTest/ct.h new file mode 100755 index 00000000..5f10f900 --- /dev/null +++ b/XilinxProcessorIPLib/drivers/nandps8_v2_0/intgTest/ct.h @@ -0,0 +1,586 @@ +/****************************************************************************** +* +* (c) Copyright 2010-14 Xilinx, Inc. All rights reserved. +* +* This file contains confidential and proprietary information of Xilinx, Inc. +* and is protected under U.S. and international copyright and other +* intellectual property laws. +* +* DISCLAIMER +* This disclaimer is not a license and does not grant any rights to the +* materials distributed herewith. Except as otherwise provided in a valid +* license issued to you by Xilinx, and to the maximum extent permitted by +* applicable law: (1) THESE MATERIALS ARE MADE AVAILABLE "AS IS" AND WITH ALL +* FAULTS, AND XILINX HEREBY DISCLAIMS ALL WARRANTIES AND CONDITIONS, EXPRESS, +* IMPLIED, OR STATUTORY, INCLUDING BUT NOT LIMITED TO WARRANTIES OF +* MERCHANTABILITY, NON-INFRINGEMENT, OR FITNESS FOR ANY PARTICULAR PURPOSE; +* and (2) Xilinx shall not be liable (whether in contract or tort, including +* negligence, or under any other theory of liability) for any loss or damage +* of any kind or nature related to, arising under or in connection with these +* materials, including for any direct, or any indirect, special, incidental, +* or consequential loss or damage (including loss of data, profits, goodwill, +* or any type of loss or damage suffered as a result of any action brought by +* a third party) even if such damage or loss was reasonably foreseeable or +* Xilinx had been advised of the possibility of the same. +* +* CRITICAL APPLICATIONS +* Xilinx products are not designed or intended to be fail-safe, or for use in +* any application requiring fail-safe performance, such as life-support or +* safety devices or systems, Class III medical devices, nuclear facilities, +* applications related to the deployment of airbags, or any other applications +* that could lead to death, personal injury, or severe property or +* environmental damage (individually and collectively, "Critical +* Applications"). Customer assumes the sole risk and liability of any use of +* Xilinx products in Critical Applications, subject only to applicable laws +* and regulations governing limitations on product liability. +* +* THIS COPYRIGHT NOTICE AND DISCLAIMER MUST BE RETAINED AS PART OF THIS FILE +* AT ALL TIMES. +* +******************************************************************************/ +/*****************************************************************************/ +/** +* +* @file ct.h +* +* Code test (CT) utility driver. +* +* This package is intended to help designers test their Xilinx device drivers +* in unit and integration testing environments. The macros and functions +* provide the following services: +* +* - Automated data comparison +* - Xilinx driver assert testing +* - Interrupt utilities +* - Error & message logging +* - Test sequencing utilities +* - Timing utilities +* +* The main benefit of this package is to simplify test code and make it easier +* for the tester to get more coverage in their integration and unit testing +* without having to replicate common testing constructs. +* +* Integrating CT Source code +* +* This package consists of this header file and an implementation file. The +* implementation can be operating system specific. When including this package +* in your test, use this file and one of the CT implementation files such as +* ct_vxworks.c. +* +* There are GNU specific "C" extensions used in this package and as a result +* make it non-ANSI compliment. The tester must compile this package and their +* other test code with the GNU compiler suite. +* +* The CT package requires that there be available standard header files +* stdio.h, string.h, and stdarg.h. +* +* +* Setup and Test Sequencing +* +* Before calling any comparison or utility function in this package, the tester +* should call CT_Init() to initialize the library. This function only needs to +* be called once. +* +* During tests, your code may be segmented into sub tests where you would want +* separate out the results. At the end of all sub tests, you may want to +summarize +* all the tests run. The following pseudo code shows how this is done with CT +* sequencing function calls: +* +*
+*
+*    CT_Init();
+*
+*    // Subtest #1
+*    CT_TestReset("This is my Subtest #1");
+*      ...
+*      // Subtest code
+*      ...
+*    Failures = CT_GetTestFailures();
+*    CT_Message("Subtest #1 had %d failures\r\n", Failures);
+*
+*    // Subtest #2
+*    CT_TestReset("This is my Subtest #2");
+*      ...
+*      // Subtest code
+*      ...
+*    Failures = CT_GetTestFailures();
+*    CT_Message("Subtest #2 had %d failures\r\n", Failures);
+*
+*    Failures = CT_GetTotalFailures();
+*    CT_Message("Total test failures = %d\r\n", Failures);
+*
+* 
+* +* General Usage +* +* The heart of this package utilizes macros to compare variables or memory +* areas. For example, +* +*
+*
+*     CT_CMP_NUM(int, ActualValue, ExpectedValue);
+*
+* 
+* +* compares two values of type int. If they are not equal, then an error message +* is logged and an internal counter is incremented. If they are equal, then the +* test proceeds as if nothing had occurred. Other examples: +* +*
+*
+*     CT_CMP_NUM(int, *ActualPtr, 5);
+*     CT_CMP_NUM(int*, ActualPtr, 0x20002100);
+*
+* 
+* +* With each failure, a descriptive message is printed along with the line number +* of the invoking code. +* +* If the tester needs to make a comparison manually, then they can use the +* CT_LOG_FAILURE() macro to note the error in case the comparison is negative. +* If the tester needs to emit an informational message, then they can use the +* CT_Mesage() function. Calling this function does not increment error counters. +* +* +* Message Logging +* +* This package uses the printf() library for message logging. +* +* Ideally, the tester's environment should include some sort of UART. By +* default CT utilizes a pre-configured console UART. +* +* If your system does not contain a UART, then another method of providing +* results includes printf'ing messages to memory. To enable this method, +* enable the definition of IO_USE_BUFFER in this file. To further tailor this +* method of logging, change IO_BUF_SIZE and IO_BUF_CUSHION. All output will +* be written to the TextBuf array. Use your debugger or your own test +* utilities to examine this buffer for generated output. +* +* +* Limitations +* +* - This package must be compiled under the GNU compiler suite. +* - CT_CMP macros can compare only ordinal data types. Structure type +* comparisons require the tester to implement their own function. +* - Some sort of BSP is required to support implementation of string.h, +* stdio.h, and stdarg.h at a minimum. +* - Advanced BSP support of signal.h is required to use CT_SetAlarm(). +* If support is not available, then this function will return an error. +* - Testing asserts requires that NDEBUG not be defined in your driver under +* test code. +* +*
+* MODIFICATION HISTORY:
+*
+* Ver Who  Date     Changes
+* --- ---- -------- -----------------------------------------------
+*  1  rmm  12/23/03 First release for VxWorks
+*
+* 
+* +******************************************************************************/ +#ifndef CT_H +#define CT_H + +/***************************** Include Files *********************************/ + +#include "xil_types.h" /* Needed for assert testing */ +#include "xil_assert.h" +#include +#include +#include +#include "intg.h" + +/************************** Constant Definitions *****************************/ + + +/** + * This is what the CT_Log* lines will be prefixed with. The numerical arg + * should be the line number within the source file containing the call to + * the CT library function or macro. + */ +#define CT_ERR_FMT " FAIL: %s: %04d:" + + +/**************************** Type Definitions *******************************/ + +typedef unsigned long long CT_TIME_STAMP; /**< Type defination for Time Stamp.*/ + +/***************** Macros (Inline Functions) Definitions *********************/ + + +/*****************************************************************************/ +/** + * + * Log a failure with a supplied message. This provides a useful wrapper + * around the CT_LogFailure function that prints messages of the same format + * as other CT macros: + * + *
+ *   1  int i;
+ *   2
+ *   3  i = 10;
+ *   4  if (i != 5)
+ *   5  {
+ *   6     CT_LOG_FAILURE("GetDataFromDevice() returned %d instead of 5", i);
+ *   7     CT_LOG_FAILURE("D'oh");
+ *   8  }
+ * 
+ * + * yields the output: + * + * FAIL: 0006: GetDataFromDevice() returned 10 instead of 5 + * FAIL: 0007: D'oh + * + * @param fmt is a printf style format string + * @param args is a variable argument list that matches fields in the fmt + * string. + * + * @note + * Usage: CT_LOG_FAILURE(char* fmt, ...) + *****************************************************************************/ +#define CT_LOG_FAILURE(fmt, args...) \ + CT_LogFailure(CT_ERR_FMT fmt "\r\n", __FILE__, __LINE__ , ## args) + +/* Note: In the preceding construct, the space between __FILE__, __LINE__ and + * the comma are needed for the ## args to work when there is no "args" + * expansion like in line 7 of the example shown above. + */ + +/*****************************************************************************/ +/** + * + * Test asserts for a function. This macro will verify whether the called + * function generates an assert from the provided arguments. If it does not + * then a failure message is logged. + * + * The design of this macro allows the tester to verify an assert occurs + * with a single line of code with full type checking of the called + * function. For example, if your function under test is coded as: + * + *
+ *   void XDev_Start(Dev* Instance)
+ *   {
+ *      Xil_AssertVoid(Dev != NULL);
+ *          ...
+ *   }
+ * 
+ * + * Then use CT_ASSERT in the following way to verify that the assert is caught. + * + *
+ *   CT_ASSERT(XDev_Start, (Dev*)NULL);
+ * 
+ * + * @param Function is the function being tested for asserts. + * @param args is a variable number of arguments. It contains whatever arguments + * should cause an assert. These arguments are arranged by the + * preprocessor in the order provided by the tester. + * + * @note + * Usage: CT_ASSERT(SomeFunc, arg1, arg2, ...) + *****************************************************************************/ +#define CT_ASSERT(Function, args...) \ +{ \ + if (CT_IsAssertDisabled()) \ + CT_LogFailure(CT_ERR_FMT "NDEBUG is defined, assert test failed\r\n", \ + __FILE__, __LINE__); \ + else \ + { \ + XAssertStatus = XASSERT_NONE; \ + XWaitInAssert = FALSE; \ + (void)Function(args); \ + XWaitInAssert = TRUE; \ + if (XAssertStatus == XASSERT_NONE) \ + CT_LogFailure(CT_ERR_FMT "Assert failed\r\n", __FILE__, __LINE__); \ + } \ +} + +/*****************************************************************************/ +/** + * + * Compare numbers. If not equal, then output message and increment fail + * counter. The message contains the line number of the failure, the + * name of the variable, and its actual and expected values in hex and + * decimal. An example: + * + *
+ *     1  UINT32 result = 5;
+ *     2  UINT32 expected = 17;
+ *     3
+ *     4  CT_CMP_NUM(UINT32, result, expected)
+ *
+ * yields the output:
+ *
+ *     FAIL: 0004: result=5(5h), expected 17(11h)
+ *
+ * 
+ * + * @param type is data type to compare (must be an ordinal type such as int) + * @param actual is the actual data retrieved from test + * @param expected is the expected value + * + * @note + * Usage: CT_CMP_NUM(, actual, expected) + ****************************************************************************/ +#define CT_CMP_NUM(type, actual, expected) \ + if ((type)(actual) != (type)(expected)) \ + { \ + printf(CT_ERR_FMT "%s=%d(%Xh), expected %d(%Xh)\r\n", \ + __FILE__, __LINE__, #actual, (int)actual, (int)actual, \ + (int)expected, (int)expected); \ + CT_LogFailure2(); \ + } + +/*****************************************************************************/ +/** + * + * Like CT_CMP_NUM except an extra argument is printed. Helpful if comparing + * numbers in a loop where the loop index may prove useful if the test fails. + * + *
+ *     1  UINT32 result[5];
+ *     2  UINT32 expected[5];
+ *     3  int i;
+ *     4
+ *     5  for (i=0; i<5; i++)
+ *     6  {
+ *     7     CT_CMP_NUM_ARG(UINT32, result[i], expected[i], i);
+ *     8  }
+ *     9
+ *
+ * yeilds the output if for example failure occurs at i=3:
+ *
+ *     FAIL: 0007: result=5(5h), expected 17(11h). i=3
+ * 
+ * + * @param type is data type to compare (must be an ordinal type such as int) + * @param actual is the actual data retrieved from test + * @param expected is the expected value + * @param arg is an argument that can be treated as an integer. + * + * @note + * Usage: CT_CMP_NUM_ARG(, actual, expected, arg1) + ****************************************************************************/ +#define CT_CMP_NUM_ARG(type, actual, expected, arg) \ + if ((type)(actual) != (type)(expected)) \ + { \ + CT_LogFailure(CT_ERR_FMT "%s=%d(%Xh), expected %d(%Xh). %s=%d\r\n", \ + __FILE__, __LINE__, #actual, (int)actual, (int)actual, \ + (int)expected, (int)expected, #arg, arg); \ + } + +/*****************************************************************************/ +/** + * + * Like CT_CMP_NUM_ARG except a second extra argument is printed. Helpful if + * comparing numbers in a loop where the loop index may prove useful if the test + * fails. + * + *
+ *     1  UINT32 result[5];
+ *     2  UINT32 expected[5];
+ *     3  int i, j=(int)&result[0];
+ *     4
+ *     5  for (i=0; i<5; i++, j++)
+ *     6  {
+ *     7     CT_CMP_NUM_ARG2(UINT32, result[i], expected[i], i, j);
+ *     8  }
+ *     9
+ *
+ * yeilds the output if for example failure occurs at i=3:
+ *
+ *     FAIL: 0007: result=5(5h), expected 17(11h). i=3, j=543234
+ * 
+ * + * @param type is data type to compare (must be an ordinal type such as int) + * @param actual is the actual data retrieved from test + * @param expected is the expected value + * @param arg1 is an argument that can be treated as an integer. + * @param arg2 is an argument that can be treated as an integer. + * + * @note + * Usage: CT_CMP_NUM_ARG2(, actual, expected, arg1, arg2) + ****************************************************************************/ +#define CT_CMP_NUM_ARG2(type, actual, expected, arg1, arg2) \ + if ((type)(actual) != (type)(expected)) \ + { \ + CT_LogFailure(CT_ERR_FMT "%s=%d(%Xh), expected %d(%Xh). %s=%d. \ + %s=%d\r\n",\ + __FILE__, __LINE__, #actual, (int)actual, (int)actual,\ + (int)expected, (int)expected, #arg1, arg1, #arg2, arg2);\ + } + +/*****************************************************************************/ +/** + * + * Like CT_CMP_NUM except a range of memory is compared. + * + * @param type is data type to compare (must be an ordinal type such as int) + * @param actual is the actual data retrieved from test and must be an array + * of type + * @param bytes is the number of bytes to test + * @param expected is the expected value and must be of type. + * + * @note + * Usage: CT_CMP_NUM_RANGE(, actual[], bytes, expected) + ****************************************************************************/ +#define CT_CMP_NUM_RANGE(type, actual, bytes, expected) \ +{ \ + int d112a; \ + int words = (bytes)/sizeof(type); \ + type *a = (type*)(actual); \ + \ + for (d112a=0; d112a + * 1 UINT32 result[500]; + * 2 UINT32 expected[500]; + * 3 + * 4 CT_CMP_MEM(UINT32, result, expected, 500) + * + * yeilds the output if result[13]=100 and expected[13]=121: + * + * FAIL: 0004: result[13]=100(64h), expected 121(79h) + * + * + * @param type is data type to compare (must be an ordinal type such as int) + * @param actual is the area of memory to test + * @param expected is the expected contents + * @param words is the number of data type "type" to test. + * + * @note + * Usage: CT_CMP_MEM(, *actual, *expected, unsigned words) + ****************************************************************************/ +#define CT_CMP_MEM(type, actual, expected, words) \ +{ \ + int d112a; \ + type *a = (type*)(actual); \ + type *e = (type*)(expected); \ + \ + for (d112a=0; d112a + * 1 UINT32 result[TEST_WORDS]; + * 2 UINT32 expected[TEST_WORDS]; + * 3 int i; + * 4 + * 5 for (i=0; i<3; i++) + * 6 { + * 7 CT_CMP_MEM_ARG(UINT32, result, expected, TEST_WORDS, i); + * 8 taskDelay(10); + * 8 } + * 9 + * + * yeilds the output if for example failure occurs at i=1, and result[2]=1, + * and expected[2]=3: + * + * FAIL: 0007: result[2]=1(1h), expected 3(3h) + * + * + * @param type is data type to compare (must be an ordinal type such as int) + * @param actual is the area of memory to test + * @param expected is the expected contents + * @param words is the number of data type "type" to test. + * @param index is an argument that can be treated as an integer. + * + * @note + * Usage: CT_CM_MEM_ARG(, actual[], expected[], index) + ****************************************************************************/ +#define CT_CMP_MEM_ARG(type, actual, expected, words, index) \ +{ \ + int d112a; \ + type *a = (type*)(actual); \ + type *e = (type*)(expected); \ + \ + for (d112a=0; d112a, *dest, *src) + ****************************************************************************/ +#define CT_COPY_STRUCT(type,dest,src) \ +{ \ + type *td = dest; \ + type *ts = src; \ + memcpy(td,ts,sizeof(type)); \ +} + + + +/************************** Function Prototypes ******************************/ + +void CT_Init(void); +void CT_TestReset(char *fmt, ...); +void CT_NotifyNextPass(void); +void CT_LogFailure(char* fmt, ...); +void CT_LogFailure2(); +unsigned CT_GetTestFailures(void); +unsigned CT_GetTotalFailures(void); +void CT_Message(char *fmt, ...); +void CT_MemSet(void *Address, char Value, unsigned Bytes); +int CT_IsAssertDisabled(void); + +#endif /* CT_H */ diff --git a/XilinxProcessorIPLib/drivers/nandps8_v2_0/intgTest/ct_standalone.c b/XilinxProcessorIPLib/drivers/nandps8_v2_0/intgTest/ct_standalone.c new file mode 100755 index 00000000..5a9fab72 --- /dev/null +++ b/XilinxProcessorIPLib/drivers/nandps8_v2_0/intgTest/ct_standalone.c @@ -0,0 +1,300 @@ +/****************************************************************************** +* +* (c) Copyright 2010-2014 Xilinx, Inc. All rights reserved. +* +* This file contains confidential and proprietary information of Xilinx, Inc. +* and is protected under U.S. and international copyright and other +* intellectual property laws. +* +* DISCLAIMER +* This disclaimer is not a license and does not grant any rights to the +* materials distributed herewith. Except as otherwise provided in a valid +* license issued to you by Xilinx, and to the maximum extent permitted by +* applicable law: (1) THESE MATERIALS ARE MADE AVAILABLE "AS IS" AND WITH ALL +* FAULTS, AND XILINX HEREBY DISCLAIMS ALL WARRANTIES AND CONDITIONS, EXPRESS, +* IMPLIED, OR STATUTORY, INCLUDING BUT NOT LIMITED TO WARRANTIES OF +* MERCHANTABILITY, NON-INFRINGEMENT, OR FITNESS FOR ANY PARTICULAR PURPOSE; +* and (2) Xilinx shall not be liable (whether in contract or tort, including +* negligence, or under any other theory of liability) for any loss or damage +* of any kind or nature related to, arising under or in connection with these +* materials, including for any direct, or any indirect, special, incidental, +* or consequential loss or damage (including loss of data, profits, goodwill, +* or any type of loss or damage suffered as a result of any action brought by +* a third party) even if such damage or loss was reasonably foreseeable or +* Xilinx had been advised of the possibility of the same. +* +* CRITICAL APPLICATIONS +* Xilinx products are not designed or intended to be fail-safe, or for use in +* any application requiring fail-safe performance, such as life-support or +* safety devices or systems, Class III medical devices, nuclear facilities, +* applications related to the deployment of airbags, or any other applications +* that could lead to death, personal injury, or severe property or +* environmental damage (individually and collectively, "Critical +* Applications"). Customer assumes the sole risk and liability of any use of +* Xilinx products in Critical Applications, subject only to applicable laws +* and regulations governing limitations on product liability. +* +* THIS COPYRIGHT NOTICE AND DISCLAIMER MUST BE RETAINED AS PART OF THIS FILE +* AT ALL TIMES. +* +******************************************************************************/ +/*****************************************************************************/ +/** +* +* @file ct_standalone.c +* +* Implements Code test (CT) utility driver. +* +*
+* MODIFICATION HISTORY:
+*
+* Ver Who  Date     Changes
+* --- ---- -------- -----------------------------------------------
+* 1.0 rmm  12/23/03 First release
+* 1.1 xd   03/16/04 Changed to support PPC405 without OS.
+*
+* 
+* +******************************************************************************/ + +/***************************** Include Files *********************************/ +#include +#include +#include +#include +#include "ct.h" +#include "intg.h" + +/************************** Constant Definitions *****************************/ + + +/**************************** Type Definitions *******************************/ + + +/***************** Macros (Inline Functions) Definitions *********************/ + + +/************************** Function Prototypes ******************************/ + + +/************************** Variable Definitions *****************************/ + +unsigned CT_TotalFailures; /**< Total failures flag */ +unsigned CT_TestFailures; /**< Test failures flag */ +unsigned CT_TestPass; /**< Test pass flag */ + +/*****************************************************************************/ +/** +* +* Initialize the CT subsystem. +* +* @return +* +* Nothing +* +******************************************************************************/ +void CT_Init(void) +{ + CT_TestFailures = 0; + CT_TotalFailures = 0; + CT_TestPass = 0; +} + + +/*****************************************************************************/ +/** +* +* Reset for a new test and display a test specific message. This involves: +* +* - Zero out test failure counter. +* - Print a message specified by the fmt parameter and its associated +* arguments. +* +* @param fmt is a "printf" style format string. +* @param ... is a variable number of arguments that match "fmt" +* +* @return Nothing +* +******************************************************************************/ +void CT_TestReset(char *fmt, ...) +{ + va_list args; + + CT_TestFailures = 0; + CT_TestPass = 1; + + /* Print out the format and its associated argument list */ + va_start(args, fmt); + printf(fmt, args); + CT_Message("\r\n====================================================="); + + va_end(args); + CT_Message("\r\n"); +} + + +/*****************************************************************************/ +/** +* +* Display current test pass number to user +* +* @return +* +* Nothing +* +******************************************************************************/ +void CT_NotifyNextPass(void) +{ + printf("\r\n=====>Pass %d\r\n\r\n", CT_TestPass); + CT_TestPass++; +} + + +/*****************************************************************************/ +/** +* +* Log a test failure. This involves incrementing test failure and total test +* failure counters, and displaying test specific message. +* +* @param fmt is a "printf" style format string. +* @param ... is a variable number of arguments that match "fmt" +* +* @return Nothing +* +******************************************************************************/ +void CT_LogFailure(char* fmt, ...) +{ + va_list args; + + /* + * Increment failure counters + */ + CT_TestFailures++; + CT_TotalFailures++; + + /* + * Print out the format and its associated argument list. + */ + va_start(args, fmt); + + printf(fmt, args); + va_end(args); +} + + +/*****************************************************************************/ +/** +* +* Log a test failure. This involves incrementing test failure and total test +* failure counters, and displaying test specific message. +* +* param fmt is a "printf" style format string. +* param ... is a variable number of arguments that match "fmt" +* +* @return Nothing +* +******************************************************************************/ +void CT_LogFailure2() +{ + /* + * Increment failure counters + */ + CT_TestFailures++; + CT_TotalFailures++; +} + + +/*****************************************************************************/ +/** +* +* Return the number of test failures since CT_TestReset() was called. +* +* @return Number of failures logged. +* +******************************************************************************/ +unsigned CT_GetTestFailures(void) +{ + return(CT_TestFailures); +} + + +/*****************************************************************************/ +/** +* +* Return the number of test failures since CT_Init() was called. +* +* @return Total number of failures logged. +* +******************************************************************************/ +unsigned CT_GetTotalFailures(void) +{ + return(CT_TotalFailures); +} + + +/*****************************************************************************/ +/** + * Return status of the Xilinx driver assert mechanism. + * + * @return + * + * 1 if asserts are disabled, 0 otherwise. + *****************************************************************************/ +int CT_IsAssertDisabled(void) +{ +#ifdef NDEBUG + return(1); +#else + return(0); +#endif +} + + +/*****************************************************************************/ +/** +* +* Print a message based on the given format string and parameters. +* +* @param fmt is a "printf" style format string. +* @param ... is a variable number of arguments that match "fmt" +* +* @return +* +* Nothing +* +******************************************************************************/ +void CT_Message(char *fmt, ...) +{ + va_list args; + + va_start(args, fmt); + + printf(fmt, args); + + va_end(args); +} + + +/*****************************************************************************/ +/** +* +* Set a series of bytes in memory to a specific value +* +* @param Address is the start address in memory to write +* @param Value is the value to set memory to +* @param Bytes is the number of bytes to set +* +* @return +* +* Nothing +* +******************************************************************************/ +void CT_MemSet(void *Address, char Value, unsigned Bytes) +{ + char* Ptr = Address; + + while(Bytes--) + { + *Ptr++ = Value; + } +} diff --git a/XilinxProcessorIPLib/drivers/nandps8_v2_0/intgTest/intg.c b/XilinxProcessorIPLib/drivers/nandps8_v2_0/intgTest/intg.c new file mode 100755 index 00000000..a1928067 --- /dev/null +++ b/XilinxProcessorIPLib/drivers/nandps8_v2_0/intgTest/intg.c @@ -0,0 +1,889 @@ +/****************************************************************************** +* +* (c) Copyright 2010-14 Xilinx, Inc. All rights reserved. +* +* This file contains confidential and proprietary information of Xilinx, Inc. +* and is protected under U.S. and international copyright and other +* intellectual property laws. +* +* DISCLAIMER +* This disclaimer is not a license and does not grant any rights to the +* materials distributed herewith. Except as otherwise provided in a valid +* license issued to you by Xilinx, and to the maximum extent permitted by +* applicable law: (1) THESE MATERIALS ARE MADE AVAILABLE "AS IS" AND WITH ALL +* FAULTS, AND XILINX HEREBY DISCLAIMS ALL WARRANTIES AND CONDITIONS, EXPRESS, +* IMPLIED, OR STATUTORY, INCLUDING BUT NOT LIMITED TO WARRANTIES OF +* MERCHANTABILITY, NON-INFRINGEMENT, OR FITNESS FOR ANY PARTICULAR PURPOSE +* and (2) Xilinx shall not be liable (whether in contract or tort, including +* negligence, or under any other theory of liability) for any loss or damage +* of any kind or nature related to, arising under or in connection with these +* materials, including for any direct, or any indirect, special, incidental, +* or consequential loss or damage (including loss of data, profits, goodwill, +* or any type of loss or damage suffered as a result of any action brought by +* a third party) even if such damage or loss was reasonably foreseeable or +* Xilinx had been advised of the possibility of the same. +* +* CRITICAL APPLICATIONS +* Xilinx products are not designed or intended to be fail-safe, or for use in +* any application requiring fail-safe performance, such as life-support or +* safety devices or systems, Class III medical devices, nuclear facilities, +* applications related to the deployment of airbags, or any other applications +* that could lead to death, personal injury, or severe property or +* environmental damage (individually and collectively, "Critical +* Applications"). Customer assumes the sole risk and liability of any use of +* Xilinx products in Critical Applications, subject only to applicable laws +* and regulations governing limitations on product liability. +* +* THIS COPYRIGHT NOTICE AND DISCLAIMER MUST BE RETAINED AS PART OF THIS FILE +* AT ALL TIMES. +* +******************************************************************************/ +/******************************************************************************/ +/** +* +* @file intg.c +* +* DESCRIPTION: +* +* Provides integration test entry point for the XNandPs8 component. +* +* @note None +* +*
+*
+* MODIFICATION HISTORY:
+*
+* Ver   Who    Date     Changes
+* ----- ----   ----------------------------------------------------------------
+* 1.0   sb    11/28/14 First release.
+* 
+* +******************************************************************************/ + +/***************************** Include Files *********************************/ + +#include "intg.h" +#include + +/************************** Constant Definitions *****************************/ + +/** + * Main menu selections. + * @{ + */ +#define MENU_MAIN_TEST 1 +#define MENU_MAIN_UTIL 2 +#define MENU_MAIN_EXIT 99 +/*@}*/ + +/** + * Test sub-menu selections. + * @{ + */ +#define MENU_TEST_ALL 0 +#define MENU_TEST_ERASE_READ 1 +#define MENU_TEST_FLASH_RW 2 +#define MENU_TEST_RANDOM_RW 3 +#define MENU_TEST_SPAREBYTES_RW 4 +#define MENU_TEST_PARTIAL_RW 5 +#define MENU_TEST_ECC 6 +#define MENU_TEST_EXIT 99 +/*@}*/ + +/** + * Create unique bitmasks from the test numbers. + * @{ + */ +#define INTG_TEST_ALL 0xFFFFFFFF +#define INTG_TEST_ERASE_READ (1 << MENU_TEST_ERASE_READ) +#define INTG_TEST_FLASH_RW (1 << MENU_TEST_FLASH_RW) +#define INTG_TEST_RANDOM_RW (1 << MENU_TEST_RANDOM_RW) +#define INTG_TEST_SPAREBYTES_RW (1 << MENU_TEST_SPAREBYTES_RW) +#define INTG_TEST_PARTIAL_RW (1 << MENU_TEST_PARTIAL_RW) +#define INTG_TEST_ECC (1 << MENU_TEST_ECC) +/*@}*/ + +/** + * Utility sub-menu selections. + * @{ + */ +#define MENU_UTIL_DATA_INTERFACE 1 +#define MENU_UTIL_FLASH_DETAILS 2 +#define MENU_UTIL_EXIT 99 +/*@}*/ + +typedef enum TimingMode { + Mode0 = 0U, + Mode1, + Mode2, + Mode3, + Mode4, + Mode5 +}NandPs8_TimingMode; + +/* + * Uncomment the following constant definition if UART16550 is standard output + * device. If UartLite is standard output device, comment the definition + */ +//#define UART16550 + +/* + * Uncomment the following constant definition if UARTLITE is standard output + * device. If UART16550 is standard output device, comment the definition + */ +//#define UARTLITE + +#ifdef UART16550 +#include "xuartns550_l.h" +#define UART_BASEADDR XPAR_RS232_UART_BASEADDR +#elif UARTLITE +#include "xuartlite_l.h" +#define UART_BASEADDR XPAR_UARTLITE_BASEADDR +#else +#include "xuartps_hw.h" +#define UART_BASEADDR XPS_UART1_BASEADDR /**< UART-1 Base Address */ +#endif + +//#define printf xil_printf +/**************************** Type Definitions *******************************/ + +/***************** Macros (Inline Functions) Definitions *********************/ + +/************************** Variable Definitions *****************************/ +/* + * Buffers used during read and write transactions. + */ +u8 ReadBuffer[TEST_BUF_SIZE] __attribute__ ((aligned(64)));/**< Read buffer */ +u8 WriteBuffer[TEST_BUF_SIZE] __attribute__ ((aligned(64)));/**< write buffer */ +/** + * Nand driver instance for the Nand device. + */ +XNandPs8 NandInstance; +XNandPs8 *NandInstPtr = &NandInstance; +XNandPs8_Config *Config; +/************************** Function Prototypes ******************************/ + +static unsigned int GetUserInput(char* Prompt, char* Response, + unsigned int + MaxChars); +static int GetMainMenuCommand(char* CmdLine); +static void RunTestMenu(char* CmdLine); +static void RunUtilMenu(char* CmdLine); +static int ChangeTimingMode(XNandPs8 *NandInstPtr, + XNandPs8_DataInterface NewIntf, + XNandPs8_TimingMode NewMode); + +extern char inbyte (); /**< Inbyte returns the byte received by device. */ +s32 FlashInit(u16 NandDeviceId); +#ifdef AUTOMATIC_TEST_MODE +int Automode_Tests(int TestLoops); +#endif + +/*****************************************************************************/ +/* + * Retrieve a line of input from the user. A line is defined as all characters + * up to a new line. + * + * This basically implements a fgets function. The standalone EDK stdin + * is apparently buggy because it behaves differently when new line is + * entered by itself vs. when it is entered after a number of regular chars + * have been entered. Characters entered are echoed back. + * + * @param Prompt - Printed before string is accepted to ask the user to + * enter something. + * @param Response - User entered string with new line stripped + * @param MaxChars - Maximum number of characters to read + * + * @return Number of characters read (excluding newlines) + * + *****************************************************************************/ +unsigned int GetUserInput(char* Prompt, char* Response, unsigned int MaxChars) +{ + int Finished, i; + + /* display prompt */ + if (Prompt) printf(Prompt); + + Finished = 0; + i = 0; + + while(!Finished && (i < MaxChars - 1)) { + /* flush out any output pending in stdout */ + fflush(stdout); + + /* wait for a character to arrive */ + Response[i] = inbyte(); + + /* normal chars, add them to the string and keep going */ + if ((Response[i] >= 0x20) && (Response[i] <=0x7E)) { + printf("%c", Response[i++]); + continue; + } + + /* control chars */ + switch(Response[i]) { + /* carriage return */ + case 0x0D: + /* Case Fall through */ + /* Line Feed */ + case 0x0A: + Response[i++] = '\n'; + Finished = 1; + printf("\r\n"); + break; + + /* backspace */ + case 0x08: + if (i != 0) { + /* erase previous character and move + cursor back one space */ + printf("\b \b"); + Response[--i] = 0; + } + break; + + /* ignore all other control chars */ + default: + continue; + } + } + + Response[i] = 0; + return i; +} + +/*****************************************************************************/ +/** +* +* Intg_Entry +* +* Executes all unit tests for the device +* +* param None +* +* @return None +* +* @note None +* +******************************************************************************/ +void Intg_Entry(void) +{ + char CmdLine[132]; + s32 Status = XST_FAILURE; +#ifdef AUTOMATIC_TEST_MODE + int TestLoops; + int TestFailures; + u32 t_mode = 0U; + u32 RegVal = 0U; + u32 feature; + u32 ddr_mode[2]; +#endif + + /* print banner */ + printf("\r\n\r\nNand Driver Integration Test\r\n"); + printf("Created on %s\n\n\r", __DATE__); + printf("=====================================================\r\n"); + + CT_Init(); + + Status = FlashInit(NAND_DEVICE_ID); + if(Status != XST_SUCCESS){ + printf("Nand Flash Initialization Failed\r\n"); + goto Out; + } + printf("Flash initialization done\r\n"); +#ifndef AUTOMATIC_TEST_MODE + /* prompt user for menu selections */ + while(1) { + switch(GetMainMenuCommand(CmdLine)) { + case MENU_MAIN_TEST: + RunTestMenu(CmdLine); + break; + + case MENU_MAIN_UTIL: + RunUtilMenu(CmdLine); + break; + + case MENU_MAIN_EXIT: + printf("\r\nByebye! Thanks for using Nand "); + printf("and Driver integration tests :)\r\n"); + return; + + default: + printf("Invalid selections\r\n"); + } + } +#else + /* set defaults */ + TestLoops = 1; + TestFailures = 0; + + /* + * Setting Interface + */ + NandInstPtr->DataInterface = SDR; + + for (t_mode = Mode0; t_mode <= Mode5; t_mode++){ + NandInstPtr->DataInterface = SDR; + + /* + * Set Timing mode + */ + Status = ChangeTimingMode(NandInstPtr, SDR, t_mode); + if (Status != XST_SUCCESS) { + goto Out; + } + /* + * Run the test cases + */ + TestFailures += Automode_Tests(TestLoops); + } + + for (t_mode = Mode0; t_mode <= Mode5; t_mode++){ + + NandInstPtr->DataInterface = NVDDR; + /* + * Set Timing mode + */ + Status = ChangeTimingMode(NandInstPtr, NVDDR, t_mode); + if (Status != XST_SUCCESS) { + goto Out; + } + /* + * Run the test cases + */ + TestFailures += Automode_Tests(TestLoops); + } + + if (TestFailures) { + XIL_FAIL(TestFailures); + } else { + XIL_PASS(); + } +#endif + +Out: + exit(0); +} + +#ifdef AUTOMATIC_TEST_MODE +/*****************************************************************************/ +/** +* +* Auto Mode Tests +* +* Executes all unit tests for the device +* +* param TestLoops: Number of times a test should run. +* +* @return Total Test failures +* +* @note None +* +******************************************************************************/ +int Automode_Tests(int TestLoops) +{ + volatile int failures = 0; + + failures += Intg_EraseReadTest(NandInstPtr, TestLoops); + failures += Intg_FlashRWTest(NandInstPtr, TestLoops); + failures += Intg_RandomRWTest(NandInstPtr, TestLoops); + failures += Intg_SpareBytesRWTest(NandInstPtr, TestLoops); + failures += Intg_PartialRWTest(NandInstPtr, TestLoops); + failures += Intg_EccTest(NandInstPtr, TestLoops); + + return failures; +} +#endif + +/*****************************************************************************/ +/** + * + * Prompt the user for selections in the main menu. The user is allowed to + * enter one command at a time. + * + * @param CmdLine - Storage to use for User input. + * + * @return Numeric command entered. + * + * @note None. + * + *****************************************************************************/ +static int GetMainMenuCommand(char* CmdLine) +{ + /* prompt user */ + printf("\r\n\r\n\r\nMain Menu:\r\n"); + printf("==========\r\n"); + printf("%d - Test menu\r\n", MENU_MAIN_TEST); + printf("%d - Util menu\r\n", MENU_MAIN_UTIL); + printf("%d - Exit\r\n\r\n", MENU_MAIN_EXIT); + + *CmdLine = '\n'; + while(*CmdLine == '\n') { + printf("Enter selection: "); + GetUserInput(0, CmdLine, 131); + } + return(atoi(CmdLine)); +} + + +/*****************************************************************************/ +/** + * + * Prompt the user for a sequence of tests to run in the test sub-menu + * + * @param CmdLine - Storage to use for User input + * + * @return None + * + * @note None + * + *****************************************************************************/ +static void RunTestMenu(char* CmdLine) +{ + char* Token; + char* tmp; + int QuitToMain = 0; + int TestLoops; + int TestFailures; + u32 RunTestMask; + + /* + * Flash Initialization Function + */ + + while(!QuitToMain) { + /* set defaults */ + TestLoops = 1; + RunTestMask = 0; + TestFailures = 0; + + /* prompt user */ + printf("\r\n\r\n\r\nTest Menu:\r\n"); + printf("==========\r\n"); + printf("%d - Run all tests\r\n", MENU_TEST_ALL); + printf("%d - Flash Erase Read Test\r\n", MENU_TEST_ERASE_READ); + printf("%d - Flash Read Write Test \r\n", MENU_TEST_FLASH_RW); + printf("%d - Random Block Flash Read Write Test\r\n", MENU_TEST_RANDOM_RW); + printf("%d - Spare Bytes Read Write Test \r\n", + MENU_TEST_SPAREBYTES_RW); + printf("%d - Partial Page Read Write Test\r\n", + MENU_TEST_PARTIAL_RW); + printf("%d - ECC Test.\r\n", + MENU_TEST_ECC); + printf("%d - Exit to main menu\r\n\r\n", MENU_TEST_EXIT); + printf("More than one test can be specified\r\n"); + printf("Adding l sets the number of test loops\n\n"); + + /* wait for input */ + *CmdLine = '\n'; + while(*CmdLine == '\n') { + printf("Enter test(s) to execute: "); + GetUserInput(0, CmdLine, 131); + } + + /* parse input line */ + Token = strtok_r(CmdLine, " ", &tmp); + while(Token) { + if ((*Token == 'l') || (*Token == 'L')) { + TestLoops = atoi(Token+1); + } + else { + switch(atoi(Token)) { + case MENU_TEST_ALL: + RunTestMask |= INTG_TEST_ALL; + break; + + case MENU_TEST_FLASH_RW: + RunTestMask |= INTG_TEST_FLASH_RW; + break; + + case MENU_TEST_ERASE_READ: + RunTestMask |= INTG_TEST_ERASE_READ; + break; + + case MENU_TEST_RANDOM_RW: + RunTestMask |= INTG_TEST_RANDOM_RW; + break; + + case MENU_TEST_SPAREBYTES_RW: + RunTestMask |= + INTG_TEST_SPAREBYTES_RW; + break; + + case MENU_TEST_PARTIAL_RW: + RunTestMask |= + INTG_TEST_PARTIAL_RW; + break; + + case MENU_TEST_ECC: + RunTestMask |= + INTG_TEST_ECC; + break; + + case MENU_TEST_EXIT: + QuitToMain = 1; + break; + + default: + printf("Unknown test id %s\r\n", + Token); + } + } + + Token = strtok_r(0, " ", &tmp); + } + + /* + * Execute selected tests + */ + if (QuitToMain == 1) break; + + printf("\r\n\r\n"); + if (RunTestMask & INTG_TEST_ERASE_READ) { + TestFailures += Intg_EraseReadTest(NandInstPtr, TestLoops); + } + + if (RunTestMask & INTG_TEST_FLASH_RW) { + TestFailures += Intg_FlashRWTest(NandInstPtr, TestLoops); + } + + if (RunTestMask & INTG_TEST_RANDOM_RW) { + TestFailures += Intg_RandomRWTest(NandInstPtr, TestLoops); + } + + if (RunTestMask & INTG_TEST_SPAREBYTES_RW) { + TestFailures += Intg_SpareBytesRWTest(NandInstPtr, TestLoops); + } + + if (RunTestMask & INTG_TEST_PARTIAL_RW) { + TestFailures += Intg_PartialRWTest(NandInstPtr, TestLoops); + } + + if (RunTestMask & INTG_TEST_ECC) { + TestFailures += Intg_EccTest(NandInstPtr, TestLoops); + } + + printf("************************************************\r\n"); + if (TestFailures) { + printf("* %d test FAILURE(s) recorded\r\n", \ + TestFailures); + } else { + printf("* Tests pass\r\n"); + } + printf("*********************************************\r\n"); + } +} + +/*****************************************************************************/ +/** + * + * Prompt the user for a selection in the utility sub-menu + * + * @param CmdLine - Storage to use for User input + * + * @return None. + * + * @note None. + * + *****************************************************************************/ +static void RunUtilMenu(char* CmdLine) +{ + int QuitToMain = 0; + int Status = XST_FAILURE; + + while(!QuitToMain) { + /* prompt user */ + printf("\r\n\r\n\r\nUtil Menu:\r\n"); + printf("==========\r\n"); + printf("%d - Change Data Interface Timing mode- 0 for SDR, 1 for NVDDR" + "\r\n",MENU_UTIL_DATA_INTERFACE); + printf("%d - Print Flash Details\r\n", + MENU_UTIL_FLASH_DETAILS); + + /* wait for input */ + *CmdLine = '\n'; + while(*CmdLine == '\n') { + printf("Enter selection: "); + GetUserInput(0, CmdLine, 131); + } + + /* execute selection */ + switch(atoi(CmdLine)) { + case MENU_UTIL_DATA_INTERFACE: + printf("Type 0 for SDR, 1 for NVDDR\r\n"); + /* wait for input */ + *CmdLine = '\n'; + while(*CmdLine == '\n') { + printf("Enter selection: "); + GetUserInput(0, CmdLine, 131); + } + switch(atoi(CmdLine)) { + case SDR: + printf("Enter Timing Mode : 0 - 5 for SDR Interface : "); + /* wait for input */ + *CmdLine = '\n'; + while(*CmdLine == '\n') { + GetUserInput(0, CmdLine, 131); + } + if((u8)atoi(CmdLine) >= 0 && (u8)atoi(CmdLine) <= 5){ + Status = ChangeTimingMode(NandInstPtr,SDR,(u8)atoi(CmdLine)); + if (Status != XST_SUCCESS) { + printf("Data Interface / Timing Mode Change" + " failed\r\n"); + } + + } + else{ + printf("Invalid Input\n\r"); + } + break; + + case NVDDR: + printf("Enter Timing Mode : 0 - 5 for NVDDR Interface : "); + /* wait for input */ + *CmdLine = '\n'; + while(*CmdLine == '\n') { + GetUserInput(0, CmdLine, 131); + } + if((u8)atoi(CmdLine) >= 0 && (u8)atoi(CmdLine) <= 5){ + Status = ChangeTimingMode(NandInstPtr,NVDDR,(XNandPs8_TimingMode)atoi(CmdLine)); + if (Status != XST_SUCCESS) { + printf("Data Interface / Timing Mode Change" + " failed\r\n"); + } + } + else{ + printf("Invalid Input\n\r"); + } + break; + + default: + printf("Invalid selection\r\n"); + } + break; + + case MENU_UTIL_FLASH_DETAILS: + xil_printf("Bytes Per Page: 0x%x\r\n", + NandInstPtr->Geometry.BytesPerPage); + xil_printf("Spare Bytes Per Page: 0x%x\r\n", + NandInstPtr->Geometry.SpareBytesPerPage); + xil_printf("Pages Per Block: 0x%x\r\n", + NandInstPtr->Geometry.PagesPerBlock); + xil_printf("Blocks Per LUN: 0x%x\r\n", + NandInstPtr->Geometry.BlocksPerLun); + xil_printf("Number of LUNs: 0x%x\r\n", + NandInstPtr->Geometry.NumLuns); + xil_printf("Number of bits per cell: 0x%x\r\n", + NandInstPtr->Geometry.NumBitsPerCell); + xil_printf("Number of ECC bits: 0x%x\r\n", + NandInstPtr->Geometry.NumBitsECC); + xil_printf("Block Size: 0x%x\r\n", + NandInstPtr->Geometry.BlockSize); + xil_printf("Number of Target Blocks: 0x%x\r\n", + NandInstPtr->Geometry.NumTargetBlocks); + xil_printf("Number of Target Pages: 0x%x\r\n", + NandInstPtr->Geometry.NumTargetPages); + break; + + case MENU_UTIL_EXIT: + QuitToMain = 1; + break; + + default: + printf("Invalid selection\r\n"); + } + } +} + +/****************************************************************************/ +/** +* +* This functions receives a single byte using the UART. It is non-blocking in +* that it returns if there is no data received. +* +* @param Data will have the received data after this function returns +* XST_SUCCESS +* +* @return XST_SUCCESS if received a byte, XST_FAILURE otherwise +* +* @note None. +* +******************************************************************************/ +int UART_RecvByte(u8 *Data) +{ +#ifdef UART16550 + if (!XUartNs550_IsReceiveData(UART_BASEADDR)) { + return XST_FAILURE; + } else { + *Data = XUartNs550_ReadReg(UART_BASEADDR, XUN_RBR_OFFSET); + return XST_SUCCESS; + } + +#elif UARTLITE + if(XUartLite_IsReceiveEmpty(UART_BASEADDR)) { + return XST_FAILURE; + } else { + *Data = (u8)Xil_In32(UART_BASEADDR + XUL_RX_FIFO_OFFSET); + return XST_SUCCESS; + } +#else + if(!XUartPs_IsReceiveData(UART_BASEADDR)) { + return XST_FAILURE; + } else { + *Data = (u8)XUartPs_ReadReg(UART_BASEADDR, + XUARTPS_FIFO_OFFSET); + return XST_SUCCESS; + } +#endif + return XST_SUCCESS; +} + +/****************************************************************************/ +/** +* +* This function initialize the Nand flash. +* +* @param NandDeviceId is is the XPAR__DEVICE_ID value +* from xparameters.h. +* +* @return +* - XST_SUCCESS if successful. +* - XST_FAILURE if failed. +* +* @note +* None +* +****************************************************************************/ +s32 FlashInit(u16 NandDeviceId){ + + s32 Status = XST_FAILURE; + + Config = XNandPs8_LookupConfig(NandDeviceId); + if (Config == NULL) { + Status = XST_FAILURE; + goto Out; + } + + /* + * Initialize the flash driver. + */ + Status = XNandPs8_CfgInitialize(NandInstPtr, Config, + Config->BaseAddress); + if (Status != XST_SUCCESS) { + goto Out; + } + +Out: + return Status; + +} + +/*****************************************************************************/ +/** +* +* This function changes the data interface and timing mode. +* +* @param NandInstPtr is a pointer to the XNandPs8 instance. +* @param NewIntf is the new data interface. +* @param NewMode is the new timing mode. +* +* @return +* - XST_SUCCESS if successful. +* - XST_FAILURE if failed. +* +* @note None +* +******************************************************************************/ +static int ChangeTimingMode(XNandPs8 *NandInstPtr, + XNandPs8_DataInterface NewIntf, + XNandPs8_TimingMode NewMode){ + + s32 Status = XST_FAILURE; + u32 t_mode = NewMode; + u32 RegVal = 0U; + u32 feature = 0U; + u32 ddr_mode[2] = {0U}; + + if (NewIntf == SDR){ + NandInstPtr->DataInterface = SDR; + + /* + * Set Timing mode + */ + Status = XNandPs8_SetFeature(NandInstPtr, 0, 0x1, &t_mode); + if (Status != XST_SUCCESS) { + goto Out; + } + + /* + * Setting Interface and Timing Mode + */ + NandInstPtr->TimingMode = t_mode; + } + else{ + NandInstPtr->DataInterface = NVDDR; + ddr_mode[0] = t_mode | 0x10; + + /* + * Set Timing mode + */ + Status = XNandPs8_SetFeature(NandInstPtr, 0, 0x1, &ddr_mode[0]); + if (Status != XST_SUCCESS) { + goto Out; + } + + /* + * Setting Interface and Timing Mode + */ + NandInstPtr->TimingMode = ddr_mode[0]; + } + + /* + * Setting the Data Interface Register + */ + RegVal = ((NewMode % 6U) << ((NewIntf == NVDDR) ? 3U : 0U)) | + ((u32)NewIntf << XNANDPS8_DATA_INTF_DATA_INTF_SHIFT); + XNandPs8_WriteReg(NandInstPtr->Config.BaseAddress, + XNANDPS8_DATA_INTF_OFFSET, RegVal); + /* + * Get the Timing mode + */ + Status = XNandPs8_GetFeature(NandInstPtr, 0, 0x1, &feature); + if (Status != XST_SUCCESS) { + goto Out; + } + xil_printf("\tCurrent Interface type : %d, Timing mode is " + "%d\r\n\n",NandInstPtr->DataInterface,t_mode); + + /* + * Check if set_feature was successful + */ + if (feature != NandInstPtr->TimingMode) { + xil_printf("Interface / Mode Changed failed %x = %x\r\n", + feature,NandInstPtr->TimingMode); + Status = XST_FAILURE; + goto Out; + } + +Out: + return Status; +} + +/*****************************************************************************/ +/** + * + * Main entry function for the whole integration test. + * + * param None. + * + * @return 0 + * + * @note None. + * + *****************************************************************************/ +int main() +{ + Intg_Entry(); + return 0; +} diff --git a/XilinxProcessorIPLib/drivers/nandps8_v2_0/intgTest/intg.h b/XilinxProcessorIPLib/drivers/nandps8_v2_0/intgTest/intg.h new file mode 100755 index 00000000..2e5e3169 --- /dev/null +++ b/XilinxProcessorIPLib/drivers/nandps8_v2_0/intgTest/intg.h @@ -0,0 +1,162 @@ +/****************************************************************************** +* +* (c) Copyright 2010-14 Xilinx, Inc. All rights reserved. +* +* This file contains confidential and proprietary information of Xilinx, Inc. +* and is protected under U.S. and international copyright and other +* intellectual property laws. +* +* DISCLAIMER +* This disclaimer is not a license and does not grant any rights to the +* materials distributed herewith. Except as otherwise provided in a valid +* license issued to you by Xilinx, and to the maximum extent permitted by +* applicable law: (1) THESE MATERIALS ARE MADE AVAILABLE "AS IS" AND WITH ALL +* FAULTS, AND XILINX HEREBY DISCLAIMS ALL WARRANTIES AND CONDITIONS, EXPRESS, +* IMPLIED, OR STATUTORY, INCLUDING BUT NOT LIMITED TO WARRANTIES OF +* MERCHANTABILITY, NON-INFRINGEMENT, OR FITNESS FOR ANY PARTICULAR PURPOSE +* and (2) Xilinx shall not be liable (whether in contract or tort, including +* negligence, or under any other theory of liability) for any loss or damage +* of any kind or nature related to, arising under or in connection with these +* materials, including for any direct, or any indirect, special, incidental, +* or consequential loss or damage (including loss of data, profits, goodwill, +* or any type of loss or damage suffered as a result of any action brought by +* a third party) even if such damage or loss was reasonably foreseeable or +* Xilinx had been advised of the possibility of the same. +* +* CRITICAL APPLICATIONS +* Xilinx products are not designed or intended to be fail-safe, or for use in +* any application requiring fail-safe performance, such as life-support or +* safety devices or systems, Class III medical devices, nuclear facilities, +* applications related to the deployment of airbags, or any other applications +* that could lead to death, personal injury, or severe property or +* environmental damage (individually and collectively, "Critical +* Applications"). Customer assumes the sole risk and liability of any use of +* Xilinx products in Critical Applications, subject only to applicable laws +* and regulations governing limitations on product liability. +* +* THIS COPYRIGHT NOTICE AND DISCLAIMER MUST BE RETAINED AS PART OF THIS FILE +* AT ALL TIMES. +* +******************************************************************************/ +/*****************************************************************************/ +/** +* +* @file intg.h - defines integration test API for the can driver +* +* @note +* TEST_METHOD has to be defined whether you want +* - internal loopback (TEST_LOOPBACK) or +* - receive/send data from/to (TEST_EXTERNAL_CAN_ANALYSER) an +* external Can Analyser. +*
+*
+* MODIFICATION HISTORY:
+*
+* Ver   Who    Date	 Changes
+* ----- -----  -------- -----------------------------------------------
+* 1.00a xd/sv  01/12/09 First release
+* 1.01  kvn	   26/03/14 First release for xilinx.
+*
+* 
+* +*****************************************************************************/ +#ifndef INTG_H /**< prevent circular inclusions */ +#define INTG_H /**< by using protection macros */ + +/***************************** Include Files ********************************/ + +#include "xparameters.h" +#include "xnandps8.h" +#include "xscugic.h" +#include "xstatus.h" +#include +#include +#include "ct.h" +#include "xil_exception.h" +#include "xil_testlib.h" +#ifdef __aarch64__ +#include "xreg_cortexa53.h" +#else +#include "xreg_cortexr5.h" +#endif +/************************** Constant Definitions ****************************/ + +/** + * Nand device and other important HW properties for this build + * @{ + */ +#define INTG_XPAR_INTC_DEVICE_ID XPAR_SCUGIC_SINGLE_DEVICE_ID +#define INTG_XPAR_DEVICE_INTR_VEC XPAR_XNANDPS8_0_INTR +#define printf xil_printf +/*@}*/ +#define NAND_DEVICE_ID 0U +#define TEST_BUF_SIZE 0x4000U +#define TEST_PAGE_START 0x2U +#define TEST_BLOCK_START 0x1U + +/* + * Buffers used during read and write transactions. + */ +extern u8 ReadBuffer[]; /**< read buffer */ +extern u8 WriteBuffer[]; /**< write buffer */ + +/** + * Pele Regression tests + */ +#define AUTOMATIC_TEST_MODE + +/**************************** Type Definitions ******************************/ + +#define printf xil_printf + +/***************** Macros (Inline Functions) Definitions ********************/ + +/**< Clear the Structure variable to zero */ +#define Intg_ClearStruct(s) (memset(&(s), 0, sizeof(s))) + +/************************** Variable Definitions ****************************/ + +/**< XCanPs instance used throughout tests */ +extern XNandPs8 NandInstance; +extern XNandPs8* NandInstPtr; +s32 MismatchCounter; +/************************** Function Prototypes *****************************/ + +/* + * Utility test functions implemented in intg.c + */ +void Intg_Entry(void); +int Intg_ReinitializeInstance(void); +int UART_RecvByte(u8 *Data); + +/* + * Flash Erase Read test implemented in intg_erase_read.c + */ +int Intg_EraseReadTest(XNandPs8 * NandInstPtr, int TestLoops); + +/* + * Flash Read Write test implemented in intg_flash_rw.c + */ +int Intg_FlashRWTest(XNandPs8 * NandInstPtr, int TestLoops); + +/* + * Random Block Read Write test implemented in intg_random_rw.c + */ +int Intg_RandomRWTest(XNandPs8 * NandInstPtr, int TestLoops); + +/* + * SpareBytes Read Write test implemented in intg_sparebytes_rw.c + */ +int Intg_SpareBytesRWTest(XNandPs8 * NandInstPtr,int TestLoops); + +/* + * Partial Page Read Write test implemented in intg_partialpage_rw.c + */ +int Intg_PartialRWTest(XNandPs8 * NandInstPtr,int TestLoops); + +/* + * ECC error check tests implemented in intg_ecc_test.c + */ +int Intg_EccTest(XNandPs8 * NandInstPtr,int TestLoops); + +#endif /**< End of protection macro */ diff --git a/XilinxProcessorIPLib/drivers/nandps8_v2_0/intgTest/intg_ecc_test.c b/XilinxProcessorIPLib/drivers/nandps8_v2_0/intgTest/intg_ecc_test.c new file mode 100755 index 00000000..5db22c85 --- /dev/null +++ b/XilinxProcessorIPLib/drivers/nandps8_v2_0/intgTest/intg_ecc_test.c @@ -0,0 +1,256 @@ +/****************************************************************************** +* +* (c) Copyright 2010-14 Xilinx, Inc. All rights reserved. +* +* This file contains confidential and proprietary information of Xilinx, Inc. +* and is protected under U.S. and international copyright and other +* intellectual property laws. +* +* DISCLAIMER +* This disclaimer is not a license and does not grant any rights to the +* materials distributed herewith. Except as otherwise provided in a valid +* license issued to you by Xilinx, and to the maximum extent permitted by +* applicable law: (1) THESE MATERIALS ARE MADE AVAILABLE "AS IS" AND WITH ALL +* FAULTS, AND XILINX HEREBY DISCLAIMS ALL WARRANTIES AND CONDITIONS, EXPRESS, +* IMPLIED, OR STATUTORY, INCLUDING BUT NOT LIMITED TO WARRANTIES OF +* MERCHANTABILITY, NON-INFRINGEMENT, OR FITNESS FOR ANY PARTICULAR PURPOSE +* and (2) Xilinx shall not be liable (whether in contract or tort, including +* negligence, or under any other theory of liability) for any loss or damage +* of any kind or nature related to, arising under or in connection with these +* materials, including for any direct, or any indirect, special, incidental, +* or consequential loss or damage (including loss of data, profits, goodwill, +* or any type of loss or damage suffered as a result of any action brought by +* a third party) even if such damage or loss was reasonably foreseeable or +* Xilinx had been advised of the possibility of the same. +* +* CRITICAL APPLICATIONS +* Xilinx products are not designed or intended to be fail-safe, or for use in +* any application requiring fail-safe performance, such as life-support or +* safety devices or systems, Class III medical devices, nuclear facilities, +* applications related to the deployment of airbags, or any other applications +* that could lead to death, personal injury, or severe property or +* environmental damage (individually and collectively, "Critical +* Applications"). Customer assumes the sole risk and liability of any use of +* Xilinx products in Critical Applications, subject only to applicable laws +* and regulations governing limitations on product liability. +* +* THIS COPYRIGHT NOTICE AND DISCLAIMER MUST BE RETAINED AS PART OF THIS FILE +* AT ALL TIMES. +* +******************************************************************************/ +/*****************************************************************************/ +/** +* +* @file intg_ecc_test.c +* +* This file contains the design example for using NAND driver (XNandPs8). +* This example tests the erase, read and write feature of the controller +* in the spare bytes region.The flash is erased and written. The data is +* read back and compared with the data written for correctness. +* +* @note None. +* +* +*
+*
+* MODIFICATION HISTORY:
+*
+* Ver   Who    Date	 Changes
+* ----- -----  -------- -----------------------------------------------
+* 1.0   sb    11/28/2014 First release
+*
+*
+* 
+* +******************************************************************************/ + +/***************************** Include Files ********************************/ + +#include "intg.h" + +/************************** Constant Definitions ****************************/ + +/**************************** Type Definitions ******************************/ + +/***************** Macros (Inline Functions) Definitions ********************/ + +/************************** Variable Definitions ****************************/ + +/************************** Function Prototypes *****************************/ +s32 Ecc_Test(XNandPs8 * NandInstPtr, u16 NandDeviceId); +/************************** Function Definitions ****************************/ + +/****************************************************************************/ +/** +* +* Entry point to call the ECC R/W test. +* +* @param NandInstPtr - Instance to the nand driver. +* @param TestLoops - Number of tests to execute. +* +* @return Number of test failures. +* +* @note None. +* +*****************************************************************************/ +int Intg_EccTest(XNandPs8 * NandInstPtr, int TestLoops) +{ + + s32 Status = XST_FAILURE; + CT_TestReset("Module Ecc Error Check test"); + + while(TestLoops--) { + /* Get the configuration table entry for this CAN device */ + Status = Ecc_Test(NandInstPtr, NAND_DEVICE_ID); + if (Status != XST_SUCCESS) { + CT_LOG_FAILURE("Ecc Error Check Test Failed with " + "%d mismatches\r\n", MismatchCounter); + break; + } + CT_NotifyNextPass(); + } + + return(CT_GetTestFailures()); +} + +/****************************************************************************/ +/** +* +* This function runs a test on the NAND flash device using the basic driver +* functions in polled mode. +* The function does the following tasks: +* - Erase the flash. +* - Write data to the flash. +* - Read back the data from the flash. +* - Compare the data read against the data Written. +* - Corrupt data by writing random data to flash +* - Read back the data from the flash. +* - Compare the data read against the data Written before corruption. +* +* @param NandInstPtr - Instance to the nand driver. +* @param NandDeviceId is is the XPAR__DEVICE_ID value +* from xparameters.h. +* +* @return +* - XST_SUCCESS if successful. +* - XST_FAILURE if failed. +* +* @note +* None +* +****************************************************************************/ +s32 Ecc_Test(XNandPs8 * NandInstPtr, u16 NandDeviceId) +{ + s32 Status = XST_FAILURE; + u32 Index; + u64 Offset; + u32 Length; + s32 i; + MismatchCounter = 0; + NandInstPtr->BCH_Error_Status = 0; + + Offset = (u64)(TEST_PAGE_START * NandInstPtr->Geometry.BytesPerPage); + Length = NandInstPtr->Geometry.BytesPerPage; + + /* + * Initialize the write buffer + */ + for (Index = 0; Index < Length;Index++) { + WriteBuffer[Index] = (u8)0; + } + + /* + * Enable ECC + */ + XNandPs8_EnableEccMode(NandInstPtr); + + /* + * Erase the flash + */ + Status = XNandPs8_Erase(NandInstPtr, (u64)Offset, (u64)Length); + if (Status != XST_SUCCESS) { + goto Out; + } + + /* + * Write to flash + */ + Status = XNandPs8_Write(NandInstPtr, (u64)Offset, (u64)Length, + &WriteBuffer[0]); + if (Status != XST_SUCCESS) { + goto Out; + } + + /* + * Read the flash after writing + */ + Status = XNandPs8_Read(NandInstPtr, (u64)Offset, (u64)Length, + &ReadBuffer[0]); + if (Status != XST_SUCCESS) { + goto Out; + } + + /* + * Compare the results + */ + for (Index = 0U; Index < Length;Index++) { + if (ReadBuffer[Index] != WriteBuffer[Index]) { + MismatchCounter++; + Status = XST_FAILURE; + } + } + + for (i = 0 ; i<24 ; i++){ + /* + * Disable ECC + */ + XNandPs8_DisableEccMode(NandInstPtr); + + /* + * Corrupting data in Write buffer + */ + WriteBuffer[i] = (u8)(i+1); + + /* + * Write to flash + */ + Status = XNandPs8_Write(NandInstPtr, (u64)Offset, (u64)Length, + &WriteBuffer[0]); + if (Status != XST_SUCCESS) { + goto Out; + } + + /* + * Correcting back data in Write buffer + */ + WriteBuffer[i] = (u8)0; + + /* + * Enable ECC check + */ + XNandPs8_EnableEccMode(NandInstPtr); + + /* + * Read the flash after writing + */ + Status = XNandPs8_Read(NandInstPtr, (u64)Offset, (u64)Length, + &ReadBuffer[0]); + if (Status != XST_SUCCESS) { + goto Out; + } + + /* + * Compare the results + */ + for (Index = 0U; Index < Length;Index++) { + if (ReadBuffer[Index] != WriteBuffer[Index]) { + MismatchCounter++; + Status = XST_FAILURE; + } + } + } + xil_printf("Total BCH ECC errors = %d\r\n",NandInstPtr->BCH_Error_Status); + +Out: + return Status; +} diff --git a/XilinxProcessorIPLib/drivers/nandps8_v2_0/intgTest/intg_erase_read.c b/XilinxProcessorIPLib/drivers/nandps8_v2_0/intgTest/intg_erase_read.c new file mode 100755 index 00000000..1f2bb2ba --- /dev/null +++ b/XilinxProcessorIPLib/drivers/nandps8_v2_0/intgTest/intg_erase_read.c @@ -0,0 +1,193 @@ +/****************************************************************************** +* +* (c) Copyright 2010-14 Xilinx, Inc. All rights reserved. +* +* This file contains confidential and proprietary information of Xilinx, Inc. +* and is protected under U.S. and international copyright and other +* intellectual property laws. +* +* DISCLAIMER +* This disclaimer is not a license and does not grant any rights to the +* materials distributed herewith. Except as otherwise provided in a valid +* license issued to you by Xilinx, and to the maximum extent permitted by +* applicable law: (1) THESE MATERIALS ARE MADE AVAILABLE "AS IS" AND WITH ALL +* FAULTS, AND XILINX HEREBY DISCLAIMS ALL WARRANTIES AND CONDITIONS, EXPRESS, +* IMPLIED, OR STATUTORY, INCLUDING BUT NOT LIMITED TO WARRANTIES OF +* MERCHANTABILITY, NON-INFRINGEMENT, OR FITNESS FOR ANY PARTICULAR PURPOSE +* and (2) Xilinx shall not be liable (whether in contract or tort, including +* negligence, or under any other theory of liability) for any loss or damage +* of any kind or nature related to, arising under or in connection with these +* materials, including for any direct, or any indirect, special, incidental, +* or consequential loss or damage (including loss of data, profits, goodwill, +* or any type of loss or damage suffered as a result of any action brought by +* a third party) even if such damage or loss was reasonably foreseeable or +* Xilinx had been advised of the possibility of the same. +* +* CRITICAL APPLICATIONS +* Xilinx products are not designed or intended to be fail-safe, or for use in +* any application requiring fail-safe performance, such as life-support or +* safety devices or systems, Class III medical devices, nuclear facilities, +* applications related to the deployment of airbags, or any other applications +* that could lead to death, personal injury, or severe property or +* environmental damage (individually and collectively, "Critical +* Applications"). Customer assumes the sole risk and liability of any use of +* Xilinx products in Critical Applications, subject only to applicable laws +* and regulations governing limitations on product liability. +* +* THIS COPYRIGHT NOTICE AND DISCLAIMER MUST BE RETAINED AS PART OF THIS FILE +* AT ALL TIMES. +* +******************************************************************************/ +/*****************************************************************************/ +/** +* +* @file intg_erase_read.c +* +* This file contains the design example for using NAND driver (XNandPs8). +* This example tests the erase and read feature of the controller. +* The flash is erased. The data is +* read back and compared with the 0xFF for correctness. +* +* @note None. +* +* +*
+*
+* MODIFICATION HISTORY:
+*
+* Ver   Who    Date	 Changes
+* ----- -----  -------- -----------------------------------------------
+* 1.0   sb    11/28/2014 First release
+*
+*
+* 
+* +******************************************************************************/ + +/***************************** Include Files ********************************/ + +#include "intg.h" + +/************************** Constant Definitions ****************************/ + +/**************************** Type Definitions ******************************/ + +/***************** Macros (Inline Functions) Definitions ********************/ + +/************************** Variable Definitions ****************************/ + +/************************** Function Prototypes *****************************/ +s32 Erase_Read_Test(XNandPs8 * NandInstPtr, u16 NandDeviceId); +/************************** Function Definitions ****************************/ + +/****************************************************************************/ +/** +* +* Entry point to call the Erase Read test. +* +* @param NandInstPtr - Instance to the nand driver. +* @param TestLoops - Number of tests to execute. +* +* @return Number of test failures. +* +* @note None. +* +*****************************************************************************/ +int Intg_EraseReadTest(XNandPs8 * NandInstPtr, int TestLoops) +{ + + s32 Status = XST_FAILURE; + CT_TestReset("Module FLASH Erase Read test"); + + while(TestLoops--) { + /* Get the configuration table entry for this CAN device */ + Status = Erase_Read_Test(NandInstPtr, NAND_DEVICE_ID); + if (Status != XST_SUCCESS) { + CT_LOG_FAILURE("Nand Flash Erase ReadTest Failed" + " with %d mismatches\r\n", MismatchCounter); + break; + } + CT_NotifyNextPass(); + } + + return(CT_GetTestFailures()); +} + +/****************************************************************************/ +/** +* +* This function runs a test on the NAND flash device using the basic driver +* functions in polled mode. +* The function does the following tasks: +* - Erase the flash. +* - Read back the data from the flash. +* - Compare the data read against 0xFF. +* +* @param NandInstPtr - Instance to the nand driver. +* @param NandDeviceId is is the XPAR__DEVICE_ID value +* from xparameters.h. +* +* @return +* - XST_SUCCESS if successful. +* - XST_FAILURE if failed. +* +* @note +* None +* +****************************************************************************/ +s32 Erase_Read_Test(XNandPs8 * NandInstPtr, u16 NandDeviceId) +{ + s32 Status = XST_FAILURE; + s32 i = 0; + u32 Index; + u64 Offset; + u32 Length; + u32 BlockSize = NandInstPtr->Geometry.BlockSize; + MismatchCounter = 0; + + Offset = (u64)TEST_BLOCK_START * NandInstPtr->Geometry.BlockSize; + Length = NandInstPtr->Geometry.BytesPerPage; + + /* + * Erasing whole block + */ + Status = XNandPs8_Erase(NandInstPtr, (u64)Offset, (u64)BlockSize); + if (Status != XST_SUCCESS) { + goto Out; + } + + for (i = 0; i < NandInstPtr->Geometry.PagesPerBlock; i++){ + /* + * Disbale ECC + */ + XNandPs8_DisableEccMode(NandInstPtr); + + /* + * Read the flash after writing + */ + Status = XNandPs8_Read(NandInstPtr, (u64)Offset, (u64)Length, + &ReadBuffer[0]); + if (Status != XST_SUCCESS) { + goto Out; + } + + /* + * Enable ECC + */ + XNandPs8_EnableEccMode(NandInstPtr); + + /* + * Compare the results + */ + for (Index = 0U; Index < Length;Index++) { + if (ReadBuffer[Index] != (u8)0xFF) { + MismatchCounter++; + Status = XST_FAILURE; + } + } + Offset = Offset + NandInstPtr->Geometry.BytesPerPage; + } + +Out: + return Status; +} diff --git a/XilinxProcessorIPLib/drivers/nandps8_v2_0/intgTest/intg_flash_rw.c b/XilinxProcessorIPLib/drivers/nandps8_v2_0/intgTest/intg_flash_rw.c new file mode 100755 index 00000000..fa0b8aa9 --- /dev/null +++ b/XilinxProcessorIPLib/drivers/nandps8_v2_0/intgTest/intg_flash_rw.c @@ -0,0 +1,194 @@ +/****************************************************************************** +* +* (c) Copyright 2010-14 Xilinx, Inc. All rights reserved. +* +* This file contains confidential and proprietary information of Xilinx, Inc. +* and is protected under U.S. and international copyright and other +* intellectual property laws. +* +* DISCLAIMER +* This disclaimer is not a license and does not grant any rights to the +* materials distributed herewith. Except as otherwise provided in a valid +* license issued to you by Xilinx, and to the maximum extent permitted by +* applicable law: (1) THESE MATERIALS ARE MADE AVAILABLE "AS IS" AND WITH ALL +* FAULTS, AND XILINX HEREBY DISCLAIMS ALL WARRANTIES AND CONDITIONS, EXPRESS, +* IMPLIED, OR STATUTORY, INCLUDING BUT NOT LIMITED TO WARRANTIES OF +* MERCHANTABILITY, NON-INFRINGEMENT, OR FITNESS FOR ANY PARTICULAR PURPOSE +* and (2) Xilinx shall not be liable (whether in contract or tort, including +* negligence, or under any other theory of liability) for any loss or damage +* of any kind or nature related to, arising under or in connection with these +* materials, including for any direct, or any indirect, special, incidental, +* or consequential loss or damage (including loss of data, profits, goodwill, +* or any type of loss or damage suffered as a result of any action brought by +* a third party) even if such damage or loss was reasonably foreseeable or +* Xilinx had been advised of the possibility of the same. +* +* CRITICAL APPLICATIONS +* Xilinx products are not designed or intended to be fail-safe, or for use in +* any application requiring fail-safe performance, such as life-support or +* safety devices or systems, Class III medical devices, nuclear facilities, +* applications related to the deployment of airbags, or any other applications +* that could lead to death, personal injury, or severe property or +* environmental damage (individually and collectively, "Critical +* Applications"). Customer assumes the sole risk and liability of any use of +* Xilinx products in Critical Applications, subject only to applicable laws +* and regulations governing limitations on product liability. +* +* THIS COPYRIGHT NOTICE AND DISCLAIMER MUST BE RETAINED AS PART OF THIS FILE +* AT ALL TIMES. +* +******************************************************************************/ +/*****************************************************************************/ +/** +* +* @file intg_flash_rw.c +* +* This file contains the design example for using NAND driver (XNandPs8). +* This example tests the erase, read and write feature of the controller. +* The flash is erased and written. The data is +* read back and compared with the data written for correctness. +* +* @note None. +* +* +*
+*
+* MODIFICATION HISTORY:
+*
+* Ver   Who    Date	 Changes
+* ----- -----  -------- -----------------------------------------------
+* 1.0   sb    11/28/2014 First release
+*
+*
+* 
+* +******************************************************************************/ + +/***************************** Include Files ********************************/ + +#include "intg.h" + +/************************** Constant Definitions ****************************/ + +/**************************** Type Definitions ******************************/ + +/***************** Macros (Inline Functions) Definitions ********************/ + +/************************** Variable Definitions ****************************/ + +/************************** Function Prototypes *****************************/ +s32 Flash_RW_Test(XNandPs8 * NandInstPtr, u16 NandDeviceId); +/************************** Function Definitions ****************************/ + +/****************************************************************************/ +/** +* +* Entry point to call the Flash R/W test. +* +* @param NandInstPtr - Instance to the nand driver. +* @param TestLoops - Number of tests to execute. +* +* @return Number of test failures. +* +* @note None. +* +*****************************************************************************/ +int Intg_FlashRWTest(XNandPs8 * NandInstPtr, int TestLoops) +{ + + s32 Status = XST_FAILURE; + CT_TestReset("Module FLASH Read Write test"); + + while(TestLoops--) { + + /* Get the configuration table entry for this CAN device */ + Status = Flash_RW_Test(NandInstPtr, NAND_DEVICE_ID); + if (Status != XST_SUCCESS) { + CT_LOG_FAILURE("Nand Flash Read Write Test Failed" + " with %d mismatches\r\n", MismatchCounter); + break; + } + CT_NotifyNextPass(); + + } + + return(CT_GetTestFailures()); +} + +/****************************************************************************/ +/** +* +* This function runs a test on the NAND flash device using the basic driver +* functions in polled mode. +* The function does the following tasks: +* - Initialize the driver. +* - Erase the flash. +* - Write data to the flash. +* - Read back the data from the flash. +* - Compare the data read against the data Written. +* +* @param NandInstPtr - Instance to the nand driver. +* @param NandDeviceId is is the XPAR__DEVICE_ID value +* from xparameters.h. +* +* @return +* - XST_SUCCESS if successful. +* - XST_FAILURE if failed. +* +* @note +* None +* +****************************************************************************/ +s32 Flash_RW_Test(XNandPs8 * NandInstPtr, u16 NandDeviceId) +{ + s32 Status = XST_FAILURE; + u32 Index; + u64 Offset; + u32 Length; + MismatchCounter = 0; + + Offset = (u64)(TEST_PAGE_START * NandInstPtr->Geometry.BytesPerPage); + Length = NandInstPtr->Geometry.BytesPerPage; + + /* + * Initialize the write buffer + */ + for (Index = 0; Index < Length;Index++) { + WriteBuffer[Index] = (u8) (rand() % 256); + } + /* + * Erase the Block + */ + Status = XNandPs8_Erase(NandInstPtr, (u64)Offset, (u64)Length); + if (Status != XST_SUCCESS) { + goto Out; + } + /* + * Write to page offset + */ + Status = XNandPs8_Write(NandInstPtr, (u64)Offset, (u64)Length, + &WriteBuffer[0]); + if (Status != XST_SUCCESS) { + goto Out; + } + /* + * Read from the page after writing + */ + Status = XNandPs8_Read(NandInstPtr, (u64)Offset, (u64)Length, + &ReadBuffer[0]); + if (Status != XST_SUCCESS) { + goto Out; + } + /* + * Compare the results + */ + for (Index = 0U; Index < 10;Index++) { + if (ReadBuffer[Index] != WriteBuffer[Index]) { + MismatchCounter++; + Status = XST_FAILURE; + } + } + +Out: + return Status; +} diff --git a/XilinxProcessorIPLib/drivers/nandps8_v2_0/intgTest/intg_partialpage_rw.c b/XilinxProcessorIPLib/drivers/nandps8_v2_0/intgTest/intg_partialpage_rw.c new file mode 100755 index 00000000..597d6f0c --- /dev/null +++ b/XilinxProcessorIPLib/drivers/nandps8_v2_0/intgTest/intg_partialpage_rw.c @@ -0,0 +1,208 @@ +/****************************************************************************** +* +* (c) Copyright 2010-14 Xilinx, Inc. All rights reserved. +* +* This file contains confidential and proprietary information of Xilinx, Inc. +* and is protected under U.S. and international copyright and other +* intellectual property laws. +* +* DISCLAIMER +* This disclaimer is not a license and does not grant any rights to the +* materials distributed herewith. Except as otherwise provided in a valid +* license issued to you by Xilinx, and to the maximum extent permitted by +* applicable law: (1) THESE MATERIALS ARE MADE AVAILABLE "AS IS" AND WITH ALL +* FAULTS, AND XILINX HEREBY DISCLAIMS ALL WARRANTIES AND CONDITIONS, EXPRESS, +* IMPLIED, OR STATUTORY, INCLUDING BUT NOT LIMITED TO WARRANTIES OF +* MERCHANTABILITY, NON-INFRINGEMENT, OR FITNESS FOR ANY PARTICULAR PURPOSE +* and (2) Xilinx shall not be liable (whether in contract or tort, including +* negligence, or under any other theory of liability) for any loss or damage +* of any kind or nature related to, arising under or in connection with these +* materials, including for any direct, or any indirect, special, incidental, +* or consequential loss or damage (including loss of data, profits, goodwill, +* or any type of loss or damage suffered as a result of any action brought by +* a third party) even if such damage or loss was reasonably foreseeable or +* Xilinx had been advised of the possibility of the same. +* +* CRITICAL APPLICATIONS +* Xilinx products are not designed or intended to be fail-safe, or for use in +* any application requiring fail-safe performance, such as life-support or +* safety devices or systems, Class III medical devices, nuclear facilities, +* applications related to the deployment of airbags, or any other applications +* that could lead to death, personal injury, or severe property or +* environmental damage (individually and collectively, "Critical +* Applications"). Customer assumes the sole risk and liability of any use of +* Xilinx products in Critical Applications, subject only to applicable laws +* and regulations governing limitations on product liability. +* +* THIS COPYRIGHT NOTICE AND DISCLAIMER MUST BE RETAINED AS PART OF THIS FILE +* AT ALL TIMES. +* +******************************************************************************/ +/*****************************************************************************/ +/** +* +* @file intg_partialpage_rw.c +* +* This file contains the design example for using NAND driver (XNandPs8). +* This example tests the erase, read and write feature of the controller +* to the page.The flash is erased and written. The data is +* read back and compared with the data written for correctness. + +* +* @note None. +* +* +*
+*
+* MODIFICATION HISTORY:
+*
+* Ver   Who    Date	 Changes
+* ----- -----  -------- -----------------------------------------------
+* 1.0   sb    11/28/2014 First release
+*
+*
+* 
+* +******************************************************************************/ + +/***************************** Include Files ********************************/ + +#include "intg.h" + +/************************** Constant Definitions ****************************/ + +/**************************** Type Definitions ******************************/ + +/***************** Macros (Inline Functions) Definitions ********************/ + +/************************** Variable Definitions ****************************/ + +/************************** Function Prototypes *****************************/ +s32 PartialPage_RW_Test(XNandPs8 * NandInstPtr, u16 NandDeviceId); +/************************** Function Definitions ****************************/ + +/****************************************************************************/ +/** +* +* Entry point to call the Partial Page R/W test. +* +* @param NandInstPtr - Instance to the nand driver. +* @param TestLoops - Number of tests to execute. +* +* @return Number of test failures. +* +* @note None. +* +*****************************************************************************/ +int Intg_PartialRWTest(XNandPs8 * NandInstPtr, int TestLoops) +{ + + s32 Status = XST_FAILURE; + CT_TestReset("Module Partial Page Read Write test"); + + while(TestLoops--) { + /* Get the configuration table entry for this CAN device */ + Status = PartialPage_RW_Test(NandInstPtr, NAND_DEVICE_ID); + if (Status != XST_SUCCESS) { + CT_LOG_FAILURE("Nand Partial Page Read Write Failed" + " with %d mismatches\r\n", MismatchCounter); + break; + } + CT_NotifyNextPass(); + } + + return(CT_GetTestFailures()); +} + +/****************************************************************************/ +/** +* +* This function runs a test on the NAND flash device using the basic driver +* functions in polled mode. +* The function does the following tasks: +* - Choose random page size for read write Operations. +* - Erase the flash. +* - Write data to the flash. +* - Read back the data from the flash. +* - Compare the data read against the data Written. +* +* @param NandInstPtr - Instance to the nand driver. +* @param NandDeviceId is is the XPAR__DEVICE_ID value +* from xparameters.h. +* +* @return +* - XST_SUCCESS if successful. +* - XST_FAILURE if failed. +* +* @note +* None +* +****************************************************************************/ +s32 PartialPage_RW_Test(XNandPs8 * NandInstPtr, u16 NandDeviceId) +{ + s32 Status = (s32)XST_FAILURE; + u32 Index; + u64 Offset; + u32 Length; + s32 i; + MismatchCounter = 0; + Offset = (u64)(TEST_PAGE_START * (u64)NandInstPtr->Geometry.BytesPerPage); + Length = NandInstPtr->Geometry.BytesPerPage; + + /* + * Repeat the test for 20 iterations + */ + for(i = 0; i< 5; i++){ + + Length = rand()%NandInstPtr->Geometry.BytesPerPage; + if(Length == 0U){ + Length = NandInstPtr->Geometry.BytesPerPage; + } + + /* + * Erase the Block + */ + Status = XNandPs8_Erase(NandInstPtr, (u64)Offset, (u64)Length); + if (Status != (s32)XST_SUCCESS) { + goto Out; + } + + /* + * Initialize the write buffer + */ + for (Index = 0U; Index < Length;Index++) { + WriteBuffer[Index] = ((u8)rand() % (u8)256); + } + + /* + * Write to flash + */ + Status = XNandPs8_Write(NandInstPtr, (u64)Offset, (u64)Length, + &WriteBuffer[0]); + if (Status != (s32)XST_SUCCESS) { + goto Out; + } + + /* + * Read the flash after writing + */ + Status = XNandPs8_Read(NandInstPtr, (u64)Offset, (u64)Length, + &ReadBuffer[0]); + if (Status != (s32)XST_SUCCESS) { + goto Out; + } + + /* + * Compare the results + */ + for (Index = 0U; Index < Length;Index++) { + if (ReadBuffer[Index] != WriteBuffer[Index]) { + MismatchCounter++; + Status = (s32)XST_FAILURE; + } + } + } + +Out: + return Status; +} diff --git a/XilinxProcessorIPLib/drivers/nandps8_v2_0/intgTest/intg_random_rw.c b/XilinxProcessorIPLib/drivers/nandps8_v2_0/intgTest/intg_random_rw.c new file mode 100755 index 00000000..c043a702 --- /dev/null +++ b/XilinxProcessorIPLib/drivers/nandps8_v2_0/intgTest/intg_random_rw.c @@ -0,0 +1,209 @@ +/****************************************************************************** +* +* (c) Copyright 2010-14 Xilinx, Inc. All rights reserved. +* +* This file contains confidential and proprietary information of Xilinx, Inc. +* and is protected under U.S. and international copyright and other +* intellectual property laws. +* +* DISCLAIMER +* This disclaimer is not a license and does not grant any rights to the +* materials distributed herewith. Except as otherwise provided in a valid +* license issued to you by Xilinx, and to the maximum extent permitted by +* applicable law: (1) THESE MATERIALS ARE MADE AVAILABLE "AS IS" AND WITH ALL +* FAULTS, AND XILINX HEREBY DISCLAIMS ALL WARRANTIES AND CONDITIONS, EXPRESS, +* IMPLIED, OR STATUTORY, INCLUDING BUT NOT LIMITED TO WARRANTIES OF +* MERCHANTABILITY, NON-INFRINGEMENT, OR FITNESS FOR ANY PARTICULAR PURPOSE +* and (2) Xilinx shall not be liable (whether in contract or tort, including +* negligence, or under any other theory of liability) for any loss or damage +* of any kind or nature related to, arising under or in connection with these +* materials, including for any direct, or any indirect, special, incidental, +* or consequential loss or damage (including loss of data, profits, goodwill, +* or any type of loss or damage suffered as a result of any action brought by +* a third party) even if such damage or loss was reasonably foreseeable or +* Xilinx had been advised of the possibility of the same. +* +* CRITICAL APPLICATIONS +* Xilinx products are not designed or intended to be fail-safe, or for use in +* any application requiring fail-safe performance, such as life-support or +* safety devices or systems, Class III medical devices, nuclear facilities, +* applications related to the deployment of airbags, or any other applications +* that could lead to death, personal injury, or severe property or +* environmental damage (individually and collectively, "Critical +* Applications"). Customer assumes the sole risk and liability of any use of +* Xilinx products in Critical Applications, subject only to applicable laws +* and regulations governing limitations on product liability. +* +* THIS COPYRIGHT NOTICE AND DISCLAIMER MUST BE RETAINED AS PART OF THIS FILE +* AT ALL TIMES. +* +******************************************************************************/ +/*****************************************************************************/ +/** +* +* @file intg_random_rw.c +* +* This file contains the design example for using NAND driver (XNandPs8). +* This example tests the erase, read and write feature of the controller +* to a complete block. The block is randomly selected. +* The flash is erased and written. The data is read back and compared +* with the data written for correctness. +* +* @note None. +* +* +*
+*
+* MODIFICATION HISTORY:
+*
+* Ver   Who    Date	 Changes
+* ----- -----  -------- -----------------------------------------------
+* 1.0   sb    11/28/2014 First release
+*
+*
+* 
+* +******************************************************************************/ + +/***************************** Include Files ********************************/ + +#include "intg.h" + +/************************** Constant Definitions ****************************/ + +/**************************** Type Definitions ******************************/ + +/***************** Macros (Inline Functions) Definitions ********************/ + +/************************** Variable Definitions ****************************/ + +/************************** Function Prototypes *****************************/ +s32 Random_Block_RW_Test(XNandPs8 * NandInstPtr, u16 NandDeviceId); +/************************** Function Definitions ****************************/ + +/****************************************************************************/ +/** +* +* Entry point to call the Random Block Read Write test. +* +* @param NandInstPtr - Instance to the nand driver. +* @param TestLoops - Number of tests to execute. +* +* @return Number of test failures. +* +* @note None. +* +*****************************************************************************/ +int Intg_RandomRWTest(XNandPs8 * NandInstPtr, int TestLoops) +{ + + s32 Status = XST_FAILURE; + CT_TestReset("Module Random Block Read Write test"); + + while(TestLoops--) { + /* Get the configuration table entry for this CAN device */ + Status = Random_Block_RW_Test(NandInstPtr, NAND_DEVICE_ID); + if (Status != XST_SUCCESS) { + CT_LOG_FAILURE("Nand Random Block Read Write Test Failed" + " with %d mismatches\r\n", MismatchCounter); + break; + } + CT_NotifyNextPass(); + } + + return(CT_GetTestFailures()); +} + +/****************************************************************************/ +/** +* +* This function runs a test on the NAND flash device using the basic driver +* functions in polled mode. +* The function does the following tasks: +* - Initialize the driver. +* - Erase the flash. +* - Write data to the flash. +* - Read back the data from the flash. +* - Compare the data read against the data Written. +* +* @param NandInstPtr - Instance to the nand driver. +* @param NandDeviceId is is the XPAR__DEVICE_ID value +* from xparameters.h. +* +* @return +* - XST_SUCCESS if successful. +* - XST_FAILURE if failed. +* +* @note +* None +* +****************************************************************************/ +s32 Random_Block_RW_Test(XNandPs8 * NandInstPtr, u16 NandDeviceId) +{ + s32 Status = XST_FAILURE; + u32 Index; + u64 Offset; + u32 Length; + s32 i = 0; + u32 BlockSize = NandInstPtr->Geometry.BlockSize; + + Offset = (u64) ((rand()% 50) * + NandInstPtr->Geometry.BlockSize); + + Length = NandInstPtr->Geometry.BytesPerPage; + + /* + * Erase the Block + */ + Status = XNandPs8_Erase(NandInstPtr, (u64)Offset, (u64)BlockSize); + if (Status != XST_SUCCESS) { + goto Out; + } + + /* + * Flash operation i.e. erase, write and read for all the pages + * of the block. + * This test will take some time to execute. Please be patient. + */ + for (i = 0; i < NandInstPtr->Geometry.PagesPerBlock; i++){ + + /* + * Initialize the write buffer + */ + for (Index = 0; Index < Length;Index++) { + WriteBuffer[Index] = (u8) (rand() % 256); + } + + /* + * Write to flash + */ + Status = XNandPs8_Write(NandInstPtr, (u64)Offset, (u64)Length, + &WriteBuffer[0]); + if (Status != XST_SUCCESS) { + goto Out; + } + + /* + * Read the flash after writing + */ + Status = XNandPs8_Read(NandInstPtr, (u64)Offset, (u64)Length, + &ReadBuffer[0]); + if (Status != XST_SUCCESS) { + goto Out; + } + + /* + * Compare the results + */ + for (Index = 0U; Index < Length;Index++) { + if (ReadBuffer[Index] != WriteBuffer[Index]) { + MismatchCounter++; + Status = XST_FAILURE; + } + } + Offset = Offset + NandInstPtr->Geometry.BytesPerPage; + } + +Out: + return Status; +} diff --git a/XilinxProcessorIPLib/drivers/nandps8_v2_0/intgTest/intg_sparebytes_rw.c b/XilinxProcessorIPLib/drivers/nandps8_v2_0/intgTest/intg_sparebytes_rw.c new file mode 100755 index 00000000..e12941fb --- /dev/null +++ b/XilinxProcessorIPLib/drivers/nandps8_v2_0/intgTest/intg_sparebytes_rw.c @@ -0,0 +1,215 @@ +/****************************************************************************** +* +* (c) Copyright 2010-14 Xilinx, Inc. All rights reserved. +* +* This file contains confidential and proprietary information of Xilinx, Inc. +* and is protected under U.S. and international copyright and other +* intellectual property laws. +* +* DISCLAIMER +* This disclaimer is not a license and does not grant any rights to the +* materials distributed herewith. Except as otherwise provided in a valid +* license issued to you by Xilinx, and to the maximum extent permitted by +* applicable law: (1) THESE MATERIALS ARE MADE AVAILABLE "AS IS" AND WITH ALL +* FAULTS, AND XILINX HEREBY DISCLAIMS ALL WARRANTIES AND CONDITIONS, EXPRESS, +* IMPLIED, OR STATUTORY, INCLUDING BUT NOT LIMITED TO WARRANTIES OF +* MERCHANTABILITY, NON-INFRINGEMENT, OR FITNESS FOR ANY PARTICULAR PURPOSE +* and (2) Xilinx shall not be liable (whether in contract or tort, including +* negligence, or under any other theory of liability) for any loss or damage +* of any kind or nature related to, arising under or in connection with these +* materials, including for any direct, or any indirect, special, incidental, +* or consequential loss or damage (including loss of data, profits, goodwill, +* or any type of loss or damage suffered as a result of any action brought by +* a third party) even if such damage or loss was reasonably foreseeable or +* Xilinx had been advised of the possibility of the same. +* +* CRITICAL APPLICATIONS +* Xilinx products are not designed or intended to be fail-safe, or for use in +* any application requiring fail-safe performance, such as life-support or +* safety devices or systems, Class III medical devices, nuclear facilities, +* applications related to the deployment of airbags, or any other applications +* that could lead to death, personal injury, or severe property or +* environmental damage (individually and collectively, "Critical +* Applications"). Customer assumes the sole risk and liability of any use of +* Xilinx products in Critical Applications, subject only to applicable laws +* and regulations governing limitations on product liability. +* +* THIS COPYRIGHT NOTICE AND DISCLAIMER MUST BE RETAINED AS PART OF THIS FILE +* AT ALL TIMES. +* +******************************************************************************/ +/*****************************************************************************/ +/** +* +* @file intg_sparebytes_rw.c +* +* This file contains the design example for using NAND driver (XNandPs8). +* This example tests the erase, read and write feature of the controller +* in the spare bytes region.The flash is erased and written. The data is +* read back and compared with the data written for correctness. +* +* @note None. +* +* +*
+*
+* MODIFICATION HISTORY:
+*
+* Ver   Who    Date	 Changes
+* ----- -----  -------- -----------------------------------------------
+* 1.0   sb    11/28/2014 First release
+*
+* 
+* +******************************************************************************/ + +/***************************** Include Files ********************************/ + +#include "intg.h" + +/************************** Constant Definitions ****************************/ + +/**************************** Type Definitions ******************************/ + +/***************** Macros (Inline Functions) Definitions ********************/ + +/************************** Variable Definitions ****************************/ + +/************************** Function Prototypes *****************************/ +s32 SpareBytes_RW_Test(XNandPs8 * NandInstPtr, u16 NandDeviceId); +/************************** Function Definitions ****************************/ + +/****************************************************************************/ +/** +* +* Entry point to call the Spare Bytes test. +* +* @param NandInstPtr - Instance to the nand driver. +* @param TestLoops - Number of tests to execute. +* +* @return Number of test failures. +* +* @note None. +* +*****************************************************************************/ +int Intg_SpareBytesRWTest(XNandPs8 * NandInstPtr, int TestLoops) +{ + + s32 Status = XST_FAILURE; + CT_TestReset("Module Spare Bytes Read Write test"); + + while(TestLoops--) { + /* Get the configuration table entry for this CAN device */ + Status = SpareBytes_RW_Test(NandInstPtr, NAND_DEVICE_ID); + if (Status != XST_SUCCESS) { + CT_LOG_FAILURE("Nand Spare Bytes Read Write Test Failed" + " with %d mismatches\r\n", MismatchCounter); + break; + } + CT_NotifyNextPass(); + } + + return(CT_GetTestFailures()); +} + +/****************************************************************************/ +/** +* +* This function runs a test on the NAND flash device using the basic driver +* functions in polled mode. +* The function does the following tasks: +* - Erase the flash. +* - Write data to the spare byte section of flash. +* - Read back the data from the spare byte section of flash. +* - Compare the data read against the data Written. +* +* @param NandInstPtr - Instance to the nand driver. +* @param NandDeviceId is is the XPAR__DEVICE_ID value +* from xparameters.h. +* +* @return +* - XST_SUCCESS if successful. +* - XST_FAILURE if failed. +* +* @note +* None +* +****************************************************************************/ +s32 SpareBytes_RW_Test(XNandPs8 * NandInstPtr, u16 NandDeviceId) +{ + s32 Status = XST_FAILURE; + u32 Index; + u64 Offset; + u16 Length; + s32 i; + MismatchCounter = 0; + + Offset = (u64)(TEST_PAGE_START * NandInstPtr->Geometry.BytesPerPage); + Length = NandInstPtr->Geometry.BytesPerPage; + + /* + * Erase the flash + */ + Status = XNandPs8_Erase(NandInstPtr, (u64)Offset, (u64)Length); + if (Status != XST_SUCCESS) { + goto Out; + } + + /* + * Repeat the test for 10 iterations + */ + for(i = 0; i< 10; i++){ + Length = rand() % NandInstPtr->Geometry.SpareBytesPerPage; + if(Length == 0U){ + Length = NandInstPtr->Geometry.SpareBytesPerPage; + } + + /* + * Initialize the write buffer + */ + for (Index = 0; Index < Length;Index++) { + WriteBuffer[Index] = (u8) (rand() % 256); + } + + /* + * Disable the ECC mode + */ + XNandPs8_DisableEccMode(NandInstPtr); + + /* + * Write to flash Spare Bytes Section + */ + Status = XNandPs8_WriteSpareBytes(NandInstPtr, (u32)Offset, + &WriteBuffer[0]); + if (Status != XST_SUCCESS) { + goto Out; + } + + /* + * Read from the flash Spare Bytes after writing + */ + Status = XNandPs8_ReadSpareBytes(NandInstPtr, (u32)Offset, + &ReadBuffer[0]); + if (Status != XST_SUCCESS) { + goto Out; + } + + /* + * Enable the ECC mode + */ + XNandPs8_EnableEccMode(NandInstPtr); + /* + * Compare the results + */ + for (Index = 0U; Index < Length;Index++) { + if (ReadBuffer[Index] != WriteBuffer[Index]) { + MismatchCounter++; + Status = XST_FAILURE; + } + } + } + + Status = XST_SUCCESS; +Out: + return Status; +} diff --git a/XilinxProcessorIPLib/drivers/nandps8_v2_0/intgTest/xil_testlib.h b/XilinxProcessorIPLib/drivers/nandps8_v2_0/intgTest/xil_testlib.h new file mode 100755 index 00000000..c9f70bce --- /dev/null +++ b/XilinxProcessorIPLib/drivers/nandps8_v2_0/intgTest/xil_testlib.h @@ -0,0 +1,96 @@ +/* $Id: xil_testlib.h,v 1.00 2009/2/19 */ +/****************************************************************************** +* +* (c) Copyright 2010-13 Xilinx, Inc. All rights reserved. +* +* This file contains confidential and proprietary information of Xilinx, Inc. +* and is protected under U.S. and international copyright and other +* intellectual property laws. +* +* DISCLAIMER +* This disclaimer is not a license and does not grant any rights to the +* materials distributed herewith. Except as otherwise provided in a valid +* license issued to you by Xilinx, and to the maximum extent permitted by +* applicable law: (1) THESE MATERIALS ARE MADE AVAILABLE "AS IS" AND WITH ALL +* FAULTS, AND XILINX HEREBY DISCLAIMS ALL WARRANTIES AND CONDITIONS, EXPRESS, +* IMPLIED, OR STATUTORY, INCLUDING BUT NOT LIMITED TO WARRANTIES OF +* MERCHANTABILITY, NON-INFRINGEMENT, OR FITNESS FOR ANY PARTICULAR PURPOSE +* and (2) Xilinx shall not be liable (whether in contract or tort, including +* negligence, or under any other theory of liability) for any loss or damage +* of any kind or nature related to, arising under or in connection with these +* materials, including for any direct, or any indirect, special, incidental, +* or consequential loss or damage (including loss of data, profits, goodwill, +* or any type of loss or damage suffered as a result of any action brought by +* a third party) even if such damage or loss was reasonably foreseeable or +* Xilinx had been advised of the possibility of the same. +* +* CRITICAL APPLICATIONS +* Xilinx products are not designed or intended to be fail-safe, or for use in +* any application requiring fail-safe performance, such as life-support or +* safety devices or systems, Class III medical devices, nuclear facilities, +* applications related to the deployment of airbags, or any other applications +* that could lead to death, personal injury, or severe property or +* environmental damage (individually and collectively, "Critical +* Applications"). Customer assumes the sole risk and liability of any use of +* Xilinx products in Critical Applications, subject only to applicable laws +* and regulations governing limitations on product liability. +* +* THIS COPYRIGHT NOTICE AND DISCLAIMER MUST BE RETAINED AS PART OF THIS FILE +* AT ALL TIMES. +* +******************************************************************************/ +/*****************************************************************************/ + +/***************************** Include Files *********************************/ +#include +#include "intg.h" + +/** +* +* @file xil_testlib.h +* +* This file contains Xilinx software exit messages.These messages are set to be +* matched with the scan strings for board test such that board test would know +* the result of a standalone test program +* +******************************************************************************/ + +#ifndef XIL_TESTLIB_H /**< prevent circular inclusions */ +#define XIL_TESTLIB_H /**< by using protection macros */ + +#ifdef __cplusplus +extern "C" { +#endif + +/***************** Macros (Inline Functions) Definitions *********************/ +/** + * XIL_PASS puts out a message to signal board test that a program has pass + * the testing program without errors + * + * param None. + * + * @return None. + * + * @note None. + */ +#define XIL_PASS() xil_printf("\r\nREGRESSION TEST PASS.\r\n") + +/* + * XIL_FAIL puts out a message to signal board test that a program has not pass + * the testing program + * + * @param number of errors. + * + * @return None. + * + * @note None. + */ +#define XIL_FAIL(numErrors) \ + xil_printf("\r\nREGRESSION TEST FAIL WITH %d ERRORS.\r\n", numErrors) + + +#ifdef __cplusplus +} +#endif + +#endif /**< End of protection macro */ diff --git a/XilinxProcessorIPLib/drivers/nandps8_v2_0/src/Makefile b/XilinxProcessorIPLib/drivers/nandps8_v2_0/src/Makefile new file mode 100755 index 00000000..2aedc0d3 --- /dev/null +++ b/XilinxProcessorIPLib/drivers/nandps8_v2_0/src/Makefile @@ -0,0 +1,83 @@ +#/****************************************************************************** +#* +#* Copyright (C) 2014 Xilinx, Inc. All rights reserved. +#* +#* This file contains confidential and proprietary information of Xilinx, Inc. +#* and is protected under U.S. and international copyright and other +#* intellectual property laws. +#* +#* DISCLAIMER +#* This disclaimer is not a license and does not grant any rights to the +#* materials distributed herewith. Except as otherwise provided in a valid +#* license issued to you by Xilinx, and to the maximum extent permitted by +#* applicable law: (1) THESE MATERIALS ARE MADE AVAILABLE "AS IS" AND WITH ALL +#* FAULTS, AND XILINX HEREBY DISCLAIMS ALL WARRANTIES AND CONDITIONS, EXPRESS, +#* IMPLIED, OR STATUTORY, INCLUDING BUT NOT LIMITED TO WARRANTIES OF +#* MERCHANTABILITY, NON- INFRINGEMENT, OR FITNESS FOR ANY PARTICULAR PURPOSE; +#* and +#* (2) Xilinx shall not be liable (whether in contract or tort, including +#* negligence, or under any other theory of liability) for any loss or damage +#* of any kind or nature related to, arising under or in connection with these +#* materials, including for any direct, or any indirect, special, incidental, +#* or consequential loss or damage (including loss of data, profits, +#* goodwill, or any type of loss or damage suffered as a result of any +#* action brought by a third party) even if such damage or loss was +#* reasonably foreseeable or Xilinx had been advised of the possibility +#* of the same. +#* +#* CRITICAL APPLICATIONS +#* Xilinx products are not designed or intended to be fail- safe, or for use +#* in any application requiring fail-safe performance, such as life-support +#* or safety devices or systems, Class III medical devices, nuclear +#* facilities, applications related to the deployment of airbags, or any +#* other applications that could lead to death, personal injury, or severe +#* property or environmental damage (individually and collectively, +#* "Critical Applications"). Customer assumes the sole risk and liability +#* of any use of Xilinx products in Critical Applications, subject only to +#* applicable laws and regulations governing limitations on product liability. +#* +#* THIS COPYRIGHT NOTICE AND DISCLAIMER MUST BE RETAINED AS PART +#* OF THIS FILE AT ALL TIMES. +#* +#******************************************************************************/ + +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 xuartps_libs clean + +%.o: %.c + ${COMPILER} $(CC_FLAGS) $(ECC_FLAGS) $(INCLUDES) -o $@ $< + +banner: + echo "Compiling nandps8" + +xuartps_libs: ${OBJECTS} + $(ARCHIVER) -r ${RELEASEDIR}/${LIB} ${OBJECTS} + +.PHONY: include +include: xuartps_includes + +xuartps_includes: + ${CP} ${INCLUDEFILES} ${INCLUDEDIR} + +clean: + rm -rf ${OBJECTS} diff --git a/XilinxProcessorIPLib/drivers/nandps8_v2_0/src/xnandps8.c b/XilinxProcessorIPLib/drivers/nandps8_v2_0/src/xnandps8.c new file mode 100755 index 00000000..b18b7095 --- /dev/null +++ b/XilinxProcessorIPLib/drivers/nandps8_v2_0/src/xnandps8.c @@ -0,0 +1,4144 @@ +/****************************************************************************** +* +* Copyright (C) 2014 Xilinx, Inc. All rights reserved. +* +* This file contains confidential and proprietary information of Xilinx, Inc. +* and is protected under U.S. and international copyright and other +* intellectual property laws. +* +* DISCLAIMER +* This disclaimer is not a license and does not grant any rights to the +* materials distributed herewith. Except as otherwise provided in a valid +* license issued to you by Xilinx, and to the maximum extent permitted by +* applicable law: (1) THESE MATERIALS ARE MADE AVAILABLE "AS IS" AND WITH ALL +* FAULTS, AND XILINX HEREBY DISCLAIMS ALL WARRANTIES AND CONDITIONS, EXPRESS, +* IMPLIED, OR STATUTORY, INCLUDING BUT NOT LIMITED TO WARRANTIES OF +* MERCHANTABILITY, NON- INFRINGEMENT, OR FITNESS FOR ANY PARTICULAR PURPOSE +* and +* (2) Xilinx shall not be liable (whether in contract or tort, including +* negligence, or under any other theory of liability) for any loss or damage +* of any kind or nature related to, arising under or in connection with these +* materials, including for any direct, or any indirect, special, incidental, +* or consequential loss or damage (including loss of data, profits, +* goodwill, or any type of loss or damage suffered as a result of any +* action brought by a third party) even if such damage or loss was +* reasonably foreseeable or Xilinx had been advised of the possibility +* of the same. +* +* CRITICAL APPLICATIONS +* Xilinx products are not designed or intended to be fail- safe, or for use +* in any application requiring fail-safe performance, such as life-support +* or safety devices or systems, Class III medical devices, nuclear +* facilities, applications related to the deployment of airbags, or any +* other applications that could lead to death, personal injury, or severe +* property or environmental damage (individually and collectively, +* "Critical Applications"). Customer assumes the sole risk and liability +* of any use of Xilinx products in Critical Applications, subject only to +* applicable laws and regulations governing limitations on product liability. +* +* THIS COPYRIGHT NOTICE AND DISCLAIMER MUST BE RETAINED AS PART +* OF THIS FILE AT ALL TIMES. +* +******************************************************************************/ + +/*****************************************************************************/ +/** +* +* @file xnandps8.c +* +* This file contains the implementation of the interface functions for +* XNandPs8 driver. Refer to the header file xnandps8.h for more detailed +* information. +* +* This module supports for NAND flash memory devices that conform to the +* "Open NAND Flash Interface" (ONFI) 3.0 Specification. This modules +* implements basic flash operations like read, write and erase. +* +* @note None +* +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who    Date	   Changes
+* ----- ----   ----------  -----------------------------------------------
+* 1.0   nm     05/06/2014  First release
+* 2.0   sb     11/04/2014  Removed Null checks for Buffer passed
+*			   as parameter to Read API's
+*			   - XNandPs8_Read()
+*			   - XNandPs8_ReadPage
+*			   Modified
+*			   - XNandPs8_SetFeature()
+*			   - XNandPs8_GetFeature()
+*			   and made them public.
+*			   Removed Failure Return for BCF Error check in
+*			   XNandPs8_ReadPage() and added BCH_Error counter
+*			   in the instance pointer structure.
+* 			   Added XNandPs8_Prepare_Cmd API
+*			   Replaced
+*			   - XNandPs8_IntrStsEnable
+*			   - XNandPs8_IntrStsClear
+*			   - XNandPs8_IntrClear
+*			   - XNandPs8_SetProgramReg
+*			   with XNandPs8_WriteReg call
+*			   Modified xnandps8.c file API's with above changes.
+*  			   Corrected the program command for Set Feature API.
+*			   Modified
+*			   - XNandPs8_OnfiReadStatus
+*			   - XNandPs8_GetFeature
+*			   - XNandPs8_SetFeature
+*			   to add support for DDR mode.
+*			   Changed Convention for SLC/MLC
+*			   SLC --> HAMMING
+*			   MLC --> BCH
+*			   SlcMlc --> IsBCH
+*			   Removed extra DMA mode initialization from
+*			   the XNandPs8_CfgInitialize API.
+*			   Modified
+*			   - XNandPs8_SetEccAddrSize
+*			   ECC address now is calculated based upon the
+*			   size of spare area
+* 
+* +******************************************************************************/ + +/***************************** Include Files *********************************/ +#include "xnandps8.h" +#include "xnandps8_bbm.h" +/************************** Constant Definitions *****************************/ + +const static XNandPs8_TimingModeDesc TimingDesc[] = { + /* + * SDR to SDR + */ + {SDR, SDR, SDR0, 0U, 0x00000000U}, + {SDR, SDR, SDR1, 0U, 0x00000001U}, + {SDR, SDR, SDR2, 0U, 0x00000002U}, + {SDR, SDR, SDR3, 0U, 0x00000003U}, + {SDR, SDR, SDR4, 0U, 0x00000004U}, + {SDR, SDR, SDR5, 0U, 0x00000005U}, + /* + * NVDDR to NVDDR + */ + {NVDDR, NVDDR, NVDDR0, NVDDR_CLK_0, 0x00001010U}, + {NVDDR, NVDDR, NVDDR1, NVDDR_CLK_1, 0x00001111U}, + {NVDDR, NVDDR, NVDDR2, NVDDR_CLK_2, 0x00001212U}, + {NVDDR, NVDDR, NVDDR3, NVDDR_CLK_3, 0x00001313U}, + {NVDDR, NVDDR, NVDDR4, NVDDR_CLK_4, 0x00001414U}, + {NVDDR, NVDDR, NVDDR5, NVDDR_CLK_5, 0x00001515U}, + /* + * SDR to NVDDR + */ + {SDR, NVDDR, NVDDR0, NVDDR_CLK_0, 0x00000010U}, + {SDR, NVDDR, NVDDR1, NVDDR_CLK_1, 0x00000011U}, + {SDR, NVDDR, NVDDR2, NVDDR_CLK_2, 0x00000012U}, + {SDR, NVDDR, NVDDR3, NVDDR_CLK_3, 0x00000013U}, + {SDR, NVDDR, NVDDR4, NVDDR_CLK_4, 0x00000014U}, + {SDR, NVDDR, NVDDR5, NVDDR_CLK_5, 0x00000015U}, + /* + * NVDDR to SDR + */ + {NVDDR, SDR, SDR0, SDR_CLK, 0U}, +}; + +const XNandPs8_EccMatrix EccMatrix[] = { + /* + * 512 byte page + */ + {XNANDPS8_PAGE_SIZE_512, 9U, 1U, XNANDPS8_HAMMING, 0x20DU, 0x3U}, + {XNANDPS8_PAGE_SIZE_512, 9U, 4U, XNANDPS8_BCH, 0x209U, 0x7U}, + {XNANDPS8_PAGE_SIZE_512, 9U, 8U, XNANDPS8_BCH, 0x203U, 0xDU}, + /* + * 2K byte page + */ + {XNANDPS8_PAGE_SIZE_2K, 9U, 1U, XNANDPS8_HAMMING, 0x834U, 0xCU}, + {XNANDPS8_PAGE_SIZE_2K, 9U, 4U, XNANDPS8_BCH, 0x826U, 0x1AU}, + {XNANDPS8_PAGE_SIZE_2K, 9U, 8U, XNANDPS8_BCH, 0x80cU, 0x34U}, + {XNANDPS8_PAGE_SIZE_2K, 9U, 12U, XNANDPS8_BCH, 0x822U, 0x4EU}, + {XNANDPS8_PAGE_SIZE_2K, 9U, 16U, XNANDPS8_BCH, 0x808U, 0x68U}, + {XNANDPS8_PAGE_SIZE_2K, 10U, 24U, XNANDPS8_BCH, 0x81cU, 0x54U}, + /* + * 4K byte page + */ + {XNANDPS8_PAGE_SIZE_4K, 9U, 1U, XNANDPS8_HAMMING, 0x1068U, 0x18U}, + {XNANDPS8_PAGE_SIZE_4K, 9U, 4U, XNANDPS8_BCH, 0x104cU, 0x34U}, + {XNANDPS8_PAGE_SIZE_4K, 9U, 8U, XNANDPS8_BCH, 0x1018U, 0x68U}, + {XNANDPS8_PAGE_SIZE_4K, 9U, 12U, XNANDPS8_BCH, 0x1044U, 0x9CU}, + {XNANDPS8_PAGE_SIZE_4K, 9U, 16U, XNANDPS8_BCH, 0x1010U, 0xD0U}, + {XNANDPS8_PAGE_SIZE_4K, 10U, 24U, XNANDPS8_BCH, 0x1038U, 0xA8U}, + /* + * 8K byte page + */ + {XNANDPS8_PAGE_SIZE_8K, 9U, 1U, XNANDPS8_HAMMING, 0x20d0U, 0x30U}, + {XNANDPS8_PAGE_SIZE_8K, 9U, 4U, XNANDPS8_BCH, 0x2098U, 0x68U}, + {XNANDPS8_PAGE_SIZE_8K, 9U, 8U, XNANDPS8_BCH, 0x2030U, 0xD0U}, + {XNANDPS8_PAGE_SIZE_8K, 9U, 12U, XNANDPS8_BCH, 0x2088U, 0x138U}, + {XNANDPS8_PAGE_SIZE_8K, 9U, 16U, XNANDPS8_BCH, 0x2020U, 0x1A0U}, + {XNANDPS8_PAGE_SIZE_8K, 10U, 24U, XNANDPS8_BCH, 0x2070U, 0x150U}, + /* + * 16K byte page + */ + {XNANDPS8_PAGE_SIZE_16K, 9U, 1U, XNANDPS8_HAMMING, 0x4460U, 0x60U}, + {XNANDPS8_PAGE_SIZE_16K, 9U, 4U, XNANDPS8_BCH, 0x43f0U, 0xD0U}, + {XNANDPS8_PAGE_SIZE_16K, 9U, 8U, XNANDPS8_BCH, 0x4320U, 0x1A0U}, + {XNANDPS8_PAGE_SIZE_16K, 9U, 12U, XNANDPS8_BCH, 0x4250U, 0x270U}, + {XNANDPS8_PAGE_SIZE_16K, 9U, 16U, XNANDPS8_BCH, 0x4180U, 0x340U}, + {XNANDPS8_PAGE_SIZE_16K, 10U, 24U, XNANDPS8_BCH, 0x4220U, 0x2A0U} +}; + +/**************************** Type Definitions *******************************/ +static u8 isQemuPlatform = 0U; +/***************** Macros (Inline Functions) Definitions *********************/ + +/************************** Function Prototypes ******************************/ + +static s32 XNandPs8_FlashInit(XNandPs8 *InstancePtr); + +static void XNandPs8_InitGeometry(XNandPs8 *InstancePtr, OnfiParamPage *Param); + +static void XNandPs8_InitFeatures(XNandPs8 *InstancePtr, OnfiParamPage *Param); + +static s32 XNandPs8_PollRegTimeout(XNandPs8 *InstancePtr, u32 RegOffset, + u32 Mask, u32 Timeout); + +static void XNandPs8_SetPktSzCnt(XNandPs8 *InstancePtr, u32 PktSize, + u32 PktCount); + +static void XNandPs8_SetPageColAddr(XNandPs8 *InstancePtr, u32 Page, u16 Col); + +static void XNandPs8_SetPageSize(XNandPs8 *InstancePtr); + +static void XNandPs8_SetBusWidth(XNandPs8 *InstancePtr); + +static void XNandPs8_SelectChip(XNandPs8 *InstancePtr, u32 Target); + +static s32 XNandPs8_OnfiReset(XNandPs8 *InstancePtr, u32 Target); + +static s32 XNandPs8_OnfiReadStatus(XNandPs8 *InstancePtr, u32 Target, + u16 *OnfiStatus); + +static s32 XNandPs8_OnfiReadId(XNandPs8 *InstancePtr, u32 Target, u8 IdAddr, + u32 IdLen, u8 *Buf); + +static s32 XNandPs8_OnfiReadParamPage(XNandPs8 *InstancePtr, u32 Target, + u8 *Buf); + +static s32 XNandPs8_ProgramPage(XNandPs8 *InstancePtr, u32 Target, u32 Page, + u32 Col, u8 *Buf); + +static s32 XNandPs8_ReadPage(XNandPs8 *InstancePtr, u32 Target, u32 Page, + u32 Col, u8 *Buf); + +static s32 XNandPs8_CheckOnDie(XNandPs8 *InstancePtr, OnfiParamPage *Param); + +static void XNandPs8_SetEccAddrSize(XNandPs8 *InstancePtr); + +static s32 XNandPs8_ChangeReadColumn(XNandPs8 *InstancePtr, u32 Target, + u32 Col, u32 PktSize, u32 PktCount, + u8 *Buf); + +static s32 XNandPs8_ChangeWriteColumn(XNandPs8 *InstancePtr, u32 Target, + u32 Col, u32 PktSize, u32 PktCount, + u8 *Buf); + +static s32 XNandPs8_InitExtEcc(XNandPs8 *InstancePtr, OnfiExtPrmPage *ExtPrm); + +/*****************************************************************************/ +/** +* +* This function initializes a specific XNandPs8 instance. This function must +* be called prior to using the NAND flash device to read or write any data. +* +* @param InstancePtr is a pointer to the XNandPs8 instance. +* @param ConfigPtr points to XNandPs8 device configuration structure. +* @param EffectiveAddr is the base address of NAND flash controller. +* +* @return +* - XST_SUCCESS if successful. +* - XST_FAILURE if fail. +* +* @note The user needs to first call the XNandPs8_LookupConfig() API +* which returns the Configuration structure pointer which is +* passed as a parameter to the XNandPs8_CfgInitialize() API. +* +******************************************************************************/ +s32 XNandPs8_CfgInitialize(XNandPs8 *InstancePtr, XNandPs8_Config *ConfigPtr, + u32 EffectiveAddr) +{ + s32 Status = XST_FAILURE; + + /* + * Assert the input arguments. + */ + Xil_AssertNonvoid(InstancePtr != NULL); + Xil_AssertNonvoid(ConfigPtr != NULL); + + /* + * Initialize InstancePtr Config structure + */ + InstancePtr->Config.DeviceId = ConfigPtr->DeviceId; + InstancePtr->Config.BaseAddress = EffectiveAddr; + /* + * Operate in Polling Mode + */ + InstancePtr->Mode = POLLING; + /* + * Enable MDMA mode by default + */ + InstancePtr->DmaMode = MDMA; + InstancePtr->IsReady = XIL_COMPONENT_IS_READY; + + /* + * Temporary hack for disabling the ecc on qemu as currently there + * is no support in the utility for writing images with ecc enabled. + */ + #define CSU_VER_REG 0xFFCA0044U + #define CSU_VER_PLATFORM_MASK 0xF000U + #define CSU_VER_PLATFORM_QEMU_VAL 0x3000U + if ((*(u32 *)CSU_VER_REG & CSU_VER_PLATFORM_MASK) == + CSU_VER_PLATFORM_QEMU_VAL) { + isQemuPlatform = 1U; + } + /* + * Initialize the NAND flash targets + */ + Status = XNandPs8_FlashInit(InstancePtr); + if (Status != XST_SUCCESS) { +#ifdef XNANDPS8_DEBUG + xil_printf("%s: Flash init failed\r\n",__func__); +#endif + goto Out; + } + /* + * Set ECC mode + */ + if (InstancePtr->Features.EzNand != 0U) { + InstancePtr->EccMode = EZNAND; + } else if (InstancePtr->Features.OnDie != 0U) { + InstancePtr->EccMode = ONDIE; + } else { + InstancePtr->EccMode = HWECC; + } + + if (isQemuPlatform != 0U) { + InstancePtr->EccMode = NONE; + goto Out; + } + + /* + * Initialize BCH Error counter + */ + InstancePtr->BCH_Error_Status = 0U; + + /* + * Scan for the bad block table(bbt) stored in the flash & load it in + * memory(RAM). If bbt is not found, create bbt by scanning factory + * marked bad blocks and store it in last good blocks of flash. + */ + XNandPs8_InitBbtDesc(InstancePtr); + Status = XNandPs8_ScanBbt(InstancePtr); + if (Status != XST_SUCCESS) { +#ifdef XNANDPS8_DEBUG + xil_printf("%s: BBT scan failed\r\n",__func__); +#endif + goto Out; + } + +Out: + return Status; +} + +/*****************************************************************************/ +/** +* +* This function initializes the NAND flash and gets the geometry information. +* +* @param InstancePtr is a pointer to the XNandPs8 instance. +* +* @return +* - XST_SUCCESS if successful. +* - XST_FAILURE if failed. +* +* @note None +* +******************************************************************************/ +static s32 XNandPs8_FlashInit(XNandPs8 *InstancePtr) +{ + u32 Target; + u8 Id[ONFI_SIG_LEN] = {0U}; + OnfiParamPage Param = {0U}; + s32 Status = XST_FAILURE; + u32 Index; + u32 Crc; + u32 PrmPgOff; + u32 PrmPgLen; + OnfiExtPrmPage ExtParam __attribute__ ((aligned(64))); + + /* + * Assert the input arguments. + */ + Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + + for (Target = 0U; Target < XNANDPS8_MAX_TARGETS; Target++) { + /* + * Reset the Target + */ + Status = XNandPs8_OnfiReset(InstancePtr, Target); + if (Status != XST_SUCCESS) { + goto Out; + } + /* + * Read ONFI ID + */ + Status = XNandPs8_OnfiReadId(InstancePtr, Target, + ONFI_READ_ID_ADDR, + ONFI_SIG_LEN, + (u8 *)&Id[0]); + if (Status != XST_SUCCESS) { + goto Out; + } + + if ((Id[0] == (u8)'O') && (Id[1] == (u8)'N') && + (Id[2] == (u8)'F') && (Id[3] == (u8)'I')) { + /* + * Read Parameter Page + */ + for(Index = 0U; Index < ONFI_MND_PRM_PGS; Index++) { + if (Index == 0U) { + Status = XNandPs8_OnfiReadParamPage( + InstancePtr, Target, + (u8 *)&Param); + } else { + PrmPgOff = Index * ONFI_PRM_PG_LEN; + PrmPgLen = ONFI_PRM_PG_LEN; + + Status = XNandPs8_ChangeReadColumn( + InstancePtr, + Target, + PrmPgOff, + ONFI_PRM_PG_LEN, 1U, + (u8 *) &Param); + } + if (Status != XST_SUCCESS) { + goto Out; + } + /* + * Check CRC + */ + Crc = XNandPs8_OnfiParamPageCrc((u8*)&Param, + 0U, + ONFI_CRC_LEN); + if (Crc != Param.Crc) { +#ifdef XNANDPS8_DEBUG + xil_printf("%s: ONFI parameter page (%d) crc check failed\r\n", + __func__, Index); +#endif + continue; + } else { + break; + } + } + if (Index >= ONFI_MND_PRM_PGS) { + Status = XST_FAILURE; + goto Out; + } + /* + * Fill Geometry for the first target + */ + if (Target == 0U) { + XNandPs8_InitGeometry(InstancePtr, &Param); + XNandPs8_InitFeatures(InstancePtr, &Param); + if ((!InstancePtr->Features.EzNand) != 0U) { + Status =XNandPs8_CheckOnDie( + InstancePtr,&Param); + if (Status != XST_SUCCESS) { + InstancePtr->Features.OnDie = 0U; + } + } + if (isQemuPlatform != 0U) { + InstancePtr->Geometry.NumTargets++; + break; + } + if ((InstancePtr->Geometry.NumBitsECC == 0xFFU) + && + (InstancePtr->Features.ExtPrmPage != 0U)) { + /* + * ONFI 3.1 section 5.7.1.6 & 5.7.1.7 + */ + PrmPgLen = (u32)Param.ExtParamPageLen + * 16U; + PrmPgOff = (u32)((u32)Param.NumOfParamPages * + ONFI_PRM_PG_LEN) + + (Index * (u32)PrmPgLen); + Status = XNandPs8_ChangeReadColumn( + InstancePtr, + Target, + PrmPgOff, + PrmPgLen, 1U, + (u8 *)(void *)&ExtParam); + if (Status != XST_SUCCESS) { + goto Out; + } + /* + * Check CRC + */ + Crc = XNandPs8_OnfiParamPageCrc( + (u8 *)&ExtParam, + 2U, + PrmPgLen); + if (Crc != ExtParam.Crc) { +#ifdef XNANDPS8_DEBUG + xil_printf("%s: ONFI extended parameter page (%d) crc check failed\r\n", + __func__, Index); +#endif + Status = XST_FAILURE; + goto Out; + } + /* + * Initialize Extended ECC info + */ + Status = XNandPs8_InitExtEcc( + InstancePtr, + &ExtParam); + if (Status != XST_SUCCESS) { +#ifdef XNANDPS8_DEBUG + xil_printf("%s: Init extended ecc failed\r\n",__func__); +#endif + goto Out; + } + } + /* + * Configure ECC settings + */ + XNandPs8_SetEccAddrSize(InstancePtr); + } + InstancePtr->Geometry.NumTargets++; + } else { + if (Target == 0U) { +#ifdef XNANDPS8_DEBUG + xil_printf("%s: ONFI ID doesn't match\r\n", + __func__); +#endif + Status = XST_FAILURE; + goto Out; + } + } + } + /* + * Calculate total number of blocks and total size of flash + */ + InstancePtr->Geometry.NumPages = InstancePtr->Geometry.NumTargets * + InstancePtr->Geometry.NumTargetPages; + InstancePtr->Geometry.NumBlocks = InstancePtr->Geometry.NumTargets * + InstancePtr->Geometry.NumTargetBlocks; + InstancePtr->Geometry.DeviceSize = + (u64)InstancePtr->Geometry.NumTargets * + InstancePtr->Geometry.TargetSize; + + Status = XST_SUCCESS; +Out: + return Status; +} + +/*****************************************************************************/ +/** +* +* This function initializes the geometry information from ONFI parameter page. +* +* @param InstancePtr is a pointer to the XNandPs8 instance. +* @param Param is pointer to the ONFI parameter page. +* +* @return +* None +* +* @note None +* +******************************************************************************/ +static void XNandPs8_InitGeometry(XNandPs8 *InstancePtr, OnfiParamPage *Param) +{ + /* + * Assert the input arguments. + */ + Xil_AssertVoid(Param != NULL); + + InstancePtr->Geometry.BytesPerPage = Param->BytesPerPage; + InstancePtr->Geometry.SpareBytesPerPage = Param->SpareBytesPerPage; + InstancePtr->Geometry.PagesPerBlock = Param->PagesPerBlock; + InstancePtr->Geometry.BlocksPerLun = Param->BlocksPerLun; + InstancePtr->Geometry.NumLuns = Param->NumLuns; + InstancePtr->Geometry.RowAddrCycles = Param->AddrCycles & 0xFU; + InstancePtr->Geometry.ColAddrCycles = (Param->AddrCycles >> 4U) & 0xFU; + InstancePtr->Geometry.NumBitsPerCell = Param->BitsPerCell; + InstancePtr->Geometry.NumBitsECC = Param->EccBits; + InstancePtr->Geometry.BlockSize = (Param->PagesPerBlock * + Param->BytesPerPage); + InstancePtr->Geometry.NumTargetBlocks = (Param->BlocksPerLun * + (u32)Param->NumLuns); + InstancePtr->Geometry.NumTargetPages = (Param->BlocksPerLun * + (u32)Param->NumLuns * + Param->PagesPerBlock); + InstancePtr->Geometry.TargetSize = ((u64)Param->BlocksPerLun * + (u64)Param->NumLuns * + (u64)Param->PagesPerBlock * + (u64)Param->BytesPerPage); + InstancePtr->Geometry.EccCodeWordSize = 9U; /* 2 power of 9 = 512 */ + +#ifdef XNANDPS8_DEBUG + xil_printf("Manufacturer: %s\r\n", Param->DeviceManufacturer); + xil_printf("Device Model: %s\r\n", Param->DeviceModel); + xil_printf("Jedec ID: 0x%x\r\n", Param->JedecManufacturerId); + xil_printf("Bytes Per Page: 0x%x\r\n", Param->BytesPerPage); + xil_printf("Spare Bytes Per Page: 0x%x\r\n", Param->SpareBytesPerPage); + xil_printf("Pages Per Block: 0x%x\r\n", Param->PagesPerBlock); + xil_printf("Blocks Per LUN: 0x%x\r\n", Param->BlocksPerLun); + xil_printf("Number of LUNs: 0x%x\r\n", Param->NumLuns); + xil_printf("Number of bits per cell: 0x%x\r\n", Param->BitsPerCell); + xil_printf("Number of ECC bits: 0x%x\r\n", Param->EccBits); + xil_printf("Block Size: 0x%x\r\n", InstancePtr->Geometry.BlockSize); + + xil_printf("Number of Target Blocks: 0x%x\r\n", + InstancePtr->Geometry.NumTargetBlocks); + xil_printf("Number of Target Pages: 0x%x\r\n", + InstancePtr->Geometry.NumTargetPages); + +#endif +} + +/*****************************************************************************/ +/** +* +* This function initializes the feature list from ONFI parameter page. +* +* @param InstancePtr is a pointer to the XNandPs8 instance. +* @param Param is pointer to ONFI parameter page buffer. +* +* @return +* None +* +* @note None +* +******************************************************************************/ +static void XNandPs8_InitFeatures(XNandPs8 *InstancePtr, OnfiParamPage *Param) +{ + /* + * Assert the input arguments. + */ + Xil_AssertVoid(Param != NULL); + + InstancePtr->Features.BusWidth = ((Param->Features & (1U << 0U)) != 0U) ? + XNANDPS8_BUS_WIDTH_16 : + XNANDPS8_BUS_WIDTH_8; + InstancePtr->Features.NvDdr = ((Param->Features & (1U << 5)) != 0U) ? + 1U : 0U; + InstancePtr->Features.EzNand = ((Param->Features & (1U << 9)) != 0U) ? + 1U : 0U; + InstancePtr->Features.ExtPrmPage = ((Param->Features & (1U << 7)) != 0U) ? + 1U : 0U; +} + +/*****************************************************************************/ +/** +* +* This function checks if the flash supports on-die ECC. +* +* @param InstancePtr is a pointer to the XNandPs8 instance. +* @param Param is pointer to ONFI parameter page. +* +* @return +* None +* +* @note None +* +******************************************************************************/ +static s32 XNandPs8_CheckOnDie(XNandPs8 *InstancePtr, OnfiParamPage *Param) +{ + s32 Status = XST_FAILURE; + u8 JedecId[2] = {0U}; + u8 EccSetFeature[4] = {0x08U, 0x00U, 0x00U, 0x00U}; + u8 EccGetFeature[4] ={0U}; + + /* + * Assert the input arguments. + */ + Xil_AssertNonvoid(Param != NULL); + + /* + * Check if this flash supports On-Die ECC. + * For more information, refer to Micron TN2945. + * Micron Flash: MT29F1G08ABADA, MT29F1G08ABBDA + * MT29F1G16ABBDA, + * MT29F2G08ABBEA, MT29F2G16ABBEA, + * MT29F2G08ABAEA, MT29F2G16ABAEA, + * MT29F4G08ABBDA, MT29F4G16ABBDA, + * MT29F4G08ABADA, MT29F4G16ABADA, + * MT29F8G08ADBDA, MT29F8G16ADBDA, + * MT29F8G08ADADA, MT29F8G16ADADA + */ + + /* + * Read JEDEC ID + */ + Status = XNandPs8_OnfiReadId(InstancePtr, 0U, 0x00U, 2U, &JedecId[0]); + if (Status != XST_SUCCESS) { + goto Out; + } + + if ((JedecId[0] == 0x2CU) && + /* + * 1 Gb flash devices + */ + ((JedecId[1] == 0xF1U) || + (JedecId[1] == 0xA1U) || + (JedecId[1] == 0xB1U) || + /* + * 2 Gb flash devices + */ + (JedecId[1] == 0xAAU) || + (JedecId[1] == 0xBAU) || + (JedecId[1] == 0xDAU) || + (JedecId[1] == 0xCAU) || + /* + * 4 Gb flash devices + */ + (JedecId[1] == 0xACU) || + (JedecId[1] == 0xBCU) || + (JedecId[1] == 0xDCU) || + (JedecId[1] == 0xCCU) || + /* + * 8 Gb flash devices + */ + (JedecId[1] == 0xA3U) || + (JedecId[1] == 0xB3U) || + (JedecId[1] == 0xD3U) || + (JedecId[1] == 0xC3U))) { +#ifdef XNANDPS8_DEBUG + xil_printf("%s: Ondie flash detected, jedec id 0x%x 0x%x\r\n", + __func__, JedecId[0], JedecId[1]); +#endif + /* + * On-Die Set Feature + */ + Status = XNandPs8_SetFeature(InstancePtr, 0U, 0x90U, + &EccSetFeature[0]); + if (Status != XST_SUCCESS) { +#ifdef XNANDPS8_DEBUG + xil_printf("%s: Ondie set_feature failed\r\n", + __func__); +#endif + goto Out; + } + /* + * Check to see if ECC feature is set + */ + Status = XNandPs8_GetFeature(InstancePtr, 0U, 0x90U, + &EccGetFeature[0]); + if (Status != XST_SUCCESS) { +#ifdef XNANDPS8_DEBUG + xil_printf("%s: Ondie get_feature failed\r\n", + __func__); +#endif + goto Out; + } + if ((EccGetFeature[0] & 0x08U) != 0U) { + InstancePtr->Features.OnDie = 1U; + Status = XST_SUCCESS; + } + } else { + /* + * On-Die flash not found + */ + Status = XST_FAILURE; + } +Out: + return Status; +} + +/*****************************************************************************/ +/** +* +* This function enables DMA mode of controller operation. +* +* @param InstancePtr is a pointer to the XNandPs8 instance. +* +* @return +* None +* +* @note None +* +******************************************************************************/ +void XNandPs8_EnableDmaMode(XNandPs8 *InstancePtr) +{ + /* + * Assert the input arguments. + */ + Xil_AssertVoid(InstancePtr != NULL); + Xil_AssertVoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + + InstancePtr->DmaMode = MDMA; +} + +/*****************************************************************************/ +/** +* +* This function disables DMA mode of driver/controller operation. +* +* @param InstancePtr is a pointer to the XNandPs8 instance. +* +* @return +* None +* +* @note None +* +******************************************************************************/ +void XNandPs8_DisableDmaMode(XNandPs8 *InstancePtr) +{ + /* + * Assert the input arguments. + */ + Xil_AssertVoid(InstancePtr != NULL); + Xil_AssertVoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + + InstancePtr->DmaMode = PIO; +} + +/*****************************************************************************/ +/** +* +* This function enables ECC mode of driver/controller operation. +* +* @param InstancePtr is a pointer to the XNandPs8 instance. +* +* @return +* None +* +* @note None +* +******************************************************************************/ +void XNandPs8_EnableEccMode(XNandPs8 *InstancePtr) +{ + /* + * Assert the input arguments. + */ + Xil_AssertVoid(InstancePtr != NULL); + Xil_AssertVoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + + InstancePtr->EccMode = HWECC; +} + +/*****************************************************************************/ +/** +* +* This function disables ECC mode of driver/controller operation. +* +* @param InstancePtr is a pointer to the XNandPs8 instance. +* +* @return +* None +* +* @note None +* +******************************************************************************/ +void XNandPs8_DisableEccMode(XNandPs8 *InstancePtr) +{ + /* + * Assert the input arguments. + */ + Xil_AssertVoid(InstancePtr != NULL); + Xil_AssertVoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + + InstancePtr->EccMode = NONE; +} + +/*****************************************************************************/ +/** +* +* This function polls for a register bit set status till the timeout. +* +* @param InstancePtr is a pointer to the XNandPs8 instance. +* @param RegOffset is the offset of register. +* @param Mask is the bitmask. +* @param Timeout is the timeout value. +* +* @return +* - XST_SUCCESS if successful. +* - XST_FAILURE if failed. +* +* @note None +* +******************************************************************************/ +static s32 XNandPs8_PollRegTimeout(XNandPs8 *InstancePtr, u32 RegOffset, + u32 Mask, u32 Timeout) +{ + s32 Status = XST_FAILURE; + volatile u32 RegVal; + u32 TimeoutVar = Timeout; + + while (TimeoutVar > 0U) { + RegVal = XNandPs8_ReadReg(InstancePtr->Config.BaseAddress, + RegOffset); + if ((RegVal & Mask) != 0U) { + break; + } + TimeoutVar--; + } + + if (TimeoutVar <= 0U) { + Status = XST_FAILURE; + } else { + Status = XST_SUCCESS; + } + + return Status; +} + +/*****************************************************************************/ +/** +* +* This function sets packet size and packet count values in packet register. +* +* @param InstancePtr is a pointer to the XNandPs8 instance. +* @param PktSize is the packet size. +* @param PktCount is the packet count. +* +* @return +* None +* +* @note None +* +******************************************************************************/ +static void XNandPs8_SetPktSzCnt(XNandPs8 *InstancePtr, u32 PktSize, + u32 PktCount) +{ + /* + * Assert the input arguments. + */ + Xil_AssertVoid(PktSize <= XNANDPS8_MAX_PKT_SIZE); + Xil_AssertVoid(PktCount <= XNANDPS8_MAX_PKT_COUNT); + + /* + * Update Packet Register with pkt size and count + */ + XNandPs8_ReadModifyWrite(InstancePtr, XNANDPS8_PKT_OFFSET, + ((u32)XNANDPS8_PKT_PKT_SIZE_MASK | + (u32)XNANDPS8_PKT_PKT_CNT_MASK), + ((PktSize & XNANDPS8_PKT_PKT_SIZE_MASK) | + ((PktCount << XNANDPS8_PKT_PKT_CNT_SHIFT) & + XNANDPS8_PKT_PKT_CNT_MASK))); +} + +/*****************************************************************************/ +/** +* +* This function sets Page and Column values in the Memory address registers. +* +* @param InstancePtr is a pointer to the XNandPs8 instance. +* @param Page is the page value. +* @param Col is the column value. +* +* @return +* None +* +* @note None +* +******************************************************************************/ +static void XNandPs8_SetPageColAddr(XNandPs8 *InstancePtr, u32 Page, u16 Col) +{ + /* + * Program Memory Address Register 1 + */ + XNandPs8_WriteReg(InstancePtr->Config.BaseAddress, + XNANDPS8_MEM_ADDR1_OFFSET, + ((Col & XNANDPS8_MEM_ADDR1_COL_ADDR_MASK) | + ((Page << (u32)XNANDPS8_MEM_ADDR1_PG_ADDR_SHIFT) & + XNANDPS8_MEM_ADDR1_PG_ADDR_MASK))); + /* + * Program Memory Address Register 2 + */ + XNandPs8_ReadModifyWrite(InstancePtr, XNANDPS8_MEM_ADDR2_OFFSET, + XNANDPS8_MEM_ADDR2_MEM_ADDR_MASK, + ((Page >> XNANDPS8_MEM_ADDR1_PG_ADDR_SHIFT) & + XNANDPS8_MEM_ADDR2_MEM_ADDR_MASK)); +} + +/*****************************************************************************/ +/** +* +* This function sets the size of page in Command Register. +* +* @param InstancePtr is a pointer to the XNandPs8 instance. +* +* @return +* None +* +* @note None +* +******************************************************************************/ +static void XNandPs8_SetPageSize(XNandPs8 *InstancePtr) +{ + u32 PageSizeMask = 0; + u32 PageSize = InstancePtr->Geometry.BytesPerPage; + + /* + * Calculate page size mask + */ + switch(PageSize) { + case XNANDPS8_PAGE_SIZE_512: + PageSizeMask = (0U << XNANDPS8_CMD_PG_SIZE_SHIFT); + break; + case XNANDPS8_PAGE_SIZE_2K: + PageSizeMask = (1U << XNANDPS8_CMD_PG_SIZE_SHIFT); + break; + case XNANDPS8_PAGE_SIZE_4K: + PageSizeMask = (2U << XNANDPS8_CMD_PG_SIZE_SHIFT); + break; + case XNANDPS8_PAGE_SIZE_8K: + PageSizeMask = (3U << XNANDPS8_CMD_PG_SIZE_SHIFT); + break; + case XNANDPS8_PAGE_SIZE_16K: + PageSizeMask = (4U << XNANDPS8_CMD_PG_SIZE_SHIFT); + break; + case XNANDPS8_PAGE_SIZE_1K_16BIT: + PageSizeMask = (5U << XNANDPS8_CMD_PG_SIZE_SHIFT); + break; + default: + /* + * Not supported + */ + break; + } + /* + * Update Command Register + */ + XNandPs8_ReadModifyWrite(InstancePtr, XNANDPS8_CMD_OFFSET, + XNANDPS8_CMD_PG_SIZE_MASK, PageSizeMask); +} + +/*****************************************************************************/ +/** +* +* This function setup the Ecc Register. +* +* @param InstancePtr is a pointer to the XNandPs8 instance. +* +* @return +* None +* +* @note None +* +******************************************************************************/ +static void XNandPs8_SetEccAddrSize(XNandPs8 *InstancePtr) +{ + u32 PageSize = InstancePtr->Geometry.BytesPerPage; + u32 CodeWordSize = InstancePtr->Geometry.EccCodeWordSize; + u32 NumEccBits = InstancePtr->Geometry.NumBitsECC; + u32 Index; + u32 Found = 0U; + u8 BchModeVal = 0U; + + for (Index = 0U; Index < (sizeof(EccMatrix)/sizeof(XNandPs8_EccMatrix)); + Index++) { + if ((EccMatrix[Index].PageSize == PageSize) && + (EccMatrix[Index].CodeWordSize >= CodeWordSize)) { + if (EccMatrix[Index].NumEccBits >= NumEccBits) { + Found = Index; + break; + } + else { + Found = Index; + } + } + } + + if (Found != 0U) { +#ifdef XNANDPS8_DEBUG + xil_printf("ECC: addr 0x%x size 0x%x numbits %d codesz %d\r\n", + PageSize + (InstancePtr->Geometry.SpareBytesPerPage + - EccMatrix[Found].EccSize), + EccMatrix[Found].EccSize, + EccMatrix[Found].NumEccBits, + EccMatrix[Found].CodeWordSize); +#endif + InstancePtr->EccCfg.EccAddr = PageSize + + (InstancePtr->Geometry.SpareBytesPerPage + - EccMatrix[Found].EccSize); + InstancePtr->EccCfg.EccSize = EccMatrix[Found].EccSize; + InstancePtr->EccCfg.NumEccBits = EccMatrix[Found].NumEccBits; + InstancePtr->EccCfg.CodeWordSize = + EccMatrix[Found].CodeWordSize; + + if (EccMatrix[Found].IsBCH == XNANDPS8_HAMMING) { + InstancePtr->EccCfg.IsBCH = 0U; + } else { + InstancePtr->EccCfg.IsBCH = 1U; + } + /* + * Write ECC register + */ + XNandPs8_WriteReg(InstancePtr->Config.BaseAddress, + (u32)XNANDPS8_ECC_OFFSET, + ((u32)InstancePtr->EccCfg.EccAddr | + ((u32)InstancePtr->EccCfg.EccSize << (u32)16) | + ((u32)InstancePtr->EccCfg.IsBCH << (u32)27))); + + if (EccMatrix[Found].IsBCH == XNANDPS8_BCH) { + /* + * Write memory address register 2 + */ + switch(InstancePtr->EccCfg.NumEccBits) { + case 16U: + BchModeVal = 0x0U; + break; + case 12U: + BchModeVal = 0x1U; + break; + case 8U: + BchModeVal = 0x2U; + break; + case 4U: + BchModeVal = 0x3U; + break; + case 24U: + BchModeVal = 0x4U; + break; + default: + BchModeVal = 0x0U; + } + XNandPs8_ReadModifyWrite(InstancePtr, + XNANDPS8_MEM_ADDR2_OFFSET, + XNANDPS8_MEM_ADDR2_NFC_BCH_MODE_MASK, + (BchModeVal << + (u32)XNANDPS8_MEM_ADDR2_NFC_BCH_MODE_SHIFT)); + } + } +} + +/*****************************************************************************/ +/** +* +* This function setup the Ecc Spare Command Register. +* +* @param InstancePtr is a pointer to the XNandPs8 instance. +* +* @return +* None +* +* @note None +* +******************************************************************************/ +static void XNandPs8_SetEccSpareCmd(XNandPs8 *InstancePtr, u16 SpareCmd, + u8 AddrCycles) +{ + XNandPs8_WriteReg(InstancePtr->Config.BaseAddress, + (u32)XNANDPS8_ECC_SPR_CMD_OFFSET, + (u32)SpareCmd | ((u32)AddrCycles << 28U)); +} + +/*****************************************************************************/ +/** +* +* This function sets the flash bus width in memory address2 register. +* +* @param InstancePtr is a pointer to the XNandPs8 instance. +* +* @return +* None +* +* @note None +* +******************************************************************************/ +static void XNandPs8_SetBusWidth(XNandPs8 *InstancePtr) +{ + /* + * Update Memory Address2 register with bus width + */ + XNandPs8_ReadModifyWrite(InstancePtr, XNANDPS8_MEM_ADDR2_OFFSET, + XNANDPS8_MEM_ADDR2_BUS_WIDTH_MASK, + (InstancePtr->Features.BusWidth << + XNANDPS8_MEM_ADDR2_BUS_WIDTH_SHIFT)); + +} + +/*****************************************************************************/ +/** +* +* This function sets the chip select value in memory address2 register. +* +* @param InstancePtr is a pointer to the XNandPs8 instance. +* @param Target is the chip select value. +* +* @return +* None +* +* @note None +* +******************************************************************************/ +static void XNandPs8_SelectChip(XNandPs8 *InstancePtr, u32 Target) +{ + /* + * Update Memory Address2 register with chip select + */ + XNandPs8_ReadModifyWrite(InstancePtr, XNANDPS8_MEM_ADDR2_OFFSET, + XNANDPS8_MEM_ADDR2_CHIP_SEL_MASK, + ((Target << XNANDPS8_MEM_ADDR2_CHIP_SEL_SHIFT) & + XNANDPS8_MEM_ADDR2_CHIP_SEL_MASK)); +} + +/*****************************************************************************/ +/** +* +* This function sends ONFI Reset command to the flash. +* +* @param InstancePtr is a pointer to the XNandPs8 instance. +* @param Target is the chip select value. +* +* @return +* - XST_SUCCESS if successful. +* - XST_FAILURE if failed. +* +* @note None +* +******************************************************************************/ +static s32 XNandPs8_OnfiReset(XNandPs8 *InstancePtr, u32 Target) +{ + s32 Status = XST_FAILURE; + + /* + * Assert the input arguments. + */ + Xil_AssertNonvoid(Target < XNANDPS8_MAX_TARGETS); + + /* + * Enable Transfer Complete Interrupt in Interrupt Status Register + */ + XNandPs8_WriteReg((InstancePtr)->Config.BaseAddress, + XNANDPS8_INTR_STS_EN_OFFSET, + XNANDPS8_INTR_STS_EN_TRANS_COMP_STS_EN_MASK); + /* + * Program Command Register + */ + XNandPs8_Prepare_Cmd(InstancePtr, ONFI_CMD_RST, ONFI_CMD_INVALID, 0U, + 0U, 0U); + /* + * Program Memory Address Register2 for chip select + */ + XNandPs8_SelectChip(InstancePtr, Target); + /* + * Set Reset in Program Register + */ + XNandPs8_WriteReg((InstancePtr)->Config.BaseAddress, + XNANDPS8_PROG_OFFSET, XNANDPS8_PROG_RST_MASK); + + /* + * Poll for Transfer Complete event + */ + Status = XNandPs8_PollRegTimeout( + InstancePtr, + XNANDPS8_INTR_STS_OFFSET, + XNANDPS8_INTR_STS_TRANS_COMP_STS_EN_MASK, + XNANDPS8_INTR_POLL_TIMEOUT); + if (Status != XST_SUCCESS) { +#ifdef XNANDPS8_DEBUG + xil_printf("%s: Poll for xfer complete timeout\r\n", + __func__); +#endif + goto Out; + } + /* + * Clear Transfer Complete Interrupt in Interrupt Status Enable + * Register + */ + XNandPs8_WriteReg((InstancePtr)->Config.BaseAddress, + (XNANDPS8_INTR_STS_EN_OFFSET), 0U); + /* + * Clear Transfer Complete Interrupt in Interrupt Status Register + */ + XNandPs8_WriteReg((InstancePtr)->Config.BaseAddress, + XNANDPS8_INTR_STS_OFFSET, + XNANDPS8_INTR_STS_TRANS_COMP_STS_EN_MASK); + +Out: + return Status; +} + +/*****************************************************************************/ +/** +* +* This function sends ONFI Read Status command to the flash. +* +* @param InstancePtr is a pointer to the XNandPs8 instance. +* @param Target is the chip select value. +* @param OnfiStatus is the ONFI status value to return. +* +* @return +* - XST_SUCCESS if successful. +* - XST_FAILURE if failed. +* +* @note None +* +******************************************************************************/ +static s32 XNandPs8_OnfiReadStatus(XNandPs8 *InstancePtr, u32 Target, + u16 *OnfiStatus) +{ + s32 Status = XST_FAILURE; + + /* + * Assert the input arguments. + */ + Xil_AssertNonvoid(Target < XNANDPS8_MAX_TARGETS); + Xil_AssertNonvoid(OnfiStatus != NULL); + /* + * Enable Transfer Complete Interrupt in Interrupt Status Register + */ + XNandPs8_WriteReg((InstancePtr)->Config.BaseAddress, + XNANDPS8_INTR_STS_EN_OFFSET, + XNANDPS8_INTR_STS_EN_TRANS_COMP_STS_EN_MASK); + /* + * Program Command Register + */ + XNandPs8_Prepare_Cmd(InstancePtr, ONFI_CMD_RD_STS, ONFI_CMD_INVALID, + 0U, 0U, 0U); + /* + * Program Memory Address Register2 for chip select + */ + XNandPs8_SelectChip(InstancePtr, Target); + /* + * Program Packet Size and Packet Count + */ + if(InstancePtr->DataInterface == SDR){ + XNandPs8_SetPktSzCnt(InstancePtr, 1U, 1U); + } + else{ + XNandPs8_SetPktSzCnt(InstancePtr, 2U, 1U); + } + + /* + * Set Read Status in Program Register + */ + XNandPs8_WriteReg((InstancePtr)->Config.BaseAddress, + XNANDPS8_PROG_OFFSET,XNANDPS8_PROG_RD_STS_MASK); + /* + * Poll for Transfer Complete event + */ + Status = XNandPs8_PollRegTimeout( + InstancePtr, + XNANDPS8_INTR_STS_OFFSET, + XNANDPS8_INTR_STS_TRANS_COMP_STS_EN_MASK, + XNANDPS8_INTR_POLL_TIMEOUT); + if (Status != XST_SUCCESS) { +#ifdef XNANDPS8_DEBUG + xil_printf("%s: Poll for xfer complete timeout\r\n", + __func__); +#endif + goto Out; + } + /* + * Clear Transfer Complete Interrupt in Interrupt Status Enable + * Register + */ + XNandPs8_WriteReg((InstancePtr)->Config.BaseAddress, + XNANDPS8_INTR_STS_EN_OFFSET, 0U); + /* + * Clear Transfer Complete Interrupt in Interrupt Status Register + */ + XNandPs8_WriteReg((InstancePtr)->Config.BaseAddress, + XNANDPS8_INTR_STS_OFFSET, + XNANDPS8_INTR_STS_TRANS_COMP_STS_EN_MASK); + /* + * Read Flash Status + */ + *OnfiStatus = (u8) XNandPs8_ReadReg(InstancePtr->Config.BaseAddress, + XNANDPS8_FLASH_STS_OFFSET); + +Out: + + return Status; +} + +/*****************************************************************************/ +/** +* +* This function sends ONFI Read ID command to the flash. +* +* @param InstancePtr is a pointer to the XNandPs8 instance. +* @param Target is the chip select value. +* @param Buf is the ONFI ID value to return. +* +* @return +* - XST_SUCCESS if successful. +* - XST_FAILURE if failed. +* +* @note None +* +******************************************************************************/ +static s32 XNandPs8_OnfiReadId(XNandPs8 *InstancePtr, u32 Target, u8 IdAddr, + u32 IdLen, u8 *Buf) +{ + s32 Status = XST_FAILURE; + u32 Index; + u32 Rem; + u32 *BufPtr = (u32 *)(void *)Buf; + u32 RegVal; + u32 RemIdx; + + /* + * Assert the input arguments. + */ + Xil_AssertNonvoid(Target < XNANDPS8_MAX_TARGETS); + Xil_AssertNonvoid(Buf != NULL); + + /* + * Enable Buffer Read Ready Interrupt in Interrupt Status Enable + * Register + */ + XNandPs8_WriteReg((InstancePtr)->Config.BaseAddress, + XNANDPS8_INTR_STS_EN_OFFSET, + XNANDPS8_INTR_STS_EN_BUFF_RD_RDY_STS_EN_MASK); + /* + * Program Command + */ + XNandPs8_Prepare_Cmd(InstancePtr, ONFI_CMD_RD_ID, ONFI_CMD_INVALID, 0U, + 0U, ONFI_READ_ID_ADDR_CYCLES); + + /* + * Program Column, Page, Block address + */ + XNandPs8_SetPageColAddr(InstancePtr, 0U, IdAddr); + /* + * Program Memory Address Register2 for chip select + */ + XNandPs8_SelectChip(InstancePtr, Target); + /* + * Program Packet Size and Packet Count + */ + XNandPs8_SetPktSzCnt(InstancePtr, IdLen, 1U); + /* + * Set Read ID in Program Register + */ + XNandPs8_WriteReg((InstancePtr)->Config.BaseAddress, + XNANDPS8_PROG_OFFSET,XNANDPS8_PROG_RD_ID_MASK); + + /* + * Poll for Buffer Read Ready event + */ + Status = XNandPs8_PollRegTimeout( + InstancePtr, + XNANDPS8_INTR_STS_OFFSET, + XNANDPS8_INTR_STS_BUFF_RD_RDY_STS_EN_MASK, + XNANDPS8_INTR_POLL_TIMEOUT); + if (Status != XST_SUCCESS) { +#ifdef XNANDPS8_DEBUG + xil_printf("%s: Poll for buf read ready timeout\r\n", + __func__); +#endif + goto Out; + } + /* + * Enable Transfer Complete Interrupt in Interrupt + * Status Enable Register + */ + + XNandPs8_WriteReg((InstancePtr)->Config.BaseAddress, + XNANDPS8_INTR_STS_EN_OFFSET, + XNANDPS8_INTR_STS_EN_TRANS_COMP_STS_EN_MASK); + + /* + * Clear Buffer Read Ready Interrupt in Interrupt Status + * Register + */ + XNandPs8_WriteReg((InstancePtr)->Config.BaseAddress, + XNANDPS8_INTR_STS_OFFSET, + XNANDPS8_INTR_STS_BUFF_RD_RDY_STS_EN_MASK); + /* + * Read Packet Data from Data Port Register + */ + for (Index = 0U; Index < (IdLen/4); Index++) { + BufPtr[Index] = XNandPs8_ReadReg( + InstancePtr->Config.BaseAddress, + XNANDPS8_BUF_DATA_PORT_OFFSET); + } + Rem = IdLen % 4; + if (Rem != 0U) { + RegVal = XNandPs8_ReadReg( + InstancePtr->Config.BaseAddress, + XNANDPS8_BUF_DATA_PORT_OFFSET); + for (RemIdx = 0U; RemIdx < Rem; RemIdx++) { + Buf[(Index * 4U) + RemIdx] = (u8) (RegVal >> + (RemIdx * 8U)) & 0xFFU; + } + } + + /* + * Poll for Transfer Complete event + */ + Status = XNandPs8_PollRegTimeout( + InstancePtr, + XNANDPS8_INTR_STS_OFFSET, + XNANDPS8_INTR_STS_TRANS_COMP_STS_EN_MASK, + XNANDPS8_INTR_POLL_TIMEOUT); + if (Status != XST_SUCCESS) { +#ifdef XNANDPS8_DEBUG + xil_printf("%s: Poll for xfer complete timeout\r\n", + __func__); +#endif + goto Out; + } + /* + * Clear Transfer Complete Interrupt in Interrupt Status Enable + * Register + */ + XNandPs8_WriteReg((InstancePtr)->Config.BaseAddress, + XNANDPS8_INTR_STS_EN_OFFSET,0U); + /* + * Clear Transfer Complete Interrupt in Interrupt Status Register + */ + XNandPs8_WriteReg((InstancePtr)->Config.BaseAddress, + XNANDPS8_INTR_STS_OFFSET, + XNANDPS8_INTR_STS_TRANS_COMP_STS_EN_MASK); + +Out: + return Status; +} + +/*****************************************************************************/ +/** +* +* This function sends the ONFI Read Parameter Page command to flash. +* +* @param InstancePtr is a pointer to the XNandPs8 instance. +* @param Target is the chip select value. +* @param PrmIndex is the index of parameter page. +* @param Buf is the parameter page information to return. +* +* @return +* - XST_SUCCESS if successful. +* - XST_FAILURE if failed. +* +* @note None +* +******************************************************************************/ +static s32 XNandPs8_OnfiReadParamPage(XNandPs8 *InstancePtr, u32 Target, + u8 *Buf) +{ + s32 Status = XST_FAILURE; + u32 *BufPtr = (u32 *)(void *)Buf; + u32 Index; + + /* + * Assert the input arguments. + */ + Xil_AssertNonvoid(Target < XNANDPS8_MAX_TARGETS); + Xil_AssertNonvoid(Buf != NULL); + + /* + * Enable Buffer Read Ready Interrupt in Interrupt Status Enable + * Register + */ + XNandPs8_WriteReg((InstancePtr)->Config.BaseAddress, + XNANDPS8_INTR_STS_EN_OFFSET, + XNANDPS8_INTR_STS_EN_BUFF_RD_RDY_STS_EN_MASK); + /* + * Program Command + */ + XNandPs8_Prepare_Cmd(InstancePtr, ONFI_CMD_RD_PRM_PG, ONFI_CMD_INVALID, + 0U, 0U, ONFI_PRM_PG_ADDR_CYCLES); + /* + * Program Column, Page, Block address + */ + XNandPs8_SetPageColAddr(InstancePtr, 0U, 0U); + /* + * Program Memory Address Register2 for chip select + */ + XNandPs8_SelectChip(InstancePtr, Target); + /* + * Program Packet Size and Packet Count + */ + XNandPs8_SetPktSzCnt(InstancePtr, ONFI_PRM_PG_LEN, 1U); + /* + * Set Read Parameter Page in Program Register + */ + XNandPs8_WriteReg((InstancePtr)->Config.BaseAddress, + XNANDPS8_PROG_OFFSET,XNANDPS8_PROG_RD_PRM_PG_MASK); + + /* + * Poll for Buffer Read Ready event + */ + Status = XNandPs8_PollRegTimeout( + InstancePtr, + XNANDPS8_INTR_STS_OFFSET, + XNANDPS8_INTR_STS_BUFF_RD_RDY_STS_EN_MASK, + XNANDPS8_INTR_POLL_TIMEOUT); + if (Status != XST_SUCCESS) { +#ifdef XNANDPS8_DEBUG + xil_printf("%s: Poll for buf read ready timeout\r\n", + __func__); +#endif + goto Out; + } + + + /* + * Enable Transfer Complete Interrupt in Interrupt + * Status Enable Register + */ + XNandPs8_WriteReg((InstancePtr)->Config.BaseAddress, + (XNANDPS8_INTR_STS_EN_OFFSET), + XNANDPS8_INTR_STS_EN_TRANS_COMP_STS_EN_MASK); + /* + * Clear Buffer Read Ready Interrupt in Interrupt Status + * Register + */ + XNandPs8_WriteReg((InstancePtr)->Config.BaseAddress, + XNANDPS8_INTR_STS_OFFSET, + XNANDPS8_INTR_STS_BUFF_RD_RDY_STS_EN_MASK); + /* + * Read Packet Data from Data Port Register + */ + for (Index = 0U; Index < (ONFI_PRM_PG_LEN/4); Index++) { + BufPtr[Index] = XNandPs8_ReadReg( + InstancePtr->Config.BaseAddress, + XNANDPS8_BUF_DATA_PORT_OFFSET); + } + + /* + * Poll for Transfer Complete event + */ + Status = XNandPs8_PollRegTimeout( + InstancePtr, + XNANDPS8_INTR_STS_OFFSET, + XNANDPS8_INTR_STS_TRANS_COMP_STS_EN_MASK, + XNANDPS8_INTR_POLL_TIMEOUT); + if (Status != XST_SUCCESS) { +#ifdef XNANDPS8_DEBUG + xil_printf("%s: Poll for xfer complete timeout\r\n", + __func__); +#endif + goto Out; + } + /* + * Clear Transfer Complete Interrupt in Interrupt Status Enable + * Register + */ + XNandPs8_WriteReg((InstancePtr)->Config.BaseAddress, + XNANDPS8_INTR_STS_EN_OFFSET, 0U); + /* + * Clear Transfer Complete Interrupt in Interrupt Status Register + */ + XNandPs8_WriteReg((InstancePtr)->Config.BaseAddress, + XNANDPS8_INTR_STS_OFFSET, + XNANDPS8_INTR_STS_TRANS_COMP_STS_EN_MASK); + +Out: + return Status; +} + +/*****************************************************************************/ +/** +* +* This function returns the length including bad blocks from a given offset and +* length. +* +* @param InstancePtr is the pointer to the XNandPs8 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. +* +******************************************************************************/ +static s32 XNandPs8_CalculateLength(XNandPs8 *InstancePtr, u64 Offset, + u64 Length) +{ + s32 Status; + u32 BlockSize; + u32 BlockLen; + u32 Block; + u32 TempLen = 0; + u64 OffsetVar = Offset; + + BlockSize = InstancePtr->Geometry.BlockSize; + + while (TempLen < Length) { + Block = (u32) ((u32)OffsetVar/BlockSize); + BlockLen = BlockSize - ((u32)OffsetVar % BlockSize); + /* + * Check if the block is bad + */ + Status = XNandPs8_IsBlockBad(InstancePtr, Block); + if (Status != XST_SUCCESS) { + /* + * Good block + */ + TempLen += BlockLen; + } + if (OffsetVar >= InstancePtr->Geometry.DeviceSize) { + Status = XST_FAILURE; + goto Out; + } + OffsetVar += BlockLen; + } + + Status = XST_SUCCESS; +Out: + return Status; +} + +/*****************************************************************************/ +/** +* +* This function writes to the flash. +* +* @param InstancePtr is a pointer to the XNandPs8 instance. +* @param Offset is the starting offset of flash to write. +* @param Length is the number of bytes to write. +* @param SrcBuf is the source data buffer to write. +* +* @return +* - XST_SUCCESS if successful. +* - XST_FAILURE if failed. +* +* @note None +* +******************************************************************************/ +s32 XNandPs8_Write(XNandPs8 *InstancePtr, u64 Offset, u64 Length, u8 *SrcBuf) +{ + s32 Status = XST_FAILURE; + u32 Page; + u32 Col; + u32 Target; + u32 Block; + u32 PartialBytes = 0; + u32 NumBytes; + u32 RemLen; + u8 *BufPtr; + u8 *Ptr = (u8 *)SrcBuf; + u16 OnfiStatus; + u64 OffsetVar = Offset; + u64 LengthVar = Length; + + /* + * Assert the input arguments. + */ + Xil_AssertNonvoid(InstancePtr != NULL); + Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + Xil_AssertNonvoid(SrcBuf != NULL); + Xil_AssertNonvoid(LengthVar != 0U); + Xil_AssertNonvoid((OffsetVar + LengthVar) < + InstancePtr->Geometry.DeviceSize); + + /* + * Check if write operation exceeds flash size when including + * bad blocks. + */ + Status = XNandPs8_CalculateLength(InstancePtr, OffsetVar, LengthVar); + if (Status != XST_SUCCESS) { + goto Out; + } + + while (LengthVar > 0U) { + Block = (u32) (OffsetVar/InstancePtr->Geometry.BlockSize); + /* + * Skip the bad blocks. Increment the offset by block size. + * For better results, always program the flash starting at + * a block boundary. + */ + if (XNandPs8_IsBlockBad(InstancePtr, Block) == XST_SUCCESS) { + OffsetVar += (u64)InstancePtr->Geometry.BlockSize; + continue; + } + /* + * Calculate Page and Column address values + */ + Page = (u32) (OffsetVar/InstancePtr->Geometry.BytesPerPage); + Col = (u32) (OffsetVar & + (InstancePtr->Geometry.BytesPerPage - 1U)); + PartialBytes = 0U; + /* + * Check if partial write. + * If column address is > 0 or Length is < page size + */ + if ((Col > 0U) || + (LengthVar < InstancePtr->Geometry.BytesPerPage)) { + RemLen = InstancePtr->Geometry.BytesPerPage - Col; + PartialBytes = (RemLen < (u32)LengthVar) ? + RemLen : (u32)LengthVar; + } + + Target = (u32) (OffsetVar/InstancePtr->Geometry.TargetSize); + if (Page > InstancePtr->Geometry.NumTargetPages) { + Page %= InstancePtr->Geometry.NumTargetPages; + } + + /* + * Check if partial write + */ + if (PartialBytes > 0U) { + BufPtr = &InstancePtr->PartialDataBuf[0]; + memset(BufPtr, 0xFF, + InstancePtr->Geometry.BytesPerPage); + memcpy(BufPtr + Col, Ptr, PartialBytes); + + NumBytes = PartialBytes; + } else { + BufPtr = (u8 *)Ptr; + NumBytes = (InstancePtr->Geometry.BytesPerPage < + (u32)LengthVar) ? + InstancePtr->Geometry.BytesPerPage : + (u32)LengthVar; + } + /* + * Program page + */ + Status = XNandPs8_ProgramPage(InstancePtr, Target, Page, 0U, + BufPtr); + if (Status != XST_SUCCESS) { + goto Out; + } + /* + * ONFI ReadStatus + */ + do { + Status = XNandPs8_OnfiReadStatus(InstancePtr, Target, + &OnfiStatus); + if (Status != XST_SUCCESS) { + goto Out; + } + if ((OnfiStatus & (1U << 6U)) != 0U) { + if ((OnfiStatus & (1U << 0U)) != 0U) { + Status = XST_FAILURE; + goto Out; + } + } + } while (((OnfiStatus >> 6U) & 0x1U) == 0U); + + Ptr += NumBytes; + OffsetVar += NumBytes; + LengthVar -= NumBytes; + } + + Status = XST_SUCCESS; +Out: + return Status; +} + +/*****************************************************************************/ +/** +* +* This function reads from the flash. +* +* @param InstancePtr is a pointer to the XNandPs8 instance. +* @param Offset is the starting offset of flash to read. +* @param Length is the number of bytes to read. +* @param DestBuf is the destination data buffer to fill in. +* +* @return +* - XST_SUCCESS if successful. +* - XST_FAILURE if failed. +* +* @note None +* +******************************************************************************/ +s32 XNandPs8_Read(XNandPs8 *InstancePtr, u64 Offset, u64 Length, u8 *DestBuf) +{ + s32 Status = XST_FAILURE; + u32 Page; + u32 Col; + u32 Target; + u32 Block; + u32 PartialBytes = 0U; + u32 RemLen; + u32 NumBytes; + u8 *BufPtr; + u8 *Ptr = (u8 *)DestBuf; + u64 OffsetVar = Offset; + u64 LengthVar = Length; + + /* + * Assert the input arguments. + */ + Xil_AssertNonvoid(InstancePtr != NULL); + Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + Xil_AssertNonvoid(LengthVar != 0U); + Xil_AssertNonvoid((OffsetVar + LengthVar) < + InstancePtr->Geometry.DeviceSize); + + /* + * Check if read operation exceeds flash size when including + * bad blocks. + */ + Status = XNandPs8_CalculateLength(InstancePtr, OffsetVar, LengthVar); + if (Status != XST_SUCCESS) { + goto Out; + } + + while (LengthVar > 0U) { + Block = (u32) (OffsetVar/InstancePtr->Geometry.BlockSize); + /* + * Skip the bad block. Increment the offset by block size. + * The flash programming utility must make sure to start + * writing always at a block boundary and skip blocks if any. + */ + if (XNandPs8_IsBlockBad(InstancePtr, Block) == XST_SUCCESS) { + OffsetVar += (u64)InstancePtr->Geometry.BlockSize; + continue; + } + /* + * Calculate Page and Column address values + */ + Page = (u32) (OffsetVar/InstancePtr->Geometry.BytesPerPage); + Col = (u32) (OffsetVar & + (InstancePtr->Geometry.BytesPerPage - 1U)); + PartialBytes = 0U; + /* + * Check if partial write. + * If column address is > 0 or Length is < page size + */ + if ((Col > 0U) || + (LengthVar < InstancePtr->Geometry.BytesPerPage)) { + RemLen = InstancePtr->Geometry.BytesPerPage - Col; + PartialBytes = ((u32)RemLen < (u32)LengthVar) ? + (u32)RemLen : (u32)LengthVar; + } + + Target = (u32) (OffsetVar/InstancePtr->Geometry.TargetSize); + if (Page > InstancePtr->Geometry.NumTargetPages) { + Page %= InstancePtr->Geometry.NumTargetPages; + } + /* + * Check if partial read + */ + if (PartialBytes > 0U) { + BufPtr = &InstancePtr->PartialDataBuf[0]; + NumBytes = PartialBytes; + } else { + BufPtr = Ptr; + NumBytes = (InstancePtr->Geometry.BytesPerPage < + (u32)LengthVar) ? + InstancePtr->Geometry.BytesPerPage : + (u32)LengthVar; + } + /* + * Read page + */ + Xil_AssertNonvoid(BufPtr != NULL); + Status = XNandPs8_ReadPage(InstancePtr, Target, Page, 0U, + BufPtr); + if (Status != XST_SUCCESS) { + goto Out; + } + if (PartialBytes > 0U) { + memcpy(Ptr, BufPtr + Col, NumBytes); + } + Ptr += NumBytes; + OffsetVar += NumBytes; + LengthVar -= NumBytes; + } + + Status = XST_SUCCESS; +Out: + return Status; +} + +/*****************************************************************************/ +/** +* +* This function erases the flash. +* +* @param InstancePtr is a pointer to the XNandPs8 instance. +* @param Offset is the starting offset of flash to erase. +* @param Length is the number of bytes to erase. +* +* @return +* - XST_SUCCESS if successful. +* - XST_FAILURE if failed. +* +* @note +* The Offset and Length should be aligned to block size boundary +* to get better results. +* +******************************************************************************/ +s32 XNandPs8_Erase(XNandPs8 *InstancePtr, u64 Offset, u64 Length) +{ + s32 Status = XST_FAILURE; + u32 Target = 0; + u32 StartBlock; + u32 NumBlocks = 0; + u32 Block; + u32 AlignOff; + u32 EraseLen; + u32 BlockRemLen; + u16 OnfiStatus; + u64 OffsetVar = Offset; + u64 LengthVar = Length; + + /* + * Assert the input arguments. + */ + Xil_AssertNonvoid(InstancePtr != NULL); + Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + Xil_AssertNonvoid(LengthVar != 0U); + Xil_AssertNonvoid((OffsetVar + LengthVar) < + InstancePtr->Geometry.DeviceSize); + + /* + * Check if erase operation exceeds flash size when including + * bad blocks. + */ + Status = XNandPs8_CalculateLength(InstancePtr, OffsetVar, LengthVar); + if (Status != XST_SUCCESS) { + goto Out; + } + /* + * Calculate number of blocks to erase + */ + StartBlock = (u32) (OffsetVar/InstancePtr->Geometry.BlockSize); + + while (LengthVar > 0U) { + Block = (u32) (OffsetVar/InstancePtr->Geometry.BlockSize); + if (XNandPs8_IsBlockBad(InstancePtr, Block) == + XST_SUCCESS) { + OffsetVar += (u64)InstancePtr->Geometry.BlockSize; + NumBlocks++; + continue; + } + + AlignOff = (u32)OffsetVar & + (InstancePtr->Geometry.BlockSize - (u32)1); + if (AlignOff > 0U) { + BlockRemLen = InstancePtr->Geometry.BlockSize - + AlignOff; + EraseLen = (BlockRemLen < (u32)LengthVar) ? + BlockRemLen :(u32)LengthVar; + } else { + EraseLen = (InstancePtr->Geometry.BlockSize < + (u32)LengthVar) ? + InstancePtr->Geometry.BlockSize: + (u32)LengthVar; + } + NumBlocks++; + OffsetVar += EraseLen; + LengthVar -= EraseLen; + } + + for (Block = StartBlock; Block < (StartBlock + NumBlocks); Block++) { + Target = Block/InstancePtr->Geometry.NumTargetBlocks; + Block %= InstancePtr->Geometry.NumTargetBlocks; + if (XNandPs8_IsBlockBad(InstancePtr, Block) == + XST_SUCCESS) { + /* + * Don't erase bad block + */ + continue; + } + /* + * Block Erase + */ + Status = XNandPs8_EraseBlock(InstancePtr, Target, Block); + if (Status != XST_SUCCESS) { + goto Out; + } + /* + * ONFI ReadStatus + */ + do { + Status = XNandPs8_OnfiReadStatus(InstancePtr, Target, + &OnfiStatus); + if (Status != XST_SUCCESS) { + goto Out; + } + if ((OnfiStatus & (1U << 6U)) != 0U) { + if ((OnfiStatus & (1U << 0U)) != 0U) { + Status = XST_FAILURE; + goto Out; + } + } + } while (((OnfiStatus >> 6U) & 0x1U) == 0U); + } + + Status = XST_SUCCESS; +Out: + return Status; +} + +/*****************************************************************************/ +/** +* +* This function sends ONFI Program Page command to flash. +* +* @param InstancePtr is a pointer to the XNandPs8 instance. +* @param Target is the chip select value. +* @param Page is the page address value to program. +* @param Col is the column address value to program. +* @param Buf is the data buffer to program. +* +* @return +* - XST_SUCCESS if successful. +* - XST_FAILURE if failed. +* +* @note None +* +******************************************************************************/ +static s32 XNandPs8_ProgramPage(XNandPs8 *InstancePtr, u32 Target, u32 Page, + u32 Col, u8 *Buf) +{ + u32 AddrCycles = InstancePtr->Geometry.RowAddrCycles + + InstancePtr->Geometry.ColAddrCycles; + u32 PktSize; + u32 PktCount; + u32 BufWrCnt = 0U; + u32 *BufPtr = (u32 *)(void *)Buf; + s32 Status = XST_FAILURE; + u32 Index; + + /* + * Assert the input arguments. + */ + Xil_AssertNonvoid(Page < InstancePtr->Geometry.NumPages); + Xil_AssertNonvoid(Buf != NULL); + + if (InstancePtr->EccCfg.CodeWordSize > 9U) { + PktSize = 1024U; + } else { + PktSize = 512U; + } + PktCount = InstancePtr->Geometry.BytesPerPage/PktSize; + + XNandPs8_Prepare_Cmd(InstancePtr, ONFI_CMD_PG_PROG1, ONFI_CMD_PG_PROG2, + 1U, 1U, (u8)AddrCycles); + + if (InstancePtr->DmaMode == MDMA) { + + /* + * Enable DMA boundary Interrupt in Interrupt Status + * Enable Register + */ + XNandPs8_WriteReg((InstancePtr)->Config.BaseAddress, + XNANDPS8_INTR_STS_EN_OFFSET, + XNANDPS8_INTR_STS_EN_TRANS_COMP_STS_EN_MASK | + XNANDPS8_INTR_STS_EN_DMA_INT_STS_EN_MASK); + } else { + /* + * Enable Buffer Write Ready Interrupt in Interrupt Status + * Enable Register + */ + XNandPs8_WriteReg((InstancePtr)->Config.BaseAddress, + XNANDPS8_INTR_STS_EN_OFFSET, + XNANDPS8_INTR_STS_EN_BUFF_WR_RDY_STS_EN_MASK); + } + /* + * Program Page Size + */ + XNandPs8_SetPageSize(InstancePtr); + /* + * Program Packet Size and Packet Count + */ + XNandPs8_SetPktSzCnt(InstancePtr, PktSize, PktCount); + /* + * Program DMA system address and DMA buffer boundary + */ + if (InstancePtr->DmaMode == MDMA) { + /* + * Flush the Data Cache + */ + Xil_DCacheFlushRange(Buf, (PktSize * PktCount)); + +#ifdef __aarch64__ + XNandPs8_WriteReg(InstancePtr->Config.BaseAddress, + XNANDPS8_DMA_SYS_ADDR1_OFFSET, + (u32) (((INTPTR)Buf >> 32) & 0xFFFFFFFFU)); +#endif + XNandPs8_WriteReg(InstancePtr->Config.BaseAddress, + XNANDPS8_DMA_SYS_ADDR0_OFFSET, + (u32) ((INTPTR)(void *)Buf & 0xFFFFFFFFU)); + } + /* + * Program Column, Page, Block address + */ + XNandPs8_SetPageColAddr(InstancePtr, Page, (u16)Col); + /* + * Set Bus Width + */ + XNandPs8_SetBusWidth(InstancePtr); + /* + * Program Memory Address Register2 for chip select + */ + XNandPs8_SelectChip(InstancePtr, Target); + /* + * Set ECC + */ + if (InstancePtr->EccMode == HWECC) { + XNandPs8_SetEccSpareCmd(InstancePtr, ONFI_CMD_CHNG_WR_COL, + InstancePtr->Geometry.ColAddrCycles); + } + /* + * Set Page Program in Program Register + */ + XNandPs8_WriteReg((InstancePtr)->Config.BaseAddress, + XNANDPS8_PROG_OFFSET,XNANDPS8_PROG_PG_PROG_MASK); + + if (InstancePtr->DmaMode == MDMA) { + goto WriteDmaDone; + } + + while (BufWrCnt < PktCount) { + /* + * Poll for Buffer Write Ready event + */ + Status = XNandPs8_PollRegTimeout( + InstancePtr, + XNANDPS8_INTR_STS_OFFSET, + XNANDPS8_INTR_STS_BUFF_WR_RDY_STS_EN_MASK, + XNANDPS8_INTR_POLL_TIMEOUT); + if (Status != XST_SUCCESS) { +#ifdef XNANDPS8_DEBUG + xil_printf("%s: Poll for buf write ready timeout\r\n", + __func__); +#endif + goto Out; + } + /* + * Increment Buffer Write Interrupt Count + */ + BufWrCnt++; + + if (BufWrCnt == PktCount) { + /* + * Enable Transfer Complete Interrupt in Interrupt + * Status Enable Register + */ + XNandPs8_WriteReg((InstancePtr)->Config.BaseAddress, + XNANDPS8_INTR_STS_EN_OFFSET, + XNANDPS8_INTR_STS_EN_TRANS_COMP_STS_EN_MASK); + } else { + /* + * Clear Buffer Write Ready Interrupt in Interrupt + * Status Enable Register + */ + XNandPs8_WriteReg((InstancePtr)->Config.BaseAddress, + XNANDPS8_INTR_STS_EN_OFFSET, 0U); + + } + /* + * Clear Buffer Write Ready Interrupt in Interrupt Status + * Register + */ + XNandPs8_WriteReg((InstancePtr)->Config.BaseAddress, + XNANDPS8_INTR_STS_OFFSET, + XNANDPS8_INTR_STS_BUFF_WR_RDY_STS_EN_MASK); + /* + * Write Packet Data to Data Port Register + */ + for (Index = 0U; Index < (PktSize/4U); Index++) { + XNandPs8_WriteReg(InstancePtr->Config.BaseAddress, + XNANDPS8_BUF_DATA_PORT_OFFSET, + BufPtr[Index]); + } + BufPtr += (PktSize/4U); + + if (BufWrCnt < PktCount) { + /* + * Enable Buffer Write Ready Interrupt in Interrupt + * Status Enable Register + */ + XNandPs8_WriteReg((InstancePtr)->Config.BaseAddress, + XNANDPS8_INTR_STS_EN_OFFSET, + XNANDPS8_INTR_STS_EN_BUFF_WR_RDY_STS_EN_MASK); + } else { + break; + } + } +WriteDmaDone: + /* + * Poll for Transfer Complete event + */ + Status = XNandPs8_PollRegTimeout( + InstancePtr, + XNANDPS8_INTR_STS_OFFSET, + XNANDPS8_INTR_STS_TRANS_COMP_STS_EN_MASK, + XNANDPS8_INTR_POLL_TIMEOUT); + if (Status != XST_SUCCESS) { +#ifdef XNANDPS8_DEBUG + xil_printf("%s: Poll for xfer complete timeout\r\n", + __func__); +#endif + goto Out; + } + /* + * Clear Transfer Complete Interrupt in Interrupt Status Enable + * Register + */ + XNandPs8_WriteReg((InstancePtr)->Config.BaseAddress, + XNANDPS8_INTR_STS_EN_OFFSET, 0U); + + /* + * Clear Transfer Complete Interrupt in Interrupt Status Register + */ + XNandPs8_WriteReg((InstancePtr)->Config.BaseAddress, + XNANDPS8_INTR_STS_OFFSET, + XNANDPS8_INTR_STS_TRANS_COMP_STS_EN_MASK); + +Out: + return Status; +} + +/*****************************************************************************/ +/** +* +* This function sends ONFI Program Page command to flash. +* +* @param InstancePtr is a pointer to the XNandPs8 instance. +* @param Target is the chip select value. +* @param Page is the page address value to program. +* @param Col is the column address value to program. +* @param Buf is the data buffer to program. +* +* @return +* - XST_SUCCESS if successful. +* - XST_FAILURE if failed. +* +* @note None +* +******************************************************************************/ +s32 XNandPs8_WriteSpareBytes(XNandPs8 *InstancePtr, u32 Page, u8 *Buf) +{ + u32 AddrCycles = InstancePtr->Geometry.RowAddrCycles + + InstancePtr->Geometry.ColAddrCycles; + u32 Col = InstancePtr->Geometry.BytesPerPage; + u32 Target = Page/InstancePtr->Geometry.NumTargetPages; + u32 PktSize = InstancePtr->Geometry.SpareBytesPerPage; + u32 PktCount = 1U; + u32 BufWrCnt = 0U; + u32 *BufPtr = (u32 *)(void *)Buf; + u16 PreEccSpareCol = 0U; + u16 PreEccSpareWrCnt = 0U; + u16 PostEccSpareCol = 0U; + u16 PostEccSpareWrCnt = 0U; + u32 PostWrite = 0U; + OnfiCmdFormat Cmd; + s32 Status = XST_FAILURE; + u32 Index; + u32 PageVar = Page; + + /* + * Assert the input arguments. + */ + Xil_AssertNonvoid(InstancePtr != NULL); + Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + Xil_AssertNonvoid(PageVar < InstancePtr->Geometry.NumPages); + Xil_AssertNonvoid(Buf != NULL); + + PageVar %= InstancePtr->Geometry.NumTargetPages; + + if (InstancePtr->EccMode == HWECC) { + /* + * Calculate ECC free positions before and after ECC code + */ + PreEccSpareCol = 0x0U; + PreEccSpareWrCnt = InstancePtr->EccCfg.EccAddr - + (u16)InstancePtr->Geometry.BytesPerPage; + + PostEccSpareCol = PreEccSpareWrCnt + + InstancePtr->EccCfg.EccSize; + PostEccSpareWrCnt = InstancePtr->Geometry.SpareBytesPerPage - + PostEccSpareCol; + + PreEccSpareWrCnt = (PreEccSpareWrCnt/4U) * 4U; + PostEccSpareWrCnt = (PostEccSpareWrCnt/4U) * 4U; + + if (PreEccSpareWrCnt > 0U) { + PktSize = PreEccSpareWrCnt; + PktCount = 1U; + Col = InstancePtr->Geometry.BytesPerPage + + PreEccSpareCol; + BufPtr = (u32 *)(void *)Buf; + if (PostEccSpareWrCnt > 0U) { + PostWrite = 1U; + } + } else if (PostEccSpareWrCnt > 0U) { + PktSize = PostEccSpareWrCnt; + PktCount = 1U; + Col = InstancePtr->Geometry.BytesPerPage + + PostEccSpareCol; + BufPtr = (u32 *)(void *)&Buf[Col]; + } else { + /* + * No free spare bytes available for writing + */ + Status = XST_FAILURE; + goto Out; + } + } + + if (InstancePtr->DmaMode == MDMA) { + /* + * Enable Transfer Complete Interrupt in Interrupt Status + * Enable Register + */ + XNandPs8_WriteReg((InstancePtr)->Config.BaseAddress, + XNANDPS8_INTR_STS_EN_OFFSET, + XNANDPS8_INTR_STS_EN_TRANS_COMP_STS_EN_MASK); + + } else { + /* + * Enable Buffer Write Ready Interrupt in Interrupt Status + * Enable Register + */ + XNandPs8_WriteReg((InstancePtr)->Config.BaseAddress, + XNANDPS8_INTR_STS_EN_OFFSET, + XNANDPS8_INTR_STS_EN_BUFF_WR_RDY_STS_EN_MASK); + + } + /* + * Program Command hack for change write column + */ + if (PostWrite > 0U) { + Cmd.Command1 = 0x80U; + Cmd.Command2 = 0x00U; + XNandPs8_Prepare_Cmd(InstancePtr, Cmd.Command1, Cmd.Command2, + 0U , 1U, (u8)AddrCycles); + + } else { + XNandPs8_Prepare_Cmd(InstancePtr, ONFI_CMD_PG_PROG1, + ONFI_CMD_PG_PROG2, 0U , 1U, (u8)AddrCycles); + } + /* + * Program Page Size + */ + XNandPs8_SetPageSize(InstancePtr); + /* + * Program Packet Size and Packet Count + */ + XNandPs8_SetPktSzCnt(InstancePtr, PktSize, PktCount); + /* + * Program DMA system address and DMA buffer boundary + */ + if (InstancePtr->DmaMode == MDMA) { + /* + * Flush the Data Cache + */ + Xil_DCacheFlushRange(BufPtr, (PktSize * PktCount)); + +#ifdef __aarch64__ + XNandPs8_WriteReg(InstancePtr->Config.BaseAddress, + XNANDPS8_DMA_SYS_ADDR1_OFFSET, + (u32) (((INTPTR)BufPtr >> 32) & 0xFFFFFFFFU)); +#endif + XNandPs8_WriteReg(InstancePtr->Config.BaseAddress, + XNANDPS8_DMA_SYS_ADDR0_OFFSET, + (u32) ((INTPTR)(void *)BufPtr & 0xFFFFFFFFU)); + + XNandPs8_WriteReg(InstancePtr->Config.BaseAddress, + XNANDPS8_DMA_BUF_BND_OFFSET, + XNANDPS8_DMA_BUF_BND_512K); + } + /* + * Program Column, Page, Block address + */ + XNandPs8_SetPageColAddr(InstancePtr, PageVar, (u16)Col); + /* + * Set Bus Width + */ + XNandPs8_SetBusWidth(InstancePtr); + /* + * Program Memory Address Register2 for chip select + */ + XNandPs8_SelectChip(InstancePtr, Target); + /* + * Set Page Program in Program Register + */ + if (PostWrite > 0U) { + XNandPs8_WriteReg((InstancePtr)->Config.BaseAddress, + XNANDPS8_PROG_OFFSET,((u32)XNANDPS8_PROG_PG_PROG_MASK | + (u32)XNANDPS8_PROG_CHNG_ROW_ADDR_MASK)); + } else { + XNandPs8_WriteReg((InstancePtr)->Config.BaseAddress, + XNANDPS8_PROG_OFFSET,XNANDPS8_PROG_PG_PROG_MASK); + } + + if (InstancePtr->DmaMode == MDMA) { + goto WriteDmaDone; + } + + while (BufWrCnt < PktCount) { + /* + * Poll for Buffer Write Ready event + */ + Status = XNandPs8_PollRegTimeout( + InstancePtr, + XNANDPS8_INTR_STS_OFFSET, + XNANDPS8_INTR_STS_BUFF_WR_RDY_STS_EN_MASK, + XNANDPS8_INTR_POLL_TIMEOUT); + if (Status != XST_SUCCESS) { +#ifdef XNANDPS8_DEBUG + xil_printf("%s: Poll for buf write ready timeout\r\n", + __func__); +#endif + goto Out; + } + /* + * Increment Buffer Write Interrupt Count + */ + BufWrCnt++; + + if (BufWrCnt == PktCount) { + /* + * Enable Transfer Complete Interrupt in Interrupt + * Status Enable Register + */ + XNandPs8_WriteReg((InstancePtr)->Config.BaseAddress, + XNANDPS8_INTR_STS_EN_OFFSET, + XNANDPS8_INTR_STS_EN_TRANS_COMP_STS_EN_MASK); + + } else { + /* + * Clear Buffer Write Ready Interrupt in Interrupt + * Status Enable Register + */ + XNandPs8_WriteReg((InstancePtr)->Config.BaseAddress, + XNANDPS8_INTR_STS_EN_OFFSET, 0U); + } + /* + * Clear Buffer Write Ready Interrupt in Interrupt Status + * Register + */ + XNandPs8_WriteReg((InstancePtr)->Config.BaseAddress, + XNANDPS8_INTR_STS_OFFSET, + XNANDPS8_INTR_STS_BUFF_WR_RDY_STS_EN_MASK); + /* + * Write Packet Data to Data Port Register + */ + for (Index = 0U; Index < (PktSize/4U); Index++) { + XNandPs8_WriteReg(InstancePtr->Config.BaseAddress, + XNANDPS8_BUF_DATA_PORT_OFFSET, + BufPtr[Index]); + } + BufPtr += (PktSize/4U); + + if (BufWrCnt < PktCount) { + /* + * Enable Buffer Write Ready Interrupt in Interrupt + * Status Enable Register + */ + XNandPs8_WriteReg((InstancePtr)->Config.BaseAddress, + XNANDPS8_INTR_STS_EN_OFFSET, + XNANDPS8_INTR_STS_EN_BUFF_WR_RDY_STS_EN_MASK); + } else { + break; + } + } +WriteDmaDone: + /* + * Poll for Transfer Complete event + */ + Status = XNandPs8_PollRegTimeout( + InstancePtr, + XNANDPS8_INTR_STS_OFFSET, + XNANDPS8_INTR_STS_TRANS_COMP_STS_EN_MASK, + XNANDPS8_INTR_POLL_TIMEOUT); + if (Status != XST_SUCCESS) { +#ifdef XNANDPS8_DEBUG + xil_printf("%s: Poll for xfer complete timeout\r\n", + __func__); +#endif + goto Out; + } + /* + * Clear Transfer Complete Interrupt in Interrupt Status Enable + * Register + */ + XNandPs8_WriteReg((InstancePtr)->Config.BaseAddress, + XNANDPS8_INTR_STS_EN_OFFSET, 0U); + + /* + * Clear Transfer Complete Interrupt in Interrupt Status Register + */ + XNandPs8_WriteReg((InstancePtr)->Config.BaseAddress, + XNANDPS8_INTR_STS_OFFSET, + XNANDPS8_INTR_STS_TRANS_COMP_STS_EN_MASK); + + if (InstancePtr->EccMode == HWECC) { + if (PostWrite > 0U) { + BufPtr = (u32 *)(void *)&Buf[PostEccSpareCol]; + Status = XNandPs8_ChangeWriteColumn(InstancePtr, + Target, + PostEccSpareCol, PostEccSpareWrCnt, 1U, + (u8 *)(void *)BufPtr); + if (Status != XST_SUCCESS) { + goto Out; + } + } + } +Out: + + return Status; +} + +/*****************************************************************************/ +/** +* +* This function sends ONFI Read Page command to flash. +* +* @param InstancePtr is a pointer to the XNandPs8 instance. +* @param Target is the chip select value. +* @param Page is the page address value to read. +* @param Col is the column address value to read. +* @param Buf is the data buffer to fill in. +* +* @return +* - XST_SUCCESS if successful. +* - XST_FAILURE if failed. +* +* @note None +* +******************************************************************************/ +static s32 XNandPs8_ReadPage(XNandPs8 *InstancePtr, u32 Target, u32 Page, + u32 Col, u8 *Buf) +{ + u32 AddrCycles = InstancePtr->Geometry.RowAddrCycles + + InstancePtr->Geometry.ColAddrCycles; + u32 PktSize; + u32 PktCount; + u32 BufRdCnt = 0U; + u32 *BufPtr = (u32 *)(void *)Buf; + s32 Status = XST_FAILURE; + u32 Index; + + /* + * Assert the input arguments. + */ + Xil_AssertNonvoid(Page < InstancePtr->Geometry.NumPages); + Xil_AssertNonvoid(Target < XNANDPS8_MAX_TARGETS); + + if (InstancePtr->EccCfg.CodeWordSize > 9U) { + PktSize = 1024U; + } else { + PktSize = 512U; + } + PktCount = InstancePtr->Geometry.BytesPerPage/PktSize; + + XNandPs8_Prepare_Cmd(InstancePtr, ONFI_CMD_RD1, ONFI_CMD_RD2, + 1U, 1U, (u8)AddrCycles); + + if (InstancePtr->DmaMode == MDMA) { + + /* + * Enable DMA boundary Interrupt in Interrupt Status + * Enable Register + */ + XNandPs8_WriteReg((InstancePtr)->Config.BaseAddress, + XNANDPS8_INTR_STS_EN_OFFSET, + XNANDPS8_INTR_STS_EN_TRANS_COMP_STS_EN_MASK | + XNANDPS8_INTR_STS_EN_DMA_INT_STS_EN_MASK); + + } else { + /* + * Enable Buffer Read Ready Interrupt in Interrupt Status + * Enable Register + */ + XNandPs8_WriteReg((InstancePtr)->Config.BaseAddress, + XNANDPS8_INTR_STS_EN_OFFSET, + XNANDPS8_INTR_STS_EN_BUFF_RD_RDY_STS_EN_MASK); + + } + /* + * Enable Single bit error and Multi bit error + */ + if (InstancePtr->EccMode == HWECC) { + /* + * Interrupt Status Enable Register + */ + XNandPs8_IntrStsEnable(InstancePtr, + (XNANDPS8_INTR_STS_EN_MUL_BIT_ERR_STS_EN_MASK | + XNANDPS8_INTR_STS_EN_ERR_INTR_STS_EN_MASK)); + } + /* + * Program Page Size + */ + XNandPs8_SetPageSize(InstancePtr); + /* + * Program Column, Page, Block address + */ + XNandPs8_SetPageColAddr(InstancePtr, Page, (u16)Col); + /* + * Program Packet Size and Packet Count + */ + XNandPs8_SetPktSzCnt(InstancePtr, PktSize, PktCount); + /* + * Program DMA system address and DMA buffer boundary + */ + if (InstancePtr->DmaMode == MDMA) { + /* + * Invalidate the Data Cache + */ + Xil_DCacheInvalidateRange(Buf, (PktSize * PktCount)); + +#ifdef __aarch64__ + XNandPs8_WriteReg(InstancePtr->Config.BaseAddress, + XNANDPS8_DMA_SYS_ADDR1_OFFSET, + (u32) (((INTPTR)(void *)Buf >> 32) & + 0xFFFFFFFFU)); +#endif + XNandPs8_WriteReg(InstancePtr->Config.BaseAddress, + XNANDPS8_DMA_SYS_ADDR0_OFFSET, + (u32) ((INTPTR)(void *)Buf & 0xFFFFFFFFU)); + } + /* + * Set Bus Width + */ + XNandPs8_SetBusWidth(InstancePtr); + /* + * Program Memory Address Register2 for chip select + */ + XNandPs8_SelectChip(InstancePtr, Target); + /* + * Set ECC + */ + if (InstancePtr->EccMode == HWECC) { + XNandPs8_SetEccSpareCmd(InstancePtr, + (ONFI_CMD_CHNG_RD_COL1 | + (ONFI_CMD_CHNG_RD_COL2 << (u8)8U)), + InstancePtr->Geometry.ColAddrCycles); + } + + /* + * Set Read command in Program Register + */ + XNandPs8_WriteReg((InstancePtr)->Config.BaseAddress, + XNANDPS8_PROG_OFFSET,XNANDPS8_PROG_RD_MASK); + + if (InstancePtr->DmaMode == MDMA) { + goto ReadDmaDone; + } + + while (BufRdCnt < PktCount) { + /* + * Poll for Buffer Read Ready event + */ + Status = XNandPs8_PollRegTimeout( + InstancePtr, + XNANDPS8_INTR_STS_OFFSET, + XNANDPS8_INTR_STS_BUFF_RD_RDY_STS_EN_MASK, + XNANDPS8_INTR_POLL_TIMEOUT); + if (Status != XST_SUCCESS) { +#ifdef XNANDPS8_DEBUG + xil_printf("%s: Poll for buf read ready timeout\r\n", + __func__); +#endif + goto CheckEccError; + } + /* + * Increment Buffer Read Interrupt Count + */ + BufRdCnt++; + + if (BufRdCnt == PktCount) { + /* + * Enable Transfer Complete Interrupt in Interrupt + * Status Enable Register + */ + XNandPs8_WriteReg((InstancePtr)->Config.BaseAddress, + XNANDPS8_INTR_STS_EN_OFFSET, + XNANDPS8_INTR_STS_EN_TRANS_COMP_STS_EN_MASK); + } else { + /* + * Clear Buffer Read Ready Interrupt in Interrupt + * Status Enable Register + */ + XNandPs8_WriteReg((InstancePtr)->Config.BaseAddress, + XNANDPS8_INTR_STS_EN_OFFSET, 0U); + } + /* + * Clear Buffer Read Ready Interrupt in Interrupt Status + * Register + */ + XNandPs8_WriteReg((InstancePtr)->Config.BaseAddress, + XNANDPS8_INTR_STS_OFFSET, + XNANDPS8_INTR_STS_BUFF_RD_RDY_STS_EN_MASK); + /* + * Read Packet Data from Data Port Register + */ + for (Index = 0U; Index < (PktSize/4); Index++) { + BufPtr[Index] = XNandPs8_ReadReg( + InstancePtr->Config.BaseAddress, + XNANDPS8_BUF_DATA_PORT_OFFSET); + } + BufPtr += (PktSize/4); + + if (BufRdCnt < PktCount) { + /* + * Enable Buffer Read Ready Interrupt in Interrupt + * Status Enable Register + */ + XNandPs8_WriteReg((InstancePtr)->Config.BaseAddress, + XNANDPS8_INTR_STS_EN_OFFSET, + XNANDPS8_INTR_STS_EN_BUFF_RD_RDY_STS_EN_MASK); + + } else { + break; + } + } +ReadDmaDone: + /* + * Poll for Transfer Complete event + */ + Status = XNandPs8_PollRegTimeout( + InstancePtr, + XNANDPS8_INTR_STS_OFFSET, + XNANDPS8_INTR_STS_TRANS_COMP_STS_EN_MASK, + XNANDPS8_INTR_POLL_TIMEOUT); + if (Status != XST_SUCCESS) { +#ifdef XNANDPS8_DEBUG + xil_printf("%s: Poll for xfer complete timeout\r\n", + __func__); +#endif + goto CheckEccError; + } + /* + * Clear Transfer Complete Interrupt in Interrupt Status Enable + * Register + */ + XNandPs8_WriteReg((InstancePtr)->Config.BaseAddress, + XNANDPS8_INTR_STS_EN_OFFSET, 0U); + + /* + * Clear Transfer Complete Interrupt in Interrupt Status Register + */ + XNandPs8_WriteReg((InstancePtr)->Config.BaseAddress, + XNANDPS8_INTR_STS_OFFSET, + XNANDPS8_INTR_STS_TRANS_COMP_STS_EN_MASK); + +CheckEccError: + /* + * Check ECC Errors + */ + if (InstancePtr->EccMode == HWECC) { + /* + * Hamming Multi Bit Errors + */ + if (((u32)XNandPs8_ReadReg(InstancePtr->Config.BaseAddress, + XNANDPS8_INTR_STS_OFFSET) & + (u32)XNANDPS8_INTR_STS_MUL_BIT_ERR_STS_EN_MASK) != 0U) { + + XNandPs8_WriteReg((InstancePtr)->Config.BaseAddress, + XNANDPS8_INTR_STS_OFFSET, + XNANDPS8_INTR_STS_MUL_BIT_ERR_STS_EN_MASK); + +#ifdef XNANDPS8_DEBUG + xil_printf("%s: ECC Hamming multi bit error\r\n", + __func__); +#endif + Status = XST_FAILURE; + } + /* + * Hamming Single Bit or BCH Errors + */ + if (((u32)XNandPs8_ReadReg(InstancePtr->Config.BaseAddress, + XNANDPS8_INTR_STS_OFFSET) & + (u32)XNANDPS8_INTR_STS_ERR_INTR_STS_EN_MASK) != 0U) { + + XNandPs8_WriteReg((InstancePtr)->Config.BaseAddress, + XNANDPS8_INTR_STS_OFFSET, + XNANDPS8_INTR_STS_ERR_INTR_STS_EN_MASK); + + if (InstancePtr->EccCfg.IsBCH == 1U) { + InstancePtr->BCH_Error_Status++; + + Status = XST_SUCCESS; + } + } + } +Out: + return Status; +} + +/*****************************************************************************/ +/** +* +* This function reads spare bytes from flash. +* +* @param InstancePtr is a pointer to the XNandPs8 instance. +* @param Target is the chip select value. +* @param Page is the page address value to read. +* @param Buf is the data buffer to fill in. +* +* @return +* - XST_SUCCESS if successful. +* - XST_FAILURE if failed. +* +* @note None +* +******************************************************************************/ +s32 XNandPs8_ReadSpareBytes(XNandPs8 *InstancePtr, u32 Page, u8 *Buf) +{ + u32 AddrCycles = InstancePtr->Geometry.RowAddrCycles + + InstancePtr->Geometry.ColAddrCycles; + u32 Col = InstancePtr->Geometry.BytesPerPage; + u32 Target = Page/InstancePtr->Geometry.NumTargetPages; + u32 PktSize = InstancePtr->Geometry.SpareBytesPerPage; + u32 PktCount = 1U; + u32 BufRdCnt = 0U; + u32 *BufPtr = (u32 *)(void *)Buf; + s32 Status = XST_FAILURE; + u32 Index; + u32 PageVar = Page; + + /* + * Assert the input arguments. + */ + Xil_AssertNonvoid(InstancePtr != NULL); + Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + Xil_AssertNonvoid(PageVar < InstancePtr->Geometry.NumPages); + Xil_AssertNonvoid(Buf != NULL); + + PageVar %= InstancePtr->Geometry.NumTargetPages; + + if (InstancePtr->DmaMode == MDMA) { + /* + * Enable Transfer Complete Interrupt in Interrupt Status + * Enable Register + */ + XNandPs8_WriteReg((InstancePtr)->Config.BaseAddress, + XNANDPS8_INTR_STS_EN_OFFSET, + XNANDPS8_INTR_STS_EN_TRANS_COMP_STS_EN_MASK); + } else { + /* + * Enable Buffer Read Ready Interrupt in Interrupt Status + * Enable Register + */ + XNandPs8_WriteReg((InstancePtr)->Config.BaseAddress, + XNANDPS8_INTR_STS_EN_OFFSET, + XNANDPS8_INTR_STS_EN_BUFF_RD_RDY_STS_EN_MASK); + } + /* + * Program Command + */ + XNandPs8_Prepare_Cmd(InstancePtr, ONFI_CMD_RD1, ONFI_CMD_RD2, 0U, + 1U, (u8)AddrCycles); + /* + * Program Page Size + */ + XNandPs8_SetPageSize(InstancePtr); + /* + * Program Column, Page, Block address + */ + XNandPs8_SetPageColAddr(InstancePtr, PageVar, (u16)Col); + /* + * Program Packet Size and Packet Count + */ + XNandPs8_SetPktSzCnt(InstancePtr, PktSize, PktCount); + /* + * Program DMA system address and DMA buffer boundary + */ + if (InstancePtr->DmaMode == MDMA) { + + /* + * Invalidate the Data Cache + */ + Xil_DCacheInvalidateRange(Buf, (PktSize * PktCount)); +#ifdef __aarch64__ + XNandPs8_WriteReg(InstancePtr->Config.BaseAddress, + XNANDPS8_DMA_SYS_ADDR1_OFFSET, + (u32) (((INTPTR)(void *)Buf >> 32) & + 0xFFFFFFFFU)); +#endif + XNandPs8_WriteReg(InstancePtr->Config.BaseAddress, + XNANDPS8_DMA_SYS_ADDR0_OFFSET, + (u32) ((INTPTR)(void *)Buf & 0xFFFFFFFFU)); + } + /* + * Set Bus Width + */ + XNandPs8_SetBusWidth(InstancePtr); + /* + * Program Memory Address Register2 for chip select + */ + XNandPs8_SelectChip(InstancePtr, Target); + /* + * Set Read command in Program Register + */ + XNandPs8_WriteReg((InstancePtr)->Config.BaseAddress, + XNANDPS8_PROG_OFFSET,XNANDPS8_PROG_RD_MASK); + + if (InstancePtr->DmaMode == MDMA) { + goto ReadDmaDone; + } + + while (BufRdCnt < PktCount) { + /* + * Poll for Buffer Read Ready event + */ + Status = XNandPs8_PollRegTimeout( + InstancePtr, + XNANDPS8_INTR_STS_OFFSET, + XNANDPS8_INTR_STS_BUFF_RD_RDY_STS_EN_MASK, + XNANDPS8_INTR_POLL_TIMEOUT); + if (Status != XST_SUCCESS) { +#ifdef XNANDPS8_DEBUG + xil_printf("%s: Poll for buf read ready timeout\r\n", + __func__); +#endif + goto Out; + } + /* + * Increment Buffer Read Interrupt Count + */ + BufRdCnt++; + + if (BufRdCnt == PktCount) { + /* + * Enable Transfer Complete Interrupt in Interrupt + * Status Enable Register + */ + XNandPs8_WriteReg((InstancePtr)->Config.BaseAddress, + XNANDPS8_INTR_STS_EN_OFFSET, + XNANDPS8_INTR_STS_EN_TRANS_COMP_STS_EN_MASK); + + } else { + /* + * Clear Buffer Read Ready Interrupt in Interrupt + * Status Enable Register + */ + XNandPs8_WriteReg((InstancePtr)->Config.BaseAddress, + XNANDPS8_INTR_STS_EN_OFFSET, 0U); + + } + /* + * Clear Buffer Read Ready Interrupt in Interrupt Status + * Register + */ + XNandPs8_WriteReg((InstancePtr)->Config.BaseAddress, + XNANDPS8_INTR_STS_OFFSET, + XNANDPS8_INTR_STS_BUFF_RD_RDY_STS_EN_MASK); + /* + * Read Packet Data from Data Port Register + */ + for (Index = 0U; Index < (PktSize/4); Index++) { + BufPtr[Index] = XNandPs8_ReadReg( + InstancePtr->Config.BaseAddress, + XNANDPS8_BUF_DATA_PORT_OFFSET); + } + BufPtr += (PktSize/4); + + if (BufRdCnt < PktCount) { + /* + * Enable Buffer Read Ready Interrupt in Interrupt + * Status Enable Register + */ + XNandPs8_WriteReg((InstancePtr)->Config.BaseAddress, + XNANDPS8_INTR_STS_EN_OFFSET, + XNANDPS8_INTR_STS_EN_BUFF_RD_RDY_STS_EN_MASK); + } else { + break; + } + } +ReadDmaDone: + /* + * Poll for Transfer Complete event + */ + Status = XNandPs8_PollRegTimeout( + InstancePtr, + XNANDPS8_INTR_STS_OFFSET, + XNANDPS8_INTR_STS_TRANS_COMP_STS_EN_MASK, + XNANDPS8_INTR_POLL_TIMEOUT); + if (Status != XST_SUCCESS) { +#ifdef XNANDPS8_DEBUG + xil_printf("%s: Poll for xfer complete timeout\r\n", + __func__); +#endif + goto Out; + } + /* + * Clear Transfer Complete Interrupt in Interrupt Status Enable + * Register + */ + XNandPs8_WriteReg((InstancePtr)->Config.BaseAddress, + XNANDPS8_INTR_STS_EN_OFFSET, 0U); + + /* + * Clear Transfer Complete Interrupt in Interrupt Status Register + */ + XNandPs8_WriteReg((InstancePtr)->Config.BaseAddress, + XNANDPS8_INTR_STS_OFFSET, + XNANDPS8_INTR_STS_TRANS_COMP_STS_EN_MASK); +Out: + + return Status; +} + +/*****************************************************************************/ +/** +* +* This function sends ONFI block erase command to the flash. +* +* @param InstancePtr is a pointer to the XNandPs8 instance. +* @param Target is the chip select value. +* @param Block is the block to erase. +* +* @return +* - XST_SUCCESS if successful. +* - XST_FAILURE if failed. +* +* @note None +* +******************************************************************************/ +s32 XNandPs8_EraseBlock(XNandPs8 *InstancePtr, u32 Target, u32 Block) +{ + s32 Status = XST_FAILURE; + u32 AddrCycles = InstancePtr->Geometry.RowAddrCycles; + u32 Page; + u32 ErasePage; + u32 EraseCol; + + /* + * Assert the input arguments. + */ + Xil_AssertNonvoid(InstancePtr != NULL); + Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + Xil_AssertNonvoid(Target < XNANDPS8_MAX_TARGETS); + Xil_AssertNonvoid(Block < InstancePtr->Geometry.NumBlocks); + + Page = Block * InstancePtr->Geometry.PagesPerBlock; + ErasePage = (Page >> 16U) & 0xFFFFU; + EraseCol = Page & 0xFFFFU; + +#ifdef RTL_3_1_DRIVER_WORKAROUND + /* + * The sequence read, {erase, read status}, {program, read status} + * fails if we don't clear packet register 0x00 before erase. + * The actual reason for the issue is not yet found. + * This issue still needs to be investigated. + */ + XNandPs8_WriteReg(InstancePtr->Config.BaseAddress, 0x00U, 0x0U); +#endif + + /* + * Enable Transfer Complete Interrupt in Interrupt Status Enable + * Register + */ + XNandPs8_WriteReg((InstancePtr)->Config.BaseAddress, + XNANDPS8_INTR_STS_EN_OFFSET, + XNANDPS8_INTR_STS_EN_TRANS_COMP_STS_EN_MASK); + + /* + * Program Command + */ + XNandPs8_Prepare_Cmd(InstancePtr, ONFI_CMD_BLK_ERASE1, + ONFI_CMD_BLK_ERASE2, 0U , 0U, (u8)AddrCycles); + /* + * Program Column, Page, Block address + */ + XNandPs8_SetPageColAddr(InstancePtr, ErasePage, (u16)EraseCol); + /* + * Program Memory Address Register2 for chip select + */ + XNandPs8_SelectChip(InstancePtr, Target); + /* + * Set Block Erase in Program Register + */ + XNandPs8_WriteReg((InstancePtr)->Config.BaseAddress, + XNANDPS8_PROG_OFFSET,XNANDPS8_PROG_BLK_ERASE_MASK); + /* + * Poll for Transfer Complete event + */ + Status = XNandPs8_PollRegTimeout( + InstancePtr, + XNANDPS8_INTR_STS_OFFSET, + XNANDPS8_INTR_STS_TRANS_COMP_STS_EN_MASK, + XNANDPS8_INTR_POLL_TIMEOUT); + if (Status != XST_SUCCESS) { +#ifdef XNANDPS8_DEBUG + xil_printf("%s: Poll for xfer complete timeout\r\n", + __func__); +#endif + goto Out; + } + /* + * Clear Transfer Complete Interrupt in Interrupt Status Enable + * Register + */ + XNandPs8_WriteReg((InstancePtr)->Config.BaseAddress, + XNANDPS8_INTR_STS_EN_OFFSET, 0U); + + /* + * Clear Transfer Complete Interrupt in Interrupt Status Register + */ + XNandPs8_WriteReg((InstancePtr)->Config.BaseAddress, + XNANDPS8_INTR_STS_OFFSET, + XNANDPS8_INTR_STS_TRANS_COMP_STS_EN_MASK); + +Out: + return Status; +} + +/*****************************************************************************/ +/** +* +* This function sends ONFI Get Feature command to flash. +* +* @param InstancePtr is a pointer to the XNandPs8 instance. +* @param Target is the chip select value. +* @param Feature is the feature selector. +* @param Buf is the buffer to fill feature value. +* +* @return +* - XST_SUCCESS if successful. +* - XST_FAILURE if failed. +* +* @note None +* +******************************************************************************/ +s32 XNandPs8_GetFeature(XNandPs8 *InstancePtr, u32 Target, u8 Feature, + u8 *Buf) +{ + s32 Status; + u32 Index; + u32 PktSize = 4; + u32 PktCount = 1; + u32 *BufPtr = (u32 *)(void *)Buf; + + /* + * Assert the input arguments. + */ + Xil_AssertNonvoid(Buf != NULL); + + if (InstancePtr->DataInterface == NVDDR) { + PktSize = 8U; + } + + /* + * Enable Buffer Read Ready Interrupt in Interrupt Status + * Enable Register + */ + XNandPs8_WriteReg((InstancePtr)->Config.BaseAddress, + XNANDPS8_INTR_STS_EN_OFFSET, + XNANDPS8_INTR_STS_EN_BUFF_RD_RDY_STS_EN_MASK); + /* + * Program Command + */ + XNandPs8_Prepare_Cmd(InstancePtr, ONFI_CMD_GET_FEATURES, + ONFI_CMD_INVALID, 0U, 0U, 1U); + /* + * Program Column, Page, Block address + */ + XNandPs8_SetPageColAddr(InstancePtr, 0x0U, Feature); + /* + * Program Memory Address Register2 for chip select + */ + XNandPs8_SelectChip(InstancePtr, Target); + /* + * Program Packet Size and Packet Count + */ + XNandPs8_SetPktSzCnt(InstancePtr, PktSize, PktCount); + /* + * Set Read Parameter Page in Program Register + */ + XNandPs8_WriteReg((InstancePtr)->Config.BaseAddress, + XNANDPS8_PROG_OFFSET,XNANDPS8_PROG_GET_FEATURES_MASK); + /* + * Poll for Buffer Read Ready event + */ + Status = XNandPs8_PollRegTimeout( + InstancePtr, + XNANDPS8_INTR_STS_OFFSET, + XNANDPS8_INTR_STS_BUFF_RD_RDY_STS_EN_MASK, + XNANDPS8_INTR_POLL_TIMEOUT); + if (Status != XST_SUCCESS) { +#ifdef XNANDPS8_DEBUG + xil_printf("%s: Poll for buf read ready timeout\r\n", + __func__); +#endif + goto Out; + } + /* + * Clear Buffer Read Ready Interrupt in Interrupt Status Enable + * Register + */ + XNandPs8_WriteReg((InstancePtr)->Config.BaseAddress, + XNANDPS8_INTR_STS_EN_OFFSET, 0U); + + /* + * Clear Buffer Read Ready Interrupt in Interrupt Status Register + */ + XNandPs8_WriteReg((InstancePtr)->Config.BaseAddress, + XNANDPS8_INTR_STS_OFFSET, + XNANDPS8_INTR_STS_BUFF_RD_RDY_STS_EN_MASK); + /* + * Enable Transfer Complete Interrupt in Interrupt Status Enable + * Register + */ + XNandPs8_WriteReg((InstancePtr)->Config.BaseAddress, + XNANDPS8_INTR_STS_EN_OFFSET, + XNANDPS8_INTR_STS_EN_TRANS_COMP_STS_EN_MASK); + + /* + * Read Data from Data Port Register + */ + for (Index = 0U; Index < (PktSize/4U); Index++) { + BufPtr[Index] = XNandPs8_ReadReg( + InstancePtr->Config.BaseAddress, + XNANDPS8_BUF_DATA_PORT_OFFSET); + } + /* + * Poll for Transfer Complete event + */ + Status = XNandPs8_PollRegTimeout( + InstancePtr, + XNANDPS8_INTR_STS_OFFSET, + XNANDPS8_INTR_STS_TRANS_COMP_STS_EN_MASK, + XNANDPS8_INTR_POLL_TIMEOUT); + if (Status != XST_SUCCESS) { +#ifdef XNANDPS8_DEBUG + xil_printf("%s: Poll for xfer complete timeout\r\n", + __func__); +#endif + goto Out; + } + /* + * Clear Transfer Complete Interrupt in Interrupt Status Enable + * Register + */ + XNandPs8_WriteReg((InstancePtr)->Config.BaseAddress, + XNANDPS8_INTR_STS_EN_OFFSET, 0U); + + /* + * Clear Transfer Complete Interrupt in Interrupt Status Register + */ + XNandPs8_WriteReg((InstancePtr)->Config.BaseAddress, + XNANDPS8_INTR_STS_OFFSET, + XNANDPS8_INTR_STS_TRANS_COMP_STS_EN_MASK); + +Out: + return Status; +} + +/*****************************************************************************/ +/** +* +* This function sends ONFI Set Feature command to flash. +* +* @param InstancePtr is a pointer to the XNandPs8 instance. +* @param Target is the chip select value. +* @param Feature is the feature selector. +* @param Buf is the feature value to send. +* +* @return +* - XST_SUCCESS if successful. +* - XST_FAILURE if failed. +* +* @note None +* +******************************************************************************/ +s32 XNandPs8_SetFeature(XNandPs8 *InstancePtr, u32 Target, u8 Feature, + u8 *Buf) +{ + s32 Status; + u32 Index; + u32 PktSize = 4U; + u32 PktCount = 1U; + u32 *BufPtr = (u32 *)(void *)Buf; + + /* + * Assert the input arguments. + */ + Xil_AssertNonvoid(Buf != NULL); + if (InstancePtr->DataInterface == NVDDR) { + PktSize = 8U; + } + + XNandPs8_WriteReg((InstancePtr)->Config.BaseAddress, + XNANDPS8_INTR_STS_EN_OFFSET, 0U); + + /* + * Enable Buffer Write Ready Interrupt in Interrupt Status + * Enable Register + */ + XNandPs8_WriteReg((InstancePtr)->Config.BaseAddress, + XNANDPS8_INTR_STS_EN_OFFSET, + XNANDPS8_INTR_STS_EN_BUFF_WR_RDY_STS_EN_MASK); + + /* + * Program Command + */ + XNandPs8_Prepare_Cmd(InstancePtr, ONFI_CMD_SET_FEATURES, + ONFI_CMD_INVALID, 0U , 0U, 1U); + /* + * Program Column, Page, Block address + */ + XNandPs8_SetPageColAddr(InstancePtr, 0x0U, Feature); + /* + * Program Memory Address Register2 for chip select + */ + XNandPs8_SelectChip(InstancePtr, Target); + /* + * Program Packet Size and Packet Count + */ + XNandPs8_SetPktSzCnt(InstancePtr, PktSize, PktCount); + /* + * Set Read Parameter Page in Program Register + */ + XNandPs8_WriteReg((InstancePtr)->Config.BaseAddress, + XNANDPS8_PROG_OFFSET,XNANDPS8_PROG_SET_FEATURES_MASK); + /* + * Poll for Buffer Write Ready event + */ + Status = XNandPs8_PollRegTimeout( + InstancePtr, + XNANDPS8_INTR_STS_OFFSET, + XNANDPS8_INTR_STS_BUFF_WR_RDY_STS_EN_MASK, + XNANDPS8_INTR_POLL_TIMEOUT); + if (Status != XST_SUCCESS) { +#ifdef XNANDPS8_DEBUG + xil_printf("%s: Poll for buf write ready timeout\r\n", + __func__); +#endif + goto Out; + } + /* + * Clear Buffer Write Ready Interrupt in Interrupt Status Enable + * Register + */ + XNandPs8_WriteReg((InstancePtr)->Config.BaseAddress, + XNANDPS8_INTR_STS_EN_OFFSET, 0U); + + /* + * Clear Buffer Write Ready Interrupt in Interrupt Status Register + */ + XNandPs8_WriteReg((InstancePtr)->Config.BaseAddress, + XNANDPS8_INTR_STS_OFFSET, + XNANDPS8_INTR_STS_BUFF_WR_RDY_STS_EN_MASK); + /* + * Enable Transfer Complete Interrupt in Interrupt Status Enable + * Register + */ + XNandPs8_WriteReg((InstancePtr)->Config.BaseAddress, + (XNANDPS8_INTR_STS_EN_OFFSET), + XNANDPS8_INTR_STS_EN_TRANS_COMP_STS_EN_MASK); + /* + * Write Data to Data Port Register + */ + for (Index = 0U; Index < (PktSize/4U); Index++) { + XNandPs8_WriteReg(InstancePtr->Config.BaseAddress, + XNANDPS8_BUF_DATA_PORT_OFFSET, + BufPtr[Index]); + } + /* + * Poll for Transfer Complete event + */ + Status = XNandPs8_PollRegTimeout( + InstancePtr, + XNANDPS8_INTR_STS_OFFSET, + XNANDPS8_INTR_STS_TRANS_COMP_STS_EN_MASK, + XNANDPS8_INTR_POLL_TIMEOUT); + if (Status != XST_SUCCESS) { +#ifdef XNANDPS8_DEBUG + xil_printf("%s: Poll for xfer complete timeout\r\n", + __func__); +#endif + goto Out; + } + /* + * Clear Transfer Complete Interrupt in Interrupt Status Enable + * Register + */ + XNandPs8_WriteReg((InstancePtr)->Config.BaseAddress, + XNANDPS8_INTR_STS_EN_OFFSET, 0U); + + /* + * Clear Transfer Complete Interrupt in Interrupt Status Register + */ + XNandPs8_WriteReg((InstancePtr)->Config.BaseAddress, + XNANDPS8_INTR_STS_OFFSET, + XNANDPS8_INTR_STS_TRANS_COMP_STS_EN_MASK); + +Out: + return Status; +} + +/*****************************************************************************/ +/** +* +* This function changes clock frequency of flash controller. +* +* @param InstancePtr is a pointer to the XNandPs8 instance. +* @param ClockFreq is the clock frequency to change. +* +* @return +* None +* +* @note None +* +******************************************************************************/ +static void XNandPs8_ChangeClockFreq(XNandPs8 *InstancePtr, u32 ClockFreq) +{ + /* + * Not implemented + */ +} +/*****************************************************************************/ +/** +* +* This function changes the data interface and timing mode. +* +* @param InstancePtr is a pointer to the XNandPs8 instance. +* @param NewIntf is the new data interface. +* @param NewMode is the new timing mode. +* +* @return +* - XST_SUCCESS if successful. +* - XST_FAILURE if failed. +* +* @note None +* +******************************************************************************/ +s32 XNandPs8_ChangeTimingMode(XNandPs8 *InstancePtr, + XNandPs8_DataInterface NewIntf, + XNandPs8_TimingMode NewMode) +{ + s32 Status; + u32 Target; + u32 Index; + u32 Found = 0U; + u32 RegVal; + u8 Buf[4] = {0U}; + u32 *Feature = (u32 *)(void *)&Buf[0]; + const XNandPs8_TimingModeDesc *Desc = NULL; + + /* + * Assert the input arguments. + */ + Xil_AssertNonvoid(InstancePtr != NULL); + Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + + /* + * Get current data interface type and timing mode + */ + XNandPs8_DataInterface CurIntf = InstancePtr->DataInterface; + XNandPs8_TimingMode CurMode = InstancePtr->TimingMode; + /* + * Find the timing mode descriptor + */ + for (Index = 0U; Index < + (sizeof(TimingDesc)/sizeof(XNandPs8_TimingModeDesc)); Index++) { + Desc = &TimingDesc[Index]; + if ((Desc->CurDataIntf == CurIntf) && + (Desc->NewDataIntf == NewIntf) && + (Desc->NewTimingMode == NewMode)) { + Found = 1U; + break; + } + } + if ((!Found) != 0U) { +#ifdef XNANDPS8_DEBUG + xil_printf("%s: Timing mode desc not found\r\n",__func__); +#endif + Status = XST_FAILURE; + goto Out; + } + /* + * Check if the flash is in same mode + */ + if ((CurIntf == NewIntf) && (CurMode == NewMode)) { + Status = XST_SUCCESS; + goto Out; + } + + if ((CurIntf == NVDDR) && (NewIntf == SDR)) { + /* + * Change the clock frequency + */ + XNandPs8_ChangeClockFreq(InstancePtr, Desc->ClockFreq); + /* + * Issue Reset command + */ + for (Target = 0U; Target < InstancePtr->Geometry.NumTargets; + Target++) { + Status = XNandPs8_OnfiReset(InstancePtr, Target); + if (Status != XST_SUCCESS) { + goto Out; + } + /* + * Get Feature + */ + Status = XNandPs8_GetFeature(InstancePtr, Target, + 0x01U, &Buf[0]); + if (Status != XST_SUCCESS) { + goto Out; + } + /* + * Check SDR mode and Timing Mode 0 + */ + if (Feature != 0x0U) { + Status = XST_FAILURE; + goto Out; + } + } + InstancePtr->DataInterface = SDR; + InstancePtr->TimingMode = SDR0; + Status = XNandPs8_ChangeTimingMode(InstancePtr, NewIntf, + NewMode); + goto Out; + } + /* + * Set Feature + */ + for (Target = 0U; Target < InstancePtr->Geometry.NumTargets; + Target++) { + Status = XNandPs8_SetFeature(InstancePtr, Target, 0x01U, + (u8 *)&Desc->FeatureVal); + if (Status != XST_SUCCESS) { + goto Out; + } + } + /* + * Change the clock frequency + */ + if (Desc->ClockFreq > 0U) { + XNandPs8_ChangeClockFreq(InstancePtr, Desc->ClockFreq); + } + /* + * Get Feature + */ + for (Target = 0U; Target < InstancePtr->Geometry.NumTargets; + Target++) { + Status = XNandPs8_GetFeature(InstancePtr, Target, 0x01U, + &Buf[0]); + if (Status != XST_SUCCESS) { + goto Out; + } + /* + * Check if set_feature was successful + */ + if (*Feature != Desc->FeatureVal) { + Status = XST_FAILURE; + goto Out; + } + } + InstancePtr->DataInterface = NewIntf; + InstancePtr->TimingMode = NewMode; + /* + * Update Data Interface Register + */ + RegVal = ((NewMode % 6U) << ((NewIntf == NVDDR) ? 3U : 0U)) | + ((u32)NewIntf << XNANDPS8_DATA_INTF_DATA_INTF_SHIFT); + XNandPs8_WriteReg(InstancePtr->Config.BaseAddress, + XNANDPS8_DATA_INTF_OFFSET, RegVal); + + Status = XST_SUCCESS; +Out: + return Status; +} + +/*****************************************************************************/ +/** +* +* This function issues change read column and reads the data into buffer +* specified by user. +* +* @param InstancePtr is a pointer to the XNandPs8 instance. +* @param Target is the chip select value. +* @param Col is the coulmn address. +* @param PktSize is the number of bytes to read. +* @param PktCount is the number of transactions to read. +* @param Buf is the data buffer to fill in. +* +* @return +* - XST_SUCCESS if successful. +* - XST_FAILURE if failed. +* +* @note None +* +******************************************************************************/ +static s32 XNandPs8_ChangeReadColumn(XNandPs8 *InstancePtr, u32 Target, + u32 Col, u32 PktSize, u32 PktCount, + u8 *Buf) +{ + u32 AddrCycles = InstancePtr->Geometry.ColAddrCycles; + u32 BufRdCnt = 0U; + u32 *BufPtr = (u32 *)(void *)Buf; + s32 Status = XST_FAILURE; + u32 Index; + + /* + * Assert the input arguments. + */ + Xil_AssertNonvoid(Target < XNANDPS8_MAX_TARGETS); + Xil_AssertNonvoid(Buf != NULL); + + if (InstancePtr->DmaMode == MDMA) { + /* + * Enable DMA boundary Interrupt in Interrupt Status + * Enable Register + */ + XNandPs8_WriteReg((InstancePtr)->Config.BaseAddress, + XNANDPS8_INTR_STS_EN_OFFSET, + XNANDPS8_INTR_STS_EN_TRANS_COMP_STS_EN_MASK | + XNANDPS8_INTR_STS_EN_DMA_INT_STS_EN_MASK); + } else { + /* + * Enable Buffer Read Ready Interrupt in Interrupt Status + * Enable Register + */ + XNandPs8_WriteReg((InstancePtr)->Config.BaseAddress, + XNANDPS8_INTR_STS_EN_OFFSET, + XNANDPS8_INTR_STS_EN_BUFF_RD_RDY_STS_EN_MASK); + } + /* + * Program Command + */ + XNandPs8_Prepare_Cmd(InstancePtr, ONFI_CMD_CHNG_RD_COL1, + ONFI_CMD_CHNG_RD_COL2, 0U , 1U, (u8)AddrCycles); + /* + * Program Page Size + */ + XNandPs8_SetPageSize(InstancePtr); + /* + * Program Column, Page, Block address + */ + XNandPs8_SetPageColAddr(InstancePtr, 0U, (u16)Col); + /* + * Program Packet Size and Packet Count + */ + XNandPs8_SetPktSzCnt(InstancePtr, PktSize, PktCount); + /* + * Program DMA system address and DMA buffer boundary + */ + if (InstancePtr->DmaMode == MDMA) { + /* + * Invalidate the Data Cache + */ + Xil_DCacheInvalidateRange(Buf, (PktSize * PktCount)); +#ifdef __aarch64__ + XNandPs8_WriteReg(InstancePtr->Config.BaseAddress, + XNANDPS8_DMA_SYS_ADDR1_OFFSET, + (u32) (((INTPTR)Buf >> 32) & 0xFFFFFFFFU)); +#endif + XNandPs8_WriteReg(InstancePtr->Config.BaseAddress, + XNANDPS8_DMA_SYS_ADDR0_OFFSET, + (u32) ((INTPTR)(void *)Buf & 0xFFFFFFFFU)); + } + /* + * Set Bus Width + */ + XNandPs8_SetBusWidth(InstancePtr); + /* + * Program Memory Address Register2 for chip select + */ + XNandPs8_SelectChip(InstancePtr, Target); + /* + * Set Read command in Program Register + */ + XNandPs8_WriteReg((InstancePtr)->Config.BaseAddress, + XNANDPS8_PROG_OFFSET,XNANDPS8_PROG_RD_MASK); + + if (InstancePtr->DmaMode == MDMA) { + goto ReadDmaDone; + } + + while (BufRdCnt < PktCount) { + /* + * Poll for Buffer Read Ready event + */ + Status = XNandPs8_PollRegTimeout( + InstancePtr, + XNANDPS8_INTR_STS_OFFSET, + XNANDPS8_INTR_STS_BUFF_RD_RDY_STS_EN_MASK, + XNANDPS8_INTR_POLL_TIMEOUT); + if (Status != XST_SUCCESS) { +#ifdef XNANDPS8_DEBUG + xil_printf("%s: Poll for buf read ready timeout\r\n", + __func__); +#endif + goto Out; + } + /* + * Increment Buffer Read Interrupt Count + */ + BufRdCnt++; + + if (BufRdCnt == PktCount) { + /* + * Enable Transfer Complete Interrupt in Interrupt + * Status Enable Register + */ + XNandPs8_WriteReg((InstancePtr)->Config.BaseAddress, + XNANDPS8_INTR_STS_EN_OFFSET, + XNANDPS8_INTR_STS_EN_TRANS_COMP_STS_EN_MASK); + } else { + /* + * Clear Buffer Read Ready Interrupt in Interrupt + * Status Enable Register + */ + XNandPs8_WriteReg((InstancePtr)->Config.BaseAddress, + XNANDPS8_INTR_STS_EN_OFFSET, 0U); + + } + /* + * Clear Buffer Read Ready Interrupt in Interrupt Status + * Register + */ + XNandPs8_WriteReg((InstancePtr)->Config.BaseAddress, + XNANDPS8_INTR_STS_OFFSET, + XNANDPS8_INTR_STS_BUFF_RD_RDY_STS_EN_MASK); + /* + * Read Packet Data from Data Port Register + */ + for (Index = 0U; Index < (PktSize/4); Index++) { + BufPtr[Index] = XNandPs8_ReadReg( + InstancePtr->Config.BaseAddress, + XNANDPS8_BUF_DATA_PORT_OFFSET); + } + BufPtr += (PktSize/4U); + + if (BufRdCnt < PktCount) { + /* + * Enable Buffer Read Ready Interrupt in Interrupt + * Status Enable Register + */ + XNandPs8_WriteReg((InstancePtr)->Config.BaseAddress, + XNANDPS8_INTR_STS_EN_OFFSET, + XNANDPS8_INTR_STS_EN_BUFF_RD_RDY_STS_EN_MASK); + } else { + break; + } + } +ReadDmaDone: + /* + * Poll for Transfer Complete event + */ + Status = XNandPs8_PollRegTimeout( + InstancePtr, + XNANDPS8_INTR_STS_OFFSET, + XNANDPS8_INTR_STS_TRANS_COMP_STS_EN_MASK, + XNANDPS8_INTR_POLL_TIMEOUT); + if (Status != XST_SUCCESS) { +#ifdef XNANDPS8_DEBUG + xil_printf("%s: Poll for xfer complete timeout\r\n", + __func__); +#endif + goto Out; + } + /* + * Clear Transfer Complete Interrupt in Interrupt Status Enable + * Register + */ + XNandPs8_WriteReg((InstancePtr)->Config.BaseAddress, + XNANDPS8_INTR_STS_EN_OFFSET, 0U); + + /* + * Clear Transfer Complete Interrupt in Interrupt Status Register + */ + XNandPs8_WriteReg((InstancePtr)->Config.BaseAddress, + XNANDPS8_INTR_STS_OFFSET, + XNANDPS8_INTR_STS_TRANS_COMP_STS_EN_MASK); +Out: + return Status; +} + +/*****************************************************************************/ +/** +* +* This function issues change read column and reads the data into buffer +* specified by user. +* +* @param InstancePtr is a pointer to the XNandPs8 instance. +* @param Target is the chip select value. +* @param Col is the coulmn address. +* @param PktSize is the number of bytes to read. +* @param PktCount is the number of transactions to read. +* @param Buf is the data buffer to fill in. +* +* @return +* - XST_SUCCESS if successful. +* - XST_FAILURE if failed. +* +* @note None +* +******************************************************************************/ +static s32 XNandPs8_ChangeWriteColumn(XNandPs8 *InstancePtr, u32 Target, + u32 Col, u32 PktSize, u32 PktCount, + u8 *Buf) +{ + u32 AddrCycles = InstancePtr->Geometry.ColAddrCycles; + u32 BufWrCnt = 0U; + u32 *BufPtr = (u32 *)(void *)Buf; + s32 Status = XST_FAILURE; + OnfiCmdFormat OnfiCommand; + u32 Index; + + /* + * Assert the input arguments. + */ + Xil_AssertNonvoid(Target < XNANDPS8_MAX_TARGETS); + Xil_AssertNonvoid(Buf != NULL); + + if (PktCount == 0U) { + return XST_SUCCESS; + } + + if (InstancePtr->DmaMode == MDMA) { + /* + * Enable DMA boundary Interrupt in Interrupt Status + * Enable Register + */ + XNandPs8_WriteReg((InstancePtr)->Config.BaseAddress, + XNANDPS8_INTR_STS_EN_OFFSET, + XNANDPS8_INTR_STS_EN_TRANS_COMP_STS_EN_MASK | + XNANDPS8_INTR_STS_EN_DMA_INT_STS_EN_MASK); + } else { + /* + * Enable Buffer Write Ready Interrupt in Interrupt Status + * Enable Register + */ + XNandPs8_WriteReg((InstancePtr)->Config.BaseAddress, + XNANDPS8_INTR_STS_EN_OFFSET, + XNANDPS8_INTR_STS_EN_BUFF_WR_RDY_STS_EN_MASK); + } + /* + * Change write column hack + */ + OnfiCommand.Command1 = 0x85U; + OnfiCommand.Command2 = 0x10U; + XNandPs8_Prepare_Cmd(InstancePtr, OnfiCommand.Command1, + OnfiCommand.Command2, 0U , 0U, (u8)AddrCycles); + + /* + * Program Page Size + */ + XNandPs8_SetPageSize(InstancePtr); + /* + * Program Column, Page, Block address + */ + XNandPs8_SetPageColAddr(InstancePtr, 0U, (u16)Col); + /* + * Program Packet Size and Packet Count + */ + XNandPs8_SetPktSzCnt(InstancePtr, PktSize, PktCount); + /* + * Program DMA system address and DMA buffer boundary + */ + if (InstancePtr->DmaMode == MDMA) { +#ifdef __aarch64__ + XNandPs8_WriteReg(InstancePtr->Config.BaseAddress, + XNANDPS8_DMA_SYS_ADDR1_OFFSET, + (u32) (((INTPTR)Buf >> 32U) & 0xFFFFFFFFU)); +#endif + XNandPs8_WriteReg(InstancePtr->Config.BaseAddress, + XNANDPS8_DMA_SYS_ADDR0_OFFSET, + (u32) ((INTPTR)(void *)Buf & 0xFFFFFFFFU)); + } + /* + * Set Bus Width + */ + XNandPs8_SetBusWidth(InstancePtr); + /* + * Program Memory Address Register2 for chip select + */ + XNandPs8_SelectChip(InstancePtr, Target); + /* + * Set Page Program in Program Register + */ + XNandPs8_WriteReg((InstancePtr)->Config.BaseAddress, + XNANDPS8_PROG_OFFSET,XNANDPS8_PROG_CHNG_ROW_ADDR_END_MASK); + + if (InstancePtr->DmaMode == MDMA) { + goto WriteDmaDone; + } + + while (BufWrCnt < PktCount) { + /* + * Poll for Buffer Write Ready event + */ + Status = XNandPs8_PollRegTimeout( + InstancePtr, + XNANDPS8_INTR_STS_OFFSET, + XNANDPS8_INTR_STS_BUFF_WR_RDY_STS_EN_MASK, + XNANDPS8_INTR_POLL_TIMEOUT); + if (Status != XST_SUCCESS) { +#ifdef XNANDPS8_DEBUG + xil_printf("%s: Poll for buf write ready timeout\r\n", + __func__); +#endif + goto Out; + } + /* + * Increment Buffer Write Interrupt Count + */ + BufWrCnt++; + + if (BufWrCnt == PktCount) { + /* + * Enable Transfer Complete Interrupt in Interrupt + * Status Enable Register + */ + XNandPs8_WriteReg((InstancePtr)->Config.BaseAddress, + XNANDPS8_INTR_STS_EN_OFFSET, + XNANDPS8_INTR_STS_EN_TRANS_COMP_STS_EN_MASK); + } else { + /* + * Clear Buffer Write Ready Interrupt in Interrupt + * Status Enable Register + */ + XNandPs8_WriteReg((InstancePtr)->Config.BaseAddress, + XNANDPS8_INTR_STS_EN_OFFSET, 0U); + } + /* + * Clear Buffer Write Ready Interrupt in Interrupt Status + * Register + */ + XNandPs8_WriteReg((InstancePtr)->Config.BaseAddress, + XNANDPS8_INTR_STS_OFFSET, + XNANDPS8_INTR_STS_BUFF_WR_RDY_STS_EN_MASK); + /* + * Write Packet Data to Data Port Register + */ + for (Index = 0U; Index < (PktSize/4U); Index++) { + XNandPs8_WriteReg(InstancePtr->Config.BaseAddress, + XNANDPS8_BUF_DATA_PORT_OFFSET, + BufPtr[Index]); + } + BufPtr += (PktSize/4U); + + if (BufWrCnt < PktCount) { + /* + * Enable Buffer Write Ready Interrupt in Interrupt + * Status Enable Register + */ + XNandPs8_WriteReg((InstancePtr)->Config.BaseAddress, + XNANDPS8_INTR_STS_EN_OFFSET, + XNANDPS8_INTR_STS_EN_BUFF_WR_RDY_STS_EN_MASK); + } else { + break; + } + } +WriteDmaDone: + /* + * Poll for Transfer Complete event + */ + Status = XNandPs8_PollRegTimeout( + InstancePtr, + XNANDPS8_INTR_STS_OFFSET, + XNANDPS8_INTR_STS_TRANS_COMP_STS_EN_MASK, + XNANDPS8_INTR_POLL_TIMEOUT); + if (Status != XST_SUCCESS) { +#ifdef XNANDPS8_DEBUG + xil_printf("%s: Poll for xfer complete timeout\r\n", + __func__); +#endif + goto Out; + } + /* + * Clear Transfer Complete Interrupt in Interrupt Status Enable + * Register + */ + XNandPs8_WriteReg((InstancePtr)->Config.BaseAddress, + XNANDPS8_INTR_STS_EN_OFFSET, 0U); + + /* + * Clear Transfer Complete Interrupt in Interrupt Status Register + */ + XNandPs8_WriteReg((InstancePtr)->Config.BaseAddress, + XNANDPS8_INTR_STS_OFFSET, + XNANDPS8_INTR_STS_TRANS_COMP_STS_EN_MASK); + +Out: + return Status; +} + +/*****************************************************************************/ +/** +* +* This function initializes extended parameter page ECC information. +* +* @param InstancePtr is a pointer to the XNandPs8 instance. +* @param ExtPrm is the Extended parameter page buffer. +* +* @return +* - XST_SUCCESS if successful. +* - XST_FAILURE if failed. +* +* @note None +* +******************************************************************************/ +static s32 XNandPs8_InitExtEcc(XNandPs8 *InstancePtr, OnfiExtPrmPage *ExtPrm) +{ + s32 Status = XST_FAILURE; + u32 Index; + u32 SectionType; + u32 SectionLen; + u32 Offset = 0U; + u32 Found = 0U; + OnfiExtEccBlock *EccBlock; + + if (ExtPrm->Section0Type != 0x2U) { + Offset += (u32)ExtPrm->Section0Len; + if (ExtPrm->Section1Type != 0x2U) { +#ifdef XNANDPS8_DEBUG + xil_printf("%s: Extended ECC section not found\r\n",__func__); +#endif + Status = XST_FAILURE; + } else { + Found = 1U; + } + } else { + Found = 1U; + } + + if (Found != 0U) { + EccBlock = (OnfiExtEccBlock *)&ExtPrm->SectionData[Offset]; + Xil_AssertNonvoid(EccBlock != NULL); + if (EccBlock->CodeWordSize == 0U) { + Status = XST_FAILURE; + } else { + InstancePtr->Geometry.NumBitsECC = + EccBlock->NumBitsEcc; + InstancePtr->Geometry.EccCodeWordSize = + (u32)EccBlock->CodeWordSize; + Status = XST_SUCCESS; + } + } + return Status; +} + +/*****************************************************************************/ +/** +* +* This function prepares command to be written into command register. +* +* @param InstancePtr is a pointer to the XNandPs8 instance. +* @param Cmd1 is the first Onfi Command. +* @param Cmd1 is the second Onfi Command. +* @param EccState is the flag to set Ecc State. +* @param DmaMode is the flag to set DMA mode. +* +* @return +* None +* +* @note None +* +******************************************************************************/ +void XNandPs8_Prepare_Cmd(XNandPs8 *InstancePtr, u8 Cmd1, u8 Cmd2, u8 EccState, + u8 DmaMode, u8 AddrCycles) +{ + u32 RegValue = 0U; + + Xil_AssertVoid(InstancePtr != NULL); + + RegValue = (u32)Cmd1 | (((u32)Cmd2 << (u32)XNANDPS8_CMD_CMD2_SHIFT) & + (u32)XNANDPS8_CMD_CMD2_MASK); + + if ((EccState != 0U) && (InstancePtr->EccMode == HWECC)) { + RegValue |= 1U << XNANDPS8_CMD_ECC_ON_SHIFT; + } + + if ((DmaMode != 0U) && (InstancePtr->DmaMode == MDMA)) { + RegValue |= MDMA << XNANDPS8_CMD_DMA_EN_SHIFT; + } + + if (AddrCycles != 0U) { + RegValue |= (u32)AddrCycles << + (u32)XNANDPS8_CMD_ADDR_CYCLES_SHIFT; + } + + XNandPs8_WriteReg((InstancePtr)->Config.BaseAddress, + XNANDPS8_CMD_OFFSET, RegValue); +} diff --git a/XilinxProcessorIPLib/drivers/nandps8_v2_0/src/xnandps8.h b/XilinxProcessorIPLib/drivers/nandps8_v2_0/src/xnandps8.h new file mode 100755 index 00000000..2473bccf --- /dev/null +++ b/XilinxProcessorIPLib/drivers/nandps8_v2_0/src/xnandps8.h @@ -0,0 +1,568 @@ +/****************************************************************************** +* +* Copyright (C) 2014 Xilinx, Inc. All rights reserved. +* +* This file contains confidential and proprietary information of Xilinx, Inc. +* and is protected under U.S. and international copyright and other +* intellectual property laws. +* +* DISCLAIMER +* This disclaimer is not a license and does not grant any rights to the +* materials distributed herewith. Except as otherwise provided in a valid +* license issued to you by Xilinx, and to the maximum extent permitted by +* applicable law: (1) THESE MATERIALS ARE MADE AVAILABLE "AS IS" AND WITH ALL +* FAULTS, AND XILINX HEREBY DISCLAIMS ALL WARRANTIES AND CONDITIONS, EXPRESS, +* IMPLIED, OR STATUTORY, INCLUDING BUT NOT LIMITED TO WARRANTIES OF +* MERCHANTABILITY, NON- INFRINGEMENT, OR FITNESS FOR ANY PARTICULAR PURPOSE +* and +* (2) Xilinx shall not be liable (whether in contract or tort, including +* negligence, or under any other theory of liability) for any loss or damage +* of any kind or nature related to, arising under or in connection with these +* materials, including for any direct, or any indirect, special, incidental, +* or consequential loss or damage (including loss of data, profits, +* goodwill, or any type of loss or damage suffered as a result of any +* action brought by a third party) even if such damage or loss was +* reasonably foreseeable or Xilinx had been advised of the possibility +* of the same. +* +* CRITICAL APPLICATIONS +* Xilinx products are not designed or intended to be fail- safe, or for use +* in any application requiring fail-safe performance, such as life-support +* or safety devices or systems, Class III medical devices, nuclear +* facilities, applications related to the deployment of airbags, or any +* other applications that could lead to death, personal injury, or severe +* property or environmental damage (individually and collectively, +* "Critical Applications"). Customer assumes the sole risk and liability +* of any use of Xilinx products in Critical Applications, subject only to +* applicable laws and regulations governing limitations on product liability. +* +* THIS COPYRIGHT NOTICE AND DISCLAIMER MUST BE RETAINED AS PART +* OF THIS FILE AT ALL TIMES. +* +******************************************************************************/ + +/*****************************************************************************/ +/** +* +* @file xnandps8.h +* +* This file implements a driver to support Arasan NAND controller +* present in Zynq Ultrascale Mp. +* +* Driver Initialization +* +* The function call XNandPs8_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 XNandPs8 instance with the device specific data. +* +* Device Geometry +* +* 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-bit operational mode +* - Read, Write, and Erase operation +* +* Write Operation +* +* 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. +* +* Read Operation +* +* 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. +* +* Erase Operation +* +* 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. +* +* @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. +* +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who    Date	   Changes
+* ----- ----   ----------  -----------------------------------------------
+* 1.0   nm     05/06/2014  First release
+* 2.0   sb     11/04/2014  Removed Null checks for Buffer passed
+*			   as parameter to Read API's
+*			   - XNandPs8_Read()
+*			   - XNandPs8_ReadPage
+*			   Modified
+*			   - XNandPs8_SetFeature()
+*			   - XNandPs8_GetFeature()
+*			   and made them public.
+*			   Removed Failure Return for BCF Error check in
+*			   XNandPs8_ReadPage() and added BCH_Error counter
+*			   in the instance pointer structure.
+* 			   Added XNandPs8_Prepare_Cmd API
+*			   Replaced
+*			   - XNandPs8_IntrStsEnable
+*			   - XNandPs8_IntrStsClear
+*			   - XNandPs8_IntrClear
+*			   - XNandPs8_SetProgramReg
+*			   with XNandPs8_WriteReg call
+*			   Modified xnandps8.c file API's with above changes.
+* 			   Corrected the program command for Set Feature API.
+*			   Modified
+*			   - XNandPs8_OnfiReadStatus
+*			   - XNandPs8_GetFeature
+*			   - XNandPs8_SetFeature
+*			   to add support for DDR mode.
+*			   Changed Convention for SLC/MLC
+*			   SLC --> HAMMING
+*			   MLC --> BCH
+*			   SlcMlc --> IsBCH
+*			   Added support for writing BBT signature and version
+*			   in page section by enabling XNANDPS8_BBT_NO_OOB.
+*			   Removed extra DMA mode initialization from
+*			   the XNandPs8_CfgInitialize API.
+*			   Modified
+*			   - XNandPs8_SetEccAddrSize
+*			   ECC address now is calculated based upon the
+*			   size of spare area
+* 
+* +******************************************************************************/ + +#ifndef XNANDPS8_H /* prevent circular inclusions */ +#define XNANDPS8_H /* by using protection macros */ + +#ifdef __cplusplus +extern "C" { +#endif + +/***************************** Include Files *********************************/ +#include "xil_types.h" +#include +#include "xstatus.h" +#include "xil_assert.h" +#include "xnandps8_hw.h" +#include "xnandps8_onfi.h" +#include "xil_cache.h" +/************************** Constant Definitions *****************************/ + +#define XNANDPS8_DEBUG +#define RTL_3_1_FIX +#define RTL_3_1_DRIVER_WORKAROUND + +#define XNANDPS8_MAX_TARGETS 1U /**< ce_n0, ce_n1 */ +#define XNANDPS8_MAX_PKT_SIZE 0x7FFU /**< Max packet size */ +#define XNANDPS8_MAX_PKT_COUNT 0xFFFU /**< Max packet count */ + +#define XNANDPS8_PAGE_SIZE_512 512U /**< 512 bytes page */ +#define XNANDPS8_PAGE_SIZE_2K 2048U /**< 2K bytes page */ +#define XNANDPS8_PAGE_SIZE_4K 4096U /**< 4K bytes page */ +#define XNANDPS8_PAGE_SIZE_8K 8192U /**< 8K bytes page */ +#define XNANDPS8_PAGE_SIZE_16K 16384U /**< 16K bytes page */ +#define XNANDPS8_PAGE_SIZE_1K_16BIT 1024U /**< 16-bit 2K bytes page */ +#define XNANDPS8_MAX_PAGE_SIZE 16384U /**< Max page size supported */ + +#define XNANDPS8_BUS_WIDTH_8 0U /**< 8-bit bus width */ +#define XNANDPS8_BUS_WIDTH_16 1U /**< 16-bit bus width */ + +#define XNANDPS8_HAMMING 0x1U /**< Hamming Flash */ +#define XNANDPS8_BCH 0x2U /**< BCH Flash */ + +#define XNANDPS8_MAX_BLOCKS 32768U /**< Max number of Blocks */ +#define XNANDPS8_MAX_SPARE_SIZE 0x800U /**< Max spare bytes of a NAND + flash page of 16K */ + +#define XNANDPS8_INTR_POLL_TIMEOUT 10000U + +#define SDR_CLK ((u16)100U * (u16)1000U * (u16)1000U) +#define NVDDR_CLK_0 ((u16)20U * (u16)1000U * (u16)1000U) +#define NVDDR_CLK_1 ((u16)33U * (u16)1000U * (u16)1000U) +#define NVDDR_CLK_2 ((u16)50U * (u16)1000U * (u16)1000U) +#define NVDDR_CLK_3 ((u16)66U * (u16)1000U * (u16)1000U) +#define NVDDR_CLK_4 ((u16)83U * (u16)1000U * (u16)1000U) +#define NVDDR_CLK_5 ((u16)100U * (u16)1000U * (u16)1000U) +//#define XNANDPS8_BBT_NO_OOB + +/** + * The XNandPs8_Config structure contains configuration information for NAND + * controller. + */ +typedef struct { + u16 DeviceId; /**< Instance ID of NAND flash controller */ + u32 BaseAddress; /**< Base address of NAND flash controller */ +} XNandPs8_Config; + +/** + * The XNandPs8_DataInterface enum contains flash operating mode. + */ +typedef enum { + SDR = 0U, /**< Single Data Rate */ + NVDDR /**< Double Data Rate */ +} XNandPs8_DataInterface; + +/** + * XNandPs8_TimingMode enum contains timing modes. + */ +typedef enum { + SDR0 = 0U, + SDR1, + SDR2, + SDR3, + SDR4, + SDR5, + NVDDR0, + NVDDR1, + NVDDR2, + NVDDR3, + NVDDR4, + NVDDR5 +} XNandPs8_TimingMode; + +/** + * The XNandPs8_SWMode enum contains the driver operating mode. + */ +typedef enum { + POLLING = 0, /**< Polling */ + INTERRUPT /**< Interrupt */ +} XNandPs8_SWMode; + +/** + * The XNandPs8_DmaMode enum contains the controller MDMA mode. + */ +typedef enum { + PIO = 0, /**< PIO Mode */ + SDMA, /**< SDMA Mode */ + MDMA /**< MDMA Mode */ +} XNandPs8_DmaMode; + +/** + * The XNandPs8_EccMode enum contains ECC functionality. + */ +typedef enum { + NONE = 0, + HWECC, + EZNAND, + ONDIE +} XNandPs8_EccMode; + +typedef struct { + XNandPs8_DataInterface CurDataIntf; + XNandPs8_DataInterface NewDataIntf; + XNandPs8_TimingMode NewTimingMode; + u32 ClockFreq; + u32 FeatureVal; +} XNandPs8_TimingModeDesc; + +/** + * Bad block table descriptor + */ +typedef struct { + u32 PageOffset[XNANDPS8_MAX_TARGETS]; + /**< 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[XNANDPS8_MAX_TARGETS]; + /**< BBT version */ + u32 Valid; /**< BBT descriptor is valid or not */ +} XNandPs8_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 */ +} XNandPs8_BadBlockPattern; + +/** + * The XNandPs8_Geometry structure contains the ONFI geometry information. + */ +typedef struct { + /* + * Parameter page information + */ + u32 BytesPerPage; /**< Number of bytes per page */ + u16 SpareBytesPerPage; /**< Number of spare bytes per page */ + u32 PagesPerBlock; /**< Number of pages per block */ + u32 BlocksPerLun; /**< Number of blocks per LUN */ + u8 NumLuns; /**< Number of LUN's */ + u8 RowAddrCycles; /**< Row address cycles */ + u8 ColAddrCycles; /**< Column address cycles */ + u8 NumBitsPerCell; /**< Number of bits per cell (Hamming/BCH) */ + u8 NumBitsECC; /**< Number of bits ECC correctability */ + u32 EccCodeWordSize; /**< ECC codeword size */ + /* + * Driver specific information + */ + u32 BlockSize; /**< Block size */ + u32 NumTargetPages; /**< Total number of pages in a Target */ + u32 NumTargetBlocks; /**< Total number of blocks in a Target */ + u64 TargetSize; /**< Target size in bytes */ + u8 NumTargets; /**< Number of targets present */ + u32 NumPages; /**< Total number of pages */ + u32 NumBlocks; /**< Total number of blocks */ + u64 DeviceSize; /**< Total flash size in bytes */ +} XNandPs8_Geometry; + +/** + * The XNandPs8_Features structure contains the ONFI features information. + */ +typedef struct { + u32 BusWidth; + u32 NvDdr; + u32 EzNand; + u32 OnDie; + u32 ExtPrmPage; +} XNandPs8_Features; + +/** + * The XNandPs8_EccMatrix structure contains ECC features information. + */ +typedef struct { + u16 PageSize; + u16 CodeWordSize; + u8 NumEccBits; + u8 IsBCH; + u16 EccAddr; + u16 EccSize; +} XNandPs8_EccMatrix; + +/** + * The XNandPs8_EccCfg structure contains ECC configuration. + */ +typedef struct { + u16 EccAddr; + u16 EccSize; + u16 CodeWordSize; + u8 NumEccBits; + u8 IsBCH; +} XNandPs8_EccCfg; + +/** + * The XNandPs8 structure contains the driver instance data. The user is + * required to allocate a variable of this type for the NAND controller. + * A pointer to a variable of this type is then passed to the driver API + * functions. + */ +typedef struct { + u32 IsReady; /**< Device is initialized and ready */ + XNandPs8_Config Config; + u8 BCH_Error_Status; + XNandPs8_DataInterface DataInterface; + XNandPs8_TimingMode TimingMode; + XNandPs8_SWMode Mode; /**< Driver operating mode */ + XNandPs8_DmaMode DmaMode; /**< MDMA mode enabled/disabled */ + XNandPs8_EccMode EccMode; /**< ECC Mode */ + XNandPs8_EccCfg EccCfg; /**< ECC configuration */ + XNandPs8_Geometry Geometry; /**< Flash geometry */ + XNandPs8_Features Features; /**< ONFI features */ + u8 PartialDataBuf[XNANDPS8_MAX_PAGE_SIZE] __attribute__ ((aligned(64))); + /**< Partial read/write buffer */ + /* Bad block table definitions */ + XNandPs8_BbtDesc BbtDesc; /**< Bad block table descriptor */ + XNandPs8_BbtDesc BbtMirrorDesc; /**< Mirror BBT descriptor */ + XNandPs8_BadBlockPattern BbPattern; /**< Bad block pattern to + search */ + u8 Bbt[XNANDPS8_MAX_BLOCKS >> 2]; /**< Bad block table array */ +} XNandPs8; + +/******************* Macro Definitions (Inline Functions) *******************/ + +/*****************************************************************************/ +/** + * This macro sets the bitmask in the register. + * + * @param InstancePtr is a pointer to the XNandPs8 instance of the + * controller. + * @param RegOffset is the register offset. + * @param BitMask is the bitmask. + * + * @note C-style signature: + * void XNandPs8_SetBits(XNandPs8 *InstancePtr, u32 RegOffset, + * u32 BitMask) + * + *****************************************************************************/ +#define XNandPs8_SetBits(InstancePtr, RegOffset, BitMask) \ + XNandPs8_WriteReg((InstancePtr)->Config.BaseAddress, \ + (RegOffset), \ + ((u32)(XNandPs8_ReadReg((InstancePtr)->Config.BaseAddress, \ + (RegOffset)) | (BitMask)))) + +/*****************************************************************************/ +/** + * This macro clears the bitmask in the register. + * + * @param InstancePtr is a pointer to the XNandPs8 instance of the + * controller. + * @param RegOffset is the register offset. + * @param BitMask is the bitmask. + * + * @note C-style signature: + * void XNandPs8_ClrBits(XNandPs8 *InstancePtr, u32 RegOffset, + * u32 BitMask) + * + *****************************************************************************/ +#define XNandPs8_ClrBits(InstancePtr, RegOffset, BitMask) \ + XNandPs8_WriteReg((InstancePtr)->Config.BaseAddress, \ + (RegOffset), \ + ((u32)(XNandPs8_ReadReg((InstancePtr)->Config.BaseAddress, \ + (RegOffset)) & ~(BitMask)))) + +/*****************************************************************************/ +/** + * This macro clears and updates the bitmask in the register. + * + * @param InstancePtr is a pointer to the XNandPs8 instance of the + * controller. + * @param RegOffset is the register offset. + * @param Mask is the bitmask. + * @param Value is the register value to write. + * + * @note C-style signature: + * void XNandPs8_ReadModifyWrite(XNandPs8 *InstancePtr, + * u32 RegOffset, u32 Mask, u32 Val) + * + *****************************************************************************/ +#define XNandPs8_ReadModifyWrite(InstancePtr, RegOffset, Mask, Value) \ + XNandPs8_WriteReg((InstancePtr)->Config.BaseAddress, \ + (RegOffset), \ + ((u32)((u32)(XNandPs8_ReadReg((InstancePtr)->Config.BaseAddress,\ + (u32)(RegOffset)) & (u32)(~(Mask))) | (u32)(Value)))) + +/*****************************************************************************/ +/** + * This macro enables bitmask in Interrupt Signal Enable register. + * + * @param InstancePtr is a pointer to the XNandPs8 instance of the + * controller. + * @param Mask is the bitmask. + * + * @note C-style signature: + * void XNandPs8_IntrSigEnable(XNandPs8 *InstancePtr, u32 Mask) + * + *****************************************************************************/ +#define XNandPs8_IntrSigEnable(InstancePtr, Mask) \ + XNandPs8_SetBits((InstancePtr), \ + XNANDPS8_INTR_SIG_EN_OFFSET, \ + (Mask)) + +/*****************************************************************************/ +/** + * This macro clears bitmask in Interrupt Signal Enable register. + * + * @param InstancePtr is a pointer to the XNandPs8 instance of the + * controller. + * @param Mask is the bitmask. + * + * @note C-style signature: + * void XNandPs8_IntrSigClear(XNandPs8 *InstancePtr, u32 Mask) + * + *****************************************************************************/ +#define XNandPs8_IntrSigClear(InstancePtr, Mask) \ + XNandPs8_ClrBits((InstancePtr), \ + XNANDPS8_INTR_SIG_EN_OFFSET, \ + (Mask)) + +/*****************************************************************************/ +/** + * This macro enables bitmask in Interrupt Status Enable register. + * + * @param InstancePtr is a pointer to the XNandPs8 instance of the + * controller. + * @param Mask is the bitmask. + * + * @note C-style signature: + * void XNandPs8_IntrStsEnable(XNandPs8 *InstancePtr, u32 Mask) + * + *****************************************************************************/ +#define XNandPs8_IntrStsEnable(InstancePtr, Mask) \ + XNandPs8_SetBits((InstancePtr), \ + XNANDPS8_INTR_STS_EN_OFFSET, \ + (Mask)) + + +/************************** Function Prototypes *****************************/ + +s32 XNandPs8_CfgInitialize(XNandPs8 *InstancePtr, XNandPs8_Config *ConfigPtr, + u32 EffectiveAddr); + +s32 XNandPs8_Erase(XNandPs8 *InstancePtr, u64 Offset, u64 Length); + +s32 XNandPs8_Write(XNandPs8 *InstancePtr, u64 Offset, u64 Length, + u8 *SrcBuf); + +s32 XNandPs8_Read(XNandPs8 *InstancePtr, u64 Offset, u64 Length, + u8 *DestBuf); + +s32 XNandPs8_EraseBlock(XNandPs8 *InstancePtr, u32 Target, u32 Block); + +s32 XNandPs8_WriteSpareBytes(XNandPs8 *InstancePtr, u32 Page, u8 *Buf); + +s32 XNandPs8_ReadSpareBytes(XNandPs8 *InstancePtr, u32 Page, u8 *Buf); + +s32 XNandPs8_ChangeTimingMode(XNandPs8 *InstancePtr, + XNandPs8_DataInterface NewIntf, + XNandPs8_TimingMode NewMode); + +s32 XNandPs8_GetFeature(XNandPs8 *InstancePtr, u32 Target, u8 Feature, + u8 *Buf); + +s32 XNandPs8_SetFeature(XNandPs8 *InstancePtr, u32 Target, u8 Feature, + u8 *Buf); +void XNandPs8_EnableDmaMode(XNandPs8 *InstancePtr); + +void XNandPs8_DisableDmaMode(XNandPs8 *InstancePtr); + +void XNandPs8_EnableEccMode(XNandPs8 *InstancePtr); + +void XNandPs8_DisableEccMode(XNandPs8 *InstancePtr); + +void XNandPs8_Prepare_Cmd(XNandPs8 *InstancePtr, u8 Cmd1, u8 Cmd2, u8 EccState, + u8 DmaMode, u8 AddrCycles); + +/* + * XNandPs8_LookupConfig in xnandps8_sinit.c + */ +XNandPs8_Config *XNandPs8_LookupConfig(u16 DeviceID); + + +#ifdef __cplusplus +} +#endif + +#endif /* XNANDPS8_H end of protection macro */ diff --git a/XilinxProcessorIPLib/drivers/nandps8_v2_0/src/xnandps8_bbm.c b/XilinxProcessorIPLib/drivers/nandps8_v2_0/src/xnandps8_bbm.c new file mode 100755 index 00000000..e37153dc --- /dev/null +++ b/XilinxProcessorIPLib/drivers/nandps8_v2_0/src/xnandps8_bbm.c @@ -0,0 +1,1051 @@ +/****************************************************************************** +* +* Copyright (C) 2014 Xilinx, Inc. All rights reserved. +* +* This file contains confidential and proprietary information of Xilinx, Inc. +* and is protected under U.S. and international copyright and other +* intellectual property laws. +* +* DISCLAIMER +* This disclaimer is not a license and does not grant any rights to the +* materials distributed herewith. Except as otherwise provided in a valid +* license issued to you by Xilinx, and to the maximum extent permitted by +* applicable law: (1) THESE MATERIALS ARE MADE AVAILABLE "AS IS" AND WITH ALL +* FAULTS, AND XILINX HEREBY DISCLAIMS ALL WARRANTIES AND CONDITIONS, EXPRESS, +* IMPLIED, OR STATUTORY, INCLUDING BUT NOT LIMITED TO WARRANTIES OF +* MERCHANTABILITY, NON- INFRINGEMENT, OR FITNESS FOR ANY PARTICULAR PURPOSE +* and +* (2) Xilinx shall not be liable (whether in contract or tort, including +* negligence, or under any other theory of liability) for any loss or damage +* of any kind or nature related to, arising under or in connection with these +* materials, including for any direct, or any indirect, special, incidental, +* or consequential loss or damage (including loss of data, profits, +* goodwill, or any type of loss or damage suffered as a result of any +* action brought by a third party) even if such damage or loss was +* reasonably foreseeable or Xilinx had been advised of the possibility +* of the same. +* +* CRITICAL APPLICATIONS +* Xilinx products are not designed or intended to be fail- safe, or for use +* in any application requiring fail-safe performance, such as life-support +* or safety devices or systems, Class III medical devices, nuclear +* facilities, applications related to the deployment of airbags, or any +* other applications that could lead to death, personal injury, or severe +* property or environmental damage (individually and collectively, +* "Critical Applications"). Customer assumes the sole risk and liability +* of any use of Xilinx products in Critical Applications, subject only to +* applicable laws and regulations governing limitations on product liability. +* +* THIS COPYRIGHT NOTICE AND DISCLAIMER MUST BE RETAINED AS PART +* OF THIS FILE AT ALL TIMES. +* +******************************************************************************/ + +/*****************************************************************************/ +/** +* +* @file xnandps8_bbm.c +* This file implements the Bad Block Management (BBM) functionality. +* See xnandps8_bbm.h for more details. +* +* @note None +* +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who    Date        Changes
+* ----- ----   ----------  -----------------------------------------------
+* 1.0   nm     05/06/2014  First release
+* 2.0   sb     11/04/2014  Added support for writing BBT signature and version
+*			   in page section by enabling XNANDPS8_BBT_NO_OOB.
+* 
+* +******************************************************************************/ + +/***************************** Include Files *********************************/ +#include /**< For memcpy and memset */ +#include "xil_types.h" +#include "xnandps8.h" +#include "xnandps8_bbm.h" + +/************************** Constant Definitions *****************************/ + +/**************************** Type Definitions *******************************/ + +/***************** Macros (Inline Functions) Definitions *********************/ + +/************************** Function Prototypes ******************************/ +static s32 XNandPs8_ReadBbt(XNandPs8 *InstancePtr, u32 Target); + +static s32 XNandPs8_SearchBbt(XNandPs8 *InstancePtr, XNandPs8_BbtDesc *Desc, + u32 Target); + +static void XNandPs8_CreateBbt(XNandPs8 *InstancePtr, u32 Target); + +static void XNandPs8_ConvertBbt(XNandPs8 *InstancePtr, u8 *Buf, u32 Target); + +static s32 XNandPs8_WriteBbt(XNandPs8 *InstancePtr, XNandPs8_BbtDesc *Desc, + XNandPs8_BbtDesc *MirrorDesc, u32 Target); + +static s32 XNandPs8_MarkBbt(XNandPs8* InstancePtr, XNandPs8_BbtDesc *Desc, + u32 Target); + +static s32 XNandPs8_UpdateBbt(XNandPs8 *InstancePtr, u32 Target); + +/************************** 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 XNandPs8 instance. +* +* @return +* - NONE +* +******************************************************************************/ +void XNandPs8_InitBbtDesc(XNandPs8 *InstancePtr) +{ + u32 Index; + + Xil_AssertVoid(InstancePtr != NULL); + Xil_AssertVoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + + /* + * Initialize primary Bad Block Table(BBT) + */ + for (Index = 0U; Index < XNANDPS8_MAX_TARGETS; Index++) { + InstancePtr->BbtDesc.PageOffset[Index] = + XNANDPS8_BBT_DESC_PAGE_OFFSET; + } + if (InstancePtr->EccMode == ONDIE) { + InstancePtr->BbtDesc.SigOffset = XNANDPS8_ONDIE_SIG_OFFSET; + InstancePtr->BbtDesc.VerOffset = XNANDPS8_ONDIE_VER_OFFSET; + } else { + InstancePtr->BbtDesc.SigOffset = XNANDPS8_BBT_DESC_SIG_OFFSET; + InstancePtr->BbtDesc.VerOffset = XNANDPS8_BBT_DESC_VER_OFFSET; + } + InstancePtr->BbtDesc.SigLength = XNANDPS8_BBT_DESC_SIG_LEN; + InstancePtr->BbtDesc.MaxBlocks = XNANDPS8_BBT_DESC_MAX_BLOCKS; + (void)strcpy(&InstancePtr->BbtDesc.Signature[0], "Bbt0"); + for (Index = 0U; Index < XNANDPS8_MAX_TARGETS; Index++) { + InstancePtr->BbtDesc.Version[Index] = 0U; + } + InstancePtr->BbtDesc.Valid = 0U; + + /* + * Initialize mirror Bad Block Table(BBT) + */ + for (Index = 0U; Index < XNANDPS8_MAX_TARGETS; Index++) { + InstancePtr->BbtMirrorDesc.PageOffset[Index] = + XNANDPS8_BBT_DESC_PAGE_OFFSET; + } + if (InstancePtr->EccMode == ONDIE) { + InstancePtr->BbtMirrorDesc.SigOffset = + XNANDPS8_ONDIE_SIG_OFFSET; + InstancePtr->BbtMirrorDesc.VerOffset = + XNANDPS8_ONDIE_VER_OFFSET; + } else { + InstancePtr->BbtMirrorDesc.SigOffset = + XNANDPS8_BBT_DESC_SIG_OFFSET; + InstancePtr->BbtMirrorDesc.VerOffset = + XNANDPS8_BBT_DESC_VER_OFFSET; + } + InstancePtr->BbtMirrorDesc.SigLength = XNANDPS8_BBT_DESC_SIG_LEN; + InstancePtr->BbtMirrorDesc.MaxBlocks = XNANDPS8_BBT_DESC_MAX_BLOCKS; + (void)strcpy(&InstancePtr->BbtMirrorDesc.Signature[0], "1tbB"); + for (Index = 0U; Index < XNANDPS8_MAX_TARGETS; Index++) { + InstancePtr->BbtMirrorDesc.Version[Index] = 0U; + } + InstancePtr->BbtMirrorDesc.Valid = 0U; + + /* + * Initialize Bad block search pattern structure + */ + if (InstancePtr->Geometry.BytesPerPage > 512U) { + /* For flash page size > 512 bytes */ + InstancePtr->BbPattern.Options = XNANDPS8_BBT_SCAN_2ND_PAGE; + InstancePtr->BbPattern.Offset = + XNANDPS8_BB_PATTERN_OFFSET_LARGE_PAGE; + InstancePtr->BbPattern.Length = + XNANDPS8_BB_PATTERN_LENGTH_LARGE_PAGE; + } else { + InstancePtr->BbPattern.Options = XNANDPS8_BBT_SCAN_2ND_PAGE; + InstancePtr->BbPattern.Offset = + XNANDPS8_BB_PATTERN_OFFSET_SMALL_PAGE; + InstancePtr->BbPattern.Length = + XNANDPS8_BB_PATTERN_LENGTH_SMALL_PAGE; + } + for(Index = 0U; Index < XNANDPS8_BB_PATTERN_LENGTH_LARGE_PAGE; Index++) { + InstancePtr->BbPattern.Pattern[Index] = XNANDPS8_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 XNandPs8 instance. +* +* @return +* - NONE +* +******************************************************************************/ +static void XNandPs8_CreateBbt(XNandPs8 *InstancePtr, u32 Target) +{ + u32 BlockIndex; + u32 PageIndex; + u32 Length; + u32 BlockOffset; + u8 BlockShift; + u32 NumPages; + u32 Page; + u8 Buf[XNANDPS8_MAX_SPARE_SIZE] __attribute__ ((aligned(64))) = {0U}; + u32 StartBlock = Target * InstancePtr->Geometry.NumTargetBlocks; + u32 NumBlocks = InstancePtr->Geometry.NumTargetBlocks; + s32 Status; + + /* + * Number of pages to search for bad block pattern + */ + if ((InstancePtr->BbPattern.Options & XNANDPS8_BBT_SCAN_2ND_PAGE) != 0U) + { + NumPages = 2U; + } else { + NumPages = 1U; + } + /* + * Scan all the blocks for factory marked bad blocks + */ + for(BlockIndex = StartBlock; BlockIndex < (StartBlock + NumBlocks); + BlockIndex++) { + /* + * Block offset in Bad Block Table(BBT) entry + */ + BlockOffset = BlockIndex >> XNANDPS8_BBT_BLOCK_SHIFT; + /* + * Block shift value in the byte + */ + BlockShift = XNandPs8_BbtBlockShift(BlockIndex); + Page = BlockIndex * InstancePtr->Geometry.PagesPerBlock; + /* + * Search for the bad block pattern + */ + for(PageIndex = 0U; PageIndex < NumPages; PageIndex++) { + Status = XNandPs8_ReadSpareBytes(InstancePtr, + (Page + PageIndex), &Buf[0]); + + if (Status != XST_SUCCESS) { + /* Marking as bad block */ + InstancePtr->Bbt[BlockOffset] |= + (u8)(XNANDPS8_BLOCK_FACTORY_BAD << + BlockShift); + break; + } + /* + * Read the spare bytes to check for bad block + * pattern + */ + for(Length = 0U; Length < + InstancePtr->BbPattern.Length; Length++) { + if (Buf[InstancePtr->BbPattern.Offset + Length] + != + InstancePtr->BbPattern.Pattern[Length]) + { + /* Bad block found */ + InstancePtr->Bbt[BlockOffset] |= + (u8) + (XNANDPS8_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 XNandPs8 instance. +* +* @return +* - XST_SUCCESS if successful. +* - XST_FAILURE if fail. +* +******************************************************************************/ +s32 XNandPs8_ScanBbt(XNandPs8 *InstancePtr) +{ + s32 Status; + u32 Index; + u32 BbtLen; + + Xil_AssertNonvoid(InstancePtr != NULL); + Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + + /* + * Zero the RAM based Bad Block Table(BBT) entries + */ + BbtLen = InstancePtr->Geometry.NumBlocks >> + XNANDPS8_BBT_BLOCK_SHIFT; + memset(&InstancePtr->Bbt[0], 0, BbtLen); + + for (Index = 0U; Index < InstancePtr->Geometry.NumTargets; Index++) { + + if (XNandPs8_ReadBbt(InstancePtr, Index) != XST_SUCCESS) { + /* + * Create memory based Bad Block Table(BBT) + */ + XNandPs8_CreateBbt(InstancePtr, Index); + /* + * Write the Bad Block Table(BBT) to the flash + */ + Status = XNandPs8_WriteBbt(InstancePtr, + &InstancePtr->BbtDesc, + &InstancePtr->BbtMirrorDesc, Index); + if (Status != XST_SUCCESS) { + goto Out; + } + /* + * Write the Mirror Bad Block Table(BBT) to the flash + */ + Status = XNandPs8_WriteBbt(InstancePtr, + &InstancePtr->BbtMirrorDesc, + &InstancePtr->BbtDesc, Index); + if (Status != XST_SUCCESS) { + goto Out; + } + /* + * Mark the blocks containing Bad Block Table + * (BBT) as Reserved + */ + Status = XNandPs8_MarkBbt(InstancePtr, + &InstancePtr->BbtDesc, + Index); + if (Status != XST_SUCCESS) { + goto Out; + } + Status = XNandPs8_MarkBbt(InstancePtr, + &InstancePtr->BbtMirrorDesc, + Index); + if (Status != XST_SUCCESS) { + goto Out; + } + } + } + + Status = XST_SUCCESS; +Out: + return Status; +} + +/*****************************************************************************/ +/** +* 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 XNandPs8 instance. +* @param Buf is the buffer which contains BBT read from flash. +* +* @return +* - NONE. +* +******************************************************************************/ +static void XNandPs8_ConvertBbt(XNandPs8 *InstancePtr, u8 *Buf, u32 Target) +{ + u32 BlockOffset; + u8 BlockShift; + u32 Data; + u8 BlockType; + u32 BlockIndex; + u32 BbtLen = InstancePtr->Geometry.NumTargetBlocks >> + XNANDPS8_BBT_BLOCK_SHIFT; + u32 StartBlock = Target * InstancePtr->Geometry.NumTargetBlocks; + + for(BlockOffset = StartBlock; BlockOffset < (StartBlock + BbtLen); + BlockOffset++) { + Data = *(Buf + BlockOffset); + /* + * Clear the RAM based Bad Block Table(BBT) contents + */ + InstancePtr->Bbt[BlockOffset] = 0x0U; + /* + * Loop through the every 4 blocks in the bitmap + */ + for(BlockIndex = 0U; BlockIndex < XNANDPS8_BBT_ENTRY_NUM_BLOCKS; + BlockIndex++) { + BlockShift = XNandPs8_BbtBlockShift(BlockIndex); + BlockType = (u8) ((Data >> BlockShift) & + XNANDPS8_BLOCK_TYPE_MASK); + switch(BlockType) { + case XNANDPS8_FLASH_BLOCK_FACTORY_BAD: + /* Factory bad block */ + InstancePtr->Bbt[BlockOffset] |= + (u8) + (XNANDPS8_BLOCK_FACTORY_BAD << + BlockShift); + break; + case XNANDPS8_FLASH_BLOCK_RESERVED: + /* Reserved block */ + InstancePtr->Bbt[BlockOffset] |= + (u8) + (XNANDPS8_BLOCK_RESERVED << + BlockShift); + break; + case XNANDPS8_FLASH_BLOCK_BAD: + /* Bad block due to wear */ + InstancePtr->Bbt[BlockOffset] |= + (u8)(XNANDPS8_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 XNandPs8 instance. +* @return +* - XST_SUCCESS if successful. +* - XST_FAILURE if fail. +* +******************************************************************************/ +static s32 XNandPs8_ReadBbt(XNandPs8 *InstancePtr, u32 Target) +{ + u64 Offset; + u8 Buf[XNANDPS8_BBT_BUF_LENGTH] + __attribute__ ((aligned(64))) = {0U}; + s32 Status1; + s32 Status2; + s32 Status; + u32 BufLen; + u8 * BufPtr = Buf; + + XNandPs8_BbtDesc *Desc = &InstancePtr->BbtDesc; + XNandPs8_BbtDesc *MirrorDesc = &InstancePtr->BbtMirrorDesc; + BufLen = XNANDPS8_BBT_BUF_LENGTH; + /* + * Search the Bad Block Table(BBT) in flash + */ + Status1 = XNandPs8_SearchBbt(InstancePtr, Desc, Target); + Status2 = XNandPs8_SearchBbt(InstancePtr, MirrorDesc, Target); + if ((Status1 != XST_SUCCESS) && (Status2 != XST_SUCCESS)) { +#ifdef XNANDPS8_DEBUG + xil_printf("%s: Bad block table not found\r\n",__func__); +#endif + Status = XST_FAILURE; + goto Out; + } +#ifdef XNANDPS8_DEBUG + xil_printf("%s: Bad block table found\r\n",__func__); +#endif + /* + * Bad Block Table found + */ + if ((Desc->Valid != 0U) && (MirrorDesc->Valid != 0U)) { + /* + * Valid BBT & Mirror BBT found + */ + if (Desc->Version[Target] > MirrorDesc->Version[Target]) { + Offset = (u64)Desc->PageOffset[Target] * + (u64)InstancePtr->Geometry.BytesPerPage; + Status = XNandPs8_Read(InstancePtr, Offset, BufLen, + &BufPtr[0]); + if (Status != XST_SUCCESS) { + goto Out; + } + +#ifdef XNANDPS8_BBT_NO_OOB + BufPtr = BufPtr + Desc->VerOffset + + XNANDPS8_BBT_VERSION_LENGTH; +#endif + /* + * Convert flash BBT to memory based BBT + */ + XNandPs8_ConvertBbt(InstancePtr, &BufPtr[0], Target); + MirrorDesc->Version[Target] = Desc->Version[Target]; + + /* + * Write the BBT to Mirror BBT location in flash + */ + Status = XNandPs8_WriteBbt(InstancePtr, MirrorDesc, + Desc, Target); + if (Status != XST_SUCCESS) { + goto Out; + } + } else if (Desc->Version[Target] < + MirrorDesc->Version[Target]) { + Offset = (u64)MirrorDesc->PageOffset[Target] * + (u64)InstancePtr->Geometry.BytesPerPage; + Status = XNandPs8_Read(InstancePtr, Offset, BufLen, + &BufPtr[0]); + if (Status != XST_SUCCESS) { + goto Out; + } +#ifdef XNANDPS8_BBT_NO_OOB + BufPtr = BufPtr + Desc->VerOffset + + XNANDPS8_BBT_VERSION_LENGTH; +#endif + /* + * Convert flash BBT to memory based BBT + */ + XNandPs8_ConvertBbt(InstancePtr, &BufPtr[0], Target); + Desc->Version[Target] = MirrorDesc->Version[Target]; + + /* + * Write the Mirror BBT to BBT location in flash + */ + Status = XNandPs8_WriteBbt(InstancePtr, Desc, + MirrorDesc, Target); + if (Status != XST_SUCCESS) { + goto Out; + } + } else { + /* Both are up-to-date */ + Offset = (u64)Desc->PageOffset[Target] * + (u64)InstancePtr->Geometry.BytesPerPage; + Status = XNandPs8_Read(InstancePtr, Offset, BufLen, + &BufPtr[0]); + if (Status != XST_SUCCESS) { + goto Out; + } +#ifdef XNANDPS8_BBT_NO_OOB + BufPtr = BufPtr + Desc->VerOffset + + XNANDPS8_BBT_VERSION_LENGTH; +#endif + + /* + * Convert flash BBT to memory based BBT + */ + XNandPs8_ConvertBbt(InstancePtr, &BufPtr[0], Target); + } + } else if (Desc->Valid != 0U) { + /* + * Valid Primary BBT found + */ + Offset = (u64)Desc->PageOffset[Target] * + (u64)InstancePtr->Geometry.BytesPerPage; + Status = XNandPs8_Read(InstancePtr, Offset, BufLen, &BufPtr[0]); + if (Status != XST_SUCCESS) { + goto Out; + } +#ifdef XNANDPS8_BBT_NO_OOB + BufPtr = BufPtr + Desc->VerOffset + + XNANDPS8_BBT_VERSION_LENGTH; +#endif + /* + * Convert flash BBT to memory based BBT + */ + XNandPs8_ConvertBbt(InstancePtr, &BufPtr[0], Target); + MirrorDesc->Version[Target] = Desc->Version[Target]; + + /* + * Write the BBT to Mirror BBT location in flash + */ + Status = XNandPs8_WriteBbt(InstancePtr, MirrorDesc, Desc, + Target); + if (Status != XST_SUCCESS) { + goto Out; + } + } else { + /* + * Valid Mirror BBT found + */ + Offset = (u64)MirrorDesc->PageOffset[Target] * + (u64)InstancePtr->Geometry.BytesPerPage; + Status = XNandPs8_Read(InstancePtr, Offset, BufLen, &BufPtr[0]); + if (Status != XST_SUCCESS) { + goto Out; + } +#ifdef XNANDPS8_BBT_NO_OOB + BufPtr = BufPtr + Desc->VerOffset + + XNANDPS8_BBT_VERSION_LENGTH; +#endif + + /* + * Convert flash BBT to memory based BBT + */ + XNandPs8_ConvertBbt(InstancePtr, &BufPtr[0], Target); + Desc->Version[Target] = MirrorDesc->Version[Target]; + + /* + * Write the Mirror BBT to BBT location in flash + */ + Status = XNandPs8_WriteBbt(InstancePtr, Desc, MirrorDesc, + Target); + if (Status != XST_SUCCESS) { + goto Out; + } + } + + Status = XST_SUCCESS; +Out: + return Status; +} + +/*****************************************************************************/ +/** +* This function searches the BBT in flash. +* +* @param InstancePtr is the pointer to the XNandPs8 instance. +* @param Desc is the BBT descriptor pattern to search. +* +* @return +* - XST_SUCCESS if successful. +* - XST_FAILURE if fail. +* +******************************************************************************/ +static s32 XNandPs8_SearchBbt(XNandPs8 *InstancePtr, XNandPs8_BbtDesc *Desc, + u32 Target) +{ + u32 StartBlock; + u32 SigOffset; + u32 VerOffset; + u32 MaxBlocks; + u32 PageOff; + u32 SigLength; + u8 Buf[XNANDPS8_MAX_SPARE_SIZE] __attribute__ ((aligned(64))) = {0U}; + u32 Block; + u32 Offset; + s32 Status; + u64 BlockOff; + + StartBlock = ((Target + (u32)1) * + InstancePtr->Geometry.NumTargetBlocks) - (u32)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 = 0U; Block < MaxBlocks; Block++) { + PageOff = (StartBlock - Block) * + InstancePtr->Geometry.PagesPerBlock; + +#ifdef XNANDPS8_BBT_NO_OOB + BlockOff = (u64)PageOff * (u64)InstancePtr->Geometry.BytesPerPage; + Status = XNandPs8_Read(InstancePtr, BlockOff, + Desc->SigLength + Desc->SigOffset , &Buf[0]); +#else + Status = XNandPs8_ReadSpareBytes(InstancePtr, PageOff, &Buf[0]); +#endif + if (Status != XST_SUCCESS) { + continue; + } + /* + * Check the Bad Block Table(BBT) signature + */ + for(Offset = 0U; Offset < SigLength; Offset++) { + if (Buf[Offset + SigOffset] != + (u8)(Desc->Signature[Offset])) + { + break; /* Check the next blocks */ + } + } + if (Offset >= SigLength) { + /* + * Bad Block Table(BBT) found + */ + Desc->PageOffset[Target] = PageOff; + Desc->Version[Target] = Buf[VerOffset]; + Desc->Valid = 1U; + + Status = XST_SUCCESS; + goto Out; + } + } + /* + * Bad Block Table(BBT) not found + */ + Status = XST_FAILURE; +Out: + return Status; +} + +/*****************************************************************************/ +/** +* This function writes Bad Block Table(BBT) from RAM to flash. +* +* @param InstancePtr is the pointer to the XNandPs8 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 s32 XNandPs8_WriteBbt(XNandPs8 *InstancePtr, XNandPs8_BbtDesc *Desc, + XNandPs8_BbtDesc *MirrorDesc, u32 Target) +{ + u64 Offset; + u32 Block = {0U}; + u32 EndBlock = ((Target + (u32)1) * + InstancePtr->Geometry.NumTargetBlocks) - (u32)1; + u8 Buf[XNANDPS8_BBT_BUF_LENGTH] + __attribute__ ((aligned(64))) = {0U}; + u32 BufLen = XNANDPS8_BBT_BUF_LENGTH; + u8 SpareBuf[XNANDPS8_MAX_SPARE_SIZE] __attribute__ ((aligned(64))) = {0U}; + u8 Mask[4] = {0x00U, 0x01U, 0x02U, 0x03U}; + u8 Data; + u32 BlockOffset; + u8 BlockShift; + s32 Status; + u32 BlockIndex; + u32 Index; + u8 BlockType; + u32 BbtLen = InstancePtr->Geometry.NumBlocks >> + XNANDPS8_BBT_BLOCK_SHIFT; + u8* BufPtr = Buf; + /* + * Find a valid block to write the Bad Block Table(BBT) + */ + if ((!Desc->Valid) != 0U) { + for(Index = 0U; Index < Desc->MaxBlocks; Index++) { + Block = (EndBlock - Index); + BlockOffset = Block >> XNANDPS8_BBT_BLOCK_SHIFT; + BlockShift = XNandPs8_BbtBlockShift(Block); + BlockType = (InstancePtr->Bbt[BlockOffset] >> + BlockShift) & XNANDPS8_BLOCK_TYPE_MASK; + switch(BlockType) + { + case XNANDPS8_BLOCK_BAD: + case XNANDPS8_BLOCK_FACTORY_BAD: + continue; + default: + /* Good Block */ + break; + } + Desc->PageOffset[Target] = Block * + InstancePtr->Geometry.PagesPerBlock; + if (Desc->PageOffset[Target] != + MirrorDesc->PageOffset[Target]) { + /* Free block found */ + Desc->Valid = 1U; + break; + } + } + + /* + * Block not found for writing Bad Block Table(BBT) + */ + if (Index >= Desc->MaxBlocks) { +#ifdef XNANDPS8_DEBUG + xil_printf("%s: Blocks unavailable for writing BBT\r\n", + __func__); +#endif + Status = XST_FAILURE; + goto Out; + } + } else { + Block = Desc->PageOffset[Target] / + InstancePtr->Geometry.PagesPerBlock; + } + /* + * Convert the memory based BBT to flash based table + */ + memset(Buf, 0xff, BufLen); + +#ifdef XNANDPS8_BBT_NO_OOB + BufPtr = BufPtr + Desc->VerOffset + XNANDPS8_BBT_VERSION_LENGTH; +#endif + /* + * Loop through the number of blocks + */ + for(BlockOffset = 0U; BlockOffset < BufLen; BlockOffset++) { + Data = InstancePtr->Bbt[BlockOffset]; + /* + * Calculate the bit mask for 4 blocks at a time in loop + */ + for(BlockIndex = 0U; BlockIndex < XNANDPS8_BBT_ENTRY_NUM_BLOCKS; + BlockIndex++) { + BlockShift = XNandPs8_BbtBlockShift(BlockIndex); + BufPtr[BlockOffset] &= ~(Mask[Data & + XNANDPS8_BLOCK_TYPE_MASK] << + BlockShift); + Data >>= XNANDPS8_BBT_BLOCK_SHIFT; + } + } + /* + * Write the Bad Block Table(BBT) to flash + */ + Status = XNandPs8_EraseBlock(InstancePtr, 0U, Block); + if (Status != XST_SUCCESS) { + goto Out; + } + +#ifdef XNANDPS8_BBT_NO_OOB + /* + * Copy the signature and version to the Buffer + */ + memcpy(Buf , &Desc->Signature[0], + Desc->SigLength); + memcpy(Buf + Desc->SigLength, &Desc->Version[Target], 1U); + /* + * Write the Buffer to page offset + */ + Offset = (u64)Desc->PageOffset[Target] * + (u64)InstancePtr->Geometry.BytesPerPage; + Status = XNandPs8_Write(InstancePtr, Offset, BufLen, &Buf[0]); + if (Status != XST_SUCCESS) { + goto Out; + } +#else + /* + * Write the BBT to page offset + */ + Offset = (u64)Desc->PageOffset[Target] * + (u64)InstancePtr->Geometry.BytesPerPage; + Status = XNandPs8_Write(InstancePtr, Offset, BbtLen, &Buf[0]); + if (Status != XST_SUCCESS) { + goto Out; + } + /* + * Write the signature and version in the spare data area + */ + memset(SpareBuf, 0xff, InstancePtr->Geometry.SpareBytesPerPage); + Status = XNandPs8_ReadSpareBytes(InstancePtr, Desc->PageOffset[Target], + &SpareBuf[0]); + if (Status != XST_SUCCESS) { + goto Out; + } + + memcpy(SpareBuf + Desc->SigOffset, &Desc->Signature[0], + Desc->SigLength); + memcpy(SpareBuf + Desc->VerOffset, &Desc->Version[Target], 1U); + + Status = XNandPs8_WriteSpareBytes(InstancePtr, + Desc->PageOffset[Target], &SpareBuf[0]); + if (Status != XST_SUCCESS) { + goto Out; + } +#endif + Status = XST_SUCCESS; +Out: + return Status; +} + +/*****************************************************************************/ +/** +* This function updates the primary and mirror Bad Block Table(BBT) in the +* flash. +* +* @param InstancePtr is the pointer to the XNandPs8 instance. +* @return +* - XST_SUCCESS if successful. +* - XST_FAILURE if fail. +* +******************************************************************************/ +static s32 XNandPs8_UpdateBbt(XNandPs8 *InstancePtr, u32 Target) +{ + s32 Status; + u8 Version; + + /* + * Update the version number + */ + Version = InstancePtr->BbtDesc.Version[Target]; + InstancePtr->BbtDesc.Version[Target] = (u8)(((u16)Version + + (u16)1) % (u16)256U); + + Version = InstancePtr->BbtMirrorDesc.Version[Target]; + InstancePtr->BbtMirrorDesc.Version[Target] = (u8)(((u16)Version + + (u16)1) % (u16)256); + /* + * Update the primary Bad Block Table(BBT) in flash + */ + Status = XNandPs8_WriteBbt(InstancePtr, &InstancePtr->BbtDesc, + &InstancePtr->BbtMirrorDesc, + Target); + if (Status != XST_SUCCESS) { + goto Out; + } + + /* + * Update the mirrored Bad Block Table(BBT) in flash + */ + Status = XNandPs8_WriteBbt(InstancePtr, &InstancePtr->BbtMirrorDesc, + &InstancePtr->BbtDesc, + Target); + if (Status != XST_SUCCESS) { + goto Out; + } + + Status = XST_SUCCESS; +Out: + return Status; +} + +/*****************************************************************************/ +/** +* This function marks the block containing Bad Block Table as reserved +* and updates the BBT. +* +* @param InstancePtr is the pointer to the XNandPs8 instance. +* @param Desc is the BBT descriptor pointer. +* @return +* - XST_SUCCESS if successful. +* - XST_FAILURE if fail. +* +******************************************************************************/ +static s32 XNandPs8_MarkBbt(XNandPs8* InstancePtr, XNandPs8_BbtDesc *Desc, + u32 Target) +{ + u32 BlockIndex; + u32 BlockOffset; + u8 BlockShift; + u8 OldVal; + u8 NewVal; + s32 Status; + u32 UpdateBbt = 0U; + u32 Index; + + /* + * Mark the last four blocks as Reserved + */ + BlockIndex = ((Target + (u32)1) * InstancePtr->Geometry.NumTargetBlocks) - + Desc->MaxBlocks - (u32)1; + + for(Index = 0U; Index < Desc->MaxBlocks; Index++) { + + BlockOffset = BlockIndex >> XNANDPS8_BBT_BLOCK_SHIFT; + BlockShift = XNandPs8_BbtBlockShift(BlockIndex); + OldVal = InstancePtr->Bbt[BlockOffset]; + NewVal = (u8) (OldVal | (XNANDPS8_BLOCK_RESERVED << + BlockShift)); + InstancePtr->Bbt[BlockOffset] = NewVal; + + if (OldVal != NewVal) { + UpdateBbt = 1U; + } + BlockIndex++; + } + + /* + * Update the BBT to flash + */ + if (UpdateBbt != 0U) { + Status = XNandPs8_UpdateBbt(InstancePtr, Target); + if (Status != XST_SUCCESS) { + goto Out; + } + } + + Status = XST_SUCCESS; +Out: + return Status; +} + +/*****************************************************************************/ +/** +* +* This function checks whether a block is bad or not. +* +* @param InstancePtr is the pointer to the XNandPs8 instance. +* +* @param Block is the block number. +* +* @return +* - XST_SUCCESS if successful. +* - XST_FAILURE if fail. +* +******************************************************************************/ +s32 XNandPs8_IsBlockBad(XNandPs8 *InstancePtr, u32 Block) +{ + u8 Data; + u8 BlockShift; + u8 BlockType; + u32 BlockOffset; + s32 Status; + + Xil_AssertNonvoid(InstancePtr != NULL); + Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + Xil_AssertNonvoid(Block < InstancePtr->Geometry.NumBlocks); + + BlockOffset = Block >> XNANDPS8_BBT_BLOCK_SHIFT; + BlockShift = XNandPs8_BbtBlockShift(Block); + Data = InstancePtr->Bbt[BlockOffset]; /* Block information in BBT */ + BlockType = (Data >> BlockShift) & XNANDPS8_BLOCK_TYPE_MASK; + + if ((BlockType != XNANDPS8_BLOCK_GOOD) && + (BlockType != XNANDPS8_BLOCK_RESERVED)) { + Status = XST_SUCCESS; + } + else { + Status = XST_FAILURE; + } + return Status; +} + +/*****************************************************************************/ +/** +* 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 XNandPs8 instance. +* @param Block is the block number. +* +* @return +* - XST_SUCCESS if successful. +* - XST_FAILURE if fail. +* +******************************************************************************/ +s32 XNandPs8_MarkBlockBad(XNandPs8 *InstancePtr, u32 Block) +{ + u8 Data; + u8 BlockShift; + u32 BlockOffset; + u8 OldVal; + u8 NewVal; + s32 Status; + u32 Target; + + Xil_AssertNonvoid(InstancePtr != NULL); + Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + Xil_AssertNonvoid(Block < InstancePtr->Geometry.NumBlocks); + + Target = Block % InstancePtr->Geometry.NumTargetBlocks; + + BlockOffset = Block >> XNANDPS8_BBT_BLOCK_SHIFT; + BlockShift = XNandPs8_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 &= ~(XNANDPS8_BLOCK_TYPE_MASK << BlockShift); + Data |= (XNANDPS8_BLOCK_BAD << BlockShift); + NewVal = Data; + InstancePtr->Bbt[BlockOffset] = Data; + + /* + * Update the Bad Block Table(BBT) in flash + */ + if (OldVal != NewVal) { + Status = XNandPs8_UpdateBbt(InstancePtr, Target); + if (Status != XST_SUCCESS) { + goto Out; + } + } + + Status = XST_SUCCESS; +Out: + return Status; +} diff --git a/XilinxProcessorIPLib/drivers/nandps8_v2_0/src/xnandps8_bbm.h b/XilinxProcessorIPLib/drivers/nandps8_v2_0/src/xnandps8_bbm.h new file mode 100755 index 00000000..1c7be987 --- /dev/null +++ b/XilinxProcessorIPLib/drivers/nandps8_v2_0/src/xnandps8_bbm.h @@ -0,0 +1,215 @@ +/****************************************************************************** +* +* Copyright (C) 2014 Xilinx, Inc. All rights reserved. +* +* This file contains confidential and proprietary information of Xilinx, Inc. +* and is protected under U.S. and international copyright and other +* intellectual property laws. +* +* DISCLAIMER +* This disclaimer is not a license and does not grant any rights to the +* materials distributed herewith. Except as otherwise provided in a valid +* license issued to you by Xilinx, and to the maximum extent permitted by +* applicable law: (1) THESE MATERIALS ARE MADE AVAILABLE "AS IS" AND WITH ALL +* FAULTS, AND XILINX HEREBY DISCLAIMS ALL WARRANTIES AND CONDITIONS, EXPRESS, +* IMPLIED, OR STATUTORY, INCLUDING BUT NOT LIMITED TO WARRANTIES OF +* MERCHANTABILITY, NON- INFRINGEMENT, OR FITNESS FOR ANY PARTICULAR PURPOSE +* and +* (2) Xilinx shall not be liable (whether in contract or tort, including +* negligence, or under any other theory of liability) for any loss or damage +* of any kind or nature related to, arising under or in connection with these +* materials, including for any direct, or any indirect, special, incidental, +* or consequential loss or damage (including loss of data, profits, +* goodwill, or any type of loss or damage suffered as a result of any +* action brought by a third party) even if such damage or loss was +* reasonably foreseeable or Xilinx had been advised of the possibility +* of the same. +* +* CRITICAL APPLICATIONS +* Xilinx products are not designed or intended to be fail- safe, or for use +* in any application requiring fail-safe performance, such as life-support +* or safety devices or systems, Class III medical devices, nuclear +* facilities, applications related to the deployment of airbags, or any +* other applications that could lead to death, personal injury, or severe +* property or environmental damage (individually and collectively, +* "Critical Applications"). Customer assumes the sole risk and liability +* of any use of Xilinx products in Critical Applications, subject only to +* applicable laws and regulations governing limitations on product liability. +* +* THIS COPYRIGHT NOTICE AND DISCLAIMER MUST BE RETAINED AS PART +* OF THIS FILE AT ALL TIMES. +* +******************************************************************************/ + +/*****************************************************************************/ +/** +* +* @file xnandps8_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 +* XNandPs8_IsBlockBad and take the action based on the return value. Also user +* can update the bad block table using XNandPs8_MarkBlockBad API. +* +* @note None +* +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who    Date        Changes
+* ----- ----   ----------  -----------------------------------------------
+* 1.0   nm     05/06/2014  First release
+* 2.0   sb     11/04/2014  Added support for writing BBT signature and version
+*			   in page section by enabling XNANDPS8_BBT_NO_OOB.
+* 
+* +******************************************************************************/ +#ifndef XNANDPS8_BBM_H /* prevent circular inclusions */ +#define XNANDPS8_BBM_H /* by using protection macros */ + +#ifdef __cplusplus +extern "C" { +#endif + +/***************************** Include Files *********************************/ +#include "xnandps8.h" + +/************************** Constant Definitions *****************************/ +/* + * Block definitions for RAM based Bad Block Table (BBT) + */ +#define XNANDPS8_BLOCK_GOOD 0x0U /**< Block is good */ +#define XNANDPS8_BLOCK_BAD 0x1U /**< Block is bad */ +#define XNANDPS8_BLOCK_RESERVED 0x2U /**< Reserved block */ +#define XNANDPS8_BLOCK_FACTORY_BAD 0x3U /**< Factory marked bad + block */ +/* + * Block definitions for FLASH based Bad Block Table (BBT) + */ +#define XNANDPS8_FLASH_BLOCK_GOOD 0x3U /**< Block is good */ +#define XNANDPS8_FLASH_BLOCK_BAD 0x2U /**< Block is bad */ +#define XNANDPS8_FLASH_BLOCK_RESERVED 0x1U /**< Reserved block */ +#define XNANDPS8_FLASH_BLOCK_FACTORY_BAD 0x0U /**< Factory marked bad + block */ + +#define XNANDPS8_BBT_SCAN_2ND_PAGE 0x00000001U /**< Scan the + second page + for bad block + information + */ +#define XNANDPS8_BBT_DESC_PAGE_OFFSET 0U /**< Page offset of Bad + Block Table Desc */ +#define XNANDPS8_BBT_DESC_SIG_OFFSET 2U /**< Bad Block Table + signature offset */ +#define XNANDPS8_BBT_DESC_VER_OFFSET 6U /**< Bad block Table + version offset */ +#define XNANDPS8_BBT_DESC_SIG_LEN 4U /**< Bad block Table + signature length */ +#define XNANDPS8_BBT_DESC_MAX_BLOCKS 64U /**< Bad block Table + max blocks */ + +#define XNANDPS8_BBT_BLOCK_SHIFT 2U /**< Block shift value + for a block in BBT */ +#define XNANDPS8_BBT_ENTRY_NUM_BLOCKS 4U /**< Num of blocks in + one BBT entry */ +#define XNANDPS8_BB_PATTERN_OFFSET_SMALL_PAGE 5U /**< Bad block pattern + offset in a page */ +#define XNANDPS8_BB_PATTERN_LENGTH_SMALL_PAGE 1U /**< Bad block pattern + length */ +#define XNANDPS8_BB_PATTERN_OFFSET_LARGE_PAGE 0U /**< Bad block pattern + offset in a large + page */ +#define XNANDPS8_BB_PATTERN_LENGTH_LARGE_PAGE 2U /**< Bad block pattern + length */ +#define XNANDPS8_BB_PATTERN 0xFFU /**< Bad block pattern + to search in a page + */ +#define XNANDPS8_BLOCK_TYPE_MASK 0x03U /**< Block type mask */ +#define XNANDPS8_BLOCK_SHIFT_MASK 0x06U /**< Block shift mask + for a Bad Block Table + entry byte */ + +#define XNANDPS8_ONDIE_SIG_OFFSET 0x4U +#define XNANDPS8_ONDIE_VER_OFFSET 0x14U + +#define XNANDPS8_BBT_VERSION_LENGTH 1U +#define XNANDPS8_BBT_SIG_LENGTH 4U + +#define XNANDPS8_BBT_BUF_LENGTH ((XNANDPS8_MAX_BLOCKS >> \ + XNANDPS8_BBT_BLOCK_SHIFT) + \ + (XNANDPS8_BBT_DESC_SIG_OFFSET + \ + XNANDPS8_BBT_SIG_LENGTH + \ + XNANDPS8_BBT_VERSION_LENGTH)) +/**************************** 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 XNandPs8_BbtBlockShift(Block) \ + ((u8)(((Block) * 2U) & XNANDPS8_BLOCK_SHIFT_MASK)) + +/************************** Variable Definitions *****************************/ + +/************************** Function Prototypes ******************************/ + +void XNandPs8_InitBbtDesc(XNandPs8 *InstancePtr); + +s32 XNandPs8_ScanBbt(XNandPs8 *InstancePtr); + +s32 XNandPs8_IsBlockBad(XNandPs8 *InstancePtr, u32 Block); + +s32 XNandPs8_MarkBlockBad(XNandPs8 *InstancePtr, u32 Block); + +#ifdef __cplusplus +} +#endif + +#endif /* end of protection macro */ diff --git a/XilinxProcessorIPLib/drivers/nandps8_v2_0/src/xnandps8_g.c b/XilinxProcessorIPLib/drivers/nandps8_v2_0/src/xnandps8_g.c new file mode 100755 index 00000000..772f9256 --- /dev/null +++ b/XilinxProcessorIPLib/drivers/nandps8_v2_0/src/xnandps8_g.c @@ -0,0 +1,82 @@ +/****************************************************************************** +* +* Copyright (C) 2014 Xilinx, Inc. All rights reserved. +* +* This file contains confidential and proprietary information of Xilinx, Inc. +* and is protected under U.S. and international copyright and other +* intellectual property laws. +* +* DISCLAIMER +* This disclaimer is not a license and does not grant any rights to the +* materials distributed herewith. Except as otherwise provided in a valid +* license issued to you by Xilinx, and to the maximum extent permitted by +* applicable law: (1) THESE MATERIALS ARE MADE AVAILABLE "AS IS" AND WITH ALL +* FAULTS, AND XILINX HEREBY DISCLAIMS ALL WARRANTIES AND CONDITIONS, EXPRESS, +* IMPLIED, OR STATUTORY, INCLUDING BUT NOT LIMITED TO WARRANTIES OF +* MERCHANTABILITY, NON- INFRINGEMENT, OR FITNESS FOR ANY PARTICULAR PURPOSE +* and +* (2) Xilinx shall not be liable (whether in contract or tort, including +* negligence, or under any other theory of liability) for any loss or damage +* of any kind or nature related to, arising under or in connection with these +* materials, including for any direct, or any indirect, special, incidental, +* or consequential loss or damage (including loss of data, profits, +* goodwill, or any type of loss or damage suffered as a result of any +* action brought by a third party) even if such damage or loss was +* reasonably foreseeable or Xilinx had been advised of the possibility +* of the same. +* +* CRITICAL APPLICATIONS +* Xilinx products are not designed or intended to be fail- safe, or for use +* in any application requiring fail-safe performance, such as life-support +* or safety devices or systems, Class III medical devices, nuclear +* facilities, applications related to the deployment of airbags, or any +* other applications that could lead to death, personal injury, or severe +* property or environmental damage (individually and collectively, +* "Critical Applications"). Customer assumes the sole risk and liability +* of any use of Xilinx products in Critical Applications, subject only to +* applicable laws and regulations governing limitations on product liability. +* +* THIS COPYRIGHT NOTICE AND DISCLAIMER MUST BE RETAINED AS PART +* OF THIS FILE AT ALL TIMES. +* +******************************************************************************/ + +/*****************************************************************************/ +/** +* +* @file xnandps8_g.c +* +* This file contains a configuration table where each entry is a configuration +* structure for an XNandPs8 device in the system. +* +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who    Date	   Changes
+* ----- ----   ----------  -----------------------------------------------
+* 1.0   nm     05/06/2014  First release
+* 1.0   nm     06/02/2014  Changed the copyright to new copyright
+* 
+* +******************************************************************************/ + +/***************************** Include Files ********************************/ +#include "xparameters.h" +#include "xnandps8.h" +/************************** Constant Definitions ****************************/ + +/**************************** Type Definitions ******************************/ + +/***************** Macros (Inline Functions) Definitions ********************/ + +/************************** Variable Definitions ****************************/ + +/** + * Each XNandPs8 device in the system has an entry in this table. + */ +XNandPs8_Config XNandPs8_ConfigTable[] = { + { + 0U, + XPAR_XNANDPS8_0_BASEADDR + } +}; diff --git a/XilinxProcessorIPLib/drivers/nandps8_v2_0/src/xnandps8_hw.h b/XilinxProcessorIPLib/drivers/nandps8_v2_0/src/xnandps8_hw.h new file mode 100755 index 00000000..3b657f73 --- /dev/null +++ b/XilinxProcessorIPLib/drivers/nandps8_v2_0/src/xnandps8_hw.h @@ -0,0 +1,516 @@ +/****************************************************************************** +* +* Copyright (C) 2014 Xilinx, Inc. All rights reserved. +* +* This file contains confidential and proprietary information of Xilinx, Inc. +* and is protected under U.S. and international copyright and other +* intellectual property laws. +* +* DISCLAIMER +* This disclaimer is not a license and does not grant any rights to the +* materials distributed herewith. Except as otherwise provided in a valid +* license issued to you by Xilinx, and to the maximum extent permitted by +* applicable law: (1) THESE MATERIALS ARE MADE AVAILABLE "AS IS" AND WITH ALL +* FAULTS, AND XILINX HEREBY DISCLAIMS ALL WARRANTIES AND CONDITIONS, EXPRESS, +* IMPLIED, OR STATUTORY, INCLUDING BUT NOT LIMITED TO WARRANTIES OF +* MERCHANTABILITY, NON- INFRINGEMENT, OR FITNESS FOR ANY PARTICULAR PURPOSE +* and +* (2) Xilinx shall not be liable (whether in contract or tort, including +* negligence, or under any other theory of liability) for any loss or damage +* of any kind or nature related to, arising under or in connection with these +* materials, including for any direct, or any indirect, special, incidental, +* or consequential loss or damage (including loss of data, profits, +* goodwill, or any type of loss or damage suffered as a result of any +* action brought by a third party) even if such damage or loss was +* reasonably foreseeable or Xilinx had been advised of the possibility +* of the same. +* +* CRITICAL APPLICATIONS +* Xilinx products are not designed or intended to be fail- safe, or for use +* in any application requiring fail-safe performance, such as life-support +* or safety devices or systems, Class III medical devices, nuclear +* facilities, applications related to the deployment of airbags, or any +* other applications that could lead to death, personal injury, or severe +* property or environmental damage (individually and collectively, +* "Critical Applications"). Customer assumes the sole risk and liability +* of any use of Xilinx products in Critical Applications, subject only to +* applicable laws and regulations governing limitations on product liability. +* +* THIS COPYRIGHT NOTICE AND DISCLAIMER MUST BE RETAINED AS PART +* OF THIS FILE AT ALL TIMES. +* +******************************************************************************/ + +/*****************************************************************************/ +/** +* +* @file xnandps8_hw.h +* +* This file contains identifiers and low-level macros/functions for the Arasan +* NAND flash controller driver. +* +* See xnandps8.h for more information. +* +* @note None +* +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who    Date        Changes
+* ----- ----   ----------  -----------------------------------------------
+* 1.0   nm     05/06/2014  First Release
+* 2.0   sb     11/04/2014  Changed XNANDPS8_ECC_SLC_MLC_MASK to
+*			   XNANDPS8_ECC_HAMMING_BCH_MASK.
+* 
+* +******************************************************************************/ + +#ifndef XNANDPS8_HW_H /* prevent circular inclusions */ +#define XNANDPS8_HW_H /* by using protection macros */ + +#ifdef __cplusplus +extern "C" { +#endif + +/***************************** Include Files *********************************/ +#include "xil_io.h" + +/************************** Constant Definitions *****************************/ + +/************************** Register Offset Definitions **********************/ + +#define XNANDPS8_PKT_OFFSET 0x00U /**< Packet Register */ +#define XNANDPS8_MEM_ADDR1_OFFSET 0x04U /**< Memory Address + Register 1 */ +#define XNANDPS8_MEM_ADDR2_OFFSET 0x08U /**< Memory Address + Register 2 */ +#define XNANDPS8_CMD_OFFSET 0x0CU /**< Command Register */ +#define XNANDPS8_PROG_OFFSET 0x10U /**< Program Register */ +#define XNANDPS8_INTR_STS_EN_OFFSET 0x14U /**< Interrupt Status + Enable Register */ +#define XNANDPS8_INTR_SIG_EN_OFFSET 0x18U /**< Interrupt Signal + Enable Register */ +#define XNANDPS8_INTR_STS_OFFSET 0x1CU /**< Interrupt Status + Register */ +#define XNANDPS8_READY_BUSY_OFFSET 0x20U /**< Ready/Busy status + Register */ +#define XNANDPS8_FLASH_STS_OFFSET 0x28U /**< Flash Status Register */ +#define XNANDPS8_TIMING_OFFSET 0x2CU /**< Timing Register */ +#define XNANDPS8_BUF_DATA_PORT_OFFSET 0x30U /**< Buffer Data Port + Register */ +#define XNANDPS8_ECC_OFFSET 0x34U /**< ECC Register */ +#define XNANDPS8_ECC_ERR_CNT_OFFSET 0x38U /**< ECC Error Count + Register */ +#define XNANDPS8_ECC_SPR_CMD_OFFSET 0x3CU /**< ECC Spare Command + Register */ +#define XNANDPS8_ECC_CNT_1BIT_OFFSET 0x40U /**< Error Count 1bit + Register */ +#define XNANDPS8_ECC_CNT_2BIT_OFFSET 0x44U /**< Error Count 2bit + Register */ +#define XNANDPS8_ECC_CNT_3BIT_OFFSET 0x48U /**< Error Count 3bit + Register */ +#define XNANDPS8_ECC_CNT_4BIT_OFFSET 0x4CU /**< Error Count 4bit + Register */ +#define XNANDPS8_CPU_REL_OFFSET 0x58U /**< CPU Release Register */ +#define XNANDPS8_ECC_CNT_5BIT_OFFSET 0x5CU /**< Error Count 5bit + Register */ +#define XNANDPS8_ECC_CNT_6BIT_OFFSET 0x60U /**< Error Count 6bit + Register */ +#define XNANDPS8_ECC_CNT_7BIT_OFFSET 0x64U /**< Error Count 7bit + Register */ +#define XNANDPS8_ECC_CNT_8BIT_OFFSET 0x68U /**< Error Count 8bit + Register */ +#define XNANDPS8_DATA_INTF_OFFSET 0x6CU /**< Data Interface Register */ +#define XNANDPS8_DMA_SYS_ADDR0_OFFSET 0x50U /**< DMA System Address 0 + Register */ +#define XNANDPS8_DMA_SYS_ADDR1_OFFSET 0x24U /**< DMA System Address 1 + Register */ +#define XNANDPS8_DMA_BUF_BND_OFFSET 0x54U /**< DMA Buffer Boundary + Register */ +#define XNANDPS8_SLV_DMA_CONF_OFFSET 0x80U /**< Slave DMA Configuration + Register */ + +/** @name Packet Register bit definitions and masks + * @{ + */ +#define XNANDPS8_PKT_PKT_SIZE_MASK 0x000007FFU /**< Packet Size */ +#define XNANDPS8_PKT_PKT_CNT_MASK 0x00FFF000U /**< Packet Count*/ +#define XNANDPS8_PKT_PKT_CNT_SHIFT 12U /**< Packet Count Shift */ +/* @} */ + +/** @name Memory Address Register 1 bit definitions and masks + * @{ + */ +#define XNANDPS8_MEM_ADDR1_COL_ADDR_MASK 0x0000FFFFU /**< Column Address + Mask */ +#define XNANDPS8_MEM_ADDR1_PG_ADDR_MASK 0xFFFF0000U /**< Page, Block + Address Mask */ +#define XNANDPS8_MEM_ADDR1_PG_ADDR_SHIFT 16U /**< Page Shift */ +/* @} */ + +/** @name Memory Address Register 2 bit definitions and masks + * @{ + */ +#define XNANDPS8_MEM_ADDR2_MEM_ADDR_MASK 0x000000FFU /**< Memory Address + */ +#define XNANDPS8_MEM_ADDR2_BUS_WIDTH_MASK 0x01000000U /**< Bus Width */ +#define XNANDPS8_MEM_ADDR2_NFC_BCH_MODE_MASK 0x0E000000U /**< BCH Mode + Value */ +#define XNANDPS8_MEM_ADDR2_MODE_MASK 0x30000000U /**< Flash + Connection Mode */ +#define XNANDPS8_MEM_ADDR2_CHIP_SEL_MASK 0xC0000000U /**< Chip Select */ +#define XNANDPS8_MEM_ADDR2_CHIP_SEL_SHIFT 30U /**< Chip select + shift */ +#define XNANDPS8_MEM_ADDR2_BUS_WIDTH_SHIFT 24U /**< Bus width shift */ +#define XNANDPS8_MEM_ADDR2_NFC_BCH_MODE_SHIFT 25U +/* @} */ + +/** @name Command Register bit definitions and masks + * @{ + */ +#define XNANDPS8_CMD_CMD1_MASK 0x000000FFU /**< 1st Cycle + Command */ +#define XNANDPS8_CMD_CMD2_MASK 0x0000FF00U /**< 2nd Cycle + Command */ +#define XNANDPS8_CMD_PG_SIZE_MASK 0x03800000U /**< Page Size */ +#define XNANDPS8_CMD_DMA_EN_MASK 0x0C000000U /**< DMA Enable + Mode */ +#define XNANDPS8_CMD_ADDR_CYCLES_MASK 0x70000000U /**< Number of + Address Cycles */ +#define XNANDPS8_CMD_ECC_ON_MASK 0x80000000U /**< ECC ON/OFF */ +#define XNANDPS8_CMD_CMD2_SHIFT 8U /**< 2nd Cycle Command + Shift */ +#define XNANDPS8_CMD_PG_SIZE_SHIFT 23U /**< Page Size Shift */ +#define XNANDPS8_CMD_DMA_EN_SHIFT 26U /**< DMA Enable Shift */ +#define XNANDPS8_CMD_ADDR_CYCLES_SHIFT 28U /**< Number of Address + Cycles Shift */ +#define XNANDPS8_CMD_ECC_ON_SHIFT 31U /**< ECC ON/OFF */ +/* @} */ + +/** @name Program Register bit definitions and masks + * @{ + */ +#define XNANDPS8_PROG_RD_MASK 0x00000001U /**< Read */ +#define XNANDPS8_PROG_MUL_DIE_MASK 0x00000002U /**< Multi Die */ +#define XNANDPS8_PROG_BLK_ERASE_MASK 0x00000004U /**< Block Erase */ +#define XNANDPS8_PROG_RD_STS_MASK 0x00000008U /**< Read Status */ +#define XNANDPS8_PROG_PG_PROG_MASK 0x00000010U /**< Page Program */ +#define XNANDPS8_PROG_MUL_DIE_RD_MASK 0x00000020U /**< Multi Die Rd */ +#define XNANDPS8_PROG_RD_ID_MASK 0x00000040U /**< Read ID */ +#define XNANDPS8_PROG_RD_PRM_PG_MASK 0x00000080U /**< Read Param + Page */ +#define XNANDPS8_PROG_RST_MASK 0x00000100U /**< Reset */ +#define XNANDPS8_PROG_GET_FEATURES_MASK 0x00000200U /**< Get Features */ +#define XNANDPS8_PROG_SET_FEATURES_MASK 0x00000400U /**< Set Features */ +#define XNANDPS8_PROG_RD_UNQ_ID_MASK 0x00000800U /**< Read Unique + ID */ +#define XNANDPS8_PROG_RD_STS_ENH_MASK 0x00001000U /**< Read Status + Enhanced */ +#define XNANDPS8_PROG_RD_INTRLVD_MASK 0x00002000U /**< Read + Interleaved */ +#define XNANDPS8_PROG_CHNG_RD_COL_ENH_MASK 0x00004000U /**< Change Read + Column + Enhanced */ +#define XNANDPS8_PROG_COPY_BACK_INTRLVD_MASK 0x00008000U /**< Copy Back + Interleaved */ +#define XNANDPS8_PROG_RD_CACHE_START_MASK 0x00010000U /**< Read Cache + Start */ +#define XNANDPS8_PROG_RD_CACHE_SEQ_MASK 0x00020000U /**< Read Cache + Sequential */ +#define XNANDPS8_PROG_RD_CACHE_RAND_MASK 0x00040000U /**< Read Cache + Random */ +#define XNANDPS8_PROG_RD_CACHE_END_MASK 0x00080000U /**< Read Cache + End */ +#define XNANDPS8_PROG_SMALL_DATA_MOVE_MASK 0x00100000U /**< Small Data + Move */ +#define XNANDPS8_PROG_CHNG_ROW_ADDR_MASK 0x00200000U /**< Change Row + Address */ +#define XNANDPS8_PROG_CHNG_ROW_ADDR_END_MASK 0x00400000U /**< Change Row + Address End */ +#define XNANDPS8_PROG_RST_LUN_MASK 0x00800000U /**< Reset LUN */ +#define XNANDPS8_PROG_PGM_PG_CLR_MASK 0x01000000U /**< Enhanced + Program Page + Register Clear */ +#define XNANDPS8_PROG_VOL_SEL_MASK 0x02000000U /**< Volume Select */ +#define XNANDPS8_PROG_ODT_CONF_MASK 0x04000000U /**< ODT Configure */ +/* @} */ + +/** @name Interrupt Status Enable Register bit definitions and masks + * @{ + */ +#define XNANDPS8_INTR_STS_EN_BUFF_WR_RDY_STS_EN_MASK 0x00000001U /**< Buffer + Write Ready + Status + Enable */ +#define XNANDPS8_INTR_STS_EN_BUFF_RD_RDY_STS_EN_MASK 0x00000002U /**< Buffer + Read Ready + Status + Enable */ +#define XNANDPS8_INTR_STS_EN_TRANS_COMP_STS_EN_MASK 0x00000004U /**< Transfer + Complete + Status + Enable */ +#define XNANDPS8_INTR_STS_EN_MUL_BIT_ERR_STS_EN_MASK 0x00000008U /**< Multi + Bit Error + Status + Enable */ +#define XNANDPS8_INTR_STS_EN_ERR_INTR_STS_EN_MASK 0x00000010U /**< Single + Bit Error + Status + Enable, + BCH Detect + Error + Status + Enable */ +#define XNANDPS8_INTR_STS_EN_DMA_INT_STS_EN_MASK 0x00000040U /**< DMA + Status + Enable */ +#define XNANDPS8_INTR_STS_EN_ERR_AHB_STS_EN_MASK 0x00000080U /**< Error + AHB Status + Enable */ +/* @} */ + +/** @name Interrupt Signal Enable Register bit definitions and masks + * @{ + */ +#define XNANDPS8_INTR_SIG_EN_BUFF_WR_RDY_STS_EN_MASK 0x00000001U /**< Buffer + Write Ready + Signal + Enable */ +#define XNANDPS8_INTR_SIG_EN_BUFF_RD_RDY_STS_EN_MASK 0x00000002U /**< Buffer + Read Ready + Signal + Enable */ +#define XNANDPS8_INTR_SIG_EN_TRANS_COMP_STS_EN_MASK 0x00000004U /**< Transfer + Complete + Signal + Enable */ +#define XNANDPS8_INTR_SIG_EN_MUL_BIT_ERR_STS_EN_MASK 0x00000008U /**< Multi + Bit Error + Signal + Enable */ +#define XNANDPS8_INTR_SIG_EN_ERR_INTR_STS_EN_MASK 0x00000010U /**< Single + Bit Error + Signal + Enable, + BCH Detect + Error + Signal + Enable */ +#define XNANDPS8_INTR_SIG_EN_DMA_INT_STS_EN_MASK 0x00000040U /**< DMA + Signal + Enable */ +#define XNANDPS8_INTR_SIG_EN_ERR_AHB_STS_EN_MASK 0x00000080U /**< Error + AHB Signal + Enable */ +/* @} */ + +/** @name Interrupt Status Register bit definitions and masks + * @{ + */ +#define XNANDPS8_INTR_STS_BUFF_WR_RDY_STS_EN_MASK 0x00000001U /**< Buffer + Write + Ready */ +#define XNANDPS8_INTR_STS_BUFF_RD_RDY_STS_EN_MASK 0x00000002U /**< Buffer + Read + Ready */ +#define XNANDPS8_INTR_STS_TRANS_COMP_STS_EN_MASK 0x00000004U /**< Transfer + Complete */ +#define XNANDPS8_INTR_STS_MUL_BIT_ERR_STS_EN_MASK 0x00000008U /**< Multi + Bit Error */ +#define XNANDPS8_INTR_STS_ERR_INTR_STS_EN_MASK 0x00000010U /**< Single + Bit Error, + BCH Detect + Error */ +#define XNANDPS8_INTR_STS_DMA_INT_STS_EN_MASK 0x00000040U /**< DMA + Interrupt + */ +#define XNANDPS8_INTR_STS_ERR_AHB_STS_EN_MASK 0x00000080U /**< Error + AHB */ +/* @} */ + +/** @name Interrupt bit definitions and masks + * @{ + */ +#define XNANDPS8_INTR_BUFF_WR_RDY_STS_EN_MASK 0x00000001U /**< Buffer Write + Ready Status + Enable */ +#define XNANDPS8_INTR_BUFF_RD_RDY_STS_EN_MASK 0x00000002U /**< Buffer Read + Ready Status + Enable */ +#define XNANDPS8_INTR_TRANS_COMP_STS_EN_MASK 0x00000004U /**< Transfer + Complete Status + Enable */ +#define XNANDPS8_INTR_MUL_BIT_ERR_STS_EN_MASK 0x00000008U /**< Multi Bit Error + Status Enable */ +#define XNANDPS8_INTR_ERR_INTR_STS_EN_MASK 0x00000010U /**< Single Bit Error + Status Enable, + BCH Detect Error + Status Enable */ +#define XNANDPS8_INTR_DMA_INT_STS_EN_MASK 0x00000040U /**< DMA Status + Enable */ +#define XNANDPS8_INTR_ERR_AHB_STS_EN_MASK 0x00000080U /**< Error AHB Status + Enable */ +/* @} */ + +/** @name ID2 Register bit definitions and masks + * @{ + */ +#define XNANDPS8_ID2_DEVICE_ID2_MASK 0x000000FFU /**< MSB Device ID */ +/* @} */ + +/** @name Flash Status Register bit definitions and masks + * @{ + */ +#define XNANDPS8_FLASH_STS_FLASH_STS_MASK 0x0000FFFFU /**< Flash Status + Value */ +/* @} */ + +/** @name Timing Register bit definitions and masks + * @{ + */ +#define XNANDPS8_TIMING_TCCS_TIME_MASK 0x00000003U /**< Change column + setup time */ +#define XNANDPS8_TIMING_SLOW_FAST_TCAD_MASK 0x00000004U /**< Slow/Fast device + */ +#define XNANDPS8_TIMING_DQS_BUFF_SEL_MASK 0x00000078U /**< Write/Read data + transaction value + */ +#define XNANDPS8_TIMING_TADL_TIME_MASK 0x00007F80U /**< Address latch + enable to Data + loading time */ +/* @} */ + +/** @name ECC Register bit definitions and masks + * @{ + */ +#define XNANDPS8_ECC_ADDR_MASK 0x0000FFFFU /**< ECC address */ +#define XNANDPS8_ECC_SIZE_MASK 0x01FF0000U /**< ECC size */ +#define XNANDPS8_ECC_HAMMING_BCH_MASK 0x02000000U /**< Hamming/BCH + support */ +/* @} */ + +/** @name ECC Error Count Register bit definitions and masks + * @{ + */ +#define XNANDPS8_ECC_ERR_CNT_PKT_BND_ERR_CNT_MASK 0x000000FFU /**< Packet + bound error + count */ +#define XNANDPS8_ECC_ERR_CNT_PG_BND_ERR_CNT_MASK 0x0000FF00U /**< Page + bound error + count */ +/* @} */ + +/** @name ECC Spare Command Register bit definitions and masks + * @{ + */ +#define XNANDPS8_ECC_SPR_CMD_SPR_CMD_MASK 0x000000FFU /**< ECC + spare + command */ +#define XNANDPS8_ECC_SPR_CMD_ECC_ADDR_CYCLES_MASK 0x70000000U /**< Number + of ECC/ + spare + address + cycles */ +/* @} */ + +/** @name Data Interface Register bit definitions and masks + * @{ + */ +#define XNANDPS8_DATA_INTF_SDR_MASK 0x00000007U /**< SDR mode */ +#define XNANDPS8_DATA_INTF_NVDDR_MASK 0x00000038U /**< NVDDR mode */ +#define XNANDPS8_DATA_INTF_NVDDR2_MASK 0x000001C0U /**< NVDDR2 mode */ +#define XNANDPS8_DATA_INTF_DATA_INTF_MASK 0x00000600U /**< Data + Interface */ +#define XNANDPS8_DATA_INTF_NVDDR_SHIFT 3U /**< NVDDR mode shift */ +#define XNANDPS8_DATA_INTF_DATA_INTF_SHIFT 9U /**< Data Interface Shift */ +/* @} */ + +/** @name DMA Buffer Boundary Register bit definitions and masks + * @{ + */ +#define XNANDPS8_DMA_BUF_BND_BND_MASK 0x00000007U /**< DMA buffer + boundary */ +#define XNANDPS8_DMA_BUF_BND_4K 0x0U +#define XNANDPS8_DMA_BUF_BND_8K 0x1U +#define XNANDPS8_DMA_BUF_BND_16K 0x2U +#define XNANDPS8_DMA_BUF_BND_32K 0x3U +#define XNANDPS8_DMA_BUF_BND_64K 0x4U +#define XNANDPS8_DMA_BUF_BND_128K 0x5U +#define XNANDPS8_DMA_BUF_BND_256K 0x6U +#define XNANDPS8_DMA_BUF_BND_512K 0x7U +/* @} */ + +/** @name Slave DMA Configuration Register bit definitions and masks + * @{ + */ +#define XNANDPS8_SLV_DMA_CONF_SDMA_TX_RX_MASK 0x00000001U /**< Slave + DMA + Transfer + Direction + */ +#define XNANDPS8_SLV_DMA_CONF_DMA_TRANS_CNT_MASK 0x001FFFFEU /**< Slave + DMA + Transfer + Count */ +#define XNANDPS8_SLV_DMA_CONF_DMA_BURST_SIZE_MASK 0x00E00000U /**< Slave + DMA + Burst + Size */ +#define XNANDPS8_SLV_DMA_CONF_DMA_TMOUT_CNT_VAL_MASK 0x0F000000U /**< DMA + Timeout + Counter + Value */ +#define XNANDPS8_SLV_DMA_CONF_SDMA_EN_MASK 0x10000000U /**< Slave + DMA + Enable */ +/* @} */ + +/**************************** Type Definitions *******************************/ + +/***************** Macros (Inline Functions) Definitions *********************/ + +/****************************************************************************/ +/** +* +* This macro reads the given register. +* +* @param BaseAddress is the base address of controller registers. +* @param RegOffset is the register offset to be read. +* +* @return The 32-bit value of the register. +* +* @note C-style signature: +* u32 XNandPs8_ReadReg(u32 BaseAddress, u32 RegOffset) +* +*****************************************************************************/ +#define XNandPs8_ReadReg(BaseAddress, RegOffset) \ + Xil_In32((BaseAddress) + (RegOffset)) + +/****************************************************************************/ +/** +* +* This macro writes the given register. +* +* @param BaseAddress is the the base address of controller registers. +* @param RegOffset is the register offset to be written. +* @param Data is the the 32-bit value to write to the register. +* +* @return None. +* +* @note C-style signature: +* void XNandPs8_WriteReg(u32 BaseAddress, u32 RegOffset, u32 Data) +* +******************************************************************************/ +#define XNandPs8_WriteReg(BaseAddress, RegOffset, Data) \ + Xil_Out32(((BaseAddress) + (RegOffset)), (Data)) + +/************************** Function Prototypes ******************************/ + +/************************** Variable Definitions *****************************/ + +#ifdef __cplusplus +} +#endif + +#endif /* XNANDPS8_HW_H end of protection macro */ diff --git a/XilinxProcessorIPLib/drivers/nandps8_v2_0/src/xnandps8_onfi.c b/XilinxProcessorIPLib/drivers/nandps8_v2_0/src/xnandps8_onfi.c new file mode 100755 index 00000000..ffea8d48 --- /dev/null +++ b/XilinxProcessorIPLib/drivers/nandps8_v2_0/src/xnandps8_onfi.c @@ -0,0 +1,124 @@ +/****************************************************************************** +* +* Copyright (C) 2014 Xilinx, Inc. All rights reserved. +* +* This file contains confidential and proprietary information of Xilinx, Inc. +* and is protected under U.S. and international copyright and other +* intellectual property laws. +* +* DISCLAIMER +* This disclaimer is not a license and does not grant any rights to the +* materials distributed herewith. Except as otherwise provided in a valid +* license issued to you by Xilinx, and to the maximum extent permitted by +* applicable law: (1) THESE MATERIALS ARE MADE AVAILABLE "AS IS" AND WITH ALL +* FAULTS, AND XILINX HEREBY DISCLAIMS ALL WARRANTIES AND CONDITIONS, EXPRESS, +* IMPLIED, OR STATUTORY, INCLUDING BUT NOT LIMITED TO WARRANTIES OF +* MERCHANTABILITY, NON- INFRINGEMENT, OR FITNESS FOR ANY PARTICULAR PURPOSE +* and +* (2) Xilinx shall not be liable (whether in contract or tort, including +* negligence, or under any other theory of liability) for any loss or damage +* of any kind or nature related to, arising under or in connection with these +* materials, including for any direct, or any indirect, special, incidental, +* or consequential loss or damage (including loss of data, profits, +* goodwill, or any type of loss or damage suffered as a result of any +* action brought by a third party) even if such damage or loss was +* reasonably foreseeable or Xilinx had been advised of the possibility +* of the same. +* +* CRITICAL APPLICATIONS +* Xilinx products are not designed or intended to be fail- safe, or for use +* in any application requiring fail-safe performance, such as life-support +* or safety devices or systems, Class III medical devices, nuclear +* facilities, applications related to the deployment of airbags, or any +* other applications that could lead to death, personal injury, or severe +* property or environmental damage (individually and collectively, +* "Critical Applications"). Customer assumes the sole risk and liability +* of any use of Xilinx products in Critical Applications, subject only to +* applicable laws and regulations governing limitations on product liability. +* +* THIS COPYRIGHT NOTICE AND DISCLAIMER MUST BE RETAINED AS PART +* OF THIS FILE AT ALL TIMES. +* +******************************************************************************/ + +/*****************************************************************************/ +/** +* +* @file xnandps8_onfi.c +* +* This file contains the implementation of ONFI specific functions. +* +* @note None +* +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who    Date	   Changes
+* ----- ----   ----------  -----------------------------------------------
+* 1.0   nm     05/06/2014  First release
+* 
+* +******************************************************************************/ + +/***************************** Include Files *********************************/ +#include "xnandps8_onfi.h" +#include "xnandps8.h" + +/************************** Constant Definitions *****************************/ + +/**************************** Type Definitions *******************************/ + +/***************** Macros (Inline Functions) Definitions *********************/ + +/************************** Function Prototypes ******************************/ + +/*****************************************************************************/ +/** +* +* This function calculates ONFI paramater page CRC. +* +* @param Parambuf is a pointer to the ONFI paramater page buffer. +* @param StartOff is the starting offset in buffer to calculate CRC. +* @param Length is the number of bytes for which CRC is calculated. +* +* @return +* CRC value. +* @note +* None. +* +******************************************************************************/ +u32 XNandPs8_OnfiParamPageCrc(u8 *ParamBuf, u32 StartOff, u32 Length) +{ + const u32 CrcInit = 0x4F4EU; + const u32 Order = 16U; + const u32 Polynom = 0x8005U; + u32 i, j, c, Bit; + u32 Crc = CrcInit; + u32 DataIn; + u32 DataByteCount = 0U; + u32 CrcMask, CrcHighBit; + + CrcMask = ((u32)(((u32)1 << (Order - (u32)1)) -(u32)1) << (u32)1) | (u32)1; + CrcHighBit = (u32)((u32)1 << (Order - (u32)1)); + /* + * CRC covers the data bytes between byte 0 and byte 253 + * (ONFI 1.0, section 5.4.1.36) + */ + for(i = StartOff; i < Length; i++) { + DataIn = ParamBuf[i]; + c = (u32)DataIn; + DataByteCount++; + for(j = 0x80U; j; j >>= 1U) { + Bit = Crc & CrcHighBit; + Crc <<= 1U; + if ((c & j) != 0U) { + Bit ^= CrcHighBit; + } + if (Bit != 0U) { + Crc ^= Polynom; + } + } + Crc &= CrcMask; + } + return Crc; +} diff --git a/XilinxProcessorIPLib/drivers/nandps8_v2_0/src/xnandps8_onfi.h b/XilinxProcessorIPLib/drivers/nandps8_v2_0/src/xnandps8_onfi.h new file mode 100755 index 00000000..2205ae4c --- /dev/null +++ b/XilinxProcessorIPLib/drivers/nandps8_v2_0/src/xnandps8_onfi.h @@ -0,0 +1,352 @@ +/****************************************************************************** +* +* Copyright (C) 2014 Xilinx, Inc. All rights reserved. +* +* This file contains confidential and proprietary information of Xilinx, Inc. +* and is protected under U.S. and international copyright and other +* intellectual property laws. +* +* DISCLAIMER +* This disclaimer is not a license and does not grant any rights to the +* materials distributed herewith. Except as otherwise provided in a valid +* license issued to you by Xilinx, and to the maximum extent permitted by +* applicable law: (1) THESE MATERIALS ARE MADE AVAILABLE "AS IS" AND WITH ALL +* FAULTS, AND XILINX HEREBY DISCLAIMS ALL WARRANTIES AND CONDITIONS, EXPRESS, +* IMPLIED, OR STATUTORY, INCLUDING BUT NOT LIMITED TO WARRANTIES OF +* MERCHANTABILITY, NON- INFRINGEMENT, OR FITNESS FOR ANY PARTICULAR PURPOSE +* and +* (2) Xilinx shall not be liable (whether in contract or tort, including +* negligence, or under any other theory of liability) for any loss or damage +* of any kind or nature related to, arising under or in connection with these +* materials, including for any direct, or any indirect, special, incidental, +* or consequential loss or damage (including loss of data, profits, +* goodwill, or any type of loss or damage suffered as a result of any +* action brought by a third party) even if such damage or loss was +* reasonably foreseeable or Xilinx had been advised of the possibility +* of the same. +* +* CRITICAL APPLICATIONS +* Xilinx products are not designed or intended to be fail- safe, or for use +* in any application requiring fail-safe performance, such as life-support +* or safety devices or systems, Class III medical devices, nuclear +* facilities, applications related to the deployment of airbags, or any +* other applications that could lead to death, personal injury, or severe +* property or environmental damage (individually and collectively, +* "Critical Applications"). Customer assumes the sole risk and liability +* of any use of Xilinx products in Critical Applications, subject only to +* applicable laws and regulations governing limitations on product liability. +* +* THIS COPYRIGHT NOTICE AND DISCLAIMER MUST BE RETAINED AS PART +* OF THIS FILE AT ALL TIMES. +* +******************************************************************************/ + +/*****************************************************************************/ +/** +* +* @file xnandps8_onfi.h +* +* This file defines all the ONFI 3.1 specific commands and values. +* +* @note None +* +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who    Date	   Changes
+* ----- ----   ----------  -----------------------------------------------
+* 1.0   nm     05/06/2014  First release
+* 
+* +******************************************************************************/ +#ifndef XNANDPS8_ONFI_H /* prevent circular inclusions */ +#define XNANDPS8_ONFI_H /* by using protection macros */ + +#ifdef __cplusplus +extern "C" { +#endif + +/***************************** Include Files *********************************/ +#include "xil_types.h" + +/************************** Constant Definitions *****************************/ +/* + * Standard ONFI 3.1 Commands + */ +/* + * ONFI 3.1 Mandatory Commands + */ +#define ONFI_CMD_RD1 0x00U /**< Read (1st cycle) */ +#define ONFI_CMD_RD2 0x30U /**< Read (2nd cycle) */ +#define ONFI_CMD_CHNG_RD_COL1 0x05U /**< Change Read Column + (1st cycle) */ +#define ONFI_CMD_CHNG_RD_COL2 0xE0U /**< Change Read Column + (2nd cycle) */ +#define ONFI_CMD_BLK_ERASE1 0x60U /**< Block Erase (1st cycle) */ +#define ONFI_CMD_BLK_ERASE2 0xD0U /**< Block Erase (2nd cycle) */ +#define ONFI_CMD_RD_STS 0x70U /**< Read Status */ +#define ONFI_CMD_PG_PROG1 0x80U /**< Page Program(1st cycle) */ +#define ONFI_CMD_PG_PROG2 0x10U /**< Page Program(2nd cycle) */ +#define ONFI_CMD_CHNG_WR_COL 0x85U /**< Change Write Column */ +#define ONFI_CMD_RD_ID 0x90U /**< Read ID */ +#define ONFI_CMD_RD_PRM_PG 0xECU /**< Read Parameter Page */ +#define ONFI_CMD_RST 0xFFU /**< Reset */ +/* + * ONFI 3.1 Optional Commands + */ +#define ONFI_CMD_MUL_RD1 0x00U /**< Multiplane Read + (1st cycle) */ +#define ONFI_CMD_MUL_RD2 0x32U /**< Multiplane Read + (2nd cycle) */ +#define ONFI_CMD_CPBK_RD1 0x00U /**< Copyback Read + (1st cycle) */ +#define ONFI_CMD_CPBK_RD2 0x35U /**< Copyback Read + (2nd cycle) */ +#define ONFI_CMD_CHNG_RD_COL_ENHCD1 0x06U /**< Change Read Column + Enhanced (1st cycle) */ +#define ONFI_CMD_CHNG_RD_COL_ENHCD2 0xE0U /**< Change Read Column + Enhanced (2nd cycle) */ +#define ONFI_CMD_RD_CACHE_RND1 0x00U /**< Read Cache Random + (1st cycle) */ +#define ONFI_CMD_RD_CACHE_RND2 0x31U /**< Read Cache Random + (2nd cycle) */ +#define ONFI_CMD_RD_CACHE_SEQ 0x31U /**< Read Cache Sequential */ +#define ONFI_CMD_RD_CACHE_END 0x3FU /**< Read Cache End */ +#define ONFI_CMD_MUL_BLK_ERASE1 0x60U /**< Multiplane Block Erase + (1st cycle) */ +#define ONFI_CMD_MUL_BLK_ERASE2 0xD1U /**< Multiplane Block Erase + (2nd cycle) */ +#define ONFI_CMD_RD_STS_ENHCD 0x78U /**< Read Status Enhanced */ +#define ONFI_CMD_BLK_ERASE_INTRLVD2 0xD1U /**< Block Erase Interleaved + (2nd cycle) */ +#define ONFI_CMD_MUL_PG_PROG1 0x80U /**< Multiplane Page Program + (1st cycle) */ +#define ONFI_CMD_MUL_PG_PROG2 0x11U /**< Multiplane Page Program + (2nd cycle) */ +#define ONFI_CMD_PG_CACHE_PROG1 0x80U /**< Page Cache Program + (1st cycle) */ +#define ONFI_CMD_PG_CACHE_PROG2 0x15U /**< Page Cache Program + (2nd cycle) */ +#define ONFI_CMD_CPBK_PROG1 0x85U /**< Copyback Program + (1st cycle) */ +#define ONFI_CMD_CPBK_PROG2 0x10U /**< Copyback Program + (2nd cycle) */ +#define ONFI_CMD_MUL_CPBK_PROG1 0x85U /**< Multiplane Copyback + Program (1st cycle) */ +#define ONFI_CMD_MUL_CPBK_PROG2 0x10U /**< Multiplane Copyback + Program (2nd cycle) */ +#define ONFI_CMD_SMALL_DATA_MV1 0x85U /**< Small Data Move + (1st cycle) */ +#define ONFI_CMD_SMALL_DATA_MV2 0x10U /**< Small Data Move + (2nd cycle) */ +#define ONFI_CMD_CHNG_ROW_ADDR 0x85U /**< Change Row Address */ +#define ONFI_CMD_VOL_SEL 0xE1U /**< Volume Select */ +#define ONFI_CMD_ODT_CONF 0xE2U /**< ODT Configure */ +#define ONFI_CMD_RD_UNIQID 0xEDU /**< Read Unique ID */ +#define ONFI_CMD_GET_FEATURES 0xEEU /**< Get Features */ +#define ONFI_CMD_SET_FEATURES 0xEFU /**< Set Features */ +#define ONFI_CMD_LUN_GET_FEATURES 0xD4U /**< LUN Get Features */ +#define ONFI_CMD_LUN_SET_FEATURES 0xD5U /**< LUN Set Features */ +#define ONFI_CMD_RST_LUN 0xFAU /**< Reset LUN */ +#define ONFI_CMD_SYN_RST 0xFCU /**< Synchronous Reset */ + +/* + * ONFI Status Register bit offsets + */ +#define ONFI_STS_FAIL 0x01U /**< FAIL */ +#define ONFI_STS_FAILC 0x02U /**< FAILC */ +#define ONFI_STS_CSP 0x08U /**< CSP */ +#define ONFI_STS_VSP 0x10U /**< VSP */ +#define ONFI_STS_ARDY 0x20U /**< ARDY */ +#define ONFI_STS_RDY 0x40U /**< RDY */ +#define ONFI_STS_WP 0x80U /**< WP_n */ + +/* + * ONFI constants + */ +#define ONFI_CRC_LEN 254U /**< ONFI CRC Buf Length */ +#define ONFI_PRM_PG_LEN 256U /**< Parameter Page Length */ +#define ONFI_MND_PRM_PGS 3U /**< Number of mandatory + parameter pages */ +#define ONFI_SIG_LEN 4U /**< Signature Length */ +#define ONFI_CMD_INVALID 0x00U /**< Invalid Command */ + +#define ONFI_READ_ID_LEN 4U /**< ONFI ID length */ +#define ONFI_READ_ID_ADDR 0x20U /**< ONFI Read ID Address */ +#define ONFI_READ_ID_ADDR_CYCLES 1U /**< ONFI Read ID Address + cycles */ + +#define ONFI_PRM_PG_ADDR_CYCLES 1U /**< ONFI Read Parameter page + address cycles */ + +/** + * This enum defines the ONFI 3.1 commands. + */ +enum OnfiCommandList { + READ=0, /**< Read */ + MULTIPLANE_READ, /**< Multiplane Read */ + COPYBACK_READ, /**< Copyback Read */ + CHANGE_READ_COLUMN, /**< Change Read Column */ + CHANGE_READ_COLUMN_ENHANCED, /**< Change Read Column Enhanced */ + READ_CACHE_RANDOM, /**< Read Cache Random */ + READ_CACHE_SEQUENTIAL, /**< Read Cache Sequential */ + READ_CACHE_END, /**< Read Cache End */ + BLOCK_ERASE, /**< Block Erase */ + MULTIPLANE_BLOCK_ERASE, /**< Multiplane Block Erase */ + READ_STATUS, /**< Read Status */ + READ_STATUS_ENHANCED, /**< Read Status Enhanced */ + PAGE_PROGRAM, /**< Page Program */ + MULTIPLANE_PAGE_PROGRAM, /**< Multiplane Page Program */ + PAGE_CACHE_PROGRAM, /**< Page Cache Program */ + COPYBACK_PROGRAM, /**< Copyback Program */ + MULTIPLANE_COPYBACK_PROGRAM, /**< Multiplance Copyback Program */ + SMALL_DATA_MOVE, /**< Small Data Move */ + CHANGE_WRITE_COLUMN, /**< Change Write Column */ + CHANGE_ROW_ADDR, /**< Change Row Address */ + READ_ID, /**< Read ID */ + VOLUME_SELECT, /**< Volume Select */ + ODT_CONFIGURE, /**< ODT Configure */ + READ_PARAM_PAGE, /**< Read Parameter Page */ + READ_UNIQUE_ID, /**< Read Unique ID */ + GET_FEATURES, /**< Get Features */ + SET_FEATURES, /**< Set Features */ + LUN_GET_FEATURES, /**< LUN Get Features */ + LUN_SET_FEATURES, /**< LUN Set Features */ + RESET_LUN, /**< Reset LUN */ + SYN_RESET, /**< Synchronous Reset */ + RESET, /**< Reset */ + MAX_CMDS /**< Dummy Command */ +}; + +/**************************** Type Definitions *******************************/ +/* + * Parameter page structure of ONFI 3.1 specification. + */ +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 JedecJtgPrmAdvCmd; /**< ONFI JEDEC JTG primary advanced + command support */ + u8 Reserved0; /**< Reserved (11) */ + u16 ExtParamPageLen; /**< Extended Parameter Page Length */ + u8 NumOfParamPages; /**< Number of Parameter Pages */ + u8 Reserved1[17]; /**< Reserved (15-31) */ + /* + * 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 (67-79) */ + /* + * 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 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 PlaneAddrBits; /**< Number of plane address bits */ + u8 PlaneOperationAttr; /**< Multi-plane operation + attributes */ + u8 EzNandSupport; /**< EZ NAND support */ + u8 Reserved3[12]; /**< Reserved (116 - 127) */ + /* + * Electrical parameters block + */ + u8 IOPinCapacitance; /**< I/O pin capacitance, maximum */ + u16 SDRTimingMode; /**< SDR Timing mode support */ + u16 SDRPagecacheTimingMode; /**< SDR 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 */ + u8 NVDDRTimingMode; /**< NVDDR timing mode support */ + u8 NVDDR2TimingMode; /**< NVDDR2 timing mode support */ + u8 SynFeatures; /**< NVDDR/NVDDR2 features */ + u16 ClkInputPinCap; /**< CLK input pin capacitance */ + u16 IOPinCap; /**< I/O pin capacitance */ + u16 InputPinCap; /**< Input pin capacitance typical */ + u8 InputPinCapMax; /**< Input pin capacitance maximum */ + u8 DrvStrength; /**< Driver strength support */ + u16 TMr; /**< Maximum multi-plane read time */ + u16 TAdl; /**< Program page register clear + enhancement value */ + u16 TEr; /**< Typical page read time for + EZ NAND */ + u8 NVDDR2Features; /**< NVDDR2 Features */ + u8 NVDDR2WarmupCycles; /**< NVDDR2 Warmup Cycles */ + u8 Reserved4[4]; /**< Reserved (160 - 163) */ + /* + * Vendor block + */ + u16 VendorRevisionNum; /**< Vendor specific revision number */ + u8 VendorSpecific[88]; /**< Vendor specific */ + u16 Crc; /**< Integrity CRC */ +}__attribute__((packed))OnfiParamPage; + +/* + * ONFI extended parameter page structure. + */ +typedef struct { + u16 Crc; + u8 Sig[4]; + u8 Reserved1[10]; + u8 Section0Type; + u8 Section0Len; + u8 Section1Type; + u8 Section1Len; + u8 ResSection[12]; + u8 SectionData[256]; +}__attribute__((packed))OnfiExtPrmPage; + +/* + * Driver extended parameter page information. + */ +typedef struct { + u8 NumBitsEcc; + u8 CodeWordSize; + u16 MaxBadBlocks; + u16 BlockEndurance; + u16 Reserved; +}__attribute__((packed))OnfiExtEccBlock; + +typedef struct { + u8 Command1; /**< Command Cycle 1 */ + u8 Command2; /**< Command Cycle 2 */ +} OnfiCmdFormat; + +extern const OnfiCmdFormat OnfiCmd[MAX_CMDS]; + +/************************** Function Prototypes ******************************/ + +u32 XNandPs8_OnfiParamPageCrc(u8 *ParamBuf, u32 StartOff, u32 Length); + +#ifdef __cplusplus +} +#endif + +#endif /* XNANDPS8_ONFI_H end of protection macro */ diff --git a/XilinxProcessorIPLib/drivers/nandps8_v2_0/src/xnandps8_sinit.c b/XilinxProcessorIPLib/drivers/nandps8_v2_0/src/xnandps8_sinit.c new file mode 100755 index 00000000..6d86e870 --- /dev/null +++ b/XilinxProcessorIPLib/drivers/nandps8_v2_0/src/xnandps8_sinit.c @@ -0,0 +1,106 @@ +/****************************************************************************** +* +* Copyright (C) 2014 Xilinx, Inc. All rights reserved. +* +* This file contains confidential and proprietary information of Xilinx, Inc. +* and is protected under U.S. and international copyright and other +* intellectual property laws. +* +* DISCLAIMER +* This disclaimer is not a license and does not grant any rights to the +* materials distributed herewith. Except as otherwise provided in a valid +* license issued to you by Xilinx, and to the maximum extent permitted by +* applicable law: (1) THESE MATERIALS ARE MADE AVAILABLE "AS IS" AND WITH ALL +* FAULTS, AND XILINX HEREBY DISCLAIMS ALL WARRANTIES AND CONDITIONS, EXPRESS, +* IMPLIED, OR STATUTORY, INCLUDING BUT NOT LIMITED TO WARRANTIES OF +* MERCHANTABILITY, NON- INFRINGEMENT, OR FITNESS FOR ANY PARTICULAR PURPOSE +* and +* (2) Xilinx shall not be liable (whether in contract or tort, including +* negligence, or under any other theory of liability) for any loss or damage +* of any kind or nature related to, arising under or in connection with these +* materials, including for any direct, or any indirect, special, incidental, +* or consequential loss or damage (including loss of data, profits, +* goodwill, or any type of loss or damage suffered as a result of any +* action brought by a third party) even if such damage or loss was +* reasonably foreseeable or Xilinx had been advised of the possibility +* of the same. +* +* CRITICAL APPLICATIONS +* Xilinx products are not designed or intended to be fail- safe, or for use +* in any application requiring fail-safe performance, such as life-support +* or safety devices or systems, Class III medical devices, nuclear +* facilities, applications related to the deployment of airbags, or any +* other applications that could lead to death, personal injury, or severe +* property or environmental damage (individually and collectively, +* "Critical Applications"). Customer assumes the sole risk and liability +* of any use of Xilinx products in Critical Applications, subject only to +* applicable laws and regulations governing limitations on product liability. +* +* THIS COPYRIGHT NOTICE AND DISCLAIMER MUST BE RETAINED AS PART +* OF THIS FILE AT ALL TIMES. +* +******************************************************************************/ + +/*****************************************************************************/ +/** +* +* @file xnandps8_sinit.c +* +* The implementation of the XNandPs8 driver's static initialzation +* functionality. +* +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who    Date	   Changes
+* ----- ----   ----------  -----------------------------------------------
+* 1.0   nm     05/06/2014  First release
+* 
+* +******************************************************************************/ + +/***************************** Include Files ********************************/ +#include "xstatus.h" +#include "xparameters.h" +#include "xnandps8.h" +/************************** Constant Definitions ****************************/ +#define XPAR_XNANDPS8_NUM_INSTANCES 1U + +/**************************** Type Definitions ******************************/ + +/***************** Macros (Inline Functions) Definitions ********************/ + +/************************** Variable Definitions ****************************/ + +extern XNandPs8_Config XNandPs8_ConfigTable[]; + +/************************** Function Prototypes *****************************/ + +/****************************************************************************/ +/** +* +* Looks up the controller configuration based on the unique controller ID. A +* table contains the configuration info for each controller in the system. +* +* @param DeviceID is the ID of the controller to look up the +* configuration for. +* +* @return +* A pointer to the configuration found or NULL if the specified +* controller ID was not found. +* +******************************************************************************/ +XNandPs8_Config *XNandPs8_LookupConfig(u16 DeviceID) +{ + XNandPs8_Config *CfgPtr = NULL; + u32 Index; + + for (Index = 0U; Index < XPAR_XNANDPS8_NUM_INSTANCES; Index++) { + if (XNandPs8_ConfigTable[Index].DeviceId == DeviceID) { + CfgPtr = &XNandPs8_ConfigTable[Index]; + break; + } + } + + return (XNandPs8_Config *)CfgPtr; +}