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
+* +* 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
+ * 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(
+ * 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(
+ * 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(
+* 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
+* +* MODIFICATION HISTORY: +* +* Ver Who Date Changes +* ----- ---- ---------------------------------------------------------------- +* 1.0 sb 11/28/14 First release. +*+* +******************************************************************************/ + +/***************************** Include Files *********************************/ + +#include "intg.h" +#include
+* +* 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
+* +* 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_
+* +* 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_
+* +* 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_
+* +* 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_
+* +* 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_
+* +* 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_
+* 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
+* 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
+* 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; +}